示例#1
0
        public void BroadcastReporter_ShouldInvokeAllReportersInList()
        {
            var reporterMock = new Mock <IReporter>(MockBehavior.Strict);

            reporterMock.Setup(x => x.OnAllMutantsTested(It.IsAny <IReadOnlyInputComponent>()));
            reporterMock.Setup(x => x.OnMutantsCreated(It.IsAny <IReadOnlyInputComponent>()));
            reporterMock.Setup(x => x.OnMutantTested(It.IsAny <Mutant>()));

            var exampleInputComponent = new FileLeaf();
            var exampleMutant         = new Mutant();

            var reporters = new Collection <IReporter>()
            {
                reporterMock.Object,
                reporterMock.Object
            };
            var target = new BroadcastReporter(reporters);

            target.OnAllMutantsTested(exampleInputComponent);
            target.OnMutantsCreated(exampleInputComponent);
            target.OnMutantTested(exampleMutant);

            reporterMock.Verify(x => x.OnAllMutantsTested(exampleInputComponent), Times.Exactly(2));
            reporterMock.Verify(x => x.OnMutantsCreated(exampleInputComponent), Times.Exactly(2));
            reporterMock.Verify(x => x.OnMutantTested(exampleMutant), Times.Exactly(2));
        }
示例#2
0
        public void ShouldNotMutateUnchangedFiles()
        {
            var options         = new StrykerOptions(diff: true);
            var dashboardClient = new Mock <IDashboardClient>();
            var diffProvider    = new Mock <IDiffProvider>(MockBehavior.Loose);
            var branchProvider  = new Mock <IGitInfoProvider>();

            string myFile = Path.Combine("C:/test/", "myfile.cs");;

            diffProvider.Setup(x => x.ScanDiff()).Returns(new DiffResult()
            {
                ChangedFiles = new Collection <string>()
            });
            var target = new DiffMutantFilter(options, diffProvider.Object, dashboardClient.Object, branchProvider.Object);
            var file   = new FileLeaf {
                FullPath = myFile
            };

            var mutant = new Mutant();

            var filterResult = target.FilterMutants(new List <Mutant>()
            {
                mutant
            }, file, options);

            filterResult.ShouldBeEmpty();
        }
        public void FilterMutants_should_filter_included_and_excluded_files(
            string[] patterns,
            string filePath,
            int spanStart,
            int spanEnd,
            bool shouldKeepFile)
        {
            // Arrange
            var options = new StrykerOptions(mutate: patterns);
            var file    = new FileLeaf {
                RelativePath = filePath, FullPath = Path.Combine("C:/test/", filePath)
            };

            // Create token with the correct text span
            var syntaxToken = SyntaxFactory.Identifier(
                new SyntaxTriviaList(Enumerable.Range(0, spanStart).Select(x => SyntaxFactory.Space)),
                new string('a', spanEnd - spanStart),
                SyntaxTriviaList.Empty);

            var mutant = new Mutant
            {
                Mutation = new Mutation {
                    OriginalNode = SyntaxFactory.IdentifierName(syntaxToken)
                }
            };

            var sut = new FilePatternMutantFilter();

            // Act
            var result = sut.FilterMutants(new[] { mutant }, file.ToReadOnly(), options);

            // Assert
            result.Contains(mutant).ShouldBe(shouldKeepFile);
        }
        public JsonReportFileComponent(FileLeaf file, ILogger logger = null)
        {
            var log = logger ?? ApplicationLogging.LoggerFactory.CreateLogger <JsonReportFileComponent>();

            Source   = file.SourceCode;
            Language = "cs";
            Mutants  = new HashSet <JsonMutant>(new UniqueJsonMutantComparer());

            foreach (var mutant in file.Mutants)
            {
                var jsonMutant = new JsonMutant
                {
                    Id          = mutant.Id.ToString(),
                    MutatorName = mutant.Mutation.DisplayName,
                    Replacement = mutant.Mutation.ReplacementNode.ToFullString(),
                    Location    = new JsonMutantLocation(mutant.Mutation.OriginalNode.GetLocation().GetMappedLineSpan()),
                    Status      = mutant.ResultStatus.ToString()
                };

                if (!Mutants.Add(jsonMutant))
                {
                    logger.LogWarning(
                        $"Mutant {mutant.Id} was generated twice in file {file.RelativePath}. \n" +
                        $"This should not have happened. Please create an issue at https://github.com/stryker-mutator/stryker-net/issues");
                }
            }
        }
