1
1
import signal
2
2
import textwrap
3
3
4
+ import pexpect
4
5
import pytest
5
6
6
7
8
+ PYTEST_VERSION = tuple (int (v ) for v in pytest .__version__ .split ("." )[:2 ])
9
+
10
+
7
11
@pytest .fixture (
8
12
params = [
9
13
True , # xdist enabled, active
@@ -309,7 +313,8 @@ def pyfunc(x):
309
313
assert result .ret != 0
310
314
311
315
312
- def test_looponfail (testdir ):
316
+ @pytest .mark .parametrize ("module_name" , ["__init__" , "test_demo" ])
317
+ def test_looponfail (testdir , module_name ):
313
318
"""Ensure that the plugin works with --looponfail."""
314
319
315
320
pass_source = textwrap .dedent (
@@ -324,7 +329,7 @@ def pyfunc(x: int) -> str:
324
329
return x * 2
325
330
""" ,
326
331
)
327
- pyfile = testdir .makepyfile (fail_source )
332
+ pyfile = testdir .makepyfile (** { module_name : fail_source } )
328
333
looponfailroot = testdir .mkdir ("looponfailroot" )
329
334
looponfailroot_pyfile = looponfailroot .join (pyfile .basename )
330
335
pyfile .move (looponfailroot_pyfile )
@@ -345,6 +350,14 @@ def pyfunc(x: int) -> str:
345
350
expect_timeout = 30.0 ,
346
351
)
347
352
353
+ num_tests = 2
354
+ if module_name == "__init__" and (3 , 10 ) <= PYTEST_VERSION < (6 , 2 ):
355
+ # https://github.com/pytest-dev/pytest/issues/8016
356
+ # Pytest had a bug where it assumed only a Package would have a basename of
357
+ # __init__.py. In this test, Pytest mistakes MypyFile for a Package and
358
+ # returns after collecting only one object (the MypyFileItem).
359
+ num_tests = 1
360
+
348
361
def _expect_session ():
349
362
child .expect ("==== test session starts ====" )
350
363
@@ -353,10 +366,11 @@ def _expect_failure():
353
366
child .expect ("==== FAILURES ====" )
354
367
child .expect (pyfile .basename + " ____" )
355
368
child .expect ("2: error: Incompatible return value" )
356
- # These only show with mypy>=0.730:
357
- # child.expect("==== mypy ====")
358
- # child.expect("Found 1 error in 1 file (checked 1 source file)")
359
- child .expect ("2 failed" )
369
+ # if num_tests == 2:
370
+ # # These only show with mypy>=0.730:
371
+ # child.expect("==== mypy ====")
372
+ # child.expect("Found 1 error in 1 file (checked 1 source file)")
373
+ child .expect (str (num_tests ) + " failed" )
360
374
child .expect ("#### LOOPONFAILING ####" )
361
375
_expect_waiting ()
362
376
@@ -375,10 +389,27 @@ def _expect_changed():
375
389
def _expect_success ():
376
390
for _ in range (2 ):
377
391
_expect_session ()
378
- # These only show with mypy>=0.730:
379
- # child.expect("==== mypy ====")
380
- # child.expect("Success: no issues found in 1 source file")
381
- child .expect ("2 passed" )
392
+ # if num_tests == 2:
393
+ # # These only show with mypy>=0.730:
394
+ # child.expect("==== mypy ====")
395
+ # child.expect("Success: no issues found in 1 source file")
396
+ try :
397
+ child .expect (str (num_tests ) + " passed" )
398
+ except pexpect .exceptions .TIMEOUT :
399
+ if module_name == "__init__" and (6 , 0 ) <= PYTEST_VERSION < (6 , 2 ):
400
+ # MypyItems hit the __init__.py bug too when --looponfail
401
+ # re-collects them after the failing file is modified.
402
+ # Unlike MypyFile, MypyItem is not a Collector, so this used
403
+ # to cause an AttributeError until a workaround was added
404
+ # (MypyItem.collect was defined to yield itself).
405
+ # Mypy probably noticed the __init__.py problem during the
406
+ # development of Pytest 6.0, but the error was addressed
407
+ # with an isinstance assertion, which broke the workaround.
408
+ # Here, we hit that assertion:
409
+ child .expect ("AssertionError" )
410
+ child .expect ("1 error" )
411
+ pytest .xfail ("https://github.com/pytest-dev/pytest/issues/8016" )
412
+ raise
382
413
_expect_waiting ()
383
414
384
415
def _break ():
@@ -391,3 +422,27 @@ def _break():
391
422
_break ()
392
423
_fix ()
393
424
child .kill (signal .SIGTERM )
425
+
426
+
427
+ def test_mypy_item_collect (testdir , xdist_args ):
428
+ """Ensure coverage for a 3.10<=pytest<6.0 workaround."""
429
+ testdir .makepyfile (
430
+ """
431
+ def test_mypy_item_collect(request):
432
+ plugin = request.config.pluginmanager.getplugin("mypy")
433
+ mypy_items = [
434
+ item
435
+ for item in request.session.items
436
+ if isinstance(item, plugin.MypyItem)
437
+ ]
438
+ assert mypy_items
439
+ for mypy_item in mypy_items:
440
+ assert all(item is mypy_item for item in mypy_item.collect())
441
+ """ ,
442
+ )
443
+ result = testdir .runpytest_subprocess ("--mypy" , * xdist_args )
444
+ test_count = 1
445
+ mypy_file_checks = 1
446
+ mypy_status_check = 1
447
+ result .assert_outcomes (passed = test_count + mypy_file_checks + mypy_status_check )
448
+ assert result .ret == 0
0 commit comments