Example #1
0
 private void PrintClassCoverage(SourceClassDetail source, string coverageClassName)
 {
     Output += " ".PrintWithPreTag();
     Output += "Class Coverage: ".PrintWithPreTagImportant(3, Colors.Green);
     Output += $"Class Name: {coverageClassName} {source.Coverage.ToString().Print(color: Colors.BlueViolet)}".PrintWithPreTagImportant();
     Output += "Methods Coverage: ".PrintWithPreTagImportant();
 }
Example #2
0
 private async Task InitItemSources(SourceClassDetail source)
 {
     await new MethodsInitializer
     {
         IncludeNestedClasses = IncludeNestedClasses
     }.FindMethods(source);
 }
Example #3
0
        private async Task ExecuteTests(SourceClassDetail source)
        {
            _chalk.Default("\nExecuting Tests...");
            var log = new StringBuilder();

            void OutputData(object sender, string args) => log.AppendLine(args);

            var testExecutor = new TestExecutor(_settings, source.TestClaz.ClassLibrary)
            {
                X64TargetPlatform  = X64TargetPlatform,
                FullyQualifiedName = source.TestClaz.MethodDetails.Count > _useClassFilterTestsThreshold ||
                                     UseClassFilter || source.TestClaz.BaseClass != null
                    ? source.TestClaz.Claz.Syntax.FullName()
                    : string.Empty,
                EnableCustomOptions = true,
                EnableLogging       = true
            };

            testExecutor.OutputDataReceived += OutputData;
            testExecutor.BeforeTestExecuted += (sender, args) =>
            {
                _chalk.Yellow($"\nRunning VSTest.Console with {args}\n");
            };

            await testExecutor.ExecuteTests(source.TestClaz.MethodDetails.ToList());

            source.NumberOfTests = Convert.ToInt32(testExecutor.TestResult?.ResultSummary?.Counters?.Total);

            _chalk.Yellow($"\nNumber of Tests: {source.NumberOfTests}\n");

            if (testExecutor.LastTestExecutionStatus != Constants.TestExecutionStatus.Success)
            {
                throw new MuTestFailingTestException(log.ToString());
            }

            if (!NoCoverage)
            {
                _chalk.Green("\nCalculating Code Coverage...");

                if (testExecutor.CodeCoverage != null)
                {
                    var coverage = new CoverageAnalyzer();
                    coverage.FindCoverage(source, testExecutor.CodeCoverage);
                }

                if (source.Coverage != null)
                {
                    var coveredLines = source.Coverage.LinesCovered;
                    var totalLines   = source.Coverage.TotalLines;
                    _chalk.Yellow(
                        $"\nCode Coverage for Class {Path.GetFileName(source.FilePath)} is {decimal.Divide(coveredLines, totalLines):P} ({coveredLines}/{totalLines})\n");
                }
            }

            testExecutor.OutputDataReceived -= OutputData;
        }
Example #4
0
        private async Task GetFromDB(string hash)
        {
            var data = await _client.GetFileDataFromStorage(hash);

            if (data != null)
            {
                _source           = JsonConvert.DeserializeObject <SourceClassDetail>(data);
                _source.StoreToDb = false;
            }
        }
Example #5
0
 private void PrintExternalCoveredClasses(SourceClassDetail source)
 {
     if (source.ExternalCoveredClasses.Any())
     {
         Output += " ".PrintWithPreTag();
         Output += "External Coverage: ".PrintWithPreTagImportant(3, Colors.Red);
         foreach (var clz in source.ExternalCoveredClasses)
         {
             Output += clz.ToString().PrintWithPreTagWithMarginImportant(color: Colors.BlueViolet);
         }
     }
 }
Example #6
0
        public void ClassLookupSelectedIndexChanged(object selectedItem)
        {
            try
            {
                IsSplashScreenShown = true;
                _selectedClass      = (SourceClassDetail)selectedItem;
                ShowAnalyzeButton();
            }
            catch (Exception)
            {
                IsSplashScreenShown = false;
                MessageBoxService.Show(ErrorMessage);
            }

            IsSplashScreenShown = false;
        }
Example #7
0
        private async Task Initialization(SourceClassDetail source)
        {
            var defaultMutants = MutantOrchestrator.GetDefaultMutants(source.Claz.Syntax, source.Claz);

            await InitItemSources(source);

            if ((defaultMutants.Any() || string.IsNullOrWhiteSpace(ProcessWholeProject)) && !UseExternalCodeCoverage)
            {
                if (TestExecutionTime > -1)
                {
                    await FindTestExecutionTime(source);
                }

                await ExecuteTests(source);
            }

            await InitializeMutants(source);
            await AnalyzeMutant(source);
        }
