xunit.ts 1.0.2 → 1.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.editorconfig +2 -0
- package/.eslintrc.json +37 -0
- package/cli.ts +5 -5
- package/dist/cli.js.map +1 -1
- package/dist/src/Assertions/Contains.js +1 -1
- package/dist/src/Assertions/Contains.js.map +1 -1
- package/dist/src/Assertions/Count.js.map +1 -1
- package/dist/src/Assertions/Defined.js +2 -2
- package/dist/src/Assertions/Defined.js.map +1 -1
- package/dist/src/Assertions/DoesNotContain.js +1 -1
- package/dist/src/Assertions/DoesNotContain.js.map +1 -1
- package/dist/src/Assertions/DoesNotThrow.js +2 -2
- package/dist/src/Assertions/DoesNotThrow.js.map +1 -1
- package/dist/src/Assertions/Empty.js +1 -1
- package/dist/src/Assertions/Empty.js.map +1 -1
- package/dist/src/Assertions/Equal.js +1 -1
- package/dist/src/Assertions/Equal.js.map +1 -1
- package/dist/src/Assertions/False.js +1 -1
- package/dist/src/Assertions/False.js.map +1 -1
- package/dist/src/Assertions/InstanceOf.d.ts +1 -1
- package/dist/src/Assertions/InstanceOf.d.ts.map +1 -1
- package/dist/src/Assertions/InstanceOf.js.map +1 -1
- package/dist/src/Assertions/NotEmpty.js +2 -2
- package/dist/src/Assertions/NotEmpty.js.map +1 -1
- package/dist/src/Assertions/NotEqual.js +1 -1
- package/dist/src/Assertions/NotEqual.js.map +1 -1
- package/dist/src/Assertions/NotNull.js +2 -2
- package/dist/src/Assertions/NotNull.js.map +1 -1
- package/dist/src/Assertions/Null.js +1 -1
- package/dist/src/Assertions/Null.js.map +1 -1
- package/dist/src/Assertions/StringContains.js +1 -1
- package/dist/src/Assertions/StringContains.js.map +1 -1
- package/dist/src/Assertions/StringDoesNotContain.d.ts.map +1 -1
- package/dist/src/Assertions/StringDoesNotContain.js +1 -1
- package/dist/src/Assertions/StringDoesNotContain.js.map +1 -1
- package/dist/src/Assertions/StringDoesNotEndWith.js +1 -1
- package/dist/src/Assertions/StringDoesNotEndWith.js.map +1 -1
- package/dist/src/Assertions/StringDoesNotStartWith.d.ts.map +1 -1
- package/dist/src/Assertions/StringDoesNotStartWith.js +1 -1
- package/dist/src/Assertions/StringDoesNotStartWith.js.map +1 -1
- package/dist/src/Assertions/StringEndsWith.js +1 -1
- package/dist/src/Assertions/StringEndsWith.js.map +1 -1
- package/dist/src/Assertions/StringStartsWith.d.ts.map +1 -1
- package/dist/src/Assertions/StringStartsWith.js +1 -1
- package/dist/src/Assertions/StringStartsWith.js.map +1 -1
- package/dist/src/Assertions/Throws.js +1 -1
- package/dist/src/Assertions/Throws.js.map +1 -1
- package/dist/src/Assertions/True.js +1 -1
- package/dist/src/Assertions/True.js.map +1 -1
- package/dist/src/Assertions/Undefined.js +1 -1
- package/dist/src/Assertions/Undefined.js.map +1 -1
- package/dist/src/Assertions/index.d.ts +22 -22
- package/dist/src/Assertions/index.d.ts.map +1 -1
- package/dist/src/Assertions/index.js.map +1 -1
- package/dist/src/CLI.d.ts.map +1 -1
- package/dist/src/CLI.js +2 -2
- package/dist/src/CLI.js.map +1 -1
- package/dist/src/Factory.d.ts +4 -4
- package/dist/src/Factory.d.ts.map +1 -1
- package/dist/src/Factory.js.map +1 -1
- package/dist/src/Framework/ResultType.d.ts.map +1 -1
- package/dist/src/Framework/ResultType.js.map +1 -1
- package/dist/src/Framework/Test.d.ts.map +1 -1
- package/dist/src/Framework/Test.js.map +1 -1
- package/dist/src/Framework/TestName.d.ts.map +1 -1
- package/dist/src/Framework/TestName.js.map +1 -1
- package/dist/src/Framework/TestResult.d.ts.map +1 -1
- package/dist/src/Framework/TestResult.js.map +1 -1
- package/dist/src/Framework/TestSuite.d.ts +1 -1
- package/dist/src/Framework/TestSuite.d.ts.map +1 -1
- package/dist/src/Framework/TestSuite.js.map +1 -1
- package/dist/src/Framework/TestSuiteResults.d.ts +1 -1
- package/dist/src/Framework/TestSuiteResults.d.ts.map +1 -1
- package/dist/src/Framework/TestSuiteResults.js.map +1 -1
- package/dist/src/IO/FileSystem.d.ts +2 -2
- package/dist/src/IO/FileSystem.d.ts.map +1 -1
- package/dist/src/IO/FileSystem.js +6 -6
- package/dist/src/IO/FileSystem.js.map +1 -1
- package/dist/src/IO/Output.d.ts.map +1 -1
- package/dist/src/IO/Output.js.map +1 -1
- package/dist/src/Reporters/ConsoleReporter.d.ts.map +1 -1
- package/dist/src/Reporters/ConsoleReporter.js +8 -7
- package/dist/src/Reporters/ConsoleReporter.js.map +1 -1
- package/dist/src/Reporters/FileReporter.d.ts.map +1 -1
- package/dist/src/Reporters/FileReporter.js +1 -0
- package/dist/src/Reporters/FileReporter.js.map +1 -1
- package/dist/src/Reporters/JUnitReporter.d.ts +2 -2
- package/dist/src/Reporters/JUnitReporter.d.ts.map +1 -1
- package/dist/src/Reporters/JUnitReporter.js +7 -7
- package/dist/src/Reporters/JUnitReporter.js.map +1 -1
- package/dist/src/Reporters/ResultReporter.d.ts +3 -3
- package/dist/src/Reporters/ResultReporter.d.ts.map +1 -1
- package/dist/src/Reporters/SonarReporter.d.ts +2 -2
- package/dist/src/Reporters/SonarReporter.d.ts.map +1 -1
- package/dist/src/Reporters/SonarReporter.js +16 -16
- package/dist/src/Reporters/SonarReporter.js.map +1 -1
- package/dist/src/Reporters/XMLReporter.d.ts.map +1 -1
- package/dist/src/Reporters/XMLReporter.js.map +1 -1
- package/dist/src/Runners/Runner.d.ts +3 -3
- package/dist/src/Runners/Runner.d.ts.map +1 -1
- package/dist/src/Runners/Runner.js +5 -5
- package/dist/src/Runners/Runner.js.map +1 -1
- package/dist/src/Runners/TestRunner.d.ts +4 -4
- package/dist/src/Runners/TestRunner.d.ts.map +1 -1
- package/dist/src/Runners/TestRunner.js +4 -4
- package/dist/src/Runners/TestRunner.js.map +1 -1
- package/dist/src/Runners/TestSuiteLoader.d.ts +3 -3
- package/dist/src/Runners/TestSuiteLoader.d.ts.map +1 -1
- package/dist/src/Runners/TestSuiteLoader.js +15 -15
- package/dist/src/Runners/TestSuiteLoader.js.map +1 -1
- package/dist/src/Runners/TestSuiteRunner.d.ts +5 -5
- package/dist/src/Runners/TestSuiteRunner.d.ts.map +1 -1
- package/dist/src/Runners/TestSuiteRunner.js +1 -1
- package/dist/src/Runners/TestSuiteRunner.js.map +1 -1
- package/dist/xunit.d.ts +3 -3
- package/dist/xunit.d.ts.map +1 -1
- package/dist/xunit.js.map +1 -1
- package/icon.svg +74 -75
- package/logo.svg +130 -130
- package/package.json +43 -37
- package/src/Assertions/Contains.ts +10 -10
- package/src/Assertions/Count.ts +11 -11
- package/src/Assertions/Defined.ts +11 -11
- package/src/Assertions/DoesNotContain.ts +11 -11
- package/src/Assertions/DoesNotThrow.ts +13 -13
- package/src/Assertions/Empty.ts +11 -11
- package/src/Assertions/Equal.ts +12 -12
- package/src/Assertions/False.ts +11 -11
- package/src/Assertions/InstanceOf.ts +2 -2
- package/src/Assertions/NotEmpty.ts +11 -11
- package/src/Assertions/NotEqual.ts +12 -12
- package/src/Assertions/NotNull.ts +11 -11
- package/src/Assertions/Null.ts +11 -11
- package/src/Assertions/StringContains.ts +11 -11
- package/src/Assertions/StringDoesNotContain.ts +12 -12
- package/src/Assertions/StringDoesNotEndWith.ts +13 -13
- package/src/Assertions/StringDoesNotStartWith.ts +12 -12
- package/src/Assertions/StringEndsWith.ts +13 -13
- package/src/Assertions/StringStartsWith.ts +12 -12
- package/src/Assertions/Throws.ts +11 -11
- package/src/Assertions/True.ts +11 -11
- package/src/Assertions/Undefined.ts +12 -12
- package/src/Assertions/index.ts +45 -45
- package/src/CLI.ts +85 -85
- package/src/Factory.ts +25 -25
- package/src/Framework/ResultType.ts +4 -4
- package/src/Framework/Test.ts +6 -6
- package/src/Framework/TestName.ts +7 -7
- package/src/Framework/TestResult.ts +3 -2
- package/src/Framework/TestSuite.ts +18 -18
- package/src/Framework/TestSuiteResults.ts +17 -16
- package/src/IO/FileSystem.ts +28 -29
- package/src/IO/Output.ts +21 -20
- package/src/Reporters/ConsoleReporter.ts +88 -87
- package/src/Reporters/FileReporter.ts +29 -29
- package/src/Reporters/JUnitReporter.ts +80 -80
- package/src/Reporters/ResultReporter.ts +20 -12
- package/src/Reporters/SonarReporter.ts +86 -86
- package/src/Reporters/XMLReporter.ts +6 -6
- package/src/Runners/Runner.ts +21 -21
- package/src/Runners/TestRunner.ts +34 -33
- package/src/Runners/TestSuiteLoader.ts +41 -40
- package/src/Runners/TestSuiteRunner.ts +27 -26
- package/tsconfig.json +26 -26
- package/xunit.ts +6 -6
|
@@ -1,94 +1,94 @@
|
|
|
1
|
-
import TestSuiteResults from
|
|
2
|
-
import xml from
|
|
1
|
+
import TestSuiteResults from "../Framework/TestSuiteResults";
|
|
2
|
+
import xml from "xml";
|
|
3
3
|
import TestName from "../Framework/TestName";
|
|
4
|
-
import {ResultType} from "../Framework/ResultType";
|
|
4
|
+
import { ResultType } from "../Framework/ResultType";
|
|
5
5
|
import TestResult from "../Framework/TestResult";
|
|
6
6
|
import XMLReporter from "./XMLReporter";
|
|
7
7
|
|
|
8
8
|
export default class JUnitReporter extends XMLReporter {
|
|
9
|
-
|
|
9
|
+
static readonly defaultFileName: string = "junit.xml";
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
11
|
+
private static testSuite(results: TestSuiteResults, id: number) {
|
|
12
|
+
return {
|
|
13
|
+
testsuite: [
|
|
14
|
+
{
|
|
15
|
+
_attr: {
|
|
16
|
+
id: id,
|
|
17
|
+
name: TestName.toSentenceCase(results.suite.constructor.name),
|
|
18
|
+
tests: results.total(),
|
|
19
|
+
failures: results.count(ResultType.Failed),
|
|
20
|
+
errors: results.count(ResultType.Error),
|
|
21
|
+
skipped: results.count(ResultType.Incomplete),
|
|
22
|
+
time: results.time() / 1_000
|
|
23
|
+
}
|
|
24
|
+
},
|
|
25
|
+
...Object.keys(results.results)
|
|
26
|
+
.map(test_name => JUnitReporter.testCase(test_name, results.suite.constructor.name, results.results[test_name]))
|
|
27
|
+
]
|
|
28
|
+
};
|
|
29
|
+
}
|
|
17
30
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
skipped: results.count(ResultType.Incomplete),
|
|
29
|
-
time: results.time() / 1_000
|
|
30
|
-
}
|
|
31
|
-
},
|
|
32
|
-
...Object.keys(results.results)
|
|
33
|
-
.map(test_name => JUnitReporter.testCase(test_name, results.suite.constructor.name, results.results[test_name]))
|
|
34
|
-
]
|
|
35
|
-
};
|
|
36
|
-
}
|
|
31
|
+
private static testCase(test_name: string, suite_name: string, result: TestResult) {
|
|
32
|
+
const testcase: object[] = [
|
|
33
|
+
{
|
|
34
|
+
_attr: {
|
|
35
|
+
name: test_name,
|
|
36
|
+
classname: suite_name,
|
|
37
|
+
time: result.duration / 1_000
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
];
|
|
37
41
|
|
|
38
|
-
|
|
39
|
-
const testcase: object[] = [
|
|
40
|
-
{
|
|
41
|
-
_attr: {
|
|
42
|
-
name: test_name,
|
|
43
|
-
classname: suite_name,
|
|
44
|
-
time: result.duration / 1_000
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
];
|
|
42
|
+
const details = JUnitReporter.details(result);
|
|
48
43
|
|
|
49
|
-
|
|
44
|
+
if (details !== null) {
|
|
45
|
+
testcase.push(details);
|
|
46
|
+
}
|
|
50
47
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
return {
|
|
56
|
-
testcase: testcase
|
|
57
|
-
};
|
|
58
|
-
}
|
|
48
|
+
return {
|
|
49
|
+
testcase: testcase
|
|
50
|
+
};
|
|
51
|
+
}
|
|
59
52
|
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
53
|
+
private static details(result: TestResult): object | null {
|
|
54
|
+
switch (result.type) {
|
|
55
|
+
case ResultType.Incomplete:
|
|
56
|
+
return { skipped: {} };
|
|
57
|
+
case ResultType.Failed:
|
|
58
|
+
return JUnitReporter.failure(result);
|
|
59
|
+
case ResultType.Error:
|
|
60
|
+
return JUnitReporter.error(result);
|
|
61
|
+
default:
|
|
62
|
+
return null;
|
|
63
|
+
}
|
|
64
|
+
}
|
|
72
65
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
66
|
+
private static failure(result: TestResult) {
|
|
67
|
+
return {
|
|
68
|
+
failure: {
|
|
69
|
+
_attr: {
|
|
70
|
+
type: result.error?.name,
|
|
71
|
+
message: result.error?.message
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
};
|
|
75
|
+
}
|
|
83
76
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
77
|
+
private static error(result: TestResult) {
|
|
78
|
+
return {
|
|
79
|
+
error: {
|
|
80
|
+
_attr: {
|
|
81
|
+
type: result.error?.name,
|
|
82
|
+
message: result.error?.message
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
};
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
xml(results: Record<string, TestSuiteResults>): string {
|
|
89
|
+
const data = {
|
|
90
|
+
"testsuites": Object.values(results).map((result, index) => JUnitReporter.testSuite(result, index))
|
|
91
|
+
};
|
|
92
|
+
return xml(data, { indent: "\t" });
|
|
93
|
+
}
|
|
94
94
|
}
|
|
@@ -1,15 +1,23 @@
|
|
|
1
|
-
import TestSuite from
|
|
2
|
-
import { AssertionError } from
|
|
3
|
-
import TestSuiteResults from
|
|
1
|
+
import TestSuite from "../Framework/TestSuite";
|
|
2
|
+
import { AssertionError } from "assert";
|
|
3
|
+
import TestSuiteResults from "../Framework/TestSuiteResults";
|
|
4
4
|
|
|
5
5
|
export default interface ResultReporter {
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
6
|
+
runStarted(): void;
|
|
7
|
+
|
|
8
|
+
suiteStarted(suite: TestSuite): void;
|
|
9
|
+
|
|
10
|
+
testStarted(suite: TestSuite, test_name: string): void;
|
|
11
|
+
|
|
12
|
+
testPassed(suite: TestSuite, test_name: string, duration: number): void;
|
|
13
|
+
|
|
14
|
+
testFailed(suite: TestSuite, test_name: string, error: AssertionError, duration: number): void;
|
|
15
|
+
|
|
16
|
+
testErrored(suite: TestSuite, test_name: string, error: Error, duration: number): void;
|
|
17
|
+
|
|
18
|
+
testIncomplete(suite: TestSuite, test_name: string): void;
|
|
19
|
+
|
|
20
|
+
suiteCompleted(suite: TestSuite, results: TestSuiteResults): void;
|
|
21
|
+
|
|
22
|
+
runCompleted(results: Record<string, TestSuiteResults>): void;
|
|
15
23
|
}
|
|
@@ -1,100 +1,100 @@
|
|
|
1
|
-
import TestSuiteResults from
|
|
2
|
-
import xml from
|
|
3
|
-
import {ResultType} from "../Framework/ResultType";
|
|
1
|
+
import TestSuiteResults from "../Framework/TestSuiteResults";
|
|
2
|
+
import xml from "xml";
|
|
3
|
+
import { ResultType } from "../Framework/ResultType";
|
|
4
4
|
import TestResult from "../Framework/TestResult";
|
|
5
5
|
import XMLReporter from "./XMLReporter";
|
|
6
6
|
import path from "path";
|
|
7
7
|
|
|
8
8
|
export default class SonarReporter extends XMLReporter {
|
|
9
|
-
|
|
9
|
+
static readonly defaultFileName: string = "sonar.xml";
|
|
10
10
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
}
|
|
11
|
+
private static testSuite(results: TestSuiteResults, file: string) {
|
|
12
|
+
return {
|
|
13
|
+
file: [
|
|
14
|
+
{
|
|
15
|
+
_attr: {
|
|
16
|
+
path: file.substr(file.split(path.sep)[0].length + 1).replace(/\.js$/, ".ts"),
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
...Object.keys(results.results)
|
|
20
|
+
.map(test_name => SonarReporter.testCase(test_name, results.results[test_name]))
|
|
21
|
+
]
|
|
22
|
+
};
|
|
23
|
+
}
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
.map(test_name => SonarReporter.testCase(test_name, results.results[test_name]))
|
|
36
|
-
]
|
|
37
|
-
};
|
|
38
|
-
}
|
|
25
|
+
private static testCase(test_name: string, result: TestResult) {
|
|
26
|
+
const testcase: object[] = [
|
|
27
|
+
{
|
|
28
|
+
_attr: {
|
|
29
|
+
name: test_name,
|
|
30
|
+
duration: Math.round(result.duration)
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
];
|
|
39
34
|
|
|
40
|
-
|
|
41
|
-
const testcase: object[] = [
|
|
42
|
-
{
|
|
43
|
-
_attr: {
|
|
44
|
-
name: test_name,
|
|
45
|
-
duration: Math.round(result.duration)
|
|
46
|
-
}
|
|
47
|
-
}
|
|
48
|
-
];
|
|
35
|
+
const details = SonarReporter.details(result);
|
|
49
36
|
|
|
50
|
-
|
|
37
|
+
if (details !== null) {
|
|
38
|
+
testcase.push(details);
|
|
39
|
+
}
|
|
51
40
|
|
|
52
|
-
if (details !== null) {
|
|
53
|
-
testcase.push(details);
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
return {
|
|
58
|
-
testCase: testcase
|
|
59
|
-
};
|
|
60
|
-
}
|
|
61
41
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
case ResultType.Failed:
|
|
67
|
-
return SonarReporter.failure(result);
|
|
68
|
-
case ResultType.Error:
|
|
69
|
-
return SonarReporter.error(result);
|
|
70
|
-
default:
|
|
71
|
-
return null;
|
|
72
|
-
}
|
|
73
|
-
}
|
|
42
|
+
return {
|
|
43
|
+
testCase: testcase
|
|
44
|
+
};
|
|
45
|
+
}
|
|
74
46
|
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
47
|
+
private static details(result: TestResult): object | null {
|
|
48
|
+
switch (result.type) {
|
|
49
|
+
case ResultType.Incomplete:
|
|
50
|
+
return { skipped: {} };
|
|
51
|
+
case ResultType.Failed:
|
|
52
|
+
return SonarReporter.failure(result);
|
|
53
|
+
case ResultType.Error:
|
|
54
|
+
return SonarReporter.error(result);
|
|
55
|
+
default:
|
|
56
|
+
return null;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
87
59
|
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
60
|
+
private static failure(result: TestResult) {
|
|
61
|
+
return {
|
|
62
|
+
failure: [
|
|
63
|
+
{
|
|
64
|
+
_attr: {
|
|
65
|
+
message: result.error?.message
|
|
66
|
+
}
|
|
67
|
+
},
|
|
68
|
+
result.error?.stack
|
|
69
|
+
]
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
private static error(result: TestResult) {
|
|
74
|
+
return {
|
|
75
|
+
error: [
|
|
76
|
+
{
|
|
77
|
+
_attr: {
|
|
78
|
+
message: result.error?.message
|
|
79
|
+
}
|
|
80
|
+
},
|
|
81
|
+
result.error?.stack
|
|
82
|
+
]
|
|
83
|
+
};
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
xml(results: Record<string, TestSuiteResults>): string {
|
|
87
|
+
const data = {
|
|
88
|
+
testExecutions: [
|
|
89
|
+
{
|
|
90
|
+
_attr: {
|
|
91
|
+
version: 1
|
|
92
|
+
}
|
|
93
|
+
},
|
|
94
|
+
...Object.keys(results)
|
|
95
|
+
.map(file => SonarReporter.testSuite(results[file], file))
|
|
96
|
+
]
|
|
97
|
+
};
|
|
98
|
+
return xml(data, { indent: "\t" });
|
|
99
|
+
}
|
|
100
100
|
}
|
|
@@ -2,10 +2,10 @@
|
|
|
2
2
|
import TestSuiteResults from "../Framework/TestSuiteResults";
|
|
3
3
|
|
|
4
4
|
export default abstract class XMLReporter extends FileReporter {
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
5
|
+
async runCompleted(results: Record<string, TestSuiteResults>): Promise<void> {
|
|
6
|
+
const xmlString = this.xml(results);
|
|
7
|
+
await this.file_system.save(xmlString, this.path);
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
abstract xml(results: Record<string, TestSuiteResults>): string;
|
|
11
11
|
}
|
package/src/Runners/Runner.ts
CHANGED
|
@@ -1,29 +1,29 @@
|
|
|
1
|
-
import TestSuiteLoader from
|
|
2
|
-
import TestSuiteRunner from
|
|
1
|
+
import TestSuiteLoader from "./TestSuiteLoader";
|
|
2
|
+
import TestSuiteRunner from "./TestSuiteRunner";
|
|
3
3
|
import ResultReporter from "../Reporters/ResultReporter";
|
|
4
4
|
import TestSuiteResults from "../Framework/TestSuiteResults";
|
|
5
|
-
import {ResultType} from
|
|
5
|
+
import { ResultType } from "../Framework/ResultType";
|
|
6
6
|
|
|
7
7
|
export default class Runner {
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
9
|
+
constructor(private readonly loader: TestSuiteLoader, private readonly runner: TestSuiteRunner, private readonly reporters: ReadonlyArray<ResultReporter>) {
|
|
10
|
+
}
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
const suite = suites[file];
|
|
18
|
-
results[file] = await this.runner.runSuite(suite);
|
|
19
|
-
}
|
|
20
|
-
await Promise.all(this.reporters.map(r => r.runCompleted(results)));
|
|
21
|
-
return results;
|
|
22
|
-
}
|
|
12
|
+
static allTestsPassed(results: Record<string, TestSuiteResults>): boolean {
|
|
13
|
+
const tests_with_results = Object.values(results).filter(result => result.total() > 0);
|
|
14
|
+
return tests_with_results.length > 0
|
|
15
|
+
&& tests_with_results.filter(result => result.count(ResultType.Passed) < result.total()).length === 0;
|
|
16
|
+
}
|
|
23
17
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
18
|
+
async runAll(dir: string): Promise<Record<string, TestSuiteResults>> {
|
|
19
|
+
await Promise.all(this.reporters.map(r => r.runStarted()));
|
|
20
|
+
const results: Record<string, TestSuiteResults> = {};
|
|
21
|
+
const suites = await this.loader.loadTestSuites(dir);
|
|
22
|
+
for (const file of Object.keys(suites)) {
|
|
23
|
+
const suite = suites[file];
|
|
24
|
+
results[file] = await this.runner.runSuite(suite);
|
|
25
|
+
}
|
|
26
|
+
await Promise.all(this.reporters.map(r => r.runCompleted(results)));
|
|
27
|
+
return results;
|
|
28
|
+
}
|
|
29
29
|
}
|
|
@@ -1,43 +1,44 @@
|
|
|
1
|
-
import TestInfo from
|
|
2
|
-
import TestSuite from
|
|
3
|
-
import { ResultType } from
|
|
4
|
-
import ResultReporter from
|
|
1
|
+
import TestInfo from "../Framework/TestInfo";
|
|
2
|
+
import TestSuite from "../Framework/TestSuite";
|
|
3
|
+
import { ResultType } from "../Framework/ResultType";
|
|
4
|
+
import ResultReporter from "../Reporters/ResultReporter";
|
|
5
5
|
import TestResult from "../Framework/TestResult";
|
|
6
|
-
import {AssertionError} from "assert";
|
|
6
|
+
import { AssertionError } from "assert";
|
|
7
7
|
|
|
8
8
|
export default class TestRunner {
|
|
9
9
|
|
|
10
|
-
|
|
10
|
+
constructor(private readonly reporters: ReadonlyArray<ResultReporter>) {
|
|
11
|
+
}
|
|
11
12
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
return new TestResult(ResultType.Incomplete, 0);
|
|
17
|
-
}
|
|
13
|
+
private static msSince(start: [ number, number ]) {
|
|
14
|
+
const duration = process.hrtime(start);
|
|
15
|
+
return duration[0] * 1_000 + duration[1] / 1_000_000;
|
|
16
|
+
}
|
|
18
17
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
18
|
+
async runTest(name: string, info: TestInfo, suite: TestSuite): Promise<TestResult> {
|
|
19
|
+
await Promise.all(this.reporters.map(r => r.testStarted(suite, name)));
|
|
20
|
+
if (info.value === undefined) {
|
|
21
|
+
await Promise.all(this.reporters.map(r => r.testIncomplete(suite, name)));
|
|
22
|
+
return new TestResult(ResultType.Incomplete, 0);
|
|
23
|
+
}
|
|
25
24
|
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
}
|
|
25
|
+
const start = process.hrtime();
|
|
26
|
+
try {
|
|
27
|
+
await info.value.call(suite);
|
|
28
|
+
const duration = TestRunner.msSince(start);
|
|
29
|
+
await Promise.all(this.reporters.map(r => r.testPassed(suite, name, duration)));
|
|
30
|
+
return new TestResult(ResultType.Passed, duration);
|
|
33
31
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
32
|
+
} catch (error) {
|
|
33
|
+
const duration = TestRunner.msSince(start);
|
|
34
|
+
const typedError = error as Error;
|
|
35
|
+
if (typedError instanceof AssertionError) {
|
|
36
|
+
await Promise.all(this.reporters.map(r => r.testFailed(suite, name, typedError, duration)));
|
|
37
|
+
return new TestResult(ResultType.Failed, duration, typedError);
|
|
38
|
+
}
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
40
|
+
await Promise.all(this.reporters.map(r => r.testErrored(suite, name, typedError, duration)));
|
|
41
|
+
return new TestResult(ResultType.Error, duration, typedError);
|
|
42
|
+
}
|
|
43
|
+
}
|
|
43
44
|
}
|
|
@@ -1,49 +1,50 @@
|
|
|
1
|
-
import TestSuite from
|
|
2
|
-
import FileSystem from
|
|
3
|
-
import path from
|
|
1
|
+
import TestSuite from "../Framework/TestSuite";
|
|
2
|
+
import FileSystem from "../IO/FileSystem";
|
|
3
|
+
import path from "path";
|
|
4
4
|
|
|
5
5
|
export default class TestSuiteLoader {
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
constructor(private readonly file_system: FileSystem) {
|
|
8
|
+
}
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
if (suite !== undefined && suite !== null) {
|
|
16
|
-
suites[file] = suite;
|
|
17
|
-
}
|
|
18
|
-
}
|
|
19
|
-
return suites;
|
|
20
|
-
}
|
|
10
|
+
static async loadTestSuite(file: string) {
|
|
11
|
+
const module_path = TestSuiteLoader.getModulePath(__dirname, file);
|
|
12
|
+
const test_class = await import(module_path);
|
|
13
|
+
if (!(test_class.default.prototype instanceof TestSuite)) {
|
|
14
|
+
return null;
|
|
15
|
+
}
|
|
21
16
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
17
|
+
const tests = test_class.default.prototype.getTests();
|
|
18
|
+
const suite: TestSuite = new test_class.default();
|
|
19
|
+
suite.setTests(tests);
|
|
20
|
+
return suite;
|
|
21
|
+
}
|
|
28
22
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
23
|
+
static getModulePath(current_dir: string, file: string) {
|
|
24
|
+
const root = TestSuiteLoader.isFromNodeModules(path.resolve(current_dir))
|
|
25
|
+
? `..${path.sep}..${path.sep}..${path.sep}..${path.sep}..`
|
|
26
|
+
: `..${path.sep}..${path.sep}..`;
|
|
27
|
+
const extension = FileSystem.extension(file);
|
|
28
|
+
const module_name = extension.length > 0
|
|
29
|
+
? file.substr(0, file.length - extension.length - 1)
|
|
30
|
+
: file;
|
|
31
|
+
return `${root}${path.sep}${module_name}`;
|
|
32
|
+
}
|
|
34
33
|
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
: `..${path.sep}..${path.sep}..`;
|
|
39
|
-
const extension = FileSystem.extension(file);
|
|
40
|
-
const module_name = extension.length > 0
|
|
41
|
-
? file.substr(0, file.length - extension.length - 1)
|
|
42
|
-
: file;
|
|
43
|
-
return `${root}${path.sep}${module_name}`;
|
|
44
|
-
}
|
|
34
|
+
static isFromNodeModules(dir: string) {
|
|
35
|
+
return dir.indexOf("node_modules") !== -1;
|
|
36
|
+
}
|
|
45
37
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
38
|
+
async loadTestSuites(dir: string): Promise<Record<string, TestSuite>> {
|
|
39
|
+
const files = (await this.file_system.getFiles(dir))
|
|
40
|
+
.filter((file) => FileSystem.extension(file) === FileSystem.extension(__filename));
|
|
41
|
+
const suites: Record<string, TestSuite> = {};
|
|
42
|
+
for (const file of files) {
|
|
43
|
+
const suite = await TestSuiteLoader.loadTestSuite(file);
|
|
44
|
+
if (suite !== undefined && suite !== null) {
|
|
45
|
+
suites[file] = suite;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return suites;
|
|
49
|
+
}
|
|
49
50
|
}
|