@@ -29,7 +29,10 @@ def pyfunc(x: int) -> int:
2929 result = testdir .runpytest_subprocess (* xdist_args )
3030 result .assert_outcomes ()
3131 result = testdir .runpytest_subprocess ('--mypy' , * xdist_args )
32- result .assert_outcomes (passed = pyfile_count )
32+ mypy_file_checks = pyfile_count
33+ mypy_status_check = 1
34+ mypy_checks = mypy_file_checks + mypy_status_check
35+ result .assert_outcomes (passed = mypy_checks )
3336 assert result .ret == 0
3437
3538
@@ -42,7 +45,10 @@ def pyfunc(x: int) -> str:
4245 result = testdir .runpytest_subprocess (* xdist_args )
4346 result .assert_outcomes ()
4447 result = testdir .runpytest_subprocess ('--mypy' , * xdist_args )
45- result .assert_outcomes (failed = 1 )
48+ mypy_file_checks = 1
49+ mypy_status_check = 1
50+ mypy_checks = mypy_file_checks + mypy_status_check
51+ result .assert_outcomes (failed = mypy_checks )
4652 result .stdout .fnmatch_lines ([
4753 '2: error: Incompatible return value*' ,
4854 ])
@@ -62,7 +68,10 @@ def test_mypy_ignore_missings_imports(testdir, xdist_args):
6268 pass
6369 ''' .format (module_name = module_name ))
6470 result = testdir .runpytest_subprocess ('--mypy' , * xdist_args )
65- result .assert_outcomes (failed = 1 )
71+ mypy_file_checks = 1
72+ mypy_status_check = 1
73+ mypy_checks = mypy_file_checks + mypy_status_check
74+ result .assert_outcomes (failed = mypy_checks )
6675 result .stdout .fnmatch_lines ([
6776 "2: error: Cannot find *module named '{module_name}'" .format (
6877 module_name = module_name ,
@@ -73,7 +82,7 @@ def test_mypy_ignore_missings_imports(testdir, xdist_args):
7382 '--mypy-ignore-missing-imports' ,
7483 * xdist_args
7584 )
76- result .assert_outcomes (passed = 1 )
85+ result .assert_outcomes (passed = mypy_checks )
7786 assert result .ret == 0
7887
7988
@@ -84,10 +93,14 @@ def test_fails():
8493 assert False
8594 ''' )
8695 result = testdir .runpytest_subprocess ('--mypy' , * xdist_args )
87- result .assert_outcomes (failed = 1 , passed = 1 )
96+ test_count = 1
97+ mypy_file_checks = 1
98+ mypy_status_check = 1
99+ mypy_checks = mypy_file_checks + mypy_status_check
100+ result .assert_outcomes (failed = test_count , passed = mypy_checks )
88101 assert result .ret != 0
89102 result = testdir .runpytest_subprocess ('--mypy' , '-m' , 'mypy' , * xdist_args )
90- result .assert_outcomes (passed = 1 )
103+ result .assert_outcomes (passed = mypy_checks )
91104 assert result .ret == 0
92105
93106
@@ -107,7 +120,12 @@ def runtest(self):
107120 result = testdir .runpytest_subprocess (* xdist_args )
108121 result .assert_outcomes ()
109122 result = testdir .runpytest_subprocess ('--mypy' , * xdist_args )
110- result .assert_outcomes (failed = 1 )
123+ mypy_file_checks = 1 # conftest.py
124+ mypy_status_check = 1
125+ result .assert_outcomes (
126+ failed = mypy_file_checks , # patched to raise an Exception
127+ passed = mypy_status_check , # conftest.py has no type errors.
128+ )
111129 result .stdout .fnmatch_lines (['*' + message ])
112130 assert result .ret != 0
113131
@@ -171,6 +189,9 @@ def test_pytest_collection_modifyitems(testdir, xdist_args):
171189 Verify that collected files which are removed in a
172190 pytest_collection_modifyitems implementation are not
173191 checked by mypy.
192+
193+ This would also fail if a MypyStatusItem were injected
194+ despite there being no MypyFileItems.
174195 """
175196 testdir .makepyfile (conftest = '''
176197 def pytest_collection_modifyitems(session, config, items):
@@ -190,5 +211,49 @@ def test_pass():
190211 pass
191212 ''' )
192213 result = testdir .runpytest_subprocess ('--mypy' , * xdist_args )
193- result .assert_outcomes (passed = 1 )
214+ test_count = 1
215+ result .assert_outcomes (passed = test_count )
194216 assert result .ret == 0
217+
218+
219+ def test_mypy_indirect (testdir , xdist_args ):
220+ """Verify that uncollected files checked by mypy cause a failure."""
221+ testdir .makepyfile (bad = '''
222+ def pyfunc(x: int) -> str:
223+ return x * 2
224+ ''' )
225+ testdir .makepyfile (good = '''
226+ import bad
227+ ''' )
228+ xdist_args .append ('good.py' ) # Nothing may come after xdist_args in py34.
229+ result = testdir .runpytest_subprocess ('--mypy' , * xdist_args )
230+ assert result .ret != 0
231+
232+
233+ def test_mypy_indirect_inject (testdir , xdist_args ):
234+ """
235+ Verify that uncollected files checked by mypy because of a MypyFileItem
236+ injected in pytest_collection_modifyitems cause a failure.
237+ """
238+ testdir .makepyfile (bad = '''
239+ def pyfunc(x: int) -> str:
240+ return x * 2
241+ ''' )
242+ testdir .makepyfile (good = '''
243+ import bad
244+ ''' )
245+ testdir .makepyfile (conftest = '''
246+ import py
247+ import pytest
248+
249+ @pytest.hookimpl(trylast=True) # Inject as late as possible.
250+ def pytest_collection_modifyitems(session, config, items):
251+ plugin = config.pluginmanager.getplugin('mypy')
252+ items.append(
253+ plugin.MypyFileItem(py.path.local('good.py'), session),
254+ )
255+ ''' )
256+ testdir .mkdir ('empty' )
257+ xdist_args .append ('empty' ) # Nothing may come after xdist_args in py34.
258+ result = testdir .runpytest_subprocess ('--mypy' , * xdist_args )
259+ assert result .ret != 0
0 commit comments