Example #8
0
        private async Task InitializeMutants(SourceClassDetail source)
        {
            _chalk.Default("\nInitialize Mutants...");
            var mutantAnalyzer = new MutantInitializer(source)
            {
                ExecuteAllTests     = source.TestClaz.MethodDetails.Count > _useClassFilterTestsThreshold || ExecuteAllTests,
                MutantFilterRegEx   = RegEx,
                SpecificFilterRegEx = Specific,
                MutantsPerLine      = MutantsPerLine
            };

            if (UseExternalCodeCoverage)
            {
                mutantAnalyzer.ExecuteAllTests     = true;
                mutantAnalyzer.MutantFilterRegEx   = string.Empty;
                mutantAnalyzer.SpecificFilterRegEx = string.Empty;
                mutantAnalyzer.MutantsAtSpecificLines.AddRange(ExternalCoveredMutants);
            }

            await mutantAnalyzer.InitializeMutants(MutantOrchestrator.DefaultMutators);
        }
 protected MutantViewerViewModel(SourceClassDetail source)
 {
     _source                           = source;
     _silently                         = false;
     MutantList                        = ListBoxEditViewModel.CreateListBoxEdit();
     _outputLogger                     = new CommandPromptOutputLogger();
     ChkExecuteAllTests                = ControlViewModel.Create();
     ChkEnableDiagnostic               = ControlViewModel.Create();
     ChkEnableCodeCoverage             = ControlViewModel.CreateWithChecked();
     ChkAnalyzeExternalCoverage        = ControlViewModel.Create();
     ChkOptimizeTestProject            = ControlViewModel.CreateWithChecked();
     ChkUseClassFilter                 = ControlViewModel.CreateWithChecked();
     ChkRealTimeAnalysis               = ControlViewModel.Create();
     _testDiagnosticDocumentViewModel  = _outputLogger.GetLogFromOutput("Test Diagnostics Window", string.Empty);
     _buildDiagnosticDocumentViewModel = _outputLogger.GetLogFromOutput("Build Diagnostics Window", string.Empty);
     InitItemSources();
     _directoryFactory              = new TestDirectoryFactory(_source);
     _mutantInitializer             = new MutantInitializer(_source);
     _previousMutants               = new Dictionary <string, MutantStatus>();
     _isRealMutationAnalysisRunning = false;
     _isClosed = false;
 }
Example #10
0
        private async Task AnalyzeMutant(SourceClassDetail source)
        {
            _chalk.Default("\nPreparing Tests Files...\n");
            var directoryFactory = new TestDirectoryFactory(source)
            {
                NumberOfMutantsExecutingInParallel = ConcurrentTestRunners
            };

            directoryFactory.DeleteDirectories();
            await directoryFactory.PrepareDirectoriesAndFiles();

            _chalk.Default("\nRunning Mutation...\n");
            var mutantAnalyzer = new MutantExecutor(source, _settings)
            {
                NumberOfMutantsExecutingInParallel = ConcurrentTestRunners,
                EnableDiagnostics = EnableDiagnostics,
                SurvivedThreshold = 0.01,
                BaseAddress       = _settings.ServiceAddress
            };

            if (!UseExternalCodeCoverage)
            {
                MutantExecutor = mutantAnalyzer;
                mutantAnalyzer.UseClassFilter = UseClassFilter ||
                                                source.TestClaz.MethodDetails.Count > _useClassFilterTestsThreshold ||
                                                source.TestClaz.BaseClass != null;
                mutantAnalyzer.SurvivedThreshold = SurvivedThreshold;
                mutantAnalyzer.KilledThreshold   = KilledThreshold;
            }

            TotalMutants   = source.MethodDetails.SelectMany(x => x.NotRunMutants).Count();
            MutantProgress = 0;
            mutantAnalyzer.MutantExecuted += MutantAnalyzerOnMutantExecuted;
            await mutantAnalyzer.ExecuteMutants();

            directoryFactory.DeleteDirectories();
        }
