private FolderComposite FindProjectFilesScanningProjectFolders(ProjectAnalyzerResult analyzerResult) { var inputFiles = new FolderComposite(); var projectUnderTestDir = Path.GetDirectoryName(analyzerResult.ProjectFilePath); foreach (var dir in ExtractProjectFolders(analyzerResult)) { var folder = _fileSystem.Path.Combine(Path.GetDirectoryName(projectUnderTestDir), dir); _logger.LogDebug($"Scanning {folder}"); if (!_fileSystem.Directory.Exists(folder)) { throw new DirectoryNotFoundException($"Can't find {folder}"); } inputFiles.Add(FindInputFiles(folder, projectUnderTestDir)); } return(inputFiles); }
public void ClearTextTreeReporter_ShouldPrintGreenAboveThresholdHigh() { var tree = CSharpSyntaxTree.ParseText("void M(){ int i = 0 + 8; }"); var originalNode = tree.GetRoot().DescendantNodes().OfType <BinaryExpressionSyntax>().First(); var mutation = new Mutation() { OriginalNode = originalNode, ReplacementNode = SyntaxFactory.BinaryExpression(SyntaxKind.SubtractExpression, originalNode.Left, originalNode.Right), DisplayName = "This name should display", Type = Mutator.Arithmetic }; var textWriter = new StringWriter(); var target = new ClearTextTreeReporter(new StrykerOptions(), textWriter); var folder = new FolderComposite() { Name = "RootFolder", RelativePath = "RootFolder", FullPath = "C://RootFolder", }; folder.Add(new FileLeaf() { Name = "SomeFile.cs", RelativePath = "RootFolder/SomeFile.cs", FullPath = "C://RootFolder/SomeFile.cs", Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = MutantStatus.Killed, Mutation = mutation }, } }); target.OnAllMutantsTested(folder.ToReadOnly()); textWriter.GreenSpanCount().ShouldBe(3); }
/// <summary> /// Finds the referencedProjects and looks for all files that should be mutated in those projects /// </summary> public ProjectInfo ResolveInput(StrykerOptions options) { var result = new ProjectInfo(); var testProjectFile = FindProjectFile(options.BasePath, options.TestProjectNameFilter); // Analyze the test project result.TestProjectAnalyzerResult = _projectFileReader.AnalyzeProject(testProjectFile, options.SolutionPath); // Determine project under test var reader = new ProjectFileReader(); var projectUnderTest = reader.DetermineProjectUnderTest(result.TestProjectAnalyzerResult.ProjectReferences, options.ProjectUnderTestNameFilter); _logger.LogInformation("The project {0} will be mutated", projectUnderTest); // Analyze project under test result.ProjectUnderTestAnalyzerResult = _projectFileReader.AnalyzeProject(projectUnderTest, options.SolutionPath); var inputFiles = new FolderComposite(); result.FullFramework = !result.TestProjectAnalyzerResult.TargetFramework.Contains("netcoreapp", StringComparison.InvariantCultureIgnoreCase); var projectUnderTestDir = Path.GetDirectoryName(result.ProjectUnderTestAnalyzerResult.ProjectFilePath); foreach (var dir in ExtractProjectFolders(result.ProjectUnderTestAnalyzerResult, result.FullFramework)) { var folder = _fileSystem.Path.Combine(Path.GetDirectoryName(projectUnderTestDir), dir); _logger.LogDebug($"Scanning {folder}"); if (!_fileSystem.Directory.Exists(folder)) { throw new DirectoryNotFoundException($"Can't find {folder}"); } inputFiles.Add(FindInputFiles(folder, options.FilesToExclude.ToList())); } MarkInputFilesAsExcluded(inputFiles, options.FilesToExclude.ToList(), projectUnderTestDir); result.ProjectContents = inputFiles; ValidateResult(result, options); return(result); }
public void ConsoleReportReporter_ShouldPrintYellowOn80PercentAndLower() { string output = ""; var chalkMock = new Mock<IChalk>(MockBehavior.Strict); chalkMock.Setup(x => x.Red(It.IsAny<string>())).Callback((string text) => { output += text; }); chalkMock.Setup(x => x.Default(It.IsAny<string>())).Callback((string text) => { output += text; }); chalkMock.Setup(x => x.Green(It.IsAny<string>())).Callback((string text) => { output += text; }); chalkMock.Setup(x => x.Yellow(It.IsAny<string>())).Callback((string text) => { output += text; }); var tree = CSharpSyntaxTree.ParseText("void M(){ int i = 0 + 8; }"); var originalNode = tree.GetRoot().DescendantNodes().OfType<BinaryExpressionSyntax>().First(); var mutation = new Mutation() { OriginalNode = originalNode, ReplacementNode = SyntaxFactory.BinaryExpression(SyntaxKind.SubtractExpression, originalNode.Left, originalNode.Right), DisplayName = "This name should display", Type = MutatorType.Arithmetic }; var target = new ConsoleReportReporter(new StrykerOptions("", "ReportOnly", "", 1000, null, "debug", false, 1, 80, 60, 0), chalkMock.Object); var folder = new FolderComposite() { Name = "RootFolder" }; folder.Add(new FileLeaf() { Name = "SomeFile.cs", Mutants = new Collection<Mutant>() { new Mutant() { ResultStatus = MutantStatus.Survived, Mutation = mutation }, new Mutant() { ResultStatus = MutantStatus.Killed, Mutation = mutation }, new Mutant() { ResultStatus = MutantStatus.Killed, Mutation = mutation }, new Mutant() { ResultStatus = MutantStatus.Killed, Mutation = mutation }, new Mutant() { ResultStatus = MutantStatus.Killed, Mutation = mutation } } }); target.OnAllMutantsTested(folder); chalkMock.Verify(x => x.Yellow(It.IsAny<string>()), Times.Exactly(2)); }
public void ConsoleReportReporter_ShouldPrintSurvivedMutation() { string output = ""; var chalkMock = new Mock<IChalk>(MockBehavior.Strict); chalkMock.Setup(x => x.Red(It.IsAny<string>())).Callback((string text) => { output += text; }); chalkMock.Setup(x => x.Default(It.IsAny<string>())).Callback((string text) => { output += text; }); var tree = CSharpSyntaxTree.ParseText("void M(){ int i = 0 + 8; }"); var originalNode = tree.GetRoot().DescendantNodes().OfType<BinaryExpressionSyntax>().First(); var mutation = new Mutation() { OriginalNode = originalNode, ReplacementNode = SyntaxFactory.BinaryExpression(SyntaxKind.SubtractExpression, originalNode.Left, originalNode.Right), DisplayName = "This name should display", Type = MutatorType.Arithmetic }; var target = new ConsoleReportReporter(new StrykerOptions("", "ReportOnly", "", 1000, null, "debug", false, 1, 80, 60, 0), chalkMock.Object); var folder = new FolderComposite() { Name = "RootFolder" }; folder.Add(new FileLeaf() { Name = "SomeFile.cs", Mutants = new Collection<Mutant>() { new Mutant() { ResultStatus = MutantStatus.Survived, Mutation = mutation } } }); target.OnAllMutantsTested(folder); output.ShouldBeWithNewlineReplace( $@" All mutants have been tested, and your mutation score has been calculated - {Path.DirectorySeparatorChar}RootFolder [0/1 (0.00 %)] --- SomeFile.cs [0/1 (0.00 %)] [Survived] This name should display on line 1: '0 + 8' ==> '0 -8' "); // All percentages should be red and the [Survived] too chalkMock.Verify(x => x.Red(It.IsAny<string>()), Times.Exactly(3)); }
public void ConsoleReportReporter_ShouldPrintOnReportDone() { string output = ""; var chalkMock = new Mock<IChalk>(MockBehavior.Strict); chalkMock.Setup(x => x.DarkGray(It.IsAny<string>())).Callback((string text) => { output += text; }); chalkMock.Setup(x => x.Default(It.IsAny<string>())).Callback((string text) => { output += text; }); var target = new ConsoleReportReporter(new StrykerOptions("", "ReportOnly", "", 1000, null, "debug", false, 1, 80, 60, 0), chalkMock.Object); var folder = new FolderComposite() { Name = "RootFolder" }; folder.Add(new FileLeaf() { Name = "SomeFile.cs", Mutants = new Collection<Mutant>() { } }); target.OnAllMutantsTested(folder); output.ToString().ShouldBeWithNewlineReplace($@" All mutants have been tested, and your mutation score has been calculated - {Path.DirectorySeparatorChar}RootFolder [0/0 (- %)] --- SomeFile.cs [0/0 (- %)] "); chalkMock.Verify(x => x.DarkGray(It.IsAny<string>()), Times.Exactly(2)); }
public void ReportComponent_ShouldCalculateMutationScore_BuildErrorIsNull() { var target = new FolderComposite() { Name = "RootFolder" }; target.Add(new FileLeaf() { Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = MutantStatus.CompileError } } }); var result = target.GetMutationScore(); result.ShouldBe(double.NaN); }
public void ReportComponent_ShouldCalculateMutationScore_OnlyKilledIsSuccessful(MutantStatus status, double expectedScore) { var target = new FolderComposite() { Name = "RootFolder" }; target.Add(new FileLeaf() { Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = status } } }); var result = target.GetMutationScore(); result.ShouldBe(expectedScore); }
public void ReportComponent_ShouldCalculateMutationScore_OneMutation() { var target = new FolderComposite() { Name = "RootFolder" }; target.Add(new FileLeaf() { Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = MutantStatus.Killed } } }); var result = target.GetMutationScore(); result.ShouldBe(100M); }
/// <summary> /// Finds the referencedProjects and looks for all files that should be mutated in those projects /// </summary> public ProjectInfo ResolveInput(string currentDirectory, string projectName, List <string> filesToExclude) { var projectFile = ScanProjectFile(currentDirectory); var currentProjectInfo = ReadProjectFile(projectFile, projectName); var projectReferencePath = FilePathUtils.ConvertPathSeparators(currentProjectInfo.ProjectReference); var projectUnderTestPath = Path.GetDirectoryName(Path.GetFullPath(Path.Combine(currentDirectory, projectReferencePath))); var projectReference = Path.Combine(projectUnderTestPath, Path.GetFileName(projectReferencePath)); var projectFilePath = Path.GetFullPath(projectReference); var projectUnderTestInfo = FindProjectUnderTestAssemblyName(projectFilePath); var inputFiles = new FolderComposite(); foreach (var dir in ExtractProjectFolders(projectFilePath)) { var folder = Path.Combine(Path.GetDirectoryName(projectFilePath), dir); _logger.LogDebug($"Scanning {folder}"); if (!_fileSystem.Directory.Exists(folder)) { throw new DirectoryNotFoundException($"Can't find {folder}"); } inputFiles.Add(FindInputFiles(folder, filesToExclude)); } MarkInputFilesAsExcluded(inputFiles, filesToExclude, projectUnderTestPath); return(new ProjectInfo() { TestProjectPath = currentDirectory, TestProjectFileName = Path.GetFileName(projectFile), TargetFramework = currentProjectInfo.TargetFramework, ProjectContents = inputFiles, ProjectUnderTestPath = projectUnderTestPath, ProjectUnderTestAssemblyName = projectUnderTestInfo ?? Path.GetFileNameWithoutExtension(projectReferencePath), ProjectUnderTestProjectName = Path.GetFileNameWithoutExtension(projectReferencePath), AppendTargetFrameworkToOutputPath = currentProjectInfo.AppendTargetFrameworkToOutputPath }); }
public void ClearTextReporter_ShouldPrintOnReportDone() { var textWriter = new StringWriter(); var target = new ClearTextReporter(new StrykerOptions(), textWriter); var folder = new FolderComposite() { Name = "RootFolder", RelativePath = "RootFolder", FullPath = "C://RootFolder", }; folder.Add(new FileLeaf() { Name = "SomeFile.cs", RelativePath = "RootFolder/SomeFile.cs", RelativePathToProjectFile = "SomeFile.cs", FullPath = "C://RootFolder/SomeFile.cs", Mutants = new Collection <Mutant>() { } }); target.OnAllMutantsTested(folder.ToReadOnly()); textWriter.RemoveAnsi().ShouldBeWithNewlineReplace($@" All mutants have been tested, and your mutation score has been calculated ┌─────────────┬──────────┬──────────┬───────────┬────────────┬──────────┬─────────┐ │ File │ % score │ # killed │ # timeout │ # survived │ # no cov │ # error │ ├─────────────┼──────────┼──────────┼───────────┼────────────┼──────────┼─────────┤ │ All files │ N/A │ 0 │ 0 │ 0 │ 0 │ 0 │ │ SomeFile.cs │ N/A │ 0 │ 0 │ 0 │ 0 │ 0 │ └─────────────┴──────────┴──────────┴───────────┴────────────┴──────────┴─────────┘ "); textWriter.DarkGraySpanCount().ShouldBe(2); }
public void ClearTextTreeReporter_ShouldPrintOnReportDone() { string output = ""; var chalkMock = new Mock <IChalk>(MockBehavior.Strict); chalkMock.Setup(x => x.DarkGray(It.IsAny <string>())).Callback((string text) => { output += text; }); chalkMock.Setup(x => x.Default(It.IsAny <string>())).Callback((string text) => { output += text; }); var target = new ClearTextTreeReporter(new StrykerOptions(), chalkMock.Object); var folder = new FolderComposite() { Name = "RootFolder", RelativePath = "RootFolder", FullPath = "C://RootFolder", }; folder.Add(new FileLeaf() { Name = "SomeFile.cs", RelativePath = "RootFolder/SomeFile.cs", FullPath = "C://RootFolder/SomeFile.cs", Mutants = new Collection <Mutant>() { } }); target.OnAllMutantsTested(folder); output.ToString().ShouldBeWithNewlineReplace($@" All mutants have been tested, and your mutation score has been calculated RootFolder [0/0 (N/A)] └── SomeFile.cs [0/0 (N/A)] "); chalkMock.Verify(x => x.DarkGray(It.IsAny <string>()), Times.Exactly(2)); }
public void ShouldCallMutantOrchestratorAndReporter() { var inputFile = new FileLeaf() { Name = "Recursive.cs", SourceCode = SourceFile, SyntaxTree = CSharpSyntaxTree.ParseText(SourceFile) }; var logger = ApplicationLogging.LoggerFactory.CreateLogger <ProjectAnalyzerResult>(); var folder = new FolderComposite() { Name = Path.Combine(FilesystemRoot, "ExampleProject") }; folder.Add(inputFile); var input = new MutationTestInput() { ProjectInfo = new ProjectInfo() { TestProjectAnalyzerResults = new List <ProjectAnalyzerResult> { new ProjectAnalyzerResult(logger, null) { AssemblyPath = "/bin/Debug/netcoreapp2.1/TestName.dll", Properties = new Dictionary <string, string>() { { "TargetDir", "/bin/Debug/netcoreapp2.1" }, { "AssemblyName", "TestName" } } } }, ProjectUnderTestAnalyzerResult = new ProjectAnalyzerResult(logger, null) { AssemblyPath = "/bin/Debug/netcoreapp2.1/TestName.dll", Properties = new Dictionary <string, string>() { { "TargetDir", "/bin/Debug/netcoreapp2.1" }, { "AssemblyName", "TestName" } } }, ProjectContents = folder }, AssemblyReferences = _assemblies }; var fileSystem = new MockFileSystem(new Dictionary <string, MockFileData> { { Path.Combine(FilesystemRoot, "ExampleProject", "Recursive.cs"), new MockFileData(SourceFile) }, { Path.Combine(FilesystemRoot, "ExampleProject.Test", "bin", "Debug", "netcoreapp2.0", "ExampleProject.dll"), new MockFileData("Bytecode") }, { Path.Combine(FilesystemRoot, "ExampleProject.Test", "obj", "Release", "netcoreapp2.0", "ExampleProject.dll"), new MockFileData("Bytecode") } }); var mutantToBeSkipped = new Mutant() { Mutation = new Mutation() }; var mockMutants = new Collection <Mutant>() { new Mutant() { Mutation = new Mutation() }, mutantToBeSkipped }; // create mocks var orchestratorMock = new Mock <IMutantOrchestrator>(MockBehavior.Strict); var reporterMock = new Mock <IReporter>(MockBehavior.Strict); var mutationTestExecutorMock = new Mock <IMutationTestExecutor>(MockBehavior.Strict); // setup mocks reporterMock.Setup(x => x.OnMutantsCreated(It.IsAny <ReadOnlyProjectComponent>())); orchestratorMock.Setup(x => x.GetLatestMutantBatch()).Returns(mockMutants); orchestratorMock.Setup(x => x.Mutate(It.IsAny <SyntaxNode>())).Returns(CSharpSyntaxTree.ParseText(SourceFile).GetRoot()); orchestratorMock.SetupAllProperties(); var options = new StrykerOptions(devMode: true, excludedMutations: new string[] { }); var target = new MutationTestProcess(input, reporterMock.Object, mutationTestExecutorMock.Object, orchestratorMock.Object, fileSystem, options, new BroadcastMutantFilter(Enumerable.Empty <IMutantFilter>())); // start mutation process target.Mutate(); target.FilterMutants(); // verify the right methods were called orchestratorMock.Verify(x => x.Mutate(It.IsAny <SyntaxNode>()), Times.Once); reporterMock.Verify(x => x.OnMutantsCreated(It.IsAny <ReadOnlyProjectComponent>()), Times.Once); }
public void ShouldCallExecutorForEveryMutant() { var mutant = new Mutant { Id = 1, MustRunAgainstAllTests = true }; var otherMutant = new Mutant { Id = 2, MustRunAgainstAllTests = true }; string basePath = Path.Combine(FilesystemRoot, "ExampleProject.Test"); var folder = new FolderComposite() { Name = "ProjectRoot" }; folder.Add(new FileLeaf() { Name = "SomeFile.cs", SourceCode = SourceFile, Mutants = new List <Mutant>() { mutant, otherMutant } }); var input = new MutationTestInput() { ProjectInfo = new ProjectInfo() { ProjectUnderTestAnalyzerResult = TestHelper.SetupProjectAnalyzerResult(properties: new Dictionary <string, string>() { { "TargetDir", "/bin/Debug/netcoreapp2.1" }, { "TargetFileName", "TestName.dll" } }).Object , ProjectContents = folder }, AssemblyReferences = _assemblies }; var reporterMock = new Mock <IReporter>(MockBehavior.Strict); reporterMock.Setup(x => x.OnMutantTested(It.IsAny <Mutant>())); var runnerMock = new Mock <ITestRunner>(); runnerMock.Setup(x => x.DiscoverNumberOfTests()).Returns(1); var executorMock = new Mock <IMutationTestExecutor>(MockBehavior.Strict); executorMock.SetupGet(x => x.TestRunner).Returns(runnerMock.Object); executorMock.Setup(x => x.Test(It.IsAny <IList <Mutant> >(), It.IsAny <int>(), It.IsAny <TestUpdateHandler>())); var mutantFilterMock = new Mock <IMutantFilter>(MockBehavior.Loose); var options = new StrykerOptions(basePath: basePath, fileSystem: new MockFileSystem()); var target = new MutationTestProcess(input, reporterMock.Object, executorMock.Object, mutantFilter: mutantFilterMock.Object, options: options); target.Test(input.ProjectInfo.ProjectContents.Mutants); executorMock.Verify(x => x.Test(new List <Mutant> { mutant }, It.IsAny <int>(), It.IsAny <TestUpdateHandler>()), Times.Once); }
public void ShouldThrowExceptionWhenOtherStatusThanNotRunIsPassed(MutantStatus status) { var mutant = new Mutant { Id = 1, ResultStatus = status }; var basePath = Path.Combine(FilesystemRoot, "ExampleProject.Test"); var folder = new FolderComposite() { Name = "ProjectRoot" }; folder.Add(new FileLeaf() { Name = "SomeFile.cs", Mutants = new Collection <Mutant>() { mutant } }); var input = new MutationTestInput() { ProjectInfo = new ProjectInfo() { ProjectUnderTestAnalyzerResult = TestHelper.SetupProjectAnalyzerResult(properties: new Dictionary <string, string>() { { "TargetDir", "/bin/Debug/netcoreapp2.1" }, { "TargetFileName", "TestName.dll" } }).Object, TestProjectAnalyzerResults = new List <IAnalyzerResult> { TestHelper.SetupProjectAnalyzerResult(properties: new Dictionary <string, string>() { { "TargetDir", "/bin/Debug/netcoreapp2.1" }, { "TargetFileName", "TestName.dll" } }).Object }, ProjectContents = folder }, AssemblyReferences = new ReferenceProvider().GetReferencedAssemblies() }; var reporterMock = new Mock <IReporter>(MockBehavior.Strict); reporterMock.Setup(x => x.OnMutantTested(It.IsAny <Mutant>())); var runnerMock = new Mock <ITestRunner>(); runnerMock.Setup(x => x.DiscoverNumberOfTests()).Returns(1); var executorMock = new Mock <IMutationTestExecutor>(MockBehavior.Strict); executorMock.SetupGet(x => x.TestRunner).Returns(runnerMock.Object); executorMock.Setup(x => x.Test(It.IsAny <IList <Mutant> >(), It.IsAny <int>(), It.IsAny <TestUpdateHandler>())); var mutantFilterMock = new Mock <IMutantFilter>(MockBehavior.Loose); var options = new StrykerOptions(basePath: basePath, fileSystem: new MockFileSystem()); var target = new MutationTestProcess(input, reporterMock.Object, executorMock.Object, mutantFilter: mutantFilterMock.Object, options: options); Should.Throw <GeneralStrykerException>(() => target.Test(input.ProjectInfo.ProjectContents.Mutants)); }
public void FilterMutantsShouldCallMutantFilters() { var inputFile = new FileLeaf() { Name = "Recursive.cs", SourceCode = SourceFile, SyntaxTree = CSharpSyntaxTree.ParseText(SourceFile) }; var folder = new FolderComposite() { Name = Path.Combine(FilesystemRoot, "ExampleProject") }; folder.Add(inputFile); var input = new MutationTestInput() { ProjectInfo = new ProjectInfo() { TestProjectAnalyzerResults = new List <ProjectAnalyzerResult> { new ProjectAnalyzerResult(null, null) { AssemblyPath = "/bin/Debug/netcoreapp2.1/TestName.dll", Properties = new Dictionary <string, string>() { { "TargetDir", "/bin/Debug/netcoreapp2.1" }, { "AssemblyName", "TestName" }, } } }, ProjectUnderTestAnalyzerResult = new ProjectAnalyzerResult(null, null) { AssemblyPath = "/bin/Debug/netcoreapp2.1/TestName.dll", Properties = new Dictionary <string, string>() { { "TargetDir", "/bin/Debug/netcoreapp2.1" }, { "AssemblyName", "TestName" }, } }, ProjectContents = folder }, AssemblyReferences = _assemblies }; var fileSystem = new MockFileSystem(new Dictionary <string, MockFileData> { { Path.Combine(FilesystemRoot, "ExampleProject", "Recursive.cs"), new MockFileData(SourceFile) }, { Path.Combine(FilesystemRoot, "ExampleProject.Test", "bin", "Debug", "netcoreapp2.0", "ExampleProject.dll"), new MockFileData("Bytecode") }, { Path.Combine(FilesystemRoot, "ExampleProject.Test", "obj", "Release", "netcoreapp2.0", "ExampleProject.dll"), new MockFileData("Bytecode") } }); var mutantToBeSkipped = new Mutant() { Mutation = new Mutation() }; var compileErrorMutant = new Mutant() { Mutation = new Mutation(), ResultStatus = MutantStatus.CompileError }; var mockMutants = new Collection <Mutant>() { new Mutant() { Mutation = new Mutation() }, mutantToBeSkipped, compileErrorMutant }; // create mocks var orchestratorMock = new Mock <IMutantOrchestrator>(MockBehavior.Strict); var reporterMock = new Mock <IReporter>(MockBehavior.Strict); var mutationTestExecutorMock = new Mock <IMutationTestExecutor>(MockBehavior.Strict); var mutantFilterMock = new Mock <IMutantFilter>(MockBehavior.Strict); // setup mocks reporterMock.Setup(x => x.OnMutantsCreated(It.IsAny <ReadOnlyProjectComponent>())); orchestratorMock.Setup(x => x.GetLatestMutantBatch()).Returns(mockMutants); orchestratorMock.Setup(x => x.Mutate(It.IsAny <SyntaxNode>())).Returns(CSharpSyntaxTree.ParseText(SourceFile).GetRoot()); orchestratorMock.SetupAllProperties(); mutantFilterMock.SetupGet(x => x.DisplayName).Returns("Mock filter"); IEnumerable <Mutant> mutantsPassedToFilter = null; mutantFilterMock.Setup(x => x.FilterMutants(It.IsAny <IEnumerable <Mutant> >(), It.IsAny <ReadOnlyFileLeaf>(), It.IsAny <StrykerOptions>())) .Callback <IEnumerable <Mutant>, ReadOnlyFileLeaf, StrykerOptions>((mutants, _, __) => mutantsPassedToFilter = mutants) .Returns((IEnumerable <Mutant> mutants, ReadOnlyFileLeaf file, StrykerOptions o) => mutants.Take(1)); var options = new StrykerOptions(devMode: true, excludedMutations: new string[] { }); var target = new MutationTestProcess(input, reporterMock.Object, mutationTestExecutorMock.Object, orchestratorMock.Object, fileSystem, options, new BroadcastMutantFilter(new[] { mutantFilterMock.Object })); // start mutation process target.Mutate(); target.FilterMutants(); // verify that compiler error mutants are not passed to filter mutantsPassedToFilter.ShouldNotContain(compileErrorMutant); // verify that filtered mutants are skipped inputFile.Mutants.ShouldContain(mutantToBeSkipped); mutantToBeSkipped.ResultStatus.ShouldBe(MutantStatus.Ignored); }
public void MutateShouldWriteToDisk_IfCompilationIsSuccessful() { string basePath = Path.Combine(FilesystemRoot, "ExampleProject.Test"); var folder = new FolderComposite() { Name = "ProjectRoot" }; folder.Add(new FileLeaf { Name = "SomeFile.cs", SourceCode = SourceFile, SyntaxTree = CSharpSyntaxTree.ParseText(SourceFile) }); var input = new MutationTestInput() { ProjectInfo = new ProjectInfo() { TestProjectAnalyzerResults = new List <ProjectAnalyzerResult> { new ProjectAnalyzerResult(null, null) { AssemblyPath = Path.Combine(basePath, "bin", "Debug", "netcoreapp2.0", "TestName.dll"), Properties = new Dictionary <string, string>() { { "TargetDir", Path.Combine(basePath, "bin", "Debug", "netcoreapp2.0") }, { "AssemblyName", "TestName" }, } } }, ProjectUnderTestAnalyzerResult = new ProjectAnalyzerResult(null, null) { AssemblyPath = Path.Combine(basePath, "bin", "Debug", "netcoreapp2.0", "ExampleProject.dll"), Properties = new Dictionary <string, string>() { { "TargetDir", Path.Combine(basePath, "bin", "Debug", "netcoreapp2.0") }, { "AssemblyName", "ExampleProject" } } }, ProjectContents = folder }, AssemblyReferences = _assemblies }; var mockMutants = new Collection <Mutant>() { new Mutant() { Mutation = new Mutation() } }; // create mocks var orchestratorMock = new Mock <IMutantOrchestrator>(MockBehavior.Strict); var reporterMock = new Mock <IReporter>(MockBehavior.Strict); var mutationTestExecutorMock = new Mock <IMutationTestExecutor>(MockBehavior.Strict); var fileSystem = new MockFileSystem(new Dictionary <string, MockFileData> { { Path.Combine(FilesystemRoot, "SomeFile.cs"), new MockFileData("SomeFile") }, }); fileSystem.AddDirectory(Path.Combine(basePath, "bin", "Debug", "netcoreapp2.0")); // setup mocks orchestratorMock.Setup(x => x.Mutate(It.IsAny <SyntaxNode>())).Returns(CSharpSyntaxTree.ParseText(SourceFile).GetRoot()); orchestratorMock.SetupAllProperties(); orchestratorMock.Setup(x => x.GetLatestMutantBatch()).Returns(mockMutants); reporterMock.Setup(x => x.OnMutantsCreated(It.IsAny <ReadOnlyProjectComponent>())); var options = new StrykerOptions(); var target = new MutationTestProcess(input, reporterMock.Object, mutationTestExecutorMock.Object, orchestratorMock.Object, fileSystem, options, new BroadcastMutantFilter(Enumerable.Empty <IMutantFilter>())); target.Mutate(); // Verify the created assembly is written to disk on the right location string expectedPath = Path.Combine(basePath, "bin", "Debug", "netcoreapp2.0", "ExampleProject.dll"); fileSystem.FileExists(expectedPath) .ShouldBeTrue($"The mutated Assembly was not written to disk, or not to the right location ({expectedPath})."); }
private FolderComposite FindProjectFilesUsingBuildalyzer(IAnalyzerResult analyzerResult, IStrykerOptions options) { var inputFiles = new FolderComposite(); var projectUnderTestDir = Path.GetDirectoryName(analyzerResult.ProjectFilePath); var projectRoot = Path.GetDirectoryName(projectUnderTestDir); var generatedAssemblyInfo = analyzerResult.AssemblyAttributeFileName(); var rootFolderComposite = new FolderComposite() { Name = string.Empty, FullPath = projectRoot, RelativePath = string.Empty, RelativePathToProjectFile = Path.GetRelativePath(projectUnderTestDir, projectUnderTestDir) }; var cache = new Dictionary <string, FolderComposite> { [string.Empty] = rootFolderComposite }; // Save cache in a singleton so we can use it in other parts of the project FolderCompositeCache <FolderComposite> .Instance.Cache = cache; inputFiles.Add(rootFolderComposite); CSharpParseOptions cSharpParseOptions = BuildCsharpParseOptions(analyzerResult, options); InjectMutantHelpers(rootFolderComposite, cSharpParseOptions); foreach (var sourceFile in analyzerResult.SourceFiles) { // Skip xamarin UI generated files if (sourceFile.EndsWith(".xaml.cs")) { continue; } var relativePath = Path.GetRelativePath(projectUnderTestDir, sourceFile); var folderComposite = GetOrBuildFolderComposite(cache, Path.GetDirectoryName(relativePath), projectUnderTestDir, projectRoot, inputFiles); var fileName = Path.GetFileName(sourceFile); var file = new FileLeaf() { SourceCode = _fileSystem.File.ReadAllText(sourceFile), Name = _fileSystem.Path.GetFileName(sourceFile), RelativePath = _fileSystem.Path.Combine(folderComposite.RelativePath, fileName), FullPath = sourceFile, RelativePathToProjectFile = Path.GetRelativePath(projectUnderTestDir, sourceFile) }; // Get the syntax tree for the source file var syntaxTree = CSharpSyntaxTree.ParseText(file.SourceCode, path: file.FullPath, encoding: Encoding.UTF32, options: cSharpParseOptions); // don't mutate auto generated code if (syntaxTree.IsGenerated()) { // we found the generated assemblyinfo file if (_fileSystem.Path.GetFileName(sourceFile).ToLowerInvariant() == generatedAssemblyInfo) { // add the mutated text syntaxTree = InjectMutationLabel(syntaxTree); } _logger.LogDebug("Skipping auto-generated code file: {fileName}", file.Name); folderComposite.AddCompilationSyntaxTree(syntaxTree); // Add the syntaxTree to the list of compilationSyntaxTrees continue; // Don't add the file to the folderComposite as we're not reporting on the file } file.SyntaxTree = syntaxTree; folderComposite.Add(file); } return(inputFiles); }
public void ClearTextTreeReporter_ShouldPrintYellowBetweenThresholdLowAndThresholdBreak() { string output = ""; var chalkMock = new Mock <IChalk>(MockBehavior.Strict); chalkMock.Setup(x => x.Red(It.IsAny <string>())).Callback((string text) => { output += text; }); chalkMock.Setup(x => x.Default(It.IsAny <string>())).Callback((string text) => { output += text; }); chalkMock.Setup(x => x.Green(It.IsAny <string>())).Callback((string text) => { output += text; }); chalkMock.Setup(x => x.Yellow(It.IsAny <string>())).Callback((string text) => { output += text; }); var tree = CSharpSyntaxTree.ParseText("void M(){ int i = 0 + 8; }"); var originalNode = tree.GetRoot().DescendantNodes().OfType <BinaryExpressionSyntax>().First(); var mutation = new Mutation() { OriginalNode = originalNode, ReplacementNode = SyntaxFactory.BinaryExpression(SyntaxKind.SubtractExpression, originalNode.Left, originalNode.Right), DisplayName = "This name should display", Type = Mutator.Arithmetic }; var target = new ClearTextTreeReporter(new StrykerOptions(thresholdHigh: 90, thresholdLow: 70, thresholdBreak: 0), chalkMock.Object); var folder = new FolderComposite() { Name = "RootFolder", RelativePath = "RootFolder", FullPath = "C://RootFolder", }; folder.Add(new FileLeaf() { Name = "SomeFile.cs", RelativePath = "RootFolder/SomeFile.cs", FullPath = "C://RootFolder/SomeFile.cs", Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = MutantStatus.Survived, Mutation = mutation }, new Mutant() { ResultStatus = MutantStatus.Killed, Mutation = mutation }, new Mutant() { ResultStatus = MutantStatus.Killed, Mutation = mutation }, new Mutant() { ResultStatus = MutantStatus.Killed, Mutation = mutation }, new Mutant() { ResultStatus = MutantStatus.Killed, Mutation = mutation } } }); target.OnAllMutantsTested(folder); chalkMock.Verify(x => x.Yellow(It.IsAny <string>()), Times.Exactly(2)); }
public void JsonReporter_OnAllMutantsTestedShouldWriteJsonToFile() { var tree = CSharpSyntaxTree.ParseText("void M(){ int i = 0 + 8; }"); var originalNode = tree.GetRoot().DescendantNodes().OfType <BinaryExpressionSyntax>().First(); var mutation = new Mutation() { OriginalNode = originalNode, ReplacementNode = SyntaxFactory.BinaryExpression(SyntaxKind.SubtractExpression, originalNode.Left, originalNode.Right), DisplayName = "This name should display", Type = Mutator.Arithmetic }; var folder = new FolderComposite() { Name = "RootFolder" }; folder.Add(new FileLeaf() { Name = "SomeFile.cs", Mutants = new Collection <Mutant>() { new Mutant() { Id = 55, ResultStatus = MutantStatus.Killed, Mutation = mutation } }, SourceCode = "void M(){ int i = 0 + 8; }" }); folder.Add(new FileLeaf() { Name = "SomeOtherFile.cs", Mutants = new Collection <Mutant>() { new Mutant() { Id = 56, ResultStatus = MutantStatus.Survived, Mutation = mutation } }, SourceCode = "void M(){ int i = 0 + 8; }" }); folder.Add(new FileLeaf() { Name = "SomeOtherFile.cs", Mutants = new Collection <Mutant>() { new Mutant() { Id = 56, ResultStatus = MutantStatus.Skipped, Mutation = mutation } }, SourceCode = "void M(){ int i = 0 + 8; }" }); var mockFileSystem = new MockFileSystem(); var options = new StrykerOptions(thresholdBreak: 0, thresholdHigh: 80, thresholdLow: 60); var reporter = new JsonReporter(options, mockFileSystem); reporter.OnAllMutantsTested(folder); var reportPath = Path.Combine(options.BasePath, "StrykerOutput", "reports", $"mutation-report-{DateTime.Today.ToString("yyyy-MM-dd")}.json"); mockFileSystem.FileExists(reportPath).ShouldBeTrue($"Path {reportPath} should exist but it does not."); var reportObject = JsonConvert.DeserializeObject <JsonReporter.JsonReportComponent>(mockFileSystem.GetFile(reportPath).TextContents); reportObject.ThresholdHigh.ShouldBe(80); reportObject.ThresholdLow.ShouldBe(60); reportObject.ThresholdBreak.ShouldBe(0); ValidateJsonReportComponent(reportObject, folder, "Warning"); ValidateJsonReportComponent(reportObject.ChildResults.ElementAt(0), folder.Children.ElementAt(0), "Good", 1); ValidateJsonReportComponent(reportObject.ChildResults.ElementAt(1), folder.Children.ElementAt(1), "Danger", 1); }
public void ShouldNotCallExecutorForNotCoveredMutants() { var mutant = new Mutant { Id = 1, ResultStatus = MutantStatus.Survived }; var otherMutant = new Mutant { Id = 2, ResultStatus = MutantStatus.NotRun }; var basePath = Path.Combine(FilesystemRoot, "ExampleProject.Test"); var folder = new FolderComposite() { Name = "ProjectRoot" }; folder.Add(new FileLeaf() { Name = "SomeFile.cs", Mutants = new Collection <Mutant>() { mutant, otherMutant } }); var input = new MutationTestInput() { ProjectInfo = new ProjectInfo() { TestProjectAnalyzerResults = new List <ProjectAnalyzerResult> { new ProjectAnalyzerResult(null, null) { AssemblyPath = "/bin/Debug/netcoreapp2.1/TestName.dll", Properties = new Dictionary <string, string>() { { "TargetDir", "/bin/Debug/netcoreapp2.1" }, { "TargetFileName", "TestName.dll" } } } }, ProjectUnderTestAnalyzerResult = new ProjectAnalyzerResult(null, null) { AssemblyPath = "/bin/Debug/netcoreapp2.1/TestName.dll", Properties = new Dictionary <string, string>() { { "TargetDir", "/bin/Debug/netcoreapp2.1" }, { "TargetFileName", "TestName.dll" } } }, ProjectContents = folder }, AssemblyReferences = new ReferenceProvider().GetReferencedAssemblies() }; var reporterMock = new Mock <IReporter>(MockBehavior.Strict); reporterMock.Setup(x => x.OnMutantTested(It.IsAny <Mutant>())); reporterMock.Setup(x => x.OnAllMutantsTested(It.IsAny <ReadOnlyProjectComponent>())); reporterMock.Setup(x => x.OnStartMutantTestRun(It.IsAny <IList <Mutant> >(), It.IsAny <IEnumerable <TestDescription> >())); var runnerMock = new Mock <ITestRunner>(); runnerMock.Setup(x => x.DiscoverNumberOfTests()).Returns(1); var executorMock = new Mock <IMutationTestExecutor>(MockBehavior.Strict); executorMock.SetupGet(x => x.TestRunner).Returns(runnerMock.Object); executorMock.Setup(x => x.Test(It.IsAny <IList <Mutant> >(), It.IsAny <int>(), It.IsAny <TestUpdateHandler>())); var mutantFilterMock = new Mock <IMutantFilter>(MockBehavior.Loose); var options = new StrykerOptions(fileSystem: new MockFileSystem(), basePath: basePath); var target = new MutationTestProcess(input, reporterMock.Object, executorMock.Object, mutantFilter: mutantFilterMock.Object, options: options); target.Test(options); reporterMock.Verify(x => x.OnStartMutantTestRun(It.Is <IList <Mutant> >(y => y.Count == 1), It.IsAny <IEnumerable <TestDescription> >()), Times.Once); executorMock.Verify(x => x.Test(new List <Mutant> { otherMutant }, It.IsAny <int>(), It.IsAny <TestUpdateHandler>()), Times.Once); reporterMock.Verify(x => x.OnAllMutantsTested(It.IsAny <ReadOnlyProjectComponent>()), Times.Once); }
public void JsonReportComponent_ShouldGenerateFileTreeForJsonSerialization() { var tree = CSharpSyntaxTree.ParseText("void M(){ int i = 0 + 8; }"); var originalNode = tree.GetRoot().DescendantNodes().OfType <BinaryExpressionSyntax>().First(); var mutation = new Mutation() { OriginalNode = originalNode, ReplacementNode = SyntaxFactory.BinaryExpression(SyntaxKind.SubtractExpression, originalNode.Left, originalNode.Right), DisplayName = "This name should display", Type = MutatorType.Arithmetic }; var folder = new FolderComposite() { Name = "RootFolder" }; folder.Add(new FileLeaf() { Name = "SomeFile.cs", Mutants = new Collection <Mutant>() { new Mutant() { Id = 55, ResultStatus = MutantStatus.Killed, Mutation = mutation } }, SourceCode = "void M(){ int i = 0 + 8; }" }); folder.Add(new FileLeaf() { Name = "SomeOtherFile.cs", Mutants = new Collection <Mutant>() { new Mutant() { Id = 56, ResultStatus = MutantStatus.Survived, Mutation = mutation } }, SourceCode = "void M(){ int i = 0 + 8; }" }); folder.Add(new FileLeaf() { Name = "SomeOtherFile.cs", Mutants = new Collection <Mutant>() { new Mutant() { Id = 56, ResultStatus = MutantStatus.Skipped, Mutation = mutation } }, SourceCode = "void M(){ int i = 0 + 8; }" }); var result = JsonReportComponent.FromProjectComponent(folder, new ThresholdOptions(80, 60, 0)); ValidateJsonReportComponent(result, folder, "warning"); ValidateJsonReportComponent(result.ChildResults.ElementAt(0), folder.Children.ElementAt(0), "ok", 1); ValidateJsonReportComponent(result.ChildResults.ElementAt(1), folder.Children.ElementAt(1), "danger", 1); }
public void ReportComponent_ShouldCalculateMutationScore_Recursive2() { var target = new FolderComposite() { Name = "RootFolder" }; var subFolder = new FolderComposite() { Name = "SubFolder" }; target.Add(new FileLeaf() { Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = MutantStatus.Survived } } }); target.Add(new FileLeaf() { Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = MutantStatus.Survived } } }); target.Add(subFolder); subFolder.Add(new FileLeaf() { Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = MutantStatus.Survived }, new Mutant() { ResultStatus = MutantStatus.Killed } } }); subFolder.Add(new FileLeaf() { Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = MutantStatus.Killed }, new Mutant() { ResultStatus = MutantStatus.Killed } } }); subFolder.Add(new FileLeaf() { Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = MutantStatus.Survived }, new Mutant() { ResultStatus = MutantStatus.Killed } } }); subFolder.Add(new FileLeaf() { Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = MutantStatus.Killed }, new Mutant() { ResultStatus = MutantStatus.Killed } } }); subFolder.Add(new FileLeaf() { Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = MutantStatus.Killed }, new Mutant() { ResultStatus = MutantStatus.Killed } } }); var result = target.GetMutationScore(); result.ShouldBe(66.66666666666666666666666667M); }
public void ShouldNotTest_WhenThereAreNoTestableMutations() { var mutant = new Mutant() { Id = 1, ResultStatus = MutantStatus.Ignored }; var mutant2 = new Mutant() { Id = 2, ResultStatus = MutantStatus.CompileError }; string basePath = Path.Combine(FilesystemRoot, "ExampleProject.Test"); var folder = new FolderComposite() { Name = "ProjectRoot" }; folder.Add(new FileLeaf() { Name = "SomeFile.cs", Mutants = new Collection <Mutant>() { mutant, mutant2 } }); var input = new MutationTestInput() { ProjectInfo = new ProjectInfo() { ProjectContents = folder }, AssemblyReferences = _assemblies }; var reporterMock = new Mock <IReporter>(MockBehavior.Strict); reporterMock.Setup(x => x.OnMutantTested(It.IsAny <Mutant>())); reporterMock.Setup(x => x.OnAllMutantsTested(It.IsAny <ReadOnlyProjectComponent>())); reporterMock.Setup(x => x.OnStartMutantTestRun(It.IsAny <IList <Mutant> >(), It.IsAny <IEnumerable <TestDescription> >())); var runnerMock = new Mock <ITestRunner>(); runnerMock.Setup(x => x.DiscoverNumberOfTests()).Returns(1); var executorMock = new Mock <IMutationTestExecutor>(MockBehavior.Strict); executorMock.SetupGet(x => x.TestRunner).Returns(runnerMock.Object); executorMock.Setup(x => x.Test(It.IsAny <IList <Mutant> >(), It.IsAny <int>(), It.IsAny <TestUpdateHandler>())); var mutantFilterMock = new Mock <IMutantFilter>(MockBehavior.Loose); var options = new StrykerOptions(fileSystem: new MockFileSystem(), basePath: basePath); var target = new MutationTestProcess(input, reporterMock.Object, executorMock.Object, mutantFilter: mutantFilterMock.Object, options: options); var testResult = target.Test(options); executorMock.Verify(x => x.Test(It.IsAny <IList <Mutant> >(), It.IsAny <int>(), It.IsAny <TestUpdateHandler>()), Times.Never); reporterMock.Verify(x => x.OnStartMutantTestRun(It.IsAny <IList <Mutant> >(), It.IsAny <IEnumerable <TestDescription> >()), Times.Never); reporterMock.Verify(x => x.OnMutantTested(It.IsAny <Mutant>()), Times.Never); reporterMock.Verify(x => x.OnAllMutantsTested(It.IsAny <ReadOnlyProjectComponent>()), Times.Once); testResult.MutationScore.ShouldBe(double.NaN); }
// initialize the test context and mock objects public VsTestRunnersShould() { var currentDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); var filesystemRoot = Path.GetPathRoot(currentDirectory); var sourceFile = File.ReadAllText(currentDirectory + "/TestResources/ExampleSourceFile.cs"); var testProjectPath = FilePathUtils.NormalizePathSeparators(Path.Combine(filesystemRoot, "TestProject", "TestProject.csproj")); var projectUnderTestPath = FilePathUtils.NormalizePathSeparators(Path.Combine(filesystemRoot, "ExampleProject", "ExampleProject.csproj")); const string defaultTestProjectFileContents = @"<Project Sdk=""Microsoft.NET.Sdk""> <PropertyGroup> <TargetFramework>netcoreapp2.0</TargetFramework> <IsPackable>false</IsPackable> </PropertyGroup> <ItemGroup> <PackageReference Include=""Microsoft.NET.Test.Sdk"" Version = ""15.5.0"" /> <PackageReference Include=""xunit"" Version=""2.3.1"" /> <PackageReference Include=""xunit.runner.visualstudio"" Version=""2.3.1"" /> <DotNetCliToolReference Include=""dotnet-xunit"" Version=""2.3.1"" /> </ItemGroup> <ItemGroup> <ProjectReference Include=""..\ExampleProject\ExampleProject.csproj"" /> </ItemGroup> </Project>"; _testAssemblyPath = Path.Combine(filesystemRoot, "_firstTest", "bin", "Debug", "TestApp.dll"); _executorUri = new Uri("exec://nunit"); var firstTest = new TestCase("T0", _executorUri, _testAssemblyPath); var secondTest = new TestCase("T1", _executorUri, _testAssemblyPath); var content = new FolderComposite(); _coverageProperty = TestProperty.Register("Stryker.Coverage", "Coverage", typeof(string), typeof(TestResult)); _mutant = new Mutant { Id = 0 }; _otherMutant = new Mutant { Id = 1 }; _projectContents = content; _projectContents.Add(new FileLeaf { Mutants = new[] { _otherMutant, _mutant } }); _targetProject = new ProjectInfo() { TestProjectAnalyzerResults = new List <IAnalyzerResult> { TestHelper.SetupProjectAnalyzerResult( properties: new Dictionary <string, string>() { { "TargetDir", Path.GetDirectoryName(_testAssemblyPath) }, { "TargetFileName", Path.GetFileName(_testAssemblyPath) } }, targetFramework: "toto").Object }, ProjectUnderTestAnalyzerResult = TestHelper.SetupProjectAnalyzerResult( properties: new Dictionary <string, string>() { { "TargetDir", Path.Combine(filesystemRoot, "app", "bin", "Debug") }, { "TargetFileName", "AppToTest.dll" } }).Object, ProjectContents = _projectContents }; //CodeInjection.HelperNamespace = "Stryker.Core.UnitTest.TestRunners"; _fileSystem = new MockFileSystem(new Dictionary <string, MockFileData> { { projectUnderTestPath, new MockFileData(defaultTestProjectFileContents) }, { Path.Combine(filesystemRoot, "ExampleProject", "Recursive.cs"), new MockFileData(sourceFile) }, { Path.Combine(filesystemRoot, "ExampleProject", "OneFolderDeeper", "Recursive.cs"), new MockFileData(sourceFile) }, { testProjectPath, new MockFileData(defaultTestProjectFileContents) }, { _testAssemblyPath, new MockFileData("Bytecode") }, { Path.Combine(filesystemRoot, "app", "bin", "Debug", "AppToTest.dll"), new MockFileData("Bytecode") }, }); _testCases = new List <TestCase> { firstTest, secondTest }; }
public void JsonReportComponent_ShouldGenerateFileTreeForJsonSerialization() { var tree = CSharpSyntaxTree.ParseText("void M(){ int i = 0 + 8; }"); var originalNode = tree.GetRoot().DescendantNodes().OfType <BinaryExpressionSyntax>().First(); var mutation = new Mutation() { OriginalNode = originalNode, ReplacementNode = SyntaxFactory.BinaryExpression(SyntaxKind.SubtractExpression, originalNode.Left, originalNode.Right), DisplayName = "This name should display", Type = Mutator.Arithmetic }; var folder = new FolderComposite() { Name = "RootFolder" }; folder.Add(new FileLeaf() { Name = "SomeFile.cs", Mutants = new Collection <Mutant>() { new Mutant() { Id = 55, ResultStatus = MutantStatus.Killed, Mutation = mutation } }, SourceCode = "void M(){ int i = 0 + 8; }" }); folder.Add(new FileLeaf() { Name = "SomeOtherFile.cs", Mutants = new Collection <Mutant>() { new Mutant() { Id = 56, ResultStatus = MutantStatus.Survived, Mutation = mutation } }, SourceCode = "void M(){ int i = 0 + 8; }" }); folder.Add(new FileLeaf() { Name = "SomeOtherFile.cs", Mutants = new Collection <Mutant>() { new Mutant() { Id = 56, ResultStatus = MutantStatus.Skipped, Mutation = mutation } }, SourceCode = "void M(){ int i = 0 + 8; }" }); var result = JsonReporter.JsonReportComponent.FromProjectComponent(folder, new StrykerOptions(thresholdBreak: 0, thresholdHigh: 80, thresholdLow: 60)); }