Skip to content

Commit

Permalink
feat: refactor suite builder (#214)
Browse files Browse the repository at this point in the history
  • Loading branch information
dstallenberg authored Dec 11, 2023
1 parent cf26455 commit e8a820b
Show file tree
Hide file tree
Showing 2 changed files with 268 additions and 153 deletions.
183 changes: 152 additions & 31 deletions libraries/search-javascript/lib/testbuilding/JavaScriptSuiteBuilder.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
*/
import { Target } from "@syntest/analysis";
import { ImplementationError } from "@syntest/diagnostics";
import { InstrumentationDataMap } from "@syntest/instrumentation-javascript";
import { StorageManager } from "@syntest/storage";

import { JavaScriptRunner } from "../testcase/execution/JavaScriptRunner";
Expand All @@ -39,21 +40,27 @@ export class JavaScriptSuiteBuilder {
this.runner = runner;
}

async runSuite(
/**
*
* @param archive
* @param sourceDirectory
* @param testDirectory
* @param gatherAssertionData
* @param compact decides whether the tests in each archive are put into a single file
* @param final
*/
createSuite(
archive: Map<Target, JavaScriptTestCase[]>,
sourceDirectory: string,
testDirectory: string,
gatherAssertionData: boolean,
compact: boolean,
final = false
) {
const paths: string[] = [];
const paths: { [key: string]: number } = {};

// write the test cases with logs to know what to assert
let totalAmount = 0;
if (compact) {
for (const target of archive.keys()) {
totalAmount += archive.get(target).length;
for (const target of archive.keys()) {
if (compact) {
const decodedTest = this.decoder.decode(
archive.get(target),
gatherAssertionData,
Expand All @@ -65,11 +72,13 @@ export class JavaScriptSuiteBuilder {
decodedTest,
!final
);
paths.push(testPath);
}
} else {
for (const target of archive.keys()) {
totalAmount += archive.get(target).length;

if (paths[testPath] !== undefined) {
throw new ImplementationError("Should only be one of each path!");
}

paths[testPath] = archive.get(target).length;
} else {
for (const testCase of archive.get(target)) {
const decodedTest = this.decoder.decode(
testCase,
Expand All @@ -78,39 +87,151 @@ export class JavaScriptSuiteBuilder {
);
const testPath = this.storageManager.store(
[testDirectory],
`test${target.name}${testCase.id}.spec.js`,
`test-${target.name}-${testCase.id}.spec.js`,
decodedTest,
!final
);

paths.push(testPath);
if (paths[testPath] !== undefined) {
throw new ImplementationError("Should only be one of each path!");
}

paths[testPath] = 1;
}
}
}

if (final) {
// eslint-disable-next-line unicorn/no-null
return null;
return paths;
}

/**
*
* @param archive
* @param sourceDirectory
* @param testDirectory
* @param gatherAssertionData
* @returns
*/
async runSuite(
archive: Map<Target, JavaScriptTestCase[]>,
paths: { [key: string]: number },
gatherAssertionData: boolean
) {
const results = [];

for (const [filePath, amount] of Object.entries(paths)) {
const { stats, instrumentationData, assertionData } =
await this.runner.run([filePath], amount * 2);

if (gatherAssertionData && assertionData) {
// put assertion data on testCases
for (const [id, data] of Object.entries(assertionData)) {
const testCase = [...archive.values()]
.flat()
.find((x) => x.id === id);
if (!testCase) {
throw new ImplementationError("invalid id");
}

testCase.assertionData = data;
}
}

results.push({ stats, instrumentationData });
}

const { stats, instrumentationData, assertionData } = await this.runner.run(
paths,
totalAmount * 2
);
if (assertionData) {
// put assertion data on testCases
for (const [id, data] of Object.entries(assertionData)) {
const testCase = [...archive.values()].flat().find((x) => x.id === id);
if (!testCase) {
throw new ImplementationError("invalid id");
return results;
}

summariseResults(
results: {
stats: Mocha.Stats;
instrumentationData: InstrumentationDataMap;
}[],
targets: Target[]
) {
type Summary = {
branch: {
covered: Set<string>;
total: Set<string>;
};
statement: {
covered: Set<string>;
total: Set<string>;
};
function: {
covered: Set<string>;
total: Set<string>;
};
};

const summaryTotal = {
failures: 0,
data: new Map<Target, Summary>(),
};

for (const { stats, instrumentationData } of results) {
summaryTotal.failures += stats.failures;

for (const file of Object.keys(instrumentationData)) {
const target = targets.find((target: Target) => target.path === file);
if (!target) {
continue;
}

const data = instrumentationData[file];

let summary: Summary = {
branch: {
covered: new Set(),
total: new Set(),
},
statement: {
covered: new Set(),
total: new Set(),
},
function: {
covered: new Set(),
total: new Set(),
},
};
if (summaryTotal.data.has(target)) {
summary = summaryTotal.data.get(target);
} else {
summaryTotal.data.set(target, summary);
}

testCase.assertionData = data;
for (const statementKey of Object.keys(data.s)) {
summary["statement"].total.add(statementKey);
if (data.s[statementKey]) {
summary["statement"].covered.add(statementKey);
}
}

for (const branchKey of Object.keys(data.b)) {
for (const branchIndex of data.b[branchKey].keys()) {
summary["branch"].total.add(
branchKey + " - " + String(branchIndex)
);

if (data.b[branchKey][branchIndex]) {
summary["branch"].covered.add(
branchKey + " - " + String(branchIndex)
);
}
}
}

for (const functionKey of Object.keys(data.f)) {
summary["function"].total.add(functionKey);

if (data.f[functionKey]) {
summary["function"].covered.add(functionKey);
}
}
}
}

// TODO use the results of the tests to show some statistics

return { stats, instrumentationData };
return summaryTotal;
}
}
Loading

0 comments on commit e8a820b

Please sign in to comment.