Example #11
0
        public void FindCoverage(SourceClassDetail source, CoverageDS codeCoverage)
        {
            if (codeCoverage != null)
            {
                source.ExternalCoveredClasses.Clear();
                source.ExternalCoveredClasses.AddRange(FindExternalCoveredClasses(source, codeCoverage));
                var parentClassName = string.Join(".", source.Claz.Syntax.Ancestors <ClassDeclarationSyntax>().Select(x => x.ClassName()));
                var className       = $"{parentClassName}.{source.Claz.Syntax.ClassName()}".TrimStart('.');
                var coverages       = codeCoverage
                                      .Class
                                      .Where(x => x.NamespaceTableRow.NamespaceName == source.Claz.Syntax.NameSpace() &&
                                             (x.ClassName == className ||
                                              x.ClassName.StartsWith($"{className}.{GenericMethodStart}") ||
                                              x.ClassName.StartsWith($"{className}{GenericMethodStart}"))).ToList();

                if (coverages.Any())
                {
                    source.Coverage = new Coverage
                    {
                        LinesCovered     = (uint)coverages.Sum(x => x.LinesCovered),
                        LinesNotCovered  = (uint)coverages.Sum(x => x.LinesNotCovered),
                        BlocksCovered    = (uint)coverages.Sum(x => x.BlocksCovered),
                        BlocksNotCovered = (uint)coverages.Sum(x => x.BlocksNotCovered)
                    };

                    var methodsWithCoverage = new List <MethodDetail>();
                    PrintClassCoverage(source, className);
                    foreach (var coverage in coverages)
                    {
                        var coverageClassName = coverage.ClassName;
                        var methods           = codeCoverage
                                                .Method.Where(x => x.ClassKeyName == coverage.ClassKeyName)
                                                .ToList();

                        foreach (CoverageDSPriv.MethodRow mCoverage in methods)
                        {
                            var methodFullName = mCoverage.MethodFullName;
                            if (methodFullName.StartsWith(GenericMethodStart) && methodFullName.Contains(GenericMethodEnd))
                            {
                                var startIndex = methodFullName.IndexOf(GenericMethodStart, StringComparison.InvariantCulture) + 1;
                                var length     = methodFullName.IndexOf(GenericMethodEnd, StringComparison.InvariantCulture) - 1;
                                methodFullName = $"{methodFullName.Substring(startIndex, length)}(";
                            }

                            var numberOfOverloadedMethods = source.MethodDetails.Where(x =>
                                                                                       methodFullName.StartsWith($"{x.Method.MethodName()}(") ||
                                                                                       methodFullName.StartsWith($"set_{x.Method.MethodName()}(") ||
                                                                                       methodFullName.StartsWith($"get_{x.Method.MethodName()}(")).ToList();
                            MethodDetail methodDetail = null;
                            if (numberOfOverloadedMethods.Count == 1)
                            {
                                methodDetail = numberOfOverloadedMethods.First();
                            }

                            if (methodDetail == null)
                            {
                                methodDetail = source.MethodDetails
                                               .FirstOrDefault(x =>
                                                               x.Method.MethodWithParameterTypes() == methodFullName.Replace("System.", string.Empty));
                            }

                            string methodName;
                            if (methodDetail == null && coverageClassName.Contains(GenericMethodStart))
                            {
                                var startIndex = coverageClassName.IndexOf(GenericMethodStart, StringComparison.InvariantCulture);
                                var endIndex   = coverageClassName.IndexOf(GenericMethodEnd, StringComparison.InvariantCulture);
                                methodName   = coverageClassName.Substring(startIndex + 1, endIndex - startIndex - 1);
                                methodDetail = source.MethodDetails.FirstOrDefault(x => x.Method.MethodName().Equals(methodName));
                            }

                            if (methodDetail != null)
                            {
                                if (methodDetail.Coverage == null)
                                {
                                    methodDetail.Coverage = new Coverage();
                                }

                                methodDetail.Coverage = new Coverage
                                {
                                    LinesCovered     = methodDetail.Coverage.LinesCovered + mCoverage.LinesCovered,
                                    LinesNotCovered  = methodDetail.Coverage.LinesNotCovered + mCoverage.LinesNotCovered,
                                    BlocksCovered    = methodDetail.Coverage.BlocksCovered + mCoverage.BlocksCovered,
                                    BlocksNotCovered = methodDetail.Coverage.BlocksNotCovered + mCoverage.BlocksNotCovered
                                };

                                methodDetail.Lines.AddRange(mCoverage.GetLinesRows());
                                methodsWithCoverage.Add(methodDetail);
                            }
                        }
                    }

                    methodsWithCoverage = methodsWithCoverage.GroupBy(x => x.Method.MethodWithParameterTypes()).Select(x =>
                    {
                        var methodDetail = new MethodDetail
                        {
                            Coverage   = x.Last().Coverage,
                            Method     = x.First().Method,
                            MethodName = x.First().MethodName
                        };

                        methodDetail.Lines.AddRange(x.First().Lines);
                        return(methodDetail);
                    }).ToList();
                    foreach (var methodDetail in methodsWithCoverage)
                    {
                        var methodName = methodDetail.Method.MethodWithParameterTypes();
                        Output += $"{methodName} {methodDetail.Coverage.ToString().Print(color: Colors.BlueViolet)}".PrintWithPreTagWithMarginImportant();
                    }
                }

                PrintExternalCoveredClasses(source);
            }
        }
