@@ -22,11 +22,15 @@ import { execFile, getErrorDescription } from "../utilities/utilities";
22
22
import { createSwiftTask } from "../tasks/SwiftTaskProvider" ;
23
23
import configuration from "../configuration" ;
24
24
import { WorkspaceContext } from "../WorkspaceContext" ;
25
- import { XCTestOutputParser } from "./TestParsers/XCTestOutputParser" ;
25
+ import {
26
+ IXCTestOutputParser ,
27
+ ParallelXCTestOutputParser ,
28
+ XCTestOutputParser ,
29
+ } from "./TestParsers/XCTestOutputParser" ;
26
30
import { SwiftTestingOutputParser } from "./TestParsers/SwiftTestingOutputParser" ;
27
31
import { LoggingDebugAdapterTracker } from "../debugger/logTracker" ;
28
32
import { TaskOperation } from "../tasks/TaskQueue" ;
29
- import { TestXUnitParser , iXUnitTestState } from "./TestXUnitParser" ;
33
+ import { TestXUnitParser } from "./TestXUnitParser" ;
30
34
import { ITestRunState } from "./TestParsers/TestRunState" ;
31
35
import { TestRunArguments } from "./TestRunArguments" ;
32
36
import { TemporaryFolder } from "../utilities/tempFolder" ;
@@ -68,7 +72,10 @@ export class TestRunProxy {
68
72
69
73
// Allows for introspection on the state of TestItems after a test run.
70
74
public runState = {
71
- failed : [ ] as vscode . TestItem [ ] ,
75
+ failed : [ ] as {
76
+ test : vscode . TestItem ;
77
+ message : vscode . TestMessage | readonly vscode . TestMessage [ ] ;
78
+ } [ ] ,
72
79
passed : [ ] as vscode . TestItem [ ] ,
73
80
skipped : [ ] as vscode . TestItem [ ] ,
74
81
errored : [ ] as vscode . TestItem [ ] ,
@@ -179,7 +186,7 @@ export class TestRunProxy {
179
186
message : vscode . TestMessage | readonly vscode . TestMessage [ ] ,
180
187
duration ?: number
181
188
) {
182
- this . runState . failed . push ( test ) ;
189
+ this . runState . failed . push ( { test, message } ) ;
183
190
this . testRun ?. failed ( test , message , duration ) ;
184
191
}
185
192
@@ -218,7 +225,7 @@ export class TestRunProxy {
218
225
export class TestRunner {
219
226
private testRun : TestRunProxy ;
220
227
private testArgs : TestRunArguments ;
221
- private xcTestOutputParser : XCTestOutputParser ;
228
+ private xcTestOutputParser : IXCTestOutputParser ;
222
229
private swiftTestOutputParser : SwiftTestingOutputParser ;
223
230
224
231
/**
@@ -228,13 +235,17 @@ export class TestRunner {
228
235
* @param controller Test controller
229
236
*/
230
237
constructor (
238
+ private testKind : TestKind ,
231
239
private request : vscode . TestRunRequest ,
232
240
private folderContext : FolderContext ,
233
241
private controller : vscode . TestController
234
242
) {
235
243
this . testArgs = new TestRunArguments ( this . ensureRequestIncludesTests ( this . request ) ) ;
236
244
this . testRun = new TestRunProxy ( request , controller , this . testArgs , folderContext ) ;
237
- this . xcTestOutputParser = new XCTestOutputParser ( ) ;
245
+ this . xcTestOutputParser =
246
+ testKind === TestKind . parallel
247
+ ? new ParallelXCTestOutputParser ( )
248
+ : new XCTestOutputParser ( ) ;
238
249
this . swiftTestOutputParser = new SwiftTestingOutputParser (
239
250
this . testRun . testRunStarted ,
240
251
this . testRun . addParameterizedTestCase
@@ -274,9 +285,14 @@ export class TestRunner {
274
285
RunProfileName . run ,
275
286
vscode . TestRunProfileKind . Run ,
276
287
async ( request , token ) => {
277
- const runner = new TestRunner ( request , folderContext , controller ) ;
288
+ const runner = new TestRunner (
289
+ TestKind . standard ,
290
+ request ,
291
+ folderContext ,
292
+ controller
293
+ ) ;
278
294
onCreateTestRun . fire ( runner . testRun ) ;
279
- await runner . runHandler ( false , TestKind . standard , token ) ;
295
+ await runner . runHandler ( token ) ;
280
296
} ,
281
297
true ,
282
298
runnableTag
@@ -286,9 +302,14 @@ export class TestRunner {
286
302
RunProfileName . runParallel ,
287
303
vscode . TestRunProfileKind . Run ,
288
304
async ( request , token ) => {
289
- const runner = new TestRunner ( request , folderContext , controller ) ;
305
+ const runner = new TestRunner (
306
+ TestKind . parallel ,
307
+ request ,
308
+ folderContext ,
309
+ controller
310
+ ) ;
290
311
onCreateTestRun . fire ( runner . testRun ) ;
291
- await runner . runHandler ( false , TestKind . parallel , token ) ;
312
+ await runner . runHandler ( token ) ;
292
313
} ,
293
314
false ,
294
315
runnableTag
@@ -298,14 +319,19 @@ export class TestRunner {
298
319
RunProfileName . coverage ,
299
320
vscode . TestRunProfileKind . Coverage ,
300
321
async ( request , token ) => {
301
- const runner = new TestRunner ( request , folderContext , controller ) ;
322
+ const runner = new TestRunner (
323
+ TestKind . coverage ,
324
+ request ,
325
+ folderContext ,
326
+ controller
327
+ ) ;
302
328
onCreateTestRun . fire ( runner . testRun ) ;
303
329
if ( request . profile ) {
304
330
request . profile . loadDetailedCoverage = async ( testRun , fileCoverage ) => {
305
331
return runner . testRun . coverage . loadDetailedCoverage ( fileCoverage . uri ) ;
306
332
} ;
307
333
}
308
- await runner . runHandler ( false , TestKind . coverage , token ) ;
334
+ await runner . runHandler ( token ) ;
309
335
await runner . testRun . computeCoverage ( ) ;
310
336
} ,
311
337
false ,
@@ -316,9 +342,14 @@ export class TestRunner {
316
342
RunProfileName . debug ,
317
343
vscode . TestRunProfileKind . Debug ,
318
344
async ( request , token ) => {
319
- const runner = new TestRunner ( request , folderContext , controller ) ;
345
+ const runner = new TestRunner (
346
+ TestKind . debug ,
347
+ request ,
348
+ folderContext ,
349
+ controller
350
+ ) ;
320
351
onCreateTestRun . fire ( runner . testRun ) ;
321
- await runner . runHandler ( true , TestKind . debug , token ) ;
352
+ await runner . runHandler ( token ) ;
322
353
await vscode . commands . executeCommand ( "testing.openCoverage" ) ;
323
354
} ,
324
355
false ,
@@ -333,13 +364,13 @@ export class TestRunner {
333
364
* @param token Cancellation token
334
365
* @returns When complete
335
366
*/
336
- async runHandler ( shouldDebug : boolean , testKind : TestKind , token : vscode . CancellationToken ) {
367
+ async runHandler ( token : vscode . CancellationToken ) {
337
368
const runState = new TestRunnerTestRunState ( this . testRun ) ;
338
369
try {
339
- if ( shouldDebug ) {
370
+ if ( this . testKind === TestKind . debug ) {
340
371
await this . debugSession ( token , runState ) ;
341
372
} else {
342
- await this . runSession ( token , testKind , runState ) ;
373
+ await this . runSession ( token , runState ) ;
343
374
}
344
375
} catch ( error ) {
345
376
this . workspaceContext . outputChannel . log ( `Error: ${ getErrorDescription ( error ) } ` ) ;
@@ -350,11 +381,7 @@ export class TestRunner {
350
381
}
351
382
352
383
/** Run test session without attaching to a debugger */
353
- async runSession (
354
- token : vscode . CancellationToken ,
355
- testKind : TestKind ,
356
- runState : TestRunnerTestRunState
357
- ) {
384
+ async runSession ( token : vscode . CancellationToken , runState : TestRunnerTestRunState ) {
358
385
// Run swift-testing first, then XCTest.
359
386
// swift-testing being parallel by default should help these run faster.
360
387
if ( this . testArgs . hasSwiftTestingTests ) {
@@ -373,7 +400,7 @@ export class TestRunner {
373
400
const testBuildConfig = TestingDebugConfigurationFactory . swiftTestingConfig (
374
401
this . folderContext ,
375
402
fifoPipePath ,
376
- testKind ,
403
+ this . testKind ,
377
404
this . testArgs . swiftTestArgs ,
378
405
true
379
406
) ;
@@ -401,7 +428,8 @@ export class TestRunner {
401
428
await this . swiftTestOutputParser . watch ( fifoPipePath , runState ) ;
402
429
403
430
await this . launchTests (
404
- testKind === TestKind . parallel ? TestKind . standard : testKind ,
431
+ runState ,
432
+ this . testKind === TestKind . parallel ? TestKind . standard : this . testKind ,
405
433
token ,
406
434
outputStream ,
407
435
testBuildConfig ,
@@ -413,7 +441,7 @@ export class TestRunner {
413
441
if ( this . testArgs . hasXCTests ) {
414
442
const testBuildConfig = TestingDebugConfigurationFactory . xcTestConfig (
415
443
this . folderContext ,
416
- testKind ,
444
+ this . testKind ,
417
445
this . testArgs . xcTestArgs ,
418
446
true
419
447
) ;
@@ -425,13 +453,7 @@ export class TestRunner {
425
453
write : ( chunk , encoding , next ) => {
426
454
const text = chunk . toString ( ) ;
427
455
this . testRun . appendOutput ( text . replace ( / \n / g, "\r\n" ) ) ;
428
-
429
- // If a test fails in a parallel run the XCTest output is printed.
430
- // Since we get all results from the xunit xml we don't parse here
431
- // to prevent parsing twice.
432
- if ( testKind !== TestKind . parallel ) {
433
- this . xcTestOutputParser . parseResult ( text , runState ) ;
434
- }
456
+ this . xcTestOutputParser . parseResult ( text , runState ) ;
435
457
next ( ) ;
436
458
} ,
437
459
} ) ;
@@ -445,7 +467,8 @@ export class TestRunner {
445
467
this . testRun . testRunStarted ( ) ;
446
468
447
469
await this . launchTests (
448
- testKind ,
470
+ runState ,
471
+ this . testKind ,
449
472
token ,
450
473
parsedOutputStream ,
451
474
testBuildConfig ,
@@ -455,6 +478,7 @@ export class TestRunner {
455
478
}
456
479
457
480
private async launchTests (
481
+ runState : TestRunnerTestRunState ,
458
482
testKind : TestKind ,
459
483
token : vscode . CancellationToken ,
460
484
outputStream : stream . Writable ,
@@ -472,7 +496,7 @@ export class TestRunner {
472
496
) ;
473
497
break ;
474
498
case TestKind . parallel :
475
- await this . runParallelSession ( token , outputStream , testBuildConfig ) ;
499
+ await this . runParallelSession ( token , outputStream , testBuildConfig , runState ) ;
476
500
break ;
477
501
default :
478
502
await this . runStandardSession ( token , outputStream , testBuildConfig , testKind ) ;
@@ -581,7 +605,8 @@ export class TestRunner {
581
605
async runParallelSession (
582
606
token : vscode . CancellationToken ,
583
607
outputStream : stream . Writable ,
584
- testBuildConfig : vscode . DebugConfiguration
608
+ testBuildConfig : vscode . DebugConfiguration ,
609
+ runState : TestRunnerTestRunState
585
610
) {
586
611
await this . workspaceContext . tempFolder . withTemporaryFile ( "xml" , async filename => {
587
612
const args = [ ...( testBuildConfig . args ?? [ ] ) , "--xunit-output" , filename ] ;
@@ -602,12 +627,12 @@ export class TestRunner {
602
627
throw error ;
603
628
}
604
629
}
630
+
605
631
const buffer = await asyncfs . readFile ( filename , "utf8" ) ;
606
- const xUnitParser = new TestXUnitParser ( ) ;
607
- const results = await xUnitParser . parse (
608
- buffer ,
609
- new TestRunnerXUnitTestState ( this . testItemFinder , this . testRun )
632
+ const xUnitParser = new TestXUnitParser (
633
+ this . folderContext . workspaceContext . toolchain . swiftVersion
610
634
) ;
635
+ const results = await xUnitParser . parse ( buffer , runState ) ;
611
636
if ( results ) {
612
637
this . testRun . appendOutput (
613
638
`\r\nExecuted ${ results . tests } tests, with ${ results . failures } failures and ${ results . errors } errors.\r\n`
@@ -863,7 +888,7 @@ class NonDarwinTestItemFinder implements TestItemFinder {
863
888
/**
864
889
* Store state of current test run output parse
865
890
*/
866
- class TestRunnerTestRunState implements ITestRunState {
891
+ export class TestRunnerTestRunState implements ITestRunState {
867
892
constructor ( private testRun : TestRunProxy ) { }
868
893
869
894
public currentTestItem ?: vscode . TestItem ;
@@ -953,30 +978,3 @@ class TestRunnerTestRunState implements ITestRunState {
953
978
// Nothing to do here
954
979
}
955
980
}
956
-
957
- class TestRunnerXUnitTestState implements iXUnitTestState {
958
- constructor (
959
- private testItemFinder : TestItemFinder ,
960
- private testRun : TestRunProxy
961
- ) { }
962
-
963
- passTest ( id : string , duration : number ) : void {
964
- const index = this . testItemFinder . getIndex ( id ) ;
965
- if ( index !== - 1 ) {
966
- this . testRun . passed ( this . testItemFinder . testItems [ index ] , duration ) ;
967
- }
968
- }
969
- failTest ( id : string , duration : number , message ?: string ) : void {
970
- const index = this . testItemFinder . getIndex ( id ) ;
971
- if ( index !== - 1 ) {
972
- const testMessage = new vscode . TestMessage ( message ?? "Failed" ) ;
973
- this . testRun . failed ( this . testItemFinder . testItems [ index ] , testMessage , duration ) ;
974
- }
975
- }
976
- skipTest ( id : string ) : void {
977
- const index = this . testItemFinder . getIndex ( id ) ;
978
- if ( index !== - 1 ) {
979
- this . testRun . skipped ( this . testItemFinder . testItems [ index ] ) ;
980
- }
981
- }
982
- }
0 commit comments