OLD | NEW |
(Empty) | |
| 1 # Licensed under the Apache License: http://www.apache.org/licenses/LICENSE-2.0 |
| 2 # For details: https://bitbucket.org/ned/coveragepy/src/default/NOTICE.txt |
| 3 |
| 4 """Test cmdline.py for coverage.py.""" |
| 5 |
| 6 import pprint |
| 7 import re |
| 8 import shlex |
| 9 import sys |
| 10 import textwrap |
| 11 |
| 12 import mock |
| 13 |
| 14 import coverage |
| 15 import coverage.cmdline |
| 16 from coverage.config import CoverageConfig |
| 17 from coverage.data import CoverageData, CoverageDataFiles |
| 18 from coverage.misc import ExceptionDuringRun |
| 19 |
| 20 from tests.coveragetest import CoverageTest, OK, ERR |
| 21 |
| 22 |
| 23 class BaseCmdLineTest(CoverageTest): |
| 24 """Tests of execution paths through the command line interpreter.""" |
| 25 |
| 26 run_in_temp_dir = False |
| 27 |
| 28 # Make a dict mapping function names to the default values that cmdline.py |
| 29 # uses when calling the function. |
| 30 defaults = mock.Mock() |
| 31 defaults.coverage( |
| 32 cover_pylib=None, data_suffix=None, timid=None, branch=None, |
| 33 config_file=True, source=None, include=None, omit=None, debug=None, |
| 34 concurrency=None, |
| 35 ) |
| 36 defaults.annotate( |
| 37 directory=None, ignore_errors=None, include=None, omit=None, morfs=[], |
| 38 ) |
| 39 defaults.html_report( |
| 40 directory=None, ignore_errors=None, include=None, omit=None, morfs=[], |
| 41 title=None, |
| 42 ) |
| 43 defaults.report( |
| 44 ignore_errors=None, include=None, omit=None, morfs=[], |
| 45 show_missing=None, skip_covered=None |
| 46 ) |
| 47 defaults.xml_report( |
| 48 ignore_errors=None, include=None, omit=None, morfs=[], outfile=None, |
| 49 ) |
| 50 |
| 51 DEFAULT_KWARGS = dict((name, kw) for name, _, kw in defaults.mock_calls) |
| 52 |
| 53 def model_object(self): |
| 54 """Return a Mock suitable for use in CoverageScript.""" |
| 55 mk = mock.Mock() |
| 56 # We'll invoke .coverage as the constructor, and then keep using the |
| 57 # same object as the resulting coverage object. |
| 58 mk.coverage.return_value = mk |
| 59 |
| 60 # The mock needs to get options, but shouldn't need to set them. |
| 61 config = CoverageConfig() |
| 62 mk.get_option = config.get_option |
| 63 |
| 64 return mk |
| 65 |
| 66 def mock_command_line(self, args, path_exists=None): |
| 67 """Run `args` through the command line, with a Mock. |
| 68 |
| 69 Returns the Mock it used and the status code returned. |
| 70 |
| 71 """ |
| 72 m = self.model_object() |
| 73 m.path_exists.return_value = path_exists |
| 74 |
| 75 ret = coverage.cmdline.CoverageScript( |
| 76 _covpkg=m, _run_python_file=m.run_python_file, |
| 77 _run_python_module=m.run_python_module, _help_fn=m.help_fn, |
| 78 _path_exists=m.path_exists, |
| 79 ).command_line(shlex.split(args)) |
| 80 |
| 81 return m, ret |
| 82 |
| 83 def cmd_executes(self, args, code, ret=OK, path_exists=None): |
| 84 """Assert that the `args` end up executing the sequence in `code`.""" |
| 85 m1, r1 = self.mock_command_line(args, path_exists=path_exists) |
| 86 self.assertEqual(r1, ret, "Wrong status: got %r, wanted %r" % (r1, ret)) |
| 87 |
| 88 # Remove all indentation, and change ".foo()" to "m2.foo()". |
| 89 code = re.sub(r"(?m)^\s+", "", code) |
| 90 code = re.sub(r"(?m)^\.", "m2.", code) |
| 91 m2 = self.model_object() |
| 92 m2.path_exists.return_value = path_exists |
| 93 code_obj = compile(code, "<code>", "exec") |
| 94 eval(code_obj, globals(), { 'm2': m2 }) # pylint: disable=eval-used |
| 95 |
| 96 # Many of our functions take a lot of arguments, and cmdline.py |
| 97 # calls them with many. But most of them are just the defaults, which |
| 98 # we don't want to have to repeat in all tests. For each call, apply |
| 99 # the defaults. This lets the tests just mention the interesting ones. |
| 100 for name, args, kwargs in m2.method_calls: |
| 101 for k, v in self.DEFAULT_KWARGS.get(name, {}).items(): |
| 102 if k not in kwargs: |
| 103 kwargs[k] = v |
| 104 self.assert_same_method_calls(m1, m2) |
| 105 |
| 106 def cmd_executes_same(self, args1, args2): |
| 107 """Assert that the `args1` executes the same as `args2`.""" |
| 108 m1, r1 = self.mock_command_line(args1) |
| 109 m2, r2 = self.mock_command_line(args2) |
| 110 self.assertEqual(r1, r2) |
| 111 self.assert_same_method_calls(m1, m2) |
| 112 |
| 113 def assert_same_method_calls(self, m1, m2): |
| 114 """Assert that `m1.method_calls` and `m2.method_calls` are the same.""" |
| 115 # Use a real equality comparison, but if it fails, use a nicer assert |
| 116 # so we can tell what's going on. We have to use the real == first due |
| 117 # to CmdOptionParser.__eq__ |
| 118 if m1.method_calls != m2.method_calls: |
| 119 pp1 = pprint.pformat(m1.method_calls) |
| 120 pp2 = pprint.pformat(m2.method_calls) |
| 121 self.assertMultiLineEqual(pp1+'\n', pp2+'\n') |
| 122 |
| 123 def cmd_help(self, args, help_msg=None, topic=None, ret=ERR): |
| 124 """Run a command line, and check that it prints the right help. |
| 125 |
| 126 Only the last function call in the mock is checked, which should be the |
| 127 help message that we want to see. |
| 128 |
| 129 """ |
| 130 m, r = self.mock_command_line(args) |
| 131 self.assertEqual(r, ret, |
| 132 "Wrong status: got %s, wanted %s" % (r, ret) |
| 133 ) |
| 134 if help_msg: |
| 135 self.assertEqual(m.method_calls[-1], |
| 136 ('help_fn', (help_msg,), {}) |
| 137 ) |
| 138 else: |
| 139 self.assertEqual(m.method_calls[-1], |
| 140 ('help_fn', (), {'topic':topic}) |
| 141 ) |
| 142 |
| 143 |
| 144 class BaseCmdLineTestTest(BaseCmdLineTest): |
| 145 """Tests that our BaseCmdLineTest helpers work.""" |
| 146 def test_assert_same_method_calls(self): |
| 147 # All the other tests here use self.cmd_executes_same in successful |
| 148 # ways, so here we just check that it fails. |
| 149 with self.assertRaises(AssertionError): |
| 150 self.cmd_executes_same("run", "debug") |
| 151 |
| 152 |
| 153 class CmdLineTest(BaseCmdLineTest): |
| 154 """Tests of the coverage.py command line.""" |
| 155 |
| 156 def test_annotate(self): |
| 157 # coverage annotate [-d DIR] [-i] [--omit DIR,...] [FILE1 FILE2 ...] |
| 158 self.cmd_executes("annotate", """\ |
| 159 .coverage() |
| 160 .load() |
| 161 .annotate() |
| 162 """) |
| 163 self.cmd_executes("annotate -d dir1", """\ |
| 164 .coverage() |
| 165 .load() |
| 166 .annotate(directory="dir1") |
| 167 """) |
| 168 self.cmd_executes("annotate -i", """\ |
| 169 .coverage() |
| 170 .load() |
| 171 .annotate(ignore_errors=True) |
| 172 """) |
| 173 self.cmd_executes("annotate --omit fooey", """\ |
| 174 .coverage(omit=["fooey"]) |
| 175 .load() |
| 176 .annotate(omit=["fooey"]) |
| 177 """) |
| 178 self.cmd_executes("annotate --omit fooey,booey", """\ |
| 179 .coverage(omit=["fooey", "booey"]) |
| 180 .load() |
| 181 .annotate(omit=["fooey", "booey"]) |
| 182 """) |
| 183 self.cmd_executes("annotate mod1", """\ |
| 184 .coverage() |
| 185 .load() |
| 186 .annotate(morfs=["mod1"]) |
| 187 """) |
| 188 self.cmd_executes("annotate mod1 mod2 mod3", """\ |
| 189 .coverage() |
| 190 .load() |
| 191 .annotate(morfs=["mod1", "mod2", "mod3"]) |
| 192 """) |
| 193 |
| 194 def test_combine(self): |
| 195 # coverage combine with args |
| 196 self.cmd_executes("combine datadir1", """\ |
| 197 .coverage() |
| 198 .load() |
| 199 .combine(["datadir1"]) |
| 200 .save() |
| 201 """) |
| 202 # coverage combine without args |
| 203 self.cmd_executes("combine", """\ |
| 204 .coverage() |
| 205 .load() |
| 206 .combine(None) |
| 207 .save() |
| 208 """) |
| 209 |
| 210 def test_combine_doesnt_confuse_options_with_args(self): |
| 211 # https://bitbucket.org/ned/coveragepy/issues/385/coverage-combine-doesn
t-work-with-rcfile |
| 212 self.cmd_executes("combine --rcfile cov.ini", """\ |
| 213 .coverage(config_file='cov.ini') |
| 214 .load() |
| 215 .combine(None) |
| 216 .save() |
| 217 """) |
| 218 self.cmd_executes("combine --rcfile cov.ini data1 data2/more", """\ |
| 219 .coverage(config_file='cov.ini') |
| 220 .load() |
| 221 .combine(["data1", "data2/more"]) |
| 222 .save() |
| 223 """) |
| 224 |
| 225 def test_debug(self): |
| 226 self.cmd_help("debug", "What information would you like: data, sys?") |
| 227 self.cmd_help("debug foo", "Don't know what you mean by 'foo'") |
| 228 |
| 229 def test_debug_sys(self): |
| 230 self.command_line("debug sys") |
| 231 out = self.stdout() |
| 232 self.assertIn("version:", out) |
| 233 self.assertIn("data_path:", out) |
| 234 |
| 235 def test_erase(self): |
| 236 # coverage erase |
| 237 self.cmd_executes("erase", """\ |
| 238 .coverage() |
| 239 .erase() |
| 240 """) |
| 241 |
| 242 def test_version(self): |
| 243 # coverage --version |
| 244 self.cmd_help("--version", topic="version", ret=OK) |
| 245 |
| 246 def test_help_option(self): |
| 247 # coverage -h |
| 248 self.cmd_help("-h", topic="help", ret=OK) |
| 249 self.cmd_help("--help", topic="help", ret=OK) |
| 250 |
| 251 def test_help_command(self): |
| 252 self.cmd_executes("help", ".help_fn(topic='help')") |
| 253 |
| 254 def test_cmd_help(self): |
| 255 self.cmd_executes("run --help", |
| 256 ".help_fn(parser='<CmdOptionParser:run>')") |
| 257 self.cmd_executes_same("help run", "run --help") |
| 258 |
| 259 def test_html(self): |
| 260 # coverage html -d DIR [-i] [--omit DIR,...] [FILE1 FILE2 ...] |
| 261 self.cmd_executes("html", """\ |
| 262 .coverage() |
| 263 .load() |
| 264 .html_report() |
| 265 """) |
| 266 self.cmd_executes("html -d dir1", """\ |
| 267 .coverage() |
| 268 .load() |
| 269 .html_report(directory="dir1") |
| 270 """) |
| 271 self.cmd_executes("html -i", """\ |
| 272 .coverage() |
| 273 .load() |
| 274 .html_report(ignore_errors=True) |
| 275 """) |
| 276 self.cmd_executes("html --omit fooey", """\ |
| 277 .coverage(omit=["fooey"]) |
| 278 .load() |
| 279 .html_report(omit=["fooey"]) |
| 280 """) |
| 281 self.cmd_executes("html --omit fooey,booey", """\ |
| 282 .coverage(omit=["fooey", "booey"]) |
| 283 .load() |
| 284 .html_report(omit=["fooey", "booey"]) |
| 285 """) |
| 286 self.cmd_executes("html mod1", """\ |
| 287 .coverage() |
| 288 .load() |
| 289 .html_report(morfs=["mod1"]) |
| 290 """) |
| 291 self.cmd_executes("html mod1 mod2 mod3", """\ |
| 292 .coverage() |
| 293 .load() |
| 294 .html_report(morfs=["mod1", "mod2", "mod3"]) |
| 295 """) |
| 296 self.cmd_executes("html --title=Hello_there", """\ |
| 297 .coverage() |
| 298 .load() |
| 299 .html_report(title='Hello_there') |
| 300 """) |
| 301 |
| 302 def test_report(self): |
| 303 # coverage report [-m] [-i] [-o DIR,...] [FILE1 FILE2 ...] |
| 304 self.cmd_executes("report", """\ |
| 305 .coverage() |
| 306 .load() |
| 307 .report(show_missing=None) |
| 308 """) |
| 309 self.cmd_executes("report -i", """\ |
| 310 .coverage() |
| 311 .load() |
| 312 .report(ignore_errors=True) |
| 313 """) |
| 314 self.cmd_executes("report -m", """\ |
| 315 .coverage() |
| 316 .load() |
| 317 .report(show_missing=True) |
| 318 """) |
| 319 self.cmd_executes("report --omit fooey", """\ |
| 320 .coverage(omit=["fooey"]) |
| 321 .load() |
| 322 .report(omit=["fooey"]) |
| 323 """) |
| 324 self.cmd_executes("report --omit fooey,booey", """\ |
| 325 .coverage(omit=["fooey", "booey"]) |
| 326 .load() |
| 327 .report(omit=["fooey", "booey"]) |
| 328 """) |
| 329 self.cmd_executes("report mod1", """\ |
| 330 .coverage() |
| 331 .load() |
| 332 .report(morfs=["mod1"]) |
| 333 """) |
| 334 self.cmd_executes("report mod1 mod2 mod3", """\ |
| 335 .coverage() |
| 336 .load() |
| 337 .report(morfs=["mod1", "mod2", "mod3"]) |
| 338 """) |
| 339 self.cmd_executes("report --skip-covered", """\ |
| 340 .coverage() |
| 341 .load() |
| 342 .report(skip_covered=True) |
| 343 """) |
| 344 |
| 345 def test_run(self): |
| 346 # coverage run [-p] [-L] [--timid] MODULE.py [ARG1 ARG2 ...] |
| 347 |
| 348 # run calls coverage.erase first. |
| 349 self.cmd_executes("run foo.py", """\ |
| 350 .coverage() |
| 351 .erase() |
| 352 .start() |
| 353 .run_python_file('foo.py', ['foo.py']) |
| 354 .stop() |
| 355 .save() |
| 356 """) |
| 357 # run -a combines with an existing data file before saving. |
| 358 self.cmd_executes("run -a foo.py", """\ |
| 359 .coverage() |
| 360 .start() |
| 361 .run_python_file('foo.py', ['foo.py']) |
| 362 .stop() |
| 363 .path_exists('.coverage') |
| 364 .combine(data_paths=['.coverage']) |
| 365 .save() |
| 366 """, path_exists=True) |
| 367 # run -a doesn't combine anything if the data file doesn't exist. |
| 368 self.cmd_executes("run -a foo.py", """\ |
| 369 .coverage() |
| 370 .start() |
| 371 .run_python_file('foo.py', ['foo.py']) |
| 372 .stop() |
| 373 .path_exists('.coverage') |
| 374 .save() |
| 375 """, path_exists=False) |
| 376 # --timid sets a flag, and program arguments get passed through. |
| 377 self.cmd_executes("run --timid foo.py abc 123", """\ |
| 378 .coverage(timid=True) |
| 379 .erase() |
| 380 .start() |
| 381 .run_python_file('foo.py', ['foo.py', 'abc', '123']) |
| 382 .stop() |
| 383 .save() |
| 384 """) |
| 385 # -L sets a flag, and flags for the program don't confuse us. |
| 386 self.cmd_executes("run -p -L foo.py -a -b", """\ |
| 387 .coverage(cover_pylib=True, data_suffix=True) |
| 388 .erase() |
| 389 .start() |
| 390 .run_python_file('foo.py', ['foo.py', '-a', '-b']) |
| 391 .stop() |
| 392 .save() |
| 393 """) |
| 394 self.cmd_executes("run --branch foo.py", """\ |
| 395 .coverage(branch=True) |
| 396 .erase() |
| 397 .start() |
| 398 .run_python_file('foo.py', ['foo.py']) |
| 399 .stop() |
| 400 .save() |
| 401 """) |
| 402 self.cmd_executes("run --rcfile=myrc.rc foo.py", """\ |
| 403 .coverage(config_file="myrc.rc") |
| 404 .erase() |
| 405 .start() |
| 406 .run_python_file('foo.py', ['foo.py']) |
| 407 .stop() |
| 408 .save() |
| 409 """) |
| 410 self.cmd_executes("run --include=pre1,pre2 foo.py", """\ |
| 411 .coverage(include=["pre1", "pre2"]) |
| 412 .erase() |
| 413 .start() |
| 414 .run_python_file('foo.py', ['foo.py']) |
| 415 .stop() |
| 416 .save() |
| 417 """) |
| 418 self.cmd_executes("run --omit=opre1,opre2 foo.py", """\ |
| 419 .coverage(omit=["opre1", "opre2"]) |
| 420 .erase() |
| 421 .start() |
| 422 .run_python_file('foo.py', ['foo.py']) |
| 423 .stop() |
| 424 .save() |
| 425 """) |
| 426 self.cmd_executes("run --include=pre1,pre2 --omit=opre1,opre2 foo.py", |
| 427 """\ |
| 428 .coverage(include=["pre1", "pre2"], omit=["opre1", "opre2"]) |
| 429 .erase() |
| 430 .start() |
| 431 .run_python_file('foo.py', ['foo.py']) |
| 432 .stop() |
| 433 .save() |
| 434 """) |
| 435 self.cmd_executes("run --source=quux,hi.there,/home/bar foo.py", """\ |
| 436 .coverage(source=["quux", "hi.there", "/home/bar"]) |
| 437 .erase() |
| 438 .start() |
| 439 .run_python_file('foo.py', ['foo.py']) |
| 440 .stop() |
| 441 .save() |
| 442 """) |
| 443 self.cmd_executes("run --concurrency=gevent foo.py", """\ |
| 444 .coverage(concurrency='gevent') |
| 445 .erase() |
| 446 .start() |
| 447 .run_python_file('foo.py', ['foo.py']) |
| 448 .stop() |
| 449 .save() |
| 450 """) |
| 451 |
| 452 def test_bad_concurrency(self): |
| 453 self.command_line("run --concurrency=nothing", ret=ERR) |
| 454 out = self.stdout() |
| 455 self.assertIn("option --concurrency: invalid choice: 'nothing'", out) |
| 456 |
| 457 def test_run_debug(self): |
| 458 self.cmd_executes("run --debug=opt1 foo.py", """\ |
| 459 .coverage(debug=["opt1"]) |
| 460 .erase() |
| 461 .start() |
| 462 .run_python_file('foo.py', ['foo.py']) |
| 463 .stop() |
| 464 .save() |
| 465 """) |
| 466 self.cmd_executes("run --debug=opt1,opt2 foo.py", """\ |
| 467 .coverage(debug=["opt1","opt2"]) |
| 468 .erase() |
| 469 .start() |
| 470 .run_python_file('foo.py', ['foo.py']) |
| 471 .stop() |
| 472 .save() |
| 473 """) |
| 474 |
| 475 def test_run_module(self): |
| 476 self.cmd_executes("run -m mymodule", """\ |
| 477 .coverage() |
| 478 .erase() |
| 479 .start() |
| 480 .run_python_module('mymodule', ['mymodule']) |
| 481 .stop() |
| 482 .save() |
| 483 """) |
| 484 self.cmd_executes("run -m mymodule -qq arg1 arg2", """\ |
| 485 .coverage() |
| 486 .erase() |
| 487 .start() |
| 488 .run_python_module('mymodule', ['mymodule', '-qq', 'arg1', 'arg2']) |
| 489 .stop() |
| 490 .save() |
| 491 """) |
| 492 self.cmd_executes("run --branch -m mymodule", """\ |
| 493 .coverage(branch=True) |
| 494 .erase() |
| 495 .start() |
| 496 .run_python_module('mymodule', ['mymodule']) |
| 497 .stop() |
| 498 .save() |
| 499 """) |
| 500 self.cmd_executes_same("run -m mymodule", "run --module mymodule") |
| 501 |
| 502 def test_run_nothing(self): |
| 503 self.command_line("run", ret=ERR) |
| 504 self.assertIn("Nothing to do", self.stdout()) |
| 505 |
| 506 def test_cant_append_parallel(self): |
| 507 self.command_line("run --append --parallel-mode foo.py", ret=ERR) |
| 508 self.assertIn("Can't append to data files in parallel mode.", self.stdou
t()) |
| 509 |
| 510 def test_xml(self): |
| 511 # coverage xml [-i] [--omit DIR,...] [FILE1 FILE2 ...] |
| 512 self.cmd_executes("xml", """\ |
| 513 .coverage() |
| 514 .load() |
| 515 .xml_report() |
| 516 """) |
| 517 self.cmd_executes("xml -i", """\ |
| 518 .coverage() |
| 519 .load() |
| 520 .xml_report(ignore_errors=True) |
| 521 """) |
| 522 self.cmd_executes("xml -o myxml.foo", """\ |
| 523 .coverage() |
| 524 .load() |
| 525 .xml_report(outfile="myxml.foo") |
| 526 """) |
| 527 self.cmd_executes("xml -o -", """\ |
| 528 .coverage() |
| 529 .load() |
| 530 .xml_report(outfile="-") |
| 531 """) |
| 532 self.cmd_executes("xml --omit fooey", """\ |
| 533 .coverage(omit=["fooey"]) |
| 534 .load() |
| 535 .xml_report(omit=["fooey"]) |
| 536 """) |
| 537 self.cmd_executes("xml --omit fooey,booey", """\ |
| 538 .coverage(omit=["fooey", "booey"]) |
| 539 .load() |
| 540 .xml_report(omit=["fooey", "booey"]) |
| 541 """) |
| 542 self.cmd_executes("xml mod1", """\ |
| 543 .coverage() |
| 544 .load() |
| 545 .xml_report(morfs=["mod1"]) |
| 546 """) |
| 547 self.cmd_executes("xml mod1 mod2 mod3", """\ |
| 548 .coverage() |
| 549 .load() |
| 550 .xml_report(morfs=["mod1", "mod2", "mod3"]) |
| 551 """) |
| 552 |
| 553 def test_no_arguments_at_all(self): |
| 554 self.cmd_help("", topic="minimum_help", ret=OK) |
| 555 |
| 556 def test_bad_command(self): |
| 557 self.cmd_help("xyzzy", "Unknown command: 'xyzzy'") |
| 558 |
| 559 |
| 560 class CmdLineWithFilesTest(BaseCmdLineTest): |
| 561 """Test the command line in ways that need temp files.""" |
| 562 |
| 563 run_in_temp_dir = True |
| 564 no_files_in_temp_dir = True |
| 565 |
| 566 def test_debug_data(self): |
| 567 data = CoverageData() |
| 568 data.add_lines({ |
| 569 "file1.py": dict.fromkeys(range(1, 18)), |
| 570 "file2.py": dict.fromkeys(range(1, 24)), |
| 571 }) |
| 572 data.add_file_tracers({"file1.py": "a_plugin"}) |
| 573 data_files = CoverageDataFiles() |
| 574 data_files.write(data) |
| 575 |
| 576 self.command_line("debug data") |
| 577 self.assertMultiLineEqual(self.stdout(), textwrap.dedent("""\ |
| 578 -- data ------------------------------------------------------ |
| 579 path: FILENAME |
| 580 has_arcs: False |
| 581 |
| 582 2 files: |
| 583 file1.py: 17 lines [a_plugin] |
| 584 file2.py: 23 lines |
| 585 """).replace("FILENAME", data_files.filename)) |
| 586 |
| 587 def test_debug_data_with_no_data(self): |
| 588 data_files = CoverageDataFiles() |
| 589 self.command_line("debug data") |
| 590 self.assertMultiLineEqual(self.stdout(), textwrap.dedent("""\ |
| 591 -- data ------------------------------------------------------ |
| 592 path: FILENAME |
| 593 No data collected |
| 594 """).replace("FILENAME", data_files.filename)) |
| 595 |
| 596 |
| 597 class CmdLineStdoutTest(BaseCmdLineTest): |
| 598 """Test the command line with real stdout output.""" |
| 599 |
| 600 def test_minimum_help(self): |
| 601 self.command_line("") |
| 602 out = self.stdout() |
| 603 self.assertIn("Code coverage for Python.", out) |
| 604 self.assertLess(out.count("\n"), 4) |
| 605 |
| 606 def test_version(self): |
| 607 self.command_line("--version") |
| 608 out = self.stdout() |
| 609 self.assertIn("ersion ", out) |
| 610 self.assertLess(out.count("\n"), 4) |
| 611 |
| 612 def test_help(self): |
| 613 self.command_line("help") |
| 614 out = self.stdout() |
| 615 self.assertIn("readthedocs.org", out) |
| 616 self.assertGreater(out.count("\n"), 10) |
| 617 |
| 618 def test_cmd_help(self): |
| 619 self.command_line("help run") |
| 620 out = self.stdout() |
| 621 self.assertIn("<pyfile>", out) |
| 622 self.assertIn("--timid", out) |
| 623 self.assertGreater(out.count("\n"), 10) |
| 624 |
| 625 def test_error(self): |
| 626 self.command_line("fooey kablooey", ret=ERR) |
| 627 out = self.stdout() |
| 628 self.assertIn("fooey", out) |
| 629 self.assertIn("help", out) |
| 630 |
| 631 |
| 632 class CmdMainTest(CoverageTest): |
| 633 """Tests of coverage.cmdline.main(), using mocking for isolation.""" |
| 634 |
| 635 run_in_temp_dir = False |
| 636 |
| 637 class CoverageScriptStub(object): |
| 638 """A stub for coverage.cmdline.CoverageScript, used by CmdMainTest.""" |
| 639 |
| 640 def command_line(self, argv): |
| 641 """Stub for command_line, the arg determines what it will do.""" |
| 642 if argv[0] == 'hello': |
| 643 print("Hello, world!") |
| 644 elif argv[0] == 'raise': |
| 645 try: |
| 646 raise Exception("oh noes!") |
| 647 except: |
| 648 raise ExceptionDuringRun(*sys.exc_info()) |
| 649 elif argv[0] == 'internalraise': |
| 650 raise ValueError("coverage is broken") |
| 651 elif argv[0] == 'exit': |
| 652 sys.exit(23) |
| 653 else: |
| 654 raise AssertionError("Bad CoverageScriptStub: %r"% (argv,)) |
| 655 return 0 |
| 656 |
| 657 def setUp(self): |
| 658 super(CmdMainTest, self).setUp() |
| 659 self.old_CoverageScript = coverage.cmdline.CoverageScript |
| 660 coverage.cmdline.CoverageScript = self.CoverageScriptStub |
| 661 self.addCleanup(self.cleanup_coverage_script) |
| 662 |
| 663 def cleanup_coverage_script(self): |
| 664 """Restore CoverageScript when the test is done.""" |
| 665 coverage.cmdline.CoverageScript = self.old_CoverageScript |
| 666 |
| 667 def test_normal(self): |
| 668 ret = coverage.cmdline.main(['hello']) |
| 669 self.assertEqual(ret, 0) |
| 670 self.assertEqual(self.stdout(), "Hello, world!\n") |
| 671 |
| 672 def test_raise(self): |
| 673 ret = coverage.cmdline.main(['raise']) |
| 674 self.assertEqual(ret, 1) |
| 675 self.assertEqual(self.stdout(), "") |
| 676 err = self.stderr().split('\n') |
| 677 self.assertEqual(err[0], 'Traceback (most recent call last):') |
| 678 self.assertEqual(err[-3], ' raise Exception("oh noes!")') |
| 679 self.assertEqual(err[-2], 'Exception: oh noes!') |
| 680 |
| 681 def test_internalraise(self): |
| 682 with self.assertRaisesRegex(ValueError, "coverage is broken"): |
| 683 coverage.cmdline.main(['internalraise']) |
| 684 |
| 685 def test_exit(self): |
| 686 ret = coverage.cmdline.main(['exit']) |
| 687 self.assertEqual(ret, 23) |
OLD | NEW |