Example #1
0
        public void Notify(RepositoryCoverageEntity coverageEntity, IList <CoverageEntity> methodList)
        {
            Console.WriteLine($"Email From: {_from}");
            Console.WriteLine($"To: {string.Join(',', _toList)}");

            var query = methodList.AsQueryable();

            query = query.Where(i => i.Repository == coverageEntity.Repository);
            if (string.IsNullOrWhiteSpace(coverageEntity.Project) == false)
            {
                query = query.Where(i => i.Project == coverageEntity.Project);
            }
            var projectMethod = query.ToList();

            var downMethod        = projectMethod.Where(i => i.Status == CoverageStatus.Down).ToList();
            var updateMethodCount = projectMethod.Count(i => i.IsUpdate);

            var subject = $"Phanerozic - {downMethod.Count}/{updateMethodCount}/{projectMethod.Count} - {coverageEntity.Repository} - {coverageEntity.Project}";

            var stringBuilder = new StringBuilder();

            stringBuilder.AppendLine($"Repository: {coverageEntity.Repository}");
            if (string.IsNullOrWhiteSpace(coverageEntity.Project) == false)
            {
                stringBuilder.AppendLine($"Project: {coverageEntity.Project}");
            }
            stringBuilder.AppendLine($"Project Method Count: {projectMethod.Count}");
            stringBuilder.AppendLine($"Update Method Count: {updateMethodCount}");
            stringBuilder.AppendLine($"Coverage Down Method Count: {downMethod.Count}");
            downMethod.ForEach(i => stringBuilder.AppendLine($"{i.Class}.{i.Method}: {i.TargetCoverage} → {i.Coverage}"));

            _emailService.Send(_from, _toList, subject, stringBuilder.ToString());
        }
Example #2
0
        public IList <CoverageEntity> Parser(RepositoryCoverageEntity coverageEntity, ReportEntity reportEntity)
        {
            var json   = this._fileHelper.ReadAllText(reportEntity.FilePath);
            var report = JsonSerializer.Deserialize <DotCoverReport>(json);

            var result = new List <CoverageEntity>();

            FindMethod(result, string.Empty, null, report.Children);

            //// Method without argument
            //// Set Repository
            result.ForEach(i =>
            {
                if (i.Method.Contains('('))
                {
                    i.Method = i.Method.Substring(0, i.Method.IndexOf('('));
                }
                i.Repository = coverageEntity.Repository;
            });

            //// Print Method
            if (this._printMethod)
            {
                result.ForEach(i => Console.WriteLine(i.ToString()));
            }

            Console.WriteLine($"Report Method Count: {result.Count}");

            return(result);
        }
Example #3
0
        public void Collect_FileName()
        {
            //// Arrange
            var repositoryName = "Office.Repository";
            var projectName    = "Office.Project";
            var outputPath     = "C:";
            var dateTime       = new DateTime(2020, 1, 18);
            var excpted        = Path.Combine(outputPath, $"{repositoryName}_{dateTime.ToString("yyyyMMdd")}.json");

            IList <CoverageEntity>   methodList     = new List <CoverageEntity>();
            RepositoryCoverageEntity coverageEntity = new RepositoryCoverageEntity
            {
                Repository = repositoryName,
                Project    = projectName,
                OutputPath = outputPath,
            };

            this._stubDateTimeHelper.Now.Returns(dateTime);

            //// Act
            var actual = GetTarget().Collect(coverageEntity, methodList);

            //// Assert
            actual.Should().BeEquivalentTo(excpted);
        }
Example #4
0
        public void NotifyTest()
        {
            //// Assert
            string repository     = "Phanerozoic";
            string project        = "Phanerozoic.Core";
            var    coverageEntity = new RepositoryCoverageEntity
            {
                Repository = repository,
                Project    = project,
            };
            var methodList = new List <CoverageEntity>
            {
                new CoverageEntity
                {
                    Repository = repository,
                    Project    = project,
                    Class      = "SomeClass",
                    Method     = "SomeMethod",
                    Coverage   = 12,
                }
            };

            this._configuration["Notification:To"].Returns("*****@*****.**");

            //// Act
            EmailNotifyer target = this.GetTarget();

            target.Notify(coverageEntity, methodList);

            //// Arrange
        }