示例#5
0
        public void ShouldMutateAllFilesWhenATestHasBeenChanged()
        {
            string testProjectPath = "C:/MyTests";
            var    options         = new StrykerOptions(diff: false);
            var    diffProvider    = new Mock <IDiffProvider>(MockBehavior.Strict);
            // If a file inside the test project is changed, a test has been changed
            string myTest = Path.Combine(testProjectPath, "myTest.cs");;

            diffProvider.Setup(x => x.ScanDiff()).Returns(new DiffResult()
            {
                ChangedFiles = new Collection <string>()
                {
                    myTest
                }
            });
            var target = new DiffMutantFilter(options, diffProvider.Object);

            // check the diff result for a file not inside the test project
            var file = new FileLeaf {
                FullPath = Path.Combine("C:/NotMyTests", "myfile.cs")
            };

            var mutant = new Mutant();

            var filterResult = target.FilterMutants(new List <Mutant>()
            {
                mutant
            }, file, options);

            filterResult.ShouldContain(mutant);
        }
        public void ShouldOnlyMutateChangedFiles()
        {
            // Arrange
            var options = new StrykerOptions(diff: true);

            var baselineProvider = new Mock <IBaselineProvider>();
            var diffProvider     = new Mock <IDiffProvider>(MockBehavior.Loose);
            var branchProvider   = new Mock <IGitInfoProvider>();

            string myFile = Path.Combine("C:/test/", "myfile.cs");;

            diffProvider.Setup(x => x.ScanDiff()).Returns(new DiffResult()
            {
                ChangedFiles = new Collection <string>()
                {
                    myFile
                }
            });
            var target = new DiffMutantFilter(options, diffProvider.Object, baselineProvider.Object, branchProvider.Object);
            var file   = new FileLeaf {
                FullPath = myFile
            };

            var mutant = new Mutant();

            // Act
            var filterResult = target.FilterMutants(new List <Mutant>()
            {
                mutant
            }, file, options);

            // Assert
            filterResult.ShouldContain(mutant);
        }
示例#7
0
        public IEnumerable <Mutant> FilterMutants(IEnumerable <Mutant> mutants, FileLeaf file, StrykerOptions options)
        {
            var includePattern = options.FilePatterns.Where(x => !x.IsExclude).ToList();
            var excludePattern = options.FilePatterns.Where(x => x.IsExclude).ToList();

            return(mutants.Where(IsMutantIncluded));

            bool IsMutantIncluded(Mutant mutant)
            {
                // Check if the the mutant is included.
                if (!includePattern.Any(MatchesPattern))
                {
                    return(false);
                }

                // Check if the mutant is excluded.
                if (excludePattern.Any(MatchesPattern))
                {
                    return(false);
                }

                return(true);

                bool MatchesPattern(FilePattern pattern)
                {
                    // We check both the full and the relative path to allow for relative paths.
                    return(pattern.IsMatch(file.FullPath, mutant.Mutation.OriginalNode.Span) ||
                           pattern.IsMatch(file.RelativePathToProjectFile, mutant.Mutation.OriginalNode.Span));
                }
            }
        }
