示例#1
0
        private void HandleStrykerRunResult(IStrykerInputs inputs, StrykerRunResult result)
        {
            var logger = ApplicationLogging.LoggerFactory.CreateLogger <StrykerCli>();

            if (double.IsNaN(result.MutationScore))
            {
                logger.LogInformation("Stryker was unable to calculate a mutation score");
            }
            else
            {
                logger.LogInformation("The final mutation score is {MutationScore:P2}", result.MutationScore);
            }

            if (result.ScoreIsLowerThanThresholdBreak())
            {
                var thresholdBreak = (double)inputs.ValidateAll().Thresholds.Break / 100;
                logger.LogWarning("Final mutation score is below threshold break. Crashing...");

                _console.WriteLine();
                _console.MarkupLine($"[Red]The mutation score is lower than the configured break threshold of {thresholdBreak:P0}.[/]");
                _console.MarkupLine(" [Red]Looks like you've got some work to do :smiling_face_with_halo:[/]");

                ExitCode = ExitCodes.BreakThresholdViolated;
            }
        }
示例#2
0
        /// <summary>
        /// Creates the needed paths for logging and initializes the logger factory
        /// </summary>
        /// <param name="fileSystem">Mock filesystem</param>
        public void SetupLogOptions(IStrykerInputs inputs, IFileSystem fileSystem = null)
        {
            fileSystem ??= new FileSystem();
            var basePath = inputs.BasePathInput.SuppliedInput;

            var outputPath = CreateOutputPath(basePath, fileSystem);

            inputs.OutputPathInput.SuppliedInput = outputPath;

            var logLevel  = inputs.VerbosityInput.Validate();
            var logToFile = inputs.LogToFileInput.Validate(outputPath);

            ApplicationLogging.ConfigureLogger(logLevel, logToFile, outputPath);
        }
