diff --git a/src/Stryker.Core/Stryker.Core/Initialisation/ProjectMutator.cs b/src/Stryker.Core/Stryker.Core/Initialisation/ProjectMutator.cs index df399d9793..0f7099014e 100644 --- a/src/Stryker.Core/Stryker.Core/Initialisation/ProjectMutator.cs +++ b/src/Stryker.Core/Stryker.Core/Initialisation/ProjectMutator.cs @@ -1,3 +1,4 @@ +using System; using System.IO; using System.Linq; using Microsoft.CodeAnalysis.CSharp.Syntax; @@ -30,7 +31,7 @@ public IMutationTestProcess MutateProject(StrykerOptions options, MutationTestIn { var process = _injectedMutationTestProcess ?? new MutationTestProcess(input, options, reporters, new MutationTestExecutor(input.TestRunner)); - + // Enrich test projects info with unit tests EnrichTestProjectsWithTestInfo(input.InitialTestRun, input.TestProjectsInfo); @@ -46,7 +47,15 @@ private void EnrichTestProjectsWithTestInfo(InitialTestRun initialTestRun, TestP initialTestRun.Result.VsTestDescriptions .Select(desc => desc.Case) // F# has a different syntax tree and would throw further down the line - .Where(unitTest => Path.GetExtension(unitTest.CodeFilePath) == ".cs"); + .Where(unitTest => Path.GetExtension(unitTest.CodeFilePath) == ".cs").ToList(); + + if (!unitTests.Any()) + { + unitTests = initialTestRun.Result.VsTestDescriptions + .Select(desc => desc.Case) + // F# has a different syntax tree and would throw further down the line + .Where(unitTest => Path.GetExtension(unitTest.CodeFilePath) != ".fs").ToList(); + } foreach (var unitTest in unitTests) { @@ -60,7 +69,49 @@ private void EnrichTestProjectsWithTestInfo(InitialTestRun initialTestRun, TestP } else { - _logger.LogDebug("Could not locate unit test in any testfile. This should not happen and results in incorrect test reporting."); + //Test if you can find the file by scanning the sources for testcase name + var qualifiedNameArray = unitTest.FullyQualifiedName.Split('.'); + var methodName = qualifiedNameArray[^1]; + var className = qualifiedNameArray[^2]; + var nameSpace1 = new ArraySegment(qualifiedNameArray, 0, qualifiedNameArray.Length - 2); + var nameSpace = $"namespace {string.Join('.', nameSpace1)}"; + + testFile = testProjectsInfo.TestFiles.Where(tFile => !tFile.FilePath.EndsWith("GlobalSuppressions.cs")).SingleOrDefault(tFile => + tFile.Source.Contains(className) && tFile.Source.Contains(methodName) && tFile.Source.Contains(nameSpace)); + if (testFile is not null) + { + var testDescriptions = + initialTestRun.Result.VsTestDescriptions.Where(td => td.Description.Name == unitTest.FullyQualifiedName); + foreach (var testDescription in testDescriptions) + { + testDescription.Description.TestFilePath = testFile.FilePath; + } + + var lineNumber = unitTest.LineNumber; + if (lineNumber < 1) + { + var lines = testFile.Source.Split("\r\n"); + foreach (var line in lines) + { + if (line.Contains(methodName) && !line.Contains("class")) + { + lineNumber = Array.IndexOf(testFile.Source.Split("\r\n"), + testFile.Source.Split("\r\n").First(sourceLine => sourceLine.Contains(methodName) && !sourceLine.Contains("class"))); + break; + } + } + } + + var lineSpan = testFile.SyntaxTree.GetText().Lines[lineNumber].Span; + var nodesInSpan = testFile.SyntaxTree.GetRoot().DescendantNodes(lineSpan); + var node = nodesInSpan.First(n => n is MethodDeclarationSyntax); + testFile.AddTest(unitTest.Id, unitTest.FullyQualifiedName, node); + } + else + { + _logger.LogDebug( + "Could not locate unit test in any testfile. This should not happen and results in incorrect test reporting."); + } } } } diff --git a/src/Stryker.Core/Stryker.Core/Mutants/TestDescription.cs b/src/Stryker.Core/Stryker.Core/Mutants/TestDescription.cs index 3ab6ce0e9b..34187af987 100644 --- a/src/Stryker.Core/Stryker.Core/Mutants/TestDescription.cs +++ b/src/Stryker.Core/Stryker.Core/Mutants/TestDescription.cs @@ -15,7 +15,7 @@ public TestDescription(Guid id, string name, string testFilePath) public string Name { get; } - public string TestFilePath { get; } + public string TestFilePath { get; set; } private bool Equals(TestDescription other) {