@@ -37,7 +37,7 @@ private static int Main(string[] args)
3737 {
3838 if ( ! File . Exists ( file ) )
3939 {
40- Console . WriteLine ( $ "Error: Code coverage file not found - { file } .") ;
40+ Console . WriteLine ( $ "Error: Coverage file not found - { file } .") ;
4141 return - 2 ; // error
4242 }
4343 }
@@ -46,19 +46,28 @@ private static int Main(string[] args)
4646 CodeSummary summary = new ( ) ;
4747 foreach ( var file in matchingFiles )
4848 {
49- Console . WriteLine ( $ "Code Coverage File: { file } ") ;
49+ Console . WriteLine ( $ "Coverage File: { file } ") ;
5050 summary = ParseTestResults ( file , summary ) ;
5151 }
52+
53+ if ( summary == null )
54+ return - 2 ; // error
55+
5256 summary . LineRate /= matchingFiles . Count ( ) ;
5357 summary . BranchRate /= matchingFiles . Count ( ) ;
5458
5559 if ( summary . Packages . Count == 0 )
5660 {
57- Console . WriteLine ( "Error: Parsing code coverage file, no packages found ." ) ;
61+ Console . WriteLine ( "Parsing Error: No packages found in coverage files ." ) ;
5862 return - 2 ; // error
5963 }
6064 else
6165 {
66+ // hide branch rate if metrics missing
67+ bool hideBranchRate = o . HideBranchRate ;
68+ if ( summary . BranchRate == 0 && summary . BranchesCovered == 0 && summary . BranchesValid == 0 )
69+ hideBranchRate = true ;
70+
6271 // set health badge thresholds
6372 if ( ! string . IsNullOrWhiteSpace ( o . Thresholds ) )
6473 SetThresholds ( o . Thresholds ) ;
@@ -72,14 +81,14 @@ private static int Main(string[] args)
7281 if ( o . Format . Equals ( "text" , StringComparison . OrdinalIgnoreCase ) )
7382 {
7483 fileExt = "txt" ;
75- output = GenerateTextOutput ( summary , badgeUrl , o . Indicators , o . HideBranchRate , o . HideComplexity ) ;
84+ output = GenerateTextOutput ( summary , badgeUrl , o . Indicators , hideBranchRate , o . HideComplexity ) ;
7685 if ( o . FailBelowThreshold )
7786 output += $ "Minimum allowed line rate is { lowerThreshold * 100 : N0} %{ Environment . NewLine } ";
7887 }
7988 else if ( o . Format . Equals ( "md" , StringComparison . OrdinalIgnoreCase ) || o . Format . Equals ( "markdown" , StringComparison . OrdinalIgnoreCase ) )
8089 {
8190 fileExt = "md" ;
82- output = GenerateMarkdownOutput ( summary , badgeUrl , o . Indicators , o . HideBranchRate , o . HideComplexity ) ;
91+ output = GenerateMarkdownOutput ( summary , badgeUrl , o . Indicators , hideBranchRate , o . HideComplexity ) ;
8392 if ( o . FailBelowThreshold )
8493 output += $ "{ Environment . NewLine } _Minimum allowed line rate is `{ lowerThreshold * 100 : N0} %`_{ Environment . NewLine } ";
8594 }
@@ -92,6 +101,7 @@ private static int Main(string[] args)
92101 // output
93102 if ( o . Output . Equals ( "console" , StringComparison . OrdinalIgnoreCase ) )
94103 {
104+ Console . WriteLine ( ) ;
95105 Console . WriteLine ( output ) ;
96106 }
97107 else if ( o . Output . Equals ( "file" , StringComparison . OrdinalIgnoreCase ) )
@@ -100,6 +110,7 @@ private static int Main(string[] args)
100110 }
101111 else if ( o . Output . Equals ( "both" , StringComparison . OrdinalIgnoreCase ) )
102112 {
113+ Console . WriteLine ( ) ;
103114 Console . WriteLine ( output ) ;
104115 File . WriteAllText ( $ "code-coverage-results.{ fileExt } ", output ) ;
105116 }
@@ -129,6 +140,9 @@ private static int Main(string[] args)
129140
130141 private static CodeSummary ParseTestResults ( string filename , CodeSummary summary )
131142 {
143+ if ( summary == null )
144+ return null ;
145+
132146 try
133147 {
134148 string rss = File . ReadAllText ( filename ) ;
@@ -138,46 +152,72 @@ private static CodeSummary ParseTestResults(string filename, CodeSummary summary
138152 var coverage = from item in xdoc . Descendants ( "coverage" )
139153 select item ;
140154
155+ if ( ! coverage . Any ( ) )
156+ throw new Exception ( "Coverage file invalid, data not found" ) ;
157+
141158 var lineR = from item in coverage . Attributes ( )
142159 where item . Name == "line-rate"
143160 select item ;
161+
162+ if ( ! lineR . Any ( ) )
163+ throw new Exception ( "Overall line rate not found" ) ;
164+
144165 summary . LineRate += double . Parse ( lineR . First ( ) . Value ) ;
145166
146167 var linesCovered = from item in coverage . Attributes ( )
147168 where item . Name == "lines-covered"
148169 select item ;
170+
171+ if ( ! linesCovered . Any ( ) )
172+ throw new Exception ( "Overall lines covered not found" ) ;
173+
149174 summary . LinesCovered += int . Parse ( linesCovered . First ( ) . Value ) ;
150175
151176 var linesValid = from item in coverage . Attributes ( )
152177 where item . Name == "lines-valid"
153178 select item ;
179+
180+ if ( ! linesValid . Any ( ) )
181+ throw new Exception ( "Overall lines valid not found" ) ;
182+
154183 summary . LinesValid += int . Parse ( linesValid . First ( ) . Value ) ;
155184
156185 var branchR = from item in coverage . Attributes ( )
157186 where item . Name == "branch-rate"
158187 select item ;
159- summary . BranchRate += double . Parse ( branchR . First ( ) . Value ) ;
160188
161- var branchesCovered = from item in coverage . Attributes ( )
162- where item . Name == "branches-covered"
163- select item ;
164- summary . BranchesCovered += int . Parse ( branchesCovered . First ( ) . Value ) ;
189+ if ( branchR . Any ( ) )
190+ {
191+ summary . BranchRate += double . Parse ( branchR . First ( ) . Value ) ;
192+
193+ var branchesCovered = from item in coverage . Attributes ( )
194+ where item . Name == "branches-covered"
195+ select item ;
165196
166- var branchesValid = from item in coverage . Attributes ( )
167- where item . Name == "branches-valid"
168- select item ;
169- summary . BranchesValid += int . Parse ( branchesValid . First ( ) . Value ) ;
197+ if ( branchesCovered . Any ( ) )
198+ summary . BranchesCovered += int . Parse ( branchesCovered . First ( ) . Value ) ;
199+
200+ var branchesValid = from item in coverage . Attributes ( )
201+ where item . Name == "branches-valid"
202+ select item ;
203+
204+ if ( branchesValid . Any ( ) )
205+ summary . BranchesValid += int . Parse ( branchesValid . First ( ) . Value ) ;
206+ }
170207
171208 // test coverage for individual packages
172209 var packages = from item in coverage . Descendants ( "package" )
173210 select item ;
174211
212+ if ( ! packages . Any ( ) )
213+ throw new Exception ( "No package data found" ) ;
214+
175215 int i = 1 ;
176216 foreach ( var item in packages )
177217 {
178218 CodeCoverage packageCoverage = new ( )
179219 {
180- Name = string . IsNullOrWhiteSpace ( item . Attribute ( "name" ) . Value ) ? $ "Package { i } " : item . Attribute ( "name" ) . Value ,
220+ Name = string . IsNullOrWhiteSpace ( item . Attribute ( "name" ) ? . Value ) ? $ "{ Path . GetFileNameWithoutExtension ( filename ) } Package { i } " : item . Attribute ( "name" ) . Value ,
181221 LineRate = double . Parse ( item . Attribute ( "line-rate" ) ? . Value ?? "0" ) ,
182222 BranchRate = double . Parse ( item . Attribute ( "branch-rate" ) ? . Value ?? "0" ) ,
183223 Complexity = double . Parse ( item . Attribute ( "complexity" ) ? . Value ?? "0" )
@@ -191,7 +231,7 @@ private static CodeSummary ParseTestResults(string filename, CodeSummary summary
191231 }
192232 catch ( Exception ex )
193233 {
194- Console . WriteLine ( $ "Parse Error: { ex . Message } ") ;
234+ Console . WriteLine ( $ "Parsing Error: { ex . Message } - { filename } ") ;
195235 return null ;
196236 }
197237 }
@@ -212,10 +252,10 @@ private static void SetThresholds(string thresholds)
212252 }
213253 else
214254 {
215- if ( ! int . TryParse ( thresholds . Substring ( 0 , s ) , out lowerPercentage ) )
255+ if ( ! int . TryParse ( thresholds . AsSpan ( 0 , s ) , out lowerPercentage ) )
216256 throw new ArgumentException ( "Threshold parameter set incorrectly." ) ;
217257
218- if ( ! int . TryParse ( thresholds . Substring ( s + 1 ) , out upperPercentage ) )
258+ if ( ! int . TryParse ( thresholds . AsSpan ( s + 1 ) , out upperPercentage ) )
219259 throw new ArgumentException ( "Threshold parameter set incorrectly." ) ;
220260 }
221261 lowerThreshold = lowerPercentage / 100.0 ;
0 commit comments