Skip to content

Commit dee6c36

Browse files
committed
Merge pull request #34 from WoLpH/2.0
Added support for `cov-min` option to require coverage percentage
2 parents 313d5b9 + f80178d commit dee6c36

File tree

3 files changed

+60
-6
lines changed

3 files changed

+60
-6
lines changed

cov-core/cov_core.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,12 @@ def sep(stream, s, txt):
7878

7979
def summary(self, stream):
8080
"""Produce coverage reports."""
81+
total = 0
82+
8183
if self.cov_report == ['']:
82-
return
84+
with open(os.devnull, 'w') as null:
85+
total = self.cov.report(show_missing=True, ignore_errors=True, file=null)
86+
return total
8387

8488
# Output coverage section header.
8589
if len(self.node_descs) == 1:
@@ -92,21 +96,21 @@ def summary(self, stream):
9296
# Produce terminal report if wanted.
9397
if 'term' in self.cov_report or 'term-missing' in self.cov_report:
9498
show_missing = 'term-missing' in self.cov_report
95-
self.cov.report(show_missing=show_missing, ignore_errors=True, file=stream)
99+
total = self.cov.report(show_missing=show_missing, ignore_errors=True, file=stream)
96100

97101
# Produce annotated source code report if wanted.
98102
if 'annotate' in self.cov_report:
99-
self.cov.annotate(ignore_errors=True)
103+
total = self.cov.annotate(ignore_errors=True)
100104
stream.write('Coverage annotated source written next to source\n')
101105

102106
# Produce html report if wanted.
103107
if 'html' in self.cov_report:
104-
self.cov.html_report(ignore_errors=True)
108+
total = self.cov.html_report(ignore_errors=True)
105109
stream.write('Coverage HTML written to dir %s\n' % self.cov.config.html_dir)
106110

107111
# Produce xml report if wanted.
108112
if 'xml' in self.cov_report:
109-
self.cov.xml_report(ignore_errors=True)
113+
total = self.cov.xml_report(ignore_errors=True)
110114
stream.write('Coverage XML written to file %s\n' % self.cov.config.xml_output)
111115

112116
# Report on any failed slaves.
@@ -117,6 +121,8 @@ def summary(self, stream):
117121
for node in self.failed_slaves:
118122
stream.write('%s\n' % node.gateway.id)
119123

124+
return total
125+
120126

121127
class Central(CovController):
122128
"""Implementation for centralised operation."""

pytest-cov/pytest_cov.py

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@
88
import cov_core_init
99

1010

11+
class CoverageError(Exception):
12+
'''Indicates that our coverage is too low'''
13+
14+
1115
def pytest_addoption(parser):
1216
"""Add options to control coverage."""
1317

@@ -34,6 +38,8 @@ def pytest_addoption(parser):
3438
dest='no_cov_on_fail',
3539
help='do not report coverage if test run fails, '
3640
'default: False')
41+
group.addoption('--cov-min', action='store', metavar='MIN', type='int',
42+
help='Fail if the total coverage is less than MIN.')
3743

3844

3945
@pytest.mark.tryfirst
@@ -148,7 +154,13 @@ def pytest_terminal_summary(self, terminalreporter):
148154
if self.cov_controller is None:
149155
return
150156
if not (self.failed and self.options.no_cov_on_fail):
151-
self.cov_controller.summary(terminalreporter.writer)
157+
total = self.cov_controller.summary(terminalreporter.writer)
158+
assert total is not None, 'Test coverage should never be `None`'
159+
cov_min = self.options.cov_min
160+
if cov_min is not None and total < cov_min:
161+
raise CoverageError(('Required test coverage of %d%% not '
162+
'reached. Total coverage: %.2f%%')
163+
% (self.options.cov_min, total))
152164

153165
def pytest_runtest_setup(self, item):
154166
if os.getpid() != self.pid:

pytest-cov/test_pytest_cov.py

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,42 @@ def test_central(testdir):
113113
assert result.ret == 0
114114

115115

116+
def test_cov_min_100(testdir):
117+
script = testdir.makepyfile(SCRIPT)
118+
119+
result = testdir.runpytest('-v',
120+
'--cov', '--cov-source=%s' % script.dirpath(),
121+
'--cov-report=term-missing',
122+
'--cov-min=100',
123+
script)
124+
125+
assert result.ret == 1
126+
127+
128+
def test_cov_min_50(testdir):
129+
script = testdir.makepyfile(SCRIPT)
130+
131+
result = testdir.runpytest('-v',
132+
'--cov', '--cov-source=%s' % script.dirpath(),
133+
'--cov-report=term-missing',
134+
'--cov-min=50',
135+
script)
136+
137+
assert result.ret == 0
138+
139+
140+
def test_cov_min_no_report(testdir):
141+
script = testdir.makepyfile(SCRIPT)
142+
143+
result = testdir.runpytest('-v',
144+
'--cov', '--cov-source=%s' % script.dirpath(),
145+
'--cov-report=',
146+
'--cov-min=50',
147+
script)
148+
149+
assert result.ret == 0
150+
151+
116152
def test_central_nonspecific(testdir):
117153
script = testdir.makepyfile(SCRIPT)
118154

0 commit comments

Comments
 (0)