Example #12
0
        private static IList <ClassCoverage> FindExternalCoveredClasses(SourceClassDetail source, CoverageDSPriv codeCoverage)
        {
            var data           = new List <ClassCoverage>();
            var thirdPartyLibs = source.TestClaz.ClassProject
                                 .GetProjectThirdPartyLibraries()
                                 .Select(x => x
                                         .Split('\\')
                                         .Last()).ToList();

            thirdPartyLibs.Add("nunit");
            thirdPartyLibs.Add("microsoft.");
            if (codeCoverage != null)
            {
                var parentClassNameList = $"{source.Claz.Syntax.NameSpace()}.{string.Join(".", source.Claz.Syntax.Ancestors<ClassDeclarationSyntax>().Select(x => x.ClassNameWithoutGeneric()))}".TrimEnd('.');
                var nestedClassNameList = $"{parentClassNameList}.{source.Claz.Syntax.ClassNameWithoutGeneric()}.{string.Join(".", source.Claz.Syntax.DescendantNodes<ClassDeclarationSyntax>().Select(x => x.ClassNameWithoutGeneric()))}".TrimEnd('.');
                if (parentClassNameList == source.Claz.Syntax.NameSpace())
                {
                    parentClassNameList = $"{parentClassNameList}.{source.Claz.Syntax.ClassNameWithoutGeneric()}";
                }

                foreach (CoverageDSPriv.ClassRow claz in codeCoverage.Class)
                {
                    if (claz.LinesCovered > 0 && thirdPartyLibs.All(x => !claz.NamespaceTableRow.ModuleRow.ModuleName.StartsWith(x, StringComparison.InvariantCultureIgnoreCase)))
                    {
                        var className            = claz.ClassName;
                        var genericIndexLocation = claz.ClassName.IndexOf(GenericMethodStart, StringComparison.Ordinal);
                        if (genericIndexLocation != -1)
                        {
                            className = className.Substring(0, genericIndexLocation).TrimEnd('.');
                        }

                        var fullName = $"{claz.NamespaceTableRow.NamespaceName}.{className}";
                        if (data.All(x => x.ClassName != fullName) &&
                            !fullName.Contains(parentClassNameList) &&
                            !fullName.Contains(nestedClassNameList))
                        {
                            var coverages = codeCoverage
                                            .Class
                                            .Where(x => x.ClassName == className ||
                                                   x.ClassName.StartsWith($"{className}.{GenericMethodStart}") ||
                                                   x.ClassName.StartsWith($"{className}{GenericMethodStart}")).ToList();

                            coverages = coverages.Where(x => x.NamespaceTableRow.NamespaceKeyName == claz.NamespaceKeyName).ToList();

                            if (coverages.Any())
                            {
                                var methods         = codeCoverage.Method.Where(x => x.ClassKeyName == claz.ClassKeyName).ToList();
                                var method          = methods.FirstOrDefault();
                                var numberOfMutants = 0;
                                var excluded        = false;
                                var mutantsLines    = new List <int>();

                                uint autogeneratedLineCovered     = 0;
                                uint autogeneratedLineNonCovered  = 0;
                                uint autogeneratedBlockCovered    = 0;
                                uint autogeneratedBlockNonCovered = 0;

                                var file = string.Empty;
                                if (method != null)
                                {
                                    file = codeCoverage.SourceFileNames.FirstOrDefault(x => x.SourceFileID == method.GetLinesRows().FirstOrDefault()?.SourceFileID)?.SourceFileName;
                                    if (!string.IsNullOrWhiteSpace(file) && File.Exists(file))
                                    {
                                        var root             = file.GetCodeFileContent().RootNode().ClassNode(className.Split('.').Last());
                                        var classDeclaration = new ClassDeclaration(root);
                                        var classDetail      = new SourceClassDetail
                                        {
                                            Claz     = classDeclaration,
                                            TestClaz = new TestClassDetail()
                                        };

                                        if (root != null)
                                        {
                                            new MethodsInitializer().FindMethods(classDetail).Wait();
                                            var mutants = classDetail.MethodDetails
                                                          .Where(x => !x.IsProperty && !x.IsConstructor && !x.IsOverrideMethod)
                                                          .SelectMany(x => MutantOrchestrator.GetDefaultMutants(x.Method, classDetail.Claz));
                                            var coveredLines = claz.GetMethodRows().SelectMany(x => x.GetLinesRows()).Where(x => x.Coverage == 0).ToList();
                                            mutants         = mutants.Where(x => coveredLines.Any(y => y.LnStart == x.Mutation.Location)).ToList();
                                            mutantsLines    = mutants.Select(x => x.Mutation.Location ?? 0).ToList();
                                            numberOfMutants = mutants.Count();

                                            excluded = root.ExcludeFromExternalCoverage();

                                            var autogeneratedMethods = root.GetGeneratedCodeMethods();
                                            foreach (var methodSyntax in autogeneratedMethods)
                                            {
                                                var autoGeneratedCoverage = methods.FirstOrDefault(x => x.MethodFullName.Equals($"{methodSyntax.MethodName()}()") ||
                                                                                                   x.MethodName.Equals($"{methodSyntax.MethodName()}()"));
                                                if (autoGeneratedCoverage != null)
                                                {
                                                    autogeneratedLineCovered     += autoGeneratedCoverage.LinesCovered;
                                                    autogeneratedLineNonCovered  += autoGeneratedCoverage.LinesNotCovered;
                                                    autogeneratedBlockCovered    += autoGeneratedCoverage.BlocksCovered;
                                                    autogeneratedBlockNonCovered += autoGeneratedCoverage.BlocksNotCovered;
                                                }
                                            }

                                            if (methods.Any(x => x.MethodFullName.Equals($"{InitializecomponentMethod}()")) &&
                                                !autogeneratedMethods.Any() &&
                                                !classDetail.MethodDetails.Any(x => x.Method.MethodName().Equals(InitializecomponentMethod)))
                                            {
                                                var autoGeneratedCoverage = methods.First(x => x.MethodFullName.Equals($"{InitializecomponentMethod}()"));

                                                autogeneratedLineCovered     += autoGeneratedCoverage.LinesCovered;
                                                autogeneratedLineNonCovered  += autoGeneratedCoverage.LinesNotCovered;
                                                autogeneratedBlockCovered    += autoGeneratedCoverage.BlocksCovered;
                                                autogeneratedBlockNonCovered += autoGeneratedCoverage.BlocksNotCovered;
                                            }
                                        }
                                        else
                                        {
                                            excluded = true;
                                        }
                                    }
                                }

                                var classCoverage = new ClassCoverage
                                {
                                    ClassName = fullName,
                                    ClassPath = file,
                                    Coverage  = new Coverage {
                                        LinesCovered     = (uint)coverages.Sum(x => x.LinesCovered) - autogeneratedLineCovered,
                                        LinesNotCovered  = (uint)coverages.Sum(x => x.LinesNotCovered) - autogeneratedLineNonCovered,
                                        BlocksCovered    = (uint)coverages.Sum(x => x.BlocksCovered) - autogeneratedBlockCovered,
                                        BlocksNotCovered = (uint)coverages.Sum(x => x.BlocksNotCovered) - autogeneratedBlockNonCovered
                                    },
                                    NumberOfMutants = numberOfMutants,
                                    Excluded        = excluded
                                };

                                classCoverage.MutantsLines.AddRange(mutantsLines);
                                data.Add(classCoverage);
                            }
                        }
                    }
                }
            }

            return(data);
        }
