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()); }
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); }
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); }
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 }
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> >()); }
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); }
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); }
/// <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); }
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()); }
/// <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>()); }
/// <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); }
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()); }
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>()); }
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); }
/// <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); }
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>()); }
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); }
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); }