@@ -157,15 +157,6 @@ def test_foo(cov):
157
157
pytest .param ('-n 1' , marks = pytest .mark .skipif ('sys.platform == "win32" and platform.python_implementation() == "PyPy"' ))
158
158
], ids = ['nodist' , 'xdist' ])
159
159
160
- skipif_multiprocessing_is_broken = pytest .mark .skipif (
161
- 'sys.version_info[:2] >= (3, 8)' ,
162
- reason = "deadlocks on Python 3.8+, see: https://bugs.python.org/issue38227"
163
- )
164
- method_params = pytest .mark .parametrize ('method' , [
165
- pytest .param ('fork' , marks = skipif_multiprocessing_is_broken ),
166
- pytest .param ('spawn' , marks = skipif_multiprocessing_is_broken ),
167
- ])
168
-
169
160
170
161
@pytest .fixture (scope = 'session' , autouse = True )
171
162
def adjust_sys_path ():
@@ -203,7 +194,7 @@ def prop(request):
203
194
)
204
195
205
196
206
- def test_central (testdir , prop ):
197
+ def test_central (pytester , testdir , prop ):
207
198
script = testdir .makepyfile (prop .code )
208
199
testdir .tmpdir .join ('.coveragerc' ).write (prop .fullconf )
209
200
@@ -470,7 +461,7 @@ def test_cov_min_no_report(testdir):
470
461
])
471
462
472
463
473
- def test_central_nonspecific (testdir , prop ):
464
+ def test_central_nonspecific (pytester , testdir , prop ):
474
465
script = testdir .makepyfile (prop .code )
475
466
testdir .tmpdir .join ('.coveragerc' ).write (prop .fullconf )
476
467
result = testdir .runpytest ('-v' ,
@@ -505,7 +496,7 @@ def test_cov_min_from_coveragerc(testdir):
505
496
assert result .ret != 0
506
497
507
498
508
- def test_central_coveragerc (testdir , prop ):
499
+ def test_central_coveragerc (pytester , testdir , prop ):
509
500
script = testdir .makepyfile (prop .code )
510
501
testdir .tmpdir .join ('.coveragerc' ).write (COVERAGERC_SOURCE + prop .conf )
511
502
@@ -523,7 +514,7 @@ def test_central_coveragerc(testdir, prop):
523
514
524
515
525
516
@xdist_params
526
- def test_central_with_path_aliasing (testdir , monkeypatch , opts , prop ):
517
+ def test_central_with_path_aliasing (pytester , testdir , monkeypatch , opts , prop ):
527
518
mod1 = testdir .mkdir ('src' ).join ('mod.py' )
528
519
mod1 .write (SCRIPT )
529
520
mod2 = testdir .mkdir ('aliased' ).join ('mod.py' )
@@ -557,7 +548,7 @@ def test_central_with_path_aliasing(testdir, monkeypatch, opts, prop):
557
548
558
549
559
550
@xdist_params
560
- def test_borken_cwd (testdir , monkeypatch , opts ):
551
+ def test_borken_cwd (pytester , testdir , monkeypatch , opts ):
561
552
testdir .makepyfile (mod = '''
562
553
def foobar(a, b):
563
554
return a + b
@@ -596,7 +587,7 @@ def test_foobar(bad):
596
587
assert result .ret == 0
597
588
598
589
599
- def test_subprocess_with_path_aliasing (testdir , monkeypatch ):
590
+ def test_subprocess_with_path_aliasing (pytester , testdir , monkeypatch ):
600
591
src = testdir .mkdir ('src' )
601
592
src .join ('parent_script.py' ).write (SCRIPT_PARENT )
602
593
src .join ('child_script.py' ).write (SCRIPT_CHILD )
@@ -632,7 +623,7 @@ def test_subprocess_with_path_aliasing(testdir, monkeypatch):
632
623
assert result .ret == 0
633
624
634
625
635
- def test_show_missing_coveragerc (testdir , prop ):
626
+ def test_show_missing_coveragerc (pytester , testdir , prop ):
636
627
script = testdir .makepyfile (prop .code )
637
628
testdir .tmpdir .join ('.coveragerc' ).write ("""
638
629
[run]
@@ -675,7 +666,7 @@ def test_fail():
675
666
result .stdout .fnmatch_lines (['*1 failed*' ])
676
667
677
668
678
- def test_no_cov (testdir , monkeypatch ):
669
+ def test_no_cov (pytester , testdir , monkeypatch ):
679
670
script = testdir .makepyfile (SCRIPT )
680
671
testdir .makeini ("""
681
672
[pytest]
@@ -742,7 +733,7 @@ def test_foo(foo):
742
733
743
734
744
735
@pytest .mark .skipif ('sys.platform == "win32" and platform.python_implementation() == "PyPy"' )
745
- def test_dist_collocated (testdir , prop ):
736
+ def test_dist_collocated (pytester , testdir , prop ):
746
737
script = testdir .makepyfile (prop .code )
747
738
testdir .tmpdir .join ('.coveragerc' ).write (prop .fullconf )
748
739
result = testdir .runpytest ('-v' ,
@@ -762,7 +753,7 @@ def test_dist_collocated(testdir, prop):
762
753
763
754
764
755
@pytest .mark .skipif ('sys.platform == "win32" and platform.python_implementation() == "PyPy"' )
765
- def test_dist_not_collocated (testdir , prop ):
756
+ def test_dist_not_collocated (pytester , testdir , prop ):
766
757
script = testdir .makepyfile (prop .code )
767
758
dir1 = testdir .mkdir ('dir1' )
768
759
dir2 = testdir .mkdir ('dir2' )
@@ -795,7 +786,7 @@ def test_dist_not_collocated(testdir, prop):
795
786
796
787
797
788
@pytest .mark .skipif ('sys.platform == "win32" and platform.python_implementation() == "PyPy"' )
798
- def test_dist_not_collocated_coveragerc_source (testdir , prop ):
789
+ def test_dist_not_collocated_coveragerc_source (pytester , testdir , prop ):
799
790
script = testdir .makepyfile (prop .code )
800
791
dir1 = testdir .mkdir ('dir1' )
801
792
dir2 = testdir .mkdir ('dir2' )
@@ -870,7 +861,7 @@ def test_central_subprocess_change_cwd(testdir):
870
861
assert result .ret == 0
871
862
872
863
873
- def test_central_subprocess_change_cwd_with_pythonpath (testdir , monkeypatch ):
864
+ def test_central_subprocess_change_cwd_with_pythonpath (pytester , testdir , monkeypatch ):
874
865
stuff = testdir .mkdir ('stuff' )
875
866
parent_script = stuff .join ('parent_script.py' )
876
867
parent_script .write (SCRIPT_PARENT_CHANGE_CWD_IMPORT_CHILD )
@@ -941,7 +932,7 @@ def test_dist_subprocess_collocated(testdir):
941
932
942
933
943
934
@pytest .mark .skipif ('sys.platform == "win32" and platform.python_implementation() == "PyPy"' )
944
- def test_dist_subprocess_not_collocated (testdir , tmpdir ):
935
+ def test_dist_subprocess_not_collocated (pytester , testdir , tmpdir ):
945
936
scripts = testdir .makepyfile (parent_script = SCRIPT_PARENT ,
946
937
child_script = SCRIPT_CHILD )
947
938
parent_script = scripts .dirpath ().join ('parent_script.py' )
@@ -1071,10 +1062,11 @@ def test_funcarg_not_active(testdir):
1071
1062
@pytest .mark .skipif ("sys.version_info[0] < 3" , reason = "no context manager api on Python 2" )
1072
1063
@pytest .mark .skipif ('sys.platform == "win32"' , reason = "multiprocessing support is broken on Windows" )
1073
1064
@pytest .mark .skipif ('platform.python_implementation() == "PyPy"' , reason = "often deadlocks on PyPy" )
1074
- @method_params
1075
- def test_multiprocessing_pool (testdir , method ):
1065
+ @pytest .mark .parametrize ('method' , ['fork' , 'spawn' ])
1066
+ @pytest .mark .xfail
1067
+ def test_multiprocessing_pool (pytester , testdir , method ):
1076
1068
pytest .importorskip ('multiprocessing.util' )
1077
-
1069
+ pytester . path . joinpath ( ".coveragerc" ). write_text ( MP_COVERAGERC )
1078
1070
script = testdir .makepyfile ('''
1079
1071
import multiprocessing
1080
1072
@@ -1084,9 +1076,6 @@ def target_fn(a):
1084
1076
1085
1077
def test_run_target():
1086
1078
multiprocessing.set_start_method({!r})
1087
- from pytest_cov.embed import cleanup_on_sigterm
1088
- cleanup_on_sigterm()
1089
-
1090
1079
for i in range(33):
1091
1080
with multiprocessing.Pool(3) as p:
1092
1081
p.map(target_fn, [i * 3 + j for j in range(3)])
@@ -1102,21 +1091,21 @@ def test_run_target():
1102
1091
1103
1092
assert "Doesn't seem to be a coverage.py data file" not in result .stdout .str ()
1104
1093
assert "Doesn't seem to be a coverage.py data file" not in result .stderr .str ()
1105
- assert not testdir .tmpdir .listdir (".coverage.*" )
1106
1094
result .stdout .fnmatch_lines ([
1107
1095
'*- coverage: platform *, python * -*' ,
1108
1096
'test_multiprocessing_pool* 100%*' ,
1109
1097
'*1 passed*'
1110
1098
])
1099
+ assert not testdir .tmpdir .listdir (".coverage.*" )
1111
1100
assert result .ret == 0
1112
1101
1113
1102
1114
1103
@pytest .mark .skipif ('sys.platform == "win32"' , reason = "multiprocessing support is broken on Windows" )
1115
1104
@pytest .mark .skipif ('platform.python_implementation() == "PyPy"' , reason = "often deadlocks on PyPy" )
1116
- @method_params
1117
- def test_multiprocessing_pool_terminate (testdir , method ):
1105
+ @pytest . mark . parametrize ( 'method' , [ 'fork' , 'spawn' ])
1106
+ def test_multiprocessing_pool_terminate (pytester , testdir , method ):
1118
1107
pytest .importorskip ('multiprocessing.util' )
1119
-
1108
+ pytester . path . joinpath ( ".coveragerc" ). write_text ( MP_COVERAGERC )
1120
1109
script = testdir .makepyfile ('''
1121
1110
import multiprocessing
1122
1111
@@ -1126,8 +1115,6 @@ def target_fn(a):
1126
1115
1127
1116
def test_run_target():
1128
1117
multiprocessing.set_start_method({!r})
1129
- from pytest_cov.embed import cleanup_on_sigterm
1130
- cleanup_on_sigterm()
1131
1118
1132
1119
for i in range(33):
1133
1120
p = multiprocessing.Pool(3)
@@ -1147,21 +1134,21 @@ def test_run_target():
1147
1134
1148
1135
assert "Doesn't seem to be a coverage.py data file" not in result .stdout .str ()
1149
1136
assert "Doesn't seem to be a coverage.py data file" not in result .stderr .str ()
1150
- assert not testdir .tmpdir .listdir (".coverage.*" )
1151
1137
result .stdout .fnmatch_lines ([
1152
1138
'*- coverage: platform *, python * -*' ,
1153
1139
'test_multiprocessing_pool* 100%*' ,
1154
1140
'*1 passed*'
1155
1141
])
1142
+ assert not testdir .tmpdir .listdir (".coverage.*" )
1156
1143
assert result .ret == 0
1157
1144
1158
1145
1159
1146
@pytest .mark .skipif ('sys.platform == "win32"' , reason = "multiprocessing support is broken on Windows" )
1160
1147
@pytest .mark .skipif ('sys.version_info[0] > 2 and platform.python_implementation() == "PyPy"' , reason = "broken on PyPy3" )
1161
- @method_params
1162
- def test_multiprocessing_pool_close (testdir , method ):
1148
+ @pytest . mark . parametrize ( 'method' , [ 'fork' , 'spawn' ])
1149
+ def test_multiprocessing_pool_close (pytester , testdir , method ):
1163
1150
pytest .importorskip ('multiprocessing.util' )
1164
-
1151
+ pytester . path . joinpath ( ".coveragerc" ). write_text ( MP_COVERAGERC )
1165
1152
script = testdir .makepyfile ('''
1166
1153
import multiprocessing
1167
1154
@@ -1188,20 +1175,20 @@ def test_run_target():
1188
1175
script )
1189
1176
assert "Doesn't seem to be a coverage.py data file" not in result .stdout .str ()
1190
1177
assert "Doesn't seem to be a coverage.py data file" not in result .stderr .str ()
1191
- assert not testdir .tmpdir .listdir (".coverage.*" )
1192
1178
result .stdout .fnmatch_lines ([
1193
1179
'*- coverage: platform *, python * -*' ,
1194
1180
'test_multiprocessing_pool* 100%*' ,
1195
1181
'*1 passed*'
1196
1182
])
1183
+ # assert not testdir.tmpdir.listdir(".coverage.*")
1197
1184
assert result .ret == 0
1198
1185
1199
1186
1200
1187
@pytest .mark .skipif ('sys.platform == "win32"' , reason = "multiprocessing support is broken on Windows" )
1201
- @method_params
1202
- def test_multiprocessing_process (testdir , method ):
1188
+ @pytest . mark . parametrize ( 'method' , [ 'fork' , 'spawn' ])
1189
+ def test_multiprocessing_process (pytester , testdir , method ):
1203
1190
pytest .importorskip ('multiprocessing.util' )
1204
-
1191
+ pytester . path . joinpath ( ".coveragerc" ). write_text ( MP_COVERAGERC )
1205
1192
script = testdir .makepyfile ('''
1206
1193
import multiprocessing
1207
1194
@@ -1230,9 +1217,9 @@ def test_run_target():
1230
1217
1231
1218
1232
1219
@pytest .mark .skipif ('sys.platform == "win32"' , reason = "multiprocessing support is broken on Windows" )
1233
- def test_multiprocessing_process_no_source (testdir ):
1220
+ def test_multiprocessing_process_no_source (pytester , testdir ):
1234
1221
pytest .importorskip ('multiprocessing.util' )
1235
-
1222
+ pytester . path . joinpath ( ".coveragerc" ). write_text ( MP_COVERAGERC )
1236
1223
script = testdir .makepyfile ('''
1237
1224
import multiprocessing
1238
1225
@@ -1260,9 +1247,9 @@ def test_run_target():
1260
1247
1261
1248
1262
1249
@pytest .mark .skipif ('sys.platform == "win32"' , reason = "multiprocessing support is broken on Windows" )
1263
- def test_multiprocessing_process_with_terminate (testdir ):
1250
+ def test_multiprocessing_process_with_terminate (pytester , testdir ):
1264
1251
pytest .importorskip ('multiprocessing.util' )
1265
-
1252
+ pytester . path . joinpath ( ".coveragerc" ). write_text ( MP_COVERAGERC )
1266
1253
script = testdir .makepyfile ('''
1267
1254
import multiprocessing
1268
1255
import time
@@ -1349,7 +1336,7 @@ def test_run():
1349
1336
('cleanup_on_signal(signal.SIGBREAK)' , '87% 21-22' ),
1350
1337
('cleanup()' , '73% 19-22' ),
1351
1338
])
1352
- def test_cleanup_on_sigterm_sig_break (testdir , setup ):
1339
+ def test_cleanup_on_sigterm_sig_break (pytester , testdir , setup ):
1353
1340
# worth a read: https://stefan.sofa-rockers.org/2013/08/15/handling-sub-process-hierarchies-python-linux-os-x/
1354
1341
script = testdir .makepyfile ('''
1355
1342
import os, signal, subprocess, sys, time
@@ -1395,7 +1382,7 @@ def test_run():
1395
1382
('cleanup_on_sigterm()' , '88% 18-19' ),
1396
1383
('cleanup()' , '75% 16-19' ),
1397
1384
])
1398
- def test_cleanup_on_sigterm_sig_dfl (testdir , setup ):
1385
+ def test_cleanup_on_sigterm_sig_dfl (pytester , testdir , setup ):
1399
1386
script = testdir .makepyfile ('''
1400
1387
import os, signal, subprocess, sys, time
1401
1388
@@ -1551,17 +1538,17 @@ def test_cover_conftest(testdir):
1551
1538
1552
1539
1553
1540
@pytest .mark .skipif ('sys.platform == "win32" and platform.python_implementation() == "PyPy"' )
1554
- def test_cover_looponfail (testdir , monkeypatch ):
1541
+ def test_cover_looponfail (pytester , testdir , monkeypatch ):
1555
1542
testdir .makepyfile (mod = MODULE )
1556
1543
testdir .makeconftest (CONFTEST )
1557
1544
script = testdir .makepyfile (BASIC_TEST )
1558
1545
1559
1546
def mock_run (* args , ** kwargs ):
1560
1547
return _TestProcess (* map (str , args ))
1561
1548
1562
- monkeypatch .setattr (testdir , 'run' , mock_run )
1549
+ monkeypatch .setattr (pytester , testdir , 'run' , mock_run )
1563
1550
assert testdir .run is mock_run
1564
- if hasattr (testdir , '_pytester' ):
1551
+ if hasattr (pytester , testdir , '_pytester' ):
1565
1552
monkeypatch .setattr (testdir ._pytester , 'run' , mock_run )
1566
1553
assert testdir ._pytester .run is mock_run
1567
1554
with testdir .runpytest ('-v' ,
@@ -1637,7 +1624,13 @@ def test_basic(no_cover):
1637
1624
# Regexes for lines to exclude from consideration
1638
1625
exclude_lines =
1639
1626
raise NotImplementedError
1627
+ '''
1640
1628
1629
+ MP_COVERAGERC = '''
1630
+ [run]
1631
+ concurrency = multiprocessing
1632
+ parallel = true
1633
+ sigterm = True
1641
1634
'''
1642
1635
1643
1636
EXCLUDED_TEST = '''
@@ -1704,7 +1697,7 @@ def test_basic():
1704
1697
@pytest .mark .parametrize ('report_option' , [
1705
1698
'term-missing:skip-covered' ,
1706
1699
'term:skip-covered' ])
1707
- def test_skip_covered_cli (testdir , report_option ):
1700
+ def test_skip_covered_cli (pytester , testdir , report_option ):
1708
1701
testdir .makefile ('' , coveragerc = SKIP_COVERED_COVERAGERC )
1709
1702
script = testdir .makepyfile (SKIP_COVERED_TEST )
1710
1703
result = testdir .runpytest ('-v' ,
@@ -1910,7 +1903,7 @@ def test_external_data_file_negative(testdir):
1910
1903
1911
1904
1912
1905
@xdist_params
1913
- def test_append_coverage (testdir , opts , prop ):
1906
+ def test_append_coverage (pytester , testdir , opts , prop ):
1914
1907
script = testdir .makepyfile (test_1 = prop .code )
1915
1908
testdir .tmpdir .join ('.coveragerc' ).write (prop .fullconf )
1916
1909
result = testdir .runpytest ('-v' ,
@@ -1933,7 +1926,7 @@ def test_append_coverage(testdir, opts, prop):
1933
1926
1934
1927
1935
1928
@xdist_params
1936
- def test_do_not_append_coverage (testdir , opts , prop ):
1929
+ def test_do_not_append_coverage (pytester , testdir , opts , prop ):
1937
1930
script = testdir .makepyfile (test_1 = prop .code )
1938
1931
testdir .tmpdir .join ('.coveragerc' ).write (prop .fullconf )
1939
1932
result = testdir .runpytest ('-v' ,
@@ -2115,7 +2108,7 @@ def find_labels(text, pattern):
2115
2108
2116
2109
@pytest .mark .skipif ("coverage.version_info < (5, 0)" )
2117
2110
@xdist_params
2118
- def test_contexts (testdir , opts ):
2111
+ def test_contexts (pytester , testdir , opts ):
2119
2112
with open (os .path .join (os .path .dirname (__file__ ), "contextful.py" )) as f :
2120
2113
contextful_tests = f .read ()
2121
2114
script = testdir .makepyfile (contextful_tests )
0 commit comments