Example #13
0
 public MutantInitializer(SourceClassDetail source, IMutantSelector selector = null)
 {
     _source   = source ?? throw new ArgumentNullException(nameof(source));
     _selector = selector ?? new MutantSelector();
 }
Example #14
0
        public async Task RunMutationTest(MuTestOptions options)
        {
            if (!File.Exists(MuTestSettings.MSBuildPath))
            {
                throw new MuTestInputException($"Unable to locate MSBuild Path at {MuTestSettings.MSBuildPath}. Please update MSBuildPath in MuTest.Console.exe.config if you are using different version");
            }

            if (!File.Exists(MuTestSettings.VSTestConsolePath))
            {
                throw new MuTestInputException($"Unable to locate VS Test Console Path at {MuTestSettings.VSTestConsolePath}. Please update VSTestConsolePath in MuTest.Console.exe.config if you are using different version");
            }

            if (!File.Exists(MuTestSettings.RunSettingsPath))
            {
                throw new MuTestInputException($"Unable to locate tests run settings path at {MuTestSettings.RunSettingsPath}. Please update RunSettingsPath in MuTest.Console.exe.config if you are using different location");
            }

            _stopwatch = new Stopwatch();
            _stopwatch.Start();

            _options = options;

            if (!_options.SkipTestProjectBuild)
            {
                var originalProject = _options.TestProjectParameter;
                if (_options.OptimizeTestProject &&
                    _options.MultipleTargetClasses.Count == 1)
                {
                    var targetClass = _options.MultipleTargetClasses.First();

                    _options.TestProjectParameter = _options
                                                    .TestProjectParameter
                                                    .UpdateTestProject(targetClass.TestClassPath.GetClass().ClassName());
                }

                await ExecuteBuild();

                if (!originalProject.Equals(_options.TestProjectParameter, StringComparison.InvariantCultureIgnoreCase))
                {
                    if (File.Exists(_options.TestProjectParameter))
                    {
                        File.Delete(_options.TestProjectParameter);
                    }

                    _options.TestProjectParameter = originalProject;
                }
            }

            var serial = 1;

            _chalk.Default("\n*********************************** Matched Classes ***********************************");
            foreach (var srcClass in _options.MultipleTargetClasses)
            {
                _chalk.Green($"\n{serial++}. {srcClass.ClassName} in {srcClass.ClassPath}");
            }

            _chalk.Default("\n***************************************************************************************");

            var projectSummary = new ProjectSummary
            {
                SourceProject = _options.SourceProjectParameter,
                TestProject   = _options.TestProjectParameter
            };

            var mutantAnalyzer = new MutantAnalyzer(_chalk, MuTestSettings)
            {
                ProcessWholeProject   = _options.ProcessWholeProject,
                BuildInReleaseMode    = _options.BuildInReleaseModeParameter,
                ConcurrentTestRunners = _options.ConcurrentTestRunners,
                EnableDiagnostics     = _options.EnableDiagnostics,
                ExecuteAllTests       = _options.ExecuteAllTests,
                IncludeNestedClasses  = _options.IncludeNestedClasses,
                IncludePartialClasses = _options.IncludePartialClasses ||
                                        _options.UseClassFilter ||
                                        _options.ExecuteAllTests,
                KilledThreshold    = _options.KilledThreshold,
                NoCoverage         = _options.NoCoverage,
                RegEx              = _options.RegEx,
                Specific           = _options.Specific,
                SurvivedThreshold  = _options.SurvivedThreshold,
                TestProject        = _options.TestProjectParameter,
                TestProjectLibrary = _options.TestProjectLibraryParameter,
                UseClassFilter     = _options.UseClassFilter,
                X64TargetPlatform  = _options.X64TargetPlatform,
                TestExecutionTime  = _options.TestExecutionThreshold,
                MutantsPerLine     = _options.MutantsPerLine
            };

            foreach (var targetClass in _options.MultipleTargetClasses)
            {
                mutantAnalyzer.TestClass = targetClass.TestClassPath;
                mutantAnalyzer.UseExternalCodeCoverage = false;
                mutantAnalyzer.MutantExecutor          = null;
                var sourceClass = targetClass.ClassPath;
                var className   = targetClass.ClassName;
                mutantAnalyzer.SourceProjectLibrary = _options.SourceProjectLibraryParameter;

                try
                {
                    var sourceHash = sourceClass.GetCodeFileContent().ComputeHash();
                    var testHash   = targetClass.TestClassPath.GetCodeFileContent().ComputeHash();
                    var hash       = $"{sourceHash}-{testHash}".ComputeHash();

                    await GetFromDB(hash);

                    if (_source != null)
                    {
                        var testClaz = targetClass.TestClassPath.GetClass();
                        var loader   = new SemanticsClassDeclarationLoader();
                        _source.Claz         = loader.Load(sourceClass, _options.SourceProjectParameter, className);
                        _source.ClassLibrary = _options.SourceProjectLibraryParameter;
                        _source.ClassProject = _options.SourceProjectParameter;
                        _source.FilePath     = sourceClass;

                        _source.TestClaz = new TestClassDetail
                        {
                            Claz              = new ClassDeclaration(testClaz),
                            FilePath          = targetClass.TestClassPath,
                            ClassProject      = _options.TestProjectParameter,
                            FullName          = testClaz.FullName(),
                            ClassLibrary      = _options.TestProjectLibraryParameter,
                            X64TargetPlatform = _options.X64TargetPlatform
                        };
                    }

                    if (_source == null)
                    {
                        mutantAnalyzer.ExternalCoveredMutants.Clear();
                        _source = await mutantAnalyzer.Analyze(sourceClass, className, _options.SourceProjectParameter);

                        _source.SHA256    = hash;
                        _source.StoreToDb = true;

                        if (_source.ExternalCoveredClassesIncluded.Any() && _options.AnalyzeExternalCoveredClasses)
                        {
                            _chalk.Yellow("\n\nAnalyzing External Coverage...");
                            mutantAnalyzer.UseExternalCodeCoverage = true;
                            foreach (var acc in _source.ExternalCoveredClassesIncluded)
                            {
                                mutantAnalyzer.ExternalCoveredMutants.AddRange(acc.MutantsLines);
                                var projectFile = new FileInfo(acc.ClassPath).FindProjectFile();
                                mutantAnalyzer.SourceProjectLibrary = projectFile.FindLibraryPath()?.FullName;
                                if (!string.IsNullOrWhiteSpace(mutantAnalyzer.SourceProjectLibrary))
                                {
                                    var accClass = await mutantAnalyzer.Analyze(
                                        acc.ClassPath,
                                        acc.ClassName,
                                        projectFile.FullName);

                                    accClass.CalculateMutationScore();

                                    if (accClass.MutationScore.Survived == 0)
                                    {
                                        acc.ZeroSurvivedMutants = true;
                                    }
                                }
                            }

                            mutantAnalyzer.ExternalCoveredMutants.Clear();
                        }
                    }
                }
                catch (Exception ex) when(!(ex is MuTestInputException))
                {
                    throw;
                }
                finally
                {
                    MutantExecutor = mutantAnalyzer.MutantExecutor ?? new MutantExecutor(_source, MuTestSettings);
                    _stopwatch.Stop();
                    if (_source != null)
                    {
                        await GenerateReports();

                        if (!string.IsNullOrWhiteSpace(_options.ProcessWholeProject))
                        {
                            projectSummary.Classes.Add(new ClassSummary
                            {
                                TargetClass = new TargetClass
                                {
                                    ClassPath     = _source.FilePath,
                                    ClassName     = _source.Claz.Syntax.FullName(),
                                    TestClassPath = _source.TestClaz.FilePath
                                },
                                MutationScore = _source.MutationScore,
                                Coverage      = _source.Coverage ?? new Coverage()
                            });
                        }
                    }
                }
            }

            if (!string.IsNullOrWhiteSpace(_options.ProcessWholeProject))
            {
                projectSummary.CalculateMutationScore();
                var builder = new StringBuilder(HtmlTemplate);
                builder.AppendLine("<fieldset style=\"margin-bottom:10; margin-top:10\">");
                builder.AppendLine("Mutation Report".PrintImportantWithLegend());
                builder.Append("  ".PrintWithPreTag());
                builder.Append($"{"Source Project:".PrintImportant()} {projectSummary.SourceProject}".PrintWithPreTag());
                builder.Append($"{"Test Project  :".PrintImportant()} {projectSummary.TestProject}".PrintWithPreTag());
                builder.Append("  ".PrintWithPreTag());

                builder.AppendLine("<fieldset style=\"margin-bottom:10; margin-top:10\">");
                builder.AppendLine("Classes Mutation".PrintImportantWithLegend());
                foreach (var claz in projectSummary.Classes)
                {
                    builder.AppendLine("<fieldset style=\"margin-bottom:10; margin-top:10\">");

                    builder.AppendLine($"{claz.TargetClass.ClassName} [{claz.TargetClass.ClassPath}]".PrintImportantWithLegend(color: Colors.BlueViolet));
                    builder.Append($"{claz.MutationScore.Mutation} - {claz.MutationScore}".PrintWithPreTagWithMarginImportant());
                    builder.Append($"Code Coverage - {claz.Coverage}".PrintWithPreTagWithMarginImportant());

                    builder.AppendLine("</fieldset>");
                }

                builder.AppendLine("</fieldset>");

                builder.AppendLine("<fieldset style=\"margin-bottom:10; margin-top:10\">");
                builder.AppendLine("ProjectWise Summary".PrintImportantWithLegend());
                builder.Append(projectSummary.MutationScore.ToString().PrintWithPreTagWithMarginImportant(color: Colors.BlueViolet));
                builder.Append($"Coverage: Mutation({projectSummary.MutationScore.Mutation}) {projectSummary.Coverage}".PrintWithPreTagWithMarginImportant(color: Colors.Blue));
                builder.AppendLine("</fieldset>");
                builder.AppendLine("</fieldset>");

                CreateHtmlReport(builder, ProjectSummary);
                await CreateJsonReport(ProjectSummary, projectSummary);
            }
        }
