Skip to content

Commit

Permalink
Support localized strings when parsing test output (#333)
Browse files Browse the repository at this point in the history
Support localized strings when parsing test output
  • Loading branch information
chausner authored Sep 9, 2021
1 parent ae7db63 commit ef691f3
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 12 deletions.
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
## Prerequisites

* [.NET Core](https://www.microsoft.com/net/core) is installed
* NUnit and MSTest requires a dotnet [sdk](https://www.microsoft.com/net/download) version of >= 2.2.104 and running dotnet tooling in English (see [#77](https://github.com/formulahendry/vscode-dotnet-test-explorer/issues/77) for details).
* NUnit and MSTest requires a dotnet [sdk](https://www.microsoft.com/net/download) version of >= 2.2.104.

## New in 0.7.6

Expand Down Expand Up @@ -83,8 +83,8 @@ This is because of limitations in the omnisharp extensions. We can only navigate
##### Test result is not shown in CodeLens / tree
Try and change the setting dotnet-test-explorer.pathForResultFile to point to a folder you have access right too. CodeLens functionality also requires the [C# extension](https://marketplace.visualstudio.com/items?itemName=ms-vscode.csharp))

##### No tree view or color coded explorer for NUnit / MSTest
This requires you to run dotnet SDK version 2.2.104 or higher. The extension tries to run the commands with the English cli but if things are not working as expected anyway it may be due to the cli language (see [#77](https://github.com/formulahendry/vscode-dotnet-test-explorer/issues/77) for details).
##### No tree view or color-coded explorer for NUnit / MSTest
This requires you to run dotnet SDK version 2.2.104 or higher.

##### xUnit projects assembly name needs to match the test class namespace
See [#201](https://github.com/formulahendry/vscode-dotnet-test-explorer/issues/201)
Expand Down
31 changes: 29 additions & 2 deletions src/testDiscovery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -78,14 +78,41 @@ function extractTestNames(testCommandStdout: string): string[] {
}

function extractAssemblyPaths(testCommandStdout: string): string[] {
const testRunLineRegex = /^Test run for (.+\.dll)/gm;
/*
* The string we need to parse is localized
* (see https://github.com/microsoft/vstest/blob/018b6e4cc6e0ea7c8761c2a2f89c3e5032db74aa/src/Microsoft.TestPlatform.Build/Resources/xlf/Resources.xlf#L15-L18).
**/
const testRunLineStrings = [
"Testovací běh pro {0} ({1})", // cs
"Testlauf für \"{0}\" ({1})", // de
"Test run for {0} ({1})", // en
"Serie de pruebas para {0} ({1})", // es
"Série de tests pour {0} ({1})", // fr
"Esecuzione dei test per {0} ({1})", // it
"{0} ({1}) のテスト実行", // ja
"{0}({1})에 대한 테스트 실행", // ko
"Przebieg testu dla: {0} ({1})", // pl
"Execução de teste para {0} ({1})", // pt-BR
"Тестовый запуск для {0} ({1})", // ru
"{0} ({1}) için test çalıştırması", // tr
"{0} ({1})的测试运行", // zh-Hans
"{0} 的測試回合 ({1})" // zh-Hant
];
// construct regex that matches any of the above localized strings
const r = "^(?:" + testRunLineStrings
.map((s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')) // escape characters
.map((s) => s.replace("\\{0\\}", "(.+\\.dll)").replace("\\{1\\}", ".+"))
.join("|")
+ ")$";
const testRunLineRegex = new RegExp(r, "gm")
const results = [];
let match = null;

do {
match = testRunLineRegex.exec(testCommandStdout);
if (match) {
results.push(match[1]);
const assemblyPath = match.find((capture, i) => capture && i != 0); // first capture group is the whole match
results.push(assemblyPath);
}
}
while (match);
Expand Down
47 changes: 40 additions & 7 deletions test/testDiscovery.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,16 @@ suite("Test discovery", () => {
.then((result) => assert.deepEqual(result.testNames, testNames));
});

test("Fully qualified test names returned when dotnet test outputs FQ test names and CLI language is French", () => {
const testNames = ["Ns1.Class1.Test1", "Ns1.Class1.Test2"];

execStub.withArgs(dotnetTestExecCmd, sinon.match.func, testDirectoryPath)
.callsArgWith(1, null, buildDotnetTestOutput(testNames, assemblyFilePath, "fr"), "");

return discoverTests(testDirectoryPath, dotnetTestOptions)
.then((result) => assert.deepEqual(result.testNames, testNames));
});

test("Promise rejected when dotnet test failing", () => {
const error = "error";

Expand All @@ -78,6 +88,14 @@ suite("Test discovery", () => {
.then((result) => assert.deepEqual(result.testNames, []));
});

test("Empty list returned when dotnet test outputs empty list and CLI language is French", () => {
execStub.withArgs(dotnetTestExecCmd, sinon.match.func, testDirectoryPath)
.callsArgWithAsync(1, null, buildDotnetTestOutput([], assemblyFilePath, "fr"), "");

return discoverTests(testDirectoryPath, dotnetTestOptions)
.then((result) => assert.deepEqual(result.testNames, []));
});

test("Fully qualified test names returned using dotnet vstest when dotnet test output is missing fq names", () => {
const testNames = ["Test1", "Test2"];
const fqTestNames = ["Ns1.Class1.Test1", "Ns1.Class1.Test2"];
Expand Down Expand Up @@ -215,26 +233,41 @@ suite("Test discovery", () => {
});
});

function buildDotnetTestOutput(testNames: string[], testAssemblyFilePath: string) {
function buildDotnetTestOutput(testNames: string[], testAssemblyFilePath: string, language: string = "en") {
const testsLists = testNames.map((n) => ` ${n}`).join("\r\n");
return String.raw`
if (language === "en") {
return String.raw`
Build started, please wait...
Build completed.
Test run for ${testAssemblyFilePath}(.NETCoreApp,Version=v2.0)
Microsoft (R) Test Execution Command Line Tool Version 15.6.0-preview-20180109-01
Test run for ${testAssemblyFilePath} (.NETCoreApp,Version=v5.0)
Microsoft (R) Test Execution Command Line Tool Version 16.11.0
Copyright (c) Microsoft Corporation. All rights reserved.
The following Tests are available:
` + testsLists;
} else if (language === "fr") {
return String.raw`
La build a démarré. Patientez…
Fin de la build.
Série de tests pour ${testAssemblyFilePath} (.NETCoreApp,Version=v5.0)
Outil en ligne de commande d'exécution de tests Microsoft (R), version 16.11.0
Copyright (c) Microsoft Corporation. Tous droits réservés.
Les tests suivants sont disponibles :
` + testsLists;
} else {
throw new Error("Unexpected language: " + language);
}
}

function getDotnetTestOutputWithoutTestAssemblyPath() {
return String.raw`
Build started, please wait...
Build completed.
Microsoft (R) Test Execution Command Line Tool Version 15.6.0-preview-20180109-01
Microsoft (R) Test Execution Command Line Tool Version 16.11.0
Copyright (c) Microsoft Corporation. All rights reserved.
The following Tests are available:
Expand All @@ -251,8 +284,8 @@ function buildDotnetTestSolutionOutput(testNames: string[], testAssemblyFilePath
output += String.raw`
Build completed.
Test run for ${testAssemblyFilePath}(.NETCoreApp,Version=v2.0)
Microsoft (R) Test Execution Command Line Tool Version 15.6.0-preview-20180109-01
Test run for ${testAssemblyFilePath} (.NETCoreApp,Version=v5.0)
Microsoft (R) Test Execution Command Line Tool Version 16.11.0
Copyright (c) Microsoft Corporation. All rights reserved.
The following Tests are available:
Expand Down

0 comments on commit ef691f3

Please sign in to comment.