From b785ab0735933c89405aebbecfb44c67ae9a48f0 Mon Sep 17 00:00:00 2001 From: Alex Meseldzija Date: Thu, 28 Nov 2024 18:06:34 +0100 Subject: [PATCH] NET-767 Add test importer for MSTest format Co-authored-by: Costin Zaharia <56015273+costin-zaharia-sonarsource@users.noreply.github.com> --- .../dotnet/tests/UnitTestResultParser.java | 25 +++ .../plugins/dotnet/tests/UnitTestResults.java | 23 ++- .../tests/VisualStudioTestResultParser.java | 169 ++++++++++++++++++ .../dotnet/tests/VisualStudioTestResults.java | 52 ++++++ .../VisualStudioTestResultParserTest.java | 141 +++++++++++++++ .../invalid_character.trx | 19 ++ .../invalid_dates.trx | 22 +++ .../invalid_test_outcome.trx | 22 +++ .../visualstudio_test_results/readme.md | 107 +++++++++++ .../test_name_not_mapped.trx | 22 +++ .../test_result_no_test_method.trx | 18 ++ .../visualstudio_test_results/valid.trx | 133 ++++++++++++++ 12 files changed, 748 insertions(+), 5 deletions(-) create mode 100644 sonar-dotnet-core/src/main/java/org/sonar/plugins/dotnet/tests/UnitTestResultParser.java create mode 100644 sonar-dotnet-core/src/main/java/org/sonar/plugins/dotnet/tests/VisualStudioTestResultParser.java create mode 100644 sonar-dotnet-core/src/main/java/org/sonar/plugins/dotnet/tests/VisualStudioTestResults.java create mode 100644 sonar-dotnet-core/src/test/java/org/sonar/plugins/dotnet/tests/VisualStudioTestResultParserTest.java create mode 100644 sonar-dotnet-core/src/test/resources/visualstudio_test_results/invalid_character.trx create mode 100644 sonar-dotnet-core/src/test/resources/visualstudio_test_results/invalid_dates.trx create mode 100644 sonar-dotnet-core/src/test/resources/visualstudio_test_results/invalid_test_outcome.trx create mode 100644 sonar-dotnet-core/src/test/resources/visualstudio_test_results/readme.md create mode 100644 sonar-dotnet-core/src/test/resources/visualstudio_test_results/test_name_not_mapped.trx create mode 100644 sonar-dotnet-core/src/test/resources/visualstudio_test_results/test_result_no_test_method.trx create mode 100644 sonar-dotnet-core/src/test/resources/visualstudio_test_results/valid.trx diff --git a/sonar-dotnet-core/src/main/java/org/sonar/plugins/dotnet/tests/UnitTestResultParser.java b/sonar-dotnet-core/src/main/java/org/sonar/plugins/dotnet/tests/UnitTestResultParser.java new file mode 100644 index 00000000000..0eff10a3464 --- /dev/null +++ b/sonar-dotnet-core/src/main/java/org/sonar/plugins/dotnet/tests/UnitTestResultParser.java @@ -0,0 +1,25 @@ +/* + * SonarSource :: .NET :: Core + * Copyright (C) 2014-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Sonar Source-Available License Version 1, as published by SonarSource SA. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the Sonar Source-Available License for more details. + * + * You should have received a copy of the Sonar Source-Available License + * along with this program; if not, see https://sonarsource.com/license/ssal/ + */ +package org.sonar.plugins.dotnet.tests; + +import java.io.File; +import java.util.Map; +import java.util.function.BiConsumer; + +@FunctionalInterface +interface UnitTestResultParser extends BiConsumer> { +} diff --git a/sonar-dotnet-core/src/main/java/org/sonar/plugins/dotnet/tests/UnitTestResults.java b/sonar-dotnet-core/src/main/java/org/sonar/plugins/dotnet/tests/UnitTestResults.java index 9245f4b97dc..0e9e68171a8 100644 --- a/sonar-dotnet-core/src/main/java/org/sonar/plugins/dotnet/tests/UnitTestResults.java +++ b/sonar-dotnet-core/src/main/java/org/sonar/plugins/dotnet/tests/UnitTestResults.java @@ -21,11 +21,11 @@ public class UnitTestResults { - private int tests; - private int skipped; - private int failures; - private int errors; - private Long executionTime; + protected int tests; + protected int skipped; + protected int failures; + protected int errors; + protected Long executionTime; public void add(int tests, int skipped, int failures, int errors, @Nullable Long executionTime) { this.tests += tests; @@ -41,6 +41,19 @@ public void add(int tests, int skipped, int failures, int errors, @Nullable Long } } + public void add(UnitTestResults unitTestResults) { + this.tests += unitTestResults.tests(); + this.skipped += unitTestResults.skipped(); + this.failures += unitTestResults.failures(); + this.errors += unitTestResults.errors(); + if (unitTestResults.executionTime() != null) { + if (this.executionTime == null) { + this.executionTime = 0L; + } + this.executionTime += unitTestResults.executionTime(); + } + } + public int tests() { return tests; } diff --git a/sonar-dotnet-core/src/main/java/org/sonar/plugins/dotnet/tests/VisualStudioTestResultParser.java b/sonar-dotnet-core/src/main/java/org/sonar/plugins/dotnet/tests/VisualStudioTestResultParser.java new file mode 100644 index 00000000000..6ab23d00efd --- /dev/null +++ b/sonar-dotnet-core/src/main/java/org/sonar/plugins/dotnet/tests/VisualStudioTestResultParser.java @@ -0,0 +1,169 @@ +/* + * SonarSource :: .NET :: Core + * Copyright (C) 2014-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Sonar Source-Available License Version 1, as published by SonarSource SA. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the Sonar Source-Available License for more details. + * + * You should have received a copy of the Sonar Source-Available License + * along with this program; if not, see https://sonarsource.com/license/ssal/ + */ +package org.sonar.plugins.dotnet.tests; + +import java.io.File; +import java.io.IOException; +import java.text.DateFormat; +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class VisualStudioTestResultParser implements UnitTestResultParser { + + private static final Logger LOG = LoggerFactory.getLogger(VisualStudioTestResultParser.class); + private final Map methodFileMap; + + VisualStudioTestResultParser(Map methodFileMap) { + this.methodFileMap = methodFileMap; + } + + @Override + public void accept(File file, Map unitTestResults) { + LOG.info("Parsing the Visual Studio Test Results file '{}'.", file.getAbsolutePath()); + new Parser(file, unitTestResults, this.methodFileMap).parse(); + } + + private static class Parser { + private final File file; + private final Map testIdTestResultMap; + private final Map unitTestResults; + // Date Format: // https://github.com/microsoft/vstest/blob/7d34b30433259fb914aaaf276fde663a47b6ef2f/src/Microsoft.TestPlatform.Extensions.TrxLogger/XML/XmlPersistence.cs#L557-L572 + private final DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX"); + private final Pattern millisecondsPattern = Pattern.compile("(\\.(\\d{0,3}))\\d*+"); + private final Map methodFileMap; + + Parser(File file, Map unitTestResults, Map methodFileMap) { + this.file = file; + this.unitTestResults = unitTestResults; + this.testIdTestResultMap = new HashMap<>(); + this.methodFileMap = methodFileMap; + } + + public void parse() { + try (XmlParserHelper xmlParserHelper = new XmlParserHelper(file)) { + checkRootTag(xmlParserHelper); + dispatchTags(xmlParserHelper); + } catch (IOException e) { + throw new IllegalStateException("Unable to close report", e); + } + } + + private void dispatchTags(XmlParserHelper xmlParserHelper) { + String tagName; + while ((tagName = xmlParserHelper.nextStartTag()) != null) { + if ("UnitTestResult".equals(tagName)) { + handleUnitTestResultTag(xmlParserHelper); + } else if ("UnitTest".equals(tagName)) { + handleUnitTestTag(xmlParserHelper); + } + } + } + + private void handleUnitTestResultTag(XmlParserHelper xmlParserHelper) { + String testId = xmlParserHelper.getRequiredAttribute("testId"); + String outcome = xmlParserHelper.getRequiredAttribute("outcome"); + Date start = getRequiredDateAttribute(xmlParserHelper, "startTime"); + Date finish = getRequiredDateAttribute(xmlParserHelper, "endTime"); + long duration = finish.getTime() - start.getTime(); + + var testResult = new VisualStudioTestResults(outcome, duration); + testIdTestResultMap.put(testId, testResult); + LOG.debug("Parsed Visual Studio Unit Test - testId: {} outcome: {}, startTime: {}, endTime: {}", + testId, outcome, start, finish); + } + + private void handleUnitTestTag(XmlParserHelper xmlParserHelper) { + String testId = xmlParserHelper.getRequiredAttribute("id"); + + String tagName; + while ((tagName = xmlParserHelper.nextStartTag()) != null) { + if ("TestMethod".equals(tagName)) { + break; + } + } + if (tagName == null){ + throw new ParseErrorException("No TestMethod attribute found on UnitTest tag"); + } + + String methodName = xmlParserHelper.getRequiredAttribute("name"); + String className = xmlParserHelper.getRequiredAttribute("className"); + String codeBase = xmlParserHelper.getRequiredAttribute("codeBase"); + + String dllName = codeBase.substring(codeBase.lastIndexOf(File.separator) + 1, codeBase.lastIndexOf('.')); + + String fullyQualifiedName = dllName + "." + className + "." + methodName; + + associateTestIdTestResultWithFile(testId, fullyQualifiedName); + } + + public void associateTestIdTestResultWithFile(String testId, String methodFullName) { + if(!methodFileMap.containsKey(methodFullName)) { + throw new IllegalStateException(String.format("Test method %s with testId %s cannot be mapped to the test source file", methodFullName, testId)); + } + + String fileName = methodFileMap.get(methodFullName); + + if (unitTestResults.containsKey(fileName)) { + var fileTestResult = unitTestResults.get(fileName); + var testIdTestResult = testIdTestResultMap.get(testId); + fileTestResult.add(testIdTestResult); + } else { + unitTestResults.put(fileName, testIdTestResultMap.get(testId)); + } + + LOG.debug("Associated Visual Studio Unit Test to File - file: {}, TestId: {} MethodFullName: {}", + fileName, testId, methodFullName); + } + + private Date getRequiredDateAttribute(XmlParserHelper xmlParserHelper, String name) { + String value = xmlParserHelper.getRequiredAttribute(name); + try { + value = keepOnlyMilliseconds(value); + return dateFormat.parse(value); + } catch (ParseException e) { + throw xmlParserHelper.parseError("Expected a valid date and time instead of \"" + value + "\" for the attribute \"" + name + "\". " + e.getMessage()); + } + } + + private String keepOnlyMilliseconds(String value) { + StringBuilder sb = new StringBuilder(); + + Matcher matcher = millisecondsPattern.matcher(value); + StringBuilder trailingZeros = new StringBuilder(); + while (matcher.find()) { + String milliseconds = matcher.group(2); + trailingZeros.setLength(0); + trailingZeros.append("0".repeat(Math.max(0, 3 - milliseconds.length()))); + matcher.appendReplacement(sb, "$1" + trailingZeros); + } + matcher.appendTail(sb); + + return sb.toString(); + } + + private static void checkRootTag(XmlParserHelper xmlParserHelper) { + xmlParserHelper.checkRootTag("TestRun"); + } + } +} diff --git a/sonar-dotnet-core/src/main/java/org/sonar/plugins/dotnet/tests/VisualStudioTestResults.java b/sonar-dotnet-core/src/main/java/org/sonar/plugins/dotnet/tests/VisualStudioTestResults.java new file mode 100644 index 00000000000..e39c47356f3 --- /dev/null +++ b/sonar-dotnet-core/src/main/java/org/sonar/plugins/dotnet/tests/VisualStudioTestResults.java @@ -0,0 +1,52 @@ +/* + * SonarSource :: .NET :: Core + * Copyright (C) 2014-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Sonar Source-Available License Version 1, as published by SonarSource SA. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the Sonar Source-Available License for more details. + * + * You should have received a copy of the Sonar Source-Available License + * along with this program; if not, see https://sonarsource.com/license/ssal/ + */ +package org.sonar.plugins.dotnet.tests; + +public class VisualStudioTestResults extends UnitTestResults { + + VisualStudioTestResults(String outcome, Long executionTime) { + this.tests = 1; + this.executionTime = executionTime; + switch(outcome) { + case "Passed", + "Warning": + // success + break; + case "Failed": + // failure + this.failures = 1; + break; + case "Error": + // error + this.errors = 1; + break; + case "PassedButRunAborted", + "NotExecuted", + "Inconclusive", + "Completed", + "Timeout", + "Aborted", + "Blocked", + "NotRunnable": + //skipped + this.skipped = 1; + break; + default: + throw new IllegalArgumentException("Outcome of unit test must match VSTest Format"); + } + } +} diff --git a/sonar-dotnet-core/src/test/java/org/sonar/plugins/dotnet/tests/VisualStudioTestResultParserTest.java b/sonar-dotnet-core/src/test/java/org/sonar/plugins/dotnet/tests/VisualStudioTestResultParserTest.java new file mode 100644 index 00000000000..81804fdd66c --- /dev/null +++ b/sonar-dotnet-core/src/test/java/org/sonar/plugins/dotnet/tests/VisualStudioTestResultParserTest.java @@ -0,0 +1,141 @@ +/* + * SonarSource :: .NET :: Core + * Copyright (C) 2014-2024 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the Sonar Source-Available License Version 1, as published by SonarSource SA. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the Sonar Source-Available License for more details. + * + * You should have received a copy of the Sonar Source-Available License + * along with this program; if not, see https://sonarsource.com/license/ssal/ + */ +package org.sonar.plugins.dotnet.tests; + +import java.io.File; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Rule; +import org.junit.Test; +import org.slf4j.event.Level; +import org.sonar.api.testfixtures.log.LogTester; + +import static org.assertj.core.api.Assertions.assertThat; + +public class VisualStudioTestResultParserTest { + + @Rule + public LogTester logTester = new LogTester(); + + @Before + public void before() { + logTester.setLevel(Level.DEBUG); + } + + @Test + public void valid() { + Map results = new HashMap<>(); + + var sut = new VisualStudioTestResultParser(new HashMap<>() { + { + put("Playground.Test.TestProject1.UnitTest1.TestMethod1", "C:\\dev\\Playground\\Playground.Test\\Sample.cs"); + put("Playground.Test.TestProject1.UnitTest1.TestShouldFail", "C:\\dev\\Playground\\Playground.Test\\UnitTest1.cs"); + put("Playground.Test.TestProject1.UnitTest1.TestShouldSkip", "C:\\dev\\Playground\\Playground.Test\\UnitTest1.cs"); + put("Playground.Test.TestProject1.UnitTest1.TestShouldError", "C:\\dev\\Playground\\Playground.Test\\UnitTest1.cs"); + put("Playground.Test.TestProject1.UnitTest2.TestMethod5", "C:\\dev\\Playground\\Playground.Test\\Sample.cs"); + } + }); + + sut.accept(new File("src/test/resources/visualstudio_test_results/valid.trx"), results); + + assertThat(results).hasSize(2); + assertThat(results.get("C:\\dev\\Playground\\Playground.Test\\Sample.cs").tests()).isEqualTo(13); + assertThat(results.get("C:\\dev\\Playground\\Playground.Test\\Sample.cs").failures()).isZero(); + assertThat(results.get("C:\\dev\\Playground\\Playground.Test\\Sample.cs").skipped()).isEqualTo(7); + assertThat(results.get("C:\\dev\\Playground\\Playground.Test\\Sample.cs").errors()).isEqualTo(1); + assertThat(results.get("C:\\dev\\Playground\\Playground.Test\\Sample.cs").executionTime()).isEqualTo(47); + + assertThat(results.get("C:\\dev\\Playground\\Playground.Test\\UnitTest1.cs").tests()).isEqualTo(3); + assertThat(results.get("C:\\dev\\Playground\\Playground.Test\\UnitTest1.cs").failures()).isEqualTo(2); + assertThat(results.get("C:\\dev\\Playground\\Playground.Test\\UnitTest1.cs").skipped()).isEqualTo(1); + assertThat(results.get("C:\\dev\\Playground\\Playground.Test\\UnitTest1.cs").errors()).isZero(); + assertThat(results.get("C:\\dev\\Playground\\Playground.Test\\UnitTest1.cs").executionTime()).isEqualTo(22); + + List infoLogs = logTester.logs(Level.INFO); + assertThat(infoLogs).hasSize(1); + assertThat(infoLogs.get(0)).startsWith("Parsing the Visual Studio Test Results file "); + + List debugLogs = logTester.logs(Level.DEBUG); + assertThat(debugLogs).hasSize(32); + assertThat(logTester.logs(Level.DEBUG).get(0)).startsWith("Parsed Visual Studio Unit Test - testId:"); + assertThat(logTester.logs(Level.DEBUG).get(15)).startsWith("Parsed Visual Studio Unit Test - testId:"); + assertThat(logTester.logs(Level.DEBUG).get(16)).startsWith("Associated Visual Studio Unit Test to File - file:"); + assertThat(logTester.logs(Level.DEBUG).get(31)).startsWith("Associated Visual Studio Unit Test to File - file:"); + } + + @Test + public void test_name_not_mapped() { + Map results = new HashMap<>(); + var sut = new VisualStudioTestResultParser(new HashMap<>() { + { + put("Some.Other.TestMethod", "C:\\dev\\Playground\\Playground.Test\\Sample.cs"); + } + }); + var file = new File("src/test/resources/visualstudio_test_results/test_name_not_mapped.trx"); + + var exception = Assert.assertThrows(IllegalStateException.class, () -> sut.accept(file, results)); + + Assert.assertEquals("Test method Playground.Test.TestProject1.UnitTest1.TestShouldFail with testId d7744238-9adf-b364-3d70-ae38261a8cd8 cannot be mapped to the test source file", + exception.getMessage()); + } + + @Test + public void invalid_date() { + Map results = new HashMap<>(); + var sut = new VisualStudioTestResultParser(new HashMap<>()); + var file = new File("src/test/resources/visualstudio_test_results/invalid_dates.trx"); + + var exception = Assert.assertThrows(ParseErrorException.class, () -> sut.accept(file, results)); + assertThat(exception.getMessage()).startsWith("Expected a valid date and time instead of \"2016-xx-14T17:04:31.100+01:00\" for the attribute \"startTime\". Unparseable date: \"2016-xx-14T17:04:31.100+01:00\" in "); + } + + @Test + public void invalid_character_fail() { + Map results = new HashMap<>(); + var sut = new VisualStudioTestResultParser(new HashMap<>()); + var file = new File("src/test/resources/visualstudio_test_results/invalid_character.trx"); + + var exception = Assert.assertThrows(IllegalStateException.class, () -> sut.accept(file, results)); + + assertThat(exception.getMessage()).startsWith("Error while parsing the XML file:"); + } + + @Test + public void test_result_no_test_method() { + Map results = new HashMap<>(); + var sut = new VisualStudioTestResultParser(new HashMap<>()); + var file = new File("src/test/resources/visualstudio_test_results/test_result_no_test_method.trx"); + + var exception = Assert.assertThrows(ParseErrorException.class, () -> sut.accept(file, results)); + Assert.assertEquals("No TestMethod attribute found on UnitTest tag", + exception.getMessage()); + } + + @Test + public void invalid_test_outcome() { + Map results = new HashMap<>(); + var sut = new VisualStudioTestResultParser(Map.of("Playground.Test.TestProject1.UnitTest1.InvalidOutcome", "C:\\dev\\Playground\\Playground.Test\\Sample.cs")); + var file = new File("src/test/resources/visualstudio_test_results/invalid_test_outcome.trx"); + + var exception = Assert.assertThrows(IllegalArgumentException.class, () -> sut.accept(file,results)); + Assert.assertEquals("Outcome of unit test must match VSTest Format", + exception.getMessage()); + } +} diff --git a/sonar-dotnet-core/src/test/resources/visualstudio_test_results/invalid_character.trx b/sonar-dotnet-core/src/test/resources/visualstudio_test_results/invalid_character.trx new file mode 100644 index 00000000000..d390d00369e --- /dev/null +++ b/sonar-dotnet-core/src/test/resources/visualstudio_test_results/invalid_character.trx @@ -0,0 +1,19 @@ + + + + + + + + + + < + + + + + + + Test 'TestShouldSkip' was skipped in the test run. + + \ No newline at end of file diff --git a/sonar-dotnet-core/src/test/resources/visualstudio_test_results/invalid_dates.trx b/sonar-dotnet-core/src/test/resources/visualstudio_test_results/invalid_dates.trx new file mode 100644 index 00000000000..b7ceb8657e5 --- /dev/null +++ b/sonar-dotnet-core/src/test/resources/visualstudio_test_results/invalid_dates.trx @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sonar-dotnet-core/src/test/resources/visualstudio_test_results/invalid_test_outcome.trx b/sonar-dotnet-core/src/test/resources/visualstudio_test_results/invalid_test_outcome.trx new file mode 100644 index 00000000000..aaf08c11798 --- /dev/null +++ b/sonar-dotnet-core/src/test/resources/visualstudio_test_results/invalid_test_outcome.trx @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sonar-dotnet-core/src/test/resources/visualstudio_test_results/readme.md b/sonar-dotnet-core/src/test/resources/visualstudio_test_results/readme.md new file mode 100644 index 00000000000..89e44d53d11 --- /dev/null +++ b/sonar-dotnet-core/src/test/resources/visualstudio_test_results/readme.md @@ -0,0 +1,107 @@ +# Generating VS Test Results + +## Valid.trx + +These results are generated from [this project](https://github.com/alex-meseldzija-sonarsource/Playground/tree/main/Playground.Test) by running the `dotnet test --logger:trx` command + +This will generate a valid .trx file in Playground/Playground.Test/TestResults. + +These results do not cover the full possibilities of results possible from .trx files. +There is no documentation on how the outcome value is determined so many are added manually. + +Under the `` tag these tests are added to hit all possible outcomes + +```xml + + + + + + + + + + +``` + +Then Under the `` tag these are added. Please note that the ``value matches exactly to a `` value. + +```xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +``` + +## invalid_character.trx + +This is a valid .trx file that has been modified to be an invalid .trx and invalid .xml. +There can be only 1 UnitTestResult tag and no Test Definition tags, otherwise the XMLParserHelper will not throw an exception. + +```xml + + + < + + +``` + +## invalid_dates.trx + +This is a valid .trx file that has been modified to have an invalid datetime format. + +```xml + +``` + +## invalid_test_outcome.trx + +This is a valid .trx file that has been modified to have an outcome that doesn't exist. + +```xml + +``` + +## test_name_not mapped.trx + +This is a valid .trx file consisting of a single unit test extracted from valid.trx that is then not mapped correctly in the Hashmap provided to the VisualStudioTestResultParser. + +## test_result_no_test_method.trx + +This is a valid .trx file consisting of a a single unit test extracted from valid.trx that has had the methodName tag removed from the UnitTestResult tag. diff --git a/sonar-dotnet-core/src/test/resources/visualstudio_test_results/test_name_not_mapped.trx b/sonar-dotnet-core/src/test/resources/visualstudio_test_results/test_name_not_mapped.trx new file mode 100644 index 00000000000..9af6478e2ed --- /dev/null +++ b/sonar-dotnet-core/src/test/resources/visualstudio_test_results/test_name_not_mapped.trx @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sonar-dotnet-core/src/test/resources/visualstudio_test_results/test_result_no_test_method.trx b/sonar-dotnet-core/src/test/resources/visualstudio_test_results/test_result_no_test_method.trx new file mode 100644 index 00000000000..54c43603881 --- /dev/null +++ b/sonar-dotnet-core/src/test/resources/visualstudio_test_results/test_result_no_test_method.trx @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sonar-dotnet-core/src/test/resources/visualstudio_test_results/valid.trx b/sonar-dotnet-core/src/test/resources/visualstudio_test_results/valid.trx new file mode 100644 index 00000000000..59294788a55 --- /dev/null +++ b/sonar-dotnet-core/src/test/resources/visualstudio_test_results/valid.trx @@ -0,0 +1,133 @@ + + + + + + + + + + + Assert.IsTrue failed. + at TestProject1.UnitTest1.TestShouldFail() in C:\dev\Playground\Playground.Test\UnitTest1.cs:line 18 + at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor) + at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr) + + + + + + + + + Test method TestProject1.UnitTest1.TestShouldError threw exception: +System.Exception: This is an error + at TestProject1.UnitTest1.TestShouldError() in C:\dev\Playground\Playground.Test\UnitTest1.cs:line 31 + at System.RuntimeMethodHandle.InvokeMethod(Object target, Void** arguments, Signature sig, Boolean isConstructor) + at System.Reflection.MethodBaseInvoker.InvokeWithNoArgs(Object obj, BindingFlags invokeAttr) + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Test 'TestShouldSkip' was skipped in the test run. + + + + \ No newline at end of file