Example #15
0
 public MutantExecutor(SourceClassDetail source, MuTestSettings settings)
 {
     _source           = source ?? throw new ArgumentNullException(nameof(source));
     _directoryFactory = new TestDirectoryFactory(_source);
     _settings         = settings;
 }
 public TestDirectoryFactory(SourceClassDetail source)
 {
     _source = source ?? throw new ArgumentNullException(nameof(source));
 }
 public static MutantViewerViewModel Create(SourceClassDetail source)
 {
     return(ViewModelSource.Create(() => new MutantViewerViewModel(source)));
 }
Example #18
0
        public async Task <SourceClassDetail> Analyze(string sourceClass, string className, string sourceProject)
        {
            var testClaz = TestClass.GetClass();
            var semanticsClassDeclarationLoader = new SemanticsClassDeclarationLoader();
            var source = new SourceClassDetail
            {
                ClassLibrary       = SourceProjectLibrary,
                ClassProject       = sourceProject,
                BuildInReleaseMode = BuildInReleaseMode,
                Claz              = semanticsClassDeclarationLoader.Load(sourceClass, sourceProject, className),
                FullName          = className,
                FilePath          = sourceClass,
                X64TargetPlatform = X64TargetPlatform,
                TestClaz          = new TestClassDetail
                {
                    Claz = new ClassDeclaration(testClaz),
                    BuildInReleaseMode = BuildInReleaseMode,
                    ClassLibrary       = TestProjectLibrary,
                    ClassProject       = TestProject,
                    FilePath           = TestClass,
                    FullName           = testClaz.FullName(),
                    X64TargetPlatform  = X64TargetPlatform
                }
            };

            _chalk.Yellow($"\nProcessing source class {source.DisplayName}");
            _chalk.Yellow($"\nTest class {source.TestClaz.DisplayName}");

            source.TestClaz.PartialClasses.Clear();
            source.TestClaz.PartialClasses.Add(new ClassDetail
            {
                Claz     = source.TestClaz.Claz,
                FilePath = source.TestClaz.FilePath
            });

            var baseListSyntax = source.TestClaz.Claz.Syntax.BaseList;

            if (baseListSyntax != null &&
                baseListSyntax.Types.Any())
            {
                foreach (var type in baseListSyntax.Types)
                {
                    var typeSyntax = type.Type;
                    var fileName   = typeSyntax.ToString();
                    if (typeSyntax is GenericNameSyntax syntax)
                    {
                        fileName = syntax.Identifier.ValueText;
                    }

                    if (Path.GetDirectoryName(TestProject)
                        .FindFile($"{fileName}.cs")?
                        .GetCodeFileContent()
                        .RootNode() is CompilationUnitSyntax baseFile)
                    {
                        source.TestClaz.BaseClass = baseFile;
                    }
                }
            }

            if (IncludePartialClasses)
            {
                var testProjectFiles = Path.GetDirectoryName(TestClass).GetCSharpClassDeclarations();
                var testClassDetails = testProjectFiles
                                       .SelectMany(cu => cu.CompilationUnitSyntax.DescendantNodes <ClassDeclarationSyntax>(),
                                                   (cu, classDeclarationSyntax) => new TestClassDetail
                {
                    FullName             = $"{cu.CompilationUnitSyntax.NameSpace()}.{classDeclarationSyntax.Identifier.Text}",
                    FilePath             = cu.FileName,
                    TotalNumberOfMethods = classDeclarationSyntax.DescendantNodes <MethodDeclarationSyntax>().Count,
                    Claz = new ClassDeclaration(classDeclarationSyntax)
                }).Where(x => x.TotalNumberOfMethods > 0)
                                       .OrderByDescending(x => x.TotalNumberOfMethods)
                                       .ToList();

                foreach (var data in testClassDetails)
                {
                    if (!source.TestClaz.PartialClassNodesAdded &&
                        source.TestClaz.FullName == data.FullName &&
                        data.FilePath != source.TestClaz.FilePath)
                    {
                        source.TestClaz.PartialClasses.Add(data);
                    }
                }

                source.TestClaz.PartialClassNodesAdded = true;
            }

            await Initialization(source);

            return(source);
        }
