Skip to content

Commit ccd4238

Browse files
committed
Simplify XCTestOutputParser
1 parent 38de2d4 commit ccd4238

File tree

3 files changed

+48
-54
lines changed

3 files changed

+48
-54
lines changed

Diff for: src/TestExplorer/TestParsers/XCTestOutputParser.ts

+29-10
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import { ITestRunState } from "./TestRunState";
1616

1717
/** Regex for parsing XCTest output */
18-
export interface TestRegex {
18+
interface TestRegex {
1919
started: RegExp;
2020
passed: RegExp;
2121
failed: RegExp;
@@ -67,11 +67,21 @@ export const nonDarwinTestRegex = {
6767
};
6868

6969
export class XCTestOutputParser {
70+
private regex: TestRegex;
71+
72+
/**
73+
* Create an XCTestOutputParser.
74+
* Optional regex can be supplied for tests.
75+
*/
76+
constructor(regex?: TestRegex) {
77+
this.regex = regex ?? this.platformTestRegex;
78+
}
79+
7080
/**
7181
* Parse results from `swift test` and update tests accordingly
7282
* @param output Output from `swift test`
7383
*/
74-
public parseResult(output: string, runState: ITestRunState, regex: TestRegex) {
84+
public parseResult(output: string, runState: ITestRunState) {
7585
const output2 = output.replace(/\r\n/g, "\n");
7686
const lines = output2.split("\n");
7787
if (runState.excess) {
@@ -98,23 +108,23 @@ export class XCTestOutputParser {
98108
// the above method is unsuccessful.
99109
for (const line of lines) {
100110
// Regex "Test Case '-[<test target> <class.function>]' started"
101-
const startedMatch = regex.started.exec(line);
111+
const startedMatch = this.regex.started.exec(line);
102112
if (startedMatch) {
103113
const testName = `${startedMatch[1]}/${startedMatch[2]}`;
104114
const startedTestIndex = runState.getTestItemIndex(testName, undefined);
105115
this.startTest(startedTestIndex, runState);
106116
continue;
107117
}
108118
// Regex "Test Case '-[<test target> <class.function>]' failed (<duration> seconds)"
109-
const failedMatch = regex.failed.exec(line);
119+
const failedMatch = this.regex.failed.exec(line);
110120
if (failedMatch) {
111121
const testName = `${failedMatch[1]}/${failedMatch[2]}`;
112122
const failedTestIndex = runState.getTestItemIndex(testName, undefined);
113123
this.failTest(failedTestIndex, { duration: +failedMatch[3] }, runState);
114124
continue;
115125
}
116126
// Regex "<path/to/test>:<line number>: error: <class>.<function> : <error>"
117-
const errorMatch = regex.error.exec(line);
127+
const errorMatch = this.regex.error.exec(line);
118128
if (errorMatch) {
119129
const testName = `${errorMatch[3]}/${errorMatch[4]}`;
120130
const failedTestIndex = runState.getTestItemIndex(testName, errorMatch[1]);
@@ -128,27 +138,27 @@ export class XCTestOutputParser {
128138
continue;
129139
}
130140
// Regex "<path/to/test>:<line number>: <class>.<function> : Test skipped"
131-
const skippedMatch = regex.skipped.exec(line);
141+
const skippedMatch = this.regex.skipped.exec(line);
132142
if (skippedMatch) {
133143
const testName = `${skippedMatch[3]}/${skippedMatch[4]}`;
134144
const skippedTestIndex = runState.getTestItemIndex(testName, skippedMatch[1]);
135145
this.skipTest(skippedTestIndex, runState);
136146
continue;
137147
}
138148
// Regex "Test Suite '-[<test target> <class.function>]' started"
139-
const startedSuiteMatch = regex.startedSuite.exec(line);
149+
const startedSuiteMatch = this.regex.startedSuite.exec(line);
140150
if (startedSuiteMatch) {
141151
this.startTestSuite(startedSuiteMatch[1], runState);
142152
continue;
143153
}
144154
// Regex "Test Suite '-[<test target> <class.function>]' passed"
145-
const passedSuiteMatch = regex.passedSuite.exec(line);
155+
const passedSuiteMatch = this.regex.passedSuite.exec(line);
146156
if (passedSuiteMatch) {
147157
this.passTestSuite(passedSuiteMatch[1], runState);
148158
continue;
149159
}
150160
// Regex "Test Suite '-[<test target> <class.function>]' failed"
151-
const failedSuiteMatch = regex.failedSuite.exec(line);
161+
const failedSuiteMatch = this.regex.failedSuite.exec(line);
152162
if (failedSuiteMatch) {
153163
this.failTestSuite(failedSuiteMatch[1], runState);
154164
continue;
@@ -162,7 +172,7 @@ export class XCTestOutputParser {
162172
// to be passed.
163173
for (const line of lines) {
164174
// Regex "Test Case '<class>.<function>' passed (<duration> seconds)"
165-
const passedMatch = regex.passed.exec(line);
175+
const passedMatch = this.regex.passed.exec(line);
166176
if (passedMatch) {
167177
const testName = `${passedMatch[1]}/${passedMatch[2]}`;
168178
const duration: number = +passedMatch[3];
@@ -173,6 +183,15 @@ export class XCTestOutputParser {
173183
}
174184
}
175185

186+
/** Get Test parsing regex for current platform */
187+
private get platformTestRegex(): TestRegex {
188+
if (process.platform === "darwin") {
189+
return darwinTestRegex;
190+
} else {
191+
return nonDarwinTestRegex;
192+
}
193+
}
194+
176195
/** Flag a test suite has started */
177196
private startTestSuite(name: string, runState: ITestRunState) {
178197
runState.startedSuite(name);

Diff for: src/TestExplorer/TestRunner.ts

+3-19
Original file line numberDiff line numberDiff line change
@@ -33,12 +33,7 @@ import {
3333
import { getBuildAllTask } from "../SwiftTaskProvider";
3434
import configuration from "../configuration";
3535
import { WorkspaceContext } from "../WorkspaceContext";
36-
import {
37-
darwinTestRegex,
38-
nonDarwinTestRegex,
39-
XCTestOutputParser,
40-
TestRegex,
41-
} from "./TestParsers/XCTestOutputParser";
36+
import { XCTestOutputParser } from "./TestParsers/XCTestOutputParser";
4237
import { SwiftTestingOutputParser } from "./TestParsers/SwiftTestingOutputParser";
4338
import { Version } from "../utilities/version";
4439
import { LoggingDebugAdapterTracker } from "../debugger/logTracker";
@@ -259,13 +254,12 @@ export class TestRunner {
259254
if (testBuildConfig === null) {
260255
return;
261256
}
262-
const testRegex = this.testRegex;
263257
// Parse output from stream and output to log
264258
const parsedOutputStream = new stream.Writable({
265259
write: (chunk, encoding, next) => {
266260
const text = chunk.toString();
267261
this.testRun.appendOutput(text.replace(/\n/g, "\r\n"));
268-
this.xcTestOutputParser.parseResult(text, runState, testRegex);
262+
this.xcTestOutputParser.parseResult(text, runState);
269263
next();
270264
},
271265
});
@@ -570,7 +564,6 @@ export class TestRunner {
570564
config => config !== null
571565
) as vscode.DebugConfiguration[];
572566

573-
const testRegex = this.testRegex;
574567
const subscriptions: vscode.Disposable[] = [];
575568

576569
const debugRuns = validBuildConfigs.map(config => {
@@ -584,7 +577,7 @@ export class TestRunner {
584577
);
585578
LoggingDebugAdapterTracker.setDebugSessionCallback(session, output => {
586579
this.testRun.appendOutput(output);
587-
this.xcTestOutputParser.parseResult(output, runState, testRegex);
580+
this.xcTestOutputParser.parseResult(output, runState);
588581
});
589582
const cancellation = token.onCancellationRequested(() => {
590583
this.workspaceContext.outputChannel.logDiagnostic(
@@ -659,15 +652,6 @@ export class TestRunner {
659652
return new NonDarwinTestItemFinder(this.testArgs.testItems, this.folderContext);
660653
}
661654
}
662-
663-
/** Get Test parsing regex for current platform */
664-
get testRegex(): TestRegex {
665-
if (process.platform === "darwin") {
666-
return darwinTestRegex;
667-
} else {
668-
return nonDarwinTestRegex;
669-
}
670-
}
671655
}
672656

673657
class LaunchConfigurations {

Diff for: test/suite/testexplorer/XCTestOutputParser.test.ts

+16-25
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,18 @@ import {
2020
} from "../../../src/TestExplorer/TestParsers/XCTestOutputParser";
2121
import { TestRunState, TestStatus } from "./MockTestRunState";
2222

23-
suite("XCTestOutputParser Suite", () => {
24-
const outputParser = new XCTestOutputParser();
25-
23+
suite.only("XCTestOutputParser Suite", () => {
2624
suite("Darwin", () => {
25+
const outputParser = new XCTestOutputParser(darwinTestRegex);
26+
2727
test("Passed Test", async () => {
2828
const testRunState = new TestRunState(["MyTests.MyTests/testPass"], true);
2929
const runState = testRunState.tests[0];
3030
outputParser.parseResult(
3131
`Test Case '-[MyTests.MyTests testPass]' started.
3232
Test Case '-[MyTests.MyTests testPass]' passed (0.001 seconds).
3333
`,
34-
testRunState,
35-
darwinTestRegex
34+
testRunState
3635
);
3736
assert.strictEqual(runState.status, TestStatus.passed);
3837
assert.deepEqual(runState.timing, { duration: 0.001 });
@@ -46,8 +45,7 @@ Test Case '-[MyTests.MyTests testPass]' passed (0.001 seconds).
4645
/Users/user/Developer/MyTests/MyTests.swift:59: error: -[MyTests.MyTests testFail] : XCTAssertEqual failed: ("1") is not equal to ("2")
4746
Test Case '-[MyTests.MyTests testFail]' failed (0.106 seconds).
4847
`,
49-
testRunState,
50-
darwinTestRegex
48+
testRunState
5149
);
5250
assert.strictEqual(runState.status, TestStatus.failed);
5351
assert.deepEqual(runState.issues, [
@@ -69,8 +67,7 @@ Test Case '-[MyTests.MyTests testFail]' failed (0.106 seconds).
6967
/Users/user/Developer/MyTests/MyTests.swift:90: -[MyTests.MyTests testSkip] : Test skipped
7068
Test Case '-[MyTests.MyTests testSkip]' skipped (0.002 seconds).
7169
`,
72-
testRunState,
73-
darwinTestRegex
70+
testRunState
7471
);
7572
assert.strictEqual(runState.status, TestStatus.skipped);
7673
});
@@ -85,8 +82,7 @@ fail
8582
message
8683
Test Case '-[MyTests.MyTests testFail]' failed (0.571 seconds).
8784
`,
88-
testRunState,
89-
darwinTestRegex
85+
testRunState
9086
);
9187
assert.strictEqual(runState.status, TestStatus.failed);
9288
assert.deepEqual(runState.issues, [
@@ -113,8 +109,7 @@ message
113109
/Users/user/Developer/MyTests/MyTests.swift:61: error: -[MyTests.MyTests testFail] : failed - Again
114110
Test Case '-[MyTests.MyTests testFail]' failed (0.571 seconds).
115111
`,
116-
testRunState,
117-
darwinTestRegex
112+
testRunState
118113
);
119114
assert.strictEqual(runState.status, TestStatus.failed);
120115
assert.deepEqual(runState.issues, [
@@ -146,8 +141,7 @@ message`,
146141
/Users/user/Developer/MyTests/MyTests.swift:61: error: -[MyTests.MyTests testFail] : failed - Again
147142
Test Case '-[MyTests.MyTests testFail]' failed (0.571 seconds).
148143
`,
149-
testRunState,
150-
darwinTestRegex
144+
testRunState
151145
);
152146
assert.strictEqual(runState.status, TestStatus.failed);
153147
assert.deepEqual(runState.issues, [
@@ -174,30 +168,29 @@ Test Case '-[MyTests.MyTests testFail]' failed (0.571 seconds).
174168
outputParser.parseResult(
175169
`Test Case '-[MyTests.MyTests testPass]' started.
176170
Test Case '-[MyTests.MyTests`,
177-
testRunState,
178-
darwinTestRegex
171+
testRunState
179172
);
180173
outputParser.parseResult(
181174
` testPass]' passed (0.006 seconds).
182175
`,
183-
testRunState,
184-
darwinTestRegex
176+
testRunState
185177
);
186178
assert.strictEqual(runState.status, TestStatus.passed);
187179
assert.deepEqual(runState.timing, { duration: 0.006 });
188180
});
189181
});
190182

191183
suite("Linux", () => {
184+
const outputParser = new XCTestOutputParser(nonDarwinTestRegex);
185+
192186
test("Passed Test", async () => {
193187
const testRunState = new TestRunState(["MyTests.MyTests/testPass"], false);
194188
const runState = testRunState.tests[0];
195189
outputParser.parseResult(
196190
`Test Case 'MyTests.testPass' started.
197191
Test Case 'MyTests.testPass' passed (0.001 seconds).
198192
`,
199-
testRunState,
200-
nonDarwinTestRegex
193+
testRunState
201194
);
202195
assert.strictEqual(runState.status, TestStatus.passed);
203196
assert.deepEqual(runState.timing, { duration: 0.001 });
@@ -211,8 +204,7 @@ Test Case 'MyTests.testPass' passed (0.001 seconds).
211204
/Users/user/Developer/MyTests/MyTests.swift:59: error: MyTests.testFail : XCTAssertEqual failed: ("1") is not equal to ("2")
212205
Test Case 'MyTests.testFail' failed (0.106 seconds).
213206
`,
214-
testRunState,
215-
nonDarwinTestRegex
207+
testRunState
216208
);
217209
assert.strictEqual(runState.status, TestStatus.failed);
218210
assert.deepEqual(runState.issues, [
@@ -234,8 +226,7 @@ Test Case 'MyTests.testFail' failed (0.106 seconds).
234226
/Users/user/Developer/MyTests/MyTests.swift:90: MyTests.testSkip : Test skipped
235227
Test Case 'MyTests.testSkip' skipped (0.002 seconds).
236228
`,
237-
testRunState,
238-
nonDarwinTestRegex
229+
testRunState
239230
);
240231
assert.strictEqual(runState.status, TestStatus.skipped);
241232
});

0 commit comments

Comments
 (0)