示例#8
0
        public void ShouldGet50MutationScore()
        {
            var file = new FileLeaf()
            {
                Name         = "SomeFile.cs",
                RelativePath = "RootFolder/SomeFile.cs",
                FullPath     = "C://RootFolder/SomeFile.cs",
                Mutants      = new Collection <Mutant>()
                {
                    new Mutant()
                    {
                        ResultStatus = MutantStatus.Survived
                    },
                    new Mutant()
                    {
                        ResultStatus = MutantStatus.Killed
                    },
                }
            };

            file.GetMutationScore().ShouldBe(0.5);
            file.CheckHealth(new Threshold(high: 80, low: 60, @break: 0)).ShouldBe(Health.Danger);
            file.CheckHealth(new Threshold(high: 80, low: 50, @break: 0)).ShouldBe(Health.Warning);
            file.CheckHealth(new Threshold(high: 50, low: 49, @break: 0)).ShouldBe(Health.Good);
        }
        /// <inheritdoc />
        public IEnumerable <Mutant> FilterMutants(IEnumerable <Mutant> mutants, FileLeaf file, StrykerOptions options)
        {
            if (file.IsExcluded)
            {
                return(Enumerable.Empty <Mutant>());
            }

            return(mutants);
        }
        /// <inheritdoc />
        public IEnumerable <Mutant> FilterMutants(IEnumerable <Mutant> mutants, FileLeaf file, StrykerOptions options)
        {
            if (!options.IgnoredMethods.Any())
            {
                return(mutants);
            }

            return(mutants.Where(m => !IsPartOfIgnoredMethodCall(m.Mutation.OriginalNode, options)));
        }
        /// <summary>
        /// Recursively scans the given directory for files to mutate
        /// </summary>
        private FolderComposite FindInputFiles(string path, string projectUnderTestDir, string parentFolder, CSharpParseOptions cSharpParseOptions)
        {
            var lastPathComponent = Path.GetFileName(path);

            var folderComposite = new FolderComposite
            {
                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))
            {
                // Roslyn cannot compile xaml.cs files generated by xamarin.
                // Since the files are generated they should not be mutated anyway, so skip these files.
                if (!file.EndsWith(".xaml.cs"))
                {
                    var fileName = Path.GetFileName(file);

                    var fileLeaf = new FileLeaf()
                    {
                        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);
        }
示例#12
0
 public IEnumerable <Mutant> FilterMutants(IEnumerable <Mutant> mutants, FileLeaf file, StrykerOptions options)
 {
     if (options.DiffEnabled && !_diffResult.TestsChanged)
     {
         if (_diffResult.ChangedFiles.Contains(file.FullPath))
         {
             return(mutants);
         }
         return(Enumerable.Empty <Mutant>());
     }
     return(mutants);
 }
示例#13
0
        public void Stryker_ShouldInvokeAllProcesses()
        {
            var initialisationMock      = new Mock <IInitialisationProcess>(MockBehavior.Strict);
            var mutationTestProcessMock = new Mock <IMutationTestProcess>(MockBehavior.Strict);
            var fileSystemMock          = new MockFileSystem();
            var reporterMock            = new Mock <IReporter>(MockBehavior.Loose);

            var folder = new FolderComposite()
            {
                Name = "ProjectRoot"
            };
            var file = new FileLeaf()
            {
                Name    = "SomeFile.cs",
                Mutants = new List <Mutant> {
                    new Mutant {
                        Id = 1
                    }
                }
            };

            folder.Add(file);

            var mutationTestInput = new MutationTestInput()
            {
                ProjectInfo = new ProjectInfo()
                {
                    ProjectContents = folder
                },
            };

            initialisationMock.Setup(x => x.Initialize(It.IsAny <StrykerOptions>())).Returns(mutationTestInput);
            var options = new StrykerOptions(basePath: "c:/test", fileSystem: fileSystemMock);
            var nbTests = 0;

            initialisationMock.Setup(x => x.InitialTest(options, out nbTests)).Returns(0);

            mutationTestProcessMock.Setup(x => x.Mutate());
            mutationTestProcessMock.Setup(x => x.GetCoverage());
            mutationTestProcessMock.Setup(x => x.FilterMutants());
            mutationTestProcessMock.Setup(x => x.Test(It.IsAny <StrykerOptions>()))
            .Returns(new StrykerRunResult(It.IsAny <StrykerOptions>(), It.IsAny <double>()));



            var target = new StrykerRunner(initialisationMock.Object, mutationTestProcessMock.Object, reporter: reporterMock.Object);

            target.RunMutationTest(options);

            initialisationMock.Verify(x => x.Initialize(It.IsAny <StrykerOptions>()), Times.Once);
            mutationTestProcessMock.Verify(x => x.Mutate(), Times.Once);
            mutationTestProcessMock.Verify(x => x.Test(It.IsAny <StrykerOptions>()), Times.Once);
        }
示例#14
0
        public void BroadcastReporter_NoReportersInList()
        {
            var reporters = new Collection <IReporter>()
            {
            };

            var exampleInputComponent = new FileLeaf();
            var exampleMutant         = new Mutant();

            var target = new BroadcastReporter(reporters);

            target.OnAllMutantsTested(exampleInputComponent);
            target.OnMutantsCreated(exampleInputComponent);
            target.OnMutantTested(exampleMutant);
        }
        public void ShouldNotFilterMutantsWhereCoveringTestsContainsChangedTestFile()
        {
            // Arrange
            string testProjectPath = "C:/MyTests";
            var    options         = new StrykerOptions(diff: false);

            var baselineProvider = new Mock <IBaselineProvider>();
            var diffProvider     = new Mock <IDiffProvider>(MockBehavior.Loose);
            var branchProvider   = new Mock <IGitInfoProvider>();

            // If a file inside the test project is changed, a test has been changed
            string myTest = Path.Combine(testProjectPath, "myTest.cs");;

            diffProvider.Setup(x => x.ScanDiff()).Returns(new DiffResult()
            {
                ChangedFiles = new Collection <string>()
                {
                    myTest
                },
                TestFilesChanged = new Collection <string>()
                {
                    myTest
                }
            });
            var target = new DiffMutantFilter(options, diffProvider.Object, baselineProvider.Object, branchProvider.Object);

            // check the diff result for a file not inside the test project
            var file = new FileLeaf {
                FullPath = Path.Combine("C:/NotMyTests", "myfile.cs")
            };

            var mutant = new Mutant();

            mutant.CoveringTests.Add(new TestDescription(Guid.NewGuid().ToString(), "name", myTest));

            // Act
            var filterResult = target.FilterMutants(new List <Mutant>()
            {
                mutant
            }, file, options);

            // Assert
            filterResult.ShouldContain(mutant);
        }
        public void BroadcastReporter_ShouldInvokeSameMethodWithSameObject_OnMutantTested()
        {
            var reporterMock = new Mock <IReporter>(MockBehavior.Strict);

            reporterMock.Setup(x => x.OnMutantTested(It.IsAny <Mutant>()));

            var exampleInputComponent = new FileLeaf();
            var exampleMutant         = new Mutant();

            var reporters = new Collection <IReporter>()
            {
                reporterMock.Object
            };
            var target = new BroadcastReporter(reporters);

            target.OnMutantTested(exampleMutant);

            reporterMock.Verify(x => x.OnMutantTested(exampleMutant), Times.Once);
        }
示例#17
0
        public IEnumerable <Mutant> FilterMutants(IEnumerable <Mutant> mutants, FileLeaf file, StrykerOptions options)
        {
            if (options.CompareToDashboard)
            {
                // If the dashboard feature is enabled but we cannot find a baseline. We are going to test the entire project. Thus none of the mutants can be filtered out and all are returned.
                if (_baseline == null)
                {
                    _logger.LogDebug("Testing all mutants on {0} because there is no baseline", file.RelativePathToProjectFile);
                    return(mutants);
                }

                // Updates all the mutants in this file with their counterpart's result in the report of the previous run.
                UpdateMutantsWithBaseline(mutants, file);
            }

            // We check if the tests have changed, if this is the case we should run all mutants. Otherwise we start filtering.
            if (!_diffResult.TestsChanged)
            {
                if (_diffResult.ChangedFiles.Contains(file.FullPath))
                {
                    _logger.LogDebug("returning all mutants in {0} because the file is modified", file.RelativePathToProjectFile);
                    // If the diffresult flags this file as modified. We want to run all mutants again.
                    return(SetMutantStatusForFileChanged(mutants));
                }

                if (_options.CompareToDashboard)
                {
                    // When using the compare to dashboard feature.
                    // Some mutants mutants have no certain result because we couldn't say with certainty which mutant on the dashboard belonged to it.
                    //These mutants have to be reset and tested.
                    _logger.LogDebug("Running mutants for which we couldn't determine status on file {0}", file.RelativePathToProjectFile);
                    return(ReturnMutantsWithStatusNotRun(mutants));
                }
                _logger.LogDebug("Filtered all mutants because file {0} hasn't changed", file.RelativePathToProjectFile);
                // If tests haven't changed and neither the file has changed or the compare feature is being used, we are not interested in the mutants of this file and thus can be filtered out completely.
                return(Enumerable.Empty <Mutant>());
            }

            _logger.LogDebug("Running all mmutants in {0} because tests have changed", file.RelativePathToProjectFile);
            // If tests are changed, return all mutants with status set to NotRun. We cannot guarantee the result.
            return(ResetMutantStatus(mutants));
        }
示例#18
0
        public IEnumerable <Mutant> FilterMutants(IEnumerable <Mutant> mutants, FileLeaf file, StrykerOptions options)
        {
            // Mutants can be enabled for testing based on multiple reasons. We store all the filtered mutants in this list and return this list.
            IEnumerable <Mutant> filteredMutants;

            // If the dashboard feature is turned on we first filter based on previous results
            if (options.CompareToDashboard)
            {
                // If the dashboard feature is enabled but we cannot find a baseline. We are going to test the entire project. Thus none of the mutants can be filtered out and all are returned.
                if (_baseline == null)
                {
                    _logger.LogDebug("Testing all mutants on {0} because there is no baseline available", file.RelativePathToProjectFile);
                    return(mutants);
                }

                // Updates all the mutants in this file with their counterpart's result in the report of the previous run
                UpdateMutantsWithBaselineStatus(mutants, file);
            }

            // A non-csharp file is flagged by the diff result as modified. We cannot determine which mutants will be affected by this, thus all mutants have to be tested.
            if (_diffResult.ChangedTestFiles is { } && _diffResult.ChangedTestFiles.Any(x => !x.EndsWith(".cs")))
        public IEnumerable <Mutant> FilterMutants(IEnumerable <Mutant> mutants, FileLeaf file, StrykerOptions options)
        {
            IEnumerable <Mutant> mutantsToTest = mutants.ToList();

            // Then all other filters except diff filter
            foreach (var mutantFilter in MutantFilters.Where(f => !(f is DiffMutantFilter)))
            {
                // These mutants should be tested according to current filter
                var extraMutantsToTest = mutantFilter.FilterMutants(mutantsToTest, file, options);

                // All mutants that weren't filtered out by a previous filter but were by the current filter are set to Ignored
                foreach (var skippedMutant in mutantsToTest.Except(extraMutantsToTest))
                {
                    skippedMutant.ResultStatus       = MutantStatus.Ignored;
                    skippedMutant.ResultStatusReason = $"Removed by {mutantFilter.DisplayName}";
                }

                mutantsToTest = extraMutantsToTest;
            }

            // Diff filter goes last if it is enabled
            if (MutantFilters.SingleOrDefault(f => f is DiffMutantFilter) is var diffFilter && diffFilter is { })
示例#20
0
        public IEnumerable <Mutant> FilterMutants(IEnumerable <Mutant> mutants, FileLeaf file, StrykerOptions options)
        {
            IEnumerable <Mutant> filteredMutants = mutants;

            foreach (var mutantFilter in MutantFilters)
            {
                var current = mutantFilter.FilterMutants(mutants, file, options);

                foreach (var skippedMutant in filteredMutants.Except(current))
                {
                    if (skippedMutant.ResultStatus == MutantStatus.NotRun)
                    {
                        skippedMutant.ResultStatus       = MutantStatus.Ignored;
                        skippedMutant.ResultStatusReason = $"Removed by {mutantFilter.DisplayName}";
                    }
                }

                filteredMutants = current;
            }

            return(filteredMutants);
        }
示例#21
0
        private void UpdateMutantsWithBaseline(IEnumerable <Mutant> mutants, FileLeaf file)
        {
            foreach (var baselineFile in _baseline.Files)
            {
                var filePath = FilePathUtils.NormalizePathSeparators(baselineFile.Key);

                if (filePath == file.RelativePath)
                {
                    foreach (var baselineMutant in baselineFile.Value.Mutants)
                    {
                        var baselineMutantSourceCode = GetMutantSourceCode(baselineFile.Value.Source, baselineMutant);

                        IEnumerable <Mutant> matchingMutants = GetMutantMatchingSourceCode(mutants, baselineMutant, baselineMutantSourceCode);

                        if (matchingMutants.Count() == 1)
                        {
                            UpdateMutantStatusWithBaseline(baselineMutant, matchingMutants.First());
                        }
                        else
                        {
                            UpdateMutantsForStatusUnclear(matchingMutants);
                        }
                    }
                }
            }

            var mutantGroups = mutants
                               .GroupBy(x => x.ResultStatusReason)
                               .OrderBy(x => x.Key);

            foreach (var skippedMutantGroup in mutantGroups)
            {
                _logger.LogInformation("{0} mutants got status {1}. Reason: {2}", skippedMutantGroup.Count(),
                                       skippedMutantGroup.First().ResultStatus, skippedMutantGroup.Key);
            }
        }
示例#22
0
        public void ShouldMutateAllFilesWhenTurnedOff()
        {
            var    options      = new StrykerOptions(diff: false);
            var    diffProvider = new Mock <IDiffProvider>(MockBehavior.Strict);
            string myFile       = Path.Combine("C:/test/", "myfile.cs");;

            diffProvider.Setup(x => x.ScanDiff()).Returns(new DiffResult()
            {
                ChangedFiles = new Collection <string>()
            });
            var target = new DiffMutantFilter(options, diffProvider.Object);
            var file   = new FileLeaf {
                FullPath = myFile
            };

            var mutant = new Mutant();

            var filterResult = target.FilterMutants(new List <Mutant>()
            {
                mutant
            }, file, options);

            filterResult.ShouldContain(mutant);
        }
示例#23
0
 private IDictionary <string, JsonReportFileComponent> GenerateFileReportComponents(FileLeaf fileComponent)
 {
     return(new Dictionary <string, JsonReportFileComponent> {
         { fileComponent.RelativePath, new JsonReportFileComponent(fileComponent) }
     });
 }
示例#24
0
 /// <inheritdoc />
 public IEnumerable <Mutant> FilterMutants(IEnumerable <Mutant> mutants, FileLeaf file, StrykerOptions options)
 {
     return(mutants.Where(mutant => !options.ExcludedMutations.Contains(mutant.Mutation.Type)));
 }
示例#25
0
 public ReadOnlyFileLeaf(FileLeaf projectComponent) : base(projectComponent)
 {
     _projectComponent = projectComponent;
 }
        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);
        }
示例#27
0
        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);
        }