示例#3
0
        public static void DeserializeConfig(string configFilePath, IStrykerInputs inputs)
        {
            var jsonConfig = LoadJsonConfig(configFilePath);

            // As json values are first in line we can just overwrite all supplied inputs
            inputs.ConcurrencyInput.SuppliedInput = jsonConfig.Concurrency;

            inputs.SinceInput.SuppliedInput =
                jsonConfig.Since is not null &&
                (jsonConfig.Since.Enabled.HasValue && jsonConfig.Since.Enabled.Value);

            inputs.WithBaselineInput.SuppliedInput =
                jsonConfig.Baseline is not null &&
                (jsonConfig.Baseline.Enabled.HasValue && jsonConfig.Baseline.Enabled.Value);

            inputs.BaselineProviderInput.SuppliedInput    = jsonConfig.Baseline?.Provider;
            inputs.DiffIgnoreChangesInput.SuppliedInput   = jsonConfig.Since?.IgnoreChangesIn;
            inputs.FallbackVersionInput.SuppliedInput     = jsonConfig.Baseline?.FallbackVersion;
            inputs.AzureFileStorageUrlInput.SuppliedInput = jsonConfig.Baseline?.AzureFileShareUrl;
            inputs.CoverageAnalysisInput.SuppliedInput    = jsonConfig.CoverageAnalysis;
            inputs.DisableBailInput.SuppliedInput         = jsonConfig.DisableBail;
            inputs.DisableMixMutantsInput.SuppliedInput   = jsonConfig.DisableMixMutants;
            inputs.AdditionalTimeoutInput.SuppliedInput   = jsonConfig.AdditionalTimeout;
            inputs.MutateInput.SuppliedInput         = jsonConfig.Mutate;
            inputs.MutationLevelInput.SuppliedInput  = jsonConfig.MutationLevel;
            inputs.ProjectNameInput.SuppliedInput    = jsonConfig.ProjectInfo?.Name;
            inputs.ModuleNameInput.SuppliedInput     = jsonConfig.ProjectInfo?.Module;
            inputs.ProjectVersionInput.SuppliedInput = jsonConfig.ProjectInfo?.Version;
            inputs.ReportersInput.SuppliedInput      = jsonConfig.Reporters;

            inputs.SinceTargetInput.SuppliedInput     = jsonConfig.Since?.Target;
            inputs.SolutionInput.SuppliedInput        = jsonConfig.Solution;
            inputs.TargetFrameworkInput.SuppliedInput = jsonConfig.TargetFramework;

            inputs.ProjectUnderTestNameInput.SuppliedInput = jsonConfig.Project;
            inputs.ThresholdBreakInput.SuppliedInput       = jsonConfig.Thresholds?.Break;
            inputs.ThresholdHighInput.SuppliedInput        = jsonConfig.Thresholds?.High;
            inputs.ThresholdLowInput.SuppliedInput         = jsonConfig.Thresholds?.Low;
            inputs.VerbosityInput.SuppliedInput            = jsonConfig.Verbosity;
            inputs.LanguageVersionInput.SuppliedInput      = jsonConfig.LanguageVersion;
            inputs.TestProjectsInput.SuppliedInput         = jsonConfig.TestProjects;
            inputs.TestCaseFilterInput.SuppliedInput       = jsonConfig.TestCaseFilter;
            inputs.DashboardUrlInput.SuppliedInput         = jsonConfig.DashboardUrl;
            inputs.IgnoreMutationsInput.SuppliedInput      = jsonConfig.IgnoreMutations;
            inputs.IgnoredMethodsInput.SuppliedInput       = jsonConfig.IgnoreMethods;

            inputs.ReportFileNameInput.SuppliedInput = jsonConfig.ReportFileName;
        }
        /// <summary>
        /// Reads all config from json and console to fill stryker inputs
        /// </summary>
        /// <param name="args">Console app arguments</param>
        /// <param name="app">The console application containing all argument information</param>
        /// <param name="cmdConfigHandler">Mock console config handler</param>
        /// <returns>Filled stryker inputs (except output path)</returns>
        public void Build(IStrykerInputs inputs, string[] args, CommandLineApplication app, CommandLineConfigHandler cmdConfigHandler)
        {
            // set basepath
            var basePath = Directory.GetCurrentDirectory();

            inputs.BasePathInput.SuppliedInput = basePath;

            // read config from json and commandline
            var configFilePath = Path.Combine(basePath, cmdConfigHandler.GetConfigFilePath(args, app));

            if (File.Exists(configFilePath))
            {
                JsonConfigHandler.DeserializeConfig(configFilePath, inputs);
            }
            cmdConfigHandler.ReadCommandLineConfig(args, app, inputs);
        }
        public void WithConfigFile_ShouldStartStrykerWithConfigFileOptions(string argName)
        {
            IStrykerInputs actualInputs = null;
            var            options      = new StrykerOptions()
            {
                Thresholds = new Thresholds()
                {
                    High  = 80,
                    Low   = 60,
                    Break = 0
                }
            };
            var runResults = new StrykerRunResult(options, 0.3);

            var mock = new Mock <IStrykerRunner>(MockBehavior.Strict);

            mock.Setup(x => x.RunMutationTest(It.IsAny <IStrykerInputs>(), It.IsAny <ILoggerFactory>(), It.IsAny <IProjectOrchestrator>()))
            .Callback <IStrykerInputs, ILoggerFactory, IProjectOrchestrator>((c, l, p) => actualInputs = c)
            .Returns(runResults)
            .Verifiable();

            var target = new StrykerCli(mock.Object);

            target.Run(new string[] { argName, "filled-stryker-config.json" });

            mock.VerifyAll();

            actualInputs.AdditionalTimeoutInput.SuppliedInput.ShouldBe(9999);
            actualInputs.VerbosityInput.SuppliedInput.ShouldBe("trace");
            actualInputs.ProjectUnderTestNameInput.SuppliedInput.ShouldBe("ExampleProject.csproj");
            actualInputs.ReportersInput.SuppliedInput.ShouldHaveSingleItem();
            actualInputs.ReportersInput.SuppliedInput.ShouldContain(Reporter.Json.ToString());
            actualInputs.ConcurrencyInput.SuppliedInput.ShouldBe(1);
            actualInputs.ThresholdBreakInput.SuppliedInput.ShouldBe(20);
            actualInputs.ThresholdLowInput.SuppliedInput.ShouldBe(30);
            actualInputs.ThresholdHighInput.SuppliedInput.ShouldBe(40);
            actualInputs.MutateInput.SuppliedInput.ShouldHaveSingleItem();
            actualInputs.MutateInput.SuppliedInput.ShouldContain("!**/Test.cs{1..100}{200..300}");
            actualInputs.CoverageAnalysisInput.SuppliedInput.ShouldBe("perTest");
            actualInputs.DisableBailInput.SuppliedInput.ShouldBe(true);
            actualInputs.IgnoreMutationsInput.SuppliedInput.ShouldContain("linq.FirstOrDefault");
            actualInputs.IgnoredMethodsInput.SuppliedInput.ShouldContain("Log*");
            actualInputs.TestCaseFilterInput.SuppliedInput.ShouldBe("(FullyQualifiedName~UnitTest1&TestCategory=CategoryA)|Priority=1");
            actualInputs.DashboardUrlInput.SuppliedInput.ShouldBe("https://alternative-stryker-dashboard.io");
        }
