OLD | NEW |
(Empty) | |
| 1 # coding: utf-8 |
| 2 # Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 |
| 3 # For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt |
| 4 |
| 5 """Test the config file handling for coverage.py""" |
| 6 |
| 7 import sys |
| 8 import os |
| 9 |
| 10 import coverage |
| 11 from coverage.misc import CoverageException |
| 12 |
| 13 from tests.coveragetest import CoverageTest |
| 14 |
| 15 |
| 16 class ConfigTest(CoverageTest): |
| 17 """Tests of the different sources of configuration settings.""" |
| 18 |
| 19 def test_default_config(self): |
| 20 # Just constructing a coverage() object gets the right defaults. |
| 21 cov = coverage.Coverage() |
| 22 self.assertFalse(cov.config.timid) |
| 23 self.assertFalse(cov.config.branch) |
| 24 self.assertEqual(cov.config.data_file, ".coverage") |
| 25 |
| 26 def test_arguments(self): |
| 27 # Arguments to the constructor are applied to the configuration. |
| 28 cov = coverage.Coverage(timid=True, data_file="fooey.dat") |
| 29 self.assertTrue(cov.config.timid) |
| 30 self.assertFalse(cov.config.branch) |
| 31 self.assertEqual(cov.config.data_file, "fooey.dat") |
| 32 |
| 33 def test_config_file(self): |
| 34 # A .coveragerc file will be read into the configuration. |
| 35 self.make_file(".coveragerc", """\ |
| 36 # This is just a bogus .rc file for testing. |
| 37 [run] |
| 38 timid = True |
| 39 data_file = .hello_kitty.data |
| 40 """) |
| 41 cov = coverage.Coverage() |
| 42 self.assertTrue(cov.config.timid) |
| 43 self.assertFalse(cov.config.branch) |
| 44 self.assertEqual(cov.config.data_file, ".hello_kitty.data") |
| 45 |
| 46 def test_named_config_file(self): |
| 47 # You can name the config file what you like. |
| 48 self.make_file("my_cov.ini", """\ |
| 49 [run] |
| 50 timid = True |
| 51 ; I wouldn't really use this as a data file... |
| 52 data_file = delete.me |
| 53 """) |
| 54 cov = coverage.Coverage(config_file="my_cov.ini") |
| 55 self.assertTrue(cov.config.timid) |
| 56 self.assertFalse(cov.config.branch) |
| 57 self.assertEqual(cov.config.data_file, "delete.me") |
| 58 |
| 59 def test_ignored_config_file(self): |
| 60 # You can disable reading the .coveragerc file. |
| 61 self.make_file(".coveragerc", """\ |
| 62 [run] |
| 63 timid = True |
| 64 data_file = delete.me |
| 65 """) |
| 66 cov = coverage.Coverage(config_file=False) |
| 67 self.assertFalse(cov.config.timid) |
| 68 self.assertFalse(cov.config.branch) |
| 69 self.assertEqual(cov.config.data_file, ".coverage") |
| 70 |
| 71 def test_config_file_then_args(self): |
| 72 # The arguments override the .coveragerc file. |
| 73 self.make_file(".coveragerc", """\ |
| 74 [run] |
| 75 timid = True |
| 76 data_file = weirdo.file |
| 77 """) |
| 78 cov = coverage.Coverage(timid=False, data_file=".mycov") |
| 79 self.assertFalse(cov.config.timid) |
| 80 self.assertFalse(cov.config.branch) |
| 81 self.assertEqual(cov.config.data_file, ".mycov") |
| 82 |
| 83 def test_data_file_from_environment(self): |
| 84 # There's an environment variable for the data_file. |
| 85 self.make_file(".coveragerc", """\ |
| 86 [run] |
| 87 timid = True |
| 88 data_file = weirdo.file |
| 89 """) |
| 90 self.set_environ("COVERAGE_FILE", "fromenv.dat") |
| 91 cov = coverage.Coverage() |
| 92 self.assertEqual(cov.config.data_file, "fromenv.dat") |
| 93 # But the constructor arguments override the environment variable. |
| 94 cov = coverage.Coverage(data_file="fromarg.dat") |
| 95 self.assertEqual(cov.config.data_file, "fromarg.dat") |
| 96 |
| 97 def test_parse_errors(self): |
| 98 # Im-parsable values raise CoverageException, with details. |
| 99 bad_configs_and_msgs = [ |
| 100 ("[run]\ntimid = maybe?\n", r"maybe[?]"), |
| 101 ("timid = 1\n", r"timid = 1"), |
| 102 ("[run\n", r"\[run"), |
| 103 ("[report]\nexclude_lines = foo(\n", |
| 104 r"Invalid \[report\].exclude_lines value 'foo\(': " |
| 105 r"(unbalanced parenthesis|missing \))"), |
| 106 ("[report]\npartial_branches = foo[\n", |
| 107 r"Invalid \[report\].partial_branches value 'foo\[': " |
| 108 r"(unexpected end of regular expression|unterminated character s
et)"), |
| 109 ("[report]\npartial_branches_always = foo***\n", |
| 110 r"Invalid \[report\].partial_branches_always value " |
| 111 r"'foo\*\*\*': " |
| 112 r"multiple repeat"), |
| 113 ] |
| 114 |
| 115 for bad_config, msg in bad_configs_and_msgs: |
| 116 print("Trying %r" % bad_config) |
| 117 self.make_file(".coveragerc", bad_config) |
| 118 with self.assertRaisesRegex(CoverageException, msg): |
| 119 coverage.Coverage() |
| 120 |
| 121 def test_environment_vars_in_config(self): |
| 122 # Config files can have $envvars in them. |
| 123 self.make_file(".coveragerc", """\ |
| 124 [run] |
| 125 data_file = $DATA_FILE.fooey |
| 126 branch = $OKAY |
| 127 [report] |
| 128 exclude_lines = |
| 129 the_$$one |
| 130 another${THING} |
| 131 x${THING}y |
| 132 x${NOTHING}y |
| 133 huh$${X}what |
| 134 """) |
| 135 self.set_environ("DATA_FILE", "hello-world") |
| 136 self.set_environ("THING", "ZZZ") |
| 137 self.set_environ("OKAY", "yes") |
| 138 cov = coverage.Coverage() |
| 139 self.assertEqual(cov.config.data_file, "hello-world.fooey") |
| 140 self.assertEqual(cov.config.branch, True) |
| 141 self.assertEqual( |
| 142 cov.config.exclude_list, |
| 143 ["the_$one", "anotherZZZ", "xZZZy", "xy", "huh${X}what"] |
| 144 ) |
| 145 |
| 146 def test_tweaks_after_constructor(self): |
| 147 # Arguments to the constructor are applied to the configuration. |
| 148 cov = coverage.Coverage(timid=True, data_file="fooey.dat") |
| 149 cov.set_option("run:timid", False) |
| 150 |
| 151 self.assertFalse(cov.config.timid) |
| 152 self.assertFalse(cov.config.branch) |
| 153 self.assertEqual(cov.config.data_file, "fooey.dat") |
| 154 |
| 155 self.assertFalse(cov.get_option("run:timid")) |
| 156 self.assertFalse(cov.get_option("run:branch")) |
| 157 self.assertEqual(cov.get_option("run:data_file"), "fooey.dat") |
| 158 |
| 159 def test_tweak_error_checking(self): |
| 160 # Trying to set an unknown config value raises an error. |
| 161 cov = coverage.Coverage() |
| 162 with self.assertRaises(CoverageException): |
| 163 cov.set_option("run:xyzzy", 12) |
| 164 with self.assertRaises(CoverageException): |
| 165 cov.set_option("xyzzy:foo", 12) |
| 166 with self.assertRaises(CoverageException): |
| 167 _ = cov.get_option("run:xyzzy") |
| 168 with self.assertRaises(CoverageException): |
| 169 _ = cov.get_option("xyzzy:foo") |
| 170 |
| 171 def test_tweak_plugin_options(self): |
| 172 # Plugin options have a more flexible syntax. |
| 173 cov = coverage.Coverage() |
| 174 cov.set_option("run:plugins", ["fooey.plugin", "xyzzy.coverage.plugin"]) |
| 175 cov.set_option("fooey.plugin:xyzzy", 17) |
| 176 cov.set_option("xyzzy.coverage.plugin:plugh", ["a", "b"]) |
| 177 with self.assertRaises(CoverageException): |
| 178 cov.set_option("no_such.plugin:foo", 23) |
| 179 |
| 180 self.assertEqual(cov.get_option("fooey.plugin:xyzzy"), 17) |
| 181 self.assertEqual(cov.get_option("xyzzy.coverage.plugin:plugh"), ["a", "b
"]) |
| 182 with self.assertRaises(CoverageException): |
| 183 _ = cov.get_option("no_such.plugin:foo") |
| 184 |
| 185 def test_unknown_option(self): |
| 186 self.make_file(".coveragerc", """\ |
| 187 [run] |
| 188 xyzzy = 17 |
| 189 """) |
| 190 msg = r"Unrecognized option '\[run\] xyzzy=' in config file .coveragerc" |
| 191 with self.assertRaisesRegex(CoverageException, msg): |
| 192 _ = coverage.Coverage() |
| 193 |
| 194 def test_misplaced_option(self): |
| 195 self.make_file(".coveragerc", """\ |
| 196 [report] |
| 197 branch = True |
| 198 """) |
| 199 msg = r"Unrecognized option '\[report\] branch=' in config file .coverag
erc" |
| 200 with self.assertRaisesRegex(CoverageException, msg): |
| 201 _ = coverage.Coverage() |
| 202 |
| 203 def test_unknown_option_in_other_ini_file(self): |
| 204 self.make_file("setup.cfg", """\ |
| 205 [coverage:run] |
| 206 huh = what? |
| 207 """) |
| 208 msg = r"Unrecognized option '\[coverage:run\] huh=' in config file setup
.cfg" |
| 209 with self.assertRaisesRegex(CoverageException, msg): |
| 210 _ = coverage.Coverage() |
| 211 |
| 212 |
| 213 class ConfigFileTest(CoverageTest): |
| 214 """Tests of the config file settings in particular.""" |
| 215 |
| 216 def setUp(self): |
| 217 super(ConfigFileTest, self).setUp() |
| 218 # Parent class saves and restores sys.path, we can just modify it. |
| 219 # Add modules to the path so we can import plugins. |
| 220 sys.path.append(self.nice_file(os.path.dirname(__file__), 'modules')) |
| 221 |
| 222 # This sample file tries to use lots of variation of syntax... |
| 223 # The {section} placeholder lets us nest these settings in another file. |
| 224 LOTSA_SETTINGS = """\ |
| 225 # This is a settings file for coverage.py |
| 226 [{section}run] |
| 227 timid = yes |
| 228 data_file = something_or_other.dat |
| 229 branch = 1 |
| 230 cover_pylib = TRUE |
| 231 parallel = on |
| 232 include = a/ , b/ |
| 233 concurrency = thread |
| 234 plugins = |
| 235 plugins.a_plugin |
| 236 plugins.another |
| 237 |
| 238 [{section}report] |
| 239 ; these settings affect reporting. |
| 240 exclude_lines = |
| 241 if 0: |
| 242 |
| 243 pragma:?\\s+no cover |
| 244 another_tab |
| 245 |
| 246 ignore_errors = TRUE |
| 247 omit = |
| 248 one, another, some_more, |
| 249 yet_more |
| 250 precision = 3 |
| 251 |
| 252 partial_branches = |
| 253 pragma:?\\s+no branch |
| 254 partial_branches_always = |
| 255 if 0: |
| 256 while True: |
| 257 |
| 258 show_missing= TruE |
| 259 skip_covered = TruE |
| 260 |
| 261 [{section}html] |
| 262 |
| 263 directory = c:\\tricky\\dir.somewhere |
| 264 extra_css=something/extra.css |
| 265 title = Title & nums # nums! |
| 266 [{section}xml] |
| 267 output=mycov.xml |
| 268 package_depth = 17 |
| 269 |
| 270 [{section}paths] |
| 271 source = |
| 272 . |
| 273 /home/ned/src/ |
| 274 |
| 275 other = other, /home/ned/other, c:\\Ned\\etc |
| 276 |
| 277 [{section}plugins.a_plugin] |
| 278 hello = world |
| 279 ; comments still work. |
| 280 names = Jane/John/Jenny |
| 281 """ |
| 282 |
| 283 # Just some sample setup.cfg text from the docs. |
| 284 SETUP_CFG = """\ |
| 285 [bdist_rpm] |
| 286 release = 1 |
| 287 packager = Jane Packager <janep@pysoft.com> |
| 288 doc_files = CHANGES.txt |
| 289 README.txt |
| 290 USAGE.txt |
| 291 doc/ |
| 292 examples/ |
| 293 """ |
| 294 |
| 295 def assert_config_settings_are_correct(self, cov): |
| 296 """Check that `cov` has all the settings from LOTSA_SETTINGS.""" |
| 297 self.assertTrue(cov.config.timid) |
| 298 self.assertEqual(cov.config.data_file, "something_or_other.dat") |
| 299 self.assertTrue(cov.config.branch) |
| 300 self.assertTrue(cov.config.cover_pylib) |
| 301 self.assertTrue(cov.config.parallel) |
| 302 self.assertEqual(cov.config.concurrency, "thread") |
| 303 |
| 304 self.assertEqual(cov.get_exclude_list(), ["if 0:", r"pragma:?\s+no cover
", "another_tab"]) |
| 305 self.assertTrue(cov.config.ignore_errors) |
| 306 self.assertEqual(cov.config.include, ["a/", "b/"]) |
| 307 self.assertEqual(cov.config.omit, ["one", "another", "some_more", "yet_m
ore"]) |
| 308 self.assertEqual(cov.config.precision, 3) |
| 309 |
| 310 self.assertEqual(cov.config.partial_list, [r"pragma:?\s+no branch"]) |
| 311 self.assertEqual(cov.config.partial_always_list, ["if 0:", "while True:"
]) |
| 312 self.assertEqual(cov.config.plugins, ["plugins.a_plugin", "plugins.anoth
er"]) |
| 313 self.assertTrue(cov.config.show_missing) |
| 314 self.assertTrue(cov.config.skip_covered) |
| 315 self.assertEqual(cov.config.html_dir, r"c:\tricky\dir.somewhere") |
| 316 self.assertEqual(cov.config.extra_css, "something/extra.css") |
| 317 self.assertEqual(cov.config.html_title, "Title & nums # nums!") |
| 318 |
| 319 self.assertEqual(cov.config.xml_output, "mycov.xml") |
| 320 self.assertEqual(cov.config.xml_package_depth, 17) |
| 321 |
| 322 self.assertEqual(cov.config.paths, { |
| 323 'source': ['.', '/home/ned/src/'], |
| 324 'other': ['other', '/home/ned/other', 'c:\\Ned\\etc'] |
| 325 }) |
| 326 |
| 327 self.assertEqual(cov.config.get_plugin_options("plugins.a_plugin"), { |
| 328 'hello': 'world', |
| 329 'names': 'Jane/John/Jenny', |
| 330 }) |
| 331 self.assertEqual(cov.config.get_plugin_options("plugins.another"), {}) |
| 332 |
| 333 def test_config_file_settings(self): |
| 334 self.make_file(".coveragerc", self.LOTSA_SETTINGS.format(section="")) |
| 335 cov = coverage.Coverage() |
| 336 self.assert_config_settings_are_correct(cov) |
| 337 |
| 338 def test_config_file_settings_in_setupcfg(self): |
| 339 # Configuration will be read from setup.cfg from sections prefixed with |
| 340 # "coverage:" |
| 341 nested = self.LOTSA_SETTINGS.format(section="coverage:") |
| 342 self.make_file("setup.cfg", nested + "\n" + self.SETUP_CFG) |
| 343 cov = coverage.Coverage() |
| 344 self.assert_config_settings_are_correct(cov) |
| 345 |
| 346 def test_config_file_settings_in_setupcfg_if_coveragerc_specified(self): |
| 347 # Configuration will be read from setup.cfg from sections prefixed with |
| 348 # "coverage:", even if the API said to read from a (non-existent) |
| 349 # .coveragerc file. |
| 350 nested = self.LOTSA_SETTINGS.format(section="coverage:") |
| 351 self.make_file("setup.cfg", nested + "\n" + self.SETUP_CFG) |
| 352 cov = coverage.Coverage(config_file=".coveragerc") |
| 353 self.assert_config_settings_are_correct(cov) |
| 354 |
| 355 def test_setupcfg_only_if_not_coveragerc(self): |
| 356 self.make_file(".coveragerc", """\ |
| 357 [run] |
| 358 include = foo |
| 359 """) |
| 360 self.make_file("setup.cfg", """\ |
| 361 [coverage:run] |
| 362 omit = bar |
| 363 branch = true |
| 364 """) |
| 365 cov = coverage.Coverage() |
| 366 self.assertEqual(cov.config.include, ["foo"]) |
| 367 self.assertEqual(cov.config.omit, None) |
| 368 self.assertEqual(cov.config.branch, False) |
| 369 |
| 370 def test_setupcfg_only_if_prefixed(self): |
| 371 self.make_file("setup.cfg", """\ |
| 372 [run] |
| 373 omit = bar |
| 374 branch = true |
| 375 """) |
| 376 cov = coverage.Coverage() |
| 377 self.assertEqual(cov.config.omit, None) |
| 378 self.assertEqual(cov.config.branch, False) |
| 379 |
| 380 def test_non_ascii(self): |
| 381 self.make_file(".coveragerc", """\ |
| 382 [html] |
| 383 title = tabblo & «ταБЬℓσ» # numbers |
| 384 """) |
| 385 cov = coverage.Coverage() |
| 386 |
| 387 self.assertEqual(cov.config.html_title, "tabblo & «ταБЬℓσ» # numbers") |
| 388 |
| 389 def test_unreadable_config(self): |
| 390 # If a config file is explicitly specified, then it is an error for it |
| 391 # to not be readable. |
| 392 bad_files = [ |
| 393 "nosuchfile.txt", |
| 394 ".", |
| 395 ] |
| 396 for bad_file in bad_files: |
| 397 msg = "Couldn't read %r as a config file" % bad_file |
| 398 with self.assertRaisesRegex(CoverageException, msg): |
| 399 coverage.Coverage(config_file=bad_file) |
| 400 |
| 401 def test_nocoveragerc_file_when_specified(self): |
| 402 cov = coverage.Coverage(config_file=".coveragerc") |
| 403 self.assertFalse(cov.config.timid) |
| 404 self.assertFalse(cov.config.branch) |
| 405 self.assertEqual(cov.config.data_file, ".coverage") |
OLD | NEW |