Example #19
0
        private async Task FindTestExecutionTime(SourceClassDetail source)
        {
            _chalk.Default("\nFinding Tests Execution Time...");
            var log = new StringBuilder();

            void OutputData(object sender, string args) => log.AppendLine(args);

            var testExecutor = new TestExecutor(_settings, source.TestClaz.ClassLibrary)
            {
                X64TargetPlatform  = X64TargetPlatform,
                FullyQualifiedName = source.TestClaz.MethodDetails.Count > _useClassFilterTestsThreshold ||
                                     UseClassFilter || source.TestClaz.BaseClass != null
                    ? source.TestClaz.Claz.Syntax.FullName()
                    : string.Empty,
                EnableLogging       = true,
                EnableCustomOptions = false
            };

            testExecutor.OutputDataReceived += OutputData;

            await testExecutor.ExecuteTests(source.TestClaz.MethodDetails.ToList());

            testExecutor.OutputDataReceived -= OutputData;

            if (testExecutor.LastTestExecutionStatus != Constants.TestExecutionStatus.Success)
            {
                throw new MuTestFailingTestException(log.ToString());
            }

            if (testExecutor.TestResult?.Results?.UnitTestResult != null)
            {
                var tests = testExecutor.TestResult?.Results?.UnitTestResult;
                foreach (var test in tests)
                {
                    var executionTime = 0d;
                    if (test.Duration != null)
                    {
                        executionTime = TimeSpan.Parse(test.Duration).TotalMilliseconds;
                    }

                    if (executionTime <= TestExecutionTime)
                    {
                        source.TestExecutionTimes.Add(new TestExecutionTime(test.TestName, executionTime));
                    }
                    else
                    {
                        source.TestExecutionTimesAboveThreshold.Add(new TestExecutionTime(test.TestName, executionTime));
                    }
                }

                source.TestExecutionTimes.Sort((x1, x2) => x2.ExecutionTime.CompareTo(x1.ExecutionTime));
                source.TestExecutionTimesAboveThreshold.Sort((x1, x2) => x2.ExecutionTime.CompareTo(x1.ExecutionTime));

                foreach (var test in source.TestExecutionTimesAboveThreshold)
                {
                    _chalk.Red($"\n  {test.TestName} ({test.ExecutionTime}ms)");
                }

                foreach (var test in source.TestExecutionTimes)
                {
                    _chalk.Green($"\n  {test.TestName} ({test.ExecutionTime}ms)");
                }
            }
        }
