public void Test_Process_Flow() { //// arrange this._stubFileHelper.Exists(Arg.Any <string>()).Returns(true); var reportEntity = new ReportEntity { FilePath = "report.json" }; var coverageEntity = new CoverageEntity { FilePath = "coverage.csv" }; var target = GetTarget(); //// act target.Process(reportEntity, coverageEntity); //// assert this._stubReportParser.Received(1).Parser(Arg.Any <CoverageEntity>(), Arg.Any <ReportEntity>()); this._stubCoverageUpdater.Received(1).Update(Arg.Any <CoverageEntity>(), Arg.Any <IList <MethodEntity> >()); this._stubNotifyer.Received(1).Notify(Arg.Any <CoverageEntity>(), Arg.Any <IList <MethodEntity> >()); this._stubEmailNotifyer.Received(1).Notify(Arg.Any <CoverageEntity>(), Arg.Any <IList <MethodEntity> >()); this._stubCoverageLogger.Received(1).Log(Arg.Any <IList <MethodEntity> >()); }
private string TagGroup(CoverageEntity method) { var message = string.Empty; if (string.IsNullOrEmpty(method.Team)) { return(message); } var teamArray = method.Team.Split(','); var groupList = new List <string>(); foreach (var team in teamArray) { var teamName = team.ToLower(); var groupId = _slackGroupIdDictionary.ContainsKey(teamName) ? $"<!subteam^{_slackGroupIdDictionary[teamName]}>" : $"`{team}`"; groupList.Add(groupId); } if (groupList.Count > 0) { message = $", {string.Join(" ", groupList)}"; } return(message); }
/// <summary> /// 只保留指定的 Repository 與 Project 下的方法 /// </summary> /// <param name="coverageEntity"></param> /// <param name="methodList"></param> /// <returns></returns> private IList <MethodEntity> FilterMethod(CoverageEntity coverageEntity, IList <MethodEntity> methodList) { return(methodList.Where(i => i.Repository == coverageEntity.Repository && i.Project == coverageEntity.Project ).ToList()); }
public void NotifyTest() { //// Assert string repository = "Phanerozoic"; string project = "Phanerozoic.Core"; var coverageEntity = new CoverageEntity { Repository = repository, Project = project, }; var methodList = new List <MethodEntity> { new MethodEntity { 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 }
private static List <CoverageEntity> SheetRangeToEntityList(IList <IList <object> > sheetRange) { List <CoverageEntity> methodList = new List <CoverageEntity>(); if (sheetRange != null && sheetRange.Count > 0) { foreach (var row in sheetRange) { var methodEntity = new CoverageEntity { Repository = row[0].ToString().Trim(), Project = row[1].ToString().Trim(), Class = row[2].ToString().Trim(), Method = row[3].ToString().Trim(), Coverage = SheetHelper.ObjectToInt(row[4]), Team = row[6].ToString().Trim(), UpdatedDate = row.Count < 10 ? string.Empty : row[9].ToString().Trim(), RawData = row, }; if (string.IsNullOrWhiteSpace(methodEntity.Method) == false) { methodList.Add(methodEntity); } } } return(methodList); }
private static void Main(string[] args) { // create service collection var serviceCollection = new ServiceCollection(); ConfigureServices(serviceCollection); // create service provider var serviceProvider = serviceCollection.BuildServiceProvider(); var reportEntity = new ReportEntity { FilePath = args[0].Trim(), }; var file = new FileInfo(reportEntity.FilePath); var fileName = file.Name; fileName = fileName.Substring(0, fileName.LastIndexOf('.')); var coverageEntity = new CoverageEntity { FilePath = Path.Combine(file.DirectoryName, $"{fileName}.csv"), Repository = args[1].Trim(), Project = args[2].Trim(), }; var coverageProcessor = serviceProvider.GetService <ICoverageProcessor>(); coverageProcessor.Process(reportEntity, coverageEntity); serviceProvider.Dispose(); }
public void Process(ReportEntity reportEntity, CoverageEntity 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"); this.GetSlackNotifyer().Notify(coverageEntity, updateMethodList); this.GetEmailNotifyer().Notify(coverageEntity, updateMethodList); //// Log Console.WriteLine("* Log"); this._coverageLogger.Log(updateMethodList); }
public IList <MethodEntity> Parser(CoverageEntity coverageEntity, ReportEntity reportEntity) { var json = this._fileHelper.ReadAllText(reportEntity.FilePath); var report = JsonSerializer.Deserialize <DotCoverReport>(json); var result = new List <MethodEntity>(); FindMethod(result, string.Empty, string.Empty, 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 Notify(CoverageEntity coverageEntity, IList <MethodEntity> methodList) { var slackMessageJson = this.GetSlackMessage(coverageEntity, methodList); if (string.IsNullOrWhiteSpace(slackMessageJson)) { return; } this._slackService.SendAsync(this._webHookUrl, slackMessageJson); }
private double ComputeBuildCoverage(CoverageEntity coverages) { if (coverages == null) { return(0); } var covered = coverages.BlocksCovered; var notCovered = coverages.BlocksNotCovered; return(((Double)covered * 100) / (notCovered + covered)); }
public void Test_取得目前的涵蓋率() { //// Arrange var coverageEntity = new CoverageEntity(); var methodList = new List <MethodEntity>(); 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>()); }
private void NewTargetCoverageShouldBe(int targetCoverage, int newCoverage, int result) { //// Arrange var reportEntity = new CoverageEntity(); reportEntity.Coverage = newCoverage; var target = new CoverageEntity(); target.TargetCoverage = targetCoverage; //// Act target.UpdateCoverage(reportEntity); //// Assert target.NewTargetCoverage.Should().Be(result); }
public IList <CoverageEntity> GetList() { var startIndex = 1; var maxRow = string.Empty; var sheetName = "Coverage"; IList <CoverageEntity> sheetMethodList = new List <CoverageEntity>(); //// TODO J 須為動態 IList <IList <object> > values = this._googleSheetsService.GetValues(this._sheetsId, $"{sheetName}!A{startIndex + 1}:J{maxRow}"); var index = startIndex; if (values != null && values.Count > 0) { foreach (var row in values) { index++; if (row.Count < 10) { Console.WriteLine($"Pass Sheet Row:{index}, Value: {row.EnumerableToString()}"); continue; } var methodEntity = new CoverageEntity { Repository = row[0].ToString().Trim(), Project = row[1].ToString().Trim(), Namespace = row[2].ToString().Trim(), Class = row[3].ToString().Trim(), Method = row[4].ToString().Trim(), Coverage = row.Count > 5 ? SheetHelper.ObjectToInt(row[5]) : 0, TargetCoverage = row.Count > 7 ? SheetHelper.ObjectToInt(row[7]) : 0, Level = SheetHelper.ObjectToEnum <MethodLevel>(row[8]), Team = row[9].ToString().Trim(), RawIndex = index, RawData = row, }; if (string.IsNullOrWhiteSpace(methodEntity.Method) == false) { sheetMethodList.Add(methodEntity); } } } return(sheetMethodList); }
public void Test_Update_Flow() { //// Arrange var methodList = new List <MethodEntity>(); var coverageEntity = new CoverageEntity { FilePath = "a.txt" }; //// Act var target = new FileUpdater(this._stubServiceProvider); target.Update(coverageEntity, methodList); //// Assert this._stubFileHelper.Received(1).WriteAllText(Arg.Any <string>(), Arg.Any <string>()); }
private void LastCoverageShouldBe(int coverage, int newCoverage) { //// Arrange var reportEntity = new CoverageEntity(); reportEntity.Coverage = newCoverage; var target = new CoverageEntity(); target.Coverage = coverage; //// Act target.UpdateCoverage(reportEntity); //// Assert target.LastCoverage.Should().Be(coverage); }
private void CoverageStatusShouldBe(int coverage, int newCoverage, CoverageStatus result) { //// Arrange var reportEntity = new CoverageEntity(); reportEntity.Coverage = newCoverage; var target = new CoverageEntity(); target.Coverage = coverage; //// Act target.UpdateCoverage(reportEntity); //// Assert target.Status.Should().Be(result); }
public void Notify(CoverageEntity coverageEntity, IList <MethodEntity> methodList) { Console.WriteLine($"Email From: {this._from}"); Console.WriteLine($"To: {string.Join(',', this._toList)}"); var subject = $"Phanerozic Notify - {coverageEntity.Repository} - {coverageEntity.Project}"; var projectMethod = methodList.Where(i => i.Repository == coverageEntity.Repository && i.Project == coverageEntity.Project).ToList(); var downMethod = projectMethod.Where(i => i.Status == CoverageStatus.Down).ToList(); var stringBuilder = new StringBuilder(); stringBuilder.AppendLine($"Repository: {coverageEntity.Repository}"); stringBuilder.AppendLine($"Project: {coverageEntity.Project}"); stringBuilder.AppendLine($"Coverage Down Rate: {downMethod.Count}/{projectMethod.Count}"); downMethod.ForEach(i => stringBuilder.AppendLine($"{i.Class}.{i.Method}: {i.LastCoverage} → {i.Coverage}")); this._emailService.Send(this._from, this._toList, subject, stringBuilder.ToString()); }
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 void Test涵蓋率未下降則不發通知() { //// Arrange var coverageEntity = new CoverageEntity { Repository = "Phanerozoic" }; var methodUnchange = new MethodEntity { Class = "AClass", Method = "AMethod", Status = CoverageStatus.Unchange, Coverage = 23, }; var methodUp = new MethodEntity { Class = "AClass", Method = "AMethod", Status = CoverageStatus.Up, Coverage = 23, }; var methodList = new List <MethodEntity> { methodUnchange, methodUp, }; var stringBuilder = new StringBuilder(); stringBuilder.AppendLine(methodUnchange.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 <MethodEntity> Update(CoverageEntity coverageEntity, IList <MethodEntity> 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(); this._fileHelper.WriteAllText(coverageEntity.FilePath, contents); return(methodList); }
private List <CoverageEntity> GetCurrentMethodList() { var now = _dateTimeHelper.Now; var startIndex = 1; var maxRow = string.Empty; List <CoverageEntity> methodLogList = new List <CoverageEntity>(); IList <IList <object> > values = _googleSheetsService.GetValues(_sheetsId, $"{now.Year}!A{startIndex + 1}:I{maxRow}"); var index = startIndex; if (values != null && values.Count > 0) { foreach (var row in values) { if (row.Count < 5) { continue; } index++; var methodEntity = new CoverageEntity { Repository = row[0].ToString().Trim(), Project = row[1].ToString().Trim(), Namespace = row[2].ToString().Trim(), Class = row[3].ToString().Trim(), Method = row[4].ToString().Trim(), RawIndex = index, RawData = row, }; if (string.IsNullOrWhiteSpace(methodEntity.Method) == false) { methodLogList.Add(methodEntity); } } } return(methodLogList); }
private string GetSlackMessage(CoverageEntity coverageEntity, IList <MethodEntity> methodList) { var downCount = methodList.Count(i => i.Status == CoverageStatus.Down); if (downCount == 0) { return(null); } var color = downCount > 0 ? "#FF0000" : "#00FF00"; var attachment = new Attachment { Color = color, AuthorName = $"Repository: {coverageEntity.Repository}", Title = $"Project: {coverageEntity.Project} 涵蓋率下降方法數量: {downCount}", Footer = $"Phanerozoic Notifyer", }; var stringBuilder = new StringBuilder(); foreach (var method in methodList) { if (method.Status == CoverageStatus.Down) { var msg = $"{method.Class}.{method.Method}: {method.LastCoverage} → {method.Coverage}"; stringBuilder.AppendLine(msg); } } attachment.Text = stringBuilder.ToString(); var slackMessage = new SlackMessage { Attachments = new List <Attachment> { attachment } }; return(slackMessage.ToJson()); }
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 CoverageEntity { FilePath = "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 CoverageEntity { Repository = "Phanerozoic" }; var method = new MethodEntity { Class = "AClass", Method = "AMethod", Status = CoverageStatus.Down, Coverage = 23, }; var methodList = new List <MethodEntity> { 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(CoverageEntity coverageEntity, IList <MethodEntity> methodList) { var stringBuilder = new StringBuilder(); stringBuilder.AppendLine($"Phanerozoic Notify @{DateTime.Now.ToString(DateTimeHelper.Format)}"); var downCount = methodList.Count(i => i.Status == CoverageStatus.Down); stringBuilder.AppendLine($"> Repository: {coverageEntity.Repository}, 涵蓋率下降方法數量 {downCount}"); foreach (var method in methodList) { if (method.Status == CoverageStatus.Down) { var msg = $"{method.Class}.{method.Method}: {method.LastCoverage} → {method.Coverage}"; stringBuilder.AppendLine(msg); } } var data = new { text = stringBuilder.ToString() }; var json = JsonSerializer.Serialize(data); return(json); }
public IList <MethodEntity> Update(CoverageEntity coverageEntity, IList <MethodEntity> reportMethodList) { var reportMethodTotalCount = reportMethodList.Count; reportMethodList = this.FilterMethod(coverageEntity, reportMethodList); Console.WriteLine("** Report Method"); Console.WriteLine($"Repository: {coverageEntity.Repository}, Project: {coverageEntity.Project}, Method Count: {reportMethodList.Count}/{reportMethodTotalCount}"); var startIndex = 1; var maxRow = string.Empty; var sheetName = "Coverage"; IList <MethodEntity> sheetMethodList = new List <MethodEntity>(); IList <IList <object> > values = this._googleSheetsService.GetValues(this._sheetsId, $"{sheetName}!A{startIndex + 1}:I{maxRow}"); var index = startIndex; if (values != null && values.Count > 0) { foreach (var row in values) { index++; var methodEntity = new MethodEntity { Repository = row[0].ToString().Trim(), Project = row[1].ToString().Trim(), Class = row[2].ToString().Trim(), Method = row[3].ToString().Trim(), Coverage = SheetHelper.ObjectToInt(row[4]), RawIndex = index, RawData = row, }; if (string.IsNullOrWhiteSpace(methodEntity.Method) == false) { sheetMethodList.Add(methodEntity); } } } var sheetMethodTotalCount = sheetMethodList.Count; sheetMethodList = this.FilterMethod(coverageEntity, sheetMethodList); Console.WriteLine("** Sheet Method"); Console.WriteLine($"Repository: {coverageEntity.Repository}, Project: {coverageEntity.Project}, Method Count: {sheetMethodList.Count}/{sheetMethodTotalCount}"); if (sheetMethodList.Count <= 0) { return(sheetMethodList); } var updateCount = 0; foreach (var coreMethod in sheetMethodList) { var reportMethod = reportMethodList.FirstOrDefault(i => i.Class == coreMethod.Class && i.Method == coreMethod.Method); if (reportMethod == null) { continue; } updateCount++; coreMethod.UpdateCoverage(reportMethod); var symbolDictionary = new Dictionary <CoverageStatus, string>(); symbolDictionary.Add(CoverageStatus.Unchange, "="); symbolDictionary.Add(CoverageStatus.Up, "▲"); symbolDictionary.Add(CoverageStatus.Down, "▼"); var symbol = symbolDictionary[coreMethod.Status]; Console.WriteLine($"{coreMethod.Class}.{coreMethod.Method}: {coreMethod.LastCoverage} {symbol} {coreMethod.Coverage}"); if (coreMethod.Status != CoverageStatus.Unchange || coreMethod.Coverage == 0) { this.UpdateCell($"E{coreMethod.RawIndex}", coreMethod.Coverage); } this.UpdateCell($"J{coreMethod.RawIndex}", DateTime.Now.ToString(DateTimeHelper.Format)); } Console.WriteLine($"Update Rate: {updateCount}/{sheetMethodList.Count}"); return(sheetMethodList); }
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 CoverageEntity { Repository = "Phanerozoic", }; var reportEntity = new ReportEntity { FilePath = "report.json", }; //// act var target = GetTarget(); var actual = target.Parser(coverageEntity, reportEntity); actual.Count.Should().Be(2); }
/// <summary> /// 尋找 Kind = Method 的各階層的項目 /// </summary> /// <param name="result">回傳值</param> /// <param name="source">目前的階層</param> private void FindMethod(List <CoverageEntity> result, string assembly, CoverageEntity parent, List <DotCoverReportChild> source) { if (source == null) { return; } foreach (var item in source) { var currentName = string.Empty; CoverageEntity currentCoverage = default; if (item.Kind == Kind.Method) { currentCoverage = new CoverageEntity { Project = assembly, Namespace = parent.Namespace, Class = parent.Class, Method = item.Name, Coverage = (int)item.CoveragePercent, }; } else if (item.Kind == Kind.Type) { currentCoverage = new CoverageEntity { Project = assembly, Namespace = parent.Namespace, Class = item.Name, Method = "*", Coverage = (int)item.CoveragePercent, }; } else if (item.Kind == Kind.Namespace) { currentCoverage = new CoverageEntity { Project = assembly, Namespace = item.Name, Class = $"*", Method = "*", Coverage = (int)item.CoveragePercent, }; } else if (item.Kind == Kind.Assembly) { assembly = item.Name; currentCoverage = new CoverageEntity { Project = assembly, Namespace = "*", Class = "*", Method = "*", Coverage = (int)item.CoveragePercent, }; } if (currentCoverage != null) { result.Add(currentCoverage); } FindMethod(result, assembly, currentCoverage, item.Children); } }