Skip to content

Commit aa0fe65

Browse files
committed
Code coverage for linux
Refactor common debug config creation
1 parent 4fafa93 commit aa0fe65

File tree

7 files changed

+598
-553
lines changed

7 files changed

+598
-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 */
@@ -599,13 +613,13 @@ export class TestRunner {
599613

600614
await TemporaryFolder.withNamedTemporaryFile(fifoPipePath, async () => {
601615
if (this.testArgs.hasSwiftTestingTests) {
602-
const swiftTestBuildConfig =
603-
await LaunchConfigurations.createLaunchConfigurationForSwiftTesting(
604-
this.testArgs.swiftTestArgs,
605-
this.folderContext,
606-
fifoPipePath,
607-
false
608-
);
616+
const swiftTestBuildConfig = DebugConfigurationFactory.swiftTestingConfig(
617+
this.folderContext,
618+
fifoPipePath,
619+
TestKind.standard,
620+
this.testArgs.swiftTestArgs,
621+
true
622+
);
609623

610624
if (swiftTestBuildConfig !== null) {
611625
// given we have already run a build task there is no need to have a pre launch task
@@ -644,14 +658,12 @@ export class TestRunner {
644658

645659
// create launch config for testing
646660
if (this.testArgs.hasXCTests) {
647-
const xcTestBuildConfig =
648-
await LaunchConfigurations.createLaunchConfigurationForXCTestTesting(
649-
this.testArgs.xcTestArgs,
650-
this.workspaceContext,
651-
this.folderContext,
652-
true,
653-
false
654-
);
661+
const xcTestBuildConfig = DebugConfigurationFactory.xcTestConfig(
662+
this.folderContext,
663+
TestKind.standard,
664+
this.testArgs.xcTestArgs,
665+
true
666+
);
655667

656668
if (xcTestBuildConfig !== null) {
657669
// given we have already run a build task there is no need to have a pre launch task
@@ -766,111 +778,6 @@ export class TestRunner {
766778
}
767779
}
768780

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

0 commit comments

Comments
 (0)