Example #5
0
        public void Test_Process_Flow()
        {
            //// arrange
            this._stubFileHelper.Exists(Arg.Any <string>()).Returns(true);
            var reportEntity = new ReportEntity
            {
                FilePath = "report.json"
            };
            var coverageEntity = new RepositoryCoverageEntity
            {
                CoverageFileName = "coverage.csv"
            };

            var target = GetTarget();

            //// act
            target.Process(reportEntity, coverageEntity);

            //// assert
            this._stubReportParser.Received(1).Parser(Arg.Any <RepositoryCoverageEntity>(), Arg.Any <ReportEntity>());
            this._stubCoverageUpdater.Received(1).Update(Arg.Any <RepositoryCoverageEntity>(), Arg.Any <IList <CoverageEntity> >());
            this._stubNotifyer.Received(1).Notify(Arg.Any <RepositoryCoverageEntity>(), Arg.Any <IList <CoverageEntity> >());
            this._stubEmailNotifyer.Received(1).Notify(Arg.Any <RepositoryCoverageEntity>(), Arg.Any <IList <CoverageEntity> >());
            this._stubCoverageLogger.Received(1).Log(Arg.Any <IList <CoverageEntity> >());
        }
Example #6
0
        public void Process(ReportEntity reportEntity, RepositoryCoverageEntity coverageEntity)
        {
            if (this._fileHelper.Exists(reportEntity.FilePath) == false)
            {
                Console.WriteLine($"File Not Found: {reportEntity.FilePath}");
                throw new FileNotFoundException("File Not Found!", reportEntity.FilePath);
            }

            //// Parser
            Console.WriteLine("* Parser");
            var methodList = this._reportParser.Parser(coverageEntity, reportEntity);

            //// Update
            Console.WriteLine("* Update");
            var updateMethodList = this._coverageUpdater.Update(coverageEntity, methodList);

            //// Notify
            Console.WriteLine("* Notify");
            if (IsSendSlack())
            {
                this.GetSlackNotifyer().Notify(coverageEntity, updateMethodList);
            }
            this.GetEmailNotifyer().Notify(coverageEntity, updateMethodList);

            //// Log
            Console.WriteLine("* Log");
            this._coverageLogger.Log(updateMethodList);
        }
Example #7
0
        public void Notify(RepositoryCoverageEntity coverageEntity, IList <CoverageEntity> methodList)
        {
            var slackMessageJson = GetSlackMessage(coverageEntity, methodList);

            if (string.IsNullOrWhiteSpace(slackMessageJson))
            {
                return;
            }

            _slackService.SendAsync(_webHookUrl, slackMessageJson);
        }
        public IList <CoverageEntity> Update(RepositoryCoverageEntity coverageEntity, IList <CoverageEntity> reportMethodList)
        {
            var reportMethodTotalCount = reportMethodList.Count;

            reportMethodList = FilterMethod(coverageEntity, reportMethodList);
            Console.WriteLine("** Report Method");
            Console.WriteLine($"Repository: {coverageEntity.Repository}, Project: {coverageEntity.Project}, Method Count: {reportMethodList.Count}/{reportMethodTotalCount}");

            IList <CoverageEntity> sheetMethodList = _coverageReader.GetList();

            var sheetMethodTotalCount = sheetMethodList.Count;

            sheetMethodList = FilterMethod(coverageEntity, sheetMethodList);
            Console.WriteLine("** Sheet Method");
            Console.WriteLine($"Repository: {coverageEntity.Repository}, Project: {coverageEntity.Project}, Method Count: {sheetMethodList.Count}/{sheetMethodTotalCount}");
            if (sheetMethodList.Count <= 0 || reportMethodList.Count <= 0)
            {
                Console.WriteLine($"No Update. Report Count: {reportMethodList.Count}, Sheet Count: {sheetMethodList.Count}");
                return(sheetMethodList);
            }

            var updateCount = 0;

            foreach (var coreMethod in sheetMethodList)
            {
                var reportMethod = reportMethodList.FirstOrDefault(i => i.Equals(coreMethod));

                if (reportMethod == null)
                {
                    continue;
                }
                updateCount++;

                coreMethod.UpdateCoverage(reportMethod);

                var symbol = SymbolDictionary[coreMethod.Status];

                Console.WriteLine($"{coreMethod.Class}.{coreMethod.Method}: {coreMethod.LastCoverage} {symbol} {coreMethod.Coverage}, Target: {coreMethod.TargetCoverage}, {(coreMethod.IsPass ? "Pass" : "Fail")}");

                if (coreMethod.Status != CoverageStatus.Unchange || coreMethod.Coverage == 0)
                {
                    UpdateCell($"F{coreMethod.RawIndex}", coreMethod.Coverage);
                }
                //// 目標涵蓋率小於0則不更新
                if (coreMethod.TargetCoverage > -1 && (coreMethod.TargetCoverage != coreMethod.NewTargetCoverage || coreMethod.NewTargetCoverage == 0))
                {
                    UpdateCell($"H{coreMethod.RawIndex}", coreMethod.NewTargetCoverage);
                }
                UpdateCell($"M{coreMethod.RawIndex}", DateTime.Now.ToString(DateTimeHelper.Format));
            }
            Console.WriteLine($"Update Rate: {updateCount}/{sheetMethodList.Count}");

            return(sheetMethodList);
        }
