public void ReportComponent_ShouldCalculateMutationScore_TwoFolders() { var target = new CsharpFolderComposite() { Name = "RootFolder" }; target.Add(new CsharpFileLeaf() { Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = MutantStatus.Killed } } }); target.Add(new CsharpFileLeaf() { Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = MutantStatus.Survived } } }); var result = target.GetMutationScore(); result.ShouldBe(0.5); }
/// <summary> /// Recursively scans the given directory for files to mutate /// </summary> private CsharpFolderComposite FindInputFiles(string path, string projectUnderTestDir, string parentFolder, CSharpParseOptions cSharpParseOptions) { var lastPathComponent = Path.GetFileName(path); var folderComposite = new CsharpFolderComposite { Name = lastPathComponent, FullPath = Path.GetFullPath(path), RelativePath = Path.Combine(parentFolder, lastPathComponent), RelativePathToProjectFile = Path.GetRelativePath(projectUnderTestDir, Path.GetFullPath(path)) }; foreach (var folder in _fileSystem.Directory.EnumerateDirectories(folderComposite.FullPath).Where(x => !_foldersToExclude.Contains(Path.GetFileName(x)))) { folderComposite.Add(FindInputFiles(folder, projectUnderTestDir, folderComposite.RelativePath, cSharpParseOptions)); } foreach (var file in _fileSystem.Directory.GetFiles(folderComposite.FullPath, "*.cs", SearchOption.TopDirectoryOnly).Where(f => !f.EndsWith(".xaml.cs"))) { // Roslyn cannot compile xaml.cs files generated by xamarin. // Since the files are generated they should not be mutated anyway, so skip these files. var fileName = Path.GetFileName(file); var fileLeaf = new CsharpFileLeaf() { SourceCode = _fileSystem.File.ReadAllText(file), Name = _fileSystem.Path.GetFileName(file), RelativePath = Path.Combine(folderComposite.RelativePath, fileName), FullPath = file, RelativePathToProjectFile = Path.GetRelativePath(projectUnderTestDir, file) }; // Get the syntax tree for the source file var syntaxTree = CSharpSyntaxTree.ParseText(fileLeaf.SourceCode, path: fileLeaf.FullPath, options: cSharpParseOptions); // don't mutate auto generated code if (syntaxTree.IsGenerated()) { _logger.LogDebug("Skipping auto-generated code file: {fileName}", fileLeaf.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 } fileLeaf.SyntaxTree = syntaxTree; folderComposite.Add(fileLeaf); } return(folderComposite); }
public void ClearTextTreeReporter_ShouldPrintOnReportDone() { var textWriter = new StringWriter(); var target = new ClearTextTreeReporter(new StrykerOptions(), textWriter); var folder = new CsharpFolderComposite() { RelativePath = "RootFolder", FullPath = "C://RootFolder", }; folder.Add(new CsharpFileLeaf() { RelativePath = "RootFolder/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 All files [0/0 (N/A)] └── SomeFile.cs [0/0 (N/A)] "); textWriter.DarkGraySpanCount().ShouldBe(2); }
public void ClearTextReporter_ShouldPrintYellowBetweenThresholdLowAndThresholdBreak() { 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 options = new StrykerOptions { Thresholds = new Thresholds { High = 90, Low = 70, Break = 0 } }; var target = new ClearTextReporter(options, textWriter); var folder = new CsharpFolderComposite() { RelativePath = "RootFolder", FullPath = "C://RootFolder", }; folder.Add(new CsharpFileLeaf() { 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); textWriter.YellowSpanCount().ShouldBe(2); }
public void Stryker_ShouldInvokeAllProcesses() { var projectOrchestratorMock = new Mock <IProjectOrchestrator>(MockBehavior.Strict); var mutationTestProcessMock = new Mock <IMutationTestProcess>(MockBehavior.Strict); var reporterFactoryMock = new Mock <IReporterFactory>(MockBehavior.Strict); var reporterMock = new Mock <IReporter>(MockBehavior.Strict); var fileSystemMock = new MockFileSystem(); var folder = new CsharpFolderComposite { Name = "ProjectRoot" }; folder.Add(new CsharpFileLeaf() { Name = "SomeFile.cs", Mutants = new List <Mutant> { new Mutant { Id = 1 } } }); var mutationTestInput = new MutationTestInput() { ProjectInfo = new ProjectInfo() { ProjectContents = folder }, }; var options = new StrykerOptions(basePath: "c:/test", fileSystem: fileSystemMock); projectOrchestratorMock.Setup(x => x.MutateProjects(options, It.IsAny <IReporter>())) .Returns(new List <IMutationTestProcess>() { mutationTestProcessMock.Object }); reporterFactoryMock.Setup(x => x.Create(It.IsAny <StrykerOptions>(), It.IsAny <IGitInfoProvider>())).Returns(reporterMock.Object); reporterMock.Setup(x => x.OnMutantsCreated(It.IsAny <IReadOnlyProjectComponent>())); reporterMock.Setup(x => x.OnStartMutantTestRun(It.IsAny <IEnumerable <IReadOnlyMutant> >())); reporterMock.Setup(x => x.OnAllMutantsTested(It.IsAny <IReadOnlyProjectComponent>())); mutationTestProcessMock.SetupGet(x => x.Input).Returns(mutationTestInput); mutationTestProcessMock.Setup(x => x.GetCoverage()); mutationTestProcessMock.Setup(x => x.Test(It.IsAny <IEnumerable <Mutant> >())) .Returns(new StrykerRunResult(It.IsAny <StrykerOptions>(), It.IsAny <double>())); var target = new StrykerRunner(projectOrchestratorMock.Object, reporterFactory: reporterFactoryMock.Object); target.RunMutationTest(options); projectOrchestratorMock.Verify(x => x.MutateProjects(options, It.IsAny <IReporter>()), Times.Once); mutationTestProcessMock.Verify(x => x.GetCoverage(), Times.Once); mutationTestProcessMock.Verify(x => x.Test(It.IsAny <IEnumerable <Mutant> >()), Times.Once); reporterMock.Verify(x => x.OnMutantsCreated(It.IsAny <IReadOnlyProjectComponent>()), Times.Once); reporterMock.Verify(x => x.OnStartMutantTestRun(It.IsAny <IEnumerable <IReadOnlyMutant> >()), Times.Once); reporterMock.Verify(x => x.OnAllMutantsTested(It.IsAny <IReadOnlyProjectComponent>()), Times.Once); }
public void ShouldNotTest_WhenThereAreNoTestableMutations() { string basePath = Path.Combine(FilesystemRoot, "ExampleProject.Test"); var folder = new CsharpFolderComposite() { Name = "ProjectRoot" }; folder.Add(new CsharpFileLeaf() { Name = "SomeFile.cs", Mutants = new Collection <Mutant>() { } }); var projectUnderTest = TestHelper.SetupProjectAnalyzerResult( properties: new Dictionary <string, string>() { { "Language", "F#" } }).Object; var input = new MutationTestInput() { ProjectInfo = new ProjectInfo() { ProjectContents = folder, ProjectUnderTestAnalyzerResult = projectUnderTest }, 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(fileSystem: new MockFileSystem(), basePath: basePath); var target = new MutationTestProcess(input, reporterMock.Object, executorMock.Object, mutantFilter: mutantFilterMock.Object, options: options); var testResult = target.Test(folder.Mutants); executorMock.Verify(x => x.Test(It.IsAny <IList <Mutant> >(), It.IsAny <int>(), It.IsAny <TestUpdateHandler>()), Times.Never); reporterMock.Verify(x => x.OnMutantTested(It.IsAny <Mutant>()), Times.Never); testResult.MutationScore.ShouldBe(double.NaN); }
public void InitialisationProcess_ShouldCallNeededResolvers() { var testRunnerMock = new Mock <ITestRunner>(MockBehavior.Strict); var inputFileResolverMock = new Mock <IInputFileResolver>(MockBehavior.Strict); var initialBuildProcessMock = new Mock <IInitialBuildProcess>(MockBehavior.Strict); var initialTestProcessMock = new Mock <IInitialTestProcess>(MockBehavior.Strict); var assemblyReferenceResolverMock = new Mock <IAssemblyReferenceResolver>(MockBehavior.Strict); testRunnerMock.Setup(x => x.RunAll(It.IsAny <int>(), null, null)) .Returns(new TestRunResult(true)); // testrun is successful testRunnerMock.Setup(x => x.DiscoverNumberOfTests()).Returns(999); testRunnerMock.Setup(x => x.Dispose()); var projectContents = new CsharpFolderComposite(); projectContents.Add(new CsharpFileLeaf { Name = "SomeFile.cs" }); var folder = new CsharpFolderComposite { Name = "ProjectRoot" }; folder.AddRange(new Collection <IProjectComponent> { new CsharpFileLeaf { Name = "SomeFile.cs" } }); inputFileResolverMock.Setup(x => x.ResolveInput(It.IsAny <IStrykerOptions>())) .Returns(new ProjectInfo { ProjectUnderTestAnalyzerResult = TestHelper.SetupProjectAnalyzerResult( references: new string[0]).Object, TestProjectAnalyzerResults = new List <IAnalyzerResult> { TestHelper.SetupProjectAnalyzerResult( projectFilePath: "C://Example/Dir/ProjectFolder").Object }, ProjectContents = folder }); initialTestProcessMock.Setup(x => x.InitialTest(It.IsAny <ITestRunner>())).Returns(999); initialBuildProcessMock.Setup(x => x.InitialBuild(It.IsAny <bool>(), It.IsAny <string>(), It.IsAny <string>())); assemblyReferenceResolverMock.Setup(x => x.LoadProjectReferences(It.IsAny <string[]>())) .Returns(Enumerable.Empty <PortableExecutableReference>()); var target = new InitialisationProcess( inputFileResolverMock.Object, initialBuildProcessMock.Object, initialTestProcessMock.Object, testRunnerMock.Object, assemblyReferenceResolverMock.Object); var options = new StrykerOptions(); var result = target.Initialize(options); inputFileResolverMock.Verify(x => x.ResolveInput(It.IsAny <IStrykerOptions>()), Times.Once); }
public void ReportComponent_ShouldCalculateMutationScore_Recursive() { var target = new CsharpFolderComposite(); var subFolder = new CsharpFolderComposite(); target.Add(new CsharpFileLeaf() { Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = MutantStatus.Killed } } }); target.Add(new CsharpFileLeaf() { Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = MutantStatus.Survived } } }); target.Add(subFolder); subFolder.Add(new CsharpFileLeaf() { Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = MutantStatus.Survived }, new Mutant() { ResultStatus = MutantStatus.Killed } } }); var result = target.GetMutationScore(); result.ShouldBe(0.5); }
public void ShouldStop_WhenAllMutationsWereIgnored() { var projectOrchestratorMock = new Mock <IProjectOrchestrator>(MockBehavior.Strict); var mutationTestProcessMock = new Mock <IMutationTestProcess>(MockBehavior.Strict); var reporterFactoryMock = new Mock <IReporterFactory>(MockBehavior.Strict); var reporterMock = new Mock <IReporter>(MockBehavior.Strict); var fileSystemMock = new MockFileSystem(); var folder = new CsharpFolderComposite() { Name = "ProjectRoot" }; folder.Add(new CsharpFileLeaf { Name = "SomeFile.cs", Mutants = new Collection <Mutant>() { new Mutant() { Id = 1, ResultStatus = MutantStatus.Ignored } } }); var mutationTestInput = new MutationTestInput() { ProjectInfo = new ProjectInfo() { ProjectContents = folder } }; var options = new StrykerOptions(basePath: "c:/test", fileSystem: fileSystemMock, coverageAnalysis: "off"); projectOrchestratorMock.Setup(x => x.MutateProjects(options, It.IsAny <IReporter>())) .Returns(new List <IMutationTestProcess>() { mutationTestProcessMock.Object }); mutationTestProcessMock.SetupGet(x => x.Input).Returns(mutationTestInput); reporterFactoryMock.Setup(x => x.Create(It.IsAny <StrykerOptions>(), It.IsAny <IGitInfoProvider>())).Returns(reporterMock.Object); reporterMock.Setup(x => x.OnMutantsCreated(It.IsAny <IReadOnlyProjectComponent>())); reporterMock.Setup(x => x.OnStartMutantTestRun(It.IsAny <IEnumerable <IReadOnlyMutant> >())); var target = new StrykerRunner(projectOrchestratorMock.Object, reporterFactory: reporterFactoryMock.Object); var result = target.RunMutationTest(options); result.MutationScore.ShouldBe(double.NaN); reporterMock.Verify(x => x.OnStartMutantTestRun(It.IsAny <IList <Mutant> >()), Times.Never); reporterMock.Verify(x => x.OnMutantTested(It.IsAny <Mutant>()), Times.Never); reporterMock.Verify(x => x.OnAllMutantsTested(It.IsAny <IReadOnlyProjectComponent>()), Times.Never); }
public void InitialisationProcess_ShouldCallNeededResolvers() { var testRunnerMock = new Mock <ITestRunner>(MockBehavior.Strict); var inputFileResolverMock = new Mock <IInputFileResolver>(MockBehavior.Strict); var initialBuildProcessMock = new Mock <IInitialBuildProcess>(MockBehavior.Strict); var initialTestProcessMock = new Mock <IInitialTestProcess>(MockBehavior.Strict); var assemblyReferenceResolverMock = new Mock <IAssemblyReferenceResolver>(MockBehavior.Strict); testRunnerMock.Setup(x => x.RunAll(It.IsAny <ITimeoutValueCalculator>(), null, null)) .Returns(new TestRunResult(true)); // testrun is successful testRunnerMock.Setup(x => x.DiscoverTests()).Returns(new TestSet()); testRunnerMock.Setup(x => x.Dispose()); var projectContents = new CsharpFolderComposite(); projectContents.Add(new CsharpFileLeaf()); var folder = new CsharpFolderComposite(); folder.AddRange(new Collection <IProjectComponent> { new CsharpFileLeaf() }); inputFileResolverMock.Setup(x => x.ResolveInput(It.IsAny <StrykerOptions>())) .Returns(new ProjectInfo(new MockFileSystem()) { ProjectUnderTestAnalyzerResult = TestHelper.SetupProjectAnalyzerResult( references: new string[0]).Object, TestProjectAnalyzerResults = new List <IAnalyzerResult> { TestHelper.SetupProjectAnalyzerResult( projectFilePath: "C://Example/Dir/ProjectFolder", targetFramework: "netcoreapp2.1").Object }, ProjectContents = folder }); initialTestProcessMock.Setup(x => x.InitialTest(It.IsAny <StrykerOptions>(), It.IsAny <ITestRunner>())).Returns(new InitialTestRun(new TestRunResult(true), new TimeoutValueCalculator(1))); initialBuildProcessMock.Setup(x => x.InitialBuild(It.IsAny <bool>(), It.IsAny <string>(), It.IsAny <string>(), null)); assemblyReferenceResolverMock.Setup(x => x.LoadProjectReferences(It.IsAny <string[]>())) .Returns(Enumerable.Empty <PortableExecutableReference>()); var target = new InitialisationProcess( inputFileResolverMock.Object, initialBuildProcessMock.Object, initialTestProcessMock.Object, testRunnerMock.Object, assemblyReferenceResolverMock.Object); var options = new StrykerOptions { ProjectName = "TheProjectName", ProjectVersion = "TheProjectVersion" }; var result = target.Initialize(options); inputFileResolverMock.Verify(x => x.ResolveInput(It.IsAny <StrykerOptions>()), Times.Once); }
public void ShouldNotTest_WhenThereAreNoMutationsAtAll() { string basePath = Path.Combine(FilesystemRoot, "ExampleProject.Test"); var scenario = new FullRunScenario(); var folder = new CsharpFolderComposite(); folder.Add(new CsharpFileLeaf() { Mutants = scenario.GetMutants() }); var projectUnderTest = TestHelper.SetupProjectAnalyzerResult( properties: new Dictionary <string, string>() { { "Language", "C#" } }).Object; var input = new MutationTestInput() { ProjectInfo = new ProjectInfo(new MockFileSystem()) { ProjectContents = folder, ProjectUnderTestAnalyzerResult = projectUnderTest }, AssemblyReferences = _assemblies }; var executorMock = new Mock <IMutationTestExecutor>(MockBehavior.Strict); executorMock.SetupGet(x => x.TestRunner).Returns(scenario.GetTestRunnerMock().Object); executorMock.Setup(x => x.Test(It.IsAny <IList <Mutant> >(), It.IsAny <ITimeoutValueCalculator>(), It.IsAny <TestUpdateHandler>())); var mutantFilterMock = new Mock <IMutantFilter>(MockBehavior.Loose); var options = new StrykerOptions() { BasePath = basePath }; var reporterMock = new Mock <IReporter>(MockBehavior.Strict); reporterMock.Setup(x => x.OnMutantTested(It.IsAny <Mutant>())); var target = new MutationTestProcess(input, reporterMock.Object, executorMock.Object, mutantFilter: mutantFilterMock.Object, options: options); var testResult = target.Test(input.ProjectInfo.ProjectContents.Mutants); executorMock.Verify(x => x.Test(It.IsAny <IList <Mutant> >(), It.IsAny <ITimeoutValueCalculator>(), It.IsAny <TestUpdateHandler>()), Times.Never); reporterMock.Verify(x => x.OnStartMutantTestRun(It.IsAny <IList <Mutant> >()), Times.Never); reporterMock.Verify(x => x.OnMutantTested(It.IsAny <Mutant>()), Times.Never); testResult.MutationScore.ShouldBe(double.NaN); }
public void ClearTextReporter_ShouldPrintKilledMutation() { 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 ClearTextReporter(new StrykerOptions(), textWriter); var rootFolder = new CsharpFolderComposite(); var folder = new CsharpFolderComposite() { RelativePath = "FolderA", FullPath = "C://Project/FolderA", }; folder.Add(new CsharpFileLeaf() { RelativePath = "FolderA/SomeFile.cs", FullPath = "C://Project/FolderA/SomeFile.cs", Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = MutantStatus.Killed, Mutation = mutation } } }); rootFolder.Add(folder); target.OnAllMutantsTested(rootFolder); 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 │ {100:N2} │ 1 │ 0 │ 0 │ 0 │ 0 │ │ FolderA/SomeFile.cs │ {100:N2} │ 1 │ 0 │ 0 │ 0 │ 0 │ └─────────────────────┴──────────┴──────────┴───────────┴────────────┴──────────┴─────────┘ "); textWriter.GreenSpanCount().ShouldBe(2); }
public void ShouldPrintEachReasonWithCount() { var target = new FilteredMutantsLogger(_loggerMock.Object); var folder = new CsharpFolderComposite(); folder.Add(new CsharpFileLeaf() { Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = MutantStatus.Ignored, ResultStatusReason = "In excluded file" }, new Mutant() { ResultStatus = MutantStatus.Ignored, ResultStatusReason = "In excluded file" }, new Mutant() { ResultStatus = MutantStatus.Ignored, ResultStatusReason = "Mutator excluded" }, new Mutant() { ResultStatus = MutantStatus.Ignored, ResultStatusReason = "Mutator excluded" }, new Mutant() { ResultStatus = MutantStatus.Ignored, ResultStatusReason = "Mutator excluded" }, new Mutant() { ResultStatus = MutantStatus.CompileError, ResultStatusReason = "CompileError" }, new Mutant() { ResultStatus = MutantStatus.Ignored, ResultStatusReason = "In excluded file" }, new Mutant() { ResultStatus = MutantStatus.NotRun }, } }); target.OnMutantsCreated(folder.ToReadOnlyInputComponent()); _loggerMock.Verify(LogLevel.Information, "1 mutants got status CompileError. Reason: CompileError", Times.Once); _loggerMock.Verify(LogLevel.Information, "3 mutants got status Ignored. Reason: In excluded file", Times.Once); _loggerMock.Verify(LogLevel.Information, "3 mutants got status Ignored. Reason: Mutator excluded", Times.Once); _loggerMock.Verify(LogLevel.Information, "7 total mutants are skipped for the above mentioned reasons", Times.Once); _loggerMock.Verify(LogLevel.Information, "1 total mutants will be tested", Times.Once); _loggerMock.VerifyNoOtherCalls(); }
public static IProjectComponent CreateProjectWith(bool duplicateMutant = false, int mutationScore = 60) { 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 CsharpFolderComposite { FullPath = "/home/user/src/project/", RelativePath = "" }; int mutantCount = 0; for (var i = 1; i <= 2; i++) { var addedFolder = new CsharpFolderComposite { RelativePath = $"{i}", FullPath = $"/home/user/src/project/{i}", }; folder.Add(addedFolder); for (var y = 0; y <= 4; y++) { var m = new Collection <Mutant>(); addedFolder.Add(new CsharpFileLeaf() { RelativePath = $"{i}/SomeFile{y}.cs", FullPath = $"/home/user/src/project/{i}/SomeFile{y}.cs", Mutants = m, SourceCode = "void M(){ int i = 0 + 8; }" }); for (var z = 0; z <= 5; z++) { m.Add(new Mutant() { Id = duplicateMutant ? 2 : ++mutantCount, ResultStatus = 100 / 6 * z < mutationScore ? MutantStatus.Killed : MutantStatus.Survived, Mutation = mutation, CoveringTests = TestsGuidList.EveryTest() }); } } } return(folder); }
public void InitialisationProcess_ShouldThrowOnFailedInitialTestRun() { var testRunnerMock = new Mock <ITestRunner>(MockBehavior.Strict); var inputFileResolverMock = new Mock <IInputFileResolver>(MockBehavior.Strict); var initialBuildProcessMock = new Mock <IInitialBuildProcess>(MockBehavior.Strict); var initialTestProcessMock = new Mock <IInitialTestProcess>(MockBehavior.Strict); var assemblyReferenceResolverMock = new Mock <IAssemblyReferenceResolver>(MockBehavior.Strict); testRunnerMock.Setup(x => x.RunAll(It.IsAny <ITimeoutValueCalculator>(), null, null)); var folder = new CsharpFolderComposite(); folder.Add(new CsharpFileLeaf()); inputFileResolverMock.Setup(x => x.ResolveInput(It.IsAny <StrykerOptions>())).Returns( new ProjectInfo(new MockFileSystem()) { ProjectUnderTestAnalyzerResult = TestHelper.SetupProjectAnalyzerResult( references: new string[0]).Object, TestProjectAnalyzerResults = new List <IAnalyzerResult> { TestHelper.SetupProjectAnalyzerResult( projectFilePath: "C://Example/Dir/ProjectFolder").Object }, ProjectContents = folder }); initialBuildProcessMock.Setup(x => x.InitialBuild(It.IsAny <bool>(), It.IsAny <string>(), It.IsAny <string>(), null)); testRunnerMock.Setup(x => x.DiscoverTests()).Returns(new TestSet()); testRunnerMock.Setup(x => x.Dispose()); initialTestProcessMock.Setup(x => x.InitialTest(It.IsAny <StrykerOptions>(), It.IsAny <ITestRunner>())).Throws(new InputException("")); // failing test assemblyReferenceResolverMock.Setup(x => x.LoadProjectReferences(It.IsAny <string[]>())) .Returns(Enumerable.Empty <PortableExecutableReference>()) .Verifiable(); var target = new InitialisationProcess( inputFileResolverMock.Object, initialBuildProcessMock.Object, initialTestProcessMock.Object, testRunnerMock.Object, assemblyReferenceResolverMock.Object); var options = new StrykerOptions { ProjectName = "TheProjectName", ProjectVersion = "TheProjectVersion" }; target.Initialize(options); Assert.Throws <InputException>(() => target.InitialTest(options)); inputFileResolverMock.Verify(x => x.ResolveInput(It.IsAny <StrykerOptions>()), Times.Once); assemblyReferenceResolverMock.Verify(); initialTestProcessMock.Verify(x => x.InitialTest(It.IsAny <StrykerOptions>(), testRunnerMock.Object), Times.Once); }
public void ClearTextTreeReporter_ShouldPrintSurvivedMutation() { 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 CsharpFolderComposite() { Name = "RootFolder", RelativePath = "RootFolder", FullPath = "C://RootFolder", }; folder.Add(new CsharpFileLeaf() { Name = "SomeFile.cs", RelativePath = "RootFolder/SomeFile.cs", FullPath = "C://RootFolder/SomeFile.cs", Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = MutantStatus.Survived, Mutation = mutation } } }); target.OnAllMutantsTested(folder.ToReadOnly()); textWriter.RemoveAnsi().ShouldBeWithNewlineReplace($@" All mutants have been tested, and your mutation score has been calculated RootFolder [0/1 ({0:P2})] └── SomeFile.cs [0/1 ({0:P2})] └── [Survived] This name should display on line 1 ├── [-] 0 + 8 └── [+] 0 -8 "); // All percentages should be red and the [Survived] too textWriter.RedSpanCount().ShouldBe(3); }
// get the FolderComposite object representing the the project's folder 'targetFolder'. Build the needed FolderComposite(s) for a complete path private CsharpFolderComposite GetOrBuildFolderComposite(IDictionary <string, CsharpFolderComposite> cache, string targetFolder, string projectUnderTestDir, string projectRoot, ProjectComponent <SyntaxTree> inputFiles) { if (cache.ContainsKey(targetFolder)) { return(cache[targetFolder]); } var folder = targetFolder; CsharpFolderComposite subDir = null; while (!string.IsNullOrEmpty(folder)) { if (!cache.ContainsKey(folder)) { // we have not scanned this folder yet var sub = Path.GetFileName(folder); var fullPath = _fileSystem.Path.Combine(projectUnderTestDir, sub); var newComposite = new CsharpFolderComposite { Name = sub, FullPath = fullPath, RelativePath = Path.GetRelativePath(projectRoot, fullPath), RelativePathToProjectFile = Path.GetRelativePath(projectUnderTestDir, fullPath) }; if (subDir != null) { newComposite.Add(subDir); } cache.Add(folder, newComposite); subDir = newComposite; folder = Path.GetDirectoryName(folder); if (string.IsNullOrEmpty(folder)) { // we are at root var root = inputFiles as IFolderComposite; root.Add(subDir); } } else { cache[folder].Add(subDir); break; } } return(cache[targetFolder]); }
public void ReportComponent_ShouldCalculateMutationScore_NoMutations() { var target = new CsharpFolderComposite(); target.Add(new CsharpFileLeaf() { Mutants = new Collection <Mutant>() { } }); var result = target.GetMutationScore(); result.ShouldBe(double.NaN); }
public void ClearTextTreeReporter_ShouldPrintKilledMutation() { 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 console = new TestConsole().EmitAnsiSequences(); var target = new ClearTextTreeReporter(new StrykerOptions(), console); var folder = new CsharpFolderComposite() { RelativePath = "RootFolder", FullPath = "C://RootFolder", }; folder.Add(new CsharpFileLeaf() { RelativePath = "RootFolder/SomeFile.cs", FullPath = "C://RootFolder/SomeFile.cs", Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = MutantStatus.Killed, Mutation = mutation } } }); target.OnAllMutantsTested(folder); console.Output.RemoveAnsi().ShouldBeWithNewlineReplace($@" All mutants have been tested, and your mutation score has been calculated All files [1/1 ({1:P2})] └── SomeFile.cs [1/1 ({1:P2})] └── [Killed] This name should display on line 1 ├── [-] 0 + 8 └── [+] 0 -8 "); console.Output.GreenSpanCount().ShouldBe(3); }
/// <summary> /// Recursively scans the given directory for files to mutate /// Deprecated method, should not be maintained /// </summary> private CsharpFolderComposite FindInputFiles(string path, string projectUnderTestDir, IAnalyzerResult analyzerResult, StrykerOptions options) { var rootFolderComposite = new CsharpFolderComposite { FullPath = Path.GetFullPath(path), RelativePath = Path.GetRelativePath(projectUnderTestDir, Path.GetFullPath(path)) }; CSharpParseOptions cSharpParseOptions = BuildCsharpParseOptions(analyzerResult, options); InjectMutantHelpers(rootFolderComposite, cSharpParseOptions); rootFolderComposite.Add( FindInputFiles(path, Path.GetDirectoryName(analyzerResult.ProjectFilePath), cSharpParseOptions) ); return(rootFolderComposite); }
public void ShouldPrintNoMutations() { var target = new FilteredMutantsLogger(_loggerMock.Object); var folder = new CsharpFolderComposite(); folder.Add(new CsharpFileLeaf() { Mutants = new Collection <Mutant>() { } }); target.OnMutantsCreated(folder.ToReadOnlyInputComponent()); _loggerMock.Verify(LogLevel.Information, "0 total mutants will be tested", Times.Once); _loggerMock.VerifyNoOtherCalls(); }
public void ReportComponent_ShouldCalculateMutationScore_BuildErrorIsNull() { var target = new CsharpFolderComposite(); target.Add(new CsharpFileLeaf() { Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = MutantStatus.CompileError } } }); var result = target.GetMutationScore(); result.ShouldBe(double.NaN); }
public void ReportComponent_ShouldCalculateMutationScore_OneMutation() { var target = new CsharpFolderComposite(); target.Add(new CsharpFileLeaf() { Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = MutantStatus.Killed } } }); var result = target.GetMutationScore(); result.ShouldBe(1); }
public void ReportComponent_ShouldCalculateMutationScore_OnlyKilledIsSuccessful(MutantStatus status, double expectedScore) { var target = new CsharpFolderComposite(); target.Add(new CsharpFileLeaf() { Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = status } } }); var result = target.GetMutationScore(); result.ShouldBe(expectedScore); }
public void ClearTextReporter_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 ClearTextReporter(new StrykerOptions(), textWriter); var folder = new CsharpFolderComposite() { Name = "RootFolder", RelativePath = "RootFolder", FullPath = "C://RootFolder", }; folder.Add(new CsharpFileLeaf() { Name = "SomeFile.cs", RelativePath = "RootFolder/SomeFile.cs", RelativePathToProjectFile = "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(2); }
private CsharpFolderComposite FindProjectFilesScanningProjectFolders(IAnalyzerResult analyzerResult, IStrykerOptions options) { var inputFiles = new CsharpFolderComposite(); 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, analyzerResult, options)); } return(inputFiles); }
public void ClearTextReporter_ShouldPrintOnReportDone() { var textWriter = new StringWriter(); var target = new ClearTextReporter(new StrykerOptions(), textWriter); var rootFolder = new CsharpFolderComposite(); var folder = new CsharpFolderComposite() { RelativePath = "FolderA", FullPath = "C://Project/FolderA", }; folder.Add(new CsharpFileLeaf() { RelativePath = "FolderA/SomeFile.cs", FullPath = "C://Project/FolderA/SomeFile.cs", Mutants = new Collection <Mutant>() { } }); rootFolder.Add(folder); target.OnAllMutantsTested(rootFolder); 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 │ │ FolderA/SomeFile.cs │ N/A │ 0 │ 0 │ 0 │ 0 │ 0 │ └─────────────────────┴──────────┴──────────┴───────────┴────────────┴──────────┴─────────┘ "); textWriter.DarkGraySpanCount().ShouldBe(2); }
public void ShouldPrintIgnoredStatus() { var target = new FilteredMutantsLogger(_loggerMock.Object); var folder = new CsharpFolderComposite(); folder.Add(new CsharpFileLeaf() { Mutants = new Collection <Mutant>() { new Mutant() { ResultStatus = MutantStatus.Ignored, ResultStatusReason = "In excluded file" }, } }); target.OnMutantsCreated(folder); _loggerMock.Verify(LogLevel.Information, "1 mutants got status Ignored. Reason: In excluded file", Times.Once); _loggerMock.Verify(LogLevel.Information, "1 total mutants are skipped for the above mentioned reasons", Times.Once); _loggerMock.Verify(LogLevel.Information, "0 total mutants will be tested", Times.Once); _loggerMock.VerifyNoOtherCalls(); }
public void ShouldCallMutantOrchestratorAndReporter() { var inputFile = new CsharpFileLeaf() { SourceCode = SourceFile, SyntaxTree = CSharpSyntaxTree.ParseText(SourceFile) }; var folder = new CsharpFolderComposite(); folder.Add(inputFile); var input = new MutationTestInput() { ProjectInfo = new ProjectInfo() { ProjectUnderTestAnalyzerResult = TestHelper.SetupProjectAnalyzerResult(properties: new Dictionary <string, string>() { { "TargetDir", "/bin/Debug/netcoreapp2.1" }, { "TargetFileName", "TestName.dll" }, { "AssemblyName", "AssemblyName" }, { "Language", "C#" } }).Object, TestProjectAnalyzerResults = new List <IAnalyzerResult> { TestHelper.SetupProjectAnalyzerResult(properties: new Dictionary <string, string>() { { "TargetDir", "/bin/Debug/netcoreapp2.1" }, { "TargetFileName", "TestName.dll" }, { "AssemblyName", "AssemblyName" }, { "Language", "C#" } }).Object }, 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 <MutantOrchestrator <SyntaxNode> >(MockBehavior.Strict); var reporterMock = new Mock <IReporter>(MockBehavior.Strict); var mutationTestExecutorMock = new Mock <IMutationTestExecutor>(MockBehavior.Strict); var coverageAnalyzerMock = new Mock <ICoverageAnalyser>(MockBehavior.Strict); // setup mocks 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[] { }, fileSystem: new MockFileSystem()); var target = new MutationTestProcess(input, reporterMock.Object, mutationTestExecutorMock.Object, orchestratorMock.Object, fileSystem, new BroadcastMutantFilter(Enumerable.Empty <IMutantFilter>()), coverageAnalyzerMock.Object, options); // start mutation process target.Mutate(); target.FilterMutants(); // verify the right methods were called orchestratorMock.Verify(x => x.Mutate(It.IsAny <SyntaxNode>()), 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 CsharpFolderComposite(); folder.Add(new CsharpFileLeaf() { 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" }, { "Language", "C#" } }).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)); }