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 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 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); }
// initialize the test context and mock objects public VsTestRunnersTest() { 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 = FilePathUtils.NormalizePathSeparators(Path.Combine(filesystemRoot, "_firstTest", "bin", "Debug", "TestApp.dll")); _executorUri = new Uri("exec://nunit"); var firstTest = BuildCase("T0"); var secondTest = BuildCase("T1"); var content = new CsharpFolderComposite(); _fileSystem = new MockFileSystem(new Dictionary <string, MockFileData> { { projectUnderTestPath, new MockFileData(defaultTestProjectFileContents) },
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); }
private static void InjectMutantHelpers(CsharpFolderComposite rootFolderComposite, CSharpParseOptions cSharpParseOptions) { foreach (var(name, code) in CodeInjection.MutantHelpers) { rootFolderComposite.AddCompilationSyntaxTree(CSharpSyntaxTree.ParseText(code, path: name, encoding: Encoding.UTF32, options: cSharpParseOptions)); } }
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 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); }
private CsharpFolderComposite FindProjectFilesUsingBuildalyzer(IAnalyzerResult analyzerResult, StrykerOptions options) { var projectUnderTestDir = Path.GetDirectoryName(analyzerResult.ProjectFilePath); var generatedAssemblyInfo = analyzerResult.AssemblyAttributeFileName(); var projectUnderTestFolderComposite = new CsharpFolderComposite() { FullPath = projectUnderTestDir, RelativePath = null, }; var cache = new Dictionary <string, CsharpFolderComposite> { [string.Empty] = projectUnderTestFolderComposite }; // Save cache in a singleton so we can use it in other parts of the project FolderCompositeCache <CsharpFolderComposite> .Instance.Cache = cache; CSharpParseOptions cSharpParseOptions = BuildCsharpParseOptions(analyzerResult, options); InjectMutantHelpers(projectUnderTestFolderComposite, cSharpParseOptions); foreach (var sourceFile in analyzerResult.SourceFiles) { var relativePath = Path.GetRelativePath(projectUnderTestDir, sourceFile); var folderComposite = GetOrBuildFolderComposite(cache, Path.GetDirectoryName(relativePath), projectUnderTestDir, projectUnderTestFolderComposite); var file = new CsharpFileLeaf() { SourceCode = FileSystem.File.ReadAllText(sourceFile), FullPath = sourceFile, RelativePath = 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.FullPath); 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(projectUnderTestFolderComposite); }
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 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 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 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 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); }
/// <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); }
// 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_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 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); }