diff --git a/README.md b/README.md index 5fb139e..3d23db7 100644 --- a/README.md +++ b/README.md @@ -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 @@ -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) diff --git a/src/testDiscovery.ts b/src/testDiscovery.ts index 7796726..eef973a 100644 --- a/src/testDiscovery.ts +++ b/src/testDiscovery.ts @@ -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); diff --git a/test/testDiscovery.test.ts b/test/testDiscovery.test.ts index 1f90a69..59f48be 100644 --- a/test/testDiscovery.test.ts +++ b/test/testDiscovery.test.ts @@ -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"; @@ -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"]; @@ -215,18 +233,33 @@ 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() { @@ -234,7 +267,7 @@ function getDotnetTestOutputWithoutTestAssemblyPath() { 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: @@ -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: