Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions news/1 Enhancements/4796.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Generalize Test results service
2 changes: 1 addition & 1 deletion resources/dark/status-unknown.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
2 changes: 1 addition & 1 deletion resources/light/status-unknown.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
163 changes: 46 additions & 117 deletions src/client/unittests/common/services/testResultsService.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { inject, injectable, named } from 'inversify';
import { TestDataItem } from '../../types';
import { visitParentsRecursive } from '../testVisitors/visitor';
import { ITestResultsService, ITestVisitor, TestFile, TestFolder, Tests, TestStatus, TestSuite } from './../types';
import { getChildren, getTestType } from '../testUtils';
import { ITestResultsService, ITestVisitor, Tests, TestStatus, TestType } from './../types';

@injectable()
export class TestResultsService implements ITestResultsService {
Expand All @@ -13,134 +13,63 @@ export class TestResultsService implements ITestResultsService {
tests.testFiles.forEach(testFile => this.resultResetVisitor.visitTestFile(testFile));
}
public updateResults(tests: Tests): void {
tests.testFiles.forEach(test => this.updateTestFileResults(test));
tests.rootTestFolders.forEach(folder => this.updateTestFolderResults(folder));
// List items should be updated in order
[TestStatus.Pass, TestStatus.Fail].forEach(item => this.updateParentStatus(tests, item));
}
private updateTestSuiteResults(test: TestSuite): void {
this.updateTestSuiteAndFileResults(test);
}
private updateTestFileResults(test: TestFile): void {
this.updateTestSuiteAndFileResults(test);
}
private updateParentStatus(tests: Tests, status: TestStatus): void {
const visitor = (item: TestDataItem) => item.status = status;
tests.testFiles.forEach(item => {
if (typeof item.passed === 'boolean') {
if (status === TestStatus.Pass ? item.passed : !item.passed) {
visitParentsRecursive(tests, item, visitor);
}
}
});
tests.testSuites.forEach(item => {
if (typeof item.testSuite.passed === 'boolean') {
if (status === TestStatus.Pass ? item.testSuite.passed : !item.testSuite.passed) {
visitParentsRecursive(tests, item.testSuite, visitor);
}
}
});
tests.testFunctions.forEach(item => {
if (typeof item.testFunction.passed === 'boolean') {
if (status === TestStatus.Pass ? item.testFunction.passed : !item.testFunction.passed) {
visitParentsRecursive(tests, item.testFunction, visitor);
}
}
});
}
private updateTestFolderResults(testFolder: TestFolder): void {
let totalTime = 0;
let allFilesPassed = true;
let noFilesRan = true;
testFolder.functionsPassed = testFolder.functionsFailed = testFolder.functionsDidNotRun = 0;
// Update Test tree bottom to top
const testQueue: TestDataItem[] = [];
const testStack: TestDataItem[] = [];
tests.rootTestFolders.forEach(folder => testQueue.push(folder));

testFolder.testFiles.forEach(fl => {
totalTime += fl.time;
if (typeof fl.passed === 'boolean') {
noFilesRan = false;
if (!fl.passed) {
allFilesPassed = false;
}
}

testFolder.functionsFailed! += fl.functionsFailed!;
testFolder.functionsPassed! += fl.functionsPassed!;
testFolder.functionsDidNotRun! += fl.functionsDidNotRun!;
});

let allFoldersPassed = true;
let noFoldersRan = true;

testFolder.folders.forEach(folder => {
totalTime += folder.time;
this.updateTestFolderResults(folder);
if (typeof folder.passed === 'boolean') {
noFoldersRan = false;
if (!folder.passed) {
allFoldersPassed = false;
}
}

testFolder.functionsFailed! += folder.functionsFailed!;
testFolder.functionsPassed! += folder.functionsPassed!;
testFolder.functionsDidNotRun! += folder.functionsDidNotRun!;
});

testFolder.time = totalTime;
if (noFilesRan && noFoldersRan) {
testFolder.passed = undefined;
testFolder.status = TestStatus.Unknown;
} else {
testFolder.passed = allFilesPassed && allFoldersPassed;
testFolder.status = testFolder.passed ? TestStatus.Pass : TestStatus.Fail;
while (testQueue.length > 0) {
const item = testQueue.shift();
testStack.push(item);
const children = getChildren(item);
children.forEach(child => testQueue.push(child));
}
while (testStack.length > 0) {
const item = testStack.pop();
this.updateTestItem(item);
}
}
private updateTestSuiteAndFileResults(test: TestSuite | TestFile): void {
let totalTime = 0;
let allFunctionsPassed = true;
let noFunctionsRan = true;
test.functionsPassed = test.functionsFailed = test.functionsDidNotRun = 0;
private updateTestItem(test: TestDataItem): void {
if (getTestType(test) === TestType.testFunction) {
return;
}
let allChildrenPassed = true;
let noChildrenRan = true;
test.time = test.functionsPassed = test.functionsFailed = test.functionsDidNotRun = 0;

test.functions.forEach(fn => {
totalTime += fn.time;
if (typeof fn.passed === 'boolean') {
noFunctionsRan = false;
if (fn.passed) {
test.functionsPassed! += 1;
const children = getChildren(test);
children.forEach(child => {
test.time += child.time;
if (getTestType(child) === TestType.testFunction) {
if (typeof child.passed === 'boolean') {
noChildrenRan = false;
if (child.passed) {
test.functionsPassed! += 1;
} else {
test.functionsFailed! += 1;
allChildrenPassed = false;
}
} else {
test.functionsFailed! += 1;
allFunctionsPassed = false;
test.functionsDidNotRun! += 1;
}
} else {
test.functionsDidNotRun! += 1;
}
});

let allSuitesPassed = true;
let noSuitesRan = true;

test.suites.forEach(suite => {
this.updateTestSuiteResults(suite);
totalTime += suite.time;
if (typeof suite.passed === 'boolean') {
noSuitesRan = false;
if (!suite.passed) {
allSuitesPassed = false;
if (typeof child.passed === 'boolean') {
noChildrenRan = false;
if (!child.passed) {
allChildrenPassed = false;
}
}
test.functionsFailed! += child.functionsFailed!;
test.functionsPassed! += child.functionsPassed!;
test.functionsDidNotRun! += child.functionsDidNotRun!;
}

test.functionsFailed! += suite.functionsFailed!;
test.functionsPassed! += suite.functionsPassed!;
test.functionsDidNotRun! += suite.functionsDidNotRun!;
});

test.time = totalTime;
if (noSuitesRan && noFunctionsRan) {
if (noChildrenRan) {
test.passed = undefined;
test.status = TestStatus.Unknown;
} else {
test.passed = allFunctionsPassed && allSuitesPassed;
test.status = test.passed ? TestStatus.Pass : TestStatus.Error;
test.passed = allChildrenPassed;
test.status = test.passed ? TestStatus.Pass : TestStatus.Fail;
}
}
}
1 change: 1 addition & 0 deletions src/client/unittests/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -164,6 +164,7 @@ export class TestWorkspaceFolder {
public functionsPassed?: number;
public functionsFailed?: number;
public functionsDidNotRun?: number;
public passed?: boolean;
constructor(public readonly workspaceFolder: WorkspaceFolder) { }
public get resource(): Uri {
return this.workspaceFolder.uri;
Expand Down
Loading