Skip to content

Commit 6c0aa09

Browse files
committed
Code coverage for linux
Refactor common debug config creation
1 parent b1191ad commit 6c0aa09

File tree

7 files changed

+596
-553
lines changed

7 files changed

+596
-553
lines changed

src/FolderContext.ts

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@ import { TestExplorer } from "./TestExplorer/TestExplorer";
2121
import { WorkspaceContext, FolderEvent } from "./WorkspaceContext";
2222
import { BackgroundCompilation } from "./BackgroundCompilation";
2323
import { TaskQueue } from "./tasks/TaskQueue";
24-
import { LcovResults } from "./coverage/LcovResults";
2524
import { isPathInsidePath } from "./utilities/utilities";
2625

2726
export class FolderContext implements vscode.Disposable {
@@ -30,7 +29,6 @@ export class FolderContext implements vscode.Disposable {
3029
public hasResolveErrors = false;
3130
public testExplorer?: TestExplorer;
3231
public taskQueue: TaskQueue;
33-
public lcovResults: LcovResults;
3432

3533
/**
3634
* FolderContext constructor
@@ -49,15 +47,13 @@ export class FolderContext implements vscode.Disposable {
4947
this.packageWatcher.install();
5048
this.backgroundCompilation = new BackgroundCompilation(this);
5149
this.taskQueue = new TaskQueue(this);
52-
this.lcovResults = new LcovResults(this);
5350
}
5451

5552
/** dispose of any thing FolderContext holds */
5653
dispose() {
5754
this.linuxMain?.dispose();
5855
this.packageWatcher.dispose();
5956
this.testExplorer?.dispose();
60-
this.lcovResults.dispose();
6157
}
6258

6359
/**

src/TestExplorer/TestRunner.ts

Lines changed: 54 additions & 147 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,9 @@ import * as path from "path";
1717
import * as stream from "stream";
1818
import * as os from "os";
1919
import * as asyncfs from "fs/promises";
20-
import {
21-
createXCTestConfiguration,
22-
createSwiftTestConfiguration,
23-
createDarwinTestConfiguration,
24-
} from "../debugger/launch";
2520
import { FolderContext } from "../FolderContext";
21+
import { execFile, getErrorDescription } from "../utilities/utilities";
2622
import { getBuildAllTask } from "../tasks/SwiftTaskProvider";
27-
import { execFile, getErrorDescription, regexEscapedString } from "../utilities/utilities";
2823
import configuration from "../configuration";
2924
import { WorkspaceContext } from "../WorkspaceContext";
3025
import { XCTestOutputParser } from "./TestParsers/XCTestOutputParser";
@@ -37,8 +32,9 @@ import { ITestRunState } from "./TestParsers/TestRunState";
3732
import { TestRunArguments } from "./TestRunArguments";
3833
import { TemporaryFolder } from "../utilities/tempFolder";
3934
import { TestClass, runnableTag, upsertTestItem } from "./TestDiscovery";
40-
import { SwiftProcess } from "../tasks/SwiftProcess";
41-
import { TestCoverage } from "../coverage/TestCoverage";
35+
import { TestCoverage } from "../coverage/LcovResults";
36+
import { DebugConfigurationFactory } from "../debugger/buildConfig";
37+
import { SwiftPtyProcess } from "../tasks/SwiftProcess";
4238

4339
/** Workspace Folder events */
4440
export enum TestKind {
@@ -50,6 +46,11 @@ export enum TestKind {
5046
coverage = "coverage",
5147
}
5248

49+
export enum TestLibrary {
50+
xctest = "XCTest",
51+
swiftTesting = "swift-testing",
52+
}
53+
5354
class TestRunProxy {
5455
private testRun?: vscode.TestRun;
5556
private addedTestItems: { testClass: TestClass; parentIndex: number }[] = [];
@@ -363,13 +364,13 @@ export class TestRunner {
363364
await execFile("mkfifo", [fifoPipePath], undefined, this.folderContext);
364365
}
365366

366-
const testBuildConfig =
367-
await LaunchConfigurations.createLaunchConfigurationForSwiftTesting(
368-
this.testArgs.swiftTestArgs,
369-
this.folderContext,
370-
fifoPipePath,
371-
testKind === TestKind.coverage
372-
);
367+
const testBuildConfig = DebugConfigurationFactory.swiftTestingConfig(
368+
this.folderContext,
369+
fifoPipePath,
370+
testKind,
371+
this.testArgs.swiftTestArgs,
372+
true
373+
);
373374

374375
if (testBuildConfig === null) {
375376
return;
@@ -397,18 +398,18 @@ export class TestRunner {
397398
testKind === TestKind.parallel ? TestKind.standard : testKind,
398399
token,
399400
outputStream,
400-
testBuildConfig
401+
testBuildConfig,
402+
TestLibrary.swiftTesting
401403
);
402404
});
403405
}
404406

405407
if (this.testArgs.hasXCTests) {
406-
const testBuildConfig = LaunchConfigurations.createLaunchConfigurationForXCTestTesting(
407-
this.testArgs.xcTestArgs,
408-
this.workspaceContext,
408+
const testBuildConfig = DebugConfigurationFactory.xcTestConfig(
409409
this.folderContext,
410-
false,
411-
testKind === TestKind.coverage
410+
testKind,
411+
this.testArgs.xcTestArgs,
412+
true
412413
);
413414
if (testBuildConfig === null) {
414415
return;
@@ -431,21 +432,33 @@ export class TestRunner {
431432
// XCTestRuns are started immediately
432433
this.testRun.testRunStarted();
433434

434-
await this.launchTests(testKind, token, parsedOutputStream, testBuildConfig);
435+
await this.launchTests(
436+
testKind,
437+
token,
438+
parsedOutputStream,
439+
testBuildConfig,
440+
TestLibrary.xctest
441+
);
435442
}
436443
}
437444

438445
private async launchTests(
439446
testKind: TestKind,
440447
token: vscode.CancellationToken,
441448
outputStream: stream.Writable,
442-
testBuildConfig: vscode.DebugConfiguration
449+
testBuildConfig: vscode.DebugConfiguration,
450+
testLibrary: TestLibrary
443451
) {
444452
this.testRun.appendOutput(`> Test run started at ${new Date().toLocaleString()} <\r\n\r\n`);
445453
try {
446454
switch (testKind) {
447455
case TestKind.coverage:
448-
await this.runCoverageSession(token, outputStream, testBuildConfig);
456+
await this.runCoverageSession(
457+
token,
458+
outputStream,
459+
testBuildConfig,
460+
testLibrary
461+
);
449462
break;
450463
case TestKind.parallel:
451464
await this.runParallelSession(token, outputStream, testBuildConfig);
@@ -475,7 +488,7 @@ export class TestRunner {
475488
let didError = false;
476489
let cancellation: vscode.Disposable;
477490

478-
const exec = new SwiftProcess(testBuildConfig.program, args, {
491+
const exec = new SwiftPtyProcess(testBuildConfig.program, args, {
479492
cwd: testBuildConfig.cwd,
480493
env: { ...process.env, ...testBuildConfig.env },
481494
});
@@ -527,7 +540,8 @@ export class TestRunner {
527540
async runCoverageSession(
528541
token: vscode.CancellationToken,
529542
outputStream: stream.Writable,
530-
testBuildConfig: vscode.DebugConfiguration
543+
testBuildConfig: vscode.DebugConfiguration,
544+
testLibrary: TestLibrary
531545
) {
532546
try {
533547
await this.runStandardSession(token, outputStream, testBuildConfig);
@@ -538,7 +552,7 @@ export class TestRunner {
538552
}
539553
}
540554

541-
await this.testRun.coverage.captureCoverage();
555+
await this.testRun.coverage.captureCoverage(testLibrary);
542556
}
543557

544558
/** Run tests in parallel outside of debugger */
@@ -605,13 +619,13 @@ export class TestRunner {
605619
}
606620

607621
if (this.testArgs.hasSwiftTestingTests) {
608-
const swiftTestBuildConfig =
609-
await LaunchConfigurations.createLaunchConfigurationForSwiftTesting(
610-
this.testArgs.swiftTestArgs,
611-
this.folderContext,
612-
fifoPipePath,
613-
false
614-
);
622+
const swiftTestBuildConfig = DebugConfigurationFactory.swiftTestingConfig(
623+
this.folderContext,
624+
fifoPipePath,
625+
TestKind.standard,
626+
this.testArgs.swiftTestArgs,
627+
true
628+
);
615629

616630
if (swiftTestBuildConfig !== null) {
617631
// given we have already run a build task there is no need to have a pre launch task
@@ -650,14 +664,12 @@ export class TestRunner {
650664

651665
// create launch config for testing
652666
if (this.testArgs.hasXCTests) {
653-
const xcTestBuildConfig =
654-
await LaunchConfigurations.createLaunchConfigurationForXCTestTesting(
655-
this.testArgs.xcTestArgs,
656-
this.workspaceContext,
657-
this.folderContext,
658-
true,
659-
false
660-
);
667+
const xcTestBuildConfig = DebugConfigurationFactory.xcTestConfig(
668+
this.folderContext,
669+
TestKind.standard,
670+
this.testArgs.xcTestArgs,
671+
true
672+
);
661673

662674
if (xcTestBuildConfig !== null) {
663675
// given we have already run a build task there is no need to have a pre launch task
@@ -772,111 +784,6 @@ export class TestRunner {
772784
}
773785
}
774786

775-
class LaunchConfigurations {
776-
/**
777-
* Edit launch configuration to run tests
778-
* @param debugging Do we need this configuration for debugging
779-
* @param outputFile Debug output file
780-
* @returns
781-
*/
782-
static createLaunchConfigurationForXCTestTesting(
783-
args: string[],
784-
workspaceContext: WorkspaceContext,
785-
folderContext: FolderContext,
786-
debugging: boolean,
787-
coverage: boolean
788-
): vscode.DebugConfiguration | null {
789-
const testList = args.join(",");
790-
791-
if (process.platform === "darwin") {
792-
// if debugging on macOS with Swift 5.6 we need to create a custom launch
793-
// configuration so we can set the system architecture
794-
const swiftVersion = workspaceContext.toolchain.swiftVersion;
795-
if (
796-
debugging &&
797-
swiftVersion.isLessThan(new Version(5, 7, 0)) &&
798-
swiftVersion.isGreaterThanOrEqual(new Version(5, 6, 0))
799-
) {
800-
let testFilterArg: string;
801-
if (testList.length > 0) {
802-
testFilterArg = `-XCTest ${testList}`;
803-
} else {
804-
testFilterArg = "";
805-
}
806-
const testBuildConfig = createDarwinTestConfiguration(folderContext, testFilterArg);
807-
if (testBuildConfig === null) {
808-
return null;
809-
}
810-
return testBuildConfig;
811-
} else {
812-
const testBuildConfig = createXCTestConfiguration(folderContext, true);
813-
if (testBuildConfig === null) {
814-
return null;
815-
}
816-
817-
let additionalArgs: string[] = [];
818-
if (testList.length > 0) {
819-
additionalArgs = args.flatMap(arg => ["--filter", regexEscapedString(arg)]);
820-
}
821-
822-
if (coverage) {
823-
additionalArgs = [...additionalArgs, "--enable-code-coverage"];
824-
}
825-
826-
testBuildConfig.args = [...testBuildConfig.args, ...additionalArgs];
827-
testBuildConfig.terminal = "console";
828-
829-
return testBuildConfig;
830-
}
831-
} else {
832-
const testBuildConfig = createXCTestConfiguration(folderContext, true);
833-
if (testBuildConfig === null) {
834-
return null;
835-
}
836-
837-
let testFilterArg: string[] = [];
838-
if (testList.length > 0) {
839-
testFilterArg = args.flatMap(arg => ["--filter", regexEscapedString(arg)]);
840-
}
841-
if (coverage) {
842-
testFilterArg = [...testFilterArg, "--enable-code-coverage"];
843-
}
844-
testBuildConfig.args = [...testBuildConfig.args, ...testFilterArg];
845-
846-
// output test logging to debug console so we can catch it with a tracker
847-
testBuildConfig.terminal = "console";
848-
return testBuildConfig;
849-
}
850-
}
851-
852-
static async createLaunchConfigurationForSwiftTesting(
853-
args: string[],
854-
folderContext: FolderContext,
855-
fifoPipePath: string,
856-
coverage: boolean
857-
): Promise<vscode.DebugConfiguration | null> {
858-
const testList = args.join(",");
859-
860-
const testBuildConfig = createSwiftTestConfiguration(folderContext, fifoPipePath, true);
861-
if (testBuildConfig === null) {
862-
return null;
863-
}
864-
865-
let additionalArgs: string[] = [];
866-
if (testList.length > 0) {
867-
additionalArgs = args.flatMap(arg => ["--filter", regexEscapedString(arg)]);
868-
}
869-
870-
if (coverage) {
871-
additionalArgs = [...additionalArgs, "--enable-code-coverage"];
872-
}
873-
874-
testBuildConfig.args = [...testBuildConfig.args, ...additionalArgs];
875-
testBuildConfig.terminal = "console";
876-
return testBuildConfig;
877-
}
878-
}
879-
880787
/** Interface defining how to find test items given a test id from XCTest output */
881788
interface TestItemFinder {
882789
getIndex(id: string, filename?: string): number;

0 commit comments

Comments
 (0)