Skip to content

Commit

Permalink
Extract summary & logging from TestRunner. (#6297)
Browse files Browse the repository at this point in the history
## Summary
This is a part of a plan to clean up TestRunner. Logging and managing
the summary was the easiest functionality for extracting

## Test plan
  • Loading branch information
Latropos authored Jul 26, 2024
1 parent 5c44da9 commit 1c805ae
Show file tree
Hide file tree
Showing 3 changed files with 76 additions and 73 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,19 +8,12 @@ import type {
TestCase,
TestConfiguration,
TestSuite,
TestSummary,
TestValue,
TrackerCallCount,
} from '../types';
import { DescribeDecorator, TestDecorator } from '../types';
import { TestComponent } from '../TestComponent';
import {
EMPTY_LOG_PLACEHOLDER,
applyMarkdown,
color,
formatString,
indentNestingLevel,
} from '../utils/stringFormatUtils';
import { applyMarkdown, formatString } from '../utils/stringFormatUtils';
import type {
SharedValue,
LayoutAnimationStartFunction,
Expand All @@ -33,6 +26,7 @@ import { assertMockedAnimationTimestamp, assertTestCase, assertTestSuite } from
import { createUpdatesContainer } from './UpdatesContainer';
import { makeMutable, runOnJS } from 'react-native-reanimated';
import { RenderLock, SyncUIRunner } from '../utils/SyncUIRunner';
import { TestSummaryLogger } from './TestSummaryLogger';
export { Presets } from '../Presets';

let callTrackerRegistryJS: Record<string, number> = {};
Expand All @@ -59,14 +53,7 @@ export class TestRunner {
private _includesOnly: boolean = false;
private _syncUIRunner: SyncUIRunner = new SyncUIRunner();
private _renderLock: RenderLock = new RenderLock();
private _summary: TestSummary = {
passed: 0,
failed: 0,
skipped: 0,
failedTests: [] as Array<string>,
startTime: Date.now(),
endTime: 0,
};
private _testSummary: TestSummaryLogger = new TestSummaryLogger();

public notify(name: string) {
'worklet';
Expand Down Expand Up @@ -275,19 +262,18 @@ export class TestRunner {
}

this._testSuites = [];
console.log('End of tests run 🏁');
this._summary.endTime = Date.now();
this.printSummary();
this._testSummary.printSummary();
}

private async runTestSuite(testSuite: TestSuite) {
this._testSummary.countSkippedTestSuiteTests(testSuite);

if (testSuite.skip) {
this._summary.skipped += testSuite.testCases.length;
return;
}

this._currentTestSuite = testSuite;
console.log(`${indentNestingLevel(testSuite.nestingLevel)} ${testSuite.name}`);
this._testSummary.logRunningTestSuite(testSuite);

if (testSuite.beforeAll) {
await testSuite.beforeAll();
Expand All @@ -296,8 +282,6 @@ export class TestRunner {
for (const testCase of testSuite.testCases) {
if (!testCase.skip) {
await this.runTestCase(testSuite, testCase);
} else {
this._summary.skipped++;
}
}

Expand Down Expand Up @@ -325,7 +309,7 @@ export class TestRunner {
await testCase.run();
}

this.showTestCaseSummary(testCase, testSuite.nestingLevel);
this._testSummary.showTestCaseSummary(testCase, testSuite.nestingLevel);

if (testSuite.afterEach) {
await testSuite.afterEach();
Expand All @@ -337,24 +321,6 @@ export class TestRunner {
await this.stopRecordingAnimationUpdates();
}

private showTestCaseSummary(testCase: TestCase, nestingLevel: number) {
let mark;
if (testCase.errors.length > 0) {
this._summary.failed++;
this._summary.failedTests.push(testCase.name);
mark = color('✖', 'red');
} else {
this._summary.passed++;
mark = color('✔', 'green');
}
console.log(`${indentNestingLevel(nestingLevel)} ${mark} ${color(testCase.name, 'gray')}`);

for (const error of testCase.errors) {
const indentedError = error.replace(/\n/g, '\n' + EMPTY_LOG_PLACEHOLDER + indentNestingLevel(nestingLevel + 2));
console.log(`${indentNestingLevel(nestingLevel)}\t${indentedError}`);
}
}

public expect(currentValue: TestValue): Matchers {
assertTestCase(this._currentTestCase);
return new Matchers(currentValue, this._currentTestCase);
Expand Down Expand Up @@ -584,28 +550,6 @@ export class TestRunner {
});
}

private printSummary() {
const { passed, failed, failedTests, startTime, endTime, skipped } = this._summary;

console.log('\n');
console.log(
`🧮 Tests summary: ${color(passed, 'green')} passed, ${color(failed, 'red')} failed, ${color(
skipped,
'orange',
)} skipped`,
);
console.log(`⏱️ Total time: ${Math.round(((endTime - startTime) / 1000) * 100) / 100}s`);
if (failed > 0) {
console.log('❌ Failed tests:');
for (const failedTest of failedTests) {
console.log(`\t- ${failedTest}`);
}
} else {
console.log('✅ All tests passed!');
}
console.log('\n');
}

private async mockConsole(testCase: TestCase): Promise<[() => Promise<void>, () => void]> {
const counterUI = makeMutable(0);
let counterJS = 0;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
import type { TestCase, TestSuite } from '../types';
import { color, EMPTY_LOG_PLACEHOLDER, indentNestingLevel } from '../utils/stringFormatUtils';

export class TestSummaryLogger {
private _passed: number = 0;
private _failed: number = 0;
private _skipped: number = 0;
private _failedTests: Array<string> = [];
private _startTime: number = Date.now();
private _endTime: number = 0;

public logRunningTestSuite(testSuite: TestSuite) {
console.log(`${indentNestingLevel(testSuite.nestingLevel)}${testSuite.name}`);
}

public showTestCaseSummary(testCase: TestCase, nestingLevel: number) {
let mark;
if (testCase.errors.length > 0) {
this._failed++;
this._failedTests.push(testCase.name);
mark = color('✖', 'red');
} else {
this._passed++;
mark = color('✔', 'green');
}
console.log(`${indentNestingLevel(nestingLevel)} ${mark} ${color(testCase.name, 'gray')}`);

for (const error of testCase.errors) {
const indentedError = error.replace(/\n/g, '\n' + EMPTY_LOG_PLACEHOLDER + indentNestingLevel(nestingLevel + 2));
console.log(`${indentNestingLevel(nestingLevel)}\t${indentedError}`);
}
}

public countSkippedTestSuiteTests(testSuite: TestSuite) {
if (testSuite.skip) {
this._skipped += testSuite.testCases.length;
return;
}
for (const testCase of testSuite.testCases) {
if (testCase.skip) {
this._skipped++;
}
}
}

public printSummary() {
this._endTime = Date.now();

console.log('End of tests run 🏁');
console.log('\n');
console.log(
`🧮 Tests summary: ${color(this._passed, 'green')} passed, ${color(this._failed, 'red')} failed, ${color(
this._skipped,
'orange',
)} skipped`,
);
console.log(`⏱️ Total time: ${Math.round(((this._endTime - this._startTime) / 1000) * 100) / 100}s`);
if (this._failed > 0) {
console.log('❌ Failed tests:');
for (const failedTest of this._failedTests) {
console.log(`\t• ${failedTest}`);
}
} else {
console.log('✅ All tests passed!');
}
console.log('\n');
}
}
9 changes: 0 additions & 9 deletions apps/common-app/src/examples/RuntimeTests/ReJest/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -150,12 +150,3 @@ declare global {
};
}
/* eslint-enable no-var */

export type TestSummary = {
passed: number;
failed: number;
skipped: number;
failedTests: Array<string>;
startTime: number;
endTime: number;
};

0 comments on commit 1c805ae

Please sign in to comment.