protected void Given_some_mutants_will_survive() { var baseSlnDir = Path.Combine(TestContext.CurrentContext.TestDirectory, "..", "..", "..", ".."); var survivingMutant = new SurvivingMutant { SourceFilePath = Path.Combine(baseSlnDir, "someclass.cs"), SourceLine = 123, OriginalLine = "a+b", MutatedLine = "a-b" }; MockMutationTestRunner .Setup(r => r.Run(It.IsAny <Config>())) .Callback(() => { // Raise events that a real MutationTestRunner would raise. var classFilePath = Path.Combine(baseSlnDir, "someclass.cs"); eventListener.BeginMutationOfFile(classFilePath, baseSlnDir, 0, 1); eventListener.MemberMutating("System.Void SomeProject.SomeOtherNamespace.SomeClass::SomeMethod(System.Int32)"); eventListener.SyntaxNodeMutating(0, 1); eventListener.MutantSurvived(survivingMutant); eventListener.EndMutationOfFile(classFilePath); }) .Returns(Task.FromResult(new MutationTestResult().WithSurvivingMutants(new [] { survivingMutant }))); }
private async Task <SurvivingMutant> CreateSurvivingMutantFromExpression( string originalExpression, string mutatedExpression) { var originalDocument = SourceToDocument( $@"namespace DummyNamespace {{ public static class DummyClass {{ public static bool IsPositive(int a) {{ return {originalExpression}; }} }} }}"); var originalSyntaxRoot = await originalDocument.GetSyntaxRootAsync(); var originalNode = originalSyntaxRoot.DescendantNodes().OfType <BinaryExpressionSyntax>().First(); var mutatedNode = SyntaxFactory.ParseExpression(mutatedExpression); var mutatedRoot = originalSyntaxRoot.ReplaceNode(originalNode, mutatedNode); return(await SurvivingMutant.Create(originalDocument, originalNode, mutatedRoot)); }
public async Task <SurvivingMutant> Run(ITestRunner testRunner, string tempDirectory, IEventListener eventListener) { var mutatedNode = mutator.Mutate(OriginalNode); MutatedSyntaxRoot = originalSyntaxRoot.ReplaceNode(OriginalNode, mutatedNode); var compilationResult = await CompileContainingProject(tempDirectory); if (!compilationResult.Success) { // Not all mutations are valid in all circumstances, and therefore may not compile. // E.g. "a + b" => "a - b" works when a and b are integers but not when they're strings. return(null); } CopyMutatedAssemblyIntoTempTestAssemblyDirectories(compilationResult.OutputFilePath, tempDirectory, config); var copiedTempTestAssemblyFilePaths = TempTestAssemblyFilePaths(config, tempDirectory).ToArray(); var ranAnyTests = false; for (var testAssemblyIndex = 0; testAssemblyIndex < config.TestAssemblyFilePaths.Length; ++testAssemblyIndex) { var originalTestAssemblyFilePath = config.TestAssemblyFilePaths[testAssemblyIndex]; var tempTestAssemblyFilePath = copiedTempTestAssemblyFilePaths[testAssemblyIndex]; string[] testsToRun = null; if (coverageAnalysisResult != null) { testsToRun = coverageAnalysisResult.TestsThatCoverMember(memberName, originalTestAssemblyFilePath); if (!testsToRun.Any()) { continue; } } ranAnyTests = true; var result = testsToRun != null? testRunner.RunTests(new[] { tempTestAssemblyFilePath }, testsToRun) : testRunner.RunAllTests(new[] { tempTestAssemblyFilePath }); if (result.Status == TestRunStatus.SomeTestsFailed) { return(null); } } return(ranAnyTests ? await SurvivingMutant.Create(OriginalClass, OriginalNode, MutatedSyntaxRoot) : null); }
private static void OutputSurvivorInfo(SurvivingMutant survivor, int index, Config config, IOutputWriter outputWriter) { string ToRelativePath(string filePath) { var baseSourceDir = Path.GetDirectoryName(Path.GetFullPath(config.SolutionFilePath)); return(filePath.Substring(baseSourceDir.Length)); } outputWriter.WriteLine(""); outputWriter.WriteFailureLine($"({index+1}) {ToRelativePath(survivor.SourceFilePath)}:{survivor.SourceLine}"); outputWriter.WriteFailureLine($" original: {survivor.OriginalLine.Trim()}"); outputWriter.WriteFailureLine($" mutated: {survivor.MutatedLine.Trim()}"); }
public void MutantSurvived(SurvivingMutant survivor) { }
public void MutantSurvived(SurvivingMutant survivingMutant) { HaveAnyMutantsSurvived = true; }
public void MutantSurvived(SurvivingMutant survivingMutant) { outputWriter.Write("✗"); }