Example #9
0
        /// <summary>
        /// Loads the collect.
        /// </summary>
        /// <param name="coverageEntity">The coverage entity.</param>
        /// <returns></returns>
        public IList <CoverageEntity> LoadCollect(RepositoryCoverageEntity coverageEntity)
        {
            var fileName = GetFileName(coverageEntity);

            Console.WriteLine($"Collect File Name: {fileName}");

            //// Load File
            var fileMethodList = LoadCoverage(fileName);

            return(fileMethodList);
        }
Example #10
0
        private static void Main(string[] args)
        {
            // create service collection
            var serviceCollection = new ServiceCollection();
            var configuration     = ConfigureServices(serviceCollection, args);

            // create service provider
            var serviceProvider = serviceCollection.BuildServiceProvider();

            var reportEntity = new ReportEntity
            {
                FilePath = configuration[Arguments.Report]?.Trim(),
            };

            var file     = new FileInfo(reportEntity.FilePath);
            var fileName = file.Name;

            fileName = fileName.Substring(0, fileName.LastIndexOf('.'));
            var coverageEntity = new RepositoryCoverageEntity
            {
                CoverageFileName = $"{fileName}.csv",
                OutputPath       = file.DirectoryName,
                Repository       = configuration[Arguments.Repository]?.Trim(),
                Project          = configuration[Arguments.Project]?.Trim(),
            };

            var coverageProcessor = serviceProvider.GetService <ICoverageProcessor>();

            var mode = string.IsNullOrWhiteSpace(configuration[Arguments.Mode]) == false ? configuration[Arguments.Mode].ToEnum <ModeType>() : ModeType.Full;

            System.Console.WriteLine($"Mode: {mode}");
            switch (mode)
            {
            case ModeType.Parse:
                System.Console.WriteLine("Parser And Collect");
                coverageProcessor.ProcessParserAndCollect(reportEntity, coverageEntity);
                break;

            case ModeType.Update:
                System.Console.WriteLine("Load From Collect. Update And Nofity");
                coverageProcessor.ProcessUpdateAndNotify(coverageEntity);
                break;

            case ModeType.Full:
            default:
                System.Console.WriteLine("Parser, Update And Notify");
                coverageProcessor.Process(reportEntity, coverageEntity);
                break;
            }

            serviceProvider.Dispose();
        }
        /// <summary>
        /// 只保留指定的 Repository 與 Project 下的方法
        /// </summary>
        /// <param name="coverageEntity"></param>
        /// <param name="methodList"></param>
        /// <returns></returns>
        private IList <CoverageEntity> FilterMethod(RepositoryCoverageEntity coverageEntity, IList <CoverageEntity> methodList)
        {
            var query = methodList.AsQueryable();

            query = query.Where(i => i.Repository == coverageEntity.Repository);

            if (string.IsNullOrWhiteSpace(coverageEntity.Project) == false)
            {
                query = query.Where(i => i.Project == coverageEntity.Project);
            }

            return(query.ToList());
        }