Example #20
0
        public async Task FindMethods(SourceClassDetail source)
        {
            if (source.Claz == null)
            {
                return;
            }

            source.MethodDetails.Clear();

            var index = 1;
            IList <MethodDeclarationSyntax>      sourceMethods;
            IList <ConstructorDeclarationSyntax> constructorMethods;
            IList <PropertyDeclarationSyntax>    sourceProperties;

            if (IncludeNestedClasses)
            {
                sourceMethods = source
                                .Claz
                                .Syntax
                                .Root()
                                .GetMethods()
                                .OrderBy(x => x.MethodName()).ToList();

                constructorMethods = source
                                     .Claz
                                     .Syntax
                                     .Root()
                                     .DescendantNodes <ConstructorDeclarationSyntax>()
                                     .OrderBy(x => x.MethodName())
                                     .ToList();

                sourceProperties = source
                                   .Claz
                                   .Syntax
                                   .Root()
                                   .DescendantNodes <PropertyDeclarationSyntax>()
                                   .Where(x => MutantOrchestrator.GetDefaultMutants(x, source.Claz).Any())
                                   .OrderBy(x => x.Identifier.ValueText)
                                   .ToList();
            }
            else
            {
                var parentClassNodesCount = source.Claz?.Syntax.AncestorsAndSelf().OfType <ClassDeclarationSyntax>().Count() ?? 0;
                sourceMethods = source
                                .Claz
                                .Syntax
                                .GetMethods()
                                .Where(x => x.Ancestors <ClassDeclarationSyntax>().Count == parentClassNodesCount)
                                .OrderBy(x => x.MethodName())
                                .ToList();

                constructorMethods = source
                                     .Claz
                                     .Syntax
                                     .DescendantNodes <ConstructorDeclarationSyntax>()
                                     .Where(x => x.Ancestors <ClassDeclarationSyntax>().Count == parentClassNodesCount)
                                     .OrderBy(x => x.MethodName())
                                     .ToList();

                sourceProperties = source
                                   .Claz
                                   .Syntax
                                   .DescendantNodes <PropertyDeclarationSyntax>()
                                   .Where(x => x.Ancestors <ClassDeclarationSyntax>().Count == parentClassNodesCount)
                                   .Where(x => MutantOrchestrator.GetDefaultMutants(x, source.Claz).Any())
                                   .OrderBy(x => x.Identifier.ValueText)
                                   .ToList();
            }

            source.MethodDetails.AddRange(sourceMethods
                                          .Select(x =>
                                                  new MethodDetail
            {
                MethodName       = $"{index++}. {x.MethodName()}{x.DescendantNodes<ParameterListSyntax>().FirstOrDefault()}",
                Method           = x,
                IsOverrideMethod = x.IsOverride()
            }));


            source.MethodDetails.AddRange(constructorMethods
                                          .Select(x =>
                                                  new MethodDetail
            {
                MethodName    = $"{index++}. {x.MethodName()}{x.DescendantNodes<ParameterListSyntax>().FirstOrDefault()}",
                Method        = x,
                IsConstructor = true
            }));

            source.MethodDetails.AddRange(sourceProperties
                                          .Select(x => new MethodDetail
            {
                MethodName = $"{index++}. Property - {x.Identifier.ValueText}",
                Method     = x,
                IsProperty = true
            }));

            source.TestClaz.MethodDetails.Clear();
            if (source.TestClaz.BaseClass != null)
            {
                source.TestClaz.MethodDetails.AddRange(GetTestMethods(source.TestClaz.BaseClass));
            }

            foreach (var partialClass in source.TestClaz.PartialClasses)
            {
                source.TestClaz.MethodDetails.AddRange(GetTestMethods(partialClass.Claz.Syntax));
            }
        }