6
6
using ConsoleTables ;
7
7
using Coverlet . Console . Logging ;
8
8
using Coverlet . Core ;
9
+ using Coverlet . Core . Enums ;
9
10
using Coverlet . Core . Reporters ;
10
11
11
12
using Microsoft . Extensions . CommandLineUtils ;
@@ -30,6 +31,7 @@ static int Main(string[] args)
30
31
CommandOption formats = app . Option ( "-f|--format" , "Format of the generated coverage report." , CommandOptionType . MultipleValue ) ;
31
32
CommandOption threshold = app . Option ( "--threshold" , "Exits with error if the coverage % is below value." , CommandOptionType . SingleValue ) ;
32
33
CommandOption thresholdTypes = app . Option ( "--threshold-type" , "Coverage type to apply the threshold to." , CommandOptionType . MultipleValue ) ;
34
+ CommandOption thresholdStat = app . Option ( "--threshold-stat" , "Coverage statistic used to enforce the threshold value." , CommandOptionType . SingleValue ) ;
33
35
CommandOption excludeFilters = app . Option ( "--exclude" , "Filter expressions to exclude specific modules and types." , CommandOptionType . MultipleValue ) ;
34
36
CommandOption includeFilters = app . Option ( "--include" , "Filter expressions to include only specific modules and types." , CommandOptionType . MultipleValue ) ;
35
37
CommandOption excludedSourceFiles = app . Option ( "--exclude-by-file" , "Glob patterns specifying source files to exclude." , CommandOptionType . MultipleValue ) ;
@@ -59,8 +61,9 @@ static int Main(string[] args)
59
61
process . WaitForExit ( ) ;
60
62
61
63
var dOutput = output . HasValue ( ) ? output . Value ( ) : Directory . GetCurrentDirectory ( ) + Path . DirectorySeparatorChar . ToString ( ) ;
62
- var dThreshold = threshold . HasValue ( ) ? int . Parse ( threshold . Value ( ) ) : 0 ;
64
+ var dThreshold = threshold . HasValue ( ) ? double . Parse ( threshold . Value ( ) ) : 0 ;
63
65
var dThresholdTypes = thresholdTypes . HasValue ( ) ? thresholdTypes . Values : new List < string > ( new string [ ] { "line" , "branch" , "method" } ) ;
66
+ var dThresholdStat = thresholdStat . HasValue ( ) ? Enum . Parse < ThresholdStatistic > ( thresholdStat . Value ( ) , true ) : Enum . Parse < ThresholdStatistic > ( "minimum" , true ) ;
64
67
65
68
logger . LogInformation ( "\n Calculating coverage result..." ) ;
66
69
@@ -79,7 +82,9 @@ static int Main(string[] args)
79
82
{
80
83
var reporter = new ReporterFactory ( format ) . CreateReporter ( ) ;
81
84
if ( reporter == null )
85
+ {
82
86
throw new Exception ( $ "Specified output format '{ format } ' is not supported") ;
87
+ }
83
88
84
89
if ( reporter . OutputType == ReporterOutputType . Console )
85
90
{
@@ -100,13 +105,31 @@ static int Main(string[] args)
100
105
}
101
106
}
102
107
103
- var summary = new CoverageSummary ( ) ;
104
- var exceptionBuilder = new StringBuilder ( ) ;
108
+ var thresholdTypeFlags = ThresholdTypeFlags . None ;
109
+
110
+ foreach ( var thresholdType in dThresholdTypes )
111
+ {
112
+ if ( thresholdType . Equals ( "line" , StringComparison . OrdinalIgnoreCase ) )
113
+ {
114
+ thresholdTypeFlags |= ThresholdTypeFlags . Line ;
115
+ }
116
+ else if ( thresholdType . Equals ( "branch" , StringComparison . OrdinalIgnoreCase ) )
117
+ {
118
+ thresholdTypeFlags |= ThresholdTypeFlags . Branch ;
119
+ }
120
+ else if ( thresholdType . Equals ( "method" , StringComparison . OrdinalIgnoreCase ) )
121
+ {
122
+ thresholdTypeFlags |= ThresholdTypeFlags . Method ;
123
+ }
124
+ }
125
+
105
126
var coverageTable = new ConsoleTable ( "Module" , "Line" , "Branch" , "Method" ) ;
106
- var thresholdFailed = false ;
107
- var overallLineCoverage = summary . CalculateLineCoverage ( result . Modules ) ;
108
- var overallBranchCoverage = summary . CalculateBranchCoverage ( result . Modules ) ;
109
- var overallMethodCoverage = summary . CalculateMethodCoverage ( result . Modules ) ;
127
+ var summary = new CoverageSummary ( ) ;
128
+ int numModules = result . Modules . Count ;
129
+
130
+ var totalLinePercent = summary . CalculateLineCoverage ( result . Modules ) . Percent * 100 ;
131
+ var totalBranchPercent = summary . CalculateBranchCoverage ( result . Modules ) . Percent * 100 ;
132
+ var totalMethodPercent = summary . CalculateMethodCoverage ( result . Modules ) . Percent * 100 ;
110
133
111
134
foreach ( var _module in result . Modules )
112
135
{
@@ -115,37 +138,40 @@ static int Main(string[] args)
115
138
var methodPercent = summary . CalculateMethodCoverage ( _module . Value ) . Percent * 100 ;
116
139
117
140
coverageTable . AddRow ( Path . GetFileNameWithoutExtension ( _module . Key ) , $ "{ linePercent } %", $ "{ branchPercent } %", $ "{ methodPercent } %") ;
141
+ }
118
142
119
- if ( dThreshold > 0 )
143
+ logger . LogInformation ( coverageTable . ToStringAlternative ( ) ) ;
144
+
145
+ coverageTable . Columns . Clear ( ) ;
146
+ coverageTable . Rows . Clear ( ) ;
147
+
148
+ coverageTable . AddColumn ( new [ ] { "" , "Line" , "Branch" , "Method" } ) ;
149
+ coverageTable . AddRow ( "Total" , $ "{ totalLinePercent } %", $ "{ totalBranchPercent } %", $ "{ totalMethodPercent } %") ;
150
+ coverageTable . AddRow ( "Average" , $ "{ totalLinePercent / numModules } %", $ "{ totalBranchPercent / numModules } %", $ "{ totalMethodPercent / numModules } %") ;
151
+
152
+ logger . LogInformation ( coverageTable . ToStringAlternative ( ) ) ;
153
+
154
+ thresholdTypeFlags = result . GetThresholdTypesBelowThreshold ( summary , dThreshold , thresholdTypeFlags , dThresholdStat ) ;
155
+ if ( thresholdTypeFlags != ThresholdTypeFlags . None )
156
+ {
157
+ var exceptionMessageBuilder = new StringBuilder ( ) ;
158
+ if ( ( thresholdTypeFlags & ThresholdTypeFlags . Line ) != ThresholdTypeFlags . None )
120
159
{
121
- if ( linePercent < dThreshold && dThresholdTypes . Contains ( "line" ) )
122
- {
123
- exceptionBuilder . AppendLine ( $ "'{ Path . GetFileNameWithoutExtension ( _module . Key ) } ' has a line coverage '{ linePercent } %' below specified threshold '{ dThreshold } %'") ;
124
- thresholdFailed = true ;
125
- }
126
-
127
- if ( branchPercent < dThreshold && dThresholdTypes . Contains ( "branch" ) )
128
- {
129
- exceptionBuilder . AppendLine ( $ "'{ Path . GetFileNameWithoutExtension ( _module . Key ) } ' has a branch coverage '{ branchPercent } %' below specified threshold '{ dThreshold } %'") ;
130
- thresholdFailed = true ;
131
- }
132
-
133
- if ( methodPercent < dThreshold && dThresholdTypes . Contains ( "method" ) )
134
- {
135
- exceptionBuilder . AppendLine ( $ "'{ Path . GetFileNameWithoutExtension ( _module . Key ) } ' has a method coverage '{ methodPercent } %' below specified threshold '{ dThreshold } %'") ;
136
- thresholdFailed = true ;
137
- }
160
+ exceptionMessageBuilder . AppendLine ( $ "The { dThresholdStat . ToString ( ) . ToLower ( ) } line coverage is below the specified { dThreshold } ") ;
138
161
}
139
- }
140
162
141
- logger . LogInformation ( string . Empty ) ;
142
- logger . LogInformation ( coverageTable . ToStringAlternative ( ) ) ;
143
- logger . LogInformation ( $ "Total Line: { overallLineCoverage . Percent * 100 } %") ;
144
- logger . LogInformation ( $ "Total Branch: { overallBranchCoverage . Percent * 100 } %") ;
145
- logger . LogInformation ( $ "Total Method: { overallMethodCoverage . Percent * 100 } %") ;
163
+ if ( ( thresholdTypeFlags & ThresholdTypeFlags . Branch ) != ThresholdTypeFlags . None )
164
+ {
165
+ exceptionMessageBuilder . AppendLine ( $ "The { dThresholdStat . ToString ( ) . ToLower ( ) } branch coverage is below the specified { dThreshold } ") ;
166
+ }
146
167
147
- if ( thresholdFailed )
148
- throw new Exception ( exceptionBuilder . ToString ( ) . TrimEnd ( Environment . NewLine . ToCharArray ( ) ) ) ;
168
+ if ( ( thresholdTypeFlags & ThresholdTypeFlags . Method ) != ThresholdTypeFlags . None )
169
+ {
170
+ exceptionMessageBuilder . AppendLine ( $ "The { dThresholdStat . ToString ( ) . ToLower ( ) } method coverage is below the specified { dThreshold } ") ;
171
+ }
172
+
173
+ throw new Exception ( exceptionMessageBuilder . ToString ( ) ) ;
174
+ }
149
175
150
176
return process . ExitCode == 0 ? 0 : process . ExitCode ;
151
177
} ) ;
0 commit comments