Example #12
0
        /// <summary>
        /// 將同一個 Solution 不同 Test Project 的 Coverage 合併
        /// </summary>
        /// <param name="coverageEntity">The coverage entity.</param>
        /// <param name="methodList">The method list.</param>
        /// <returns></returns>
        public string Collect(RepositoryCoverageEntity coverageEntity, IList <CoverageEntity> methodList)
        {
            var fileMethodList = LoadCollect(coverageEntity);

            //// Update Coverage
            MergeCoverage(methodList, ref fileMethodList);

            var fileName = GetFileName(coverageEntity);

            //// Save File
            SaveCoverage(fileName, fileMethodList);

            return(fileName);
        }
        public void Test_取得目前的涵蓋率()
        {
            //// Arrange
            var coverageEntity = new RepositoryCoverageEntity();
            var methodList     = new List <CoverageEntity>();

            this._stubConfiguration["Google.Sheets.SheetsId"].Returns("target Id");

            //// Act
            var target = new GoogleSheetsUpdater(this._stubServiceProvider, this._stubConfiguration);

            target.Update(coverageEntity, methodList);

            //// Assert
            this._stubGoogleSheetsService.Received(1).GetValues(Arg.Any <string>(), Arg.Any <string>());
        }
Example #14
0
        /// <summary>
        /// 讀取涵蓋率
        /// </summary>
        /// <param name="reportEntity">The report entity.</param>
        /// <param name="coverageEntity">The coverage entity.</param>
        /// <exception cref="NotImplementedException"></exception>
        public void ProcessParserAndCollect(ReportEntity reportEntity, RepositoryCoverageEntity coverageEntity)
        {
            if (this._fileHelper.Exists(reportEntity.FilePath) == false)
            {
                Console.WriteLine($"File Not Found: {reportEntity.FilePath}");
                throw new FileNotFoundException("File Not Found!", reportEntity.FilePath);
            }

            //// Parser
            Console.WriteLine("* Parser");
            var methodList = this._reportParser.Parser(coverageEntity, reportEntity);

            //// Log
            Console.WriteLine("* Collect");
            this._coverageCollect.Collect(coverageEntity, methodList);
        }
Example #15
0
        private string GetSlackMessage(RepositoryCoverageEntity coverageEntity, IList <CoverageEntity> methodList)
        {
            var failCount = methodList.Count(i => i.IsPass == false);

            if (failCount == 0)
            {
                return(null);
            }

            var color   = failCount > 0 ? "#FF0000" : "#00FF00";
            var project = string.Empty;

            if (string.IsNullOrWhiteSpace(coverageEntity.Project) == false)
            {
                project = $"Project: {coverageEntity.Project} ";
            }
            var title      = $"{project}涵蓋率未通過數量: {failCount}";
            var attachment = new Attachment
            {
                Color      = color,
                AuthorName = $"Repository: {coverageEntity.Repository}",
                Title      = title,
                Footer     = $"Phanerozoic Notifyer",
            };

            var stringBuilder = new StringBuilder();

            foreach (var method in methodList)
            {
                if (method.IsPass == false)
                {
                    var msg = $"{method.ToString()} < {method.TargetCoverage}";
                    msg += TagGroup(method);
                    stringBuilder.AppendLine(msg);
                }
            }
            attachment.Text = stringBuilder.ToString();

            var slackMessage = new SlackMessage
            {
                Attachments = new List <Attachment> {
                    attachment
                }
            };

            return(slackMessage.ToJson());
        }