示例#28
0
        private IDictionary <string, JsonReportFileComponent> GenerateFileReportComponents(FileLeaf fileComponent)
        {
            var reportComponent = new JsonReportFileComponent(fileComponent)
            {
                Health = fileComponent.CheckHealth(_options.Thresholds)
            };

            return(new Dictionary <string, JsonReportFileComponent> {
                { fileComponent.RelativePath, reportComponent }
            });
        }
示例#29
0
 public IEnumerable <Mutant> FilterMutants(IEnumerable <Mutant> mutants, FileLeaf file, StrykerOptions options)
 {
     return(mutants.Where(m => !Exclude(m.Mutation.OriginalNode)));
 }
        public void ShouldCallMutantOrchestratorAndReporter()
        {
            var inputFile = new FileLeaf()
            {
                Name       = "Recursive.cs",
                SourceCode = SourceFile,
                SyntaxTree = CSharpSyntaxTree.ParseText(SourceFile)
            };

            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 = new FolderComposite()
                    {
                        Name     = Path.Combine(FilesystemRoot, "ExampleProject"),
                        Children = new Collection <ProjectComponent>()
                        {
                            inputFile,
                        }
                    },
                },
                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);
            var compilingProcessMock     = new Mock <ICompilingProcess>(MockBehavior.Strict);

            // setup mocks
            reporterMock.Setup(x => x.OnMutantsCreated(It.IsAny <ProjectComponent>()));
            orchestratorMock.Setup(x => x.GetLatestMutantBatch()).Returns(mockMutants);
            orchestratorMock.Setup(x => x.Mutate(It.IsAny <SyntaxNode>())).Returns(CSharpSyntaxTree.ParseText(SourceFile).GetRoot());
            orchestratorMock.SetupAllProperties();
            compilingProcessMock.Setup(x => x.Compile(It.IsAny <IEnumerable <SyntaxTree> >(), It.IsAny <MemoryStream>(), It.IsAny <MemoryStream>(), true))
            .Returns(new CompilingProcessResult()
            {
                Success = true
            });
            var options = new StrykerOptions(devMode: true, excludedMutations: new string[] { });


            var target = new MutationTestProcess(input,
                                                 reporterMock.Object,
                                                 mutationTestExecutorMock.Object,
                                                 orchestratorMock.Object,
                                                 compilingProcessMock.Object,
                                                 fileSystem,
                                                 options,
                                                 new BroadcastMutantFilter(Enumerable.Empty <IMutantFilter>()));

            // start mutation process
            target.Mutate();

            // verify the right methods were called
            orchestratorMock.Verify(x => x.Mutate(It.IsAny <SyntaxNode>()), Times.Once);
            reporterMock.Verify(x => x.OnMutantsCreated(It.IsAny <ProjectComponent>()), Times.Once);
        }