@@ -33,7 +33,8 @@ def test_default_config(self) -> None:
33
33
34
34
def test_arguments (self ) -> None :
35
35
# Arguments to the constructor are applied to the configuration.
36
- cov = coverage .Coverage (timid = True , data_file = "fooey.dat" , concurrency = "multiprocessing" )
36
+ cov = coverage .Coverage (
37
+ timid = True , data_file = "fooey.dat" , concurrency = "multiprocessing" )
37
38
assert cov .config .timid
38
39
assert not cov .config .branch
39
40
assert cov .config .data_file == "fooey.dat"
@@ -66,9 +67,10 @@ def test_named_config_file(self, file_class: FilePathType) -> None:
66
67
assert not cov .config .branch
67
68
assert cov .config .data_file == "delete.me"
68
69
69
- def test_toml_config_file (self ) -> None :
70
- # A pyproject.toml file will be read into the configuration.
71
- self .make_file ("pyproject.toml" , """\
70
+ @pytest .mark .parametrize ("filename" , ["pyproject.toml" , ".coveragerc.toml" ])
71
+ def test_toml_config_file (self , filename ) -> None :
72
+ # A pyproject.toml and coveragerc.toml will be read into the configuration.
73
+ self .make_file (filename , """\
72
74
# This is just a bogus toml file for testing.
73
75
[tool.somethingelse]
74
76
authors = ["Joe D'Ávila <[email protected] >"]
@@ -94,11 +96,13 @@ def test_toml_config_file(self) -> None:
94
96
assert cov .config .precision == 3
95
97
assert cov .config .html_title == "tabblo & «ταБЬℓσ»"
96
98
assert cov .config .fail_under == 90.5
97
- assert cov .config .get_plugin_options ("plugins.a_plugin" ) == {"hello" : "world" }
99
+ assert cov .config .get_plugin_options ("plugins.a_plugin" ) == {
100
+ "hello" : "world" }
98
101
99
- def test_toml_ints_can_be_floats (self ) -> None :
102
+ @pytest .mark .parametrize ("filename" , ["pyproject.toml" , ".coveragerc.toml" ])
103
+ def test_toml_ints_can_be_floats (self , filename ) -> None :
100
104
# Test that our class doesn't reject integers when loading floats
101
- self .make_file ("pyproject.toml" , """\
105
+ self .make_file (filename , """\
102
106
# This is just a bogus toml file for testing.
103
107
[tool.coverage.report]
104
108
fail_under = 90
@@ -214,6 +218,7 @@ def test_parse_errors(self, bad_config: str, msg: str) -> None:
214
218
with pytest .raises (ConfigError , match = msg ):
215
219
coverage .Coverage ()
216
220
221
+ @pytest .mark .parametrize ("filename" , ["pyproject.toml" , ".coveragerc.toml" ])
217
222
@pytest .mark .parametrize ("bad_config, msg" , [
218
223
("[tool.coverage.run]\n timid = \" maybe?\" \n " , r"maybe[?]" ),
219
224
("[tool.coverage.run\n " , None ),
@@ -237,9 +242,9 @@ def test_parse_errors(self, bad_config: str, msg: str) -> None:
237
242
("[tool.coverage.report]\n precision=1.23" , "not an integer" ),
238
243
('[tool.coverage.report]\n fail_under="s"' , "couldn't convert to a float" ),
239
244
])
240
- def test_toml_parse_errors (self , bad_config : str , msg : str ) -> None :
245
+ def test_toml_parse_errors (self , filename , bad_config : str , msg : str ) -> None :
241
246
# Im-parsable values raise ConfigError, with details.
242
- self .make_file ("pyproject.toml" , bad_config )
247
+ self .make_file (filename , bad_config )
243
248
with pytest .raises (ConfigError , match = msg ):
244
249
coverage .Coverage ()
245
250
@@ -263,11 +268,13 @@ def test_environment_vars_in_config(self) -> None:
263
268
cov = coverage .Coverage ()
264
269
assert cov .config .data_file == "hello-world.fooey"
265
270
assert cov .config .branch is True
266
- assert cov .config .exclude_list == ["the_$one" , "anotherZZZ" , "xZZZy" , "xy" , "huh${X}what" ]
271
+ assert cov .config .exclude_list == [
272
+ "the_$one" , "anotherZZZ" , "xZZZy" , "xy" , "huh${X}what" ]
267
273
268
- def test_environment_vars_in_toml_config (self ) -> None :
274
+ @pytest .mark .parametrize ("filename" , ["pyproject.toml" , ".coveragerc.toml" ])
275
+ def test_environment_vars_in_toml_config (self , filename ) -> None :
269
276
# Config files can have $envvars in them.
270
- self .make_file ("pyproject.toml" , """\
277
+ self .make_file (filename , """\
271
278
[tool.coverage.run]
272
279
data_file = "$DATA_FILE.fooey"
273
280
branch = "$BRANCH"
@@ -296,7 +303,8 @@ def test_environment_vars_in_toml_config(self) -> None:
296
303
assert cov .config .branch is True
297
304
assert cov .config .precision == 3
298
305
assert cov .config .data_file == "hello-world.fooey"
299
- assert cov .config .exclude_list == ["the_$one" , "anotherZZZ" , "xZZZy" , "xy" , "huh${X}what" ]
306
+ assert cov .config .exclude_list == [
307
+ "the_$one" , "anotherZZZ" , "xZZZy" , "xy" , "huh${X}what" ]
300
308
301
309
def test_tilde_in_config (self ) -> None :
302
310
# Config entries that are file paths can be tilde-expanded.
@@ -330,9 +338,10 @@ def test_tilde_in_config(self) -> None:
330
338
331
339
self .assert_tilde_results ()
332
340
333
- def test_tilde_in_toml_config (self ) -> None :
341
+ @pytest .mark .parametrize ("filename" , ["pyproject.toml" , ".coveragerc.toml" ])
342
+ def test_tilde_in_toml_config (self , filename ) -> None :
334
343
# Config entries that are file paths can be tilde-expanded.
335
- self .make_file ("pyproject.toml" , """\
344
+ self .make_file (filename , """\
336
345
[tool.coverage.run]
337
346
data_file = "~/data.file"
338
347
@@ -384,7 +393,8 @@ def expanduser(s: str) -> str:
384
393
assert cov .config .lcov_output == "/Users/me/lcov/~foo.lcov"
385
394
assert cov .config .xml_output == "/Users/me/somewhere/xml.out"
386
395
assert cov .config .exclude_list == ["~/data.file" , "~joe/html_dir" ]
387
- assert cov .config .paths == {'mapping' : ['/Users/me/src' , '/Users/joe/source' ]}
396
+ assert cov .config .paths == {'mapping' : [
397
+ '/Users/me/src' , '/Users/joe/source' ]}
388
398
389
399
def test_tweaks_after_constructor (self ) -> None :
390
400
# set_option can be used after construction to affect the config.
@@ -440,7 +450,8 @@ def test_tweak_error_checking(self) -> None:
440
450
def test_tweak_plugin_options (self ) -> None :
441
451
# Plugin options have a more flexible syntax.
442
452
cov = coverage .Coverage ()
443
- cov .set_option ("run:plugins" , ["fooey.plugin" , "xyzzy.coverage.plugin" ])
453
+ cov .set_option ("run:plugins" , [
454
+ "fooey.plugin" , "xyzzy.coverage.plugin" ])
444
455
cov .set_option ("fooey.plugin:xyzzy" , 17 )
445
456
cov .set_option ("xyzzy.coverage.plugin:plugh" , ["a" , "b" ])
446
457
with pytest .raises (ConfigError , match = "No such option: 'no_such.plugin:foo'" ):
@@ -460,12 +471,13 @@ def test_unknown_option(self) -> None:
460
471
with pytest .warns (CoverageWarning , match = msg ):
461
472
_ = coverage .Coverage ()
462
473
463
- def test_unknown_option_toml (self ) -> None :
464
- self .make_file ("pyproject.toml" , """\
474
+ @pytest .mark .parametrize ("filename" , ["pyproject.toml" , ".coveragerc.toml" ])
475
+ def test_unknown_option_toml (self , filename ) -> None :
476
+ self .make_file (filename , """\
465
477
[tool.coverage.run]
466
478
xyzzy = 17
467
479
""" )
468
- msg = r "Unrecognized option '\[tool.coverage.run\] xyzzy=' in config file pyproject.toml "
480
+ msg = f "Unrecognized option '\\ [tool.coverage.run\\ ] xyzzy=' in config file { filename } "
469
481
with pytest .warns (CoverageWarning , match = msg ):
470
482
_ = coverage .Coverage ()
471
483
@@ -512,14 +524,16 @@ def test_exceptions_from_missing_things(self) -> None:
512
524
with pytest .raises (ConfigError , match = "No option 'foo' in section: 'xyzzy'" ):
513
525
config .get ("xyzzy" , "foo" )
514
526
515
- def test_exclude_also (self ) -> None :
516
- self .make_file ("pyproject.toml" , """\
527
+ @pytest .mark .parametrize ("filename" , ["pyproject.toml" , ".coveragerc.toml" ])
528
+ def test_exclude_also (self , filename ) -> None :
529
+ self .make_file (filename , """\
517
530
[tool.coverage.report]
518
531
exclude_also = ["foobar", "raise .*Error"]
519
532
""" )
520
533
cov = coverage .Coverage ()
521
534
522
- expected = coverage .config .DEFAULT_EXCLUDE + ["foobar" , "raise .*Error" ]
535
+ expected = coverage .config .DEFAULT_EXCLUDE + \
536
+ ["foobar" , "raise .*Error" ]
523
537
assert cov .config .exclude_list == expected
524
538
525
539
def test_partial_also (self ) -> None :
@@ -529,7 +543,8 @@ def test_partial_also(self) -> None:
529
543
""" )
530
544
cov = coverage .Coverage ()
531
545
532
- expected = coverage .config .DEFAULT_PARTIAL + ["foobar" , "raise .*Error" ]
546
+ expected = coverage .config .DEFAULT_PARTIAL + \
547
+ ["foobar" , "raise .*Error" ]
533
548
assert cov .config .partial_list == expected
534
549
535
550
def test_core_option (self ) -> None :
@@ -672,10 +687,12 @@ def assert_config_settings_are_correct(self, cov: Coverage) -> None:
672
687
assert cov .config .source_dirs == ["cooldir" ]
673
688
assert cov .config .disable_warnings == ["abcd" , "efgh" ]
674
689
675
- assert cov .get_exclude_list () == ["if 0:" , r"pragma:?\s+no cover" , "another_tab" ]
690
+ assert cov .get_exclude_list () == [
691
+ "if 0:" , r"pragma:?\s+no cover" , "another_tab" ]
676
692
assert cov .config .ignore_errors
677
693
assert cov .config .run_omit == ["twenty" ]
678
- assert cov .config .report_omit == ["one" , "another" , "some_more" , "yet_more" ]
694
+ assert cov .config .report_omit == [
695
+ "one" , "another" , "some_more" , "yet_more" ]
679
696
assert cov .config .report_include == ["thirty" ]
680
697
assert cov .config .precision == 3
681
698
@@ -719,7 +736,8 @@ def check_config_file_settings_in_other_file(self, fname: str, contents: str) ->
719
736
self .assert_config_settings_are_correct (cov )
720
737
721
738
def test_config_file_settings_in_setupcfg (self ) -> None :
722
- self .check_config_file_settings_in_other_file ("setup.cfg" , self .SETUP_CFG )
739
+ self .check_config_file_settings_in_other_file (
740
+ "setup.cfg" , self .SETUP_CFG )
723
741
724
742
def test_config_file_settings_in_toxini (self ) -> None :
725
743
self .check_config_file_settings_in_other_file ("tox.ini" , self .TOX_INI )
@@ -732,10 +750,12 @@ def check_other_config_if_coveragerc_specified(self, fname: str, contents: str)
732
750
self .assert_config_settings_are_correct (cov )
733
751
734
752
def test_config_file_settings_in_setupcfg_if_coveragerc_specified (self ) -> None :
735
- self .check_other_config_if_coveragerc_specified ("setup.cfg" , self .SETUP_CFG )
753
+ self .check_other_config_if_coveragerc_specified (
754
+ "setup.cfg" , self .SETUP_CFG )
736
755
737
756
def test_config_file_settings_in_tox_if_coveragerc_specified (self ) -> None :
738
- self .check_other_config_if_coveragerc_specified ("tox.ini" , self .TOX_INI )
757
+ self .check_other_config_if_coveragerc_specified (
758
+ "tox.ini" , self .TOX_INI )
739
759
740
760
def check_other_not_read_if_coveragerc (self , fname : str ) -> None :
741
761
"""Check config `fname` is not read if .coveragerc exists."""
@@ -839,35 +859,38 @@ def test_no_toml_installed_explicit_toml(self) -> None:
839
859
coverage .Coverage (config_file = "cov.toml" )
840
860
841
861
@pytest .mark .skipif (env .PYVERSION >= (3 , 11 ), reason = "Python 3.11 has toml in stdlib" )
842
- def test_no_toml_installed_pyproject_toml (self ) -> None :
843
- # Can't have coverage config in pyproject.toml without toml installed.
844
- self .make_file ("pyproject.toml" , """\
862
+ @pytest .mark .parametrize ("filename" , ["pyproject.toml" , ".coveragerc.toml" ])
863
+ def test_no_toml_installed_pyproject_toml (self , filename ) -> None :
864
+ # Can't have coverage config in pyproject.toml and .coveragerc.toml without toml installed.
865
+ self .make_file (filename , """\
845
866
# A toml file!
846
867
[tool.coverage.run]
847
868
xyzzy = 17
848
869
""" )
849
870
with mock .patch .object (coverage .tomlconfig , "has_tomllib" , False ):
850
- msg = "Can't read 'pyproject.toml ' without TOML support"
871
+ msg = "Can't read '{filename} ' without TOML support"
851
872
with pytest .raises (ConfigError , match = msg ):
852
873
coverage .Coverage ()
853
874
854
875
@pytest .mark .skipif (env .PYVERSION >= (3 , 11 ), reason = "Python 3.11 has toml in stdlib" )
855
- def test_no_toml_installed_pyproject_toml_shorter_syntax (self ) -> None :
876
+ @pytest .mark .parametrize ("filename" , ["pyproject.toml" , ".coveragerc.toml" ])
877
+ def test_no_toml_installed_pyproject_toml_shorter_syntax (self , filename ) -> None :
856
878
# Can't have coverage config in pyproject.toml without toml installed.
857
- self .make_file ("pyproject.toml" , """\
879
+ self .make_file (filename , """\
858
880
# A toml file!
859
881
[tool.coverage]
860
882
run.parallel = true
861
883
""" )
862
884
with mock .patch .object (coverage .tomlconfig , "has_tomllib" , False ):
863
- msg = "Can't read 'pyproject.toml ' without TOML support"
885
+ msg = "Can't read '{filename} ' without TOML support"
864
886
with pytest .raises (ConfigError , match = msg ):
865
887
coverage .Coverage ()
866
888
867
889
@pytest .mark .skipif (env .PYVERSION >= (3 , 11 ), reason = "Python 3.11 has toml in stdlib" )
868
- def test_no_toml_installed_pyproject_no_coverage (self ) -> None :
890
+ @pytest .mark .parametrize ("filename" , ["pyproject.toml" , ".coveragerc.toml" ])
891
+ def test_no_toml_installed_pyproject_no_coverage (self , filename ) -> None :
869
892
# It's ok to have non-coverage pyproject.toml without toml installed.
870
- self .make_file ("pyproject.toml" , """\
893
+ self .make_file (filename , """\
871
894
# A toml file!
872
895
[tool.something]
873
896
xyzzy = 17
@@ -879,16 +902,38 @@ def test_no_toml_installed_pyproject_no_coverage(self) -> None:
879
902
assert not cov .config .branch
880
903
assert cov .config .data_file == ".coverage"
881
904
882
- def test_exceptions_from_missing_toml_things (self ) -> None :
883
- self .make_file ("pyproject.toml" , """\
905
+ @pytest .mark .parametrize ("filename" , ["pyproject.toml" , ".coveragerc.toml" ])
906
+ def test_exceptions_from_missing_toml_things (self , filename ) -> None :
907
+ self .make_file (filename , """\
884
908
[tool.coverage.run]
885
909
branch = true
886
910
""" )
887
911
config = TomlConfigParser (False )
888
- config .read ("pyproject.toml" )
912
+ config .read (filename )
889
913
with pytest .raises (ConfigError , match = "No section: 'xyzzy'" ):
890
914
config .options ("xyzzy" )
891
915
with pytest .raises (ConfigError , match = "No section: 'xyzzy'" ):
892
916
config .get ("xyzzy" , "foo" )
893
917
with pytest .raises (ConfigError , match = "No option 'foo' in section: 'tool.coverage.run'" ):
894
918
config .get ("run" , "foo" )
919
+
920
+ def test_coveragerc_toml_priority (self ) -> None :
921
+ """Test that .coveragerc.toml has priority over pyproject.toml."""
922
+ self .make_file (".coveragerc.toml" , """\
923
+ [tool.coverage.run]
924
+ timid = true
925
+ data_file = ".toml-data.dat"
926
+ branch = true
927
+ """ )
928
+
929
+ self .make_file ("pyproject.toml" , """\
930
+ [tool.coverage.run]
931
+ timid = false
932
+ data_file = "pyproject-data.dat"
933
+ branch = false
934
+ """ )
935
+ cov = coverage .Coverage ()
936
+
937
+ assert cov .config .timid is True
938
+ assert cov .config .data_file == ".toml-data.dat"
939
+ assert cov .config .branch is True
0 commit comments