Example #16
0
        public void Test_Update_Flow()
        {
            //// Arrange
            var methodList     = new List <CoverageEntity>();
            var coverageEntity = new RepositoryCoverageEntity
            {
                CoverageFileName = "a.txt",
                OutputPath       = @"D:\",
            };

            //// Act
            var target = new FileUpdater(this._stubServiceProvider);

            target.Update(coverageEntity, methodList);

            //// Assert
            this._stubFileHelper.Received(1).WriteAllText(Arg.Any <string>(), Arg.Any <string>());
        }
        public void Test涵蓋率未下降則不發通知()
        {
            //// Arrange
            var coverageEntity = new RepositoryCoverageEntity
            {
                Repository = "Phanerozoic"
            };

            var reportMethod = new CoverageEntity
            {
                Class    = "AClass",
                Method   = "AMethod",
                Coverage = 23,
            };
            var sheetMethod = new CoverageEntity
            {
                Class    = "AClass",
                Method   = "AMethod",
                Coverage = 23,
            };

            sheetMethod.UpdateCoverage(reportMethod);

            var methodList = new List <CoverageEntity>
            {
                sheetMethod,
            };

            var stringBuilder = new StringBuilder();

            stringBuilder.AppendLine(sheetMethod.ToString());
            var expectedMessage = stringBuilder.ToString();

            //// Act
            var target = GetTarget();

            target.Notify(coverageEntity, methodList);

            //// Assert
            this._stubSlackService.DidNotReceiveWithAnyArgs().SendAsync(string.Empty, Arg.Any <string>());
        }
Example #18
0
        public IList <CoverageEntity> Update(RepositoryCoverageEntity coverageEntity, IList <CoverageEntity> methodList)
        {
            var stringBuilder = new StringBuilder();

            var filterMethodList = methodList.Where(i => i.Class.StartsWith("Xunit") == false).ToList();

            filterMethodList.ForEach(i =>
            {
                var className = i.Class;
                var method    = i.Method;
                method        = method.Substring(0, method.IndexOf('('));
                var row       = $"\"{className}\",\"{method}\",{i.Coverage}";
                stringBuilder.AppendLine(row);
            });

            string contents = stringBuilder.ToString();

            _fileHelper.WriteAllText(coverageEntity.CoverageFile, contents);

            return(methodList);
        }
Example #19
0
        /// <summary>
        /// 更新涵蓋率及通知
        /// </summary>
        /// <param name="reportEntity">The report entity.</param>
        /// <param name="coverageEntity">The coverage entity.</param>
        /// <exception cref="NotImplementedException"></exception>
        public void ProcessUpdateAndNotify(RepositoryCoverageEntity coverageEntity)
        {
            //// Load Coverage From Collect
            Console.WriteLine("* Collect");
            var methodList = this._coverageCollect.LoadCollect(coverageEntity);

            //// Update
            Console.WriteLine("* Update");
            var updateMethodList = this._coverageUpdater.Update(coverageEntity, methodList);

            //// Notify
            Console.WriteLine("* Notify");
            if (IsSendSlack())
            {
                this.GetSlackNotifyer().Notify(coverageEntity, updateMethodList);
            }
            this.GetEmailNotifyer().Notify(coverageEntity, updateMethodList);

            //// Log
            Console.WriteLine("* Log");
            this._coverageLogger.Log(updateMethodList);
        }
Example #20
0
        public void Test_Process_Flow_FileNotFound()
        {
            //// arrange
            this._stubFileHelper.Exists(Arg.Any <string>()).Returns(false);
            var reportEntity = new ReportEntity
            {
                FilePath = "report.json"
            };
            var coverageEntity = new RepositoryCoverageEntity
            {
                CoverageFileName = "coverage.csv"
            };

            var target = GetTarget();

            //// act
            Action action = () => target.Process(reportEntity, coverageEntity);

            //// assert
            action.Should()
            .Throw <FileNotFoundException>()
            .WithMessage("File Not Found!");
        }
        public void Test涵蓋率下降的方法發出通知()
        {
            //// Arrange
            var coverageEntity = new RepositoryCoverageEntity
            {
                Repository = "Phanerozoic"
            };

            var method = new CoverageEntity
            {
                Class          = "AClass",
                Method         = "AMethod",
                Coverage       = 23,
                TargetCoverage = 100,
            };
            var methodList = new List <CoverageEntity>
            {
                method,
            };

            var stringBuilder = new StringBuilder();

            stringBuilder.AppendLine(method.ToString());
            var expectedMessage = stringBuilder.ToString();

            var webHookUrl = "http://abc.com";

            this._stubConfiguration["Slack:WebHookUrl"].Returns(webHookUrl);

            //// Act
            var target = GetTarget();

            target.Notify(coverageEntity, methodList);

            //// Assert
            this._stubSlackService.Received(1).SendAsync(webHookUrl, Arg.Any <string>());
        }