示例#6
0
        private void RunStryker(IStrykerInputs inputs)
        {
            var result = _stryker.RunMutationTest(inputs, ApplicationLogging.LoggerFactory);

            HandleStrykerRunResult(inputs, result);
        }
示例#7
0
        /// <summary>
        /// Starts a mutation test run
        /// </summary>
        /// <param name="options">The user options</param>
        /// <param name="loggerFactory">This loggerfactory will be used to create loggers during the stryker run</param>
        /// <exception cref="InputException">For managed exceptions</exception>
        public StrykerRunResult RunMutationTest(IStrykerInputs inputs, ILoggerFactory loggerFactory, IProjectOrchestrator projectOrchestrator = null)
        {
            var stopwatch = new Stopwatch();

            stopwatch.Start();

            SetupLogging(loggerFactory);

            // Setup project orchestrator can't be done sooner since it needs logging
            projectOrchestrator ??= new ProjectOrchestrator();

            var options = inputs.ValidateAll();

            _logger.LogDebug("Stryker started with options: {@Options}", options);

            var reporters = _reporterFactory.Create(options);

            try
            {
                // Mutate
                _mutationTestProcesses = projectOrchestrator.MutateProjects(options, reporters).ToList();

                IReadOnlyProjectComponent rootComponent = AddRootFolderIfMultiProject(_mutationTestProcesses.Select(x => x.Input.ProjectInfo.ProjectContents).ToList(), options);

                _logger.LogInformation("{0} mutants created", rootComponent.Mutants.Count());

                AnalyseCoverage(options);

                // Filter
                foreach (var project in _mutationTestProcesses)
                {
                    project.FilterMutants();
                }

                // Report
                reporters.OnMutantsCreated(rootComponent);

                var allMutants    = rootComponent.Mutants;
                var mutantsNotRun = rootComponent.NotRunMutants().ToList();

                if (!mutantsNotRun.Any())
                {
                    if (allMutants.Any(x => x.ResultStatus == MutantStatus.Ignored))
                    {
                        _logger.LogWarning("It looks like all mutants with tests were ignored. Try a re-run with less ignoring!");
                    }
                    if (allMutants.Any(x => x.ResultStatus == MutantStatus.NoCoverage))
                    {
                        _logger.LogWarning("It looks like all non-ignored mutants are not covered by a test. Go add some tests!");
                    }
                    if (allMutants.Any(x => x.ResultStatus == MutantStatus.CompileError))
                    {
                        _logger.LogWarning("It looks like all mutants resulted in compile errors. Mutants sure are strange!");
                    }
                    if (!allMutants.Any())
                    {
                        _logger.LogWarning("It\'s a mutant-free world, nothing to test.");
                    }

                    reporters.OnAllMutantsTested(rootComponent);
                    return(new StrykerRunResult(options, rootComponent.GetMutationScore()));
                }

                // Report
                reporters.OnStartMutantTestRun(mutantsNotRun);

                // Test
                foreach (var project in _mutationTestProcesses)
                {
                    project.Test(project.Input.ProjectInfo.ProjectContents.Mutants.Where(x => x.ResultStatus == MutantStatus.NotRun).ToList());
                    project.Restore();
                }

                reporters.OnAllMutantsTested(rootComponent);

                return(new StrykerRunResult(options, rootComponent.GetMutationScore()));
            }
#if !DEBUG
            catch (Exception ex) when(!(ex is InputException))
            // let the exception be caught by the debugger when in debug
            {
                _logger.LogError(ex, "An error occurred during the mutation test run ");
                throw;
            }
#endif
            finally
            {
                // log duration
                stopwatch.Stop();
                _logger.LogInformation("Time Elapsed {0}", stopwatch.Elapsed);
            }
        }