4
4
using System . Text ;
5
5
using ConsoleTables ;
6
6
using Coverlet . Core ;
7
+ using Coverlet . Core . Enums ;
7
8
using Coverlet . Core . Reporters ;
8
9
using Microsoft . Build . Framework ;
9
10
using Microsoft . Build . Utilities ;
@@ -14,7 +15,7 @@ public class CoverageResultTask : Task
14
15
{
15
16
private string _output ;
16
17
private string _format ;
17
- private int _threshold ;
18
+ private double _threshold ;
18
19
private string _thresholdType ;
19
20
private string _thresholdStat ;
20
21
@@ -33,7 +34,7 @@ public string OutputFormat
33
34
}
34
35
35
36
[ Required ]
36
- public int Threshold
37
+ public double Threshold
37
38
{
38
39
get { return _threshold ; }
39
40
set { _threshold = value ; }
@@ -77,7 +78,9 @@ public override bool Execute()
77
78
{
78
79
var reporter = new ReporterFactory ( format ) . CreateReporter ( ) ;
79
80
if ( reporter == null )
81
+ {
80
82
throw new Exception ( $ "Specified output format '{ format } ' is not supported") ;
83
+ }
81
84
82
85
if ( reporter . OutputType == ReporterOutputType . Console )
83
86
{
@@ -98,14 +101,41 @@ public override bool Execute()
98
101
}
99
102
}
100
103
101
- var thresholdFailed = false ;
102
- var thresholdTypes = _thresholdType . Split ( ',' ) . Select ( t => t . Trim ( ) ) ;
103
- var summary = new CoverageSummary ( ) ;
104
- var exceptionBuilder = new StringBuilder ( ) ;
104
+ var thresholdTypeFlags = ThresholdTypeFlags . None ;
105
+ var thresholdStat = ThresholdStatistic . Minimum ;
106
+
107
+ foreach ( var thresholdType in _thresholdType . Split ( ',' ) . Select ( t => t . Trim ( ) ) )
108
+ {
109
+ if ( thresholdType . Equals ( "line" , StringComparison . OrdinalIgnoreCase ) )
110
+ {
111
+ thresholdTypeFlags |= ThresholdTypeFlags . Line ;
112
+ }
113
+ else if ( thresholdType . Equals ( "branch" , StringComparison . OrdinalIgnoreCase ) )
114
+ {
115
+ thresholdTypeFlags |= ThresholdTypeFlags . Branch ;
116
+ }
117
+ else if ( thresholdType . Equals ( "method" , StringComparison . OrdinalIgnoreCase ) )
118
+ {
119
+ thresholdTypeFlags |= ThresholdTypeFlags . Method ;
120
+ }
121
+ }
122
+
123
+ if ( _thresholdStat . Equals ( "average" , StringComparison . OrdinalIgnoreCase ) )
124
+ {
125
+ thresholdStat = ThresholdStatistic . Average ;
126
+ }
127
+ else if ( _thresholdStat . Equals ( "total" , StringComparison . OrdinalIgnoreCase ) )
128
+ {
129
+ thresholdStat = ThresholdStatistic . Total ;
130
+ }
131
+
105
132
var coverageTable = new ConsoleTable ( "Module" , "Line" , "Branch" , "Method" ) ;
106
- var overallLineCoverage = summary . CalculateLineCoverage ( result . Modules ) ;
107
- var overallBranchCoverage = summary . CalculateBranchCoverage ( result . Modules ) ;
108
- var overallMethodCoverage = summary . CalculateMethodCoverage ( result . Modules ) ;
133
+ var summary = new CoverageSummary ( ) ;
134
+ int numModules = result . Modules . Count ;
135
+
136
+ var totalLinePercent = summary . CalculateLineCoverage ( result . Modules ) . Percent * 100 ;
137
+ var totalBranchPercent = summary . CalculateBranchCoverage ( result . Modules ) . Percent * 100 ;
138
+ var totalMethodPercent = summary . CalculateMethodCoverage ( result . Modules ) . Percent * 100 ;
109
139
110
140
foreach ( var module in result . Modules )
111
141
{
@@ -114,37 +144,41 @@ public override bool Execute()
114
144
var methodPercent = summary . CalculateMethodCoverage ( module . Value ) . Percent * 100 ;
115
145
116
146
coverageTable . AddRow ( Path . GetFileNameWithoutExtension ( module . Key ) , $ "{ linePercent } %", $ "{ branchPercent } %", $ "{ methodPercent } %") ;
117
-
118
- if ( _threshold > 0 )
119
- {
120
- if ( linePercent < _threshold && thresholdTypes . Contains ( "line" , StringComparer . OrdinalIgnoreCase ) )
121
- {
122
- exceptionBuilder . AppendLine ( $ "'{ Path . GetFileNameWithoutExtension ( module . Key ) } ' has a line coverage '{ linePercent } %' below specified threshold '{ _threshold } %'") ;
123
- thresholdFailed = true ;
124
- }
125
-
126
- if ( branchPercent < _threshold && thresholdTypes . Contains ( "branch" , StringComparer . OrdinalIgnoreCase ) )
127
- {
128
- exceptionBuilder . AppendLine ( $ "'{ Path . GetFileNameWithoutExtension ( module . Key ) } ' has a branch coverage '{ branchPercent } %' below specified threshold '{ _threshold } %'") ;
129
- thresholdFailed = true ;
130
- }
131
-
132
- if ( methodPercent < _threshold && thresholdTypes . Contains ( "method" , StringComparer . OrdinalIgnoreCase ) )
133
- {
134
- exceptionBuilder . AppendLine ( $ "'{ Path . GetFileNameWithoutExtension ( module . Key ) } ' has a method coverage '{ methodPercent } %' below specified threshold '{ _threshold } %'") ;
135
- thresholdFailed = true ;
136
- }
137
- }
138
147
}
139
148
140
149
Console . WriteLine ( ) ;
141
150
Console . WriteLine ( coverageTable . ToStringAlternative ( ) ) ;
142
- Console . WriteLine ( $ "Total Line: { overallLineCoverage . Percent * 100 } %") ;
143
- Console . WriteLine ( $ "Total Branch: { overallBranchCoverage . Percent * 100 } %") ;
144
- Console . WriteLine ( $ "Total Method: { overallMethodCoverage . Percent * 100 } %") ;
145
151
146
- if ( thresholdFailed )
147
- throw new Exception ( exceptionBuilder . ToString ( ) . TrimEnd ( Environment . NewLine . ToCharArray ( ) ) ) ;
152
+ coverageTable . Columns . Clear ( ) ;
153
+ coverageTable . Rows . Clear ( ) ;
154
+
155
+ coverageTable . AddColumn ( new [ ] { "" , "Line" , "Branch" , "Method" } ) ;
156
+ coverageTable . AddRow ( "Total" , $ "{ totalLinePercent } %", $ "{ totalBranchPercent } %", $ "{ totalMethodPercent } %") ;
157
+ coverageTable . AddRow ( "Average" , $ "{ totalLinePercent / numModules } %", $ "{ totalBranchPercent / numModules } %", $ "{ totalMethodPercent / numModules } %") ;
158
+
159
+ Console . WriteLine ( coverageTable . ToStringAlternative ( ) ) ;
160
+
161
+ thresholdTypeFlags = result . GetThresholdTypesBelowThreshold ( summary , _threshold , thresholdTypeFlags , thresholdStat ) ;
162
+ if ( thresholdTypeFlags != ThresholdTypeFlags . None )
163
+ {
164
+ var exceptionMessageBuilder = new StringBuilder ( ) ;
165
+ if ( ( thresholdTypeFlags & ThresholdTypeFlags . Line ) != ThresholdTypeFlags . None )
166
+ {
167
+ exceptionMessageBuilder . AppendLine ( $ "The { thresholdStat . ToString ( ) . ToLower ( ) } line coverage is below the specified { _threshold } ") ;
168
+ }
169
+
170
+ if ( ( thresholdTypeFlags & ThresholdTypeFlags . Branch ) != ThresholdTypeFlags . None )
171
+ {
172
+ exceptionMessageBuilder . AppendLine ( $ "The { thresholdStat . ToString ( ) . ToLower ( ) } branch coverage is below the specified { _threshold } ") ;
173
+ }
174
+
175
+ if ( ( thresholdTypeFlags & ThresholdTypeFlags . Method ) != ThresholdTypeFlags . None )
176
+ {
177
+ exceptionMessageBuilder . AppendLine ( $ "The { thresholdStat . ToString ( ) . ToLower ( ) } method coverage is below the specified { _threshold } ") ;
178
+ }
179
+
180
+ throw new Exception ( exceptionMessageBuilder . ToString ( ) ) ;
181
+ }
148
182
}
149
183
catch ( Exception ex )
150
184
{
0 commit comments