Example #22
0
        private string GetMessage(RepositoryCoverageEntity coverageEntity, IList <CoverageEntity> methodList)
        {
            var stringBuilder = new StringBuilder();

            stringBuilder.AppendLine($"Phanerozoic Notify @{DateTime.Now.ToString(DateTimeHelper.Format)}");

            var failCount = methodList.Count(i => i.IsPass == false);

            stringBuilder.AppendLine($"> Repository: {coverageEntity.Repository}, 涵蓋率未通過數量 {failCount}");

            foreach (var method in methodList)
            {
                if (method.IsPass == false)
                {
                    var msg = $"{method.Class}.{method.Method}: {method.Coverage} < {method.TargetCoverage}";
                    stringBuilder.AppendLine(msg);
                }
            }

            var data = new { text = stringBuilder.ToString() };
            var json = JsonSerializer.Serialize(data);

            return(json);
        }
Example #23
0
 private string GetFileName(RepositoryCoverageEntity coreMethodCoverage)
 {
     return(Path.Combine(coreMethodCoverage.OutputPath, $"{coreMethodCoverage.Repository}_{this._dateTimeHelper.Now.ToString(Format)}.json"));
 }
        public void ParserTest()
        {
            //// arrange
            var report = new DotCoverReport
            {
                DotCoverVersion   = "2019.2.3",
                Kind              = Kind.Root,
                CoveredStatements = 11937,
                TotalStatements   = 160364,
                CoveragePercent   = 7,
                Children          = new List <DotCoverReportChild>
                {
                    new DotCoverReportChild
                    {
                        Kind = Kind.Assembly,
                        Name = "Phanerozoic.Core",
                        CoveredStatements = 11937,
                        TotalStatements   = 160364,
                        CoveragePercent   = 7,
                        Children          = new List <DotCoverReportChild>
                        {
                            new DotCoverReportChild
                            {
                                Kind = Kind.Assembly,
                                Name = "Phanerozoic.Core",
                                CoveredStatements = 11937,
                                TotalStatements   = 160364,
                                CoveragePercent   = 7,
                                Children          = new List <DotCoverReportChild>
                                {
                                    new DotCoverReportChild
                                    {
                                        Kind = Kind.Namespace,
                                        Name = "Phanerozoic.Core.Services",
                                        CoveredStatements = 22,
                                        TotalStatements   = 11,
                                        CoveragePercent   = 7,
                                        Children          = new List <DotCoverReportChild>
                                        {
                                            new DotCoverReportChild
                                            {
                                                Kind = Kind.Type,
                                                Name = "DotCoverParser",
                                                CoveredStatements = 22,
                                                TotalStatements   = 11,
                                                CoveragePercent   = 7,
                                                Children          = new List <DotCoverReportChild>
                                                {
                                                    new DotCoverReportChild
                                                    {
                                                        Kind = Kind.Method,
                                                        Name = "Parser(ReportEntity):List<CoverageEntity>",
                                                        CoveredStatements = 22,
                                                        TotalStatements   = 11,
                                                        CoveragePercent   = 7,
                                                        Children          = new List <DotCoverReportChild>
                                                        {
                                                        }
                                                    }
                                                }
                                            },
                                        }
                                    },
                                }
                            },
                        }
                    },
                }
            };
            string reportJson = JsonSerializer.Serialize(report);

            this._stubFileHelper.ReadAllText(Arg.Any <string>()).Returns(reportJson);

            var coverageEntity = new RepositoryCoverageEntity
            {
                Repository = "Phanerozoic",
            };

            var reportEntity = new ReportEntity
            {
                FilePath = "report.json",
            };

            //// act
            var target = GetTarget();
            var actual = target.Parser(coverageEntity, reportEntity);

            actual.Count.Should().Be(5);
        }