From c19232a9d2be2bde30e446311f32e9dcdd5d4774 Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Sat, 2 Feb 2013 11:15:11 -0500 Subject: Move the test directory to tests to avoid conflicts with the stdlib test package. --HG-- rename : test/__init__.py => tests/__init__.py rename : test/backtest.py => tests/backtest.py rename : test/backunittest.py => tests/backunittest.py rename : test/coveragetest.py => tests/coveragetest.py rename : test/covmodzip1.py => tests/covmodzip1.py rename : test/eggsrc/egg1/__init__.py => tests/eggsrc/egg1/__init__.py rename : test/eggsrc/egg1/egg1.py => tests/eggsrc/egg1/egg1.py rename : test/eggsrc/setup.py => tests/eggsrc/setup.py rename : test/farm/annotate/annotate_dir.py => tests/farm/annotate/annotate_dir.py rename : test/farm/annotate/gold/white.py,cover => tests/farm/annotate/gold/white.py,cover rename : test/farm/annotate/gold_anno_dir/a___init__.py,cover => tests/farm/annotate/gold_anno_dir/a___init__.py,cover rename : test/farm/annotate/gold_anno_dir/a_a.py,cover => tests/farm/annotate/gold_anno_dir/a_a.py,cover rename : test/farm/annotate/gold_anno_dir/b___init__.py,cover => tests/farm/annotate/gold_anno_dir/b___init__.py,cover rename : test/farm/annotate/gold_anno_dir/b_b.py,cover => tests/farm/annotate/gold_anno_dir/b_b.py,cover rename : test/farm/annotate/gold_anno_dir/multi.py,cover => tests/farm/annotate/gold_anno_dir/multi.py,cover rename : test/farm/annotate/gold_multi/a/__init__.py,cover => tests/farm/annotate/gold_multi/a/__init__.py,cover rename : test/farm/annotate/gold_multi/a/a.py,cover => tests/farm/annotate/gold_multi/a/a.py,cover rename : test/farm/annotate/gold_multi/b/__init__.py,cover => tests/farm/annotate/gold_multi/b/__init__.py,cover rename : test/farm/annotate/gold_multi/b/b.py,cover => tests/farm/annotate/gold_multi/b/b.py,cover rename : test/farm/annotate/gold_multi/multi.py,cover => tests/farm/annotate/gold_multi/multi.py,cover rename : test/farm/annotate/gold_v24/white.py,cover => tests/farm/annotate/gold_v24/white.py,cover rename : test/farm/annotate/run.py => tests/farm/annotate/run.py rename : test/farm/annotate/run_multi.py => tests/farm/annotate/run_multi.py rename : test/farm/annotate/src/a/__init__.py => tests/farm/annotate/src/a/__init__.py rename : test/farm/annotate/src/a/a.py => tests/farm/annotate/src/a/a.py rename : test/farm/annotate/src/b/__init__.py => tests/farm/annotate/src/b/__init__.py rename : test/farm/annotate/src/b/b.py => tests/farm/annotate/src/b/b.py rename : test/farm/annotate/src/multi.py => tests/farm/annotate/src/multi.py rename : test/farm/annotate/src/white.py => tests/farm/annotate/src/white.py rename : test/farm/html/gold_a/a.html => tests/farm/html/gold_a/a.html rename : test/farm/html/gold_a/index.html => tests/farm/html/gold_a/index.html rename : test/farm/html/gold_b_branch/b.html => tests/farm/html/gold_b_branch/b.html rename : test/farm/html/gold_b_branch/index.html => tests/farm/html/gold_b_branch/index.html rename : test/farm/html/gold_bom/bom.html => tests/farm/html/gold_bom/bom.html rename : test/farm/html/gold_bom/index.html => tests/farm/html/gold_bom/index.html rename : test/farm/html/gold_isolatin1/index.html => tests/farm/html/gold_isolatin1/index.html rename : test/farm/html/gold_isolatin1/isolatin1.html => tests/farm/html/gold_isolatin1/isolatin1.html rename : test/farm/html/gold_omit_1/index.html => tests/farm/html/gold_omit_1/index.html rename : test/farm/html/gold_omit_1/m1.html => tests/farm/html/gold_omit_1/m1.html rename : test/farm/html/gold_omit_1/m2.html => tests/farm/html/gold_omit_1/m2.html rename : test/farm/html/gold_omit_1/m3.html => tests/farm/html/gold_omit_1/m3.html rename : test/farm/html/gold_omit_1/main.html => tests/farm/html/gold_omit_1/main.html rename : test/farm/html/gold_omit_2/index.html => tests/farm/html/gold_omit_2/index.html rename : test/farm/html/gold_omit_2/m2.html => tests/farm/html/gold_omit_2/m2.html rename : test/farm/html/gold_omit_2/m3.html => tests/farm/html/gold_omit_2/m3.html rename : test/farm/html/gold_omit_2/main.html => tests/farm/html/gold_omit_2/main.html rename : test/farm/html/gold_omit_3/index.html => tests/farm/html/gold_omit_3/index.html rename : test/farm/html/gold_omit_3/m3.html => tests/farm/html/gold_omit_3/m3.html rename : test/farm/html/gold_omit_3/main.html => tests/farm/html/gold_omit_3/main.html rename : test/farm/html/gold_omit_4/index.html => tests/farm/html/gold_omit_4/index.html rename : test/farm/html/gold_omit_4/m1.html => tests/farm/html/gold_omit_4/m1.html rename : test/farm/html/gold_omit_4/m3.html => tests/farm/html/gold_omit_4/m3.html rename : test/farm/html/gold_omit_4/main.html => tests/farm/html/gold_omit_4/main.html rename : test/farm/html/gold_omit_5/index.html => tests/farm/html/gold_omit_5/index.html rename : test/farm/html/gold_omit_5/m1.html => tests/farm/html/gold_omit_5/m1.html rename : test/farm/html/gold_omit_5/main.html => tests/farm/html/gold_omit_5/main.html rename : test/farm/html/gold_other/blah_blah_other.html => tests/farm/html/gold_other/blah_blah_other.html rename : test/farm/html/gold_other/here.html => tests/farm/html/gold_other/here.html rename : test/farm/html/gold_other/index.html => tests/farm/html/gold_other/index.html rename : test/farm/html/gold_partial/index.html => tests/farm/html/gold_partial/index.html rename : test/farm/html/gold_partial/partial.html => tests/farm/html/gold_partial/partial.html rename : test/farm/html/gold_styled/a.html => tests/farm/html/gold_styled/a.html rename : test/farm/html/gold_styled/extra.css => tests/farm/html/gold_styled/extra.css rename : test/farm/html/gold_styled/index.html => tests/farm/html/gold_styled/index.html rename : test/farm/html/gold_styled/style.css => tests/farm/html/gold_styled/style.css rename : test/farm/html/gold_unicode/index.html => tests/farm/html/gold_unicode/index.html rename : test/farm/html/gold_unicode/unicode.html => tests/farm/html/gold_unicode/unicode.html rename : test/farm/html/gold_x_xml/coverage.xml => tests/farm/html/gold_x_xml/coverage.xml rename : test/farm/html/gold_y_xml_branch/coverage.xml => tests/farm/html/gold_y_xml_branch/coverage.xml rename : test/farm/html/othersrc/other.py => tests/farm/html/othersrc/other.py rename : test/farm/html/run_a.py => tests/farm/html/run_a.py rename : test/farm/html/run_a_xml_1.py => tests/farm/html/run_a_xml_1.py rename : test/farm/html/run_a_xml_2.py => tests/farm/html/run_a_xml_2.py rename : test/farm/html/run_b_branch.py => tests/farm/html/run_b_branch.py rename : test/farm/html/run_bom.py => tests/farm/html/run_bom.py rename : test/farm/html/run_isolatin1.py => tests/farm/html/run_isolatin1.py rename : test/farm/html/run_omit_1.py => tests/farm/html/run_omit_1.py rename : test/farm/html/run_omit_2.py => tests/farm/html/run_omit_2.py rename : test/farm/html/run_omit_3.py => tests/farm/html/run_omit_3.py rename : test/farm/html/run_omit_4.py => tests/farm/html/run_omit_4.py rename : test/farm/html/run_omit_5.py => tests/farm/html/run_omit_5.py rename : test/farm/html/run_other.py => tests/farm/html/run_other.py rename : test/farm/html/run_partial.py => tests/farm/html/run_partial.py rename : test/farm/html/run_styled.py => tests/farm/html/run_styled.py rename : test/farm/html/run_tabbed.py => tests/farm/html/run_tabbed.py rename : test/farm/html/run_unicode.py => tests/farm/html/run_unicode.py rename : test/farm/html/run_y_xml_branch.py => tests/farm/html/run_y_xml_branch.py rename : test/farm/html/src/a.py => tests/farm/html/src/a.py rename : test/farm/html/src/b.py => tests/farm/html/src/b.py rename : test/farm/html/src/bom.py => tests/farm/html/src/bom.py rename : test/farm/html/src/coverage.xml => tests/farm/html/src/coverage.xml rename : test/farm/html/src/extra.css => tests/farm/html/src/extra.css rename : test/farm/html/src/here.py => tests/farm/html/src/here.py rename : test/farm/html/src/isolatin1.py => tests/farm/html/src/isolatin1.py rename : test/farm/html/src/m1.py => tests/farm/html/src/m1.py rename : test/farm/html/src/m2.py => tests/farm/html/src/m2.py rename : test/farm/html/src/m3.py => tests/farm/html/src/m3.py rename : test/farm/html/src/main.py => tests/farm/html/src/main.py rename : test/farm/html/src/omit4.ini => tests/farm/html/src/omit4.ini rename : test/farm/html/src/omit5.ini => tests/farm/html/src/omit5.ini rename : test/farm/html/src/partial.py => tests/farm/html/src/partial.py rename : test/farm/html/src/run_a_xml_2.ini => tests/farm/html/src/run_a_xml_2.ini rename : test/farm/html/src/tabbed.py => tests/farm/html/src/tabbed.py rename : test/farm/html/src/unicode.py => tests/farm/html/src/unicode.py rename : test/farm/html/src/y.py => tests/farm/html/src/y.py rename : test/farm/run/run_chdir.py => tests/farm/run/run_chdir.py rename : test/farm/run/run_timid.py => tests/farm/run/run_timid.py rename : test/farm/run/run_xxx.py => tests/farm/run/run_xxx.py rename : test/farm/run/src/chdir.py => tests/farm/run/src/chdir.py rename : test/farm/run/src/showtrace.py => tests/farm/run/src/showtrace.py rename : test/farm/run/src/subdir/placeholder => tests/farm/run/src/subdir/placeholder rename : test/farm/run/src/xxx => tests/farm/run/src/xxx rename : test/js/index.html => tests/js/index.html rename : test/js/tests.js => tests/js/tests.js rename : test/modules/aa/__init__.py => tests/modules/aa/__init__.py rename : test/modules/aa/afile.odd.py => tests/modules/aa/afile.odd.py rename : test/modules/aa/afile.py => tests/modules/aa/afile.py rename : test/modules/aa/bb.odd/bfile.py => tests/modules/aa/bb.odd/bfile.py rename : test/modules/aa/bb/__init__.py => tests/modules/aa/bb/__init__.py rename : test/modules/aa/bb/bfile.odd.py => tests/modules/aa/bb/bfile.odd.py rename : test/modules/aa/bb/bfile.py => tests/modules/aa/bb/bfile.py rename : test/modules/aa/bb/cc/__init__.py => tests/modules/aa/bb/cc/__init__.py rename : test/modules/aa/bb/cc/cfile.py => tests/modules/aa/bb/cc/cfile.py rename : test/modules/aa/zfile.py => tests/modules/aa/zfile.py rename : test/modules/covmod1.py => tests/modules/covmod1.py rename : test/modules/pkg1/__init__.py => tests/modules/pkg1/__init__.py rename : test/modules/pkg1/__main__.py => tests/modules/pkg1/__main__.py rename : test/modules/pkg1/p1a.py => tests/modules/pkg1/p1a.py rename : test/modules/pkg1/p1b.py => tests/modules/pkg1/p1b.py rename : test/modules/pkg1/p1c.py => tests/modules/pkg1/p1c.py rename : test/modules/pkg1/runmod2.py => tests/modules/pkg1/runmod2.py rename : test/modules/pkg1/sub/__init__.py => tests/modules/pkg1/sub/__init__.py rename : test/modules/pkg1/sub/__main__.py => tests/modules/pkg1/sub/__main__.py rename : test/modules/pkg1/sub/ps1a.py => tests/modules/pkg1/sub/ps1a.py rename : test/modules/pkg1/sub/runmod3.py => tests/modules/pkg1/sub/runmod3.py rename : test/modules/pkg2/__init__.py => tests/modules/pkg2/__init__.py rename : test/modules/pkg2/p2a.py => tests/modules/pkg2/p2a.py rename : test/modules/pkg2/p2b.py => tests/modules/pkg2/p2b.py rename : test/modules/runmod1.py => tests/modules/runmod1.py rename : test/modules/usepkgs.py => tests/modules/usepkgs.py rename : test/moremodules/othermods/__init__.py => tests/moremodules/othermods/__init__.py rename : test/moremodules/othermods/othera.py => tests/moremodules/othermods/othera.py rename : test/moremodules/othermods/otherb.py => tests/moremodules/othermods/otherb.py rename : test/moremodules/othermods/sub/__init__.py => tests/moremodules/othermods/sub/__init__.py rename : test/moremodules/othermods/sub/osa.py => tests/moremodules/othermods/sub/osa.py rename : test/moremodules/othermods/sub/osb.py => tests/moremodules/othermods/sub/osb.py rename : test/osinfo.py => tests/osinfo.py rename : test/qunit/jquery.tmpl.min.js => tests/qunit/jquery.tmpl.min.js rename : test/qunit/qunit.css => tests/qunit/qunit.css rename : test/qunit/qunit.js => tests/qunit/qunit.js rename : test/stress_phystoken.tok => tests/stress_phystoken.tok rename : test/stress_phystoken_dos.tok => tests/stress_phystoken_dos.tok rename : test/test_api.py => tests/test_api.py rename : test/test_arcs.py => tests/test_arcs.py rename : test/test_cmdline.py => tests/test_cmdline.py rename : test/test_codeunit.py => tests/test_codeunit.py rename : test/test_config.py => tests/test_config.py rename : test/test_coverage.py => tests/test_coverage.py rename : test/test_data.py => tests/test_data.py rename : test/test_execfile.py => tests/test_execfile.py rename : test/test_farm.py => tests/test_farm.py rename : test/test_files.py => tests/test_files.py rename : test/test_html.py => tests/test_html.py rename : test/test_misc.py => tests/test_misc.py rename : test/test_oddball.py => tests/test_oddball.py rename : test/test_parser.py => tests/test_parser.py rename : test/test_phystokens.py => tests/test_phystokens.py rename : test/test_process.py => tests/test_process.py rename : test/test_results.py => tests/test_results.py rename : test/test_summary.py => tests/test_summary.py rename : test/test_templite.py => tests/test_templite.py rename : test/test_testing.py => tests/test_testing.py rename : test/test_xml.py => tests/test_xml.py rename : test/try_execfile.py => tests/try_execfile.py --- test/__init__.py | 1 - test/backtest.py | 49 - test/backunittest.py | 115 -- test/coveragetest.py | 465 ------ test/covmodzip1.py | 3 - test/eggsrc/egg1/__init__.py | 0 test/eggsrc/egg1/egg1.py | 4 - test/eggsrc/setup.py | 8 - test/farm/annotate/annotate_dir.py | 7 - test/farm/annotate/gold/white.py,cover | 33 - .../annotate/gold_anno_dir/a___init__.py,cover | 0 test/farm/annotate/gold_anno_dir/a_a.py,cover | 5 - .../annotate/gold_anno_dir/b___init__.py,cover | 0 test/farm/annotate/gold_anno_dir/b_b.py,cover | 3 - test/farm/annotate/gold_anno_dir/multi.py,cover | 5 - test/farm/annotate/gold_multi/a/__init__.py,cover | 0 test/farm/annotate/gold_multi/a/a.py,cover | 5 - test/farm/annotate/gold_multi/b/__init__.py,cover | 0 test/farm/annotate/gold_multi/b/b.py,cover | 2 - test/farm/annotate/gold_multi/multi.py,cover | 5 - test/farm/annotate/gold_v24/white.py,cover | 33 - test/farm/annotate/run.py | 7 - test/farm/annotate/run_multi.py | 7 - test/farm/annotate/src/a/__init__.py | 0 test/farm/annotate/src/a/a.py | 5 - test/farm/annotate/src/b/__init__.py | 0 test/farm/annotate/src/b/b.py | 3 - test/farm/annotate/src/multi.py | 5 - test/farm/annotate/src/white.py | 33 - test/farm/html/gold_a/a.html | 95 -- test/farm/html/gold_a/index.html | 89 - test/farm/html/gold_b_branch/b.html | 139 -- test/farm/html/gold_b_branch/index.html | 101 -- test/farm/html/gold_bom/bom.html | 104 -- test/farm/html/gold_bom/index.html | 90 - test/farm/html/gold_isolatin1/index.html | 89 - test/farm/html/gold_isolatin1/isolatin1.html | 91 - test/farm/html/gold_omit_1/index.html | 116 -- test/farm/html/gold_omit_1/m1.html | 85 - test/farm/html/gold_omit_1/m2.html | 85 - test/farm/html/gold_omit_1/m3.html | 85 - test/farm/html/gold_omit_1/main.html | 101 -- test/farm/html/gold_omit_2/index.html | 107 -- test/farm/html/gold_omit_2/m2.html | 85 - test/farm/html/gold_omit_2/m3.html | 85 - test/farm/html/gold_omit_2/main.html | 101 -- test/farm/html/gold_omit_3/index.html | 98 -- test/farm/html/gold_omit_3/m3.html | 85 - test/farm/html/gold_omit_3/main.html | 101 -- test/farm/html/gold_omit_4/index.html | 107 -- test/farm/html/gold_omit_4/m1.html | 85 - test/farm/html/gold_omit_4/m3.html | 85 - test/farm/html/gold_omit_4/main.html | 101 -- test/farm/html/gold_omit_5/index.html | 98 -- test/farm/html/gold_omit_5/m1.html | 85 - test/farm/html/gold_omit_5/main.html | 101 -- test/farm/html/gold_other/blah_blah_other.html | 89 - test/farm/html/gold_other/here.html | 97 -- test/farm/html/gold_other/index.html | 98 -- test/farm/html/gold_partial/index.html | 101 -- test/farm/html/gold_partial/partial.html | 121 -- test/farm/html/gold_styled/a.html | 95 -- test/farm/html/gold_styled/extra.css | 1 - test/farm/html/gold_styled/index.html | 89 - test/farm/html/gold_styled/style.css | 275 ---- test/farm/html/gold_unicode/index.html | 89 - test/farm/html/gold_unicode/unicode.html | 91 - test/farm/html/gold_x_xml/coverage.xml | 20 - test/farm/html/gold_y_xml_branch/coverage.xml | 22 - test/farm/html/othersrc/other.py | 4 - test/farm/html/run_a.py | 25 - test/farm/html/run_a_xml_1.py | 21 - test/farm/html/run_a_xml_2.py | 21 - test/farm/html/run_b_branch.py | 28 - test/farm/html/run_bom.py | 21 - test/farm/html/run_isolatin1.py | 21 - test/farm/html/run_omit_1.py | 12 - test/farm/html/run_omit_2.py | 12 - test/farm/html/run_omit_3.py | 12 - test/farm/html/run_omit_4.py | 12 - test/farm/html/run_omit_5.py | 12 - test/farm/html/run_other.py | 26 - test/farm/html/run_partial.py | 32 - test/farm/html/run_styled.py | 28 - test/farm/html/run_tabbed.py | 24 - test/farm/html/run_unicode.py | 30 - test/farm/html/run_y_xml_branch.py | 21 - test/farm/html/src/a.py | 7 - test/farm/html/src/b.py | 29 - test/farm/html/src/bom.py | 11 - test/farm/html/src/coverage.xml | 20 - test/farm/html/src/extra.css | 1 - test/farm/html/src/here.py | 8 - test/farm/html/src/isolatin1.py | 5 - test/farm/html/src/m1.py | 2 - test/farm/html/src/m2.py | 2 - test/farm/html/src/m3.py | 2 - test/farm/html/src/main.py | 10 - test/farm/html/src/omit4.ini | 2 - test/farm/html/src/omit5.ini | 8 - test/farm/html/src/partial.py | 18 - test/farm/html/src/run_a_xml_2.ini | 3 - test/farm/html/src/tabbed.py | 7 - test/farm/html/src/unicode.py | 5 - test/farm/html/src/y.py | 9 - test/farm/run/run_chdir.py | 12 - test/farm/run/run_timid.py | 60 - test/farm/run/run_xxx.py | 12 - test/farm/run/src/chdir.py | 4 - test/farm/run/src/showtrace.py | 23 - test/farm/run/src/subdir/placeholder | 0 test/farm/run/src/xxx | 8 - test/js/index.html | 52 - test/js/tests.js | 204 --- test/modules/aa/__init__.py | 1 - test/modules/aa/afile.odd.py | 1 - test/modules/aa/afile.py | 1 - test/modules/aa/bb.odd/bfile.py | 1 - test/modules/aa/bb/__init__.py | 1 - test/modules/aa/bb/bfile.odd.py | 1 - test/modules/aa/bb/bfile.py | 1 - test/modules/aa/bb/cc/__init__.py | 0 test/modules/aa/bb/cc/cfile.py | 1 - test/modules/aa/zfile.py | 1 - test/modules/covmod1.py | 3 - test/modules/pkg1/__init__.py | 3 - test/modules/pkg1/__main__.py | 3 - test/modules/pkg1/p1a.py | 5 - test/modules/pkg1/p1b.py | 3 - test/modules/pkg1/p1c.py | 3 - test/modules/pkg1/runmod2.py | 3 - test/modules/pkg1/sub/__init__.py | 0 test/modules/pkg1/sub/__main__.py | 3 - test/modules/pkg1/sub/ps1a.py | 3 - test/modules/pkg1/sub/runmod3.py | 3 - test/modules/pkg2/__init__.py | 2 - test/modules/pkg2/p2a.py | 3 - test/modules/pkg2/p2b.py | 3 - test/modules/runmod1.py | 3 - test/modules/usepkgs.py | 4 - test/moremodules/othermods/__init__.py | 0 test/moremodules/othermods/othera.py | 2 - test/moremodules/othermods/otherb.py | 2 - test/moremodules/othermods/sub/__init__.py | 0 test/moremodules/othermods/sub/osa.py | 2 - test/moremodules/othermods/sub/osb.py | 2 - test/osinfo.py | 71 - test/qunit/jquery.tmpl.min.js | 10 - test/qunit/qunit.css | 225 --- test/qunit/qunit.js | 1448 ---------------- test/stress_phystoken.tok | 52 - test/stress_phystoken_dos.tok | 52 - test/test_api.py | 571 ------- test/test_arcs.py | 578 ------- test/test_cmdline.py | 702 -------- test/test_codeunit.py | 103 -- test/test_config.py | 225 --- test/test_coverage.py | 1730 -------------------- test/test_data.py | 146 -- test/test_execfile.py | 116 -- test/test_farm.py | 366 ----- test/test_files.py | 169 -- test/test_html.py | 297 ---- test/test_misc.py | 73 - test/test_oddball.py | 386 ----- test/test_parser.py | 131 -- test/test_phystokens.py | 79 - test/test_process.py | 575 ------- test/test_results.py | 60 - test/test_summary.py | 298 ---- test/test_templite.py | 204 --- test/test_testing.py | 192 --- test/test_xml.py | 84 - test/try_execfile.py | 34 - tests/__init__.py | 1 + tests/backtest.py | 49 + tests/backunittest.py | 115 ++ tests/coveragetest.py | 465 ++++++ tests/covmodzip1.py | 3 + tests/eggsrc/egg1/__init__.py | 0 tests/eggsrc/egg1/egg1.py | 4 + tests/eggsrc/setup.py | 8 + tests/farm/annotate/annotate_dir.py | 7 + tests/farm/annotate/gold/white.py,cover | 33 + .../annotate/gold_anno_dir/a___init__.py,cover | 0 tests/farm/annotate/gold_anno_dir/a_a.py,cover | 5 + .../annotate/gold_anno_dir/b___init__.py,cover | 0 tests/farm/annotate/gold_anno_dir/b_b.py,cover | 3 + tests/farm/annotate/gold_anno_dir/multi.py,cover | 5 + tests/farm/annotate/gold_multi/a/__init__.py,cover | 0 tests/farm/annotate/gold_multi/a/a.py,cover | 5 + tests/farm/annotate/gold_multi/b/__init__.py,cover | 0 tests/farm/annotate/gold_multi/b/b.py,cover | 2 + tests/farm/annotate/gold_multi/multi.py,cover | 5 + tests/farm/annotate/gold_v24/white.py,cover | 33 + tests/farm/annotate/run.py | 7 + tests/farm/annotate/run_multi.py | 7 + tests/farm/annotate/src/a/__init__.py | 0 tests/farm/annotate/src/a/a.py | 5 + tests/farm/annotate/src/b/__init__.py | 0 tests/farm/annotate/src/b/b.py | 3 + tests/farm/annotate/src/multi.py | 5 + tests/farm/annotate/src/white.py | 33 + tests/farm/html/gold_a/a.html | 95 ++ tests/farm/html/gold_a/index.html | 89 + tests/farm/html/gold_b_branch/b.html | 139 ++ tests/farm/html/gold_b_branch/index.html | 101 ++ tests/farm/html/gold_bom/bom.html | 104 ++ tests/farm/html/gold_bom/index.html | 90 + tests/farm/html/gold_isolatin1/index.html | 89 + tests/farm/html/gold_isolatin1/isolatin1.html | 91 + tests/farm/html/gold_omit_1/index.html | 116 ++ tests/farm/html/gold_omit_1/m1.html | 85 + tests/farm/html/gold_omit_1/m2.html | 85 + tests/farm/html/gold_omit_1/m3.html | 85 + tests/farm/html/gold_omit_1/main.html | 101 ++ tests/farm/html/gold_omit_2/index.html | 107 ++ tests/farm/html/gold_omit_2/m2.html | 85 + tests/farm/html/gold_omit_2/m3.html | 85 + tests/farm/html/gold_omit_2/main.html | 101 ++ tests/farm/html/gold_omit_3/index.html | 98 ++ tests/farm/html/gold_omit_3/m3.html | 85 + tests/farm/html/gold_omit_3/main.html | 101 ++ tests/farm/html/gold_omit_4/index.html | 107 ++ tests/farm/html/gold_omit_4/m1.html | 85 + tests/farm/html/gold_omit_4/m3.html | 85 + tests/farm/html/gold_omit_4/main.html | 101 ++ tests/farm/html/gold_omit_5/index.html | 98 ++ tests/farm/html/gold_omit_5/m1.html | 85 + tests/farm/html/gold_omit_5/main.html | 101 ++ tests/farm/html/gold_other/blah_blah_other.html | 89 + tests/farm/html/gold_other/here.html | 97 ++ tests/farm/html/gold_other/index.html | 98 ++ tests/farm/html/gold_partial/index.html | 101 ++ tests/farm/html/gold_partial/partial.html | 121 ++ tests/farm/html/gold_styled/a.html | 95 ++ tests/farm/html/gold_styled/extra.css | 1 + tests/farm/html/gold_styled/index.html | 89 + tests/farm/html/gold_styled/style.css | 275 ++++ tests/farm/html/gold_unicode/index.html | 89 + tests/farm/html/gold_unicode/unicode.html | 91 + tests/farm/html/gold_x_xml/coverage.xml | 20 + tests/farm/html/gold_y_xml_branch/coverage.xml | 22 + tests/farm/html/othersrc/other.py | 4 + tests/farm/html/run_a.py | 25 + tests/farm/html/run_a_xml_1.py | 21 + tests/farm/html/run_a_xml_2.py | 21 + tests/farm/html/run_b_branch.py | 28 + tests/farm/html/run_bom.py | 21 + tests/farm/html/run_isolatin1.py | 21 + tests/farm/html/run_omit_1.py | 12 + tests/farm/html/run_omit_2.py | 12 + tests/farm/html/run_omit_3.py | 12 + tests/farm/html/run_omit_4.py | 12 + tests/farm/html/run_omit_5.py | 12 + tests/farm/html/run_other.py | 26 + tests/farm/html/run_partial.py | 32 + tests/farm/html/run_styled.py | 28 + tests/farm/html/run_tabbed.py | 24 + tests/farm/html/run_unicode.py | 30 + tests/farm/html/run_y_xml_branch.py | 21 + tests/farm/html/src/a.py | 7 + tests/farm/html/src/b.py | 29 + tests/farm/html/src/bom.py | 11 + tests/farm/html/src/coverage.xml | 20 + tests/farm/html/src/extra.css | 1 + tests/farm/html/src/here.py | 8 + tests/farm/html/src/isolatin1.py | 5 + tests/farm/html/src/m1.py | 2 + tests/farm/html/src/m2.py | 2 + tests/farm/html/src/m3.py | 2 + tests/farm/html/src/main.py | 10 + tests/farm/html/src/omit4.ini | 2 + tests/farm/html/src/omit5.ini | 8 + tests/farm/html/src/partial.py | 18 + tests/farm/html/src/run_a_xml_2.ini | 3 + tests/farm/html/src/tabbed.py | 7 + tests/farm/html/src/unicode.py | 5 + tests/farm/html/src/y.py | 9 + tests/farm/run/run_chdir.py | 12 + tests/farm/run/run_timid.py | 60 + tests/farm/run/run_xxx.py | 12 + tests/farm/run/src/chdir.py | 4 + tests/farm/run/src/showtrace.py | 23 + tests/farm/run/src/subdir/placeholder | 0 tests/farm/run/src/xxx | 8 + tests/js/index.html | 52 + tests/js/tests.js | 204 +++ tests/modules/aa/__init__.py | 1 + tests/modules/aa/afile.odd.py | 1 + tests/modules/aa/afile.py | 1 + tests/modules/aa/bb.odd/bfile.py | 1 + tests/modules/aa/bb/__init__.py | 1 + tests/modules/aa/bb/bfile.odd.py | 1 + tests/modules/aa/bb/bfile.py | 1 + tests/modules/aa/bb/cc/__init__.py | 0 tests/modules/aa/bb/cc/cfile.py | 1 + tests/modules/aa/zfile.py | 1 + tests/modules/covmod1.py | 3 + tests/modules/pkg1/__init__.py | 3 + tests/modules/pkg1/__main__.py | 3 + tests/modules/pkg1/p1a.py | 5 + tests/modules/pkg1/p1b.py | 3 + tests/modules/pkg1/p1c.py | 3 + tests/modules/pkg1/runmod2.py | 3 + tests/modules/pkg1/sub/__init__.py | 0 tests/modules/pkg1/sub/__main__.py | 3 + tests/modules/pkg1/sub/ps1a.py | 3 + tests/modules/pkg1/sub/runmod3.py | 3 + tests/modules/pkg2/__init__.py | 2 + tests/modules/pkg2/p2a.py | 3 + tests/modules/pkg2/p2b.py | 3 + tests/modules/runmod1.py | 3 + tests/modules/usepkgs.py | 4 + tests/moremodules/othermods/__init__.py | 0 tests/moremodules/othermods/othera.py | 2 + tests/moremodules/othermods/otherb.py | 2 + tests/moremodules/othermods/sub/__init__.py | 0 tests/moremodules/othermods/sub/osa.py | 2 + tests/moremodules/othermods/sub/osb.py | 2 + tests/osinfo.py | 71 + tests/qunit/jquery.tmpl.min.js | 10 + tests/qunit/qunit.css | 225 +++ tests/qunit/qunit.js | 1448 ++++++++++++++++ tests/stress_phystoken.tok | 52 + tests/stress_phystoken_dos.tok | 52 + tests/test_api.py | 571 +++++++ tests/test_arcs.py | 578 +++++++ tests/test_cmdline.py | 702 ++++++++ tests/test_codeunit.py | 103 ++ tests/test_config.py | 225 +++ tests/test_coverage.py | 1730 ++++++++++++++++++++ tests/test_data.py | 146 ++ tests/test_execfile.py | 116 ++ tests/test_farm.py | 366 +++++ tests/test_files.py | 169 ++ tests/test_html.py | 297 ++++ tests/test_misc.py | 73 + tests/test_oddball.py | 386 +++++ tests/test_parser.py | 131 ++ tests/test_phystokens.py | 79 + tests/test_process.py | 575 +++++++ tests/test_results.py | 60 + tests/test_summary.py | 298 ++++ tests/test_templite.py | 204 +++ tests/test_testing.py | 192 +++ tests/test_xml.py | 84 + tests/try_execfile.py | 34 + 348 files changed, 14512 insertions(+), 14512 deletions(-) delete mode 100644 test/__init__.py delete mode 100644 test/backtest.py delete mode 100644 test/backunittest.py delete mode 100644 test/coveragetest.py delete mode 100644 test/covmodzip1.py delete mode 100644 test/eggsrc/egg1/__init__.py delete mode 100644 test/eggsrc/egg1/egg1.py delete mode 100644 test/eggsrc/setup.py delete mode 100644 test/farm/annotate/annotate_dir.py delete mode 100644 test/farm/annotate/gold/white.py,cover delete mode 100644 test/farm/annotate/gold_anno_dir/a___init__.py,cover delete mode 100644 test/farm/annotate/gold_anno_dir/a_a.py,cover delete mode 100644 test/farm/annotate/gold_anno_dir/b___init__.py,cover delete mode 100644 test/farm/annotate/gold_anno_dir/b_b.py,cover delete mode 100644 test/farm/annotate/gold_anno_dir/multi.py,cover delete mode 100644 test/farm/annotate/gold_multi/a/__init__.py,cover delete mode 100644 test/farm/annotate/gold_multi/a/a.py,cover delete mode 100644 test/farm/annotate/gold_multi/b/__init__.py,cover delete mode 100644 test/farm/annotate/gold_multi/b/b.py,cover delete mode 100644 test/farm/annotate/gold_multi/multi.py,cover delete mode 100644 test/farm/annotate/gold_v24/white.py,cover delete mode 100644 test/farm/annotate/run.py delete mode 100644 test/farm/annotate/run_multi.py delete mode 100644 test/farm/annotate/src/a/__init__.py delete mode 100644 test/farm/annotate/src/a/a.py delete mode 100644 test/farm/annotate/src/b/__init__.py delete mode 100644 test/farm/annotate/src/b/b.py delete mode 100644 test/farm/annotate/src/multi.py delete mode 100644 test/farm/annotate/src/white.py delete mode 100644 test/farm/html/gold_a/a.html delete mode 100644 test/farm/html/gold_a/index.html delete mode 100644 test/farm/html/gold_b_branch/b.html delete mode 100644 test/farm/html/gold_b_branch/index.html delete mode 100644 test/farm/html/gold_bom/bom.html delete mode 100644 test/farm/html/gold_bom/index.html delete mode 100644 test/farm/html/gold_isolatin1/index.html delete mode 100644 test/farm/html/gold_isolatin1/isolatin1.html delete mode 100644 test/farm/html/gold_omit_1/index.html delete mode 100644 test/farm/html/gold_omit_1/m1.html delete mode 100644 test/farm/html/gold_omit_1/m2.html delete mode 100644 test/farm/html/gold_omit_1/m3.html delete mode 100644 test/farm/html/gold_omit_1/main.html delete mode 100644 test/farm/html/gold_omit_2/index.html delete mode 100644 test/farm/html/gold_omit_2/m2.html delete mode 100644 test/farm/html/gold_omit_2/m3.html delete mode 100644 test/farm/html/gold_omit_2/main.html delete mode 100644 test/farm/html/gold_omit_3/index.html delete mode 100644 test/farm/html/gold_omit_3/m3.html delete mode 100644 test/farm/html/gold_omit_3/main.html delete mode 100644 test/farm/html/gold_omit_4/index.html delete mode 100644 test/farm/html/gold_omit_4/m1.html delete mode 100644 test/farm/html/gold_omit_4/m3.html delete mode 100644 test/farm/html/gold_omit_4/main.html delete mode 100644 test/farm/html/gold_omit_5/index.html delete mode 100644 test/farm/html/gold_omit_5/m1.html delete mode 100644 test/farm/html/gold_omit_5/main.html delete mode 100644 test/farm/html/gold_other/blah_blah_other.html delete mode 100644 test/farm/html/gold_other/here.html delete mode 100644 test/farm/html/gold_other/index.html delete mode 100644 test/farm/html/gold_partial/index.html delete mode 100644 test/farm/html/gold_partial/partial.html delete mode 100644 test/farm/html/gold_styled/a.html delete mode 100644 test/farm/html/gold_styled/extra.css delete mode 100644 test/farm/html/gold_styled/index.html delete mode 100644 test/farm/html/gold_styled/style.css delete mode 100644 test/farm/html/gold_unicode/index.html delete mode 100644 test/farm/html/gold_unicode/unicode.html delete mode 100644 test/farm/html/gold_x_xml/coverage.xml delete mode 100644 test/farm/html/gold_y_xml_branch/coverage.xml delete mode 100644 test/farm/html/othersrc/other.py delete mode 100644 test/farm/html/run_a.py delete mode 100644 test/farm/html/run_a_xml_1.py delete mode 100644 test/farm/html/run_a_xml_2.py delete mode 100644 test/farm/html/run_b_branch.py delete mode 100644 test/farm/html/run_bom.py delete mode 100644 test/farm/html/run_isolatin1.py delete mode 100644 test/farm/html/run_omit_1.py delete mode 100644 test/farm/html/run_omit_2.py delete mode 100644 test/farm/html/run_omit_3.py delete mode 100644 test/farm/html/run_omit_4.py delete mode 100644 test/farm/html/run_omit_5.py delete mode 100644 test/farm/html/run_other.py delete mode 100644 test/farm/html/run_partial.py delete mode 100644 test/farm/html/run_styled.py delete mode 100644 test/farm/html/run_tabbed.py delete mode 100644 test/farm/html/run_unicode.py delete mode 100644 test/farm/html/run_y_xml_branch.py delete mode 100644 test/farm/html/src/a.py delete mode 100644 test/farm/html/src/b.py delete mode 100644 test/farm/html/src/bom.py delete mode 100644 test/farm/html/src/coverage.xml delete mode 100644 test/farm/html/src/extra.css delete mode 100644 test/farm/html/src/here.py delete mode 100644 test/farm/html/src/isolatin1.py delete mode 100644 test/farm/html/src/m1.py delete mode 100644 test/farm/html/src/m2.py delete mode 100644 test/farm/html/src/m3.py delete mode 100644 test/farm/html/src/main.py delete mode 100644 test/farm/html/src/omit4.ini delete mode 100644 test/farm/html/src/omit5.ini delete mode 100644 test/farm/html/src/partial.py delete mode 100644 test/farm/html/src/run_a_xml_2.ini delete mode 100644 test/farm/html/src/tabbed.py delete mode 100644 test/farm/html/src/unicode.py delete mode 100644 test/farm/html/src/y.py delete mode 100644 test/farm/run/run_chdir.py delete mode 100644 test/farm/run/run_timid.py delete mode 100644 test/farm/run/run_xxx.py delete mode 100644 test/farm/run/src/chdir.py delete mode 100644 test/farm/run/src/showtrace.py delete mode 100644 test/farm/run/src/subdir/placeholder delete mode 100644 test/farm/run/src/xxx delete mode 100644 test/js/index.html delete mode 100644 test/js/tests.js delete mode 100644 test/modules/aa/__init__.py delete mode 100644 test/modules/aa/afile.odd.py delete mode 100644 test/modules/aa/afile.py delete mode 100644 test/modules/aa/bb.odd/bfile.py delete mode 100644 test/modules/aa/bb/__init__.py delete mode 100644 test/modules/aa/bb/bfile.odd.py delete mode 100644 test/modules/aa/bb/bfile.py delete mode 100644 test/modules/aa/bb/cc/__init__.py delete mode 100644 test/modules/aa/bb/cc/cfile.py delete mode 100644 test/modules/aa/zfile.py delete mode 100644 test/modules/covmod1.py delete mode 100644 test/modules/pkg1/__init__.py delete mode 100644 test/modules/pkg1/__main__.py delete mode 100644 test/modules/pkg1/p1a.py delete mode 100644 test/modules/pkg1/p1b.py delete mode 100644 test/modules/pkg1/p1c.py delete mode 100644 test/modules/pkg1/runmod2.py delete mode 100644 test/modules/pkg1/sub/__init__.py delete mode 100644 test/modules/pkg1/sub/__main__.py delete mode 100644 test/modules/pkg1/sub/ps1a.py delete mode 100644 test/modules/pkg1/sub/runmod3.py delete mode 100644 test/modules/pkg2/__init__.py delete mode 100644 test/modules/pkg2/p2a.py delete mode 100644 test/modules/pkg2/p2b.py delete mode 100644 test/modules/runmod1.py delete mode 100644 test/modules/usepkgs.py delete mode 100644 test/moremodules/othermods/__init__.py delete mode 100644 test/moremodules/othermods/othera.py delete mode 100644 test/moremodules/othermods/otherb.py delete mode 100644 test/moremodules/othermods/sub/__init__.py delete mode 100644 test/moremodules/othermods/sub/osa.py delete mode 100644 test/moremodules/othermods/sub/osb.py delete mode 100644 test/osinfo.py delete mode 100644 test/qunit/jquery.tmpl.min.js delete mode 100644 test/qunit/qunit.css delete mode 100644 test/qunit/qunit.js delete mode 100644 test/stress_phystoken.tok delete mode 100644 test/stress_phystoken_dos.tok delete mode 100644 test/test_api.py delete mode 100644 test/test_arcs.py delete mode 100644 test/test_cmdline.py delete mode 100644 test/test_codeunit.py delete mode 100644 test/test_config.py delete mode 100644 test/test_coverage.py delete mode 100644 test/test_data.py delete mode 100644 test/test_execfile.py delete mode 100644 test/test_farm.py delete mode 100644 test/test_files.py delete mode 100644 test/test_html.py delete mode 100644 test/test_misc.py delete mode 100644 test/test_oddball.py delete mode 100644 test/test_parser.py delete mode 100644 test/test_phystokens.py delete mode 100644 test/test_process.py delete mode 100644 test/test_results.py delete mode 100644 test/test_summary.py delete mode 100644 test/test_templite.py delete mode 100644 test/test_testing.py delete mode 100644 test/test_xml.py delete mode 100644 test/try_execfile.py create mode 100644 tests/__init__.py create mode 100644 tests/backtest.py create mode 100644 tests/backunittest.py create mode 100644 tests/coveragetest.py create mode 100644 tests/covmodzip1.py create mode 100644 tests/eggsrc/egg1/__init__.py create mode 100644 tests/eggsrc/egg1/egg1.py create mode 100644 tests/eggsrc/setup.py create mode 100644 tests/farm/annotate/annotate_dir.py create mode 100644 tests/farm/annotate/gold/white.py,cover create mode 100644 tests/farm/annotate/gold_anno_dir/a___init__.py,cover create mode 100644 tests/farm/annotate/gold_anno_dir/a_a.py,cover create mode 100644 tests/farm/annotate/gold_anno_dir/b___init__.py,cover create mode 100644 tests/farm/annotate/gold_anno_dir/b_b.py,cover create mode 100644 tests/farm/annotate/gold_anno_dir/multi.py,cover create mode 100644 tests/farm/annotate/gold_multi/a/__init__.py,cover create mode 100644 tests/farm/annotate/gold_multi/a/a.py,cover create mode 100644 tests/farm/annotate/gold_multi/b/__init__.py,cover create mode 100644 tests/farm/annotate/gold_multi/b/b.py,cover create mode 100644 tests/farm/annotate/gold_multi/multi.py,cover create mode 100644 tests/farm/annotate/gold_v24/white.py,cover create mode 100644 tests/farm/annotate/run.py create mode 100644 tests/farm/annotate/run_multi.py create mode 100644 tests/farm/annotate/src/a/__init__.py create mode 100644 tests/farm/annotate/src/a/a.py create mode 100644 tests/farm/annotate/src/b/__init__.py create mode 100644 tests/farm/annotate/src/b/b.py create mode 100644 tests/farm/annotate/src/multi.py create mode 100644 tests/farm/annotate/src/white.py create mode 100644 tests/farm/html/gold_a/a.html create mode 100644 tests/farm/html/gold_a/index.html create mode 100644 tests/farm/html/gold_b_branch/b.html create mode 100644 tests/farm/html/gold_b_branch/index.html create mode 100644 tests/farm/html/gold_bom/bom.html create mode 100644 tests/farm/html/gold_bom/index.html create mode 100644 tests/farm/html/gold_isolatin1/index.html create mode 100644 tests/farm/html/gold_isolatin1/isolatin1.html create mode 100644 tests/farm/html/gold_omit_1/index.html create mode 100644 tests/farm/html/gold_omit_1/m1.html create mode 100644 tests/farm/html/gold_omit_1/m2.html create mode 100644 tests/farm/html/gold_omit_1/m3.html create mode 100644 tests/farm/html/gold_omit_1/main.html create mode 100644 tests/farm/html/gold_omit_2/index.html create mode 100644 tests/farm/html/gold_omit_2/m2.html create mode 100644 tests/farm/html/gold_omit_2/m3.html create mode 100644 tests/farm/html/gold_omit_2/main.html create mode 100644 tests/farm/html/gold_omit_3/index.html create mode 100644 tests/farm/html/gold_omit_3/m3.html create mode 100644 tests/farm/html/gold_omit_3/main.html create mode 100644 tests/farm/html/gold_omit_4/index.html create mode 100644 tests/farm/html/gold_omit_4/m1.html create mode 100644 tests/farm/html/gold_omit_4/m3.html create mode 100644 tests/farm/html/gold_omit_4/main.html create mode 100644 tests/farm/html/gold_omit_5/index.html create mode 100644 tests/farm/html/gold_omit_5/m1.html create mode 100644 tests/farm/html/gold_omit_5/main.html create mode 100644 tests/farm/html/gold_other/blah_blah_other.html create mode 100644 tests/farm/html/gold_other/here.html create mode 100644 tests/farm/html/gold_other/index.html create mode 100644 tests/farm/html/gold_partial/index.html create mode 100644 tests/farm/html/gold_partial/partial.html create mode 100644 tests/farm/html/gold_styled/a.html create mode 100644 tests/farm/html/gold_styled/extra.css create mode 100644 tests/farm/html/gold_styled/index.html create mode 100644 tests/farm/html/gold_styled/style.css create mode 100644 tests/farm/html/gold_unicode/index.html create mode 100644 tests/farm/html/gold_unicode/unicode.html create mode 100644 tests/farm/html/gold_x_xml/coverage.xml create mode 100644 tests/farm/html/gold_y_xml_branch/coverage.xml create mode 100644 tests/farm/html/othersrc/other.py create mode 100644 tests/farm/html/run_a.py create mode 100644 tests/farm/html/run_a_xml_1.py create mode 100644 tests/farm/html/run_a_xml_2.py create mode 100644 tests/farm/html/run_b_branch.py create mode 100644 tests/farm/html/run_bom.py create mode 100644 tests/farm/html/run_isolatin1.py create mode 100644 tests/farm/html/run_omit_1.py create mode 100644 tests/farm/html/run_omit_2.py create mode 100644 tests/farm/html/run_omit_3.py create mode 100644 tests/farm/html/run_omit_4.py create mode 100644 tests/farm/html/run_omit_5.py create mode 100644 tests/farm/html/run_other.py create mode 100644 tests/farm/html/run_partial.py create mode 100644 tests/farm/html/run_styled.py create mode 100644 tests/farm/html/run_tabbed.py create mode 100644 tests/farm/html/run_unicode.py create mode 100644 tests/farm/html/run_y_xml_branch.py create mode 100644 tests/farm/html/src/a.py create mode 100644 tests/farm/html/src/b.py create mode 100644 tests/farm/html/src/bom.py create mode 100644 tests/farm/html/src/coverage.xml create mode 100644 tests/farm/html/src/extra.css create mode 100644 tests/farm/html/src/here.py create mode 100644 tests/farm/html/src/isolatin1.py create mode 100644 tests/farm/html/src/m1.py create mode 100644 tests/farm/html/src/m2.py create mode 100644 tests/farm/html/src/m3.py create mode 100644 tests/farm/html/src/main.py create mode 100644 tests/farm/html/src/omit4.ini create mode 100644 tests/farm/html/src/omit5.ini create mode 100644 tests/farm/html/src/partial.py create mode 100644 tests/farm/html/src/run_a_xml_2.ini create mode 100644 tests/farm/html/src/tabbed.py create mode 100644 tests/farm/html/src/unicode.py create mode 100644 tests/farm/html/src/y.py create mode 100644 tests/farm/run/run_chdir.py create mode 100644 tests/farm/run/run_timid.py create mode 100644 tests/farm/run/run_xxx.py create mode 100644 tests/farm/run/src/chdir.py create mode 100644 tests/farm/run/src/showtrace.py create mode 100644 tests/farm/run/src/subdir/placeholder create mode 100644 tests/farm/run/src/xxx create mode 100644 tests/js/index.html create mode 100644 tests/js/tests.js create mode 100644 tests/modules/aa/__init__.py create mode 100644 tests/modules/aa/afile.odd.py create mode 100644 tests/modules/aa/afile.py create mode 100644 tests/modules/aa/bb.odd/bfile.py create mode 100644 tests/modules/aa/bb/__init__.py create mode 100644 tests/modules/aa/bb/bfile.odd.py create mode 100644 tests/modules/aa/bb/bfile.py create mode 100644 tests/modules/aa/bb/cc/__init__.py create mode 100644 tests/modules/aa/bb/cc/cfile.py create mode 100644 tests/modules/aa/zfile.py create mode 100644 tests/modules/covmod1.py create mode 100644 tests/modules/pkg1/__init__.py create mode 100644 tests/modules/pkg1/__main__.py create mode 100644 tests/modules/pkg1/p1a.py create mode 100644 tests/modules/pkg1/p1b.py create mode 100644 tests/modules/pkg1/p1c.py create mode 100644 tests/modules/pkg1/runmod2.py create mode 100644 tests/modules/pkg1/sub/__init__.py create mode 100644 tests/modules/pkg1/sub/__main__.py create mode 100644 tests/modules/pkg1/sub/ps1a.py create mode 100644 tests/modules/pkg1/sub/runmod3.py create mode 100644 tests/modules/pkg2/__init__.py create mode 100644 tests/modules/pkg2/p2a.py create mode 100644 tests/modules/pkg2/p2b.py create mode 100644 tests/modules/runmod1.py create mode 100644 tests/modules/usepkgs.py create mode 100644 tests/moremodules/othermods/__init__.py create mode 100644 tests/moremodules/othermods/othera.py create mode 100644 tests/moremodules/othermods/otherb.py create mode 100644 tests/moremodules/othermods/sub/__init__.py create mode 100644 tests/moremodules/othermods/sub/osa.py create mode 100644 tests/moremodules/othermods/sub/osb.py create mode 100644 tests/osinfo.py create mode 100644 tests/qunit/jquery.tmpl.min.js create mode 100644 tests/qunit/qunit.css create mode 100644 tests/qunit/qunit.js create mode 100644 tests/stress_phystoken.tok create mode 100644 tests/stress_phystoken_dos.tok create mode 100644 tests/test_api.py create mode 100644 tests/test_arcs.py create mode 100644 tests/test_cmdline.py create mode 100644 tests/test_codeunit.py create mode 100644 tests/test_config.py create mode 100644 tests/test_coverage.py create mode 100644 tests/test_data.py create mode 100644 tests/test_execfile.py create mode 100644 tests/test_farm.py create mode 100644 tests/test_files.py create mode 100644 tests/test_html.py create mode 100644 tests/test_misc.py create mode 100644 tests/test_oddball.py create mode 100644 tests/test_parser.py create mode 100644 tests/test_phystokens.py create mode 100644 tests/test_process.py create mode 100644 tests/test_results.py create mode 100644 tests/test_summary.py create mode 100644 tests/test_templite.py create mode 100644 tests/test_testing.py create mode 100644 tests/test_xml.py create mode 100644 tests/try_execfile.py diff --git a/test/__init__.py b/test/__init__.py deleted file mode 100644 index 5a0e30f4..00000000 --- a/test/__init__.py +++ /dev/null @@ -1 +0,0 @@ -"""Automated tests. Run with nosetests.""" diff --git a/test/backtest.py b/test/backtest.py deleted file mode 100644 index b17aa242..00000000 --- a/test/backtest.py +++ /dev/null @@ -1,49 +0,0 @@ -"""Add things to old Pythons so I can pretend they are newer, for tests.""" - -# pylint: disable=W0622 -# (Redefining built-in blah) -# The whole point of this file is to redefine built-ins, so shut up about it. - -import os - -# Py2k and 3k don't agree on how to run commands in a subprocess. -try: - import subprocess -except ImportError: - def run_command(cmd, status=0): - """Run a command in a subprocess. - - Returns the exit status code and the combined stdout and stderr. - - """ - _, stdouterr = os.popen4(cmd) - return status, stdouterr.read() - -else: - def run_command(cmd, status=0): - """Run a command in a subprocess. - - Returns the exit status code and the combined stdout and stderr. - - """ - proc = subprocess.Popen(cmd, shell=True, - stdin=subprocess.PIPE, stdout=subprocess.PIPE, - stderr=subprocess.STDOUT - ) - output, _ = proc.communicate() - status = proc.returncode # pylint: disable=E1101 - - # Get the output, and canonicalize it to strings with newlines. - if not isinstance(output, str): - output = output.decode('utf-8') - output = output.replace('\r', '') - - return status, output - -# No more execfile in Py3k -try: - execfile = execfile -except NameError: - def execfile(filename, globs): - """A Python 3 implementation of execfile.""" - exec(compile(open(filename).read(), filename, 'exec'), globs) diff --git a/test/backunittest.py b/test/backunittest.py deleted file mode 100644 index 30da78eb..00000000 --- a/test/backunittest.py +++ /dev/null @@ -1,115 +0,0 @@ -"""Implementations of unittest features from the future.""" - -import difflib, re, sys, unittest - -from coverage.backward import set # pylint: disable=W0622 - - -def _need(method): - """Do we need to define our own `method` method?""" - return not hasattr(unittest.TestCase, method) - - -class TestCase(unittest.TestCase): - """Just like unittest.TestCase, but with assert methods added. - - Designed to be compatible with 3.1 unittest. Methods are only defined if - the builtin `unittest` doesn't have them. - - """ - if _need('assertTrue'): - def assertTrue(self, exp, msg=None): - """Assert that `exp` is true.""" - if not exp: - self.fail(msg) - - if _need('assertFalse'): - def assertFalse(self, exp, msg=None): - """Assert that `exp` is false.""" - if exp: - self.fail(msg) - - if _need('assertIn'): - def assertIn(self, member, container, msg=None): - """Assert that `member` is in `container`.""" - if member not in container: - msg = msg or ('%r not found in %r' % (member, container)) - self.fail(msg) - - if _need('assertNotIn'): - def assertNotIn(self, member, container, msg=None): - """Assert that `member` is not in `container`.""" - if member in container: - msg = msg or ('%r found in %r' % (member, container)) - self.fail(msg) - - if _need('assertGreater'): - def assertGreater(self, a, b, msg=None): - """Assert that `a` is greater than `b`.""" - if not a > b: - msg = msg or ('%r not greater than %r' % (a, b)) - self.fail(msg) - - if _need('assertRaisesRegexp'): - def assertRaisesRegexp(self, excClass, regexp, callobj, *args, **kw): - """ Just like unittest.TestCase.assertRaises, - but checks that the message is right too. - """ - try: - callobj(*args, **kw) - except excClass: - _, exc, _ = sys.exc_info() - excMsg = str(exc) - if re.search(regexp, excMsg): - # Message provided, and we got the right one: it passes. - return - else: - # Message provided, and it didn't match: fail! - raise self.failureException( - "Right exception, wrong message: " - "%r doesn't match %r" % (excMsg, regexp) - ) - # No need to catch other exceptions: They'll fail the test all by - # themselves! - else: - if hasattr(excClass, '__name__'): - excName = excClass.__name__ - else: - excName = str(excClass) - raise self.failureException( - "Expected to raise %s, didn't get an exception at all" % - excName - ) - - if _need('assertSameElements'): - def assertSameElements(self, s1, s2): - """Assert that the two arguments are equal as sets.""" - self.assertEqual(set(s1), set(s2)) - - if _need('assertRegexpMatches'): - def assertRegexpMatches(self, text, regex, msg=None): - """Assert that `text` matches `regex`.""" - m = re.search(regex, text) - if not m: - msg = msg or ("%r doesn't match %r" % (text, regex)) - raise self.failureException(msg) - - if _need('assertMultiLineEqual'): - def assertMultiLineEqual(self, first, second, msg=None): - """Assert that two multi-line strings are equal. - - If they aren't, show a nice diff. - - """ - # Adapted from Py3.1 unittest. - self.assertTrue(isinstance(first, str), - 'First argument is not a string') - self.assertTrue(isinstance(second, str), - 'Second argument is not a string') - - if first != second: - message = ''.join(difflib.ndiff(first.splitlines(True), - second.splitlines(True))) - if msg: - message += " : " + msg - self.fail("Multi-line strings are unequal:\n" + message) diff --git a/test/coveragetest.py b/test/coveragetest.py deleted file mode 100644 index 6f6217aa..00000000 --- a/test/coveragetest.py +++ /dev/null @@ -1,465 +0,0 @@ -"""Base test case class for coverage testing.""" - -import glob, imp, os, random, shlex, shutil, sys, tempfile, textwrap - -import coverage -from coverage.backward import sorted, StringIO # pylint: disable=W0622 -from coverage.backward import to_bytes -from coverage.control import _TEST_NAME_FILE -from test.backtest import run_command -from test.backunittest import TestCase - -class Tee(object): - """A file-like that writes to all the file-likes it has.""" - - def __init__(self, *files): - """Make a Tee that writes to all the files in `files.`""" - self._files = files - if hasattr(files[0], "encoding"): - self.encoding = files[0].encoding - - def write(self, data): - """Write `data` to all the files.""" - for f in self._files: - f.write(data) - - if 0: - # Use this if you need to use a debugger, though it makes some tests - # fail, I'm not sure why... - def __getattr__(self, name): - return getattr(self._files[0], name) - - -# Status returns for the command line. -OK, ERR = 0, 1 - -class CoverageTest(TestCase): - """A base class for Coverage test cases.""" - - run_in_temp_dir = True - - def setUp(self): - super(CoverageTest, self).setUp() - - if _TEST_NAME_FILE: - f = open(_TEST_NAME_FILE, "w") - f.write("%s_%s" % (self.__class__.__name__, self._testMethodName)) - f.close() - - # Tell newer unittest implementations to print long helpful messages. - self.longMessage = True - - # tearDown will restore the original sys.path - self.old_syspath = sys.path[:] - - if self.run_in_temp_dir: - # Create a temporary directory. - self.noise = str(random.random())[2:] - self.temp_root = os.path.join(tempfile.gettempdir(), 'test_cover') - self.temp_dir = os.path.join(self.temp_root, self.noise) - os.makedirs(self.temp_dir) - self.old_dir = os.getcwd() - os.chdir(self.temp_dir) - - # Modules should be importable from this temp directory. - sys.path.insert(0, '') - - # Keep a counter to make every call to check_coverage unique. - self.n = 0 - - # Record environment variables that we changed with set_environ. - self.environ_undos = {} - - # Capture stdout and stderr so we can examine them in tests. - # nose keeps stdout from littering the screen, so we can safely Tee it, - # but it doesn't capture stderr, so we don't want to Tee stderr to the - # real stderr, since it will interfere with our nice field of dots. - self.old_stdout = sys.stdout - self.captured_stdout = StringIO() - sys.stdout = Tee(sys.stdout, self.captured_stdout) - self.old_stderr = sys.stderr - self.captured_stderr = StringIO() - sys.stderr = self.captured_stderr - - # Record sys.modules here so we can restore it in tearDown. - self.old_modules = dict(sys.modules) - - def tearDown(self): - super(CoverageTest, self).tearDown() - - # Restore the original sys.path. - sys.path = self.old_syspath - - if self.run_in_temp_dir: - # Get rid of the temporary directory. - os.chdir(self.old_dir) - shutil.rmtree(self.temp_root) - - # Restore the environment. - self.undo_environ() - - # Restore stdout and stderr - sys.stdout = self.old_stdout - sys.stderr = self.old_stderr - - self.clean_modules() - - def clean_modules(self): - """Remove any new modules imported during the test run. - - This lets us import the same source files for more than one test. - - """ - for m in [m for m in sys.modules if m not in self.old_modules]: - del sys.modules[m] - - def set_environ(self, name, value): - """Set an environment variable `name` to be `value`. - - The environment variable is set, and record is kept that it was set, - so that `tearDown` can restore its original value. - - """ - if name not in self.environ_undos: - self.environ_undos[name] = os.environ.get(name) - os.environ[name] = value - - def original_environ(self, name, if_missing=None): - """The environment variable `name` from when the test started.""" - if name in self.environ_undos: - ret = self.environ_undos[name] - else: - ret = os.environ.get(name) - if ret is None: - ret = if_missing - return ret - - def undo_environ(self): - """Undo all the changes made by `set_environ`.""" - for name, value in self.environ_undos.items(): - if value is None: - del os.environ[name] - else: - os.environ[name] = value - - def stdout(self): - """Return the data written to stdout during the test.""" - return self.captured_stdout.getvalue() - - def stderr(self): - """Return the data written to stderr during the test.""" - return self.captured_stderr.getvalue() - - def make_file(self, filename, text="", newline=None): - """Create a temp file. - - `filename` is the path to the file, including directories if desired, - and `text` is the content. If `newline` is provided, it is a string - that will be used as the line endings in the created file. - - Returns the path to the file. - - """ - # Tests that call `make_file` should be run in a temp environment. - assert self.run_in_temp_dir - text = textwrap.dedent(text) - if newline: - text = text.replace("\n", newline) - - # Make sure the directories are available. - dirs, _ = os.path.split(filename) - if dirs and not os.path.exists(dirs): - os.makedirs(dirs) - - # Create the file. - f = open(filename, 'wb') - try: - f.write(to_bytes(text)) - finally: - f.close() - - return filename - - def clean_local_file_imports(self): - """Clean up the results of calls to `import_local_file`. - - Use this if you need to `import_local_file` the same file twice in - one test. - - """ - # So that we can re-import files, clean them out first. - self.clean_modules() - # Also have to clean out the .pyc file, since the timestamp - # resolution is only one second, a changed file might not be - # picked up. - for pyc in glob.glob('*.pyc'): - os.remove(pyc) - if os.path.exists("__pycache__"): - shutil.rmtree("__pycache__") - - def import_local_file(self, modname): - """Import a local file as a module. - - Opens a file in the current directory named `modname`.py, imports it - as `modname`, and returns the module object. - - """ - modfile = modname + '.py' - f = open(modfile, 'r') - - for suff in imp.get_suffixes(): - if suff[0] == '.py': - break - try: - # pylint: disable=W0631 - # (Using possibly undefined loop variable 'suff') - mod = imp.load_module(modname, f, modfile, suff) - finally: - f.close() - return mod - - def start_import_stop(self, cov, modname): - """Start coverage, import a file, then stop coverage. - - `cov` is started and stopped, with an `import_local_file` of - `modname` in the middle. - - The imported module is returned. - - """ - cov.start() - try: # pragma: nested - # Import the python file, executing it. - mod = self.import_local_file(modname) - finally: # pragma: nested - # Stop Coverage. - cov.stop() - return mod - - def get_module_name(self): - """Return the module name to use for this test run.""" - # We append self.n because otherwise two calls in one test will use the - # same filename and whether the test works or not depends on the - # timestamps in the .pyc file, so it becomes random whether the second - # call will use the compiled version of the first call's code or not! - modname = 'coverage_test_' + self.noise + str(self.n) - self.n += 1 - return modname - - # Map chars to numbers for arcz_to_arcs - _arcz_map = {'.': -1} - _arcz_map.update(dict([(c, ord(c)-ord('0')) for c in '123456789'])) - _arcz_map.update(dict( - [(c, 10+ord(c)-ord('A')) for c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'] - )) - - def arcz_to_arcs(self, arcz): - """Convert a compact textual representation of arcs to a list of pairs. - - The text has space-separated pairs of letters. Period is -1, 1-9 are - 1-9, A-Z are 10 through 36. The resulting list is sorted regardless of - the order of the input pairs. - - ".1 12 2." --> [(-1,1), (1,2), (2,-1)] - - Minus signs can be included in the pairs: - - "-11, 12, 2-5" --> [(-1,1), (1,2), (2,-5)] - - """ - arcs = [] - for pair in arcz.split(): - asgn = bsgn = 1 - if len(pair) == 2: - a,b = pair - else: - assert len(pair) == 3 - if pair[0] == '-': - _,a,b = pair - asgn = -1 - else: - assert pair[1] == '-' - a,_,b = pair - bsgn = -1 - arcs.append((asgn*self._arcz_map[a], bsgn*self._arcz_map[b])) - return sorted(arcs) - - def assertEqualArcs(self, a1, a2, msg=None): - """Assert that the arc lists `a1` and `a2` are equal.""" - # Make them into multi-line strings so we can see what's going wrong. - s1 = "\n".join([repr(a) for a in a1]) + "\n" - s2 = "\n".join([repr(a) for a in a2]) + "\n" - self.assertMultiLineEqual(s1, s2, msg) - - def check_coverage(self, text, lines=None, missing="", report="", - excludes=None, partials="", - arcz=None, arcz_missing="", arcz_unpredicted=""): - """Check the coverage measurement of `text`. - - The source `text` is run and measured. `lines` are the line numbers - that are executable, or a list of possible line numbers, any of which - could match. `missing` are the lines not executed, `excludes` are - regexes to match against for excluding lines, and `report` is the text - of the measurement report. - - For arc measurement, `arcz` is a string that can be decoded into arcs - in the code (see `arcz_to_arcs` for the encoding scheme), - `arcz_missing` are the arcs that are not executed, and - `arcs_unpredicted` are the arcs executed in the code, but not deducible - from the code. - - """ - # We write the code into a file so that we can import it. - # Coverage wants to deal with things as modules with file names. - modname = self.get_module_name() - - self.make_file(modname+".py", text) - - arcs = arcs_missing = arcs_unpredicted = None - if arcz is not None: - arcs = self.arcz_to_arcs(arcz) - arcs_missing = self.arcz_to_arcs(arcz_missing or "") - arcs_unpredicted = self.arcz_to_arcs(arcz_unpredicted or "") - - # Start up Coverage. - cov = coverage.coverage(branch=(arcs_missing is not None)) - cov.erase() - for exc in excludes or []: - cov.exclude(exc) - for par in partials or []: - cov.exclude(par, which='partial') - - mod = self.start_import_stop(cov, modname) - - # Clean up our side effects - del sys.modules[modname] - - # Get the analysis results, and check that they are right. - analysis = cov._analyze(mod) - if lines is not None: - if type(lines[0]) == type(1): - # lines is just a list of numbers, it must match the statements - # found in the code. - self.assertEqual(analysis.statements, lines) - else: - # lines is a list of possible line number lists, one of them - # must match. - for line_list in lines: - if analysis.statements == line_list: - break - else: - self.fail("None of the lines choices matched %r" % - analysis.statements - ) - - if type(missing) == type(""): - self.assertEqual(analysis.missing_formatted(), missing) - else: - for missing_list in missing: - if analysis.missing_formatted() == missing_list: - break - else: - self.fail("None of the missing choices matched %r" % - analysis.missing_formatted() - ) - - if arcs is not None: - self.assertEqualArcs( - analysis.arc_possibilities(), arcs, "Possible arcs differ" - ) - - if arcs_missing is not None: - self.assertEqualArcs( - analysis.arcs_missing(), arcs_missing, - "Missing arcs differ" - ) - - if arcs_unpredicted is not None: - self.assertEqualArcs( - analysis.arcs_unpredicted(), arcs_unpredicted, - "Unpredicted arcs differ" - ) - - if report: - frep = StringIO() - cov.report(mod, file=frep) - rep = " ".join(frep.getvalue().split("\n")[2].split()[1:]) - self.assertEqual(report, rep) - - def nice_file(self, *fparts): - """Canonicalize the filename composed of the parts in `fparts`.""" - fname = os.path.join(*fparts) - return os.path.normcase(os.path.abspath(os.path.realpath(fname))) - - def assert_same_files(self, flist1, flist2): - """Assert that `flist1` and `flist2` are the same set of file names.""" - flist1_nice = [self.nice_file(f) for f in flist1] - flist2_nice = [self.nice_file(f) for f in flist2] - self.assertSameElements(flist1_nice, flist2_nice) - - def assert_exists(self, fname): - """Assert that `fname` is a file that exists.""" - msg = "File %r should exist" % fname - self.assert_(os.path.exists(fname), msg) - - def assert_doesnt_exist(self, fname): - """Assert that `fname` is a file that doesn't exist.""" - msg = "File %r shouldn't exist" % fname - self.assert_(not os.path.exists(fname), msg) - - def command_line(self, args, ret=OK, _covpkg=None): - """Run `args` through the command line. - - Use this when you want to run the full coverage machinery, but in the - current process. Exceptions may be thrown from deep in the code. - Asserts that `ret` is returned by `CoverageScript.command_line`. - - Compare with `run_command`. - - Returns None. - - """ - script = coverage.CoverageScript(_covpkg=_covpkg) - ret_actual = script.command_line(shlex.split(args)) - self.assertEqual(ret_actual, ret) - - def run_command(self, cmd): - """Run the command-line `cmd` in a subprocess, and print its output. - - Use this when you need to test the process behavior of coverage. - - Compare with `command_line`. - - Returns the process' stdout text. - - """ - _, output = self.run_command_status(cmd) - return output - - def run_command_status(self, cmd, status=0): - """Run the command-line `cmd` in a subprocess, and print its output. - - Use this when you need to test the process behavior of coverage. - - Compare with `command_line`. - - Returns a pair: the process' exit status and stdout text. - - The `status` argument is returned as the status on older Pythons where - we can't get the actual exit status of the process. - - """ - # Add our test modules directory to PYTHONPATH. I'm sure there's too - # much path munging here, but... - here = os.path.dirname(self.nice_file(coverage.__file__, "..")) - testmods = self.nice_file(here, 'test/modules') - zipfile = self.nice_file(here, 'test/zipmods.zip') - pypath = os.getenv('PYTHONPATH', '') - if pypath: - pypath += os.pathsep - pypath += testmods + os.pathsep + zipfile - self.set_environ('PYTHONPATH', pypath) - - status, output = run_command(cmd, status=status) - print(output) - return status, output diff --git a/test/covmodzip1.py b/test/covmodzip1.py deleted file mode 100644 index 3ec4cdc4..00000000 --- a/test/covmodzip1.py +++ /dev/null @@ -1,3 +0,0 @@ -"""covmodzip.py: for putting into a zip file.""" -j = 1 -j += 1 diff --git a/test/eggsrc/egg1/__init__.py b/test/eggsrc/egg1/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/eggsrc/egg1/egg1.py b/test/eggsrc/egg1/egg1.py deleted file mode 100644 index 3fadde33..00000000 --- a/test/eggsrc/egg1/egg1.py +++ /dev/null @@ -1,4 +0,0 @@ -# My egg file! - -walrus = "Eggman" -says = "coo-coo cachoo" diff --git a/test/eggsrc/setup.py b/test/eggsrc/setup.py deleted file mode 100644 index f9b8b9d0..00000000 --- a/test/eggsrc/setup.py +++ /dev/null @@ -1,8 +0,0 @@ -from setuptools import setup - -setup( - name="covtestegg1", - packages=['egg1'], - zip_safe=True, - install_requires=[], - ) diff --git a/test/farm/annotate/annotate_dir.py b/test/farm/annotate/annotate_dir.py deleted file mode 100644 index 3e37f9ed..00000000 --- a/test/farm/annotate/annotate_dir.py +++ /dev/null @@ -1,7 +0,0 @@ -copy("src", "run") -run(""" - coverage -e -x multi.py - coverage -a -d out_anno_dir - """, rundir="run") -compare("run/out_anno_dir", "gold_anno_dir", "*,cover", left_extra=True) -clean("run") diff --git a/test/farm/annotate/gold/white.py,cover b/test/farm/annotate/gold/white.py,cover deleted file mode 100644 index 36b0b993..00000000 --- a/test/farm/annotate/gold/white.py,cover +++ /dev/null @@ -1,33 +0,0 @@ - # A test case sent to me by Steve White - -> def f(self): -! if self==1: -! pass -! elif self.m('fred'): -! pass -! elif (g==1) and (b==2): -! pass -! elif self.m('fred')==True: -! pass -! elif ((g==1) and (b==2))==True: -! pass -! else: -! pass - -> def g(x): -> if x == 1: -> a = 1 -! else: -! a = 2 - -> g(1) - -> def h(x): -- if 0: #pragma: no cover -- pass -> if x == 1: -! a = 1 -> else: -> a = 2 - -> h(2) diff --git a/test/farm/annotate/gold_anno_dir/a___init__.py,cover b/test/farm/annotate/gold_anno_dir/a___init__.py,cover deleted file mode 100644 index e69de29b..00000000 diff --git a/test/farm/annotate/gold_anno_dir/a_a.py,cover b/test/farm/annotate/gold_anno_dir/a_a.py,cover deleted file mode 100644 index d0ff3c0c..00000000 --- a/test/farm/annotate/gold_anno_dir/a_a.py,cover +++ /dev/null @@ -1,5 +0,0 @@ -> def a(x): -> if x == 1: -> print("x is 1") -! else: -! print("x is not 1") diff --git a/test/farm/annotate/gold_anno_dir/b___init__.py,cover b/test/farm/annotate/gold_anno_dir/b___init__.py,cover deleted file mode 100644 index e69de29b..00000000 diff --git a/test/farm/annotate/gold_anno_dir/b_b.py,cover b/test/farm/annotate/gold_anno_dir/b_b.py,cover deleted file mode 100644 index 90d076f1..00000000 --- a/test/farm/annotate/gold_anno_dir/b_b.py,cover +++ /dev/null @@ -1,3 +0,0 @@ -> def b(x): -> msg = "x is %s" % x -> print(msg) diff --git a/test/farm/annotate/gold_anno_dir/multi.py,cover b/test/farm/annotate/gold_anno_dir/multi.py,cover deleted file mode 100644 index 2a5c59ce..00000000 --- a/test/farm/annotate/gold_anno_dir/multi.py,cover +++ /dev/null @@ -1,5 +0,0 @@ -> import a.a -> import b.b - -> a.a.a(1) -> b.b.b(2) diff --git a/test/farm/annotate/gold_multi/a/__init__.py,cover b/test/farm/annotate/gold_multi/a/__init__.py,cover deleted file mode 100644 index e69de29b..00000000 diff --git a/test/farm/annotate/gold_multi/a/a.py,cover b/test/farm/annotate/gold_multi/a/a.py,cover deleted file mode 100644 index fb3f5435..00000000 --- a/test/farm/annotate/gold_multi/a/a.py,cover +++ /dev/null @@ -1,5 +0,0 @@ -> def a(x): -> if x == 1: -> print "x is 1" -! else: -! print "x is not 1" diff --git a/test/farm/annotate/gold_multi/b/__init__.py,cover b/test/farm/annotate/gold_multi/b/__init__.py,cover deleted file mode 100644 index e69de29b..00000000 diff --git a/test/farm/annotate/gold_multi/b/b.py,cover b/test/farm/annotate/gold_multi/b/b.py,cover deleted file mode 100644 index a3f5daec..00000000 --- a/test/farm/annotate/gold_multi/b/b.py,cover +++ /dev/null @@ -1,2 +0,0 @@ -> def b(x): -> print "x is %s" % x diff --git a/test/farm/annotate/gold_multi/multi.py,cover b/test/farm/annotate/gold_multi/multi.py,cover deleted file mode 100644 index 2a5c59ce..00000000 --- a/test/farm/annotate/gold_multi/multi.py,cover +++ /dev/null @@ -1,5 +0,0 @@ -> import a.a -> import b.b - -> a.a.a(1) -> b.b.b(2) diff --git a/test/farm/annotate/gold_v24/white.py,cover b/test/farm/annotate/gold_v24/white.py,cover deleted file mode 100644 index bbd8d428..00000000 --- a/test/farm/annotate/gold_v24/white.py,cover +++ /dev/null @@ -1,33 +0,0 @@ - # A test case sent to me by Steve White - -> def f(self): -! if self==1: -! pass -! elif self.m('fred'): -! pass -! elif (g==1) and (b==2): -! pass -! elif self.m('fred')==True: -! pass -! elif ((g==1) and (b==2))==True: -! pass -> else: -! pass - -> def g(x): -> if x == 1: -> a = 1 -! else: -! a = 2 - -> g(1) - -> def h(x): -- if 0: #pragma: no cover -- pass -> if x == 1: -! a = 1 -> else: -> a = 2 - -> h(2) diff --git a/test/farm/annotate/run.py b/test/farm/annotate/run.py deleted file mode 100644 index c645f21c..00000000 --- a/test/farm/annotate/run.py +++ /dev/null @@ -1,7 +0,0 @@ -copy("src", "out") -run(""" - coverage -e -x white.py - coverage -a white.py - """, rundir="out") -compare("out", "gold", "*,cover") -clean("out") diff --git a/test/farm/annotate/run_multi.py b/test/farm/annotate/run_multi.py deleted file mode 100644 index 4e8252ed..00000000 --- a/test/farm/annotate/run_multi.py +++ /dev/null @@ -1,7 +0,0 @@ -copy("src", "out_multi") -run(""" - coverage -e -x multi.py - coverage -a - """, rundir="out_multi") -compare("out_multi", "gold_multi", "*,cover") -clean("out_multi") diff --git a/test/farm/annotate/src/a/__init__.py b/test/farm/annotate/src/a/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/farm/annotate/src/a/a.py b/test/farm/annotate/src/a/a.py deleted file mode 100644 index c2583d1e..00000000 --- a/test/farm/annotate/src/a/a.py +++ /dev/null @@ -1,5 +0,0 @@ -def a(x): - if x == 1: - print("x is 1") - else: - print("x is not 1") diff --git a/test/farm/annotate/src/b/__init__.py b/test/farm/annotate/src/b/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/farm/annotate/src/b/b.py b/test/farm/annotate/src/b/b.py deleted file mode 100644 index 625a5490..00000000 --- a/test/farm/annotate/src/b/b.py +++ /dev/null @@ -1,3 +0,0 @@ -def b(x): - msg = "x is %s" % x - print(msg) diff --git a/test/farm/annotate/src/multi.py b/test/farm/annotate/src/multi.py deleted file mode 100644 index 19a6200c..00000000 --- a/test/farm/annotate/src/multi.py +++ /dev/null @@ -1,5 +0,0 @@ -import a.a -import b.b - -a.a.a(1) -b.b.b(2) diff --git a/test/farm/annotate/src/white.py b/test/farm/annotate/src/white.py deleted file mode 100644 index ecbbd25a..00000000 --- a/test/farm/annotate/src/white.py +++ /dev/null @@ -1,33 +0,0 @@ -# A test case sent to me by Steve White - -def f(self): - if self==1: - pass - elif self.m('fred'): - pass - elif (g==1) and (b==2): - pass - elif self.m('fred')==True: - pass - elif ((g==1) and (b==2))==True: - pass - else: - pass - -def g(x): - if x == 1: - a = 1 - else: - a = 2 - -g(1) - -def h(x): - if 0: #pragma: no cover - pass - if x == 1: - a = 1 - else: - a = 2 - -h(2) diff --git a/test/farm/html/gold_a/a.html b/test/farm/html/gold_a/a.html deleted file mode 100644 index c794525e..00000000 --- a/test/farm/html/gold_a/a.html +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - Coverage for a: 67% - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

- -
-

# A test file for HTML reporting by coverage. 

-

 

-

if 1 < 2: 

-

    # Needed a < to look at HTML entities. 

-

    a = 3 

-

else: 

-

    a = 4 

- -
-
- - - - - diff --git a/test/farm/html/gold_a/index.html b/test/farm/html/gold_a/index.html deleted file mode 100644 index a821e9df..00000000 --- a/test/farm/html/gold_a/index.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - Coverage report - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- n - s - m - x - - c   change column sorting -

-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Modulestatementsmissingexcludedcoverage
Total31067%
a31067%
-
- - - - - diff --git a/test/farm/html/gold_b_branch/b.html b/test/farm/html/gold_b_branch/b.html deleted file mode 100644 index 0258ad13..00000000 --- a/test/farm/html/gold_b_branch/b.html +++ /dev/null @@ -1,139 +0,0 @@ - - - - - - - - Coverage for b: 76% - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

-

9

-

10

-

11

-

12

-

13

-

14

-

15

-

16

-

17

-

18

-

19

-

20

-

21

-

22

-

23

-

24

-

25

-

26

-

27

-

28

- -
-

# A test file for HTML reporting by coverage. 

-

 

-

def one(x): 

-

    # This will be a branch that misses the else. 

-

8    if x < 2: 

-

        a = 3 

-

    else: 

-

        a = 4 

-

 

-

one(1) 

-

 

-

def two(x): 

-

    # A missed else that branches to "exit" 

-

exit    if x: 

-

        a = 5 

-

 

-

two(1) 

-

 

-

def three_way(): 

-

    # for-else can be a three-way branch. 

-

25   26    for i in range(10): 

-

        if i == 3: 

-

            break 

-

    else: 

-

        return 23 

-

    return 17 

-

 

-

three_way() 

- -
-
- - - - - diff --git a/test/farm/html/gold_b_branch/index.html b/test/farm/html/gold_b_branch/index.html deleted file mode 100644 index cb6ffa17..00000000 --- a/test/farm/html/gold_b_branch/index.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - - Coverage report - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- n - s - m - x - - b - p - - c   change column sorting -

-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Modulestatementsmissingexcludedbranchespartialcoverage
Total16209476%
b16209476%
-
- - - - - diff --git a/test/farm/html/gold_bom/bom.html b/test/farm/html/gold_bom/bom.html deleted file mode 100644 index 1d61a62c..00000000 --- a/test/farm/html/gold_bom/bom.html +++ /dev/null @@ -1,104 +0,0 @@ - - - - - - - - Coverage for bom: 71% - - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

-

9

-

10

-

11

- -
-

# A python source file in utf-8, with BOM 

-

math = "3×4 = 12, ÷2 = 6±0" 

-

 

-

import sys 

-

 

-

if sys.version_info >= (3, 0): 

-

    assert len(math) == 18 

-

    assert len(math.encode('utf-8')) == 21 

-

else: 

-

    assert len(math) == 21 

-

    assert len(math.decode('utf-8')) == 18 

- -
-
- - - - - diff --git a/test/farm/html/gold_bom/index.html b/test/farm/html/gold_bom/index.html deleted file mode 100644 index 8653b23e..00000000 --- a/test/farm/html/gold_bom/index.html +++ /dev/null @@ -1,90 +0,0 @@ - - - - - Coverage report - - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- n - s - m - x - - c   change column sorting -

-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Modulestatementsmissingexcludedcoverage
Total72071%
bom72071%
-
- - - - - diff --git a/test/farm/html/gold_isolatin1/index.html b/test/farm/html/gold_isolatin1/index.html deleted file mode 100644 index 6e9f3ca7..00000000 --- a/test/farm/html/gold_isolatin1/index.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - Coverage report - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- n - s - m - x - - c   change column sorting -

-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Modulestatementsmissingexcludedcoverage
Total200100%
isolatin1200100%
-
- - - - - diff --git a/test/farm/html/gold_isolatin1/isolatin1.html b/test/farm/html/gold_isolatin1/isolatin1.html deleted file mode 100644 index 276a6c25..00000000 --- a/test/farm/html/gold_isolatin1/isolatin1.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - Coverage for isolatin1: 100% - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

-

3

-

4

-

5

- -
-

# A python source file in another encoding. 

-

# -*- coding: iso8859-1 -*- 

-

 

-

math = "3×4 = 12, ÷2 = 6±0" 

-

assert len(math) == 18 

- -
-
- - - - - diff --git a/test/farm/html/gold_omit_1/index.html b/test/farm/html/gold_omit_1/index.html deleted file mode 100644 index 5616d012..00000000 --- a/test/farm/html/gold_omit_1/index.html +++ /dev/null @@ -1,116 +0,0 @@ - - - - - Coverage report - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- n - s - m - x - - c   change column sorting -

-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Modulestatementsmissingexcludedcoverage
Total1400100%
m1200100%
m2200100%
m3200100%
main800100%
-
- - - - - diff --git a/test/farm/html/gold_omit_1/m1.html b/test/farm/html/gold_omit_1/m1.html deleted file mode 100644 index 62ba1e0a..00000000 --- a/test/farm/html/gold_omit_1/m1.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - Coverage for m1: 100% - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

- -
-

m1a = 1 

-

m1b = 2 

- -
-
- - - - - diff --git a/test/farm/html/gold_omit_1/m2.html b/test/farm/html/gold_omit_1/m2.html deleted file mode 100644 index d75a5ba0..00000000 --- a/test/farm/html/gold_omit_1/m2.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - Coverage for m2: 100% - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

- -
-

m2a = 1 

-

m2b = 2 

- -
-
- - - - - diff --git a/test/farm/html/gold_omit_1/m3.html b/test/farm/html/gold_omit_1/m3.html deleted file mode 100644 index bd99138a..00000000 --- a/test/farm/html/gold_omit_1/m3.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - Coverage for m3: 100% - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

- -
-

m3a = 1 

-

m3b = 2 

- -
-
- - - - - diff --git a/test/farm/html/gold_omit_1/main.html b/test/farm/html/gold_omit_1/main.html deleted file mode 100644 index 03948718..00000000 --- a/test/farm/html/gold_omit_1/main.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - Coverage for main: 100% - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

-

9

-

10

- -
-

import m1 

-

import m2 

-

import m3 

-

 

-

a = 5 

-

b = 6 

-

 

-

assert m1.m1a == 1 

-

assert m2.m2a == 1 

-

assert m3.m3a == 1 

- -
-
- - - - - diff --git a/test/farm/html/gold_omit_2/index.html b/test/farm/html/gold_omit_2/index.html deleted file mode 100644 index 3ce5bade..00000000 --- a/test/farm/html/gold_omit_2/index.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - Coverage report - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- n - s - m - x - - c   change column sorting -

-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Modulestatementsmissingexcludedcoverage
Total1200100%
m2200100%
m3200100%
main800100%
-
- - - - - diff --git a/test/farm/html/gold_omit_2/m2.html b/test/farm/html/gold_omit_2/m2.html deleted file mode 100644 index d75a5ba0..00000000 --- a/test/farm/html/gold_omit_2/m2.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - Coverage for m2: 100% - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

- -
-

m2a = 1 

-

m2b = 2 

- -
-
- - - - - diff --git a/test/farm/html/gold_omit_2/m3.html b/test/farm/html/gold_omit_2/m3.html deleted file mode 100644 index bd99138a..00000000 --- a/test/farm/html/gold_omit_2/m3.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - Coverage for m3: 100% - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

- -
-

m3a = 1 

-

m3b = 2 

- -
-
- - - - - diff --git a/test/farm/html/gold_omit_2/main.html b/test/farm/html/gold_omit_2/main.html deleted file mode 100644 index 03948718..00000000 --- a/test/farm/html/gold_omit_2/main.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - Coverage for main: 100% - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

-

9

-

10

- -
-

import m1 

-

import m2 

-

import m3 

-

 

-

a = 5 

-

b = 6 

-

 

-

assert m1.m1a == 1 

-

assert m2.m2a == 1 

-

assert m3.m3a == 1 

- -
-
- - - - - diff --git a/test/farm/html/gold_omit_3/index.html b/test/farm/html/gold_omit_3/index.html deleted file mode 100644 index fb826bf5..00000000 --- a/test/farm/html/gold_omit_3/index.html +++ /dev/null @@ -1,98 +0,0 @@ - - - - - Coverage report - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- n - s - m - x - - c   change column sorting -

-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Modulestatementsmissingexcludedcoverage
Total1000100%
m3200100%
main800100%
-
- - - - - diff --git a/test/farm/html/gold_omit_3/m3.html b/test/farm/html/gold_omit_3/m3.html deleted file mode 100644 index bd99138a..00000000 --- a/test/farm/html/gold_omit_3/m3.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - Coverage for m3: 100% - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

- -
-

m3a = 1 

-

m3b = 2 

- -
-
- - - - - diff --git a/test/farm/html/gold_omit_3/main.html b/test/farm/html/gold_omit_3/main.html deleted file mode 100644 index 03948718..00000000 --- a/test/farm/html/gold_omit_3/main.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - Coverage for main: 100% - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

-

9

-

10

- -
-

import m1 

-

import m2 

-

import m3 

-

 

-

a = 5 

-

b = 6 

-

 

-

assert m1.m1a == 1 

-

assert m2.m2a == 1 

-

assert m3.m3a == 1 

- -
-
- - - - - diff --git a/test/farm/html/gold_omit_4/index.html b/test/farm/html/gold_omit_4/index.html deleted file mode 100644 index e437cf10..00000000 --- a/test/farm/html/gold_omit_4/index.html +++ /dev/null @@ -1,107 +0,0 @@ - - - - - Coverage report - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- n - s - m - x - - c   change column sorting -

-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Modulestatementsmissingexcludedcoverage
Total1200100%
m1200100%
m3200100%
main800100%
-
- - - - - diff --git a/test/farm/html/gold_omit_4/m1.html b/test/farm/html/gold_omit_4/m1.html deleted file mode 100644 index 62ba1e0a..00000000 --- a/test/farm/html/gold_omit_4/m1.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - Coverage for m1: 100% - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

- -
-

m1a = 1 

-

m1b = 2 

- -
-
- - - - - diff --git a/test/farm/html/gold_omit_4/m3.html b/test/farm/html/gold_omit_4/m3.html deleted file mode 100644 index bd99138a..00000000 --- a/test/farm/html/gold_omit_4/m3.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - Coverage for m3: 100% - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

- -
-

m3a = 1 

-

m3b = 2 

- -
-
- - - - - diff --git a/test/farm/html/gold_omit_4/main.html b/test/farm/html/gold_omit_4/main.html deleted file mode 100644 index 03948718..00000000 --- a/test/farm/html/gold_omit_4/main.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - Coverage for main: 100% - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

-

9

-

10

- -
-

import m1 

-

import m2 

-

import m3 

-

 

-

a = 5 

-

b = 6 

-

 

-

assert m1.m1a == 1 

-

assert m2.m2a == 1 

-

assert m3.m3a == 1 

- -
-
- - - - - diff --git a/test/farm/html/gold_omit_5/index.html b/test/farm/html/gold_omit_5/index.html deleted file mode 100644 index 4bde6b73..00000000 --- a/test/farm/html/gold_omit_5/index.html +++ /dev/null @@ -1,98 +0,0 @@ - - - - - Coverage report - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- n - s - m - x - - c   change column sorting -

-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Modulestatementsmissingexcludedcoverage
Total1000100%
m1200100%
main800100%
-
- - - - - diff --git a/test/farm/html/gold_omit_5/m1.html b/test/farm/html/gold_omit_5/m1.html deleted file mode 100644 index 62ba1e0a..00000000 --- a/test/farm/html/gold_omit_5/m1.html +++ /dev/null @@ -1,85 +0,0 @@ - - - - - - - - Coverage for m1: 100% - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

- -
-

m1a = 1 

-

m1b = 2 

- -
-
- - - - - diff --git a/test/farm/html/gold_omit_5/main.html b/test/farm/html/gold_omit_5/main.html deleted file mode 100644 index 03948718..00000000 --- a/test/farm/html/gold_omit_5/main.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - - - - - Coverage for main: 100% - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

-

9

-

10

- -
-

import m1 

-

import m2 

-

import m3 

-

 

-

a = 5 

-

b = 6 

-

 

-

assert m1.m1a == 1 

-

assert m2.m2a == 1 

-

assert m3.m3a == 1 

- -
-
- - - - - diff --git a/test/farm/html/gold_other/blah_blah_other.html b/test/farm/html/gold_other/blah_blah_other.html deleted file mode 100644 index ab5ae371..00000000 --- a/test/farm/html/gold_other/blah_blah_other.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - - - - Coverage for /home/ned/coverage/trunk/test/farm/html/othersrc/other: 100% - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

-

3

-

4

- -
-

# A file in another directory.  We're checking that it ends up in the 

-

# HTML report. 

-

 

-

print("This is the other src!") 

- -
-
- - - - - diff --git a/test/farm/html/gold_other/here.html b/test/farm/html/gold_other/here.html deleted file mode 100644 index 1da5bcd6..00000000 --- a/test/farm/html/gold_other/here.html +++ /dev/null @@ -1,97 +0,0 @@ - - - - - - - - Coverage for here: 75% - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

- -
-

# A test file for HTML reporting by coverage. 

-

 

-

import other 

-

 

-

if 1 < 2: 

-

    h = 3 

-

else: 

-

    h = 4 

- -
-
- - - - - diff --git a/test/farm/html/gold_other/index.html b/test/farm/html/gold_other/index.html deleted file mode 100644 index 7665cfe4..00000000 --- a/test/farm/html/gold_other/index.html +++ /dev/null @@ -1,98 +0,0 @@ - - - - - Coverage report - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- n - s - m - x - - c   change column sorting -

-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Modulestatementsmissingexcludedcoverage
Total51080%
/home/ned/coverage/trunk/test/farm/html/othersrc/other100100%
here41075%
-
- - - - - diff --git a/test/farm/html/gold_partial/index.html b/test/farm/html/gold_partial/index.html deleted file mode 100644 index 5556150a..00000000 --- a/test/farm/html/gold_partial/index.html +++ /dev/null @@ -1,101 +0,0 @@ - - - - - Coverage report - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- n - s - m - x - - b - p - - c   change column sorting -

-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Modulestatementsmissingexcludedbranchespartialcoverage
Total80060100%
partial80060100%
-
- - - - - diff --git a/test/farm/html/gold_partial/partial.html b/test/farm/html/gold_partial/partial.html deleted file mode 100644 index b9640ce4..00000000 --- a/test/farm/html/gold_partial/partial.html +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - - Coverage for partial: 100% - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

-

8

-

9

-

10

-

11

-

12

-

13

-

14

-

15

-

16

-

17

-

18

-

19

- -
-

# partial branches 

-

 

-

a = 3 

-

 

-

while True: 

-

    break 

-

 

-

while 1: 

-

    break 

-

 

-

while a:        # pragma: no branch 

-

    break 

-

 

-

if 0: 

-

    never_happen() 

-

 

-

if 1: 

-

    a = 13 

-

 

- -
-
- - - - - diff --git a/test/farm/html/gold_styled/a.html b/test/farm/html/gold_styled/a.html deleted file mode 100644 index c794525e..00000000 --- a/test/farm/html/gold_styled/a.html +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - - - Coverage for a: 67% - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

-

3

-

4

-

5

-

6

-

7

- -
-

# A test file for HTML reporting by coverage. 

-

 

-

if 1 < 2: 

-

    # Needed a < to look at HTML entities. 

-

    a = 3 

-

else: 

-

    a = 4 

- -
-
- - - - - diff --git a/test/farm/html/gold_styled/extra.css b/test/farm/html/gold_styled/extra.css deleted file mode 100644 index 46c41fcd..00000000 --- a/test/farm/html/gold_styled/extra.css +++ /dev/null @@ -1 +0,0 @@ -/* Doesn't matter what goes in here, it gets copied. */ diff --git a/test/farm/html/gold_styled/index.html b/test/farm/html/gold_styled/index.html deleted file mode 100644 index a821e9df..00000000 --- a/test/farm/html/gold_styled/index.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - Coverage report - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- n - s - m - x - - c   change column sorting -

-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Modulestatementsmissingexcludedcoverage
Total31067%
a31067%
-
- - - - - diff --git a/test/farm/html/gold_styled/style.css b/test/farm/html/gold_styled/style.css deleted file mode 100644 index c40357b8..00000000 --- a/test/farm/html/gold_styled/style.css +++ /dev/null @@ -1,275 +0,0 @@ -/* CSS styles for Coverage. */ -/* Page-wide styles */ -html, body, h1, h2, h3, p, td, th { - margin: 0; - padding: 0; - border: 0; - outline: 0; - font-weight: inherit; - font-style: inherit; - font-size: 100%; - font-family: inherit; - vertical-align: baseline; - } - -/* Set baseline grid to 16 pt. */ -body { - font-family: georgia, serif; - font-size: 1em; - } - -html>body { - font-size: 16px; - } - -/* Set base font size to 12/16 */ -p { - font-size: .75em; /* 12/16 */ - line-height: 1.3333em; /* 16/12 */ - } - -table { - border-collapse: collapse; - } - -a.nav { - text-decoration: none; - color: inherit; - } -a.nav:hover { - text-decoration: underline; - color: inherit; - } - -/* Page structure */ -#header { - background: #f8f8f8; - width: 100%; - border-bottom: 1px solid #eee; - } - -#source { - padding: 1em; - font-family: "courier new", monospace; - } - -#indexfile #footer { - margin: 1em 3em; - } - -#pyfile #footer { - margin: 1em 1em; - } - -#footer .content { - padding: 0; - font-size: 85%; - font-family: verdana, sans-serif; - color: #666666; - font-style: italic; - } - -#index { - margin: 1em 0 0 3em; - } - -/* Header styles */ -#header .content { - padding: 1em 3em; - } - -h1 { - font-size: 1.25em; -} - -h2.stats { - margin-top: .5em; - font-size: 1em; -} -.stats span { - border: 1px solid; - padding: .1em .25em; - margin: 0 .1em; - cursor: pointer; - border-color: #999 #ccc #ccc #999; -} -.stats span.hide_run, .stats span.hide_exc, -.stats span.hide_mis, .stats span.hide_par, -.stats span.par.hide_run.hide_par { - border-color: #ccc #999 #999 #ccc; -} -.stats span.par.hide_run { - border-color: #999 #ccc #ccc #999; -} - -/* Help panel */ -#keyboard_icon { - float: right; - cursor: pointer; -} - -.help_panel { - position: absolute; - background: #ffc; - padding: .5em; - border: 1px solid #883; - display: none; -} - -#indexfile .help_panel { - width: 20em; height: 4em; -} - -#pyfile .help_panel { - width: 16em; height: 8em; -} - -.help_panel .legend { - font-style: italic; - margin-bottom: 1em; -} - -#panel_icon { - float: right; - cursor: pointer; -} - -.keyhelp { - margin: .75em; -} - -.keyhelp .key { - border: 1px solid black; - border-color: #888 #333 #333 #888; - padding: .1em .35em; - font-family: monospace; - font-weight: bold; - background: #eee; -} - -/* Source file styles */ -.linenos p { - text-align: right; - margin: 0; - padding: 0 .5em; - color: #999999; - font-family: verdana, sans-serif; - font-size: .625em; /* 10/16 */ - line-height: 1.6em; /* 16/10 */ - } -.linenos p.highlight { - background: #ffdd00; - } -.linenos p a { - text-decoration: none; - color: #999999; - } -.linenos p a:hover { - text-decoration: underline; - color: #999999; - } - -td.text { - width: 100%; - } -.text p { - margin: 0; - padding: 0 0 0 .5em; - border-left: 2px solid #ffffff; - white-space: nowrap; - } - -.text p.mis { - background: #ffdddd; - border-left: 2px solid #ff0000; - } -.text p.run, .text p.run.hide_par { - background: #ddffdd; - border-left: 2px solid #00ff00; - } -.text p.exc { - background: #eeeeee; - border-left: 2px solid #808080; - } -.text p.par, .text p.par.hide_run { - background: #ffffaa; - border-left: 2px solid #eeee99; - } -.text p.hide_run, .text p.hide_exc, .text p.hide_mis, .text p.hide_par, -.text p.hide_run.hide_par { - background: inherit; - } - -.text span.annotate { - font-family: georgia; - font-style: italic; - color: #666; - float: right; - padding-right: .5em; - } -.text p.hide_par span.annotate { - display: none; - } - -/* Syntax coloring */ -.text .com { - color: green; - font-style: italic; - line-height: 1px; - } -.text .key { - font-weight: bold; - line-height: 1px; - } -.text .str { - color: #000080; - } - -/* index styles */ -#index td, #index th { - text-align: right; - width: 5em; - padding: .25em .5em; - border-bottom: 1px solid #eee; - } -#index th { - font-style: italic; - color: #333; - border-bottom: 1px solid #ccc; - cursor: pointer; - } -#index th:hover { - background: #eee; - border-bottom: 1px solid #999; - } -#index td.left, #index th.left { - padding-left: 0; - } -#index td.right, #index th.right { - padding-right: 0; - } -#index th.headerSortDown, #index th.headerSortUp { - border-bottom: 1px solid #000; - } -#index td.name, #index th.name { - text-align: left; - width: auto; - } -#index td.name a { - text-decoration: none; - color: #000; - } -#index td.name a:hover { - text-decoration: underline; - color: #000; - } -#index tr.total { - } -#index tr.total td { - font-weight: bold; - border-top: 1px solid #ccc; - border-bottom: none; - } -#index tr.file:hover { - background: #eeeeee; - } diff --git a/test/farm/html/gold_unicode/index.html b/test/farm/html/gold_unicode/index.html deleted file mode 100644 index 9ba1bb39..00000000 --- a/test/farm/html/gold_unicode/index.html +++ /dev/null @@ -1,89 +0,0 @@ - - - - - Coverage report - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- n - s - m - x - - c   change column sorting -

-
-
- -
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Modulestatementsmissingexcludedcoverage
Total100100%
unicode100100%
-
- - - - - diff --git a/test/farm/html/gold_unicode/unicode.html b/test/farm/html/gold_unicode/unicode.html deleted file mode 100644 index 518a59a1..00000000 --- a/test/farm/html/gold_unicode/unicode.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - - - - Coverage for unicode: 100% - - - - - - - - - - - -
- -

Hot-keys on this page

-
-

- r - m - x - p   toggle line displays -

-

- j - k   next/prev highlighted chunk -

-

- 0   (zero) top of page -

-

- 1   (one) first highlighted chunk -

-
-
- -
- - - - - -
-

1

-

2

-

3

-

4

-

5

- -
-

# A python source file with exotic characters 

-

# -*- coding: utf-8 -*- 

-

 

-

upside_down = "ʎd˙ǝbɐɹǝʌoɔ" 

-

surrogate = "db40,dd00: x�� 󠄀" 

- -
-
- - - - - diff --git a/test/farm/html/gold_x_xml/coverage.xml b/test/farm/html/gold_x_xml/coverage.xml deleted file mode 100644 index 912112f2..00000000 --- a/test/farm/html/gold_x_xml/coverage.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/test/farm/html/gold_y_xml_branch/coverage.xml b/test/farm/html/gold_y_xml_branch/coverage.xml deleted file mode 100644 index ecbe0073..00000000 --- a/test/farm/html/gold_y_xml_branch/coverage.xml +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - diff --git a/test/farm/html/othersrc/other.py b/test/farm/html/othersrc/other.py deleted file mode 100644 index 6d3f86e7..00000000 --- a/test/farm/html/othersrc/other.py +++ /dev/null @@ -1,4 +0,0 @@ -# A file in another directory. We're checking that it ends up in the -# HTML report. - -print("This is the other src!") diff --git a/test/farm/html/run_a.py b/test/farm/html/run_a.py deleted file mode 100644 index 59cc1703..00000000 --- a/test/farm/html/run_a.py +++ /dev/null @@ -1,25 +0,0 @@ -def html_it(): - """Run coverage and make an HTML report for a.""" - import coverage - cov = coverage.coverage() - cov.start() - import a # pragma: nested - cov.stop() # pragma: nested - cov.html_report(a, directory="../html_a") - -runfunc(html_it, rundir="src") - -# HTML files will change often. Check that the sizes are reasonable, -# and check that certain key strings are in the output. -compare("gold_a", "html_a", size_within=10, file_pattern="*.html") -contains("html_a/a.html", - "if 1 < 2", - "    a = 3", - "67%" - ) -contains("html_a/index.html", - "a", - "67%" - ) - -clean("html_a") diff --git a/test/farm/html/run_a_xml_1.py b/test/farm/html/run_a_xml_1.py deleted file mode 100644 index 3d187023..00000000 --- a/test/farm/html/run_a_xml_1.py +++ /dev/null @@ -1,21 +0,0 @@ -def html_it(): - """Run coverage and make an XML report for a.""" - import coverage - cov = coverage.coverage() - cov.start() - import a # pragma: nested - cov.stop() # pragma: nested - cov.xml_report(a, outfile="../xml_1/coverage.xml") - -import os -if not os.path.exists("xml_1"): - os.makedirs("xml_1") - -runfunc(html_it, rundir="src") - -compare("gold_x_xml", "xml_1", scrubs=[ - (r' timestamp="\d+"', ' timestamp="TIMESTAMP"'), - (r' version="[-.\w]+"', ' version="VERSION"'), - (r'/code/coverage/?[-.\w]*', '/code/coverage/VER'), - ]) -clean("xml_1") diff --git a/test/farm/html/run_a_xml_2.py b/test/farm/html/run_a_xml_2.py deleted file mode 100644 index 53691ead..00000000 --- a/test/farm/html/run_a_xml_2.py +++ /dev/null @@ -1,21 +0,0 @@ -def html_it(): - """Run coverage and make an XML report for a.""" - import coverage - cov = coverage.coverage(config_file="run_a_xml_2.ini") - cov.start() - import a # pragma: nested - cov.stop() # pragma: nested - cov.xml_report(a) - -import os -if not os.path.exists("xml_2"): - os.makedirs("xml_2") - -runfunc(html_it, rundir="src") - -compare("gold_x_xml", "xml_2", scrubs=[ - (r' timestamp="\d+"', ' timestamp="TIMESTAMP"'), - (r' version="[-.\w]+"', ' version="VERSION"'), - (r'/code/coverage/?[-.\w]*', '/code/coverage/VER'), - ]) -clean("xml_2") diff --git a/test/farm/html/run_b_branch.py b/test/farm/html/run_b_branch.py deleted file mode 100644 index d0955a2a..00000000 --- a/test/farm/html/run_b_branch.py +++ /dev/null @@ -1,28 +0,0 @@ -def html_it(): - """Run coverage with branches and make an HTML report for b.""" - import coverage - cov = coverage.coverage(branch=True) - cov.start() - import b # pragma: nested - cov.stop() # pragma: nested - cov.html_report(b, directory="../html_b_branch") - -runfunc(html_it, rundir="src") - -# HTML files will change often. Check that the sizes are reasonable, -# and check that certain key strings are in the output. -compare("gold_b_branch", "html_b_branch", size_within=10, file_pattern="*.html") -contains("html_b_branch/b.html", - "if x < 2", - "    a = 3", - "70%", - "8", - "exit", - "23   25", - ) -contains("html_b_branch/index.html", - "b", - "70%" - ) - -clean("html_b_branch") diff --git a/test/farm/html/run_bom.py b/test/farm/html/run_bom.py deleted file mode 100644 index c35079be..00000000 --- a/test/farm/html/run_bom.py +++ /dev/null @@ -1,21 +0,0 @@ -import sys - -def html_it(): - """Run coverage and make an HTML report for bom.py.""" - import coverage - cov = coverage.coverage() - cov.start() - import bom # pragma: nested - cov.stop() # pragma: nested - cov.html_report(bom, directory="../html_bom") - -runfunc(html_it, rundir="src") - -# HTML files will change often. Check that the sizes are reasonable, -# and check that certain key strings are in the output. -compare("gold_bom", "html_bom", size_within=10, file_pattern="*.html") -contains("html_bom/bom.html", - ""3×4 = 12, ÷2 = 6±0"", - ) - -clean("html_bom") diff --git a/test/farm/html/run_isolatin1.py b/test/farm/html/run_isolatin1.py deleted file mode 100644 index 063e6e00..00000000 --- a/test/farm/html/run_isolatin1.py +++ /dev/null @@ -1,21 +0,0 @@ -import sys - -def html_it(): - """Run coverage and make an HTML report for isolatin1.py.""" - import coverage - cov = coverage.coverage() - cov.start() - import isolatin1 # pragma: nested - cov.stop() # pragma: nested - cov.html_report(isolatin1, directory="../html_isolatin1") - -runfunc(html_it, rundir="src") - -# HTML files will change often. Check that the sizes are reasonable, -# and check that certain key strings are in the output. -compare("gold_isolatin1", "html_isolatin1", size_within=10, file_pattern="*.html") -contains("html_isolatin1/isolatin1.html", - ""3×4 = 12, ÷2 = 6±0"", - ) - -clean("html_isolatin1") diff --git a/test/farm/html/run_omit_1.py b/test/farm/html/run_omit_1.py deleted file mode 100644 index a5556af2..00000000 --- a/test/farm/html/run_omit_1.py +++ /dev/null @@ -1,12 +0,0 @@ -def html_it(): - """Run coverage and make an HTML report for main.""" - import coverage - cov = coverage.coverage() - cov.start() - import main # pragma: nested - cov.stop() # pragma: nested - cov.html_report(directory="../html_omit_1") - -runfunc(html_it, rundir="src") -compare("gold_omit_1", "html_omit_1", size_within=10, file_pattern="*.html") -clean("html_omit_1") diff --git a/test/farm/html/run_omit_2.py b/test/farm/html/run_omit_2.py deleted file mode 100644 index 19f0ebdc..00000000 --- a/test/farm/html/run_omit_2.py +++ /dev/null @@ -1,12 +0,0 @@ -def html_it(): - """Run coverage and make an HTML report for main.""" - import coverage - cov = coverage.coverage() - cov.start() - import main # pragma: nested - cov.stop() # pragma: nested - cov.html_report(directory="../html_omit_2", omit=["m1.py"]) - -runfunc(html_it, rundir="src") -compare("gold_omit_2", "html_omit_2", size_within=10, file_pattern="*.html") -clean("html_omit_2") diff --git a/test/farm/html/run_omit_3.py b/test/farm/html/run_omit_3.py deleted file mode 100644 index 87ab8c32..00000000 --- a/test/farm/html/run_omit_3.py +++ /dev/null @@ -1,12 +0,0 @@ -def html_it(): - """Run coverage and make an HTML report for main.""" - import coverage - cov = coverage.coverage() - cov.start() - import main # pragma: nested - cov.stop() # pragma: nested - cov.html_report(directory="../html_omit_3", omit=["m1.py", "m2.py"]) - -runfunc(html_it, rundir="src") -compare("gold_omit_3", "html_omit_3", size_within=10, file_pattern="*.html") -clean("html_omit_3") diff --git a/test/farm/html/run_omit_4.py b/test/farm/html/run_omit_4.py deleted file mode 100644 index ede223f8..00000000 --- a/test/farm/html/run_omit_4.py +++ /dev/null @@ -1,12 +0,0 @@ -def html_it(): - """Run coverage and make an HTML report for main.""" - import coverage - cov = coverage.coverage(config_file="omit4.ini") - cov.start() - import main # pragma: nested - cov.stop() # pragma: nested - cov.html_report(directory="../html_omit_4") - -runfunc(html_it, rundir="src") -compare("gold_omit_4", "html_omit_4", size_within=10, file_pattern="*.html") -clean("html_omit_4") diff --git a/test/farm/html/run_omit_5.py b/test/farm/html/run_omit_5.py deleted file mode 100644 index 8da51994..00000000 --- a/test/farm/html/run_omit_5.py +++ /dev/null @@ -1,12 +0,0 @@ -def html_it(): - """Run coverage and make an HTML report for main.""" - import coverage - cov = coverage.coverage(config_file="omit5.ini") - cov.start() - import main # pragma: nested - cov.stop() # pragma: nested - cov.html_report() - -runfunc(html_it, rundir="src") -compare("gold_omit_5", "html_omit_5", size_within=10, file_pattern="*.html") -clean("html_omit_5") diff --git a/test/farm/html/run_other.py b/test/farm/html/run_other.py deleted file mode 100644 index 72bb3ec1..00000000 --- a/test/farm/html/run_other.py +++ /dev/null @@ -1,26 +0,0 @@ -def html_it(): - """Run coverage and make an HTML report for everything.""" - import coverage - cov = coverage.coverage() - cov.start() - import here # pragma: nested - cov.stop() # pragma: nested - cov.html_report(directory="../html_other") - -runfunc(html_it, rundir="src", addtopath="../othersrc") - -# Different platforms will name the "other" file differently. Rename it -import os, glob - -for p in glob.glob("html_other/*_other.html"): - os.rename(p, "html_other/blah_blah_other.html") - -# HTML files will change often. Check that the sizes are reasonable, -# and check that certain key strings are in the output. -compare("gold_other", "html_other", size_within=10, file_pattern="*.html") -contains("html_other/index.html", - "here", - "other.html'>", "other", - ) - -clean("html_other") diff --git a/test/farm/html/run_partial.py b/test/farm/html/run_partial.py deleted file mode 100644 index 41e6ba96..00000000 --- a/test/farm/html/run_partial.py +++ /dev/null @@ -1,32 +0,0 @@ -import sys - -def html_it(): - """Run coverage and make an HTML report for partial.""" - import coverage - cov = coverage.coverage(branch=True) - cov.start() - import partial # pragma: nested - cov.stop() # pragma: nested - cov.html_report(partial, directory="../html_partial") - -runfunc(html_it, rundir="src") - -# HTML files will change often. Check that the sizes are reasonable, -# and check that certain key strings are in the output. -compare("gold_partial", "html_partial", size_within=10, file_pattern="*.html") -contains("html_partial/partial.html", - "

", - "

", - "

", - # The "if 0" and "if 1" statements are optimized away. - "

", - ) -contains("html_partial/index.html", - "partial", - ) -if sys.version_info >= (2, 4): - contains("html_partial/index.html", - "100%" - ) - -clean("html_partial") diff --git a/test/farm/html/run_styled.py b/test/farm/html/run_styled.py deleted file mode 100644 index ac538ff5..00000000 --- a/test/farm/html/run_styled.py +++ /dev/null @@ -1,28 +0,0 @@ -def html_it(): - """Run coverage and make an HTML report for a.""" - import coverage - cov = coverage.coverage() - cov.start() - import a # pragma: nested - cov.stop() # pragma: nested - cov.html_report(a, directory="../html_styled", extra_css="extra.css") - -runfunc(html_it, rundir="src") - -# HTML files will change often. Check that the sizes are reasonable, -# and check that certain key strings are in the output. -compare("gold_styled", "html_styled", size_within=10, file_pattern="*.html") -compare("gold_styled", "html_styled", size_within=10, file_pattern="*.css") -contains("html_styled/a.html", - "", - "if 1 < 2", - "    a = 3", - "67%" - ) -contains("html_styled/index.html", - "", - "a", - "67%" - ) - -clean("html_styled") diff --git a/test/farm/html/run_tabbed.py b/test/farm/html/run_tabbed.py deleted file mode 100644 index 0e9b5278..00000000 --- a/test/farm/html/run_tabbed.py +++ /dev/null @@ -1,24 +0,0 @@ -def html_it(): - """Run coverage and make an HTML report for tabbed.""" - import coverage - cov = coverage.coverage() - cov.start() - import tabbed # pragma: nested - cov.stop() # pragma: nested - cov.html_report(tabbed, directory="../html_tabbed") - -runfunc(html_it, rundir="src") - -# Editors like to change things, make sure our source file still has tabs. -contains("src/tabbed.py", "\tif x:\t\t\t\t\t# look nice") - -contains("html_tabbed/tabbed.html", - ">        if " - "x:" - "                    " - "               " - "# look nice" - ) - -doesnt_contain("html_tabbed/tabbed.html", "\t") -clean("html_tabbed") diff --git a/test/farm/html/run_unicode.py b/test/farm/html/run_unicode.py deleted file mode 100644 index cef26ee5..00000000 --- a/test/farm/html/run_unicode.py +++ /dev/null @@ -1,30 +0,0 @@ -import sys - -def html_it(): - """Run coverage and make an HTML report for unicode.py.""" - import coverage - cov = coverage.coverage() - cov.start() - import unicode # pragma: nested - cov.stop() # pragma: nested - cov.html_report(unicode, directory="../html_unicode") - -runfunc(html_it, rundir="src") - -# HTML files will change often. Check that the sizes are reasonable, -# and check that certain key strings are in the output. -compare("gold_unicode", "html_unicode", size_within=10, file_pattern="*.html") -contains("html_unicode/unicode.html", - ""ʎd˙ǝbɐɹǝʌoɔ"", - ) - -if sys.maxunicode == 65535: - contains("html_unicode/unicode.html", - ""db40,dd00: x��"", - ) -else: - contains("html_unicode/unicode.html", - ""db40,dd00: x󠄀"", - ) - -clean("html_unicode") diff --git a/test/farm/html/run_y_xml_branch.py b/test/farm/html/run_y_xml_branch.py deleted file mode 100644 index 88a2e44e..00000000 --- a/test/farm/html/run_y_xml_branch.py +++ /dev/null @@ -1,21 +0,0 @@ -def xml_it(): - """Run coverage and make an XML report for y.""" - import coverage - cov = coverage.coverage(branch=True) - cov.start() - import y # pragma: nested - cov.stop() # pragma: nested - cov.xml_report(y, outfile="../xml_branch/coverage.xml") - -import os -if not os.path.exists("xml_branch"): - os.makedirs("xml_branch") - -runfunc(xml_it, rundir="src") - -compare("gold_y_xml_branch", "xml_branch", scrubs=[ - (r' timestamp="\d+"', ' timestamp="TIMESTAMP"'), - (r' version="[-.\w]+"', ' version="VERSION"'), - (r'/code/coverage/?[-.\w]*', '/code/coverage/VER'), - ]) -clean("xml_branch") diff --git a/test/farm/html/src/a.py b/test/farm/html/src/a.py deleted file mode 100644 index 9e71aebd..00000000 --- a/test/farm/html/src/a.py +++ /dev/null @@ -1,7 +0,0 @@ -# A test file for HTML reporting by coverage. - -if 1 < 2: - # Needed a < to look at HTML entities. - a = 3 -else: - a = 4 diff --git a/test/farm/html/src/b.py b/test/farm/html/src/b.py deleted file mode 100644 index 3bf73a9f..00000000 --- a/test/farm/html/src/b.py +++ /dev/null @@ -1,29 +0,0 @@ -# A test file for HTML reporting by coverage. - -def one(x): - # This will be a branch that misses the else. - if x < 2: - a = 3 - else: - a = 4 - -one(1) - -def two(x): - # A missed else that branches to "exit" - if x: - a = 5 - -two(1) - -def three(): - try: - # This if has two branches, *neither* one taken. - if name_error_this_variable_doesnt_exist: - a = 1 - else: - a = 2 - except: - pass - -three() diff --git a/test/farm/html/src/bom.py b/test/farm/html/src/bom.py deleted file mode 100644 index 2db8b717..00000000 --- a/test/farm/html/src/bom.py +++ /dev/null @@ -1,11 +0,0 @@ -# A python source file in utf-8, with BOM -math = "3×4 = 12, ÷2 = 6±0" - -import sys - -if sys.version_info >= (3, 0): - assert len(math) == 18 - assert len(math.encode('utf-8')) == 21 -else: - assert len(math) == 21 - assert len(math.decode('utf-8')) == 18 diff --git a/test/farm/html/src/coverage.xml b/test/farm/html/src/coverage.xml deleted file mode 100644 index 128cf750..00000000 --- a/test/farm/html/src/coverage.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - - - - - - - - - - - - diff --git a/test/farm/html/src/extra.css b/test/farm/html/src/extra.css deleted file mode 100644 index 46c41fcd..00000000 --- a/test/farm/html/src/extra.css +++ /dev/null @@ -1 +0,0 @@ -/* Doesn't matter what goes in here, it gets copied. */ diff --git a/test/farm/html/src/here.py b/test/farm/html/src/here.py deleted file mode 100644 index d0d26ea7..00000000 --- a/test/farm/html/src/here.py +++ /dev/null @@ -1,8 +0,0 @@ -# A test file for HTML reporting by coverage. - -import other - -if 1 < 2: - h = 3 -else: - h = 4 diff --git a/test/farm/html/src/isolatin1.py b/test/farm/html/src/isolatin1.py deleted file mode 100644 index 057c097b..00000000 --- a/test/farm/html/src/isolatin1.py +++ /dev/null @@ -1,5 +0,0 @@ -# A python source file in another encoding. -# -*- coding: iso8859-1 -*- - -math = "34 = 12, 2 = 60" -assert len(math) == 18 diff --git a/test/farm/html/src/m1.py b/test/farm/html/src/m1.py deleted file mode 100644 index 927e1f6b..00000000 --- a/test/farm/html/src/m1.py +++ /dev/null @@ -1,2 +0,0 @@ -m1a = 1 -m1b = 2 diff --git a/test/farm/html/src/m2.py b/test/farm/html/src/m2.py deleted file mode 100644 index ffddf6cf..00000000 --- a/test/farm/html/src/m2.py +++ /dev/null @@ -1,2 +0,0 @@ -m2a = 1 -m2b = 2 diff --git a/test/farm/html/src/m3.py b/test/farm/html/src/m3.py deleted file mode 100644 index 395d7d25..00000000 --- a/test/farm/html/src/m3.py +++ /dev/null @@ -1,2 +0,0 @@ -m3a = 1 -m3b = 2 diff --git a/test/farm/html/src/main.py b/test/farm/html/src/main.py deleted file mode 100644 index ce894465..00000000 --- a/test/farm/html/src/main.py +++ /dev/null @@ -1,10 +0,0 @@ -import m1 -import m2 -import m3 - -a = 5 -b = 6 - -assert m1.m1a == 1 -assert m2.m2a == 1 -assert m3.m3a == 1 diff --git a/test/farm/html/src/omit4.ini b/test/farm/html/src/omit4.ini deleted file mode 100644 index 6821ecda..00000000 --- a/test/farm/html/src/omit4.ini +++ /dev/null @@ -1,2 +0,0 @@ -[report] -omit = m2.py diff --git a/test/farm/html/src/omit5.ini b/test/farm/html/src/omit5.ini deleted file mode 100644 index 7e32b414..00000000 --- a/test/farm/html/src/omit5.ini +++ /dev/null @@ -1,8 +0,0 @@ -[report] -omit = - fooey - gooey, m[23]*, kablooey - helloworld - -[html] -directory = ../html_omit_5 diff --git a/test/farm/html/src/partial.py b/test/farm/html/src/partial.py deleted file mode 100644 index 8d62f5c5..00000000 --- a/test/farm/html/src/partial.py +++ /dev/null @@ -1,18 +0,0 @@ -# partial branches - -a = 3 - -while True: - break - -while 1: - break - -while a: # pragma: no branch - break - -if 0: - never_happen() - -if 1: - a = 13 diff --git a/test/farm/html/src/run_a_xml_2.ini b/test/farm/html/src/run_a_xml_2.ini deleted file mode 100644 index 8d28f97b..00000000 --- a/test/farm/html/src/run_a_xml_2.ini +++ /dev/null @@ -1,3 +0,0 @@ -# Put all the XML output in xml_2 -[xml] -output = ../xml_2/coverage.xml diff --git a/test/farm/html/src/tabbed.py b/test/farm/html/src/tabbed.py deleted file mode 100644 index 2035852f..00000000 --- a/test/farm/html/src/tabbed.py +++ /dev/null @@ -1,7 +0,0 @@ -# This file should have tabs. -x = 1 -if x: - a = "Tabbed" # Aligned comments - if x: # look nice - b = "No spaces" # when they - c = "Done" # line up. diff --git a/test/farm/html/src/unicode.py b/test/farm/html/src/unicode.py deleted file mode 100644 index f6a9a052..00000000 --- a/test/farm/html/src/unicode.py +++ /dev/null @@ -1,5 +0,0 @@ -# A python source file with exotic characters -# -*- coding: utf-8 -*- - -upside_down = "ʎd˙ǝbɐɹǝʌoɔ" -surrogate = "db40,dd00: x󠄀" diff --git a/test/farm/html/src/y.py b/test/farm/html/src/y.py deleted file mode 100644 index af7c9689..00000000 --- a/test/farm/html/src/y.py +++ /dev/null @@ -1,9 +0,0 @@ -# A test file for XML reporting by coverage. - -def choice(x): - if x < 2: - return 3 - else: - return 4 - -assert choice(1) == 3 diff --git a/test/farm/run/run_chdir.py b/test/farm/run/run_chdir.py deleted file mode 100644 index f459f500..00000000 --- a/test/farm/run/run_chdir.py +++ /dev/null @@ -1,12 +0,0 @@ -copy("src", "out") -run(""" - coverage run chdir.py - coverage -r - """, rundir="out", outfile="stdout.txt") -contains("out/stdout.txt", - "Line One", - "Line Two", - "chdir" - ) -doesnt_contain("out/stdout.txt", "No such file or directory") -clean("out") diff --git a/test/farm/run/run_timid.py b/test/farm/run/run_timid.py deleted file mode 100644 index ce78fff1..00000000 --- a/test/farm/run/run_timid.py +++ /dev/null @@ -1,60 +0,0 @@ -# Test that the --timid command line argument properly swaps the tracer -# function for a simpler one. -# -# This is complicated by the fact that the tests are run twice for each -# version: once with a compiled C-based trace function, and once without -# it, to also test the Python trace function. So this test has to examine -# an environment variable set in igor.py to know whether to expect to see -# the C trace function or not. - -import os - -# When meta-coverage testing, this test doesn't work, because it finds -# coverage.py's own trace function. -if os.environ.get('COVERAGE_COVERAGE', ''): - skip("Can't test timid during coverage measurement.") - -copy("src", "out") -run(""" - python showtrace.py none - coverage -e -x showtrace.py regular - coverage -e -x --timid showtrace.py timid - """, rundir="out", outfile="showtraceout.txt") - -# When running without coverage, no trace function -# When running timidly, the trace function is always Python. -contains("out/showtraceout.txt", - "none None", - "timid PyTracer", - ) - -if os.environ.get('COVERAGE_TEST_TRACER', 'c') == 'c': - # If the C trace function is being tested, then regular running should have - # the C function, which registers itself as f_trace. - contains("out/showtraceout.txt", "regular CTracer") -else: - # If the Python trace function is being tested, then regular running will - # also show the Python function. - contains("out/showtraceout.txt", "regular PyTracer") - -# Try the environment variable. -old_opts = os.environ.get('COVERAGE_OPTIONS') -os.environ['COVERAGE_OPTIONS'] = '--timid' - -run(""" - coverage -e -x showtrace.py regular - coverage -e -x --timid showtrace.py timid - """, rundir="out", outfile="showtraceout.txt") - -contains("out/showtraceout.txt", - "none None", - "timid PyTracer", - "regular PyTracer", - ) - -if old_opts: - os.environ['COVERAGE_OPTIONS'] = old_opts -else: - del os.environ['COVERAGE_OPTIONS'] - -clean("out") diff --git a/test/farm/run/run_xxx.py b/test/farm/run/run_xxx.py deleted file mode 100644 index 19e94a42..00000000 --- a/test/farm/run/run_xxx.py +++ /dev/null @@ -1,12 +0,0 @@ -copy("src", "out") -run(""" - coverage -e -x xxx - coverage -r - """, rundir="out", outfile="stdout.txt") -contains("out/stdout.txt", - "xxx: 3 4 0 7", - "\nxxx ", # The reporting line for xxx - " 7 1 86%" # The reporting data for xxx - ) -doesnt_contain("out/stdout.txt", "No such file or directory") -clean("out") diff --git a/test/farm/run/src/chdir.py b/test/farm/run/src/chdir.py deleted file mode 100644 index 6d834924..00000000 --- a/test/farm/run/src/chdir.py +++ /dev/null @@ -1,4 +0,0 @@ -import os -print("Line One") -os.chdir("subdir") -print("Line Two") diff --git a/test/farm/run/src/showtrace.py b/test/farm/run/src/showtrace.py deleted file mode 100644 index e97412e0..00000000 --- a/test/farm/run/src/showtrace.py +++ /dev/null @@ -1,23 +0,0 @@ -# Show the current frame's trace function, so that we can test what the -# command-line options do to the trace function used. - -import sys - -# Show what the trace function is. If a C-based function is used, then f_trace -# may be None. -trace_fn = sys._getframe(0).f_trace -if trace_fn is None: - trace_name = "None" -else: - # Get the name of the tracer class. Py3k has a different way to get it. - try: - trace_name = trace_fn.im_class.__name__ - except AttributeError: - try: - trace_name = trace_fn.__self__.__class__.__name__ - except AttributeError: - # A C-based function could also manifest as an f_trace value - # which doesn't have im_class or __self__. - trace_name = trace_fn.__class__.__name__ - -print("%s %s" % (sys.argv[1], trace_name)) diff --git a/test/farm/run/src/subdir/placeholder b/test/farm/run/src/subdir/placeholder deleted file mode 100644 index e69de29b..00000000 diff --git a/test/farm/run/src/xxx b/test/farm/run/src/xxx deleted file mode 100644 index 8f727f08..00000000 --- a/test/farm/run/src/xxx +++ /dev/null @@ -1,8 +0,0 @@ -# This is a python file though it doesn't look like it, like a main script. -a = b = c = d = 0 -a = 3 -b = 4 -if not b: - c = 6 -d = 7 -print("xxx: %r %r %r %r" % (a, b, c, d)) diff --git a/test/js/index.html b/test/js/index.html deleted file mode 100644 index 60bdb30a..00000000 --- a/test/js/index.html +++ /dev/null @@ -1,52 +0,0 @@ - - - - Coverage.py Javascript Test Suite - - - - - - - - - - - - - - - - - - - - - -

Coverage.py Javascript Test Suite

-

-
-

-
    -
    - - diff --git a/test/js/tests.js b/test/js/tests.js deleted file mode 100644 index 73b4ce2b..00000000 --- a/test/js/tests.js +++ /dev/null @@ -1,204 +0,0 @@ -// Tests of coverage.py HTML report chunk navigation. -/*global coverage, test, module, equals, jQuery, $ */ - -// Test helpers - -function selection_is(sel) { - raw_selection_is(sel, true); -} - -function raw_selection_is(sel, check_highlight) { - var beg = sel[0], end = sel[1]; - equals(coverage.sel_begin, beg); - equals(coverage.sel_end, end); - if (check_highlight) { - equals(coverage.code_container().find(".highlight").length, end-beg); - } -} - -function build_fixture(spec) { - var i, data; - $("#fixture-template").tmpl().appendTo("#qunit-fixture"); - for (i = 0; i < spec.length; i++) { - data = {number: i+1, klass: spec.substr(i, 1)}; - $("#lineno-template").tmpl(data).appendTo("#qunit-fixture .linenos"); - $("#text-template").tmpl(data).appendTo("#qunit-fixture .text"); - } - coverage.pyfile_ready(jQuery); -} - -// Tests - -// Zero-chunk tests - -module("Zero-chunk navigation", { - setup: function () { - build_fixture("wwww"); - } -}); - -test("set_sel defaults", function () { - coverage.set_sel(2); - equals(coverage.sel_begin, 2); - equals(coverage.sel_end, 3); -}); - -test("No first chunk to select", function () { - coverage.to_first_chunk(); -}); - -// One-chunk tests - -$.each([ - ['rrrrr', [1,6]], - ['r', [1,2]], - ['wwrrrr', [3,7]], - ['wwrrrrww', [3,7]], - ['rrrrww', [1,5]] -], function (i, params) { - - // Each of these tests uses a fixture with one highlighted chunks. - var id = params[0]; - var c1 = params[1]; - - module("One-chunk navigation - " + id, { - setup: function () { - build_fixture(id); - } - }); - - test("First chunk", function () { - coverage.to_first_chunk(); - selection_is(c1); - }); - - test("Next chunk is first chunk", function () { - coverage.to_next_chunk(); - selection_is(c1); - }); - - test("There is no next chunk", function () { - coverage.to_first_chunk(); - coverage.to_next_chunk(); - selection_is(c1); - }); - - test("There is no prev chunk", function () { - coverage.to_first_chunk(); - coverage.to_prev_chunk(); - selection_is(c1); - }); -}); - -// Two-chunk tests - -$.each([ - ['rrwwrrrr', [1,3], [5,9]], - ['rb', [1,2], [2,3]], - ['rbbbbbbbbbb', [1,2], [2,12]], - ['rrrrrrrrrrb', [1,11], [11,12]], - ['wrrwrrrrw', [2,4], [5,9]], - ['rrrbbb', [1,4], [4,7]] -], function (i, params) { - - // Each of these tests uses a fixture with two highlighted chunks. - var id = params[0]; - var c1 = params[1]; - var c2 = params[2]; - - module("Two-chunk navigation - " + id, { - setup: function () { - build_fixture(id); - } - }); - - test("First chunk", function () { - coverage.to_first_chunk(); - selection_is(c1); - }); - - test("Next chunk is first chunk", function () { - coverage.to_next_chunk(); - selection_is(c1); - }); - - test("Move to next chunk", function () { - coverage.to_first_chunk(); - coverage.to_next_chunk(); - selection_is(c2); - }); - - test("Move to first chunk", function () { - coverage.to_first_chunk(); - coverage.to_next_chunk(); - coverage.to_first_chunk(); - selection_is(c1); - }); - - test("Move to previous chunk", function () { - coverage.to_first_chunk(); - coverage.to_next_chunk(); - coverage.to_prev_chunk(); - selection_is(c1); - }); - - test("Next doesn't move after last chunk", function () { - coverage.to_first_chunk(); - coverage.to_next_chunk(); - coverage.to_next_chunk(); - selection_is(c2); - }); - - test("Prev doesn't move before first chunk", function () { - coverage.to_first_chunk(); - coverage.to_next_chunk(); - coverage.to_prev_chunk(); - coverage.to_prev_chunk(); - selection_is(c1); - }); - -}); - -module("Miscellaneous"); - -test("Jump from a line selected", function () { - build_fixture("rrwwrr"); - coverage.set_sel(3); - coverage.to_next_chunk(); - selection_is([5,7]); -}); - -// Tests of select_line_or_chunk. - -$.each([ - // The data for each test: a spec for the fixture to build, and an array - // of the selection that will be selected by select_line_or_chunk for - // each line in the fixture. - ['rrwwrr', [[1,3], [1,3], [3,4], [4,5], [5,7], [5,7]]], - ['rb', [[1,2], [2,3]]], - ['r', [[1,2]]], - ['w', [[1,2]]], - ['www', [[1,2], [2,3], [3,4]]], - ['wwwrrr', [[1,2], [2,3], [3,4], [4,7], [4,7], [4,7]]], - ['rrrwww', [[1,4], [1,4], [1,4], [4,5], [5,6], [6,7]]], - ['rrrbbb', [[1,4], [1,4], [1,4], [4,7], [4,7], [4,7]]] -], function (i, params) { - - // Each of these tests uses a fixture with two highlighted chunks. - var id = params[0]; - var sels = params[1]; - - module("Select line or chunk - " + id, { - setup: function () { - build_fixture(id); - } - }); - - $.each(sels, function (i, sel) { - i++; - test("Select line " + i, function () { - coverage.select_line_or_chunk(i); - raw_selection_is(sel); - }); - }); -}); diff --git a/test/modules/aa/__init__.py b/test/modules/aa/__init__.py deleted file mode 100644 index 77593d8f..00000000 --- a/test/modules/aa/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# aa diff --git a/test/modules/aa/afile.odd.py b/test/modules/aa/afile.odd.py deleted file mode 100644 index c6f49e18..00000000 --- a/test/modules/aa/afile.odd.py +++ /dev/null @@ -1 +0,0 @@ -# afile.odd.py diff --git a/test/modules/aa/afile.py b/test/modules/aa/afile.py deleted file mode 100644 index 3f0e38d1..00000000 --- a/test/modules/aa/afile.py +++ /dev/null @@ -1 +0,0 @@ -# afile.py diff --git a/test/modules/aa/bb.odd/bfile.py b/test/modules/aa/bb.odd/bfile.py deleted file mode 100644 index 90875404..00000000 --- a/test/modules/aa/bb.odd/bfile.py +++ /dev/null @@ -1 +0,0 @@ -# bfile.py diff --git a/test/modules/aa/bb/__init__.py b/test/modules/aa/bb/__init__.py deleted file mode 100644 index ffbe6240..00000000 --- a/test/modules/aa/bb/__init__.py +++ /dev/null @@ -1 +0,0 @@ -# bb diff --git a/test/modules/aa/bb/bfile.odd.py b/test/modules/aa/bb/bfile.odd.py deleted file mode 100644 index b45cba8c..00000000 --- a/test/modules/aa/bb/bfile.odd.py +++ /dev/null @@ -1 +0,0 @@ -# bfile.odd.py diff --git a/test/modules/aa/bb/bfile.py b/test/modules/aa/bb/bfile.py deleted file mode 100644 index 90875404..00000000 --- a/test/modules/aa/bb/bfile.py +++ /dev/null @@ -1 +0,0 @@ -# bfile.py diff --git a/test/modules/aa/bb/cc/__init__.py b/test/modules/aa/bb/cc/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/modules/aa/bb/cc/cfile.py b/test/modules/aa/bb/cc/cfile.py deleted file mode 100644 index 79764751..00000000 --- a/test/modules/aa/bb/cc/cfile.py +++ /dev/null @@ -1 +0,0 @@ -# cfile.py diff --git a/test/modules/aa/zfile.py b/test/modules/aa/zfile.py deleted file mode 100644 index 924f9b77..00000000 --- a/test/modules/aa/zfile.py +++ /dev/null @@ -1 +0,0 @@ -# zfile.py diff --git a/test/modules/covmod1.py b/test/modules/covmod1.py deleted file mode 100644 index b3f5e5f2..00000000 --- a/test/modules/covmod1.py +++ /dev/null @@ -1,3 +0,0 @@ -# covmod1.py: Simplest module for testing. -i = 1 -i += 1 diff --git a/test/modules/pkg1/__init__.py b/test/modules/pkg1/__init__.py deleted file mode 100644 index 2dfeb9c1..00000000 --- a/test/modules/pkg1/__init__.py +++ /dev/null @@ -1,3 +0,0 @@ -# This __init__.py has a module-level docstring, which is counted as a -# statement. -"""A simple package for testing with.""" diff --git a/test/modules/pkg1/__main__.py b/test/modules/pkg1/__main__.py deleted file mode 100644 index 66ce5956..00000000 --- a/test/modules/pkg1/__main__.py +++ /dev/null @@ -1,3 +0,0 @@ -# Used in the tests for run_python_module -import sys -print("pkg1.__main__: passed %s" % sys.argv[1]) diff --git a/test/modules/pkg1/p1a.py b/test/modules/pkg1/p1a.py deleted file mode 100644 index be5fcdd3..00000000 --- a/test/modules/pkg1/p1a.py +++ /dev/null @@ -1,5 +0,0 @@ -import os, sys - -# Invoke functions in os and sys so we can see if we measure code there. -x = sys.getcheckinterval() -y = os.getcwd() diff --git a/test/modules/pkg1/p1b.py b/test/modules/pkg1/p1b.py deleted file mode 100644 index 59d6fb54..00000000 --- a/test/modules/pkg1/p1b.py +++ /dev/null @@ -1,3 +0,0 @@ -x = 1 -y = 2 -z = 3 diff --git a/test/modules/pkg1/p1c.py b/test/modules/pkg1/p1c.py deleted file mode 100644 index a9aeef04..00000000 --- a/test/modules/pkg1/p1c.py +++ /dev/null @@ -1,3 +0,0 @@ -a = 1 -b = 2 -c = 3 diff --git a/test/modules/pkg1/runmod2.py b/test/modules/pkg1/runmod2.py deleted file mode 100644 index b52964cb..00000000 --- a/test/modules/pkg1/runmod2.py +++ /dev/null @@ -1,3 +0,0 @@ -# Used in the tests for run_python_module -import sys -print("runmod2: passed %s" % sys.argv[1]) diff --git a/test/modules/pkg1/sub/__init__.py b/test/modules/pkg1/sub/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/modules/pkg1/sub/__main__.py b/test/modules/pkg1/sub/__main__.py deleted file mode 100644 index b5be9f1c..00000000 --- a/test/modules/pkg1/sub/__main__.py +++ /dev/null @@ -1,3 +0,0 @@ -# Used in the tests for run_python_module -import sys -print("pkg1.sub.__main__: passed %s" % sys.argv[1]) diff --git a/test/modules/pkg1/sub/ps1a.py b/test/modules/pkg1/sub/ps1a.py deleted file mode 100644 index 4b6a15cc..00000000 --- a/test/modules/pkg1/sub/ps1a.py +++ /dev/null @@ -1,3 +0,0 @@ -d = 1 -e = 2 -f = 3 diff --git a/test/modules/pkg1/sub/runmod3.py b/test/modules/pkg1/sub/runmod3.py deleted file mode 100644 index 3a1ad155..00000000 --- a/test/modules/pkg1/sub/runmod3.py +++ /dev/null @@ -1,3 +0,0 @@ -# Used in the tests for run_python_module -import sys -print("runmod3: passed %s" % sys.argv[1]) diff --git a/test/modules/pkg2/__init__.py b/test/modules/pkg2/__init__.py deleted file mode 100644 index 090efbf5..00000000 --- a/test/modules/pkg2/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -# This is an __init__.py file, with no executable statements in it. -# This comment shouldn't confuse the parser. diff --git a/test/modules/pkg2/p2a.py b/test/modules/pkg2/p2a.py deleted file mode 100644 index b606711d..00000000 --- a/test/modules/pkg2/p2a.py +++ /dev/null @@ -1,3 +0,0 @@ -q = 1 -r = 1 -s = 1 diff --git a/test/modules/pkg2/p2b.py b/test/modules/pkg2/p2b.py deleted file mode 100644 index 7a34e2c6..00000000 --- a/test/modules/pkg2/p2b.py +++ /dev/null @@ -1,3 +0,0 @@ -t = 1 -u = 1 -v = 1 diff --git a/test/modules/runmod1.py b/test/modules/runmod1.py deleted file mode 100644 index 671d81ef..00000000 --- a/test/modules/runmod1.py +++ /dev/null @@ -1,3 +0,0 @@ -# Used in the tests for run_python_module -import sys -print("runmod1: passed %s" % sys.argv[1]) diff --git a/test/modules/usepkgs.py b/test/modules/usepkgs.py deleted file mode 100644 index 93c7d904..00000000 --- a/test/modules/usepkgs.py +++ /dev/null @@ -1,4 +0,0 @@ -import pkg1.p1a, pkg1.p1b -import pkg2.p2a, pkg2.p2b -import othermods.othera, othermods.otherb -import othermods.sub.osa, othermods.sub.osb diff --git a/test/moremodules/othermods/__init__.py b/test/moremodules/othermods/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/moremodules/othermods/othera.py b/test/moremodules/othermods/othera.py deleted file mode 100644 index 78896928..00000000 --- a/test/moremodules/othermods/othera.py +++ /dev/null @@ -1,2 +0,0 @@ -o = 1 -p = 2 diff --git a/test/moremodules/othermods/otherb.py b/test/moremodules/othermods/otherb.py deleted file mode 100644 index 2bd8a441..00000000 --- a/test/moremodules/othermods/otherb.py +++ /dev/null @@ -1,2 +0,0 @@ -q = 3 -r = 4 diff --git a/test/moremodules/othermods/sub/__init__.py b/test/moremodules/othermods/sub/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/test/moremodules/othermods/sub/osa.py b/test/moremodules/othermods/sub/osa.py deleted file mode 100644 index 0139d28b..00000000 --- a/test/moremodules/othermods/sub/osa.py +++ /dev/null @@ -1,2 +0,0 @@ -s = 5 -t = 6 diff --git a/test/moremodules/othermods/sub/osb.py b/test/moremodules/othermods/sub/osb.py deleted file mode 100644 index b024b148..00000000 --- a/test/moremodules/othermods/sub/osb.py +++ /dev/null @@ -1,2 +0,0 @@ -u = 7 -v = 8 diff --git a/test/osinfo.py b/test/osinfo.py deleted file mode 100644 index 25c3a7c6..00000000 --- a/test/osinfo.py +++ /dev/null @@ -1,71 +0,0 @@ -"""OS information for testing.""" - -import sys - -if sys.version_info >= (2, 5) and sys.platform == 'win32': - # Windows implementation - def process_ram(): - """How much RAM is this process using? (Windows)""" - import ctypes - # lifted from: - # lists.ubuntu.com/archives/bazaar-commits/2009-February/011990.html - class PROCESS_MEMORY_COUNTERS_EX(ctypes.Structure): - """Used by GetProcessMemoryInfo""" - _fields_ = [('cb', ctypes.c_ulong), - ('PageFaultCount', ctypes.c_ulong), - ('PeakWorkingSetSize', ctypes.c_size_t), - ('WorkingSetSize', ctypes.c_size_t), - ('QuotaPeakPagedPoolUsage', ctypes.c_size_t), - ('QuotaPagedPoolUsage', ctypes.c_size_t), - ('QuotaPeakNonPagedPoolUsage', ctypes.c_size_t), - ('QuotaNonPagedPoolUsage', ctypes.c_size_t), - ('PagefileUsage', ctypes.c_size_t), - ('PeakPagefileUsage', ctypes.c_size_t), - ('PrivateUsage', ctypes.c_size_t), - ] - - mem_struct = PROCESS_MEMORY_COUNTERS_EX() - ret = ctypes.windll.psapi.GetProcessMemoryInfo( - ctypes.windll.kernel32.GetCurrentProcess(), - ctypes.byref(mem_struct), - ctypes.sizeof(mem_struct) - ) - if not ret: - return 0 - return mem_struct.PrivateUsage - -elif sys.platform == 'linux2': - # Linux implementation - import os - - _scale = {'kb': 1024, 'mb': 1024*1024} - - def _VmB(key): - """Read the /proc/PID/status file to find memory use.""" - try: - # get pseudo file /proc//status - t = open('/proc/%d/status' % os.getpid()) - try: - v = t.read() - finally: - t.close() - except IOError: - return 0 # non-Linux? - # get VmKey line e.g. 'VmRSS: 9999 kB\n ...' - i = v.index(key) - v = v[i:].split(None, 3) - if len(v) < 3: - return 0 # invalid format? - # convert Vm value to bytes - return int(float(v[1]) * _scale[v[2].lower()]) - - def process_ram(): - """How much RAM is this process using? (Linux implementation)""" - return _VmB('VmRSS') - - -else: - # Don't have an implementation, at least satisfy the interface. - def process_ram(): - """How much RAM is this process using? (placebo implementation)""" - return 0 diff --git a/test/qunit/jquery.tmpl.min.js b/test/qunit/jquery.tmpl.min.js deleted file mode 100644 index 7438b2ca..00000000 --- a/test/qunit/jquery.tmpl.min.js +++ /dev/null @@ -1,10 +0,0 @@ -/* - * jQuery Templates Plugin 1.0.0pre - * http://github.com/jquery/jquery-tmpl - * Requires jQuery 1.4.2 - * - * Copyright Software Freedom Conservancy, Inc. - * Dual licensed under the MIT or GPL Version 2 licenses. - * http://jquery.org/license - */ -(function(a){var r=a.fn.domManip,d="_tmplitem",q=/^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /,b={},f={},e,p={key:0,data:{}},i=0,c=0,l=[];function g(g,d,h,e){var c={data:e||(e===0||e===false)?e:d?d.data:{},_wrap:d?d._wrap:null,tmpl:null,parent:d||null,nodes:[],calls:u,nest:w,wrap:x,html:v,update:t};g&&a.extend(c,g,{nodes:[],parent:d});if(h){c.tmpl=h;c._ctnt=c._ctnt||c.tmpl(a,c);c.key=++i;(l.length?f:b)[i]=c}return c}a.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(f,d){a.fn[f]=function(n){var g=[],i=a(n),k,h,m,l,j=this.length===1&&this[0].parentNode;e=b||{};if(j&&j.nodeType===11&&j.childNodes.length===1&&i.length===1){i[d](this[0]);g=this}else{for(h=0,m=i.length;h0?this.clone(true):this).get();a(i[h])[d](k);g=g.concat(k)}c=0;g=this.pushStack(g,f,i.selector)}l=e;e=null;a.tmpl.complete(l);return g}});a.fn.extend({tmpl:function(d,c,b){return a.tmpl(this[0],d,c,b)},tmplItem:function(){return a.tmplItem(this[0])},template:function(b){return a.template(b,this[0])},domManip:function(d,m,k){if(d[0]&&a.isArray(d[0])){var g=a.makeArray(arguments),h=d[0],j=h.length,i=0,f;while(i").join(">").split('"').join(""").split("'").join("'")}});a.extend(a.tmpl,{tag:{tmpl:{_default:{$2:"null"},open:"if($notnull_1){__=__.concat($item.nest($1,$2));}"},wrap:{_default:{$2:"null"},open:"$item.calls(__,$1,$2);__=[];",close:"call=$item.calls();__=call._.concat($item.wrap(call,__));"},each:{_default:{$2:"$index, $value"},open:"if($notnull_1){$.each($1a,function($2){with(this){",close:"}});}"},"if":{open:"if(($notnull_1) && $1a){",close:"}"},"else":{_default:{$1:"true"},open:"}else if(($notnull_1) && $1a){"},html:{open:"if($notnull_1){__.push($1a);}"},"=":{_default:{$1:"$data"},open:"if($notnull_1){__.push($.encode($1a));}"},"!":{open:""}},complete:function(){b={}},afterManip:function(f,b,d){var e=b.nodeType===11?a.makeArray(b.childNodes):b.nodeType===1?[b]:[];d.call(f,b);m(e);c++}});function j(e,g,f){var b,c=f?a.map(f,function(a){return typeof a==="string"?e.key?a.replace(/(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g,"$1 "+d+'="'+e.key+'" $2'):a:j(a,e,a._ctnt)}):e;if(g)return c;c=c.join("");c.replace(/^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/,function(f,c,e,d){b=a(e).get();m(b);if(c)b=k(c).concat(b);if(d)b=b.concat(k(d))});return b?b:k(c)}function k(c){var b=document.createElement("div");b.innerHTML=c;return a.makeArray(b.childNodes)}function o(b){return new Function("jQuery","$item","var $=jQuery,call,__=[],$data=$item.data;with($data){__.push('"+a.trim(b).replace(/([\\'])/g,"\\$1").replace(/[\r\t\n]/g," ").replace(/\$\{([^\}]*)\}/g,"{{= $1}}").replace(/\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g,function(m,l,k,g,b,c,d){var j=a.tmpl.tag[k],i,e,f;if(!j)throw"Unknown template tag: "+k;i=j._default||[];if(c&&!/\w$/.test(b)){b+=c;c=""}if(b){b=h(b);d=d?","+h(d)+")":c?")":"";e=c?b.indexOf(".")>-1?b+h(c):"("+b+").call($item"+d:b;f=c?e:"(typeof("+b+")==='function'?("+b+").call($item):("+b+"))"}else f=e=i.$1||"null";g=h(g);return"');"+j[l?"close":"open"].split("$notnull_1").join(b?"typeof("+b+")!=='undefined' && ("+b+")!=null":"true").split("$1a").join(f).split("$1").join(e).split("$2").join(g||i.$2||"")+"__.push('"})+"');}return __;")}function n(c,b){c._wrap=j(c,true,a.isArray(b)?b:[q.test(b)?b:a(b).html()]).join("")}function h(a){return a?a.replace(/\\'/g,"'").replace(/\\\\/g,"\\"):null}function s(b){var a=document.createElement("div");a.appendChild(b.cloneNode(true));return a.innerHTML}function m(o){var n="_"+c,k,j,l={},e,p,h;for(e=0,p=o.length;e=0;h--)m(j[h]);m(k)}function m(j){var p,h=j,k,e,m;if(m=j.getAttribute(d)){while(h.parentNode&&(h=h.parentNode).nodeType===1&&!(p=h.getAttribute(d)));if(p!==m){h=h.parentNode?h.nodeType===11?0:h.getAttribute(d)||0:0;if(!(e=b[m])){e=f[m];e=g(e,b[h]||f[h]);e.key=++i;b[i]=e}c&&o(m)}j.removeAttribute(d)}else if(c&&(e=a.data(j,"tmplItem"))){o(e.key);b[e.key]=e;h=a.data(j.parentNode,"tmplItem");h=h?h.key:0}if(e){k=e;while(k&&k.key!=h){k.nodes.push(j);k=k.parent}delete e._ctnt;delete e._wrap;a.data(j,"tmplItem",e)}function o(a){a=a+n;e=l[a]=l[a]||g(e,b[e.parent.key+n]||e.parent)}}}function u(a,d,c,b){if(!a)return l.pop();l.push({_:a,tmpl:d,item:this,data:c,options:b})}function w(d,c,b){return a.tmpl(a.template(d),c,b,this)}function x(b,d){var c=b.options||{};c.wrapped=d;return a.tmpl(a.template(b.tmpl),b.data,c,b.item)}function v(d,c){var b=this._wrap;return a.map(a(a.isArray(b)?b.join(""):b).filter(d||"*"),function(a){return c?a.innerText||a.textContent:a.outerHTML||s(a)})}function t(){var b=this.nodes;a.tmpl(null,null,null,this).insertBefore(b[0]);a(b).remove()}})(jQuery); \ No newline at end of file diff --git a/test/qunit/qunit.css b/test/qunit/qunit.css deleted file mode 100644 index b3c6db52..00000000 --- a/test/qunit/qunit.css +++ /dev/null @@ -1,225 +0,0 @@ -/** - * QUnit - A JavaScript Unit Testing Framework - * - * http://docs.jquery.com/QUnit - * - * Copyright (c) 2011 John Resig, Jörn Zaefferer - * Dual licensed under the MIT (MIT-LICENSE.txt) - * or GPL (GPL-LICENSE.txt) licenses. - */ - -/** Font Family and Sizes */ - -#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { - font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; -} - -#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } -#qunit-tests { font-size: smaller; } - - -/** Resets */ - -#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult { - margin: 0; - padding: 0; -} - - -/** Header */ - -#qunit-header { - padding: 0.5em 0 0.5em 1em; - - color: #8699a4; - background-color: #0d3349; - - font-size: 1.5em; - line-height: 1em; - font-weight: normal; - - border-radius: 15px 15px 0 0; - -moz-border-radius: 15px 15px 0 0; - -webkit-border-top-right-radius: 15px; - -webkit-border-top-left-radius: 15px; -} - -#qunit-header a { - text-decoration: none; - color: #c2ccd1; -} - -#qunit-header a:hover, -#qunit-header a:focus { - color: #fff; -} - -#qunit-banner { - height: 5px; -} - -#qunit-testrunner-toolbar { - padding: 0.5em 0 0.5em 2em; - color: #5E740B; - background-color: #eee; -} - -#qunit-userAgent { - padding: 0.5em 0 0.5em 2.5em; - background-color: #2b81af; - color: #fff; - text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; -} - - -/** Tests: Pass/Fail */ - -#qunit-tests { - list-style-position: inside; -} - -#qunit-tests li { - padding: 0.4em 0.5em 0.4em 2.5em; - border-bottom: 1px solid #fff; - list-style-position: inside; -} - -#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running { - display: none; -} - -#qunit-tests li strong { - cursor: pointer; -} - -#qunit-tests li a { - padding: 0.5em; - color: #c2ccd1; - text-decoration: none; -} -#qunit-tests li a:hover, -#qunit-tests li a:focus { - color: #000; -} - -#qunit-tests ol { - margin-top: 0.5em; - padding: 0.5em; - - background-color: #fff; - - border-radius: 15px; - -moz-border-radius: 15px; - -webkit-border-radius: 15px; - - box-shadow: inset 0px 2px 13px #999; - -moz-box-shadow: inset 0px 2px 13px #999; - -webkit-box-shadow: inset 0px 2px 13px #999; -} - -#qunit-tests table { - border-collapse: collapse; - margin-top: .2em; -} - -#qunit-tests th { - text-align: right; - vertical-align: top; - padding: 0 .5em 0 0; -} - -#qunit-tests td { - vertical-align: top; -} - -#qunit-tests pre { - margin: 0; - white-space: pre-wrap; - word-wrap: break-word; -} - -#qunit-tests del { - background-color: #e0f2be; - color: #374e0c; - text-decoration: none; -} - -#qunit-tests ins { - background-color: #ffcaca; - color: #500; - text-decoration: none; -} - -/*** Test Counts */ - -#qunit-tests b.counts { color: black; } -#qunit-tests b.passed { color: #5E740B; } -#qunit-tests b.failed { color: #710909; } - -#qunit-tests li li { - margin: 0.5em; - padding: 0.4em 0.5em 0.4em 0.5em; - background-color: #fff; - border-bottom: none; - list-style-position: inside; -} - -/*** Passing Styles */ - -#qunit-tests li li.pass { - color: #5E740B; - background-color: #fff; - border-left: 26px solid #C6E746; -} - -#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } -#qunit-tests .pass .test-name { color: #366097; } - -#qunit-tests .pass .test-actual, -#qunit-tests .pass .test-expected { color: #999999; } - -#qunit-banner.qunit-pass { background-color: #C6E746; } - -/*** Failing Styles */ - -#qunit-tests li li.fail { - color: #710909; - background-color: #fff; - border-left: 26px solid #EE5757; -} - -#qunit-tests > li:last-child { - border-radius: 0 0 15px 15px; - -moz-border-radius: 0 0 15px 15px; - -webkit-border-bottom-right-radius: 15px; - -webkit-border-bottom-left-radius: 15px; -} - -#qunit-tests .fail { color: #000000; background-color: #EE5757; } -#qunit-tests .fail .test-name, -#qunit-tests .fail .module-name { color: #000000; } - -#qunit-tests .fail .test-actual { color: #EE5757; } -#qunit-tests .fail .test-expected { color: green; } - -#qunit-banner.qunit-fail { background-color: #EE5757; } - - -/** Result */ - -#qunit-testresult { - padding: 0.5em 0.5em 0.5em 2.5em; - - color: #2b81af; - background-color: #D2E0E6; - - border-bottom: 1px solid white; -} - -/** Fixture */ - -#qunit-fixture { - position: absolute; - top: -10000px; - left: -10000px; -} diff --git a/test/qunit/qunit.js b/test/qunit/qunit.js deleted file mode 100644 index e00cca90..00000000 --- a/test/qunit/qunit.js +++ /dev/null @@ -1,1448 +0,0 @@ -/** - * QUnit - A JavaScript Unit Testing Framework - * - * http://docs.jquery.com/QUnit - * - * Copyright (c) 2011 John Resig, Jörn Zaefferer - * Dual licensed under the MIT (MIT-LICENSE.txt) - * or GPL (GPL-LICENSE.txt) licenses. - */ - -(function(window) { - -var defined = { - setTimeout: typeof window.setTimeout !== "undefined", - sessionStorage: (function() { - try { - return !!sessionStorage.getItem; - } catch(e){ - return false; - } - })() -}; - -var testId = 0; - -var Test = function(name, testName, expected, testEnvironmentArg, async, callback) { - this.name = name; - this.testName = testName; - this.expected = expected; - this.testEnvironmentArg = testEnvironmentArg; - this.async = async; - this.callback = callback; - this.assertions = []; -}; -Test.prototype = { - init: function() { - var tests = id("qunit-tests"); - if (tests) { - var b = document.createElement("strong"); - b.innerHTML = "Running " + this.name; - var li = document.createElement("li"); - li.appendChild( b ); - li.className = "running"; - li.id = this.id = "test-output" + testId++; - tests.appendChild( li ); - } - }, - setup: function() { - if (this.module != config.previousModule) { - if ( config.previousModule ) { - QUnit.moduleDone( { - name: config.previousModule, - failed: config.moduleStats.bad, - passed: config.moduleStats.all - config.moduleStats.bad, - total: config.moduleStats.all - } ); - } - config.previousModule = this.module; - config.moduleStats = { all: 0, bad: 0 }; - QUnit.moduleStart( { - name: this.module - } ); - } - - config.current = this; - this.testEnvironment = extend({ - setup: function() {}, - teardown: function() {} - }, this.moduleTestEnvironment); - if (this.testEnvironmentArg) { - extend(this.testEnvironment, this.testEnvironmentArg); - } - - QUnit.testStart( { - name: this.testName - } ); - - // allow utility functions to access the current test environment - // TODO why?? - QUnit.current_testEnvironment = this.testEnvironment; - - try { - if ( !config.pollution ) { - saveGlobal(); - } - - this.testEnvironment.setup.call(this.testEnvironment); - } catch(e) { - QUnit.ok( false, "Setup failed on " + this.testName + ": " + e.message ); - } - }, - run: function() { - if ( this.async ) { - QUnit.stop(); - } - - if ( config.notrycatch ) { - this.callback.call(this.testEnvironment); - return; - } - try { - this.callback.call(this.testEnvironment); - } catch(e) { - fail("Test " + this.testName + " died, exception and test follows", e, this.callback); - QUnit.ok( false, "Died on test #" + (this.assertions.length + 1) + ": " + e.message + " - " + QUnit.jsDump.parse(e) ); - // else next test will carry the responsibility - saveGlobal(); - - // Restart the tests if they're blocking - if ( config.blocking ) { - start(); - } - } - }, - teardown: function() { - try { - this.testEnvironment.teardown.call(this.testEnvironment); - checkPollution(); - } catch(e) { - QUnit.ok( false, "Teardown failed on " + this.testName + ": " + e.message ); - } - }, - finish: function() { - if ( this.expected && this.expected != this.assertions.length ) { - QUnit.ok( false, "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run" ); - } - - var good = 0, bad = 0, - tests = id("qunit-tests"); - - config.stats.all += this.assertions.length; - config.moduleStats.all += this.assertions.length; - - if ( tests ) { - var ol = document.createElement("ol"); - - for ( var i = 0; i < this.assertions.length; i++ ) { - var assertion = this.assertions[i]; - - var li = document.createElement("li"); - li.className = assertion.result ? "pass" : "fail"; - li.innerHTML = assertion.message || (assertion.result ? "okay" : "failed"); - ol.appendChild( li ); - - if ( assertion.result ) { - good++; - } else { - bad++; - config.stats.bad++; - config.moduleStats.bad++; - } - } - - // store result when possible - if ( QUnit.config.reorder && defined.sessionStorage ) { - if (bad) { - sessionStorage.setItem("qunit-" + this.module + "-" + this.testName, bad); - } else { - sessionStorage.removeItem("qunit-" + this.module + "-" + this.testName); - } - } - - if (bad == 0) { - ol.style.display = "none"; - } - - var b = document.createElement("strong"); - b.innerHTML = this.name + " (" + bad + ", " + good + ", " + this.assertions.length + ")"; - - var a = document.createElement("a"); - a.innerHTML = "Rerun"; - a.href = QUnit.url({ filter: getText([b]).replace(/\([^)]+\)$/, "").replace(/(^\s*|\s*$)/g, "") }); - - addEvent(b, "click", function() { - var next = b.nextSibling.nextSibling, - display = next.style.display; - next.style.display = display === "none" ? "block" : "none"; - }); - - addEvent(b, "dblclick", function(e) { - var target = e && e.target ? e.target : window.event.srcElement; - if ( target.nodeName.toLowerCase() == "span" || target.nodeName.toLowerCase() == "b" ) { - target = target.parentNode; - } - if ( window.location && target.nodeName.toLowerCase() === "strong" ) { - window.location = QUnit.url({ filter: getText([target]).replace(/\([^)]+\)$/, "").replace(/(^\s*|\s*$)/g, "") }); - } - }); - - var li = id(this.id); - li.className = bad ? "fail" : "pass"; - li.removeChild( li.firstChild ); - li.appendChild( b ); - li.appendChild( a ); - li.appendChild( ol ); - - } else { - for ( var i = 0; i < this.assertions.length; i++ ) { - if ( !this.assertions[i].result ) { - bad++; - config.stats.bad++; - config.moduleStats.bad++; - } - } - } - - try { - QUnit.reset(); - } catch(e) { - fail("reset() failed, following Test " + this.testName + ", exception and reset fn follows", e, QUnit.reset); - } - - QUnit.testDone( { - name: this.testName, - failed: bad, - passed: this.assertions.length - bad, - total: this.assertions.length - } ); - }, - - queue: function() { - var test = this; - synchronize(function() { - test.init(); - }); - function run() { - // each of these can by async - synchronize(function() { - test.setup(); - }); - synchronize(function() { - test.run(); - }); - synchronize(function() { - test.teardown(); - }); - synchronize(function() { - test.finish(); - }); - } - // defer when previous test run passed, if storage is available - var bad = QUnit.config.reorder && defined.sessionStorage && +sessionStorage.getItem("qunit-" + this.module + "-" + this.testName); - if (bad) { - run(); - } else { - synchronize(run); - }; - } - -}; - -var QUnit = { - - // call on start of module test to prepend name to all tests - module: function(name, testEnvironment) { - config.currentModule = name; - config.currentModuleTestEnviroment = testEnvironment; - }, - - asyncTest: function(testName, expected, callback) { - if ( arguments.length === 2 ) { - callback = expected; - expected = 0; - } - - QUnit.test(testName, expected, callback, true); - }, - - test: function(testName, expected, callback, async) { - var name = '' + testName + '', testEnvironmentArg; - - if ( arguments.length === 2 ) { - callback = expected; - expected = null; - } - // is 2nd argument a testEnvironment? - if ( expected && typeof expected === 'object') { - testEnvironmentArg = expected; - expected = null; - } - - if ( config.currentModule ) { - name = '' + config.currentModule + ": " + name; - } - - if ( !validTest(config.currentModule + ": " + testName) ) { - return; - } - - var test = new Test(name, testName, expected, testEnvironmentArg, async, callback); - test.module = config.currentModule; - test.moduleTestEnvironment = config.currentModuleTestEnviroment; - test.queue(); - }, - - /** - * Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through. - */ - expect: function(asserts) { - config.current.expected = asserts; - }, - - /** - * Asserts true. - * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" ); - */ - ok: function(a, msg) { - a = !!a; - var details = { - result: a, - message: msg - }; - msg = escapeHtml(msg); - QUnit.log(details); - config.current.assertions.push({ - result: a, - message: msg - }); - }, - - /** - * Checks that the first two arguments are equal, with an optional message. - * Prints out both actual and expected values. - * - * Prefered to ok( actual == expected, message ) - * - * @example equal( format("Received {0} bytes.", 2), "Received 2 bytes." ); - * - * @param Object actual - * @param Object expected - * @param String message (optional) - */ - equal: function(actual, expected, message) { - QUnit.push(expected == actual, actual, expected, message); - }, - - notEqual: function(actual, expected, message) { - QUnit.push(expected != actual, actual, expected, message); - }, - - deepEqual: function(actual, expected, message) { - QUnit.push(QUnit.equiv(actual, expected), actual, expected, message); - }, - - notDeepEqual: function(actual, expected, message) { - QUnit.push(!QUnit.equiv(actual, expected), actual, expected, message); - }, - - strictEqual: function(actual, expected, message) { - QUnit.push(expected === actual, actual, expected, message); - }, - - notStrictEqual: function(actual, expected, message) { - QUnit.push(expected !== actual, actual, expected, message); - }, - - raises: function(block, expected, message) { - var actual, ok = false; - - if (typeof expected === 'string') { - message = expected; - expected = null; - } - - try { - block(); - } catch (e) { - actual = e; - } - - if (actual) { - // we don't want to validate thrown error - if (!expected) { - ok = true; - // expected is a regexp - } else if (QUnit.objectType(expected) === "regexp") { - ok = expected.test(actual); - // expected is a constructor - } else if (actual instanceof expected) { - ok = true; - // expected is a validation function which returns true is validation passed - } else if (expected.call({}, actual) === true) { - ok = true; - } - } - - QUnit.ok(ok, message); - }, - - start: function() { - config.semaphore--; - if (config.semaphore > 0) { - // don't start until equal number of stop-calls - return; - } - if (config.semaphore < 0) { - // ignore if start is called more often then stop - config.semaphore = 0; - } - // A slight delay, to avoid any current callbacks - if ( defined.setTimeout ) { - window.setTimeout(function() { - if ( config.timeout ) { - clearTimeout(config.timeout); - } - - config.blocking = false; - process(); - }, 13); - } else { - config.blocking = false; - process(); - } - }, - - stop: function(timeout) { - config.semaphore++; - config.blocking = true; - - if ( timeout && defined.setTimeout ) { - clearTimeout(config.timeout); - config.timeout = window.setTimeout(function() { - QUnit.ok( false, "Test timed out" ); - QUnit.start(); - }, timeout); - } - } -}; - -// Backwards compatibility, deprecated -QUnit.equals = QUnit.equal; -QUnit.same = QUnit.deepEqual; - -// Maintain internal state -var config = { - // The queue of tests to run - queue: [], - - // block until document ready - blocking: true, - - // by default, run previously failed tests first - // very useful in combination with "Hide passed tests" checked - reorder: true, - - noglobals: false, - notrycatch: false -}; - -// Load paramaters -(function() { - var location = window.location || { search: "", protocol: "file:" }, - params = location.search.slice( 1 ).split( "&" ), - length = params.length, - urlParams = {}, - current; - - if ( params[ 0 ] ) { - for ( var i = 0; i < length; i++ ) { - current = params[ i ].split( "=" ); - current[ 0 ] = decodeURIComponent( current[ 0 ] ); - // allow just a key to turn on a flag, e.g., test.html?noglobals - current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true; - urlParams[ current[ 0 ] ] = current[ 1 ]; - if ( current[ 0 ] in config ) { - config[ current[ 0 ] ] = current[ 1 ]; - } - } - } - - QUnit.urlParams = urlParams; - config.filter = urlParams.filter; - - // Figure out if we're running the tests from a server or not - QUnit.isLocal = !!(location.protocol === 'file:'); -})(); - -// Expose the API as global variables, unless an 'exports' -// object exists, in that case we assume we're in CommonJS -if ( typeof exports === "undefined" || typeof require === "undefined" ) { - extend(window, QUnit); - window.QUnit = QUnit; -} else { - extend(exports, QUnit); - exports.QUnit = QUnit; -} - -// define these after exposing globals to keep them in these QUnit namespace only -extend(QUnit, { - config: config, - - // Initialize the configuration options - init: function() { - extend(config, { - stats: { all: 0, bad: 0 }, - moduleStats: { all: 0, bad: 0 }, - started: +new Date, - updateRate: 1000, - blocking: false, - autostart: true, - autorun: false, - filter: "", - queue: [], - semaphore: 0 - }); - - var tests = id( "qunit-tests" ), - banner = id( "qunit-banner" ), - result = id( "qunit-testresult" ); - - if ( tests ) { - tests.innerHTML = ""; - } - - if ( banner ) { - banner.className = ""; - } - - if ( result ) { - result.parentNode.removeChild( result ); - } - - if ( tests ) { - result = document.createElement( "p" ); - result.id = "qunit-testresult"; - result.className = "result"; - tests.parentNode.insertBefore( result, tests ); - result.innerHTML = 'Running...
     '; - } - }, - - /** - * Resets the test setup. Useful for tests that modify the DOM. - * - * If jQuery is available, uses jQuery's html(), otherwise just innerHTML. - */ - reset: function() { - if ( window.jQuery ) { - jQuery( "#qunit-fixture" ).html( config.fixture ); - } else { - var main = id( 'qunit-fixture' ); - if ( main ) { - main.innerHTML = config.fixture; - } - } - }, - - /** - * Trigger an event on an element. - * - * @example triggerEvent( document.body, "click" ); - * - * @param DOMElement elem - * @param String type - */ - triggerEvent: function( elem, type, event ) { - if ( document.createEvent ) { - event = document.createEvent("MouseEvents"); - event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView, - 0, 0, 0, 0, 0, false, false, false, false, 0, null); - elem.dispatchEvent( event ); - - } else if ( elem.fireEvent ) { - elem.fireEvent("on"+type); - } - }, - - // Safe object type checking - is: function( type, obj ) { - return QUnit.objectType( obj ) == type; - }, - - objectType: function( obj ) { - if (typeof obj === "undefined") { - return "undefined"; - - // consider: typeof null === object - } - if (obj === null) { - return "null"; - } - - var type = Object.prototype.toString.call( obj ) - .match(/^\[object\s(.*)\]$/)[1] || ''; - - switch (type) { - case 'Number': - if (isNaN(obj)) { - return "nan"; - } else { - return "number"; - } - case 'String': - case 'Boolean': - case 'Array': - case 'Date': - case 'RegExp': - case 'Function': - return type.toLowerCase(); - } - if (typeof obj === "object") { - return "object"; - } - return undefined; - }, - - push: function(result, actual, expected, message) { - var details = { - result: result, - message: message, - actual: actual, - expected: expected - }; - - message = escapeHtml(message) || (result ? "okay" : "failed"); - message = '' + message + ""; - expected = escapeHtml(QUnit.jsDump.parse(expected)); - actual = escapeHtml(QUnit.jsDump.parse(actual)); - var output = message + ''; - if (actual != expected) { - output += ''; - output += ''; - } - if (!result) { - var source = sourceFromStacktrace(); - if (source) { - details.source = source; - output += ''; - } - } - output += "
    Expected:
    ' + expected + '
    Result:
    ' + actual + '
    Diff:
    ' + QUnit.diff(expected, actual) +'
    Source:
    ' + escapeHtml(source) + '
    "; - - QUnit.log(details); - - config.current.assertions.push({ - result: !!result, - message: output - }); - }, - - url: function( params ) { - params = extend( extend( {}, QUnit.urlParams ), params ); - var querystring = "?", - key; - for ( key in params ) { - querystring += encodeURIComponent( key ) + "=" + - encodeURIComponent( params[ key ] ) + "&"; - } - return window.location.pathname + querystring.slice( 0, -1 ); - }, - - // Logging callbacks; all receive a single argument with the listed properties - // run test/logs.html for any related changes - begin: function() {}, - // done: { failed, passed, total, runtime } - done: function() {}, - // log: { result, actual, expected, message } - log: function() {}, - // testStart: { name } - testStart: function() {}, - // testDone: { name, failed, passed, total } - testDone: function() {}, - // moduleStart: { name } - moduleStart: function() {}, - // moduleDone: { name, failed, passed, total } - moduleDone: function() {} -}); - -if ( typeof document === "undefined" || document.readyState === "complete" ) { - config.autorun = true; -} - -addEvent(window, "load", function() { - QUnit.begin({}); - - // Initialize the config, saving the execution queue - var oldconfig = extend({}, config); - QUnit.init(); - extend(config, oldconfig); - - config.blocking = false; - - var userAgent = id("qunit-userAgent"); - if ( userAgent ) { - userAgent.innerHTML = navigator.userAgent; - } - var banner = id("qunit-header"); - if ( banner ) { - banner.innerHTML = ' ' + banner.innerHTML + ' ' + - '' + - ''; - addEvent( banner, "change", function( event ) { - var params = {}; - params[ event.target.name ] = event.target.checked ? true : undefined; - window.location = QUnit.url( params ); - }); - } - - var toolbar = id("qunit-testrunner-toolbar"); - if ( toolbar ) { - var filter = document.createElement("input"); - filter.type = "checkbox"; - filter.id = "qunit-filter-pass"; - addEvent( filter, "click", function() { - var ol = document.getElementById("qunit-tests"); - if ( filter.checked ) { - ol.className = ol.className + " hidepass"; - } else { - var tmp = " " + ol.className.replace( /[\n\t\r]/g, " " ) + " "; - ol.className = tmp.replace(/ hidepass /, " "); - } - if ( defined.sessionStorage ) { - if (filter.checked) { - sessionStorage.setItem("qunit-filter-passed-tests", "true"); - } else { - sessionStorage.removeItem("qunit-filter-passed-tests"); - } - } - }); - if ( defined.sessionStorage && sessionStorage.getItem("qunit-filter-passed-tests") ) { - filter.checked = true; - var ol = document.getElementById("qunit-tests"); - ol.className = ol.className + " hidepass"; - } - toolbar.appendChild( filter ); - - var label = document.createElement("label"); - label.setAttribute("for", "qunit-filter-pass"); - label.innerHTML = "Hide passed tests"; - toolbar.appendChild( label ); - } - - var main = id('qunit-fixture'); - if ( main ) { - config.fixture = main.innerHTML; - } - - if (config.autostart) { - QUnit.start(); - } -}); - -function done() { - config.autorun = true; - - // Log the last module results - if ( config.currentModule ) { - QUnit.moduleDone( { - name: config.currentModule, - failed: config.moduleStats.bad, - passed: config.moduleStats.all - config.moduleStats.bad, - total: config.moduleStats.all - } ); - } - - var banner = id("qunit-banner"), - tests = id("qunit-tests"), - runtime = +new Date - config.started, - passed = config.stats.all - config.stats.bad, - html = [ - 'Tests completed in ', - runtime, - ' milliseconds.
    ', - '', - passed, - ' tests of ', - config.stats.all, - ' passed, ', - config.stats.bad, - ' failed.' - ].join(''); - - if ( banner ) { - banner.className = (config.stats.bad ? "qunit-fail" : "qunit-pass"); - } - - if ( tests ) { - id( "qunit-testresult" ).innerHTML = html; - } - - if ( typeof document !== "undefined" && document.title ) { - // show ✖ for good, ✔ for bad suite result in title - // use escape sequences in case file gets loaded with non-utf-8-charset - document.title = (config.stats.bad ? "\u2716" : "\u2714") + " " + document.title; - } - - QUnit.done( { - failed: config.stats.bad, - passed: passed, - total: config.stats.all, - runtime: runtime - } ); -} - -function validTest( name ) { - var filter = config.filter, - run = false; - - if ( !filter ) { - return true; - } - - var not = filter.charAt( 0 ) === "!"; - if ( not ) { - filter = filter.slice( 1 ); - } - - if ( name.indexOf( filter ) !== -1 ) { - return !not; - } - - if ( not ) { - run = true; - } - - return run; -} - -// so far supports only Firefox, Chrome and Opera (buggy) -// could be extended in the future to use something like https://github.com/csnover/TraceKit -function sourceFromStacktrace() { - try { - throw new Error(); - } catch ( e ) { - if (e.stacktrace) { - // Opera - return e.stacktrace.split("\n")[6]; - } else if (e.stack) { - // Firefox, Chrome - return e.stack.split("\n")[4]; - } - } -} - -function escapeHtml(s) { - if (!s) { - return ""; - } - s = s + ""; - return s.replace(/[\&"<>\\]/g, function(s) { - switch(s) { - case "&": return "&"; - case "\\": return "\\\\"; - case '"': return '\"'; - case "<": return "<"; - case ">": return ">"; - default: return s; - } - }); -} - -function synchronize( callback ) { - config.queue.push( callback ); - - if ( config.autorun && !config.blocking ) { - process(); - } -} - -function process() { - var start = (new Date()).getTime(); - - while ( config.queue.length && !config.blocking ) { - if ( config.updateRate <= 0 || (((new Date()).getTime() - start) < config.updateRate) ) { - config.queue.shift()(); - } else { - window.setTimeout( process, 13 ); - break; - } - } - if (!config.blocking && !config.queue.length) { - done(); - } -} - -function saveGlobal() { - config.pollution = []; - - if ( config.noglobals ) { - for ( var key in window ) { - config.pollution.push( key ); - } - } -} - -function checkPollution( name ) { - var old = config.pollution; - saveGlobal(); - - var newGlobals = diff( config.pollution, old ); - if ( newGlobals.length > 0 ) { - ok( false, "Introduced global variable(s): " + newGlobals.join(", ") ); - } - - var deletedGlobals = diff( old, config.pollution ); - if ( deletedGlobals.length > 0 ) { - ok( false, "Deleted global variable(s): " + deletedGlobals.join(", ") ); - } -} - -// returns a new Array with the elements that are in a but not in b -function diff( a, b ) { - var result = a.slice(); - for ( var i = 0; i < result.length; i++ ) { - for ( var j = 0; j < b.length; j++ ) { - if ( result[i] === b[j] ) { - result.splice(i, 1); - i--; - break; - } - } - } - return result; -} - -function fail(message, exception, callback) { - if ( typeof console !== "undefined" && console.error && console.warn ) { - console.error(message); - console.error(exception); - console.warn(callback.toString()); - - } else if ( window.opera && opera.postError ) { - opera.postError(message, exception, callback.toString); - } -} - -function extend(a, b) { - for ( var prop in b ) { - if ( b[prop] === undefined ) { - delete a[prop]; - } else { - a[prop] = b[prop]; - } - } - - return a; -} - -function addEvent(elem, type, fn) { - if ( elem.addEventListener ) { - elem.addEventListener( type, fn, false ); - } else if ( elem.attachEvent ) { - elem.attachEvent( "on" + type, fn ); - } else { - fn(); - } -} - -function id(name) { - return !!(typeof document !== "undefined" && document && document.getElementById) && - document.getElementById( name ); -} - -// Test for equality any JavaScript type. -// Discussions and reference: http://philrathe.com/articles/equiv -// Test suites: http://philrathe.com/tests/equiv -// Author: Philippe Rathé -QUnit.equiv = function () { - - var innerEquiv; // the real equiv function - var callers = []; // stack to decide between skip/abort functions - var parents = []; // stack to avoiding loops from circular referencing - - // Call the o related callback with the given arguments. - function bindCallbacks(o, callbacks, args) { - var prop = QUnit.objectType(o); - if (prop) { - if (QUnit.objectType(callbacks[prop]) === "function") { - return callbacks[prop].apply(callbacks, args); - } else { - return callbacks[prop]; // or undefined - } - } - } - - var callbacks = function () { - - // for string, boolean, number and null - function useStrictEquality(b, a) { - if (b instanceof a.constructor || a instanceof b.constructor) { - // to catch short annotaion VS 'new' annotation of a declaration - // e.g. var i = 1; - // var j = new Number(1); - return a == b; - } else { - return a === b; - } - } - - return { - "string": useStrictEquality, - "boolean": useStrictEquality, - "number": useStrictEquality, - "null": useStrictEquality, - "undefined": useStrictEquality, - - "nan": function (b) { - return isNaN(b); - }, - - "date": function (b, a) { - return QUnit.objectType(b) === "date" && a.valueOf() === b.valueOf(); - }, - - "regexp": function (b, a) { - return QUnit.objectType(b) === "regexp" && - a.source === b.source && // the regex itself - a.global === b.global && // and its modifers (gmi) ... - a.ignoreCase === b.ignoreCase && - a.multiline === b.multiline; - }, - - // - skip when the property is a method of an instance (OOP) - // - abort otherwise, - // initial === would have catch identical references anyway - "function": function () { - var caller = callers[callers.length - 1]; - return caller !== Object && - typeof caller !== "undefined"; - }, - - "array": function (b, a) { - var i, j, loop; - var len; - - // b could be an object literal here - if ( ! (QUnit.objectType(b) === "array")) { - return false; - } - - len = a.length; - if (len !== b.length) { // safe and faster - return false; - } - - //track reference to avoid circular references - parents.push(a); - for (i = 0; i < len; i++) { - loop = false; - for(j=0;j= 0) { - type = "array"; - } else { - type = typeof obj; - } - return type; - }, - separator:function() { - return this.multiline ? this.HTML ? '
    ' : '\n' : this.HTML ? ' ' : ' '; - }, - indent:function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing - if ( !this.multiline ) - return ''; - var chr = this.indentChar; - if ( this.HTML ) - chr = chr.replace(/\t/g,' ').replace(/ /g,' '); - return Array( this._depth_ + (extra||0) ).join(chr); - }, - up:function( a ) { - this._depth_ += a || 1; - }, - down:function( a ) { - this._depth_ -= a || 1; - }, - setParser:function( name, parser ) { - this.parsers[name] = parser; - }, - // The next 3 are exposed so you can use them - quote:quote, - literal:literal, - join:join, - // - _depth_: 1, - // This is the list of parsers, to modify them, use jsDump.setParser - parsers:{ - window: '[Window]', - document: '[Document]', - error:'[ERROR]', //when no parser is found, shouldn't happen - unknown: '[Unknown]', - 'null':'null', - 'undefined':'undefined', - 'function':function( fn ) { - var ret = 'function', - name = 'name' in fn ? fn.name : (reName.exec(fn)||[])[1];//functions never have name in IE - if ( name ) - ret += ' ' + name; - ret += '('; - - ret = [ ret, QUnit.jsDump.parse( fn, 'functionArgs' ), '){'].join(''); - return join( ret, QUnit.jsDump.parse(fn,'functionCode'), '}' ); - }, - array: array, - nodelist: array, - arguments: array, - object:function( map ) { - var ret = [ ]; - QUnit.jsDump.up(); - for ( var key in map ) - ret.push( QUnit.jsDump.parse(key,'key') + ': ' + QUnit.jsDump.parse(map[key]) ); - QUnit.jsDump.down(); - return join( '{', ret, '}' ); - }, - node:function( node ) { - var open = QUnit.jsDump.HTML ? '<' : '<', - close = QUnit.jsDump.HTML ? '>' : '>'; - - var tag = node.nodeName.toLowerCase(), - ret = open + tag; - - for ( var a in QUnit.jsDump.DOMAttrs ) { - var val = node[QUnit.jsDump.DOMAttrs[a]]; - if ( val ) - ret += ' ' + a + '=' + QUnit.jsDump.parse( val, 'attribute' ); - } - return ret + close + open + '/' + tag + close; - }, - functionArgs:function( fn ) {//function calls it internally, it's the arguments part of the function - var l = fn.length; - if ( !l ) return ''; - - var args = Array(l); - while ( l-- ) - args[l] = String.fromCharCode(97+l);//97 is 'a' - return ' ' + args.join(', ') + ' '; - }, - key:quote, //object calls it internally, the key part of an item in a map - functionCode:'[code]', //function calls it internally, it's the content of the function - attribute:quote, //node calls it internally, it's an html attribute value - string:quote, - date:quote, - regexp:literal, //regex - number:literal, - 'boolean':literal - }, - DOMAttrs:{//attributes to dump from nodes, name=>realName - id:'id', - name:'name', - 'class':'className' - }, - HTML:false,//if true, entities are escaped ( <, >, \t, space and \n ) - indentChar:' ',//indentation unit - multiline:true //if true, items in a collection, are separated by a \n, else just a space. - }; - - return jsDump; -})(); - -// from Sizzle.js -function getText( elems ) { - var ret = "", elem; - - for ( var i = 0; elems[i]; i++ ) { - elem = elems[i]; - - // Get the text from text nodes and CDATA nodes - if ( elem.nodeType === 3 || elem.nodeType === 4 ) { - ret += elem.nodeValue; - - // Traverse everything else, except comment nodes - } else if ( elem.nodeType !== 8 ) { - ret += getText( elem.childNodes ); - } - } - - return ret; -}; - -/* - * Javascript Diff Algorithm - * By John Resig (http://ejohn.org/) - * Modified by Chu Alan "sprite" - * - * Released under the MIT license. - * - * More Info: - * http://ejohn.org/projects/javascript-diff-algorithm/ - * - * Usage: QUnit.diff(expected, actual) - * - * QUnit.diff("the quick brown fox jumped over", "the quick fox jumps over") == "the quick brown fox jumped jumps over" - */ -QUnit.diff = (function() { - function diff(o, n){ - var ns = new Object(); - var os = new Object(); - - for (var i = 0; i < n.length; i++) { - if (ns[n[i]] == null) - ns[n[i]] = { - rows: new Array(), - o: null - }; - ns[n[i]].rows.push(i); - } - - for (var i = 0; i < o.length; i++) { - if (os[o[i]] == null) - os[o[i]] = { - rows: new Array(), - n: null - }; - os[o[i]].rows.push(i); - } - - for (var i in ns) { - if (ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1) { - n[ns[i].rows[0]] = { - text: n[ns[i].rows[0]], - row: os[i].rows[0] - }; - o[os[i].rows[0]] = { - text: o[os[i].rows[0]], - row: ns[i].rows[0] - }; - } - } - - for (var i = 0; i < n.length - 1; i++) { - if (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null && - n[i + 1] == o[n[i].row + 1]) { - n[i + 1] = { - text: n[i + 1], - row: n[i].row + 1 - }; - o[n[i].row + 1] = { - text: o[n[i].row + 1], - row: i + 1 - }; - } - } - - for (var i = n.length - 1; i > 0; i--) { - if (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null && - n[i - 1] == o[n[i].row - 1]) { - n[i - 1] = { - text: n[i - 1], - row: n[i].row - 1 - }; - o[n[i].row - 1] = { - text: o[n[i].row - 1], - row: i - 1 - }; - } - } - - return { - o: o, - n: n - }; - } - - return function(o, n){ - o = o.replace(/\s+$/, ''); - n = n.replace(/\s+$/, ''); - var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/)); - - var str = ""; - - var oSpace = o.match(/\s+/g); - if (oSpace == null) { - oSpace = [" "]; - } - else { - oSpace.push(" "); - } - var nSpace = n.match(/\s+/g); - if (nSpace == null) { - nSpace = [" "]; - } - else { - nSpace.push(" "); - } - - if (out.n.length == 0) { - for (var i = 0; i < out.o.length; i++) { - str += '' + out.o[i] + oSpace[i] + ""; - } - } - else { - if (out.n[0].text == null) { - for (n = 0; n < out.o.length && out.o[n].text == null; n++) { - str += '' + out.o[n] + oSpace[n] + ""; - } - } - - for (var i = 0; i < out.n.length; i++) { - if (out.n[i].text == null) { - str += '' + out.n[i] + nSpace[i] + ""; - } - else { - var pre = ""; - - for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++) { - pre += '' + out.o[n] + oSpace[n] + ""; - } - str += " " + out.n[i].text + nSpace[i] + pre; - } - } - } - - return str; - }; -})(); - -})(this); diff --git a/test/stress_phystoken.tok b/test/stress_phystoken.tok deleted file mode 100644 index 8d1b6bec..00000000 --- a/test/stress_phystoken.tok +++ /dev/null @@ -1,52 +0,0 @@ -# Here's some random Python so that test_tokenize_myself will have some -# stressful stuff to try. This file is .tok instead of .py so pylint won't -# complain about it, check_eol won't look at it, etc. - -first_back = """\ -hey there! -""" - -other_back = """ -hey \ -there -""" - -lots_of_back = """\ -hey \ -there -""" -# This next line is supposed to have trailing whitespace: -fake_back = """\ -ouch -""" - -# Lots of difficulty happens with code like: -# -# fake_back = """\ -# ouch -# """ -# -# Ugh, the edge cases... - -# What about a comment like this\ -"what's this string doing here?" - -class C(object): - def there(): - this = 5 + \ - 7 - that = \ - "a continued line" - -cont1 = "one line of text" + \ - "another line of text" - -a_long_string = \ - "part 1" \ - "2" \ - "3 is longer" - -def hello(): - print("Hello world!") - -hello() diff --git a/test/stress_phystoken_dos.tok b/test/stress_phystoken_dos.tok deleted file mode 100644 index b08fd70e..00000000 --- a/test/stress_phystoken_dos.tok +++ /dev/null @@ -1,52 +0,0 @@ -# Here's some random Python so that test_tokenize_myself will have some -# stressful stuff to try. This file is .tok instead of .py so pylint won't -# complain about it, check_eol won't look at it, etc. - -first_back = """\ -hey there! -""" - -other_back = """ -hey \ -there -""" - -lots_of_back = """\ -hey \ -there -""" -# This next line is supposed to have trailing whitespace: -fake_back = """\ -ouch -""" - -# Lots of difficulty happens with code like: -# -# fake_back = """\ -# ouch -# """ -# -# Ugh, the edge cases... - -# What about a comment like this\ -"what's this string doing here?" - -class C(object): - def there(): - this = 5 + \ - 7 - that = \ - "a continued line" - -cont1 = "one line of text" + \ - "another line of text" - -a_long_string = \ - "part 1" \ - "2" \ - "3 is longer" - -def hello(): - print("Hello world!") - -hello() diff --git a/test/test_api.py b/test/test_api.py deleted file mode 100644 index 559684b8..00000000 --- a/test/test_api.py +++ /dev/null @@ -1,571 +0,0 @@ -"""Tests for Coverage's api.""" - -import fnmatch, os, re, sys, textwrap - -import coverage -from coverage.backward import StringIO - -from test.coveragetest import CoverageTest - - -class SingletonApiTest(CoverageTest): - """Tests of the old-fashioned singleton API.""" - - def setUp(self): - super(SingletonApiTest, self).setUp() - # These tests use the singleton module interface. Prevent it from - # writing .coverage files at exit. - coverage.use_cache(0) - - def do_report_work(self, modname): - """Create a module named `modname`, then measure it.""" - coverage.erase() - - self.make_file(modname+".py", """\ - a = 1 - b = 2 - if b == 3: - c = 4 - d = 5 - e = 6 - f = 7 - """) - - # Import the python file, executing it. - self.start_import_stop(coverage, modname) - - def test_simple(self): - coverage.erase() - - self.make_file("mycode.py", """\ - a = 1 - b = 2 - if b == 3: - c = 4 - d = 5 - """) - - # Import the python file, executing it. - self.start_import_stop(coverage, "mycode") - - _, statements, missing, missingtext = coverage.analysis("mycode.py") - self.assertEqual(statements, [1,2,3,4,5]) - self.assertEqual(missing, [4]) - self.assertEqual(missingtext, "4") - - def test_report(self): - self.do_report_work("mycode2") - coverage.report(["mycode2.py"]) - self.assertEqual(self.stdout(), textwrap.dedent("""\ - Name Stmts Miss Cover Missing - --------------------------------------- - mycode2 7 3 57% 4-6 - """)) - - def test_report_file(self): - # The file= argument of coverage.report makes the report go there. - self.do_report_work("mycode3") - fout = StringIO() - coverage.report(["mycode3.py"], file=fout) - self.assertEqual(self.stdout(), "") - self.assertEqual(fout.getvalue(), textwrap.dedent("""\ - Name Stmts Miss Cover Missing - --------------------------------------- - mycode3 7 3 57% 4-6 - """)) - - def test_report_default(self): - # Calling report() with no morfs will report on whatever was executed. - self.do_report_work("mycode4") - coverage.report() - rpt = re.sub(r"\s+", " ", self.stdout()) - self.assertIn("mycode4 7 3 57% 4-6", rpt) - - -class ApiTest(CoverageTest): - """Api-oriented tests for Coverage.""" - - def clean_files(self, files, pats): - """Remove names matching `pats` from `files`, a list of filenames.""" - good = [] - for f in files: - for pat in pats: - if fnmatch.fnmatch(f, pat): - break - else: - good.append(f) - return good - - def assertFiles(self, files): - """Assert that the files here are `files`, ignoring the usual junk.""" - here = os.listdir(".") - here = self.clean_files(here, ["*.pyc", "__pycache__"]) - self.assertSameElements(here, files) - - def test_unexecuted_file(self): - cov = coverage.coverage() - - self.make_file("mycode.py", """\ - a = 1 - b = 2 - if b == 3: - c = 4 - d = 5 - """) - - self.make_file("not_run.py", """\ - fooey = 17 - """) - - # Import the python file, executing it. - self.start_import_stop(cov, "mycode") - - _, statements, missing, _ = cov.analysis("not_run.py") - self.assertEqual(statements, [1]) - self.assertEqual(missing, [1]) - - def test_filenames(self): - - self.make_file("mymain.py", """\ - import mymod - a = 1 - """) - - self.make_file("mymod.py", """\ - fooey = 17 - """) - - # Import the python file, executing it. - cov = coverage.coverage() - self.start_import_stop(cov, "mymain") - - filename, _, _, _ = cov.analysis("mymain.py") - self.assertEqual(os.path.basename(filename), "mymain.py") - filename, _, _, _ = cov.analysis("mymod.py") - self.assertEqual(os.path.basename(filename), "mymod.py") - - filename, _, _, _ = cov.analysis(sys.modules["mymain"]) - self.assertEqual(os.path.basename(filename), "mymain.py") - filename, _, _, _ = cov.analysis(sys.modules["mymod"]) - self.assertEqual(os.path.basename(filename), "mymod.py") - - # Import the python file, executing it again, once it's been compiled - # already. - cov = coverage.coverage() - self.start_import_stop(cov, "mymain") - - filename, _, _, _ = cov.analysis("mymain.py") - self.assertEqual(os.path.basename(filename), "mymain.py") - filename, _, _, _ = cov.analysis("mymod.py") - self.assertEqual(os.path.basename(filename), "mymod.py") - - filename, _, _, _ = cov.analysis(sys.modules["mymain"]) - self.assertEqual(os.path.basename(filename), "mymain.py") - filename, _, _, _ = cov.analysis(sys.modules["mymod"]) - self.assertEqual(os.path.basename(filename), "mymod.py") - - def test_ignore_stdlib(self): - self.make_file("mymain.py", """\ - import colorsys - a = 1 - hls = colorsys.rgb_to_hls(1.0, 0.5, 0.0) - """) - - # Measure without the stdlib. - cov1 = coverage.coverage() - self.assertEqual(cov1.config.cover_pylib, False) - self.start_import_stop(cov1, "mymain") - - # some statements were marked executed in mymain.py - _, statements, missing, _ = cov1.analysis("mymain.py") - self.assertNotEqual(statements, missing) - # but none were in colorsys.py - _, statements, missing, _ = cov1.analysis("colorsys.py") - self.assertEqual(statements, missing) - - # Measure with the stdlib. - cov2 = coverage.coverage(cover_pylib=True) - self.start_import_stop(cov2, "mymain") - - # some statements were marked executed in mymain.py - _, statements, missing, _ = cov2.analysis("mymain.py") - self.assertNotEqual(statements, missing) - # and some were marked executed in colorsys.py - _, statements, missing, _ = cov2.analysis("colorsys.py") - self.assertNotEqual(statements, missing) - - def test_include_can_measure_stdlib(self): - self.make_file("mymain.py", """\ - import colorsys, random - a = 1 - r, g, b = [random.random() for _ in range(3)] - hls = colorsys.rgb_to_hls(r, g, b) - """) - - # Measure without the stdlib, but include colorsys. - cov1 = coverage.coverage(cover_pylib=False, include=["*/colorsys.py"]) - self.start_import_stop(cov1, "mymain") - - # some statements were marked executed in colorsys.py - _, statements, missing, _ = cov1.analysis("colorsys.py") - self.assertNotEqual(statements, missing) - # but none were in random.py - _, statements, missing, _ = cov1.analysis("random.py") - self.assertEqual(statements, missing) - - def test_exclude_list(self): - cov = coverage.coverage() - cov.clear_exclude() - self.assertEqual(cov.get_exclude_list(), []) - cov.exclude("foo") - self.assertEqual(cov.get_exclude_list(), ["foo"]) - cov.exclude("bar") - self.assertEqual(cov.get_exclude_list(), ["foo", "bar"]) - self.assertEqual(cov._exclude_regex('exclude'), "(foo)|(bar)") - cov.clear_exclude() - self.assertEqual(cov.get_exclude_list(), []) - - def test_exclude_partial_list(self): - cov = coverage.coverage() - cov.clear_exclude(which='partial') - self.assertEqual(cov.get_exclude_list(which='partial'), []) - cov.exclude("foo", which='partial') - self.assertEqual(cov.get_exclude_list(which='partial'), ["foo"]) - cov.exclude("bar", which='partial') - self.assertEqual(cov.get_exclude_list(which='partial'), ["foo", "bar"]) - self.assertEqual(cov._exclude_regex(which='partial'), "(foo)|(bar)") - cov.clear_exclude(which='partial') - self.assertEqual(cov.get_exclude_list(which='partial'), []) - - def test_exclude_and_partial_are_separate_lists(self): - cov = coverage.coverage() - cov.clear_exclude(which='partial') - cov.clear_exclude(which='exclude') - cov.exclude("foo", which='partial') - self.assertEqual(cov.get_exclude_list(which='partial'), ['foo']) - self.assertEqual(cov.get_exclude_list(which='exclude'), []) - cov.exclude("bar", which='exclude') - self.assertEqual(cov.get_exclude_list(which='partial'), ['foo']) - self.assertEqual(cov.get_exclude_list(which='exclude'), ['bar']) - cov.exclude("p2", which='partial') - cov.exclude("e2", which='exclude') - self.assertEqual(cov.get_exclude_list(which='partial'), ['foo', 'p2']) - self.assertEqual(cov.get_exclude_list(which='exclude'), ['bar', 'e2']) - cov.clear_exclude(which='partial') - self.assertEqual(cov.get_exclude_list(which='partial'), []) - self.assertEqual(cov.get_exclude_list(which='exclude'), ['bar', 'e2']) - cov.clear_exclude(which='exclude') - self.assertEqual(cov.get_exclude_list(which='partial'), []) - self.assertEqual(cov.get_exclude_list(which='exclude'), []) - - def test_datafile_default(self): - # Default data file behavior: it's .coverage - self.make_file("datatest1.py", """\ - fooey = 17 - """) - - self.assertFiles(["datatest1.py"]) - cov = coverage.coverage() - self.start_import_stop(cov, "datatest1") - cov.save() - self.assertFiles(["datatest1.py", ".coverage"]) - - def test_datafile_specified(self): - # You can specify the data file name. - self.make_file("datatest2.py", """\ - fooey = 17 - """) - - self.assertFiles(["datatest2.py"]) - cov = coverage.coverage(data_file="cov.data") - self.start_import_stop(cov, "datatest2") - cov.save() - self.assertFiles(["datatest2.py", "cov.data"]) - - def test_datafile_and_suffix_specified(self): - # You can specify the data file name and suffix. - self.make_file("datatest3.py", """\ - fooey = 17 - """) - - self.assertFiles(["datatest3.py"]) - cov = coverage.coverage(data_file="cov.data", data_suffix="14") - self.start_import_stop(cov, "datatest3") - cov.save() - self.assertFiles(["datatest3.py", "cov.data.14"]) - - def test_datafile_from_rcfile(self): - # You can specify the data file name in the .coveragerc file - self.make_file("datatest4.py", """\ - fooey = 17 - """) - self.make_file(".coveragerc", """\ - [run] - data_file = mydata.dat - """) - - self.assertFiles(["datatest4.py", ".coveragerc"]) - cov = coverage.coverage() - self.start_import_stop(cov, "datatest4") - cov.save() - self.assertFiles(["datatest4.py", ".coveragerc", "mydata.dat"]) - - def test_empty_reporting(self): - # Used to be you'd get an exception reporting on nothing... - cov = coverage.coverage() - cov.erase() - cov.report() - - def test_start_stop_start_stop(self): - self.make_file("code1.py", """\ - code1 = 1 - """) - self.make_file("code2.py", """\ - code2 = 1 - code2 = 2 - """) - cov = coverage.coverage() - self.start_import_stop(cov, "code1") - cov.save() - self.start_import_stop(cov, "code2") - _, statements, missing, _ = cov.analysis("code1.py") - self.assertEqual(statements, [1]) - self.assertEqual(missing, []) - _, statements, missing, _ = cov.analysis("code2.py") - self.assertEqual(statements, [1, 2]) - self.assertEqual(missing, []) - - if 0: # expected failure - # for https://bitbucket.org/ned/coveragepy/issue/79 - def test_start_save_stop(self): - self.make_file("code1.py", """\ - code1 = 1 - """) - self.make_file("code2.py", """\ - code2 = 1 - code2 = 2 - """) - cov = coverage.coverage() - cov.start() - self.import_local_file("code1") - cov.save() - self.import_local_file("code2") - cov.stop() - - _, statements, missing, _ = cov.analysis("code1.py") - self.assertEqual(statements, [1]) - self.assertEqual(missing, []) - _, statements, missing, _ = cov.analysis("code2.py") - self.assertEqual(statements, [1, 2]) - self.assertEqual(missing, []) - - - -class UsingModulesMixin(object): - """A mixin for importing modules from test/modules and test/moremodules.""" - - run_in_temp_dir = False - - def setUp(self): - super(UsingModulesMixin, self).setUp() - # Parent class saves and restores sys.path, we can just modify it. - self.old_dir = os.getcwd() - os.chdir(self.nice_file(os.path.dirname(__file__), 'modules')) - sys.path.append(".") - sys.path.append("../moremodules") - - def tearDown(self): - os.chdir(self.old_dir) - super(UsingModulesMixin, self).tearDown() - - -class OmitIncludeTestsMixin(UsingModulesMixin): - """Test methods for coverage methods taking include and omit.""" - - def filenames_in(self, summary, filenames): - """Assert the `filenames` are in the keys of `summary`.""" - for filename in filenames.split(): - self.assertIn(filename, summary) - - def filenames_not_in(self, summary, filenames): - """Assert the `filenames` are not in the keys of `summary`.""" - for filename in filenames.split(): - self.assertNotIn(filename, summary) - - def test_nothing_specified(self): - result = self.coverage_usepkgs() - self.filenames_in(result, "p1a p1b p2a p2b othera otherb osa osb") - self.filenames_not_in(result, "p1c") - # Because there was no source= specified, we don't search for - # unexecuted files. - - def test_include(self): - result = self.coverage_usepkgs(include=["*/p1a.py"]) - self.filenames_in(result, "p1a") - self.filenames_not_in(result, "p1b p1c p2a p2b othera otherb osa osb") - - def test_include_2(self): - result = self.coverage_usepkgs(include=["*a.py"]) - self.filenames_in(result, "p1a p2a othera osa") - self.filenames_not_in(result, "p1b p1c p2b otherb osb") - - def test_include_as_string(self): - result = self.coverage_usepkgs(include="*a.py") - self.filenames_in(result, "p1a p2a othera osa") - self.filenames_not_in(result, "p1b p1c p2b otherb osb") - - def test_omit(self): - result = self.coverage_usepkgs(omit=["*/p1a.py"]) - self.filenames_in(result, "p1b p2a p2b") - self.filenames_not_in(result, "p1a p1c") - - def test_omit_2(self): - result = self.coverage_usepkgs(omit=["*a.py"]) - self.filenames_in(result, "p1b p2b otherb osb") - self.filenames_not_in(result, "p1a p1c p2a othera osa") - - def test_omit_as_string(self): - result = self.coverage_usepkgs(omit="*a.py") - self.filenames_in(result, "p1b p2b otherb osb") - self.filenames_not_in(result, "p1a p1c p2a othera osa") - - def test_omit_and_include(self): - result = self.coverage_usepkgs( include=["*/p1*"], omit=["*/p1a.py"]) - self.filenames_in(result, "p1b") - self.filenames_not_in(result, "p1a p1c p2a p2b") - - -class SourceOmitIncludeTest(OmitIncludeTestsMixin, CoverageTest): - """Test using `source`, `omit` and `include` when measuring code.""" - - def coverage_usepkgs(self, **kwargs): - """Run coverage on usepkgs and return the line summary. - - Arguments are passed to the `coverage.coverage` constructor. - - """ - cov = coverage.coverage(**kwargs) - cov.start() - import usepkgs # pragma: nested # pylint: disable=F0401,W0612 - cov.stop() # pragma: nested - cov._harvest_data() # private! sshhh... - summary = cov.data.summary() - for k, v in list(summary.items()): - assert k.endswith(".py") - summary[k[:-3]] = v - return summary - - def test_source_package(self): - lines = self.coverage_usepkgs(source=["pkg1"]) - self.filenames_in(lines, "p1a p1b") - self.filenames_not_in(lines, "p2a p2b othera otherb osa osb") - # Because source= was specified, we do search for unexecuted files. - self.assertEqual(lines['p1c'], 0) - - def test_source_package_dotted(self): - lines = self.coverage_usepkgs(source=["pkg1.p1b"]) - self.filenames_in(lines, "p1b") - self.filenames_not_in(lines, "p1a p1c p2a p2b othera otherb osa osb") - - -class ReportIncludeOmitTest(OmitIncludeTestsMixin, CoverageTest): - """Tests of the report include/omit functionality.""" - - def coverage_usepkgs(self, **kwargs): - """Try coverage.report().""" - cov = coverage.coverage() - cov.start() - import usepkgs # pragma: nested # pylint: disable=F0401,W0612 - cov.stop() # pragma: nested - report = StringIO() - cov.report(file=report, **kwargs) - return report.getvalue() - - -class XmlIncludeOmitTest(OmitIncludeTestsMixin, CoverageTest): - """Tests of the xml include/omit functionality. - - This also takes care of the HTML and annotate include/omit, by virtue - of the structure of the code. - - """ - - def coverage_usepkgs(self, **kwargs): - """Try coverage.xml_report().""" - cov = coverage.coverage() - cov.start() - import usepkgs # pragma: nested # pylint: disable=F0401,W0612 - cov.stop() # pragma: nested - cov.xml_report(outfile="-", **kwargs) - return self.stdout() - - -class AnalysisTest(CoverageTest): - """Test the numerical analysis of results.""" - def test_many_missing_branches(self): - cov = coverage.coverage(branch=True) - - self.make_file("missing.py", """\ - def fun1(x): - if x == 1: - print("one") - else: - print("not one") - print("done") # pragma: nocover - - def fun2(x): - print("x") - - fun2(3) - """) - - # Import the python file, executing it. - self.start_import_stop(cov, "missing") - - nums = cov._analyze("missing.py").numbers - self.assertEqual(nums.n_files, 1) - self.assertEqual(nums.n_statements, 7) - self.assertEqual(nums.n_excluded, 1) - self.assertEqual(nums.n_missing, 3) - self.assertEqual(nums.n_branches, 2) - self.assertEqual(nums.n_partial_branches, 0) - self.assertEqual(nums.n_missing_branches, 2) - - -class PluginTest(CoverageTest): - """Test that the API works properly the way the plugins call it. - - We don't actually use the plugins, but these tests call the API the same - way they do. - - """ - def pretend_to_be_nose_with_cover(self, erase): - """This is what the nose --with-cover plugin does.""" - cov = coverage.coverage() - - self.make_file("no_biggie.py", """\ - a = 1 - b = 2 - if b == 1: - c = 4 - """) - - if erase: - cov.combine() - cov.erase() - cov.load() - self.start_import_stop(cov, "no_biggie") - cov.combine() - cov.save() - cov.report(["no_biggie.py"]) - self.assertEqual(self.stdout(), textwrap.dedent("""\ - Name Stmts Miss Cover Missing - ----------------------------------------- - no_biggie 4 1 75% 4 - """)) - - def test_nose_plugin(self): - self.pretend_to_be_nose_with_cover(erase=False) - - def test_nose_plugin_with_erase(self): - self.pretend_to_be_nose_with_cover(erase=True) diff --git a/test/test_arcs.py b/test/test_arcs.py deleted file mode 100644 index 69c054cc..00000000 --- a/test/test_arcs.py +++ /dev/null @@ -1,578 +0,0 @@ -"""Tests for Coverage.py's arc measurement.""" - -import sys -from test.coveragetest import CoverageTest - - -class SimpleArcTest(CoverageTest): - """Tests for Coverage.py's arc measurement.""" - - def test_simple_sequence(self): - self.check_coverage("""\ - a = 1 - b = 2 - """, - arcz=".1 12 2.") - self.check_coverage("""\ - a = 1 - - b = 3 - """, - arcz=".1 13 3.") - self.check_coverage("""\ - - a = 2 - b = 3 - - c = 5 - """, - arcz=".2 23 35 5-2") - - def test_function_def(self): - self.check_coverage("""\ - def foo(): - a = 2 - - foo() - """, - arcz=".1 .2 14 2. 4.") - - def test_if(self): - self.check_coverage("""\ - a = 1 - if len([]) == 0: - a = 3 - assert a == 3 - """, - arcz=".1 12 23 24 34 4.", arcz_missing="24") - self.check_coverage("""\ - a = 1 - if len([]) == 1: - a = 3 - assert a == 1 - """, - arcz=".1 12 23 24 34 4.", arcz_missing="23 34") - - def test_if_else(self): - self.check_coverage("""\ - if len([]) == 0: - a = 2 - else: - a = 4 - assert a == 2 - """, - arcz=".1 12 25 14 45 5.", arcz_missing="14 45") - self.check_coverage("""\ - if len([]) == 1: - a = 2 - else: - a = 4 - assert a == 4 - """, - arcz=".1 12 25 14 45 5.", arcz_missing="12 25") - - def test_compact_if(self): - self.check_coverage("""\ - a = 1 - if len([]) == 0: a = 2 - assert a == 2 - """, - arcz=".1 12 23 3.", arcz_missing="") - self.check_coverage("""\ - def fn(x): - if x % 2: return True - return False - a = fn(1) - assert a == True - """, - arcz=".1 14 45 5. .2 2. 23 3.", arcz_missing="23 3.") - - def test_multiline(self): - # The firstlineno of the a assignment below differs among Python - # versions. - if sys.version_info >= (2, 5): - arcz = ".1 15 5-2" - else: - arcz = ".1 15 5-1" - self.check_coverage("""\ - a = ( - 2 + - 3 - ) - b = \\ - 6 - """, - arcz=arcz, arcz_missing="") - - def test_if_return(self): - self.check_coverage("""\ - def if_ret(a): - if a: - return 3 - b = 4 - return 5 - x = if_ret(0) + if_ret(1) - assert x == 8 - """, - arcz=".1 16 67 7. .2 23 24 3. 45 5.", arcz_missing="" - ) - - def test_dont_confuse_exit_and_else(self): - self.check_coverage("""\ - def foo(): - if foo: - a = 3 - else: - a = 5 - return a - assert foo() == 3 # 7 - """, - arcz=".1 17 7. .2 23 36 25 56 6.", arcz_missing="25 56" - ) - self.check_coverage("""\ - def foo(): - if foo: - a = 3 - else: - a = 5 - foo() # 6 - """, - arcz=".1 16 6. .2 23 3. 25 5.", arcz_missing="25 5." - ) - - if 0: # expected failure - def test_lambdas_are_confusing_bug_90(self): - self.check_coverage("""\ - a = 1 - fn = lambda x: x - b = 3 - """, - arcz=".1 12 .2 2-2 23 3." - ) - - -if sys.version_info >= (2, 6): - class WithTest(CoverageTest): - """Arc-measuring tests involving context managers.""" - - def test_with(self): - self.check_coverage("""\ - def example(): - with open("test", "w") as f: # exit - f.write("") - return 1 - - example() - """, - arcz=".1 .2 23 34 4. 16 6." - ) - - -class LoopArcTest(CoverageTest): - """Arc-measuring tests involving loops.""" - - def test_loop(self): - self.check_coverage("""\ - for i in range(10): - a = i - assert a == 9 - """, - arcz=".1 12 21 13 3.", arcz_missing="") - self.check_coverage("""\ - a = -1 - for i in range(0): - a = i - assert a == -1 - """, - arcz=".1 12 23 32 24 4.", arcz_missing="23 32") - - def test_nested_loop(self): - self.check_coverage("""\ - for i in range(3): - for j in range(3): - a = i + j - assert a == 4 - """, - arcz=".1 12 23 32 21 14 4.", arcz_missing="") - - def test_break(self): - self.check_coverage("""\ - for i in range(10): - a = i - break # 3 - a = 99 - assert a == 0 # 5 - """, - arcz=".1 12 23 35 15 41 5.", arcz_missing="15 41") - - def test_continue(self): - self.check_coverage("""\ - for i in range(10): - a = i - continue # 3 - a = 99 - assert a == 9 # 5 - """, - arcz=".1 12 23 31 15 41 5.", arcz_missing="41") - - def test_nested_breaks(self): - self.check_coverage("""\ - for i in range(3): - for j in range(3): - a = i + j - break # 4 - if i == 2: - break - assert a == 2 and i == 2 # 7 - """, - arcz=".1 12 23 34 45 25 56 51 67 17 7.", arcz_missing="17 25") - - def test_while_true(self): - # With "while 1", the loop knows it's constant. - self.check_coverage("""\ - a, i = 1, 0 - while 1: - if i >= 3: - a = 4 - break - i += 1 - assert a == 4 and i == 3 - """, - arcz=".1 12 23 34 45 36 63 57 7.", - ) - # With "while True", 2.x thinks it's computation, 3.x thinks it's - # constant. - if sys.version_info >= (3, 0): - arcz = ".1 12 23 34 45 36 63 57 7." - else: - arcz = ".1 12 23 27 34 45 36 62 57 7." - self.check_coverage("""\ - a, i = 1, 0 - while True: - if i >= 3: - a = 4 - break - i += 1 - assert a == 4 and i == 3 - """, - arcz=arcz, - ) - - def test_for_if_else_for(self): - self.check_coverage("""\ - def branches_2(l): - if l: - for e in l: - a = 4 - else: - a = 6 - - def branches_3(l): - for x in l: - if x: - for e in l: - a = 12 - else: - a = 14 - - branches_2([0,1]) - branches_3([0,1]) - """, - arcz= - ".1 18 8G GH H. " - ".2 23 34 43 26 3. 6. " - ".9 9A 9-8 AB BC CB B9 AE E9", - arcz_missing="26 6." - ) - - def test_for_else(self): - self.check_coverage("""\ - def forelse(seq): - for n in seq: - if n > 5: - break - else: - print('None of the values were greater than 5') - print('Done') - forelse([1,2]) - forelse([1,6]) - """, - arcz=".1 .2 23 32 34 47 26 67 7. 18 89 9." - ) - - def test_confusing_for_loop_bug_175(self): - if sys.version_info >= (3, 0): - # Py3 counts the list comp as a separate code object. - arcz = ".1 .2 2-2 12 23 34 45 53 3." - else: - arcz = ".1 12 23 34 45 53 3." - self.check_coverage("""\ - o = [(1,2), (3,4)] - o = [a for a in o] - for tup in o: - x = tup[0] - y = tup[1] - """, - arcz=arcz, arcz_missing="", arcz_unpredicted="") - if sys.version_info >= (3, 0): - arcz = ".1 12 .2 2-2 23 34 42 2." - else: - arcz = ".1 12 23 34 42 2." - self.check_coverage("""\ - o = [(1,2), (3,4)] - for tup in [a for a in o]: - x = tup[0] - y = tup[1] - """, - arcz=arcz, arcz_missing="", arcz_unpredicted="") - - -class ExceptionArcTest(CoverageTest): - """Arc-measuring tests involving exception handling.""" - - def test_try_except(self): - self.check_coverage("""\ - a, b = 1, 1 - try: - a = 3 - except: - b = 5 - assert a == 3 and b == 1 - """, - arcz=".1 12 23 36 45 56 6.", arcz_missing="45 56") - self.check_coverage("""\ - a, b = 1, 1 - try: - a = 3 - raise Exception("Yikes!") - a = 5 - except: - b = 7 - assert a == 3 and b == 7 - """, - arcz=".1 12 23 34 58 67 78 8.", - arcz_missing="58", arcz_unpredicted="46") - - def test_hidden_raise(self): - self.check_coverage("""\ - a, b = 1, 1 - def oops(x): - if x % 2: raise Exception("odd") - try: - a = 5 - oops(1) - a = 7 - except: - b = 9 - assert a == 5 and b == 9 - """, - arcz=".1 12 .3 3-2 24 45 56 67 7A 89 9A A.", - arcz_missing="67 7A", arcz_unpredicted="68") - - def test_except_with_type(self): - self.check_coverage("""\ - a, b = 1, 1 - def oops(x): - if x % 2: raise ValueError("odd") - def try_it(x): - try: - a = 6 - oops(x) - a = 8 - except ValueError: - b = 10 - return a - assert try_it(0) == 8 # C - assert try_it(1) == 6 # D - """, - arcz=".1 12 .3 3-2 24 4C CD D. .5 56 67 78 8B 9A AB B-4", - arcz_missing="", - arcz_unpredicted="79") - - def test_try_finally(self): - self.check_coverage("""\ - a, c = 1, 1 - try: - a = 3 - finally: - c = 5 - assert a == 3 and c == 5 - """, - arcz=".1 12 23 35 56 6.", arcz_missing="") - self.check_coverage("""\ - a, c, d = 1, 1, 1 - try: - try: - a = 4 - finally: - c = 6 - except: - d = 8 - assert a == 4 and c == 6 and d == 1 # 9 - """, - arcz=".1 12 23 34 46 67 78 89 69 9.", - arcz_missing="67 78 89", arcz_unpredicted="") - self.check_coverage("""\ - a, c, d = 1, 1, 1 - try: - try: - a = 4 - raise Exception("Yikes!") - a = 6 - finally: - c = 8 - except: - d = 10 # A - assert a == 4 and c == 8 and d == 10 # B - """, - arcz=".1 12 23 34 45 68 89 8B 9A AB B.", - arcz_missing="68 8B", arcz_unpredicted="58") - - def test_finally_in_loop(self): - self.check_coverage("""\ - a, c, d, i = 1, 1, 1, 99 - try: - for i in range(5): - try: - a = 5 - if i > 0: - raise Exception("Yikes!") - a = 8 - finally: - c = 10 - except: - d = 12 # C - assert a == 5 and c == 10 and d == 12 # D - """, - arcz=".1 12 23 34 3D 45 56 67 68 8A A3 AB AD BC CD D.", - arcz_missing="3D AD", arcz_unpredicted="7A") - self.check_coverage("""\ - a, c, d, i = 1, 1, 1, 99 - try: - for i in range(5): - try: - a = 5 - if i > 10: - raise Exception("Yikes!") - a = 8 - finally: - c = 10 - except: - d = 12 # C - assert a == 8 and c == 10 and d == 1 # D - """, - arcz=".1 12 23 34 3D 45 56 67 68 8A A3 AB AD BC CD D.", - arcz_missing="67 AB AD BC CD", arcz_unpredicted="") - - - def test_break_in_finally(self): - self.check_coverage("""\ - a, c, d, i = 1, 1, 1, 99 - try: - for i in range(5): - try: - a = 5 - if i > 0: - break - a = 8 - finally: - c = 10 - except: - d = 12 # C - assert a == 5 and c == 10 and d == 1 # D - """, - arcz=".1 12 23 34 3D 45 56 67 68 7A 8A A3 AB AD BC CD D.", - arcz_missing="3D AB BC CD", arcz_unpredicted="") - - if 1: # expected failure - def test_finally_in_loop_bug_92(self): - self.check_coverage("""\ - for i in range(5): - try: - j = 3 - finally: - f = 5 - g = 6 - h = 7 - """, - arcz=".1 12 23 35 56 61 17 7.", - arcz_missing="", arcz_unpredicted="") - - if sys.version_info >= (2, 5): - # Try-except-finally was new in 2.5 - def test_except_finally(self): - self.check_coverage("""\ - a, b, c = 1, 1, 1 - try: - a = 3 - except: - b = 5 - finally: - c = 7 - assert a == 3 and b == 1 and c == 7 - """, - arcz=".1 12 23 45 37 57 78 8.", arcz_missing="45 57") - self.check_coverage("""\ - a, b, c = 1, 1, 1 - def oops(x): - if x % 2: raise Exception("odd") - try: - a = 5 - oops(1) - a = 7 - except: - b = 9 - finally: - c = 11 - assert a == 5 and b == 9 and c == 11 - """, - arcz=".1 12 .3 3-2 24 45 56 67 7B 89 9B BC C.", - arcz_missing="67 7B", arcz_unpredicted="68") - - -class MiscArcTest(CoverageTest): - """Miscellaneous arc-measuring tests.""" - - def test_dict_literal(self): - self.check_coverage("""\ - d = { - 'a': 2, - 'b': 3, - 'c': { - 'd': 5, - 'e': 6, - } - } - assert d - """, - arcz=".1 19 9.") - - -class ExcludeTest(CoverageTest): - """Tests of exclusions to indicate known partial branches.""" - - def test_default(self): - # A number of forms of pragma comment are accepted. - self.check_coverage("""\ - a = 1 - if a: #pragma: no branch - b = 3 - c = 4 - if c: # pragma NOBRANCH - d = 6 - e = 7 - """, - [1,2,3,4,5,6,7], - arcz=".1 12 23 24 34 45 56 57 67 7.", arcz_missing="") - - def test_custom_pragmas(self): - self.check_coverage("""\ - a = 1 - while a: # [only some] - c = 3 - break - assert c == 5-2 - """, - [1,2,3,4,5], - partials=["only some"], - arcz=".1 12 23 34 45 25 5.", arcz_missing="") diff --git a/test/test_cmdline.py b/test/test_cmdline.py deleted file mode 100644 index 33f90212..00000000 --- a/test/test_cmdline.py +++ /dev/null @@ -1,702 +0,0 @@ -"""Test cmdline.py for coverage.""" - -import pprint, re, shlex, sys, textwrap -import mock -import coverage -import coverage.cmdline -from coverage.misc import ExceptionDuringRun - -from test.coveragetest import CoverageTest, OK, ERR - - -class CmdLineTest(CoverageTest): - """Tests of execution paths through the command line interpreter.""" - - run_in_temp_dir = False - - INIT_LOAD = """\ - .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=None) - .load()\n""" - - def model_object(self): - """Return a Mock suitable for use in CoverageScript.""" - mk = mock.Mock() - mk.coverage.return_value = mk - return mk - - def mock_command_line(self, args): - """Run `args` through the command line, with a Mock. - - Returns the Mock it used and the status code returned. - - """ - m = self.model_object() - ret = coverage.CoverageScript( - _covpkg=m, _run_python_file=m.run_python_file, - _run_python_module=m.run_python_module, _help_fn=m.help_fn - ).command_line(shlex.split(args)) - return m, ret - - def cmd_executes(self, args, code, ret=OK): - """Assert that the `args` end up executing the sequence in `code`.""" - m1, r1 = self.mock_command_line(args) - self.assertEqual(r1, ret, - "Wrong status: got %s, wanted %s" % (r1, ret) - ) - - # Remove all indentation, and change ".foo()" to "m2.foo()". - code = re.sub(r"(?m)^\s+", "", code) - code = re.sub(r"(?m)^\.", "m2.", code) - m2 = self.model_object() - code_obj = compile(code, "", "exec") - eval(code_obj, globals(), { 'm2': m2 }) - self.assert_same_method_calls(m1, m2) - - def cmd_executes_same(self, args1, args2): - """Assert that the `args1` executes the same as `args2`.""" - m1, r1 = self.mock_command_line(args1) - m2, r2 = self.mock_command_line(args2) - self.assertEqual(r1, r2) - self.assert_same_method_calls(m1, m2) - - def assert_same_method_calls(self, m1, m2): - """Assert that `m1.method_calls` and `m2.method_calls` are the same.""" - # Use a real equality comparison, but if it fails, use a nicer assert - # so we can tell what's going on. We have to use the real == first due - # to CmdOptionParser.__eq__ - if m1.method_calls != m2.method_calls: - pp1 = pprint.pformat(m1.method_calls) - pp2 = pprint.pformat(m2.method_calls) - self.assertMultiLineEqual(pp1+'\n', pp2+'\n') - - def cmd_help(self, args, help_msg=None, topic=None, ret=ERR): - """Run a command line, and check that it prints the right help. - - Only the last function call in the mock is checked, which should be the - help message that we want to see. - - """ - m, r = self.mock_command_line(args) - self.assertEqual(r, ret, - "Wrong status: got %s, wanted %s" % (r, ret) - ) - if help_msg: - self.assertEqual(m.method_calls[-1], - ('help_fn', (help_msg,), {}) - ) - else: - self.assertEqual(m.method_calls[-1], - ('help_fn', (), {'topic':topic}) - ) - - -class CmdLineTestTest(CmdLineTest): - """Tests that our CmdLineTest helpers work.""" - def test_assert_same_method_calls(self): - # All the other tests here use self.cmd_executes_same in successful - # ways, so here we just check that it fails. - self.assertRaises(AssertionError, self.cmd_executes_same, "-e", "-c") - - -class ClassicCmdLineTest(CmdLineTest): - """Tests of the classic coverage.py command line.""" - - def test_erase(self): - # coverage -e - self.cmd_executes("-e", """\ - .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=None) - .erase() - """) - self.cmd_executes_same("-e", "--erase") - - def test_execute(self): - # coverage -x [-p] [-L] [--timid] MODULE.py [ARG1 ARG2 ...] - - # -x calls coverage.load first. - self.cmd_executes("-x foo.py", """\ - .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=None) - .load() - .start() - .run_python_file('foo.py', ['foo.py']) - .stop() - .save() - """) - # -e -x calls coverage.erase first. - self.cmd_executes("-e -x foo.py", """\ - .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=None) - .erase() - .start() - .run_python_file('foo.py', ['foo.py']) - .stop() - .save() - """) - # --timid sets a flag, and program arguments get passed through. - self.cmd_executes("-x --timid foo.py abc 123", """\ - .coverage(cover_pylib=None, data_suffix=None, timid=True, branch=None, config_file=True, source=None, include=None, omit=None) - .load() - .start() - .run_python_file('foo.py', ['foo.py', 'abc', '123']) - .stop() - .save() - """) - # -L sets a flag, and flags for the program don't confuse us. - self.cmd_executes("-x -p -L foo.py -a -b", """\ - .coverage(cover_pylib=True, data_suffix=True, timid=None, branch=None, config_file=True, source=None, include=None, omit=None) - .load() - .start() - .run_python_file('foo.py', ['foo.py', '-a', '-b']) - .stop() - .save() - """) - - # Check that long forms of flags do the same thing as short forms. - self.cmd_executes_same("-x f.py", "--execute f.py") - self.cmd_executes_same("-e -x f.py", "--erase --execute f.py") - self.cmd_executes_same("-x -p f.py", "-x --parallel-mode f.py") - self.cmd_executes_same("-x -L f.py", "-x --pylib f.py") - - def test_combine(self): - # coverage -c - self.cmd_executes("-c", """\ - .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=None) - .load() - .combine() - .save() - """) - self.cmd_executes_same("-c", "--combine") - - def test_report(self): - # coverage -r [-m] [-i] [-o DIR,...] [FILE1 FILE2 ...] - self.cmd_executes("-r", self.INIT_LOAD + """\ - .report(ignore_errors=None, omit=None, include=None, morfs=[], - show_missing=None) - """) - self.cmd_executes("-r -i", self.INIT_LOAD + """\ - .report(ignore_errors=True, omit=None, include=None, morfs=[], - show_missing=None) - """) - self.cmd_executes("-r -m", self.INIT_LOAD + """\ - .report(ignore_errors=None, omit=None, include=None, morfs=[], - show_missing=True) - """) - self.cmd_executes("-r -o fooey", """\ - .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["fooey"]) - .load() - .report(ignore_errors=None, omit=["fooey"], include=None, - morfs=[], show_missing=None) - """) - self.cmd_executes("-r -o fooey,booey", """\ - .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["fooey", "booey"]) - .load() - .report(ignore_errors=None, omit=["fooey", "booey"], include=None, - morfs=[], show_missing=None) - """) - self.cmd_executes("-r mod1", self.INIT_LOAD + """\ - .report(ignore_errors=None, omit=None, include=None, - morfs=["mod1"], show_missing=None) - """) - self.cmd_executes("-r mod1 mod2 mod3", self.INIT_LOAD + """\ - .report(ignore_errors=None, omit=None, include=None, - morfs=["mod1", "mod2", "mod3"], show_missing=None) - """) - - self.cmd_executes_same("-r", "--report") - self.cmd_executes_same("-r -i", "-r --ignore-errors") - self.cmd_executes_same("-r -m", "-r --show-missing") - self.cmd_executes_same("-r -o f", "-r --omit=f") - self.cmd_executes_same("-r -o f", "-r --omit f") - self.cmd_executes_same("-r -o f,b", "-r --omit=f,b") - self.cmd_executes_same("-r -o f,b", "-r --omit f,b") - self.cmd_executes_same("-r -of", "-r --omit=f") - self.cmd_executes_same("-r -of,b", "-r --omit=f,b") - - def test_annotate(self): - # coverage -a [-d DIR] [-i] [-o DIR,...] [FILE1 FILE2 ...] - self.cmd_executes("-a", self.INIT_LOAD + """\ - .annotate(directory=None, ignore_errors=None, - omit=None, include=None, morfs=[]) - """) - self.cmd_executes("-a -d dir1", self.INIT_LOAD + """\ - .annotate(directory="dir1", ignore_errors=None, - omit=None, include=None, morfs=[]) - """) - self.cmd_executes("-a -i", self.INIT_LOAD + """\ - .annotate(directory=None, ignore_errors=True, - omit=None, include=None, morfs=[]) - """) - self.cmd_executes("-a -o fooey", """\ - .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["fooey"]) - .load() - .annotate(directory=None, ignore_errors=None, - omit=["fooey"], include=None, morfs=[]) - """) - self.cmd_executes("-a -o fooey,booey", """\ - .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["fooey", "booey"]) - .load() - .annotate(directory=None, ignore_errors=None, - omit=["fooey", "booey"], include=None, morfs=[]) - """) - self.cmd_executes("-a mod1", self.INIT_LOAD + """\ - .annotate(directory=None, ignore_errors=None, - omit=None, include=None, morfs=["mod1"]) - """) - self.cmd_executes("-a mod1 mod2 mod3", self.INIT_LOAD + """\ - .annotate(directory=None, ignore_errors=None, - omit=None, include=None, morfs=["mod1", "mod2", "mod3"]) - """) - - self.cmd_executes_same("-a", "--annotate") - self.cmd_executes_same("-a -d d1", "-a --directory=d1") - self.cmd_executes_same("-a -i", "-a --ignore-errors") - self.cmd_executes_same("-a -o f", "-a --omit=f") - self.cmd_executes_same("-a -o f", "-a --omit f") - self.cmd_executes_same("-a -o f,b", "-a --omit=f,b") - self.cmd_executes_same("-a -o f,b", "-a --omit f,b") - self.cmd_executes_same("-a -of", "-a --omit=f") - self.cmd_executes_same("-a -of,b", "-a --omit=f,b") - - def test_html_report(self): - # coverage -b -d DIR [-i] [-o DIR,...] [FILE1 FILE2 ...] - self.cmd_executes("-b", self.INIT_LOAD + """\ - .html_report(directory=None, ignore_errors=None, title=None, - omit=None, include=None, morfs=[]) - """) - self.cmd_executes("-b -d dir1", self.INIT_LOAD + """\ - .html_report(directory="dir1", ignore_errors=None, title=None, - omit=None, include=None, morfs=[]) - """) - self.cmd_executes("-b -i", self.INIT_LOAD + """\ - .html_report(directory=None, ignore_errors=True, title=None, - omit=None, include=None, morfs=[]) - """) - self.cmd_executes("-b -o fooey", """\ - .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["fooey"]) - .load() - .html_report(directory=None, ignore_errors=None, title=None, - omit=["fooey"], include=None, morfs=[]) - """) - self.cmd_executes("-b -o fooey,booey", """\ - .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["fooey", "booey"]) - .load() - .html_report(directory=None, ignore_errors=None, title=None, - omit=["fooey", "booey"], include=None, morfs=[]) - """) - self.cmd_executes("-b mod1", self.INIT_LOAD + """\ - .html_report(directory=None, ignore_errors=None, title=None, - omit=None, include=None, morfs=["mod1"]) - """) - self.cmd_executes("-b mod1 mod2 mod3", self.INIT_LOAD + """\ - .html_report(directory=None, ignore_errors=None, title=None, - omit=None, include=None, morfs=["mod1", "mod2", "mod3"]) - """) - - self.cmd_executes_same("-b", "--html") - self.cmd_executes_same("-b -d d1", "-b --directory=d1") - self.cmd_executes_same("-b -i", "-b --ignore-errors") - self.cmd_executes_same("-b -o f", "-b --omit=f") - self.cmd_executes_same("-b -o f,b", "-b --omit=f,b") - self.cmd_executes_same("-b -of", "-b --omit=f") - self.cmd_executes_same("-b -of,b", "-b --omit=f,b") - - def test_help(self): - # coverage -h - self.cmd_help("-h", topic="help", ret=OK) - self.cmd_help("--help", topic="help", ret=OK) - - def test_version(self): - # coverage --version - self.cmd_help("--version", topic="version", ret=OK) - - ## Error cases - - def test_argless_actions(self): - self.cmd_help("-e foo bar", "Unexpected arguments: foo bar") - self.cmd_help("-c baz quux", "Unexpected arguments: baz quux") - - def test_need_action(self): - self.cmd_help("-p", "You must specify at least one of " - "-e, -x, -c, -r, -a, or -b.") - - def test_bad_action_combinations(self): - self.cmd_help('-e -a', - "You can't specify the 'erase' and 'annotate' " - "options at the same time." - ) - self.cmd_help('-e -r', - "You can't specify the 'erase' and 'report' " - "options at the same time." - ) - self.cmd_help('-e -b', - "You can't specify the 'erase' and 'html' " - "options at the same time." - ) - self.cmd_help('-e -c', - "You can't specify the 'erase' and 'combine' " - "options at the same time." - ) - self.cmd_help('-x -a', - "You can't specify the 'execute' and 'annotate' " - "options at the same time." - ) - self.cmd_help('-x -r', - "You can't specify the 'execute' and 'report' " - "options at the same time." - ) - self.cmd_help('-x -b', - "You can't specify the 'execute' and 'html' " - "options at the same time." - ) - self.cmd_help('-x -c', - "You can't specify the 'execute' and 'combine' " - "options at the same time." - ) - - def test_nothing_to_do(self): - self.cmd_help("-x", "Nothing to do.") - - def test_unknown_option(self): - self.cmd_help("-z", "no such option: -z") - - -class FakeCoverageForDebugData(object): - """Just enough of a fake coverage package for the 'debug data' tests.""" - def __init__(self, summary): - self._summary = summary - self.filename = "FILENAME" - self.data = self - - # package members - def coverage(self, *unused_args, **unused_kwargs): - """The coverage class in the package.""" - return self - - # coverage methods - def load(self): - """Fake coverage().load()""" - pass - - # data methods - def has_arcs(self): - """Fake coverage().data.has_arcs()""" - return False - - def summary(self, fullpath): # pylint: disable=W0613 - """Fake coverage().data.summary()""" - return self._summary - - -class NewCmdLineTest(CmdLineTest): - """Tests of the coverage.py command line.""" - - def test_annotate(self): - self.cmd_executes_same("annotate", "-a") - self.cmd_executes_same("annotate -i", "-a -i") - self.cmd_executes_same("annotate -d d1", "-a -d d1") - self.cmd_executes_same("annotate --omit f", "-a --omit f") - self.cmd_executes_same("annotate --omit f,b", "-a --omit f,b") - self.cmd_executes_same("annotate m1", "-a m1") - self.cmd_executes_same("annotate m1 m2 m3", "-a m1 m2 m3") - - def test_combine(self): - self.cmd_executes_same("combine", "-c") - - def test_debug(self): - self.cmd_help("debug", "What information would you like: data, sys?") - self.cmd_help("debug foo", "Don't know what you mean by 'foo'") - - def test_debug_data(self): - fake = FakeCoverageForDebugData({ - 'file1.py': 17, 'file2.py': 23, - }) - self.command_line("debug data", _covpkg=fake) - self.assertMultiLineEqual(self.stdout(), textwrap.dedent("""\ - -- data --------------------------------------- - path: FILENAME - has_arcs: False - - 2 files: - file1.py: 17 lines - file2.py: 23 lines - """)) - - def test_debug_data_with_no_data(self): - fake = FakeCoverageForDebugData({}) - self.command_line("debug data", _covpkg=fake) - self.assertMultiLineEqual(self.stdout(), textwrap.dedent("""\ - -- data --------------------------------------- - path: FILENAME - has_arcs: False - No data collected - """)) - - def test_debug_sys(self): - self.command_line("debug sys") - out = self.stdout() - assert "version:" in out - assert "data_path:" in out - - def test_erase(self): - self.cmd_executes_same("erase", "-e") - - def test_help(self): - self.cmd_executes("help", ".help_fn(topic='help')") - - def test_cmd_help(self): - self.cmd_executes("run --help", - ".help_fn(parser='')") - self.cmd_executes_same("help run", "run --help") - - def test_html(self): - self.cmd_executes_same("html", "-b") - self.cmd_executes_same("html -i", "-b -i") - self.cmd_executes_same("html -d d1", "-b -d d1") - self.cmd_executes_same("html --omit f", "-b --omit f") - self.cmd_executes_same("html --omit f,b", "-b --omit f,b") - self.cmd_executes_same("html m1", "-b m1") - self.cmd_executes_same("html m1 m2 m3", "-b m1 m2 m3") - self.cmd_executes("html", self.INIT_LOAD + """\ - .html_report(ignore_errors=None, omit=None, include=None, morfs=[], - directory=None, title=None) - """) - self.cmd_executes("html --title=Hello_there", self.INIT_LOAD + """\ - .html_report(ignore_errors=None, omit=None, include=None, morfs=[], - directory=None, title='Hello_there') - """) - - def test_report(self): - self.cmd_executes_same("report", "-r") - self.cmd_executes_same("report -i", "-r -i") - self.cmd_executes_same("report -m", "-r -m") - self.cmd_executes_same("report --omit f", "-r --omit f") - self.cmd_executes_same("report --omit f,b", "-r --omit f,b") - self.cmd_executes_same("report m1", "-r m1") - self.cmd_executes_same("report m1 m2 m3", "-r m1 m2 m3") - - def test_run(self): - self.cmd_executes_same("run f.py", "-e -x f.py") - self.cmd_executes_same("run f.py -a arg -z", "-e -x f.py -a arg -z") - self.cmd_executes_same("run -a f.py", "-x f.py") - self.cmd_executes_same("run -p f.py", "-e -x -p f.py") - self.cmd_executes_same("run -L f.py", "-e -x -L f.py") - self.cmd_executes_same("run --timid f.py", "-e -x --timid f.py") - self.cmd_executes_same("run", "-x") - self.cmd_executes("run --branch foo.py", """\ - .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=True, config_file=True, source=None, include=None, omit=None) - .erase() - .start() - .run_python_file('foo.py', ['foo.py']) - .stop() - .save() - """) - self.cmd_executes("run --rcfile=myrc.rc foo.py", """\ - .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file="myrc.rc", source=None, include=None, omit=None) - .erase() - .start() - .run_python_file('foo.py', ['foo.py']) - .stop() - .save() - """) - self.cmd_executes("run --include=pre1,pre2 foo.py", """\ - .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=["pre1", "pre2"], omit=None) - .erase() - .start() - .run_python_file('foo.py', ['foo.py']) - .stop() - .save() - """) - self.cmd_executes("run --omit=opre1,opre2 foo.py", """\ - .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["opre1", "opre2"]) - .erase() - .start() - .run_python_file('foo.py', ['foo.py']) - .stop() - .save() - """) - self.cmd_executes("run --include=pre1,pre2 --omit=opre1,opre2 foo.py", - """\ - .coverage(cover_pylib=None, data_suffix=None, timid=None, - branch=None, config_file=True, source=None, - include=["pre1", "pre2"], - omit=["opre1", "opre2"]) - .erase() - .start() - .run_python_file('foo.py', ['foo.py']) - .stop() - .save() - """) - self.cmd_executes("run --source=quux,hi.there,/home/bar foo.py", - """\ - .coverage(cover_pylib=None, data_suffix=None, timid=None, - branch=None, config_file=True, - source=["quux", "hi.there", "/home/bar"], include=None, - omit=None) - .erase() - .start() - .run_python_file('foo.py', ['foo.py']) - .stop() - .save() - """) - - def test_run_module(self): - self.cmd_executes("run -m mymodule", """\ - .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=None) - .erase() - .start() - .run_python_module('mymodule', ['mymodule']) - .stop() - .save() - """) - self.cmd_executes("run -m mymodule -qq arg1 arg2", """\ - .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=None) - .erase() - .start() - .run_python_module('mymodule', ['mymodule', '-qq', 'arg1', 'arg2']) - .stop() - .save() - """) - self.cmd_executes("run --branch -m mymodule", """\ - .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=True, config_file=True, source=None, include=None, omit=None) - .erase() - .start() - .run_python_module('mymodule', ['mymodule']) - .stop() - .save() - """) - self.cmd_executes_same("run -m mymodule", "run --module mymodule") - - def test_xml(self): - # coverage xml [-i] [--omit DIR,...] [FILE1 FILE2 ...] - self.cmd_executes("xml", self.INIT_LOAD + """\ - .xml_report(ignore_errors=None, omit=None, include=None, morfs=[], - outfile=None) - """) - self.cmd_executes("xml -i", self.INIT_LOAD + """\ - .xml_report(ignore_errors=True, omit=None, include=None, morfs=[], - outfile=None) - """) - self.cmd_executes("xml -o myxml.foo", self.INIT_LOAD + """\ - .xml_report(ignore_errors=None, omit=None, include=None, morfs=[], - outfile="myxml.foo") - """) - self.cmd_executes("xml -o -", self.INIT_LOAD + """\ - .xml_report(ignore_errors=None, omit=None, include=None, morfs=[], - outfile="-") - """) - self.cmd_executes("xml --omit fooey", """\ - .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["fooey"]) - .load() - .xml_report(ignore_errors=None, omit=["fooey"], include=None, morfs=[], - outfile=None) - """) - self.cmd_executes("xml --omit fooey,booey", """\ - .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["fooey", "booey"]) - .load() - .xml_report(ignore_errors=None, omit=["fooey", "booey"], include=None, - morfs=[], outfile=None) - """) - self.cmd_executes("xml mod1", self.INIT_LOAD + """\ - .xml_report(ignore_errors=None, omit=None, include=None, morfs=["mod1"], - outfile=None) - """) - self.cmd_executes("xml mod1 mod2 mod3", self.INIT_LOAD + """\ - .xml_report(ignore_errors=None, omit=None, include=None, - morfs=["mod1", "mod2", "mod3"], outfile=None) - """) - - def test_no_arguments_at_all(self): - self.cmd_help("", topic="minimum_help", ret=OK) - - def test_bad_command(self): - self.cmd_help("xyzzy", "Unknown command: 'xyzzy'") - - -class CmdLineStdoutTest(CmdLineTest): - """Test the command line with real stdout output.""" - - def test_minimum_help(self): - self.command_line("") - out = self.stdout() - assert "Code coverage for Python." in out - assert out.count("\n") < 4 - - def test_version(self): - self.command_line("--version") - out = self.stdout() - assert "ersion " in out - assert out.count("\n") < 4 - - def test_help(self): - self.command_line("help") - out = self.stdout() - assert "nedbatchelder.com" in out - assert out.count("\n") > 10 - - def test_cmd_help(self): - self.command_line("help run") - out = self.stdout() - assert "" in out - assert "--timid" in out - assert out.count("\n") > 10 - - def test_error(self): - self.command_line("fooey kablooey", ret=ERR) - out = self.stdout() - assert "fooey" in out - assert "help" in out - - -class CmdMainTest(CoverageTest): - """Tests of coverage.cmdline.main(), using mocking for isolation.""" - - class CoverageScriptStub(object): - """A stub for coverage.cmdline.CoverageScript, used by CmdMainTest.""" - - def command_line(self, argv): - """Stub for command_line, the arg determines what it will do.""" - if argv[0] == 'hello': - print("Hello, world!") - elif argv[0] == 'raise': - try: - raise Exception("oh noes!") - except: - raise ExceptionDuringRun(*sys.exc_info()) - elif argv[0] == 'internalraise': - raise ValueError("coverage is broken") - elif argv[0] == 'exit': - sys.exit(23) - else: - raise AssertionError("Bad CoverageScriptStub: %r"% (argv,)) - return 0 - - def setUp(self): - super(CmdMainTest, self).setUp() - self.old_CoverageScript = coverage.cmdline.CoverageScript - coverage.cmdline.CoverageScript = self.CoverageScriptStub - - def tearDown(self): - coverage.cmdline.CoverageScript = self.old_CoverageScript - super(CmdMainTest, self).tearDown() - - def test_normal(self): - ret = coverage.cmdline.main(['hello']) - self.assertEqual(ret, 0) - self.assertEqual(self.stdout(), "Hello, world!\n") - - def test_raise(self): - ret = coverage.cmdline.main(['raise']) - self.assertEqual(ret, 1) - self.assertEqual(self.stdout(), "") - err = self.stderr().split('\n') - self.assertEqual(err[0], 'Traceback (most recent call last):') - self.assertEqual(err[-3], ' raise Exception("oh noes!")') - self.assertEqual(err[-2], 'Exception: oh noes!') - - def test_internalraise(self): - self.assertRaisesRegexp(ValueError, - "coverage is broken", - coverage.cmdline.main, ['internalraise'] - ) - - def test_exit(self): - ret = coverage.cmdline.main(['exit']) - self.assertEqual(ret, 23) diff --git a/test/test_codeunit.py b/test/test_codeunit.py deleted file mode 100644 index b4caff88..00000000 --- a/test/test_codeunit.py +++ /dev/null @@ -1,103 +0,0 @@ -"""Tests for coverage.codeunit""" - -import os, sys - -from coverage.codeunit import code_unit_factory -from coverage.files import FileLocator - -from test.coveragetest import CoverageTest - -# pylint: disable=F0401 -# Unable to import 'aa' (No module named aa) - -class CodeUnitTest(CoverageTest): - """Tests for coverage.codeunit""" - - run_in_temp_dir = False - - def setUp(self): - super(CodeUnitTest, self).setUp() - # Parent class saves and restores sys.path, we can just modify it. - testmods = self.nice_file(os.path.dirname(__file__), 'modules') - sys.path.append(testmods) - - def test_filenames(self): - acu = code_unit_factory("aa/afile.py", FileLocator()) - bcu = code_unit_factory("aa/bb/bfile.py", FileLocator()) - ccu = code_unit_factory("aa/bb/cc/cfile.py", FileLocator()) - self.assertEqual(acu[0].name, "aa/afile") - self.assertEqual(bcu[0].name, "aa/bb/bfile") - self.assertEqual(ccu[0].name, "aa/bb/cc/cfile") - self.assertEqual(acu[0].flat_rootname(), "aa_afile") - self.assertEqual(bcu[0].flat_rootname(), "aa_bb_bfile") - self.assertEqual(ccu[0].flat_rootname(), "aa_bb_cc_cfile") - self.assertEqual(acu[0].source_file().read(), "# afile.py\n") - self.assertEqual(bcu[0].source_file().read(), "# bfile.py\n") - self.assertEqual(ccu[0].source_file().read(), "# cfile.py\n") - - def test_odd_filenames(self): - acu = code_unit_factory("aa/afile.odd.py", FileLocator()) - bcu = code_unit_factory("aa/bb/bfile.odd.py", FileLocator()) - b2cu = code_unit_factory("aa/bb.odd/bfile.py", FileLocator()) - self.assertEqual(acu[0].name, "aa/afile.odd") - self.assertEqual(bcu[0].name, "aa/bb/bfile.odd") - self.assertEqual(b2cu[0].name, "aa/bb.odd/bfile") - self.assertEqual(acu[0].flat_rootname(), "aa_afile_odd") - self.assertEqual(bcu[0].flat_rootname(), "aa_bb_bfile_odd") - self.assertEqual(b2cu[0].flat_rootname(), "aa_bb_odd_bfile") - self.assertEqual(acu[0].source_file().read(), "# afile.odd.py\n") - self.assertEqual(bcu[0].source_file().read(), "# bfile.odd.py\n") - self.assertEqual(b2cu[0].source_file().read(), "# bfile.py\n") - - def test_modules(self): - import aa, aa.bb, aa.bb.cc - cu = code_unit_factory([aa, aa.bb, aa.bb.cc], FileLocator()) - self.assertEqual(cu[0].name, "aa") - self.assertEqual(cu[1].name, "aa.bb") - self.assertEqual(cu[2].name, "aa.bb.cc") - self.assertEqual(cu[0].flat_rootname(), "aa") - self.assertEqual(cu[1].flat_rootname(), "aa_bb") - self.assertEqual(cu[2].flat_rootname(), "aa_bb_cc") - self.assertEqual(cu[0].source_file().read(), "# aa\n") - self.assertEqual(cu[1].source_file().read(), "# bb\n") - self.assertEqual(cu[2].source_file().read(), "") # yes, empty - - def test_module_files(self): - import aa.afile, aa.bb.bfile, aa.bb.cc.cfile - cu = code_unit_factory([aa.afile, aa.bb.bfile, aa.bb.cc.cfile], - FileLocator()) - self.assertEqual(cu[0].name, "aa.afile") - self.assertEqual(cu[1].name, "aa.bb.bfile") - self.assertEqual(cu[2].name, "aa.bb.cc.cfile") - self.assertEqual(cu[0].flat_rootname(), "aa_afile") - self.assertEqual(cu[1].flat_rootname(), "aa_bb_bfile") - self.assertEqual(cu[2].flat_rootname(), "aa_bb_cc_cfile") - self.assertEqual(cu[0].source_file().read(), "# afile.py\n") - self.assertEqual(cu[1].source_file().read(), "# bfile.py\n") - self.assertEqual(cu[2].source_file().read(), "# cfile.py\n") - - def test_comparison(self): - acu = code_unit_factory("aa/afile.py", FileLocator())[0] - acu2 = code_unit_factory("aa/afile.py", FileLocator())[0] - zcu = code_unit_factory("aa/zfile.py", FileLocator())[0] - bcu = code_unit_factory("aa/bb/bfile.py", FileLocator())[0] - assert acu == acu2 and acu <= acu2 and acu >= acu2 - assert acu < zcu and acu <= zcu and acu != zcu - assert zcu > acu and zcu >= acu and zcu != acu - assert acu < bcu and acu <= bcu and acu != bcu - assert bcu > acu and bcu >= acu and bcu != acu - - def test_egg(self): - # Test that we can get files out of eggs, and read their source files. - # The egg1 module is installed by an action in igor.py. - import egg1, egg1.egg1 - # Verify that we really imported from an egg. If we did, then the - # __file__ won't be an actual file, because one of the "directories" - # in the path is actually the .egg zip file. - self.assert_doesnt_exist(egg1.__file__) - - cu = code_unit_factory([egg1, egg1.egg1], FileLocator()) - self.assertEqual(cu[0].source_file().read(), "") - self.assertEqual(cu[1].source_file().read().split("\n")[0], - "# My egg file!" - ) diff --git a/test/test_config.py b/test/test_config.py deleted file mode 100644 index 1ca63765..00000000 --- a/test/test_config.py +++ /dev/null @@ -1,225 +0,0 @@ -# -*- coding: utf-8 -*- -"""Test the config file handling for coverage.py""" - -import sys -import coverage -from coverage.misc import CoverageException - -from test.coveragetest import CoverageTest - - -class ConfigTest(CoverageTest): - """Tests of the different sources of configuration settings.""" - - def test_default_config(self): - # Just constructing a coverage() object gets the right defaults. - cov = coverage.coverage() - self.assertFalse(cov.config.timid) - self.assertFalse(cov.config.branch) - self.assertEqual(cov.config.data_file, ".coverage") - - def test_arguments(self): - # Arguments to the constructor are applied to the configuation. - cov = coverage.coverage(timid=True, data_file="fooey.dat") - self.assertTrue(cov.config.timid) - self.assertFalse(cov.config.branch) - self.assertEqual(cov.config.data_file, "fooey.dat") - - def test_config_file(self): - # A .coveragerc file will be read into the configuration. - self.make_file(".coveragerc", """\ - # This is just a bogus .rc file for testing. - [run] - timid = True - data_file = .hello_kitty.data - """) - cov = coverage.coverage() - self.assertTrue(cov.config.timid) - self.assertFalse(cov.config.branch) - self.assertEqual(cov.config.data_file, ".hello_kitty.data") - - def test_named_config_file(self): - # You can name the config file what you like. - self.make_file("my_cov.ini", """\ - [run] - timid = True - ; I wouldn't really use this as a data file... - data_file = delete.me - """) - cov = coverage.coverage(config_file="my_cov.ini") - self.assertTrue(cov.config.timid) - self.assertFalse(cov.config.branch) - self.assertEqual(cov.config.data_file, "delete.me") - - def test_ignored_config_file(self): - # You can disable reading the .coveragerc file. - self.make_file(".coveragerc", """\ - [run] - timid = True - data_file = delete.me - """) - cov = coverage.coverage(config_file=False) - self.assertFalse(cov.config.timid) - self.assertFalse(cov.config.branch) - self.assertEqual(cov.config.data_file, ".coverage") - - def test_config_file_then_args(self): - # The arguments override the .coveragerc file. - self.make_file(".coveragerc", """\ - [run] - timid = True - data_file = weirdo.file - """) - cov = coverage.coverage(timid=False, data_file=".mycov") - self.assertFalse(cov.config.timid) - self.assertFalse(cov.config.branch) - self.assertEqual(cov.config.data_file, ".mycov") - - def test_data_file_from_environment(self): - # There's an environment variable for the data_file. - self.make_file(".coveragerc", """\ - [run] - timid = True - data_file = weirdo.file - """) - self.set_environ("COVERAGE_FILE", "fromenv.dat") - cov = coverage.coverage() - self.assertEqual(cov.config.data_file, "fromenv.dat") - # But the constructor args override the env var. - cov = coverage.coverage(data_file="fromarg.dat") - self.assertEqual(cov.config.data_file, "fromarg.dat") - - def test_parse_errors(self): - # Im-parseable values raise CoverageException - self.make_file(".coveragerc", """\ - [run] - timid = maybe? - """) - self.assertRaises(CoverageException, coverage.coverage) - - def test_environment_vars_in_config(self): - # Config files can have $envvars in them. - self.make_file(".coveragerc", """\ - [run] - data_file = $DATA_FILE.fooey - branch = $OKAY - [report] - exclude_lines = - the_$$one - another${THING} - x${THING}y - x${NOTHING}y - huh$${X}what - """) - self.set_environ("DATA_FILE", "hello-world") - self.set_environ("THING", "ZZZ") - self.set_environ("OKAY", "yes") - cov = coverage.coverage() - self.assertEqual(cov.config.data_file, "hello-world.fooey") - self.assertEqual(cov.config.branch, True) - self.assertEqual(cov.config.exclude_list, - ["the_$one", "anotherZZZ", "xZZZy", "xy", "huh${X}what"] - ) - - -class ConfigFileTest(CoverageTest): - """Tests of the config file settings in particular.""" - - def test_config_file_settings(self): - # This sample file tries to use lots of variation of syntax... - self.make_file(".coveragerc", """\ - # This is a settings file for coverage.py - [run] - timid = yes - data_file = something_or_other.dat - branch = 1 - cover_pylib = TRUE - parallel = on - include = a/ , b/ - - [report] - ; these settings affect reporting. - exclude_lines = - if 0: - - pragma:?\\s+no cover - another_tab - - ignore_errors = TRUE - omit = - one, another, some_more, - yet_more - precision = 3 - - partial_branches = - pragma:?\\s+no branch - partial_branches_always = - if 0: - while True: - - show_missing= TruE - - [html] - - directory = c:\\tricky\\dir.somewhere - extra_css=something/extra.css - title = Title & nums # nums! - [xml] - output=mycov.xml - - [paths] - source = - . - /home/ned/src/ - - other = other, /home/ned/other, c:\\Ned\\etc - - """) - cov = coverage.coverage() - - self.assertTrue(cov.config.timid) - self.assertEqual(cov.config.data_file, "something_or_other.dat") - self.assertTrue(cov.config.branch) - self.assertTrue(cov.config.cover_pylib) - self.assertTrue(cov.config.parallel) - - self.assertEqual(cov.get_exclude_list(), - ["if 0:", r"pragma:?\s+no cover", "another_tab"] - ) - self.assertTrue(cov.config.ignore_errors) - self.assertEqual(cov.config.include, ["a/", "b/"]) - self.assertEqual(cov.config.omit, - ["one", "another", "some_more", "yet_more"] - ) - self.assertEqual(cov.config.precision, 3) - - self.assertEqual(cov.config.partial_list, - [r"pragma:?\s+no branch"] - ) - self.assertEqual(cov.config.partial_always_list, - ["if 0:", "while True:"] - ) - self.assertTrue(cov.config.show_missing) - self.assertEqual(cov.config.html_dir, r"c:\tricky\dir.somewhere") - self.assertEqual(cov.config.extra_css, "something/extra.css") - self.assertEqual(cov.config.html_title, "Title & nums # nums!") - - self.assertEqual(cov.config.xml_output, "mycov.xml") - - self.assertEqual(cov.config.paths, { - 'source': ['.', '/home/ned/src/'], - 'other': ['other', '/home/ned/other', 'c:\\Ned\\etc'] - }) - - if sys.version_info[:2] != (3,1): - def test_one(self): - # This sample file tries to use lots of variation of syntax... - self.make_file(".coveragerc", """\ - [html] - title = tabblo & «ταБЬℓσ» # numbers - """) - cov = coverage.coverage() - - self.assertEqual(cov.config.html_title, - "tabblo & «ταБЬℓσ» # numbers" - ) diff --git a/test/test_coverage.py b/test/test_coverage.py deleted file mode 100644 index 0918dfe1..00000000 --- a/test/test_coverage.py +++ /dev/null @@ -1,1730 +0,0 @@ -"""Tests for Coverage.""" -# http://nedbatchelder.com/code/coverage - -import sys -import coverage -from coverage.misc import CoverageException -from test.coveragetest import CoverageTest - - -class TestCoverageTest(CoverageTest): - """Make sure our complex self.check_coverage method works.""" - - def test_successful_coverage(self): - # The simplest run possible. - self.check_coverage("""\ - a = 1 - b = 2 - """, - [1,2] - ) - # You can provide a list of possible statement matches. - self.check_coverage("""\ - a = 1 - b = 2 - """, - ([100], [1,2], [1723,47]), - ) - # You can specify missing lines. - self.check_coverage("""\ - a = 1 - if a == 2: - a = 3 - """, - [1,2,3], - missing="3", - ) - # You can specify a list of possible missing lines. - self.check_coverage("""\ - a = 1 - if a == 2: - a = 3 - """, - [1,2,3], - missing=("47-49", "3", "100,102") - ) - - def test_failed_coverage(self): - # If the lines are wrong, the message shows right and wrong. - self.assertRaisesRegexp(AssertionError, - r"\[1, 2] != \[1]", - self.check_coverage, """\ - a = 1 - b = 2 - """, - [1] - ) - # If the list of lines possibilities is wrong, the msg shows right. - self.assertRaisesRegexp(AssertionError, - r"None of the lines choices matched \[1, 2]", - self.check_coverage, """\ - a = 1 - b = 2 - """, - ([1], [2]) - ) - # If the missing lines are wrong, the message shows right and wrong. - self.assertRaisesRegexp(AssertionError, - r"'3' != '37'", - self.check_coverage, """\ - a = 1 - if a == 2: - a = 3 - """, - [1,2,3], - missing="37", - ) - # If the missing lines possibilities are wrong, the msg shows right. - self.assertRaisesRegexp(AssertionError, - r"None of the missing choices matched '3'", - self.check_coverage, """\ - a = 1 - if a == 2: - a = 3 - """, - [1,2,3], - missing=("37", "4-10"), - ) - - -class BasicCoverageTest(CoverageTest): - """The simplest tests, for quick smoke testing of fundamental changes.""" - - def test_simple(self): - self.check_coverage("""\ - a = 1 - b = 2 - - c = 4 - # Nothing here - d = 6 - """, - [1,2,4,6], report="4 0 100%") - - def test_indentation_wackiness(self): - # Partial final lines are OK. - self.check_coverage("""\ - import sys - if not sys.path: - a = 1 - """, - [1,2,3], "3") - - def test_multiline_initializer(self): - self.check_coverage("""\ - d = { - 'foo': 1+2, - 'bar': (lambda x: x+1)(1), - 'baz': str(1), - } - - e = { 'foo': 1, 'bar': 2 } - """, - [1,7], "") - - def test_list_comprehension(self): - self.check_coverage("""\ - l = [ - 2*i for i in range(10) - if i > 5 - ] - assert l == [12, 14, 16, 18] - """, - [1,5], "") - - -class SimpleStatementTest(CoverageTest): - """Testing simple single-line statements.""" - - def test_expression(self): - # Bare expressions as statements are tricky: some implementations - # optimize some of them away. All implementations seem to count - # the implicit return at the end as executable. - self.check_coverage("""\ - 12 - 23 - """, - ([1,2],[2]), "") - self.check_coverage("""\ - 12 - 23 - a = 3 - """, - ([1,2,3],[3]), "") - self.check_coverage("""\ - 1 + 2 - 1 + \\ - 2 - """, - ([1,2], [2]), "") - self.check_coverage("""\ - 1 + 2 - 1 + \\ - 2 - a = 4 - """, - ([1,2,4], [4]), "") - - def test_assert(self): - self.check_coverage("""\ - assert (1 + 2) - assert (1 + - 2) - assert (1 + 2), 'the universe is broken' - assert (1 + - 2), \\ - 'something is amiss' - """, - [1,2,4,5], "") - - def test_assignment(self): - # Simple variable assignment - self.check_coverage("""\ - a = (1 + 2) - b = (1 + - 2) - c = \\ - 1 - """, - [1,2,4], "") - - def test_assign_tuple(self): - self.check_coverage("""\ - a = 1 - a,b,c = 7,8,9 - assert a == 7 and b == 8 and c == 9 - """, - [1,2,3], "") - - def test_attribute_assignment(self): - # Attribute assignment - self.check_coverage("""\ - class obj: pass - o = obj() - o.foo = (1 + 2) - o.foo = (1 + - 2) - o.foo = \\ - 1 - """, - [1,2,3,4,6], "") - - def test_list_of_attribute_assignment(self): - self.check_coverage("""\ - class obj: pass - o = obj() - o.a, o.b = (1 + 2), 3 - o.a, o.b = (1 + - 2), (3 + - 4) - o.a, o.b = \\ - 1, \\ - 2 - """, - [1,2,3,4,7], "") - - def test_augmented_assignment(self): - self.check_coverage("""\ - a = 1 - a += 1 - a += (1 + - 2) - a += \\ - 1 - """, - [1,2,3,5], "") - - def test_triple_string_stuff(self): - self.check_coverage("""\ - a = ''' - a multiline - string. - ''' - b = ''' - long expression - ''' + ''' - on many - lines. - ''' - c = len(''' - long expression - ''' + - ''' - on many - lines. - ''') - """, - [1,5,11], "") - - def test_pass(self): - # pass is tricky: if it's the only statement in a block, then it is - # "executed". But if it is not the only statement, then it is not. - self.check_coverage("""\ - if 1==1: - pass - """, - [1,2], "") - self.check_coverage("""\ - def foo(): - pass - foo() - """, - [1,2,3], "") - self.check_coverage("""\ - def foo(): - "doc" - pass - foo() - """, - ([1,3,4], [1,4]), "") - self.check_coverage("""\ - class Foo: - def foo(self): - pass - Foo().foo() - """, - [1,2,3,4], "") - self.check_coverage("""\ - class Foo: - def foo(self): - "Huh?" - pass - Foo().foo() - """, - ([1,2,4,5], [1,2,5]), "") - - def test_del(self): - self.check_coverage("""\ - d = { 'a': 1, 'b': 1, 'c': 1, 'd': 1, 'e': 1 } - del d['a'] - del d[ - 'b' - ] - del d['c'], \\ - d['d'], \\ - d['e'] - assert(len(d.keys()) == 0) - """, - [1,2,3,6,9], "") - - if sys.version_info < (3, 0): # Print statement is gone in Py3k. - def test_print(self): - self.check_coverage("""\ - print "hello, world!" - print ("hey: %d" % - 17) - print "goodbye" - print "hello, world!", - print ("hey: %d" % - 17), - print "goodbye", - """, - [1,2,4,5,6,8], "") - - def test_raise(self): - self.check_coverage("""\ - try: - raise Exception( - "hello %d" % - 17) - except: - pass - """, - [1,2,5,6], "") - - def test_return(self): - self.check_coverage("""\ - def fn(): - a = 1 - return a - - x = fn() - assert(x == 1) - """, - [1,2,3,5,6], "") - self.check_coverage("""\ - def fn(): - a = 1 - return ( - a + - 1) - - x = fn() - assert(x == 2) - """, - [1,2,3,7,8], "") - self.check_coverage("""\ - def fn(): - a = 1 - return (a, - a + 1, - a + 2) - - x,y,z = fn() - assert x == 1 and y == 2 and z == 3 - """, - [1,2,3,7,8], "") - - def test_yield(self): - self.check_coverage("""\ - from __future__ import generators - def gen(): - yield 1 - yield (2+ - 3+ - 4) - yield 1, \\ - 2 - a,b,c = gen() - assert a == 1 and b == 9 and c == (1,2) - """, - [1,2,3,4,7,9,10], "") - - def test_break(self): - self.check_coverage("""\ - for x in range(10): - a = 2 + x - break - a = 4 - assert a == 2 - """, - [1,2,3,4,5], "4") - - def test_continue(self): - self.check_coverage("""\ - for x in range(10): - a = 2 + x - continue - a = 4 - assert a == 11 - """, - [1,2,3,4,5], "4") - - if 0: # expected failure - # Peephole optimization of jumps to jumps can mean that some statements - # never hit the line tracer. The behavior is different in different - # versions of Python, so don't run this test: - def test_strange_unexecuted_continue(self): - self.check_coverage("""\ - a = b = c = 0 - for n in range(100): - if n % 2: - if n % 4: - a += 1 - continue # <-- This line may not be hit. - else: - b += 1 - c += 1 - assert a == 50 and b == 50 and c == 50 - - a = b = c = 0 - for n in range(100): - if n % 2: - if n % 3: - a += 1 - continue # <-- This line is always hit. - else: - b += 1 - c += 1 - assert a == 33 and b == 50 and c == 50 - """, - [1,2,3,4,5,6,8,9,10, 12,13,14,15,16,17,19,20,21], "") - - def test_import(self): - self.check_coverage("""\ - import string - from sys import path - a = 1 - """, - [1,2,3], "") - self.check_coverage("""\ - import string - if 1 == 2: - from sys import path - a = 1 - """, - [1,2,3,4], "3") - self.check_coverage("""\ - import string, \\ - os, \\ - re - from sys import path, \\ - stdout - a = 1 - """, - [1,4,6], "") - self.check_coverage("""\ - import sys, sys as s - assert s.path == sys.path - """, - [1,2], "") - self.check_coverage("""\ - import sys, \\ - sys as s - assert s.path == sys.path - """, - [1,3], "") - self.check_coverage("""\ - from sys import path, \\ - path as p - assert p == path - """, - [1,3], "") - self.check_coverage("""\ - from sys import \\ - * - assert len(path) > 0 - """, - [1,3], "") - - def test_global(self): - self.check_coverage("""\ - g = h = i = 1 - def fn(): - global g - global h, \\ - i - g = h = i = 2 - fn() - assert g == 2 and h == 2 and i == 2 - """, - [1,2,6,7,8], "") - self.check_coverage("""\ - g = h = i = 1 - def fn(): - global g; g = 2 - fn() - assert g == 2 and h == 1 and i == 1 - """, - [1,2,3,4,5], "") - - if sys.version_info < (3, 0): - # In Python 2.x, exec is a statement. - def test_exec(self): - self.check_coverage("""\ - a = b = c = 1 - exec "a = 2" - exec ("b = " + - "c = " + - "2") - assert a == 2 and b == 2 and c == 2 - """, - [1,2,3,6], "") - self.check_coverage("""\ - vars = {'a': 1, 'b': 1, 'c': 1} - exec "a = 2" in vars - exec ("b = " + - "c = " + - "2") in vars - assert vars['a'] == 2 and vars['b'] == 2 and vars['c'] == 2 - """, - [1,2,3,6], "") - self.check_coverage("""\ - globs = {} - locs = {'a': 1, 'b': 1, 'c': 1} - exec "a = 2" in globs, locs - exec ("b = " + - "c = " + - "2") in globs, locs - assert locs['a'] == 2 and locs['b'] == 2 and locs['c'] == 2 - """, - [1,2,3,4,7], "") - else: - # In Python 3.x, exec is a function. - def test_exec(self): - self.check_coverage("""\ - a = b = c = 1 - exec("a = 2") - exec("b = " + - "c = " + - "2") - assert a == 2 and b == 2 and c == 2 - """, - [1,2,3,6], "") - self.check_coverage("""\ - vars = {'a': 1, 'b': 1, 'c': 1} - exec("a = 2", vars) - exec("b = " + - "c = " + - "2", vars) - assert vars['a'] == 2 and vars['b'] == 2 and vars['c'] == 2 - """, - [1,2,3,6], "") - self.check_coverage("""\ - globs = {} - locs = {'a': 1, 'b': 1, 'c': 1} - exec("a = 2", globs, locs) - exec("b = " + - "c = " + - "2", globs, locs) - assert locs['a'] == 2 and locs['b'] == 2 and locs['c'] == 2 - """, - [1,2,3,4,7], "") - - def test_extra_doc_string(self): - self.check_coverage("""\ - a = 1 - "An extra docstring, should be a comment." - b = 3 - assert (a,b) == (1,3) - """, - [1,3,4], "") - self.check_coverage("""\ - a = 1 - "An extra docstring, should be a comment." - b = 3 - 123 # A number for some reason: ignored - 1+1 # An expression: executed. - c = 6 - assert (a,b,c) == (1,3,6) - """, - ([1,3,6,7], [1,3,5,6,7], [1,3,4,5,6,7]), "") - - -class CompoundStatementTest(CoverageTest): - """Testing coverage of multi-line compound statements.""" - - def test_statement_list(self): - self.check_coverage("""\ - a = 1; - b = 2; c = 3 - d = 4; e = 5; - - assert (a,b,c,d,e) == (1,2,3,4,5) - """, - [1,2,3,5], "") - - def test_if(self): - self.check_coverage("""\ - a = 1 - if a == 1: - x = 3 - assert x == 3 - if (a == - 1): - x = 7 - assert x == 7 - """, - [1,2,3,4,5,7,8], "") - self.check_coverage("""\ - a = 1 - if a == 1: - x = 3 - else: - y = 5 - assert x == 3 - """, - [1,2,3,5,6], "5") - self.check_coverage("""\ - a = 1 - if a != 1: - x = 3 - else: - y = 5 - assert y == 5 - """, - [1,2,3,5,6], "3") - self.check_coverage("""\ - a = 1; b = 2 - if a == 1: - if b == 2: - x = 4 - else: - y = 6 - else: - z = 8 - assert x == 4 - """, - [1,2,3,4,6,8,9], "6-8") - - def test_elif(self): - self.check_coverage("""\ - a = 1; b = 2; c = 3; - if a == 1: - x = 3 - elif b == 2: - y = 5 - else: - z = 7 - assert x == 3 - """, - [1,2,3,4,5,7,8], "4-7", report="7 3 57% 4-7") - self.check_coverage("""\ - a = 1; b = 2; c = 3; - if a != 1: - x = 3 - elif b == 2: - y = 5 - else: - z = 7 - assert y == 5 - """, - [1,2,3,4,5,7,8], "3, 7", report="7 2 71% 3, 7") - self.check_coverage("""\ - a = 1; b = 2; c = 3; - if a != 1: - x = 3 - elif b != 2: - y = 5 - else: - z = 7 - assert z == 7 - """, - [1,2,3,4,5,7,8], "3, 5", report="7 2 71% 3, 5") - - def test_elif_no_else(self): - self.check_coverage("""\ - a = 1; b = 2; c = 3; - if a == 1: - x = 3 - elif b == 2: - y = 5 - assert x == 3 - """, - [1,2,3,4,5,6], "4-5", report="6 2 67% 4-5") - self.check_coverage("""\ - a = 1; b = 2; c = 3; - if a != 1: - x = 3 - elif b == 2: - y = 5 - assert y == 5 - """, - [1,2,3,4,5,6], "3", report="6 1 83% 3") - - def test_elif_bizarre(self): - self.check_coverage("""\ - def f(self): - if self==1: - x = 3 - elif self.m('fred'): - x = 5 - elif (g==1) and (b==2): - x = 7 - elif self.m('fred')==True: - x = 9 - elif ((g==1) and (b==2))==True: - x = 11 - else: - x = 13 - """, - [1,2,3,4,5,6,7,8,9,10,11,13], "2-13") - - def test_split_if(self): - self.check_coverage("""\ - a = 1; b = 2; c = 3; - if \\ - a == 1: - x = 3 - elif \\ - b == 2: - y = 5 - else: - z = 7 - assert x == 3 - """, - [1,2,4,5,7,9,10], "5-9") - self.check_coverage("""\ - a = 1; b = 2; c = 3; - if \\ - a != 1: - x = 3 - elif \\ - b == 2: - y = 5 - else: - z = 7 - assert y == 5 - """, - [1,2,4,5,7,9,10], "4, 9") - self.check_coverage("""\ - a = 1; b = 2; c = 3; - if \\ - a != 1: - x = 3 - elif \\ - b != 2: - y = 5 - else: - z = 7 - assert z == 7 - """, - [1,2,4,5,7,9,10], "4, 7") - - def test_pathological_split_if(self): - self.check_coverage("""\ - a = 1; b = 2; c = 3; - if ( - a == 1 - ): - x = 3 - elif ( - b == 2 - ): - y = 5 - else: - z = 7 - assert x == 3 - """, - [1,2,5,6,9,11,12], "6-11") - self.check_coverage("""\ - a = 1; b = 2; c = 3; - if ( - a != 1 - ): - x = 3 - elif ( - b == 2 - ): - y = 5 - else: - z = 7 - assert y == 5 - """, - [1,2,5,6,9,11,12], "5, 11") - self.check_coverage("""\ - a = 1; b = 2; c = 3; - if ( - a != 1 - ): - x = 3 - elif ( - b != 2 - ): - y = 5 - else: - z = 7 - assert z == 7 - """, - [1,2,5,6,9,11,12], "5, 9") - - def test_absurd_split_if(self): - self.check_coverage("""\ - a = 1; b = 2; c = 3; - if a == 1 \\ - : - x = 3 - elif b == 2 \\ - : - y = 5 - else: - z = 7 - assert x == 3 - """, - [1,2,4,5,7,9,10], "5-9") - self.check_coverage("""\ - a = 1; b = 2; c = 3; - if a != 1 \\ - : - x = 3 - elif b == 2 \\ - : - y = 5 - else: - z = 7 - assert y == 5 - """, - [1,2,4,5,7,9,10], "4, 9") - self.check_coverage("""\ - a = 1; b = 2; c = 3; - if a != 1 \\ - : - x = 3 - elif b != 2 \\ - : - y = 5 - else: - z = 7 - assert z == 7 - """, - [1,2,4,5,7,9,10], "4, 7") - - if sys.version_info >= (2, 4): - # In 2.4 and up, constant if's were compiled away. - def test_constant_if(self): - self.check_coverage("""\ - if 1: - a = 2 - assert a == 2 - """, - [2,3], "") - - def test_while(self): - self.check_coverage("""\ - a = 3; b = 0 - while a: - b += 1 - a -= 1 - assert a == 0 and b == 3 - """, - [1,2,3,4,5], "") - self.check_coverage("""\ - a = 3; b = 0 - while a: - b += 1 - break - b = 99 - assert a == 3 and b == 1 - """, - [1,2,3,4,5,6], "5") - - def test_while_else(self): - # Take the else branch. - self.check_coverage("""\ - a = 3; b = 0 - while a: - b += 1 - a -= 1 - else: - b = 99 - assert a == 0 and b == 99 - """, - [1,2,3,4,6,7], "") - # Don't take the else branch. - self.check_coverage("""\ - a = 3; b = 0 - while a: - b += 1 - a -= 1 - break - b = 123 - else: - b = 99 - assert a == 2 and b == 1 - """, - [1,2,3,4,5,6,8,9], "6-8") - - def test_split_while(self): - self.check_coverage("""\ - a = 3; b = 0 - while \\ - a: - b += 1 - a -= 1 - assert a == 0 and b == 3 - """, - [1,2,4,5,6], "") - self.check_coverage("""\ - a = 3; b = 0 - while ( - a - ): - b += 1 - a -= 1 - assert a == 0 and b == 3 - """, - [1,2,5,6,7], "") - - def test_for(self): - self.check_coverage("""\ - a = 0 - for i in [1,2,3,4,5]: - a += i - assert a == 15 - """, - [1,2,3,4], "") - self.check_coverage("""\ - a = 0 - for i in [1, - 2,3,4, - 5]: - a += i - assert a == 15 - """, - [1,2,5,6], "") - self.check_coverage("""\ - a = 0 - for i in [1,2,3,4,5]: - a += i - break - a = 99 - assert a == 1 - """, - [1,2,3,4,5,6], "5") - - def test_for_else(self): - self.check_coverage("""\ - a = 0 - for i in range(5): - a += i+1 - else: - a = 99 - assert a == 99 - """, - [1,2,3,5,6], "") - self.check_coverage("""\ - a = 0 - for i in range(5): - a += i+1 - break - a = 99 - else: - a = 123 - assert a == 1 - """, - [1,2,3,4,5,7,8], "5-7") - - def test_split_for(self): - self.check_coverage("""\ - a = 0 - for \\ - i in [1,2,3,4,5]: - a += i - assert a == 15 - """, - [1,2,4,5], "") - self.check_coverage("""\ - a = 0 - for \\ - i in [1, - 2,3,4, - 5]: - a += i - assert a == 15 - """, - [1,2,6,7], "") - - def test_try_except(self): - self.check_coverage("""\ - a = 0 - try: - a = 1 - except: - a = 99 - assert a == 1 - """, - [1,2,3,4,5,6], "4-5") - self.check_coverage("""\ - a = 0 - try: - a = 1 - raise Exception("foo") - except: - a = 99 - assert a == 99 - """, - [1,2,3,4,5,6,7], "") - self.check_coverage("""\ - a = 0 - try: - a = 1 - raise Exception("foo") - except ImportError: - a = 99 - except: - a = 123 - assert a == 123 - """, - [1,2,3,4,5,6,7,8,9], "6") - self.check_coverage("""\ - a = 0 - try: - a = 1 - raise IOError("foo") - except ImportError: - a = 99 - except IOError: - a = 17 - except: - a = 123 - assert a == 17 - """, - [1,2,3,4,5,6,7,8,9,10,11], "6, 9-10") - self.check_coverage("""\ - a = 0 - try: - a = 1 - except: - a = 99 - else: - a = 123 - assert a == 123 - """, - [1,2,3,4,5,7,8], "4-5") - self.check_coverage("""\ - a = 0 - try: - a = 1 - raise Exception("foo") - except: - a = 99 - else: - a = 123 - assert a == 99 - """, - [1,2,3,4,5,6,8,9], "8") - - def test_try_finally(self): - self.check_coverage("""\ - a = 0 - try: - a = 1 - finally: - a = 99 - assert a == 99 - """, - [1,2,3,5,6], "") - self.check_coverage("""\ - a = 0; b = 0 - try: - a = 1 - try: - raise Exception("foo") - finally: - b = 123 - except: - a = 99 - assert a == 99 and b == 123 - """, - [1,2,3,4,5,7,8,9,10], "") - - def test_function_def(self): - self.check_coverage("""\ - a = 99 - def foo(): - ''' docstring - ''' - return 1 - - a = foo() - assert a == 1 - """, - [1,2,5,7,8], "") - self.check_coverage("""\ - def foo( - a, - b - ): - ''' docstring - ''' - return a+b - - x = foo(17, 23) - assert x == 40 - """, - [1,7,9,10], "") - self.check_coverage("""\ - def foo( - a = (lambda x: x*2)(10), - b = ( - lambda x: - x+1 - )(1) - ): - ''' docstring - ''' - return a+b - - x = foo() - assert x == 22 - """, - [1,10,12,13], "") - - def test_class_def(self): - self.check_coverage("""\ - # A comment. - class theClass: - ''' the docstring. - Don't be fooled. - ''' - def __init__(self): - ''' Another docstring. ''' - self.a = 1 - - def foo(self): - return self.a - - x = theClass().foo() - assert x == 1 - """, - [2,6,8,10,11,13,14], "") - - -class ExcludeTest(CoverageTest): - """Tests of the exclusion feature to mark lines as not covered.""" - - def test_default(self): - # A number of forms of pragma comment are accepted. - self.check_coverage("""\ - a = 1 - b = 2 # pragma: no cover - c = 3 - d = 4 #pragma NOCOVER - e = 5 - """, - [1,3,5] - ) - - def test_simple(self): - self.check_coverage("""\ - a = 1; b = 2 - - if 0: - a = 4 # -cc - """, - [1,3], "", excludes=['-cc']) - - def test_two_excludes(self): - self.check_coverage("""\ - a = 1; b = 2 - - if a == 99: - a = 4 # -cc - b = 5 - c = 6 # -xx - assert a == 1 and b == 2 - """, - [1,3,5,7], "5", excludes=['-cc', '-xx']) - - def test_excluding_if_suite(self): - self.check_coverage("""\ - a = 1; b = 2 - - if 0: - a = 4 - b = 5 - c = 6 - assert a == 1 and b == 2 - """, - [1,7], "", excludes=['if 0:']) - - def test_excluding_if_but_not_else_suite(self): - self.check_coverage("""\ - a = 1; b = 2 - - if 0: - a = 4 - b = 5 - c = 6 - else: - a = 8 - b = 9 - assert a == 8 and b == 9 - """, - [1,8,9,10], "", excludes=['if 0:']) - - def test_excluding_else_suite(self): - self.check_coverage("""\ - a = 1; b = 2 - - if 1==1: - a = 4 - b = 5 - c = 6 - else: #pragma: NO COVER - a = 8 - b = 9 - assert a == 4 and b == 5 and c == 6 - """, - [1,3,4,5,6,10], "", excludes=['#pragma: NO COVER']) - self.check_coverage("""\ - a = 1; b = 2 - - if 1==1: - a = 4 - b = 5 - c = 6 - - # Lots of comments to confuse the else handler. - # more. - - else: #pragma: NO COVER - - # Comments here too. - - a = 8 - b = 9 - assert a == 4 and b == 5 and c == 6 - """, - [1,3,4,5,6,17], "", excludes=['#pragma: NO COVER']) - - def test_excluding_elif_suites(self): - self.check_coverage("""\ - a = 1; b = 2 - - if 1==1: - a = 4 - b = 5 - c = 6 - elif 1==0: #pragma: NO COVER - a = 8 - b = 9 - else: - a = 11 - b = 12 - assert a == 4 and b == 5 and c == 6 - """, - [1,3,4,5,6,11,12,13], "11-12", excludes=['#pragma: NO COVER']) - - def test_excluding_oneline_if(self): - self.check_coverage("""\ - def foo(): - a = 2 - if 0: x = 3 # no cover - b = 4 - - foo() - """, - [1,2,4,6], "", excludes=["no cover"]) - - def test_excluding_a_colon_not_a_suite(self): - self.check_coverage("""\ - def foo(): - l = list(range(10)) - a = l[:3] # no cover - b = 4 - - foo() - """, - [1,2,4,6], "", excludes=["no cover"]) - - def test_excluding_for_suite(self): - self.check_coverage("""\ - a = 0 - for i in [1,2,3,4,5]: #pragma: NO COVER - a += i - assert a == 15 - """, - [1,4], "", excludes=['#pragma: NO COVER']) - self.check_coverage("""\ - a = 0 - for i in [1, - 2,3,4, - 5]: #pragma: NO COVER - a += i - assert a == 15 - """, - [1,6], "", excludes=['#pragma: NO COVER']) - self.check_coverage("""\ - a = 0 - for i in [1,2,3,4,5 - ]: #pragma: NO COVER - a += i - break - a = 99 - assert a == 1 - """, - [1,7], "", excludes=['#pragma: NO COVER']) - - def test_excluding_for_else(self): - self.check_coverage("""\ - a = 0 - for i in range(5): - a += i+1 - break - a = 99 - else: #pragma: NO COVER - a = 123 - assert a == 1 - """, - [1,2,3,4,5,8], "5", excludes=['#pragma: NO COVER']) - - def test_excluding_while(self): - self.check_coverage("""\ - a = 3; b = 0 - while a*b: #pragma: NO COVER - b += 1 - break - b = 99 - assert a == 3 and b == 0 - """, - [1,6], "", excludes=['#pragma: NO COVER']) - self.check_coverage("""\ - a = 3; b = 0 - while ( - a*b - ): #pragma: NO COVER - b += 1 - break - b = 99 - assert a == 3 and b == 0 - """, - [1,8], "", excludes=['#pragma: NO COVER']) - - def test_excluding_while_else(self): - self.check_coverage("""\ - a = 3; b = 0 - while a: - b += 1 - break - b = 99 - else: #pragma: NO COVER - b = 123 - assert a == 3 and b == 1 - """, - [1,2,3,4,5,8], "5", excludes=['#pragma: NO COVER']) - - def test_excluding_try_except(self): - self.check_coverage("""\ - a = 0 - try: - a = 1 - except: #pragma: NO COVER - a = 99 - assert a == 1 - """, - [1,2,3,6], "", excludes=['#pragma: NO COVER']) - self.check_coverage("""\ - a = 0 - try: - a = 1 - raise Exception("foo") - except: - a = 99 - assert a == 99 - """, - [1,2,3,4,5,6,7], "", excludes=['#pragma: NO COVER']) - self.check_coverage("""\ - a = 0 - try: - a = 1 - raise Exception("foo") - except ImportError: #pragma: NO COVER - a = 99 - except: - a = 123 - assert a == 123 - """, - [1,2,3,4,7,8,9], "", excludes=['#pragma: NO COVER']) - self.check_coverage("""\ - a = 0 - try: - a = 1 - except: #pragma: NO COVER - a = 99 - else: - a = 123 - assert a == 123 - """, - [1,2,3,7,8], "", excludes=['#pragma: NO COVER']) - self.check_coverage("""\ - a = 0 - try: - a = 1 - raise Exception("foo") - except: - a = 99 - else: #pragma: NO COVER - a = 123 - assert a == 99 - """, - [1,2,3,4,5,6,9], "", excludes=['#pragma: NO COVER']) - - def test_excluding_try_except_pass(self): - self.check_coverage("""\ - a = 0 - try: - a = 1 - except: #pragma: NO COVER - x = 2 - assert a == 1 - """, - [1,2,3,6], "", excludes=['#pragma: NO COVER']) - self.check_coverage("""\ - a = 0 - try: - a = 1 - raise Exception("foo") - except ImportError: #pragma: NO COVER - x = 2 - except: - a = 123 - assert a == 123 - """, - [1,2,3,4,7,8,9], "", excludes=['#pragma: NO COVER']) - self.check_coverage("""\ - a = 0 - try: - a = 1 - except: #pragma: NO COVER - x = 2 - else: - a = 123 - assert a == 123 - """, - [1,2,3,7,8], "", excludes=['#pragma: NO COVER']) - self.check_coverage("""\ - a = 0 - try: - a = 1 - raise Exception("foo") - except: - a = 99 - else: #pragma: NO COVER - x = 2 - assert a == 99 - """, - [1,2,3,4,5,6,9], "", excludes=['#pragma: NO COVER']) - - def test_excluding_if_pass(self): - # From a comment on the coverage page by Michael McNeil Forbes: - self.check_coverage("""\ - def f(): - if False: # pragma: no cover - pass # This line still reported as missing - if False: # pragma: no cover - x = 1 # Now it is skipped. - - f() - """, - [1,7], "", excludes=["no cover"]) - - def test_excluding_function(self): - self.check_coverage("""\ - def fn(foo): #pragma: NO COVER - a = 1 - b = 2 - c = 3 - - x = 1 - assert x == 1 - """, - [6,7], "", excludes=['#pragma: NO COVER']) - - def test_excluding_method(self): - self.check_coverage("""\ - class Fooey: - def __init__(self): - self.a = 1 - - def foo(self): #pragma: NO COVER - return self.a - - x = Fooey() - assert x.a == 1 - """, - [1,2,3,8,9], "", excludes=['#pragma: NO COVER']) - - def test_excluding_class(self): - self.check_coverage("""\ - class Fooey: #pragma: NO COVER - def __init__(self): - self.a = 1 - - def foo(self): - return self.a - - x = 1 - assert x == 1 - """, - [8,9], "", excludes=['#pragma: NO COVER']) - - -if sys.version_info >= (2, 4): - class Py24Test(CoverageTest): - """Tests of new syntax in Python 2.4.""" - - def test_function_decorators(self): - self.check_coverage("""\ - def require_int(func): - def wrapper(arg): - assert isinstance(arg, int) - return func(arg) - - return wrapper - - @require_int - def p1(arg): - return arg*2 - - assert p1(10) == 20 - """, - [1,2,3,4,6,8,10,12], "") - - def test_function_decorators_with_args(self): - self.check_coverage("""\ - def boost_by(extra): - def decorator(func): - def wrapper(arg): - return extra*func(arg) - return wrapper - return decorator - - @boost_by(10) - def boosted(arg): - return arg*2 - - assert boosted(10) == 200 - """, - [1,2,3,4,5,6,8,10,12], "") - - def test_double_function_decorators(self): - self.check_coverage("""\ - def require_int(func): - def wrapper(arg): - assert isinstance(arg, int) - return func(arg) - return wrapper - - def boost_by(extra): - def decorator(func): - def wrapper(arg): - return extra*func(arg) - return wrapper - return decorator - - @require_int - @boost_by(10) - def boosted1(arg): - return arg*2 - - assert boosted1(10) == 200 - - @boost_by(10) - @require_int - def boosted2(arg): - return arg*2 - - assert boosted2(10) == 200 - """, - ([1,2,3,4,5,7,8,9,10,11,12,14,15,17,19,21,22,24,26], - [1,2,3,4,5,7,8,9,10,11,12,14, 17,19,21, 24,26]), "") - - -if sys.version_info >= (2, 5): - class Py25Test(CoverageTest): - """Tests of new syntax in Python 2.5.""" - - def test_with_statement(self): - self.check_coverage("""\ - from __future__ import with_statement - - class Managed: - def __enter__(self): - desc = "enter" - - def __exit__(self, type, value, tb): - desc = "exit" - - m = Managed() - with m: - desc = "block1a" - desc = "block1b" - - try: - with m: - desc = "block2" - raise Exception("Boo!") - except: - desc = "caught" - """, - [1,3,4,5,7,8,10,11,12,13,15,16,17,18,19,20], "") - - def test_try_except_finally(self): - self.check_coverage("""\ - a = 0; b = 0 - try: - a = 1 - except: - a = 99 - finally: - b = 2 - assert a == 1 and b == 2 - """, - [1,2,3,4,5,7,8], "4-5") - self.check_coverage("""\ - a = 0; b = 0 - try: - a = 1 - raise Exception("foo") - except: - a = 99 - finally: - b = 2 - assert a == 99 and b == 2 - """, - [1,2,3,4,5,6,8,9], "") - self.check_coverage("""\ - a = 0; b = 0 - try: - a = 1 - raise Exception("foo") - except ImportError: - a = 99 - except: - a = 123 - finally: - b = 2 - assert a == 123 and b == 2 - """, - [1,2,3,4,5,6,7,8,10,11], "6") - self.check_coverage("""\ - a = 0; b = 0 - try: - a = 1 - raise IOError("foo") - except ImportError: - a = 99 - except IOError: - a = 17 - except: - a = 123 - finally: - b = 2 - assert a == 17 and b == 2 - """, - [1,2,3,4,5,6,7,8,9,10,12,13], "6, 9-10") - self.check_coverage("""\ - a = 0; b = 0 - try: - a = 1 - except: - a = 99 - else: - a = 123 - finally: - b = 2 - assert a == 123 and b == 2 - """, - [1,2,3,4,5,7,9,10], "4-5") - self.check_coverage("""\ - a = 0; b = 0 - try: - a = 1 - raise Exception("foo") - except: - a = 99 - else: - a = 123 - finally: - b = 2 - assert a == 99 and b == 2 - """, - [1,2,3,4,5,6,8,10,11], "8") - - -class ModuleTest(CoverageTest): - """Tests for the module-level behavior of the `coverage` module.""" - - def test_not_singleton(self): - # You *can* create another coverage object. - coverage.coverage() - coverage.coverage() - - -class ReportingTest(CoverageTest): - """Tests of some reporting behavior.""" - - def test_no_data_to_report_on_annotate(self): - # Reporting with no data produces a nice message and no output dir. - self.assertRaisesRegexp( - CoverageException, "No data to report.", - self.command_line, "annotate -d ann" - ) - self.assert_doesnt_exist("ann") - - def test_no_data_to_report_on_html(self): - # Reporting with no data produces a nice message and no output dir. - self.assertRaisesRegexp( - CoverageException, "No data to report.", - self.command_line, "html -d htmlcov" - ) - self.assert_doesnt_exist("htmlcov") - - def test_no_data_to_report_on_xml(self): - # Reporting with no data produces a nice message. - self.assertRaisesRegexp( - CoverageException, "No data to report.", - self.command_line, "xml" - ) - # Currently, this leaves an empty coverage.xml file... :( diff --git a/test/test_data.py b/test/test_data.py deleted file mode 100644 index 9281ccc7..00000000 --- a/test/test_data.py +++ /dev/null @@ -1,146 +0,0 @@ -"""Tests for coverage.data""" - -from coverage.backward import pickle -from coverage.data import CoverageData -from coverage.files import PathAliases - -from test.coveragetest import CoverageTest - - -DATA_1 = { 'a.py': {1:None, 2:None}, 'b.py': {3:None} } -SUMMARY_1 = { 'a.py':2, 'b.py':1 } -MEASURED_FILES_1 = [ 'a.py', 'b.py' ] -A_PY_LINES_1 = [1,2] -B_PY_LINES_1 = [3] - -DATA_2 = { 'a.py': {1:None, 5:None}, 'c.py': {17:None} } -SUMMARY_1_2 = { 'a.py':3, 'b.py':1, 'c.py':1 } -MEASURED_FILES_1_2 = [ 'a.py', 'b.py', 'c.py' ] - -ARC_DATA_3 = { 'x.py': {(1,2):None, (2,3):None}, 'y.py': {(17,23):None} } -X_PY_ARCS_3 = [(1,2), (2,3)] -Y_PY_ARCS_3 = [(17,23)] - - -class DataTest(CoverageTest): - """Test cases for coverage.data.""" - - def assert_summary(self, covdata, summary, fullpath=False): - """Check that the summary of `covdata` is `summary`.""" - self.assertEqual(covdata.summary(fullpath), summary) - - def assert_measured_files(self, covdata, measured): - """Check that `covdata`'s measured files are `measured`.""" - self.assertSameElements(covdata.measured_files(), measured) - - def test_reading_empty(self): - covdata = CoverageData() - covdata.read() - self.assert_summary(covdata, {}) - - def test_adding_data(self): - covdata = CoverageData() - covdata.add_line_data(DATA_1) - self.assert_summary(covdata, SUMMARY_1) - self.assert_measured_files(covdata, MEASURED_FILES_1) - - def test_touch_file(self): - covdata = CoverageData() - covdata.add_line_data(DATA_1) - covdata.touch_file('x.py') - self.assert_measured_files(covdata, MEASURED_FILES_1 + ['x.py']) - - def test_writing_and_reading(self): - covdata1 = CoverageData() - covdata1.add_line_data(DATA_1) - covdata1.write() - - covdata2 = CoverageData() - covdata2.read() - self.assert_summary(covdata2, SUMMARY_1) - - def test_combining(self): - covdata1 = CoverageData() - covdata1.add_line_data(DATA_1) - covdata1.write(suffix='1') - - covdata2 = CoverageData() - covdata2.add_line_data(DATA_2) - covdata2.write(suffix='2') - - covdata3 = CoverageData() - covdata3.combine_parallel_data() - self.assert_summary(covdata3, SUMMARY_1_2) - self.assert_measured_files(covdata3, MEASURED_FILES_1_2) - - def test_erasing(self): - covdata1 = CoverageData() - covdata1.add_line_data(DATA_1) - covdata1.write() - covdata1.erase() - self.assert_summary(covdata1, {}) - - covdata2 = CoverageData() - covdata2.read() - self.assert_summary(covdata2, {}) - - def test_file_format(self): - # Write with CoverageData, then read the pickle explicitly. - covdata = CoverageData() - covdata.add_line_data(DATA_1) - covdata.write() - - fdata = open(".coverage", 'rb') - try: - data = pickle.load(fdata) - finally: - fdata.close() - - lines = data['lines'] - self.assertSameElements(lines.keys(), MEASURED_FILES_1) - self.assertSameElements(lines['a.py'], A_PY_LINES_1) - self.assertSameElements(lines['b.py'], B_PY_LINES_1) - # If not measuring branches, there's no arcs entry. - self.assertEqual(data.get('arcs', 'not there'), 'not there') - - def test_file_format_with_arcs(self): - # Write with CoverageData, then read the pickle explicitly. - covdata = CoverageData() - covdata.add_arc_data(ARC_DATA_3) - covdata.write() - - fdata = open(".coverage", 'rb') - try: - data = pickle.load(fdata) - finally: - fdata.close() - - self.assertSameElements(data['lines'].keys(), []) - arcs = data['arcs'] - self.assertSameElements(arcs['x.py'], X_PY_ARCS_3) - self.assertSameElements(arcs['y.py'], Y_PY_ARCS_3) - - def test_combining_with_aliases(self): - covdata1 = CoverageData() - covdata1.add_line_data({ - '/home/ned/proj/src/a.py': {1:None, 2:None}, - '/home/ned/proj/src/sub/b.py': {3:None}, - }) - covdata1.write(suffix='1') - - covdata2 = CoverageData() - covdata2.add_line_data({ - r'c:\ned\test\a.py': {4:None, 5:None}, - r'c:\ned\test\sub\b.py': {6:None}, - }) - covdata2.write(suffix='2') - - covdata3 = CoverageData() - aliases = PathAliases() - aliases.add("/home/ned/proj/src/", "./") - aliases.add(r"c:\ned\test", "./") - covdata3.combine_parallel_data(aliases=aliases) - self.assert_summary( - covdata3, { './a.py':4, './sub/b.py':2 }, fullpath=True - ) - self.assert_measured_files(covdata3, [ './a.py', './sub/b.py' ]) diff --git a/test/test_execfile.py b/test/test_execfile.py deleted file mode 100644 index e7d7041f..00000000 --- a/test/test_execfile.py +++ /dev/null @@ -1,116 +0,0 @@ -"""Tests for coverage.execfile""" - -import os, sys - -from coverage.execfile import run_python_file, run_python_module -from coverage.misc import NoSource - -from test.coveragetest import CoverageTest - -here = os.path.dirname(__file__) - -class RunFileTest(CoverageTest): - """Test cases for `run_python_file`.""" - - def test_run_python_file(self): - tryfile = os.path.join(here, "try_execfile.py") - run_python_file(tryfile, [tryfile, "arg1", "arg2"]) - mod_globs = eval(self.stdout()) - - # The file should think it is __main__ - self.assertEqual(mod_globs['__name__'], "__main__") - - # It should seem to come from a file named try_execfile.py - dunder_file = os.path.basename(mod_globs['__file__']) - self.assertEqual(dunder_file, "try_execfile.py") - - # It should have its correct module data. - self.assertEqual(mod_globs['__doc__'], - "Test file for run_python_file.") - self.assertEqual(mod_globs['DATA'], "xyzzy") - self.assertEqual(mod_globs['FN_VAL'], "my_fn('fooey')") - - # It must be self-importable as __main__. - self.assertEqual(mod_globs['__main__.DATA'], "xyzzy") - - # Argv should have the proper values. - self.assertEqual(mod_globs['argv'], [tryfile, "arg1", "arg2"]) - - # __builtins__ should have the right values, like open(). - self.assertEqual(mod_globs['__builtins__.has_open'], True) - - def test_no_extra_file(self): - # Make sure that running a file doesn't create an extra compiled file. - self.make_file("xxx", """\ - desc = "a non-.py file!" - """) - - self.assertEqual(os.listdir("."), ["xxx"]) - run_python_file("xxx", ["xxx"]) - self.assertEqual(os.listdir("."), ["xxx"]) - - def test_universal_newlines(self): - # Make sure we can read any sort of line ending. - pylines = """# try newlines|print('Hello, world!')|""".split('|') - for nl in ('\n', '\r\n', '\r'): - fpy = open('nl.py', 'wb') - try: - fpy.write(nl.join(pylines).encode('utf-8')) - finally: - fpy.close() - run_python_file('nl.py', ['nl.py']) - self.assertEqual(self.stdout(), "Hello, world!\n"*3) - - def test_missing_final_newline(self): - # Make sure we can deal with a Python file with no final newline. - self.make_file("abrupt.py", """\ - if 1: - a = 1 - print("a is %r" % a) - #""") - abrupt = open("abrupt.py").read() - self.assertEqual(abrupt[-1], '#') - run_python_file("abrupt.py", ["abrupt.py"]) - self.assertEqual(self.stdout(), "a is 1\n") - - def test_no_such_file(self): - self.assertRaises(NoSource, run_python_file, "xyzzy.py", []) - - -class RunModuleTest(CoverageTest): - """Test run_python_module.""" - - run_in_temp_dir = False - - def setUp(self): - super(RunModuleTest, self).setUp() - # Parent class saves and restores sys.path, we can just modify it. - sys.path.append(self.nice_file(os.path.dirname(__file__), 'modules')) - - def test_runmod1(self): - run_python_module("runmod1", ["runmod1", "hello"]) - self.assertEqual(self.stdout(), "runmod1: passed hello\n") - - def test_runmod2(self): - run_python_module("pkg1.runmod2", ["runmod2", "hello"]) - self.assertEqual(self.stdout(), "runmod2: passed hello\n") - - def test_runmod3(self): - run_python_module("pkg1.sub.runmod3", ["runmod3", "hello"]) - self.assertEqual(self.stdout(), "runmod3: passed hello\n") - - def test_pkg1_main(self): - run_python_module("pkg1", ["pkg1", "hello"]) - self.assertEqual(self.stdout(), "pkg1.__main__: passed hello\n") - - def test_pkg1_sub_main(self): - run_python_module("pkg1.sub", ["pkg1.sub", "hello"]) - self.assertEqual(self.stdout(), "pkg1.sub.__main__: passed hello\n") - - def test_no_such_module(self): - self.assertRaises(NoSource, run_python_module, "i_dont_exist", []) - self.assertRaises(NoSource, run_python_module, "i.dont_exist", []) - self.assertRaises(NoSource, run_python_module, "i.dont.exist", []) - - def test_no_main(self): - self.assertRaises(NoSource, run_python_module, "pkg2", ["pkg2", "hi"]) diff --git a/test/test_farm.py b/test/test_farm.py deleted file mode 100644 index f25d6109..00000000 --- a/test/test_farm.py +++ /dev/null @@ -1,366 +0,0 @@ -"""Run tests in the farm subdirectory. Designed for nose.""" - -import difflib, filecmp, fnmatch, glob, os, re, shutil, sys -from nose.plugins.skip import SkipTest - -from test.backtest import run_command, execfile # pylint: disable=W0622 - -from coverage.control import _TEST_NAME_FILE - - -def test_farm(clean_only=False): - """A test-generating function for nose to find and run.""" - for fname in glob.glob("test/farm/*/*.py"): - case = FarmTestCase(fname, clean_only) - yield (case,) - - -class FarmTestCase(object): - """A test case from the farm tree. - - Tests are short Python script files, often called run.py: - - copy("src", "out") - run(''' - coverage -x white.py - coverage -a white.py - ''', rundir="out") - compare("out", "gold", "*,cover") - clean("out") - - Verbs (copy, run, compare, clean) are methods in this class. FarmTestCase - has options to allow various uses of the test cases (normal execution, - cleaning-only, or run and leave the results for debugging). - - """ - def __init__(self, runpy, clean_only=False, dont_clean=False): - """Create a test case from a run.py file. - - `clean_only` means that only the clean() action is executed. - `dont_clean` means that the clean() action is not executed. - - """ - self.description = runpy - self.dir, self.runpy = os.path.split(runpy) - self.clean_only = clean_only - self.dont_clean = dont_clean - - def cd(self, newdir): - """Change the current directory, and return the old one.""" - cwd = os.getcwd() - os.chdir(newdir) - return cwd - - def addtopath(self, directory): - """Add `directory` to the path, and return the old path.""" - oldpath = sys.path[:] - if directory is not None: - sys.path.insert(0, directory) - return oldpath - - def restorepath(self, path): - """Restore the system path to `path`.""" - sys.path = path - - def __call__(self): - """Execute the test from the run.py file. - - """ - if _TEST_NAME_FILE: - f = open(_TEST_NAME_FILE, "w") - f.write(self.description.replace("/", "_")) - f.close() - - cwd = self.cd(self.dir) - - # Prepare a dictionary of globals for the run.py files to use. - fns = """ - copy run runfunc compare contains doesnt_contain clean skip - """.split() - if self.clean_only: - glo = dict([(fn, self.noop) for fn in fns]) - glo['clean'] = self.clean - else: - glo = dict([(fn, getattr(self, fn)) for fn in fns]) - if self.dont_clean: # pragma: not covered - glo['clean'] = self.noop - - old_mods = dict(sys.modules) - try: - execfile(self.runpy, glo) - finally: - self.cd(cwd) - # Remove any new modules imported during the test run. This lets us - # import the same source files for more than one test. - to_del = [m for m in sys.modules if m not in old_mods] - for m in to_del: - del sys.modules[m] - - def run_fully(self): # pragma: not covered - """Run as a full test case, with setUp and tearDown.""" - self.setUp() - try: - self() - finally: - self.tearDown() - - def fnmatch_list(self, files, file_pattern): - """Filter the list of `files` to only those that match `file_pattern`. - - If `file_pattern` is None, then return the entire list of files. - - Returns a list of the filtered files. - - """ - if file_pattern: - files = [f for f in files if fnmatch.fnmatch(f, file_pattern)] - return files - - def setUp(self): - """Test set up, run by nose before __call__.""" - - # Modules should be importable from the current directory. - self.old_syspath = sys.path[:] - sys.path.insert(0, '') - - def tearDown(self): - """Test tear down, run by nose after __call__.""" - # Make sure no matter what, the test is cleaned up. - if not self.dont_clean: # pragma: part covered - self.clean_only = True - self() - - # Restore the original sys.path - sys.path = self.old_syspath - - # Functions usable inside farm run.py files - - def noop(self, *args, **kwargs): - """A no-op function to stub out run, copy, etc, when only cleaning.""" - pass - - def copy(self, src, dst): - """Copy a directory.""" - - if os.path.exists(dst): - shutil.rmtree(dst) - shutil.copytree(src, dst) - - def run(self, cmds, rundir="src", outfile=None): - """Run a list of commands. - - `cmds` is a string, commands separated by newlines. - `rundir` is the directory in which to run the commands. - `outfile` is a filename to redirect stdout to. - - """ - cwd = self.cd(rundir) - if outfile: - fout = open(outfile, "a+") - try: - for cmd in cmds.split("\n"): - cmd = cmd.strip() - if not cmd: - continue - retcode, output = run_command(cmd) - print(output.rstrip()) - if outfile: - fout.write(output) - if retcode: - raise Exception("command exited abnormally") - finally: - if outfile: - fout.close() - self.cd(cwd) - - def runfunc(self, fn, rundir="src", addtopath=None): - """Run a function. - - `fn` is a callable. - `rundir` is the directory in which to run the function. - - """ - - cwd = self.cd(rundir) - oldpath = self.addtopath(addtopath) - try: - fn() - finally: - self.cd(cwd) - self.restorepath(oldpath) - - def compare(self, dir1, dir2, file_pattern=None, size_within=0, - left_extra=False, right_extra=False, scrubs=None - ): - """Compare files matching `file_pattern` in `dir1` and `dir2`. - - `dir2` is interpreted as a prefix, with Python version numbers appended - to find the actual directory to compare with. "foo" will compare against - "foo_v241", "foo_v24", "foo_v2", or "foo", depending on which directory - is found first. - - `size_within` is a percentage delta for the file sizes. If non-zero, - then the file contents are not compared (since they are expected to - often be different), but the file sizes must be within this amount. - For example, size_within=10 means that the two files' sizes must be - within 10 percent of each other to compare equal. - - `left_extra` true means the left directory can have extra files in it - without triggering an assertion. `right_extra` means the right - directory can. - - `scrubs` is a list of pairs, regex find and replace patterns to use to - scrub the files of unimportant differences. - - An assertion will be raised if the directories fail one of their - matches. - - """ - # Search for a dir2 with a version suffix. - version_suff = ''.join(map(str, sys.version_info[:3])) - while version_suff: - trydir = dir2 + '_v' + version_suff - if os.path.exists(trydir): - dir2 = trydir - break - version_suff = version_suff[:-1] - - assert os.path.exists(dir1), "Left directory missing: %s" % dir1 - assert os.path.exists(dir2), "Right directory missing: %s" % dir2 - - dc = filecmp.dircmp(dir1, dir2) - diff_files = self.fnmatch_list(dc.diff_files, file_pattern) - left_only = self.fnmatch_list(dc.left_only, file_pattern) - right_only = self.fnmatch_list(dc.right_only, file_pattern) - - if size_within: - # The files were already compared, use the diff_files list as a - # guide for size comparison. - wrong_size = [] - for f in diff_files: - left = open(os.path.join(dir1, f), "rb").read() - right = open(os.path.join(dir2, f), "rb").read() - size_l, size_r = len(left), len(right) - big, little = max(size_l, size_r), min(size_l, size_r) - if (big - little) / float(little) > size_within/100.0: - # print "%d %d" % (big, little) - # print "Left: ---\n%s\n-----\n%s" % (left, right) - wrong_size.append(f) - assert not wrong_size, ( - "File sizes differ between %s and %s: %s" % ( - dir1, dir2, wrong_size - )) - else: - # filecmp only compares in binary mode, but we want text mode. So - # look through the list of different files, and compare them - # ourselves. - text_diff = [] - for f in diff_files: - left = open(os.path.join(dir1, f), "rU").readlines() - right = open(os.path.join(dir2, f), "rU").readlines() - if scrubs: - left = self._scrub(left, scrubs) - right = self._scrub(right, scrubs) - if left != right: - text_diff.append(f) - print("".join(list(difflib.Differ().compare(left, right)))) - assert not text_diff, "Files differ: %s" % text_diff - - if not left_extra: - assert not left_only, "Files in %s only: %s" % (dir1, left_only) - if not right_extra: - assert not right_only, "Files in %s only: %s" % (dir2, right_only) - - def _scrub(self, strlist, scrubs): - """Scrub uninteresting data from the strings in `strlist`. - - `scrubs is a list of (find, replace) pairs of regexes that are used on - each string in `strlist`. A list of scrubbed strings is returned. - - """ - scrubbed = [] - for s in strlist: - for rgx_find, rgx_replace in scrubs: - s = re.sub(rgx_find, rgx_replace, s) - scrubbed.append(s) - return scrubbed - - def contains(self, filename, *strlist): - """Check that the file contains all of a list of strings. - - An assert will be raised if one of the arguments in `strlist` is - missing in `filename`. - - """ - text = open(filename, "r").read() - for s in strlist: - assert s in text, "Missing content in %s: %r" % (filename, s) - - def doesnt_contain(self, filename, *strlist): - """Check that the file contains none of a list of strings. - - An assert will be raised if any of the strings in strlist appears in - `filename`. - - """ - text = open(filename, "r").read() - for s in strlist: - assert s not in text, "Forbidden content in %s: %r" % (filename, s) - - def clean(self, cleandir): - """Clean `cleandir` by removing it and all its children completely.""" - # rmtree gives mysterious failures on Win7, so retry a "few" times. - # I've seen it take over 100 tries, so, 1000! This is probably the - # most unpleasant hack I've written in a long time... - tries = 1000 - while tries: # pragma: part covered - if os.path.exists(cleandir): - try: - shutil.rmtree(cleandir) - except OSError: # pragma: not covered - if tries == 1: - raise - else: - tries -= 1 - continue - break - - def skip(self, msg=None): - """Skip the current test.""" - raise SkipTest(msg) - - -def main(): # pragma: not covered - """Command-line access to test_farm. - - Commands: - - run testcase - Run a single test case. - out testcase - Run a test case, but don't clean up, to see the output. - clean - Clean all the output for all tests. - - """ - op = 'help' - try: - op = sys.argv[1] - except IndexError: - pass - - if op == 'run': - # Run the test for real. - case = FarmTestCase(sys.argv[2]) - case.run_fully() - elif op == 'out': - # Run the test, but don't clean up, so we can examine the output. - case = FarmTestCase(sys.argv[2], dont_clean=True) - case.run_fully() - elif op == 'clean': - # Run all the tests, but just clean. - for test in test_farm(clean_only=True): - test[0].run_fully() - else: - print(main.__doc__) - -# So that we can run just one farm run.py at a time. -if __name__ == '__main__': - main() diff --git a/test/test_files.py b/test/test_files.py deleted file mode 100644 index 051b2743..00000000 --- a/test/test_files.py +++ /dev/null @@ -1,169 +0,0 @@ -"""Tests for files.py""" - -import os - -from coverage.files import FileLocator, TreeMatcher, FnmatchMatcher -from coverage.files import PathAliases, find_python_files, abs_file -from coverage.backward import set # pylint: disable=W0622 -from coverage.misc import CoverageException - -from test.coveragetest import CoverageTest - - -class FileLocatorTest(CoverageTest): - """Tests of `FileLocator`.""" - - def abs_path(self, p): - """Return the absolute path for `p`.""" - return os.path.join(os.getcwd(), os.path.normpath(p)) - - def test_simple(self): - self.make_file("hello.py") - fl = FileLocator() - self.assertEqual(fl.relative_filename("hello.py"), "hello.py") - a = self.abs_path("hello.py") - self.assertNotEqual(a, "hello.py") - self.assertEqual(fl.relative_filename(a), "hello.py") - - def test_peer_directories(self): - self.make_file("sub/proj1/file1.py") - self.make_file("sub/proj2/file2.py") - a1 = self.abs_path("sub/proj1/file1.py") - a2 = self.abs_path("sub/proj2/file2.py") - d = os.path.normpath("sub/proj1") - os.chdir(d) - fl = FileLocator() - self.assertEqual(fl.relative_filename(a1), "file1.py") - self.assertEqual(fl.relative_filename(a2), a2) - - def test_filepath_contains_absolute_prefix_twice(self): - # https://bitbucket.org/ned/coveragepy/issue/194 - # Build a path that has two pieces matching the absolute path prefix. - # Technically, this test doesn't do that on Windows, but drive - # letters make that impractical to acheive. - fl = FileLocator() - d = abs_file(os.curdir) - trick = os.path.splitdrive(d)[1].lstrip(os.path.sep) - rel = os.path.join('sub', trick, 'file1.py') - self.assertEqual(fl.relative_filename(abs_file(rel)), rel) - - -class MatcherTest(CoverageTest): - """Tests of file matchers.""" - - def test_tree_matcher(self): - file1 = self.make_file("sub/file1.py") - file2 = self.make_file("sub/file2.c") - file3 = self.make_file("sub2/file3.h") - file4 = self.make_file("sub3/file4.py") - file5 = self.make_file("sub3/file5.c") - fl = FileLocator() - tm = TreeMatcher([ - fl.canonical_filename("sub"), - fl.canonical_filename(file4), - ]) - self.assertTrue(tm.match(fl.canonical_filename(file1))) - self.assertTrue(tm.match(fl.canonical_filename(file2))) - self.assertFalse(tm.match(fl.canonical_filename(file3))) - self.assertTrue(tm.match(fl.canonical_filename(file4))) - self.assertFalse(tm.match(fl.canonical_filename(file5))) - - def test_fnmatch_matcher(self): - file1 = self.make_file("sub/file1.py") - file2 = self.make_file("sub/file2.c") - file3 = self.make_file("sub2/file3.h") - file4 = self.make_file("sub3/file4.py") - file5 = self.make_file("sub3/file5.c") - fl = FileLocator() - fnm = FnmatchMatcher(["*.py", "*/sub2/*"]) - self.assertTrue(fnm.match(fl.canonical_filename(file1))) - self.assertFalse(fnm.match(fl.canonical_filename(file2))) - self.assertTrue(fnm.match(fl.canonical_filename(file3))) - self.assertTrue(fnm.match(fl.canonical_filename(file4))) - self.assertFalse(fnm.match(fl.canonical_filename(file5))) - - -class PathAliasesTest(CoverageTest): - """Tests for coverage/files.py:PathAliases""" - - def test_noop(self): - aliases = PathAliases() - self.assertEqual(aliases.map('/ned/home/a.py'), '/ned/home/a.py') - - def test_nomatch(self): - aliases = PathAliases() - aliases.add('/home/*/src', './mysrc') - self.assertEqual(aliases.map('/home/foo/a.py'), '/home/foo/a.py') - - def test_wildcard(self): - aliases = PathAliases() - aliases.add('/ned/home/*/src', './mysrc') - self.assertEqual(aliases.map('/ned/home/foo/src/a.py'), './mysrc/a.py') - aliases = PathAliases() - aliases.add('/ned/home/*/src/', './mysrc') - self.assertEqual(aliases.map('/ned/home/foo/src/a.py'), './mysrc/a.py') - - def test_no_accidental_match(self): - aliases = PathAliases() - aliases.add('/home/*/src', './mysrc') - self.assertEqual(aliases.map('/home/foo/srcetc'), '/home/foo/srcetc') - - def test_multiple_patterns(self): - aliases = PathAliases() - aliases.add('/home/*/src', './mysrc') - aliases.add('/lib/*/libsrc', './mylib') - self.assertEqual(aliases.map('/home/foo/src/a.py'), './mysrc/a.py') - self.assertEqual(aliases.map('/lib/foo/libsrc/a.py'), './mylib/a.py') - - def test_cant_have_wildcard_at_end(self): - aliases = PathAliases() - self.assertRaisesRegexp( - CoverageException, "Pattern must not end with wildcards.", - aliases.add, "/ned/home/*", "fooey" - ) - self.assertRaisesRegexp( - CoverageException, "Pattern must not end with wildcards.", - aliases.add, "/ned/home/*/", "fooey" - ) - self.assertRaisesRegexp( - CoverageException, "Pattern must not end with wildcards.", - aliases.add, "/ned/home/*/*/", "fooey" - ) - - def test_no_accidental_munging(self): - aliases = PathAliases() - aliases.add(r'c:\Zoo\boo', 'src/') - aliases.add('/home/ned$', 'src/') - self.assertEqual(aliases.map(r'c:\Zoo\boo\foo.py'), 'src/foo.py') - self.assertEqual(aliases.map(r'/home/ned$/foo.py'), 'src/foo.py') - - def test_paths_are_os_corrected(self): - aliases = PathAliases() - aliases.add('/home/ned/*/src', './mysrc') - aliases.add(r'c:\ned\src', './mysrc') - mapped = aliases.map(r'C:\Ned\src\sub\a.py') - self.assertEqual(mapped, './mysrc/sub/a.py') - - aliases = PathAliases() - aliases.add('/home/ned/*/src', r'.\mysrc') - aliases.add(r'c:\ned\src', r'.\mysrc') - mapped = aliases.map(r'/home/ned/foo/src/sub/a.py') - self.assertEqual(mapped, r'.\mysrc\sub\a.py') - - -class FindPythonFilesTest(CoverageTest): - """Tests of `find_python_files`.""" - - def test_find_python_files(self): - self.make_file("sub/a.py") - self.make_file("sub/b.py") - self.make_file("sub/x.c") # nope: not .py - self.make_file("sub/ssub/__init__.py") - self.make_file("sub/ssub/s.py") - self.make_file("sub/ssub/~s.py") # nope: editor effluvia - self.make_file("sub/lab/exp.py") # nope: no __init__.py - py_files = set(find_python_files("sub")) - self.assert_same_files(py_files, [ - "sub/a.py", "sub/b.py", - "sub/ssub/__init__.py", "sub/ssub/s.py", - ]) diff --git a/test/test_html.py b/test/test_html.py deleted file mode 100644 index 66d1bd7d..00000000 --- a/test/test_html.py +++ /dev/null @@ -1,297 +0,0 @@ -# -*- coding: utf-8 -*- -"""Tests that HTML generation is awesome.""" - -import os.path, re, sys -import coverage -from coverage.misc import NotPython, NoSource - -from test.coveragetest import CoverageTest - -class HtmlTestHelpers(CoverageTest): - """Methods that help with HTML tests.""" - - def create_initial_files(self): - """Create the source files we need to run these tests.""" - self.make_file("main_file.py", """\ - import helper1, helper2 - helper1.func1(12) - helper2.func2(12) - """) - self.make_file("helper1.py", """\ - def func1(x): - if x % 2: - print("odd") - """) - self.make_file("helper2.py", """\ - def func2(x): - print("x is %d" % x) - """) - - def run_coverage(self, covargs=None, htmlargs=None): - """Run coverage on main_file.py, and create an HTML report.""" - self.clean_local_file_imports() - cov = coverage.coverage(**(covargs or {})) - self.start_import_stop(cov, "main_file") - cov.html_report(**(htmlargs or {})) - - def remove_html_files(self): - """Remove the HTML files created as part of the HTML report.""" - os.remove("htmlcov/index.html") - os.remove("htmlcov/main_file.html") - os.remove("htmlcov/helper1.html") - os.remove("htmlcov/helper2.html") - - -class HtmlDeltaTest(HtmlTestHelpers, CoverageTest): - """Tests of the HTML delta speed-ups.""" - - def setUp(self): - super(HtmlDeltaTest, self).setUp() - - # At least one of our tests monkey-patches the version of coverage, - # so grab it here to restore it later. - self.real_coverage_version = coverage.__version__ - - self.maxDiff = None - - def tearDown(self): - coverage.__version__ = self.real_coverage_version - super(HtmlDeltaTest, self).tearDown() - - def test_html_created(self): - # Test basic HTML generation: files should be created. - self.create_initial_files() - self.run_coverage() - - self.assert_exists("htmlcov/index.html") - self.assert_exists("htmlcov/main_file.html") - self.assert_exists("htmlcov/helper1.html") - self.assert_exists("htmlcov/helper2.html") - self.assert_exists("htmlcov/style.css") - self.assert_exists("htmlcov/coverage_html.js") - - def test_html_delta_from_source_change(self): - # HTML generation can create only the files that have changed. - # In this case, helper1 changes because its source is different. - self.create_initial_files() - self.run_coverage() - index1 = open("htmlcov/index.html").read() - self.remove_html_files() - - # Now change a file and do it again - self.make_file("helper1.py", """\ - def func1(x): # A nice function - if x % 2: - print("odd") - """) - - self.run_coverage() - - # Only the changed files should have been created. - self.assert_exists("htmlcov/index.html") - self.assert_exists("htmlcov/helper1.html") - self.assert_doesnt_exist("htmlcov/main_file.html") - self.assert_doesnt_exist("htmlcov/helper2.html") - index2 = open("htmlcov/index.html").read() - self.assertMultiLineEqual(index1, index2) - - def test_html_delta_from_coverage_change(self): - # HTML generation can create only the files that have changed. - # In this case, helper1 changes because its coverage is different. - self.create_initial_files() - self.run_coverage() - self.remove_html_files() - - # Now change a file and do it again - self.make_file("main_file.py", """\ - import helper1, helper2 - helper1.func1(23) - helper2.func2(23) - """) - - self.run_coverage() - - # Only the changed files should have been created. - self.assert_exists("htmlcov/index.html") - self.assert_exists("htmlcov/helper1.html") - self.assert_exists("htmlcov/main_file.html") - self.assert_doesnt_exist("htmlcov/helper2.html") - - def test_html_delta_from_settings_change(self): - # HTML generation can create only the files that have changed. - # In this case, everything changes because the coverage settings have - # changed. - self.create_initial_files() - self.run_coverage(covargs=dict(omit=[])) - index1 = open("htmlcov/index.html").read() - self.remove_html_files() - - self.run_coverage(covargs=dict(omit=['xyzzy*'])) - - # All the files have been reported again. - self.assert_exists("htmlcov/index.html") - self.assert_exists("htmlcov/helper1.html") - self.assert_exists("htmlcov/main_file.html") - self.assert_exists("htmlcov/helper2.html") - index2 = open("htmlcov/index.html").read() - self.assertMultiLineEqual(index1, index2) - - def test_html_delta_from_coverage_version_change(self): - # HTML generation can create only the files that have changed. - # In this case, everything changes because the coverage version has - # changed. - self.create_initial_files() - self.run_coverage() - index1 = open("htmlcov/index.html").read() - self.remove_html_files() - - # "Upgrade" coverage.py! - coverage.__version__ = "XYZZY" - - self.run_coverage() - - # All the files have been reported again. - self.assert_exists("htmlcov/index.html") - self.assert_exists("htmlcov/helper1.html") - self.assert_exists("htmlcov/main_file.html") - self.assert_exists("htmlcov/helper2.html") - index2 = open("htmlcov/index.html").read() - fixed_index2 = index2.replace("XYZZY", self.real_coverage_version) - self.assertMultiLineEqual(index1, fixed_index2) - - -class HtmlTitleTests(HtmlTestHelpers, CoverageTest): - """Tests of the HTML title support.""" - - def test_default_title(self): - self.create_initial_files() - self.run_coverage() - index = open("htmlcov/index.html").read() - self.assertIn("Coverage report", index) - self.assertIn("

    Coverage report:", index) - - def test_title_set_in_config_file(self): - self.create_initial_files() - self.make_file(".coveragerc", "[html]\ntitle = Metrics & stuff!\n") - self.run_coverage() - index = open("htmlcov/index.html").read() - self.assertIn("Metrics & stuff!", index) - self.assertIn("

    Metrics & stuff!:", index) - - if sys.version_info[:2] != (3,1): - def test_non_ascii_title_set_in_config_file(self): - self.create_initial_files() - self.make_file(".coveragerc", - "[html]\ntitle = «ταБЬℓσ» numbers" - ) - self.run_coverage() - index = open("htmlcov/index.html").read() - self.assertIn( - "«ταБЬℓσ»" - " numbers", index - ) - self.assertIn( - "<h1>«ταБЬℓσ»" - " numbers", index - ) - - def test_title_set_in_args(self): - self.create_initial_files() - self.make_file(".coveragerc", "[html]\ntitle = Good title\n") - self.run_coverage(htmlargs=dict(title="«ταБЬℓσ» & stüff!")) - index = open("htmlcov/index.html").read() - self.assertIn( - "<title>«ταБЬℓσ»" - " & stüff!", index - ) - self.assertIn( - "

    «ταБЬℓσ»" - " & stüff!:", index - ) - - -class HtmlWithUnparsableFilesTest(CoverageTest): - """Test the behavior when measuring unparsable files.""" - - def test_dotpy_not_python(self): - self.make_file("innocuous.py", "a = 1") - cov = coverage.coverage() - self.start_import_stop(cov, "innocuous") - self.make_file("innocuous.py", "

    This isn't python!

    ") - self.assertRaisesRegexp( - NotPython, - "Couldn't parse '.*innocuous.py' as Python source: '.*' at line 1", - cov.html_report - ) - - def test_dotpy_not_python_ignored(self): - self.make_file("innocuous.py", "a = 2") - cov = coverage.coverage() - self.start_import_stop(cov, "innocuous") - self.make_file("innocuous.py", "

    This isn't python!

    ") - cov.html_report(ignore_errors=True) - self.assert_exists("htmlcov/index.html") - # this would be better as a glob, if the html layout changes: - self.assert_doesnt_exist("htmlcov/innocuous.html") - - def test_dothtml_not_python(self): - # We run a .html file, and when reporting, we can't parse it as - # Python. Since it wasn't .py, no error is reported. - - # Run an "html" file - self.make_file("innocuous.html", "a = 3") - self.run_command("coverage run innocuous.html") - # Before reporting, change it to be an HTML file. - self.make_file("innocuous.html", "

    This isn't python at all!

    ") - output = self.run_command("coverage html") - self.assertEqual(output.strip(), "No data to report.") - - def test_execed_liar_ignored(self): - # Jinja2 sets __file__ to be a non-Python file, and then execs code. - # If that file contains non-Python code, a TokenError shouldn't - # have been raised when writing the HTML report. - if sys.version_info < (3, 0): - source = "exec compile('','','exec') in {'__file__': 'liar.html'}" - else: - source = "exec(compile('','','exec'), {'__file__': 'liar.html'})" - self.make_file("liar.py", source) - self.make_file("liar.html", "{# Whoops, not python code #}") - cov = coverage.coverage() - self.start_import_stop(cov, "liar") - cov.html_report() - self.assert_exists("htmlcov/index.html") - - def test_execed_liar_ignored_indentation_error(self): - # Jinja2 sets __file__ to be a non-Python file, and then execs code. - # If that file contains untokenizable code, we shouldn't get an - # exception. - if sys.version_info < (3, 0): - source = "exec compile('','','exec') in {'__file__': 'liar.html'}" - else: - source = "exec(compile('','','exec'), {'__file__': 'liar.html'})" - self.make_file("liar.py", source) - # Tokenize will raise an IndentationError if it can't dedent. - self.make_file("liar.html", "0\n 2\n 1\n") - cov = coverage.coverage() - self.start_import_stop(cov, "liar") - cov.html_report() - self.assert_exists("htmlcov/index.html") - - -class HtmlTest(CoverageTest): - """Moar HTML tests.""" - - def test_missing_source_file_incorrect_message(self): - # https://bitbucket.org/ned/coveragepy/issue/60 - self.make_file("thefile.py", "import sub.another\n") - self.make_file("sub/__init__.py", "") - self.make_file("sub/another.py", "print('another')\n") - cov = coverage.coverage() - self.start_import_stop(cov, 'thefile') - os.remove("sub/another.py") - - missing_file = os.path.join(self.temp_dir, "sub", "another.py") - self.assertRaisesRegexp(NoSource, - "(?i)No source for code: '%s'" % re.escape(missing_file), - cov.html_report - ) diff --git a/test/test_misc.py b/test/test_misc.py deleted file mode 100644 index a32030ca..00000000 --- a/test/test_misc.py +++ /dev/null @@ -1,73 +0,0 @@ -"""Tests of miscellaneous stuff.""" - -from coverage.misc import Hasher, file_be_gone -from coverage import __version__, __url__ -from test.coveragetest import CoverageTest - -class HasherTest(CoverageTest): - """Test our wrapper of md5 hashing.""" - - def test_string_hashing(self): - h1 = Hasher() - h1.update("Hello, world!") - h2 = Hasher() - h2.update("Goodbye!") - h3 = Hasher() - h3.update("Hello, world!") - self.assertNotEqual(h1.digest(), h2.digest()) - self.assertEqual(h1.digest(), h3.digest()) - - def test_dict_hashing(self): - h1 = Hasher() - h1.update({'a': 17, 'b': 23}) - h2 = Hasher() - h2.update({'b': 23, 'a': 17}) - self.assertEqual(h1.digest(), h2.digest()) - - -class RemoveFileTest(CoverageTest): - """Tests of misc.file_be_gone.""" - - def test_remove_nonexistent_file(self): - # it's ok to try to remove a file that doesn't exist. - file_be_gone("not_here.txt") - - def test_remove_actual_file(self): - # it really does remove a file that does exist. - self.make_file("here.txt", "We are here, we are here, we are here!") - file_be_gone("here.txt") - self.assert_doesnt_exist("here.txt") - - def test_actual_errors(self): - # Errors can still happen. - # ". is a directory" on Unix, or "Access denied" on Windows - self.assertRaises(OSError, file_be_gone, ".") - - -class SetupPyTest(CoverageTest): - """Tests of setup.py""" - - run_in_temp_dir = False - - def test_metadata(self): - status, output = self.run_command_status( - "python setup.py --description --version --url --author" - ) - self.assertEqual(status, 0) - out = output.splitlines() - self.assertIn("measurement", out[0]) - self.assertEqual(out[1], __version__) - self.assertEqual(out[2], __url__) - self.assertIn("Ned Batchelder", out[3]) - - def test_more_metadata(self): - from setup import setup_args - - classifiers = setup_args['classifiers'] - self.assertGreater(len(classifiers), 7) - self.assertTrue(classifiers[-1].startswith("Development Status ::")) - - long_description = setup_args['long_description'].splitlines() - self.assertGreater(len(long_description), 7) - self.assertNotEqual(long_description[0].strip(), "") - self.assertNotEqual(long_description[-1].strip(), "") diff --git a/test/test_oddball.py b/test/test_oddball.py deleted file mode 100644 index 113328bb..00000000 --- a/test/test_oddball.py +++ /dev/null @@ -1,386 +0,0 @@ -"""Oddball cases for testing coverage.py""" - -import os, sys -import coverage - -from test.coveragetest import CoverageTest -from test import osinfo - -class ThreadingTest(CoverageTest): - """Tests of the threading support.""" - - def test_threading(self): - self.check_coverage("""\ - import threading - - def fromMainThread(): - return "called from main thread" - - def fromOtherThread(): - return "called from other thread" - - def neverCalled(): - return "no one calls me" - - other = threading.Thread(target=fromOtherThread) - other.start() - fromMainThread() - other.join() - """, - [1,3,4,6,7,9,10,12,13,14,15], "10") - - def test_thread_run(self): - self.check_coverage("""\ - import threading - - class TestThread(threading.Thread): - def run(self): - self.a = 5 - self.do_work() - self.a = 7 - - def do_work(self): - self.a = 10 - - thd = TestThread() - thd.start() - thd.join() - """, - [1,3,4,5,6,7,9,10,12,13,14], "") - - -class RecursionTest(CoverageTest): - """Check what happens when recursive code gets near limits.""" - - def test_short_recursion(self): - # We can definitely get close to 500 stack frames. - self.check_coverage("""\ - def recur(n): - if n == 0: - return 0 - else: - return recur(n-1)+1 - - recur(495) # We can get at least this many stack frames. - i = 8 # and this line will be traced - """, - [1,2,3,5,7,8], "") - - def test_long_recursion(self): - # We can't finish a very deep recursion, but we don't crash. - self.assertRaises(RuntimeError, self.check_coverage, - """\ - def recur(n): - if n == 0: - return 0 - else: - return recur(n-1)+1 - - recur(100000) # This is definitely too many frames. - """, - [1,2,3,5,7], "") - - def test_long_recursion_recovery(self): - # Test the core of bug 93: http://bitbucket.org/ned/coveragepy/issue/93 - # When recovering from a stack overflow, the Python trace function is - # disabled, but the C trace function is not. So if we're using a - # Python trace function, we won't trace anything after the stack - # overflow, and there should be a warning about it. If we're using - # the C trace function, only line 3 will be missing, and all else - # will be traced. - - self.make_file("recur.py", """\ - def recur(n): - if n == 0: - return 0 # never hit - else: - return recur(n-1)+1 - - try: - recur(100000) # This is definitely too many frames. - except RuntimeError: - i = 10 - i = 11 - """) - - cov = coverage.coverage() - self.start_import_stop(cov, "recur") - - pytrace = (cov.collector.tracer_name() == "PyTracer") - expected_missing = [3] - if pytrace: - expected_missing += [9,10,11] - - _, statements, missing, _ = cov.analysis("recur.py") - self.assertEqual(statements, [1,2,3,5,7,8,9,10,11]) - self.assertEqual(missing, expected_missing) - - # We can get a warning about the stackoverflow effect on the tracing - # function only if we have sys.gettrace - if pytrace and hasattr(sys, "gettrace"): - self.assertEqual(cov._warnings, - ["Trace function changed, measurement is likely wrong: None"] - ) - else: - self.assertEqual(cov._warnings, []) - - -class MemoryLeakTest(CoverageTest): - """Attempt the impossible: test that memory doesn't leak. - - Note: this test is truly unusual, and may fail unexpectedly. - In particular, it is known to fail on PyPy if test_oddball.py is run in - isolation: https://bitbucket.org/ned/coveragepy/issue/186 - - """ - - def test_for_leaks(self): - lines = list(range(301, 315)) - lines.remove(306) - # Ugly string mumbo jumbo to get 300 blank lines at the beginning.. - code = """\ - # blank line\n""" * 300 + """\ - def once(x): - if x % 100 == 0: - raise Exception("100!") - elif x % 2: - return 10 - else: - return 11 - i = 0 # Portable loop without alloc'ing memory. - while i < ITERS: - try: - once(i) - except: - pass - i += 1 - """ - ram_0 = osinfo.process_ram() - self.check_coverage(code.replace("ITERS", "10"), lines, "") - ram_1 = osinfo.process_ram() - self.check_coverage(code.replace("ITERS", "10000"), lines, "") - ram_2 = osinfo.process_ram() - ram_growth = (ram_2 - ram_1) - (ram_1 - ram_0) - self.assertTrue(ram_growth < 100000, "RAM grew by %d" % (ram_growth)) - - -class PyexpatTest(CoverageTest): - """Pyexpat screws up tracing. Make sure we've counter-defended properly.""" - - def test_pyexpat(self): - # pyexpat calls the trace function explicitly (inexplicably), and does - # it wrong for exceptions. Parsing a DOCTYPE for some reason throws - # an exception internally, and triggers its wrong behavior. This test - # checks that our fake PyTrace_RETURN hack in tracer.c works. It will - # also detect if the pyexpat bug is fixed unbeknownst to us, meaning - # we'd see two RETURNs where there should only be one. - - self.make_file("trydom.py", """\ - import xml.dom.minidom - - XML = '''\\ - - - ''' - - def foo(): - dom = xml.dom.minidom.parseString(XML) - assert len(dom.getElementsByTagName('child')) == 2 - a = 11 - - foo() - """) - - self.make_file("outer.py", "\n"*100 + "import trydom\na = 102\n") - - cov = coverage.coverage() - cov.erase() - - # Import the python file, executing it. - self.start_import_stop(cov, "outer") - - _, statements, missing, _ = cov.analysis("trydom.py") - self.assertEqual(statements, [1,3,8,9,10,11,13]) - self.assertEqual(missing, []) - - _, statements, missing, _ = cov.analysis("outer.py") - self.assertEqual(statements, [101,102]) - self.assertEqual(missing, []) - - -class ExceptionTest(CoverageTest): - """I suspect different versions of Python deal with exceptions differently - in the trace function. - """ - - def test_exception(self): - # Python 2.3's trace function doesn't get called with "return" if the - # scope is exiting due to an exception. This confounds our trace - # function which relies on scope announcements to track which files to - # trace. - # - # This test is designed to sniff this out. Each function in the call - # stack is in a different file, to try to trip up the tracer. Each - # file has active lines in a different range so we'll see if the lines - # get attributed to the wrong file. - - self.make_file("oops.py", """\ - def oops(args): - a = 2 - raise Exception("oops") - a = 4 - """) - - self.make_file("fly.py", "\n"*100 + """\ - def fly(calls): - a = 2 - calls[0](calls[1:]) - a = 4 - """) - - self.make_file("catch.py", "\n"*200 + """\ - def catch(calls): - try: - a = 3 - calls[0](calls[1:]) - a = 5 - except: - a = 7 - """) - - self.make_file("doit.py", "\n"*300 + """\ - def doit(calls): - try: - calls[0](calls[1:]) - except: - a = 5 - """) - - # Import all the modules before starting coverage, so the def lines - # won't be in all the results. - for mod in "oops fly catch doit".split(): - self.import_local_file(mod) - - # Each run nests the functions differently to get different - # combinations of catching exceptions and letting them fly. - runs = [ - ("doit fly oops", { - 'doit.py': [302,303,304,305], - 'fly.py': [102,103], - 'oops.py': [2,3], - }), - ("doit catch oops", { - 'doit.py': [302,303], - 'catch.py': [202,203,204,206,207], - 'oops.py': [2,3], - }), - ("doit fly catch oops", { - 'doit.py': [302,303], - 'fly.py': [102,103,104], - 'catch.py': [202,203,204,206,207], - 'oops.py': [2,3], - }), - ("doit catch fly oops", { - 'doit.py': [302,303], - 'catch.py': [202,203,204,206,207], - 'fly.py': [102,103], - 'oops.py': [2,3], - }), - ] - - for callnames, lines_expected in runs: - - # Make the list of functions we'll call for this test. - calls = [getattr(sys.modules[cn], cn) for cn in callnames.split()] - - cov = coverage.coverage() - cov.start() - # Call our list of functions: invoke the first, with the rest as - # an argument. - calls[0](calls[1:]) # pragma: nested - cov.stop() # pragma: nested - - # Clean the line data and compare to expected results. - # The filenames are absolute, so keep just the base. - cov._harvest_data() # private! sshhh... - lines = cov.data.line_data() - clean_lines = {} - for f, llist in lines.items(): - if f == __file__: - # ignore this file. - continue - clean_lines[os.path.basename(f)] = llist - self.assertEqual(clean_lines, lines_expected) - - -if sys.version_info >= (2, 5): - class DoctestTest(CoverageTest): - """Tests invoked with doctest should measure properly.""" - - def setUp(self): - super(DoctestTest, self).setUp() - - # Oh, the irony! This test case exists because Python 2.4's - # doctest module doesn't play well with coverage. But nose fixes - # the problem by monkeypatching doctest. I want to undo the - # monkeypatch to be sure I'm getting the doctest module that users - # of coverage will get. Deleting the imported module here is - # enough: when the test imports doctest again, it will get a fresh - # copy without the monkeypatch. - del sys.modules['doctest'] - - def test_doctest(self): - self.check_coverage('''\ - def return_arg_or_void(arg): - """If is None, return "Void"; otherwise return - - >>> return_arg_or_void(None) - 'Void' - >>> return_arg_or_void("arg") - 'arg' - >>> return_arg_or_void("None") - 'None' - """ - if arg is None: - return "Void" - else: - return arg - - import doctest, sys - doctest.testmod(sys.modules[__name__]) # we're not __main__ :( - ''', - [1,11,12,14,16,17], "") - - -if hasattr(sys, 'gettrace'): - class GettraceTest(CoverageTest): - """Tests that we work properly with `sys.gettrace()`.""" - def test_round_trip(self): - self.check_coverage('''\ - import sys - def foo(n): - return 3*n - def bar(n): - return 5*n - a = foo(6) - sys.settrace(sys.gettrace()) - a = bar(8) - ''', - [1,2,3,4,5,6,7,8], "") - - def test_multi_layers(self): - self.check_coverage('''\ - import sys - def level1(): - a = 3 - level2() - b = 5 - def level2(): - c = 7 - sys.settrace(sys.gettrace()) - d = 9 - e = 10 - level1() - f = 12 - ''', - [1,2,3,4,5,6,7,8,9,10,11,12], "") diff --git a/test/test_parser.py b/test/test_parser.py deleted file mode 100644 index 6ccef206..00000000 --- a/test/test_parser.py +++ /dev/null @@ -1,131 +0,0 @@ -"""Tests for Coverage.py's code parsing.""" - -import textwrap -from test.coveragetest import CoverageTest -from coverage.parser import CodeParser - - -class ParserTest(CoverageTest): - """Tests for Coverage.py's code parsing.""" - - run_in_temp_dir = False - - def parse_source(self, text): - """Parse `text` as source, and return the `CodeParser` used.""" - text = textwrap.dedent(text) - cp = CodeParser(text=text, exclude="nocover") - cp.parse_source() - return cp - - def test_exit_counts(self): - cp = self.parse_source("""\ - # check some basic branch counting - class Foo: - def foo(self, a): - if a: - return 5 - else: - return 7 - - class Bar: - pass - """) - self.assertEqual(cp.exit_counts(), { - 2:1, 3:1, 4:2, 5:1, 7:1, 9:1, 10:1 - }) - - def test_try_except(self): - cp = self.parse_source("""\ - try: - a = 2 - except ValueError: - a = 4 - except ZeroDivideError: - a = 6 - except: - a = 8 - b = 9 - """) - self.assertEqual(cp.exit_counts(), { - 1: 1, 2:1, 3:1, 4:1, 5:1, 6:1, 7:1, 8:1, 9:1 - }) - - def test_excluded_classes(self): - cp = self.parse_source("""\ - class Foo: - def __init__(self): - pass - - if 0: # nocover - class Bar: - pass - """) - self.assertEqual(cp.exit_counts(), { - 1:0, 2:1, 3:1 - }) - - def test_missing_branch_to_excluded_code(self): - cp = self.parse_source("""\ - if fooey: - a = 2 - else: # nocover - a = 4 - b = 5 - """) - self.assertEqual(cp.exit_counts(), { 1:1, 2:1, 5:1 }) - cp = self.parse_source("""\ - def foo(): - if fooey: - a = 3 - else: - a = 5 - b = 6 - """) - self.assertEqual(cp.exit_counts(), { 1:1, 2:2, 3:1, 5:1, 6:1 }) - cp = self.parse_source("""\ - def foo(): - if fooey: - a = 3 - else: # nocover - a = 5 - b = 6 - """) - self.assertEqual(cp.exit_counts(), { 1:1, 2:1, 3:1, 6:1 }) - - -class ParserFileTest(CoverageTest): - """Tests for Coverage.py's code parsing from files.""" - - def parse_file(self, filename): - """Parse `text` as source, and return the `CodeParser` used.""" - cp = CodeParser(filename=filename, exclude="nocover") - cp.parse_source() - return cp - - def test_line_endings(self): - text = """\ - # check some basic branch counting - class Foo: - def foo(self, a): - if a: - return 5 - else: - return 7 - - class Bar: - pass - """ - counts = { 2:1, 3:1, 4:2, 5:1, 7:1, 9:1, 10:1 } - name_endings = (("unix", "\n"), ("dos", "\r\n"), ("mac", "\r")) - for fname, newline in name_endings: - fname = fname + ".py" - self.make_file(fname, text, newline=newline) - cp = self.parse_file(fname) - self.assertEqual(cp.exit_counts(), counts) - - def test_encoding(self): - self.make_file("encoded.py", """\ - coverage = "\xe7\xf6v\xear\xe3g\xe9" - """) - cp = self.parse_file("encoded.py") - cp.exit_counts() diff --git a/test/test_phystokens.py b/test/test_phystokens.py deleted file mode 100644 index e4834e4c..00000000 --- a/test/test_phystokens.py +++ /dev/null @@ -1,79 +0,0 @@ -"""Tests for Coverage.py's improved tokenizer.""" - -import os, re -from test.coveragetest import CoverageTest -from coverage.phystokens import source_token_lines - - -SIMPLE = """\ -# yay! -def foo(): - say('two = %d' % 2) -""" - -MIXED_WS = """\ -def hello(): - a="Hello world!" -\tb="indented" -""" - -HERE = os.path.split(__file__)[0] - - -class PhysTokensTest(CoverageTest): - """Tests for Coverage.py's improver tokenizer.""" - - run_in_temp_dir = False - - def check_tokenization(self, source): - """Tokenize `source`, then put it back together, should be the same.""" - tokenized = "" - for line in source_token_lines(source): - text = "".join([t for _,t in line]) - tokenized += text + "\n" - # source_token_lines doesn't preserve trailing spaces, so trim all that - # before comparing. - source = source.replace('\r\n', '\n') - source = re.sub(r"(?m)[ \t]+$", "", source) - tokenized = re.sub(r"(?m)[ \t]+$", "", tokenized) - self.assertMultiLineEqual(source, tokenized) - - def check_file_tokenization(self, fname): - """Use the contents of `fname` for `check_tokenization`.""" - self.check_tokenization(open(fname).read()) - - def test_simple(self): - self.assertEqual(list(source_token_lines(SIMPLE)), - [ - [('com', "# yay!")], - [('key', 'def'), ('ws', ' '), ('nam', 'foo'), ('op', '('), - ('op', ')'), ('op', ':')], - [('ws', ' '), ('nam', 'say'), ('op', '('), - ('str', "'two = %d'"), ('ws', ' '), ('op', '%'), - ('ws', ' '), ('num', '2'), ('op', ')')] - ]) - self.check_tokenization(SIMPLE) - - def test_tab_indentation(self): - # Mixed tabs and spaces... - self.assertEqual(list(source_token_lines(MIXED_WS)), - [ - [('key', 'def'), ('ws', ' '), ('nam', 'hello'), ('op', '('), - ('op', ')'), ('op', ':')], - [('ws', ' '), ('nam', 'a'), ('op', '='), - ('str', '"Hello world!"')], - [('ws', ' '), ('nam', 'b'), ('op', '='), - ('str', '"indented"')], - ]) - - def test_tokenize_real_file(self): - # Check the tokenization of a real file (large, btw). - real_file = os.path.join(HERE, "test_coverage.py") - self.check_file_tokenization(real_file) - - def test_stress(self): - # Check the tokenization of a stress-test file. - stress = os.path.join(HERE, "stress_phystoken.tok") - self.check_file_tokenization(stress) - stress = os.path.join(HERE, "stress_phystoken_dos.tok") - self.check_file_tokenization(stress) diff --git a/test/test_process.py b/test/test_process.py deleted file mode 100644 index bf22cc9d..00000000 --- a/test/test_process.py +++ /dev/null @@ -1,575 +0,0 @@ -"""Tests for process behavior of coverage.py.""" - -import glob, os, sys, textwrap -from nose.plugins.skip import SkipTest -import coverage - -from test.coveragetest import CoverageTest - -here = os.path.dirname(__file__) - -class ProcessTest(CoverageTest): - """Tests of the per-process behavior of coverage.py.""" - - def number_of_data_files(self): - """Return the number of coverage data files in this directory.""" - num = 0 - for f in os.listdir('.'): - if f.startswith('.coverage.') or f == '.coverage': - num += 1 - return num - - def test_save_on_exit(self): - self.make_file("mycode.py", """\ - h = "Hello" - w = "world" - """) - - self.assert_doesnt_exist(".coverage") - self.run_command("coverage -x mycode.py") - self.assert_exists(".coverage") - - def test_environment(self): - # Checks that we can import modules from the test directory at all! - self.make_file("mycode.py", """\ - import covmod1 - import covmodzip1 - a = 1 - print ('done') - """) - - self.assert_doesnt_exist(".coverage") - out = self.run_command("coverage -x mycode.py") - self.assert_exists(".coverage") - self.assertEqual(out, 'done\n') - - def test_combine_parallel_data(self): - self.make_file("b_or_c.py", """\ - import sys - a = 1 - if sys.argv[1] == 'b': - b = 1 - else: - c = 1 - d = 1 - print ('done') - """) - - out = self.run_command("coverage -x -p b_or_c.py b") - self.assertEqual(out, 'done\n') - self.assert_doesnt_exist(".coverage") - - out = self.run_command("coverage -x -p b_or_c.py c") - self.assertEqual(out, 'done\n') - self.assert_doesnt_exist(".coverage") - - # After two -p runs, there should be two .coverage.machine.123 files. - self.assertEqual(self.number_of_data_files(), 2) - - # Combine the parallel coverage data files into .coverage . - self.run_command("coverage -c") - self.assert_exists(".coverage") - - # After combining, there should be only the .coverage file. - self.assertEqual(self.number_of_data_files(), 1) - - # Read the coverage file and see that b_or_c.py has all 7 lines - # executed. - data = coverage.CoverageData() - data.read_file(".coverage") - self.assertEqual(data.summary()['b_or_c.py'], 7) - - def test_combine_parallel_data_in_two_steps(self): - self.make_file("b_or_c.py", """\ - import sys - a = 1 - if sys.argv[1] == 'b': - b = 1 - else: - c = 1 - d = 1 - print ('done') - """) - - out = self.run_command("coverage -x -p b_or_c.py b") - self.assertEqual(out, 'done\n') - self.assert_doesnt_exist(".coverage") - self.assertEqual(self.number_of_data_files(), 1) - - # Combine the (one) parallel coverage data file into .coverage . - self.run_command("coverage -c") - self.assert_exists(".coverage") - self.assertEqual(self.number_of_data_files(), 1) - - out = self.run_command("coverage -x -p b_or_c.py c") - self.assertEqual(out, 'done\n') - self.assert_exists(".coverage") - self.assertEqual(self.number_of_data_files(), 2) - - # Combine the parallel coverage data files into .coverage . - self.run_command("coverage -c") - self.assert_exists(".coverage") - - # After combining, there should be only the .coverage file. - self.assertEqual(self.number_of_data_files(), 1) - - # Read the coverage file and see that b_or_c.py has all 7 lines - # executed. - data = coverage.CoverageData() - data.read_file(".coverage") - self.assertEqual(data.summary()['b_or_c.py'], 7) - - def test_combine_with_rc(self): - self.make_file("b_or_c.py", """\ - import sys - a = 1 - if sys.argv[1] == 'b': - b = 1 - else: - c = 1 - d = 1 - print ('done') - """) - - self.make_file(".coveragerc", """\ - [run] - parallel = true - """) - - out = self.run_command("coverage run b_or_c.py b") - self.assertEqual(out, 'done\n') - self.assert_doesnt_exist(".coverage") - - out = self.run_command("coverage run b_or_c.py c") - self.assertEqual(out, 'done\n') - self.assert_doesnt_exist(".coverage") - - # After two runs, there should be two .coverage.machine.123 files. - self.assertEqual(self.number_of_data_files(), 2) - - # Combine the parallel coverage data files into .coverage . - self.run_command("coverage combine") - self.assert_exists(".coverage") - self.assert_exists(".coveragerc") - - # After combining, there should be only the .coverage file. - self.assertEqual(self.number_of_data_files(), 1) - - # Read the coverage file and see that b_or_c.py has all 7 lines - # executed. - data = coverage.CoverageData() - data.read_file(".coverage") - self.assertEqual(data.summary()['b_or_c.py'], 7) - - # Reporting should still work even with the .rc file - out = self.run_command("coverage report") - self.assertMultiLineEqual(out, textwrap.dedent("""\ - Name Stmts Miss Cover - ---------------------------- - b_or_c 7 0 100% - """)) - - def test_combine_with_aliases(self): - self.make_file("d1/x.py", """\ - a = 1 - b = 2 - print("%s %s" % (a, b)) - """) - - self.make_file("d2/x.py", """\ - # 1 - # 2 - # 3 - c = 4 - d = 5 - print("%s %s" % (c, d)) - """) - - self.make_file(".coveragerc", """\ - [run] - parallel = True - - [paths] - source = - src - */d1 - */d2 - """) - - out = self.run_command("coverage run " + os.path.normpath("d1/x.py")) - self.assertEqual(out, '1 2\n') - out = self.run_command("coverage run " + os.path.normpath("d2/x.py")) - self.assertEqual(out, '4 5\n') - - self.assertEqual(self.number_of_data_files(), 2) - - self.run_command("coverage combine") - self.assert_exists(".coverage") - - # After combining, there should be only the .coverage file. - self.assertEqual(self.number_of_data_files(), 1) - - # Read the coverage data file and see that the two different x.py - # files have been combined together. - data = coverage.CoverageData() - data.read_file(".coverage") - summary = data.summary(fullpath=True) - self.assertEqual(len(summary), 1) - actual = os.path.normcase(os.path.abspath(list(summary.keys())[0])) - expected = os.path.normcase(os.path.abspath('src/x.py')) - self.assertEqual(actual, expected) - self.assertEqual(list(summary.values())[0], 6) - - def test_missing_source_file(self): - # Check what happens if the source is missing when reporting happens. - self.make_file("fleeting.py", """\ - s = 'goodbye, cruel world!' - """) - - self.run_command("coverage run fleeting.py") - os.remove("fleeting.py") - out = self.run_command("coverage html -d htmlcov") - self.assertRegexpMatches(out, "No source for code: '.*fleeting.py'") - self.assertNotIn("Traceback", out) - - # It happens that the code paths are different for *.py and other - # files, so try again with no extension. - self.make_file("fleeting", """\ - s = 'goodbye, cruel world!' - """) - - self.run_command("coverage run fleeting") - os.remove("fleeting") - status, out = self.run_command_status("coverage html -d htmlcov", 1) - self.assertRegexpMatches(out, "No source for code: '.*fleeting'") - self.assertNotIn("Traceback", out) - self.assertEqual(status, 1) - - def test_running_missing_file(self): - status, out = self.run_command_status("coverage run xyzzy.py", 1) - self.assertRegexpMatches(out, "No file to run: .*xyzzy.py") - self.assertNotIn("raceback", out) - self.assertNotIn("rror", out) - self.assertEqual(status, 1) - - def test_code_throws(self): - self.make_file("throw.py", """\ - def f1(): - raise Exception("hey!") - - def f2(): - f1() - - f2() - """) - - # The important thing is for "coverage run" and "python" to report the - # same traceback. - status, out = self.run_command_status("coverage run throw.py", 1) - out2 = self.run_command("python throw.py") - if '__pypy__' in sys.builtin_module_names: - # Pypy has an extra frame in the traceback for some reason - lines2 = out2.splitlines() - out2 = "".join([l+"\n" for l in lines2 if "toplevel" not in l]) - self.assertMultiLineEqual(out, out2) - - # But also make sure that the output is what we expect. - self.assertIn('File "throw.py", line 5, in f2', out) - self.assertIn('raise Exception("hey!")', out) - self.assertNotIn('coverage', out) - self.assertEqual(status, 1) - - def test_code_exits(self): - self.make_file("exit.py", """\ - import sys - def f1(): - print("about to exit..") - sys.exit(17) - - def f2(): - f1() - - f2() - """) - - # The important thing is for "coverage run" and "python" to have the - # same output. No traceback. - status, out = self.run_command_status("coverage run exit.py", 17) - status2, out2 = self.run_command_status("python exit.py", 17) - self.assertMultiLineEqual(out, out2) - self.assertMultiLineEqual(out, "about to exit..\n") - self.assertEqual(status, status2) - self.assertEqual(status, 17) - - def test_code_exits_no_arg(self): - self.make_file("exit_none.py", """\ - import sys - def f1(): - print("about to exit quietly..") - sys.exit() - - f1() - """) - status, out = self.run_command_status("coverage run exit_none.py", 0) - status2, out2 = self.run_command_status("python exit_none.py", 0) - self.assertMultiLineEqual(out, out2) - self.assertMultiLineEqual(out, "about to exit quietly..\n") - self.assertEqual(status, status2) - self.assertEqual(status, 0) - - def test_coverage_run_is_like_python(self): - tryfile = os.path.join(here, "try_execfile.py") - self.make_file("run_me.py", open(tryfile).read()) - out = self.run_command("coverage run run_me.py") - out2 = self.run_command("python run_me.py") - self.assertMultiLineEqual(out, out2) - - if sys.version_info >= (2, 6): # Doesn't work in 2.5, and I don't care! - def test_coverage_run_dashm_is_like_python_dashm(self): - # These -m commands assume the coverage tree is on the path. - out = self.run_command("coverage run -m test.try_execfile") - out2 = self.run_command("python -m test.try_execfile") - self.assertMultiLineEqual(out, out2) - - if 0: # Expected failure - # For https://bitbucket.org/ned/coveragepy/issue/207 - def test_coverage_run_dashm_is_like_python_dashm_with__main__207(self): - self.make_file("package/__init__.py") # empty - self.make_file("package/__main__.py", "#\n") # empty - out = self.run_command("coverage run -m package") - out2 = self.run_command("python -m package") - self.assertMultiLineEqual(out, out2) - - if hasattr(os, 'fork'): - def test_fork(self): - self.make_file("fork.py", """\ - import os - - def child(): - print('Child!') - - def main(): - ret = os.fork() - - if ret == 0: - child() - else: - os.waitpid(ret, 0) - - main() - """) - - out = self.run_command("coverage run -p fork.py") - self.assertEqual(out, 'Child!\n') - self.assert_doesnt_exist(".coverage") - - # After running the forking program, there should be two - # .coverage.machine.123 files. - self.assertEqual(self.number_of_data_files(), 2) - - # Combine the parallel coverage data files into .coverage . - self.run_command("coverage -c") - self.assert_exists(".coverage") - - # After combining, there should be only the .coverage file. - self.assertEqual(self.number_of_data_files(), 1) - - # Read the coverage file and see that b_or_c.py has all 7 lines - # executed. - data = coverage.CoverageData() - data.read_file(".coverage") - self.assertEqual(data.summary()['fork.py'], 9) - - def test_warnings(self): - self.make_file("hello.py", """\ - import sys, os - print("Hello") - """) - out = self.run_command("coverage run --source=sys,xyzzy,quux hello.py") - - self.assertIn("Hello\n", out) - self.assertIn(textwrap.dedent("""\ - Coverage.py warning: Module sys has no Python source. - Coverage.py warning: Module xyzzy was never imported. - Coverage.py warning: Module quux was never imported. - Coverage.py warning: No data was collected. - """), out) - - def test_warnings_during_reporting(self): - # While fixing issue #224, the warnings were being printed far too - # often. Make sure they're not any more. - self.make_file("hello.py", """\ - import sys, os, the_other - print("Hello") - """) - self.make_file("the_other.py", """\ - print("What?") - """) - self.make_file(".coveragerc", """\ - [run] - source = - . - xyzzy - """) - - self.run_command("coverage run hello.py") - out = self.run_command("coverage html") - self.assertEqual(out.count("Module xyzzy was never imported."), 0) - - def test_warnings_if_never_run(self): - out = self.run_command("coverage run i_dont_exist.py") - self.assertIn("No file to run: 'i_dont_exist.py'", out) - self.assertNotIn("warning", out) - self.assertNotIn("Exception", out) - - out = self.run_command("coverage run -m no_such_module") - self.assertTrue( - ("No module named no_such_module" in out) or - ("No module named 'no_such_module'" in out) - ) - self.assertNotIn("warning", out) - self.assertNotIn("Exception", out) - - if sys.version_info >= (3, 0): # This only works on 3.x for now. - # It only works with the C tracer, - c_tracer = os.getenv('COVERAGE_TEST_TRACER', 'c') == 'c' - # and if we aren't measuring ourselves. - metacov = os.getenv('COVERAGE_COVERAGE', '') != '' - if c_tracer and not metacov: # pragma: not covered - def test_fullcoverage(self): - # fullcoverage is a trick to get stdlib modules measured from - # the very beginning of the process. Here we import os and - # then check how many lines are measured. - self.make_file("getenv.py", """\ - import os - print("FOOEY == %s" % os.getenv("FOOEY")) - """) - - fullcov = os.path.join( - os.path.dirname(coverage.__file__), "fullcoverage" - ) - self.set_environ("FOOEY", "BOO") - self.set_environ("PYTHONPATH", fullcov) - out = self.run_command("python -m coverage run -L getenv.py") - self.assertEqual(out, "FOOEY == BOO\n") - data = coverage.CoverageData() - data.read_file(".coverage") - # The actual number of executed lines in os.py when it's - # imported is 120 or so. Just running os.getenv executes - # about 5. - self.assertGreater(data.summary()['os.py'], 50) - - -class AliasedCommandTests(CoverageTest): - """Tests of the version-specific command aliases.""" - - def test_major_version_works(self): - # "coverage2" works on py2 - cmd = "coverage%d" % sys.version_info[0] - out = self.run_command(cmd) - self.assertIn("Code coverage for Python", out) - - def test_wrong_alias_doesnt_work(self): - # "coverage3" doesn't work on py2 - badcmd = "coverage%d" % (5 - sys.version_info[0]) - out = self.run_command(badcmd) - self.assertNotIn("Code coverage for Python", out) - - def test_specific_alias_works(self): - # "coverage-2.7" works on py2.7 - cmd = "coverage-%d.%d" % sys.version_info[:2] - out = self.run_command(cmd) - self.assertIn("Code coverage for Python", out) - - -class FailUnderTest(CoverageTest): - """Tests of the --fail-under switch.""" - - def setUp(self): - super(FailUnderTest, self).setUp() - self.make_file("fifty.py", """\ - # I have 50% coverage! - a = 1 - if a > 2: - b = 3 - c = 4 - """) - st, _ = self.run_command_status("coverage run fifty.py", 0) - self.assertEqual(st, 0) - - def test_report(self): - st, _ = self.run_command_status("coverage report --fail-under=50", 0) - self.assertEqual(st, 0) - st, _ = self.run_command_status("coverage report --fail-under=51", 2) - self.assertEqual(st, 2) - - def test_html_report(self): - st, _ = self.run_command_status("coverage html --fail-under=50", 0) - self.assertEqual(st, 0) - st, _ = self.run_command_status("coverage html --fail-under=51", 2) - self.assertEqual(st, 2) - - def test_xml_report(self): - st, _ = self.run_command_status("coverage xml --fail-under=50", 0) - self.assertEqual(st, 0) - st, _ = self.run_command_status("coverage xml --fail-under=51", 2) - self.assertEqual(st, 2) - - -class ProcessStartupTest(CoverageTest): - """Test that we can measure coverage in subprocesses.""" - - def setUp(self): - super(ProcessStartupTest, self).setUp() - # Find a place to put a .pth file. - pth_contents = "import coverage; coverage.process_startup()\n" - for d in sys.path: # pragma: part covered - g = glob.glob(os.path.join(d, "*.pth")) - if g: - pth_path = os.path.join(d, "subcover.pth") - pth = open(pth_path, "w") - try: - try: - pth.write(pth_contents) - self.pth_path = pth_path - break - except (IOError, OSError): # pragma: not covered - pass - finally: - pth.close() - else: # pragma: not covered - raise Exception("Couldn't find a place for the .pth file") - - def tearDown(self): - super(ProcessStartupTest, self).tearDown() - # Clean up the .pth file we made. - os.remove(self.pth_path) - - def test_subprocess_with_pth_files(self): # pragma: not covered - if os.environ.get('COVERAGE_COVERAGE', ''): - raise SkipTest( - "Can't test subprocess pth file suppport during metacoverage" - ) - # Main will run sub.py - self.make_file("main.py", """\ - import os - os.system("python sub.py") - """) - # sub.py will write a few lines. - self.make_file("sub.py", """\ - f = open("out.txt", "w") - f.write("Hello, world!\\n") - f.close() - """) - self.make_file("coverage.ini", """\ - [run] - data_file = .mycovdata - """) - self.set_environ("COVERAGE_PROCESS_START", "coverage.ini") - import main # pylint: disable=F0401,W0612 - - self.assertEqual(open("out.txt").read(), "Hello, world!\n") - # Read the data from .coverage - data = coverage.CoverageData() - data.read_file(".mycovdata") - self.assertEqual(data.summary()['sub.py'], 3) diff --git a/test/test_results.py b/test/test_results.py deleted file mode 100644 index 3caa5a66..00000000 --- a/test/test_results.py +++ /dev/null @@ -1,60 +0,0 @@ -"""Tests for Coverage.py's results analysis.""" - -from coverage.results import Numbers -from test.coveragetest import CoverageTest - - -class NumbersTest(CoverageTest): - """Tests for Coverage.py's numeric measurement summaries.""" - - run_in_temp_dir = False - - def test_basic(self): - n1 = Numbers(n_files=1, n_statements=200, n_missing=20) - self.assertEqual(n1.n_statements, 200) - self.assertEqual(n1.n_executed, 180) - self.assertEqual(n1.n_missing, 20) - self.assertEqual(n1.pc_covered, 90) - - def test_addition(self): - n1 = Numbers(n_files=1, n_statements=200, n_missing=20) - n2 = Numbers(n_files=1, n_statements=10, n_missing=8) - n3 = n1 + n2 - self.assertEqual(n3.n_files, 2) - self.assertEqual(n3.n_statements, 210) - self.assertEqual(n3.n_executed, 182) - self.assertEqual(n3.n_missing, 28) - self.assertAlmostEqual(n3.pc_covered, 86.666666666) - - def test_sum(self): - n1 = Numbers(n_files=1, n_statements=200, n_missing=20) - n2 = Numbers(n_files=1, n_statements=10, n_missing=8) - n3 = sum([n1, n2]) - self.assertEqual(n3.n_files, 2) - self.assertEqual(n3.n_statements, 210) - self.assertEqual(n3.n_executed, 182) - self.assertEqual(n3.n_missing, 28) - self.assertAlmostEqual(n3.pc_covered, 86.666666666) - - def test_pc_covered_str(self): - n0 = Numbers(n_files=1, n_statements=1000, n_missing=0) - n1 = Numbers(n_files=1, n_statements=1000, n_missing=1) - n999 = Numbers(n_files=1, n_statements=1000, n_missing=999) - n1000 = Numbers(n_files=1, n_statements=1000, n_missing=1000) - self.assertEqual(n0.pc_covered_str, "100") - self.assertEqual(n1.pc_covered_str, "99") - self.assertEqual(n999.pc_covered_str, "1") - self.assertEqual(n1000.pc_covered_str, "0") - - def test_pc_covered_str_precision(self): - assert Numbers._precision == 0 - Numbers.set_precision(1) - n0 = Numbers(n_files=1, n_statements=10000, n_missing=0) - n1 = Numbers(n_files=1, n_statements=10000, n_missing=1) - n9999 = Numbers(n_files=1, n_statements=10000, n_missing=9999) - n10000 = Numbers(n_files=1, n_statements=10000, n_missing=10000) - self.assertEqual(n0.pc_covered_str, "100.0") - self.assertEqual(n1.pc_covered_str, "99.9") - self.assertEqual(n9999.pc_covered_str, "0.1") - self.assertEqual(n10000.pc_covered_str, "0.0") - Numbers.set_precision(0) diff --git a/test/test_summary.py b/test/test_summary.py deleted file mode 100644 index 5bb903a6..00000000 --- a/test/test_summary.py +++ /dev/null @@ -1,298 +0,0 @@ -"""Test text-based summary reporting for coverage.py""" - -import os, re, sys - -import coverage -from coverage.backward import StringIO - -from test.coveragetest import CoverageTest - -class SummaryTest(CoverageTest): - """Tests of the text summary reporting for coverage.py.""" - - def setUp(self): - super(SummaryTest, self).setUp() - self.make_file("mycode.py", """\ - import covmod1 - import covmodzip1 - a = 1 - print ('done') - """) - # Parent class saves and restores sys.path, we can just modify it. - sys.path.append(self.nice_file(os.path.dirname(__file__), 'modules')) - - def report_from_command(self, cmd): - """Return the report from the `cmd`, with some convenience added.""" - report = self.run_command(cmd).replace('\\', '/') - self.assertNotIn("error", report.lower()) - return report - - def line_count(self, report): - """How many lines are in `report`?""" - self.assertEqual(report.split('\n')[-1], "") - return len(report.split('\n')) - 1 - - def last_line_squeezed(self, report): - """Return the last line of `report` with the spaces squeezed down.""" - last_line = report.split('\n')[-2] - return re.sub(r"\s+", " ", last_line) - - def test_report(self): - out = self.run_command("coverage -x mycode.py") - self.assertEqual(out, 'done\n') - report = self.report_from_command("coverage -r") - - # Name Stmts Miss Cover - # --------------------------------------------------------------------- - # c:/ned/coverage/trunk/test/modules/covmod1 2 0 100% - # c:/ned/coverage/trunk/test/zipmods.zip/covmodzip1 2 0 100% - # mycode 4 0 100% - # --------------------------------------------------------------------- - # TOTAL 8 0 100% - - self.assertNotIn("/coverage/__init__/", report) - self.assertIn("/test/modules/covmod1 ", report) - self.assertIn("/test/zipmods.zip/covmodzip1 ", report) - self.assertIn("mycode ", report) - self.assertEqual(self.last_line_squeezed(report), "TOTAL 8 0 100%") - - def test_report_just_one(self): - # Try reporting just one module - self.run_command("coverage -x mycode.py") - report = self.report_from_command("coverage -r mycode.py") - - # Name Stmts Miss Cover - # ---------------------------- - # mycode 4 0 100% - - self.assertEqual(self.line_count(report), 3) - self.assertNotIn("/coverage/", report) - self.assertNotIn("/test/modules/covmod1 ", report) - self.assertNotIn("/test/zipmods.zip/covmodzip1 ", report) - self.assertIn("mycode ", report) - self.assertEqual(self.last_line_squeezed(report), "mycode 4 0 100%") - - def test_report_omitting(self): - # Try reporting while omitting some modules - prefix = os.path.split(__file__)[0] - self.run_command("coverage -x mycode.py") - report = self.report_from_command("coverage -r -o '%s/*'" % prefix) - - # Name Stmts Miss Cover - # ---------------------------- - # mycode 4 0 100% - - self.assertEqual(self.line_count(report), 3) - self.assertNotIn("/coverage/", report) - self.assertNotIn("/test/modules/covmod1 ", report) - self.assertNotIn("/test/zipmods.zip/covmodzip1 ", report) - self.assertIn("mycode ", report) - self.assertEqual(self.last_line_squeezed(report), "mycode 4 0 100%") - - def test_report_including(self): - # Try reporting while including some modules - self.run_command("coverage run mycode.py") - report = self.report_from_command("coverage report --include=mycode*") - - # Name Stmts Miss Cover - # ---------------------------- - # mycode 4 0 100% - - self.assertEqual(self.line_count(report), 3) - self.assertNotIn("/coverage/", report) - self.assertNotIn("/test/modules/covmod1 ", report) - self.assertNotIn("/test/zipmods.zip/covmodzip1 ", report) - self.assertIn("mycode ", report) - self.assertEqual(self.last_line_squeezed(report), "mycode 4 0 100%") - - def test_report_branches(self): - self.make_file("mybranch.py", """\ - def branch(x): - if x: - print("x") - return x - branch(1) - """) - out = self.run_command("coverage run --branch mybranch.py") - self.assertEqual(out, 'x\n') - report = self.report_from_command("coverage report") - - # Name Stmts Miss Branch BrMiss Cover - # -------------------------------------------- - # mybranch 5 0 2 1 85% - - self.assertEqual(self.line_count(report), 3) - self.assertIn("mybranch ", report) - self.assertEqual(self.last_line_squeezed(report), - "mybranch 5 0 2 1 86%") - - def test_dotpy_not_python(self): - # We run a .py file, and when reporting, we can't parse it as Python. - # We should get an error message in the report. - - self.run_command("coverage run mycode.py") - self.make_file("mycode.py", "This isn't python at all!") - report = self.report_from_command("coverage -r mycode.py") - - # pylint: disable=C0301 - # Name Stmts Miss Cover - # ---------------------------- - # mycode NotPython: Couldn't parse '/tmp/test_cover/63354509363/mycode.py' as Python source: 'invalid syntax' at line 1 - - last = self.last_line_squeezed(report) - # The actual file name varies run to run. - last = re.sub(r"parse '.*mycode.py", "parse 'mycode.py", last) - # The actual error message varies version to version - last = re.sub(r": '.*' at", ": 'error' at", last) - self.assertEqual(last, - "mycode NotPython: " - "Couldn't parse 'mycode.py' as Python source: " - "'error' at line 1" - ) - - def test_dotpy_not_python_ignored(self): - # We run a .py file, and when reporting, we can't parse it as Python, - # but we've said to ignore errors, so there's no error reported. - self.run_command("coverage run mycode.py") - self.make_file("mycode.py", "This isn't python at all!") - report = self.report_from_command("coverage -r -i mycode.py") - - # Name Stmts Miss Cover - # ---------------------------- - - self.assertEqual(self.line_count(report), 2) - - def test_dothtml_not_python(self): - # We run a .html file, and when reporting, we can't parse it as - # Python. Since it wasn't .py, no error is reported. - - # Run an "html" file - self.make_file("mycode.html", "a = 1") - self.run_command("coverage run mycode.html") - # Before reporting, change it to be an HTML file. - self.make_file("mycode.html", "

    This isn't python at all!

    ") - report = self.report_from_command("coverage -r mycode.html") - - # Name Stmts Miss Cover - # ---------------------------- - - self.assertEqual(self.line_count(report), 2) - - def get_report(self, cov): - """Get the report from `cov`, and canonicalize it.""" - repout = StringIO() - cov.report(file=repout, show_missing=False) - report = repout.getvalue().replace('\\', '/') - report = re.sub(r" +", " ", report) - return report - - def test_bug_156_file_not_run_should_be_zero(self): - # https://bitbucket.org/ned/coveragepy/issue/156 - self.make_file("mybranch.py", """\ - def branch(x): - if x: - print("x") - return x - branch(1) - """) - self.make_file("main.py", """\ - print("y") - """) - cov = coverage.coverage(branch=True, source=["."]) - cov.start() - import main # pragma: nested # pylint: disable=F0401,W0612 - cov.stop() # pragma: nested - report = self.get_report(cov).splitlines() - self.assertIn("mybranch 5 5 2 2 0%", report) - - def run_TheCode_and_report_it(self): - """A helper for the next few tests.""" - cov = coverage.coverage() - cov.start() - import TheCode # pragma: nested # pylint: disable=F0401,W0612 - cov.stop() # pragma: nested - return self.get_report(cov) - - def test_bug_203_mixed_case_listed_twice_with_rc(self): - self.make_file("TheCode.py", "a = 1\n") - self.make_file(".coveragerc", "[run]\nsource = .\n") - - report = self.run_TheCode_and_report_it() - - self.assertIn("TheCode", report) - self.assertNotIn("thecode", report) - - def test_bug_203_mixed_case_listed_twice(self): - self.make_file("TheCode.py", "a = 1\n") - - report = self.run_TheCode_and_report_it() - - self.assertIn("TheCode", report) - self.assertNotIn("thecode", report) - - -class SummaryTest2(CoverageTest): - """Another bunch of summary tests.""" - # This class exists because tests naturally clump into classes based on the - # needs of their setUp and tearDown, rather than the product features they - # are testing. There's probably a better way to organize these. - - run_in_temp_dir = False - - def setUp(self): - super(SummaryTest2, self).setUp() - # Parent class saves and restores sys.path, we can just modify it. - this_dir = os.path.dirname(__file__) - sys.path.append(self.nice_file(this_dir, 'modules')) - sys.path.append(self.nice_file(this_dir, 'moremodules')) - - def test_empty_files(self): - # Shows that empty files like __init__.py are listed as having zero - # statements, not one statement. - cov = coverage.coverage() - cov.start() - import usepkgs # pragma: nested # pylint: disable=F0401,W0612 - cov.stop() # pragma: nested - - repout = StringIO() - cov.report(file=repout, show_missing=False) - - report = repout.getvalue().replace('\\', '/') - report = re.sub(r"\s+", " ", report) - self.assertIn("test/modules/pkg1/__init__ 1 0 100%", report) - self.assertIn("test/modules/pkg2/__init__ 0 0 100%", report) - - -class ReportingReturnValue(CoverageTest): - """Tests of reporting functions returning values.""" - - def run_coverage(self): - """Run coverage on doit.py and return the coverage object.""" - self.make_file("doit.py", """\ - a = 1 - b = 2 - c = 3 - d = 4 - if a > 10: - f = 6 - g = 7 - """) - - cov = coverage.coverage() - self.start_import_stop(cov, "doit") - return cov - - def test_report(self): - cov = self.run_coverage() - val = cov.report(include="*/doit.py") - self.assertAlmostEqual(val, 85.7, 1) - - def test_html(self): - cov = self.run_coverage() - val = cov.html_report(include="*/doit.py") - self.assertAlmostEqual(val, 85.7, 1) - - def test_xml(self): - cov = self.run_coverage() - val = cov.xml_report(include="*/doit.py") - self.assertAlmostEqual(val, 85.7, 1) diff --git a/test/test_templite.py b/test/test_templite.py deleted file mode 100644 index 0435c545..00000000 --- a/test/test_templite.py +++ /dev/null @@ -1,204 +0,0 @@ -"""Tests for coverage.templite.""" - -from coverage.templite import Templite -import unittest - -# pylint: disable=W0612,E1101 -# Disable W0612 (Unused variable) and -# E1101 (Instance of 'foo' has no 'bar' member) - -class AnyOldObject(object): - """Simple testing object. - - Use keyword arguments in the constructor to set attributes on the object. - - """ - def __init__(self, **attrs): - for n, v in attrs.items(): - setattr(self, n, v) - - -class TempliteTest(unittest.TestCase): - """Tests for Templite.""" - - def try_render(self, text, ctx, result): - """Render `text` through `ctx`, and it had better be `result`.""" - self.assertEqual(Templite(text).render(ctx), result) - - def test_passthrough(self): - # Strings without variables are passed through unchanged. - self.assertEqual(Templite("Hello").render(), "Hello") - self.assertEqual( - Templite("Hello, 20% fun time!").render(), - "Hello, 20% fun time!" - ) - - def test_variables(self): - # Variables use {{var}} syntax. - self.try_render("Hello, {{name}}!", {'name':'Ned'}, "Hello, Ned!") - - def test_pipes(self): - # Variables can be filtered with pipes. - data = { - 'name': 'Ned', - 'upper': lambda x: x.upper(), - 'second': lambda x: x[1], - } - self.try_render("Hello, {{name|upper}}!", data, "Hello, NED!") - - # Pipes can be concatenated. - self.try_render("Hello, {{name|upper|second}}!", data, "Hello, E!") - - def test_reusability(self): - # A single Templite can be used more than once with different data. - globs = { - 'upper': lambda x: x.upper(), - 'punct': '!', - } - - template = Templite("This is {{name|upper}}{{punct}}", globs) - self.assertEqual(template.render({'name':'Ned'}), "This is NED!") - self.assertEqual(template.render({'name':'Ben'}), "This is BEN!") - - def test_attribute(self): - # Variables' attributes can be accessed with dots. - obj = AnyOldObject(a="Ay") - self.try_render("{{obj.a}}", locals(), "Ay") - - obj2 = AnyOldObject(obj=obj, b="Bee") - self.try_render("{{obj2.obj.a}} {{obj2.b}}", locals(), "Ay Bee") - - def test_member_function(self): - # Variables' member functions can be used, as long as they are nullary. - class WithMemberFns(AnyOldObject): - """A class to try out member function access.""" - def ditto(self): - """Return twice the .txt attribute.""" - return self.txt + self.txt - obj = WithMemberFns(txt="Once") - self.try_render("{{obj.ditto}}", locals(), "OnceOnce") - - def test_item_access(self): - # Variables' items can be used. - d = {'a':17, 'b':23} - self.try_render("{{d.a}} < {{d.b}}", locals(), "17 < 23") - - def test_loops(self): - # Loops work like in Django. - nums = [1,2,3,4] - self.try_render( - "Look: {% for n in nums %}{{n}}, {% endfor %}done.", - locals(), - "Look: 1, 2, 3, 4, done." - ) - # Loop iterables can be filtered. - def rev(l): - """Return the reverse of `l`.""" - l = l[:] - l.reverse() - return l - - self.try_render( - "Look: {% for n in nums|rev %}{{n}}, {% endfor %}done.", - locals(), - "Look: 4, 3, 2, 1, done." - ) - - def test_empty_loops(self): - self.try_render( - "Empty: {% for n in nums %}{{n}}, {% endfor %}done.", - {'nums':[]}, - "Empty: done." - ) - - def test_multiline_loops(self): - self.try_render( - "Look: \n{% for n in nums %}\n{{n}}, \n{% endfor %}done.", - {'nums':[1,2,3]}, - "Look: \n\n1, \n\n2, \n\n3, \ndone." - ) - - def test_multiple_loops(self): - self.try_render( - "{% for n in nums %}{{n}}{% endfor %} and " - "{% for n in nums %}{{n}}{% endfor %}", - {'nums': [1,2,3]}, - "123 and 123" - ) - - def test_comments(self): - # Single-line comments work: - self.try_render( - "Hello, {# Name goes here: #}{{name}}!", - {'name':'Ned'}, "Hello, Ned!" - ) - # and so do multi-line comments: - self.try_render( - "Hello, {# Name\ngoes\nhere: #}{{name}}!", - {'name':'Ned'}, "Hello, Ned!" - ) - - def test_if(self): - self.try_render( - "Hi, {% if ned %}NED{% endif %}{% if ben %}BEN{% endif %}!", - {'ned': 1, 'ben': 0}, - "Hi, NED!" - ) - self.try_render( - "Hi, {% if ned %}NED{% endif %}{% if ben %}BEN{% endif %}!", - {'ned': 0, 'ben': 1}, - "Hi, BEN!" - ) - self.try_render( - "Hi, {% if ned %}NED{% if ben %}BEN{% endif %}{% endif %}!", - {'ned': 0, 'ben': 0}, - "Hi, !" - ) - self.try_render( - "Hi, {% if ned %}NED{% if ben %}BEN{% endif %}{% endif %}!", - {'ned': 1, 'ben': 0}, - "Hi, NED!" - ) - self.try_render( - "Hi, {% if ned %}NED{% if ben %}BEN{% endif %}{% endif %}!", - {'ned': 1, 'ben': 1}, - "Hi, NEDBEN!" - ) - - def test_loop_if(self): - self.try_render( - "@{% for n in nums %}{% if n %}Z{% endif %}{{n}}{% endfor %}!", - {'nums': [0,1,2]}, - "@0Z1Z2!" - ) - self.try_render( - "X{%if nums%}@{% for n in nums %}{{n}}{% endfor %}{%endif%}!", - {'nums': [0,1,2]}, - "X@012!" - ) - self.try_render( - "X{%if nums%}@{% for n in nums %}{{n}}{% endfor %}{%endif%}!", - {'nums': []}, - "X!" - ) - - def test_nested_loops(self): - self.try_render( - "@{% for n in nums %}" - "{% for a in abc %}{{a}}{{n}}{% endfor %}" - "{% endfor %}!", - {'nums': [0,1,2], 'abc': ['a', 'b', 'c']}, - "@a0b0c0a1b1c1a2b2c2!" - ) - - def test_exception_during_evaluation(self): - # TypeError: Couldn't evaluate {{ foo.bar.baz }}: - # 'NoneType' object is unsubscriptable - self.assertRaises(TypeError, self.try_render, - "Hey {{foo.bar.baz}} there", {'foo': None}, "Hey ??? there" - ) - - def test_bogus_tag_syntax(self): - self.assertRaises(SyntaxError, self.try_render, - "Huh: {% bogus %}!!{% endbogus %}??", {}, "" - ) diff --git a/test/test_testing.py b/test/test_testing.py deleted file mode 100644 index c2d1453d..00000000 --- a/test/test_testing.py +++ /dev/null @@ -1,192 +0,0 @@ -# -*- coding: utf-8 -*- -"""Tests that our test infrastructure is really working!""" - -import os, sys -from coverage.backward import to_bytes, rpartition -from test.backunittest import TestCase -from test.coveragetest import CoverageTest - -from coverage.backward import set # pylint: disable=W0622 - -class TestingTest(TestCase): - """Tests of helper methods on `backunittest.TestCase`.""" - - run_in_temp_dir = False - - def please_raise(self, exc, msg): - """Raise an exception for testing assertRaisesRegexp.""" - raise exc(msg) - - def please_succeed(self): - """A simple successful method for testing assertRaisesRegexp.""" - return "All is well" - - def test_assert_same_elements(self): - self.assertSameElements(set(), set()) - self.assertSameElements(set([1,2,3]), set([3,1,2])) - self.assertRaises(AssertionError, self.assertSameElements, - set([1,2,3]), set() - ) - self.assertRaises(AssertionError, self.assertSameElements, - set([1,2,3]), set([4,5,6]) - ) - - def test_assert_regexp_matches(self): - self.assertRegexpMatches("hello", "hel*o") - self.assertRegexpMatches("Oh, hello there!", "hel*o") - self.assertRaises(AssertionError, self.assertRegexpMatches, - "hello there", "^hello$" - ) - - def test_assert_multiline_equal(self): - self.assertMultiLineEqual("hello", "hello") - self.assertRaises(AssertionError, self.assertMultiLineEqual, - "hello there", "Hello there" - ) - self.assertRaises(AssertionError, self.assertMultiLineEqual, - "hello\nthere", "hello\nThere" - ) - # With messages also. - self.assertMultiLineEqual("hi", "hi", "it's ok") - self.assertRaisesRegexp( - AssertionError, "my message", - self.assertMultiLineEqual, "xyz", "abc", "my message" - ) - - def test_assert_raises_regexp(self): - # Raising the right error with the right message passes. - self.assertRaisesRegexp( - ZeroDivisionError, "Wow! Zero!", - self.please_raise, ZeroDivisionError, "Wow! Zero!" - ) - # Raising the right error with a match passes. - self.assertRaisesRegexp( - ZeroDivisionError, "Zero", - self.please_raise, ZeroDivisionError, "Wow! Zero!" - ) - # Raising the right error with a mismatch fails. - self.assertRaises(AssertionError, - self.assertRaisesRegexp, ZeroDivisionError, "XYZ", - self.please_raise, ZeroDivisionError, "Wow! Zero!" - ) - # Raising the right error with a mismatch fails. - self.assertRaises(AssertionError, - self.assertRaisesRegexp, ZeroDivisionError, "XYZ", - self.please_raise, ZeroDivisionError, "Wow! Zero!" - ) - # Raising the wrong error raises the error itself. - self.assertRaises(ZeroDivisionError, - self.assertRaisesRegexp, IOError, "Wow! Zero!", - self.please_raise, ZeroDivisionError, "Wow! Zero!" - ) - # Raising no error fails. - self.assertRaises(AssertionError, - self.assertRaisesRegexp, ZeroDivisionError, "XYZ", - self.please_succeed - ) - - def test_assert_true(self): - self.assertTrue(True) - self.assertRaises(AssertionError, self.assertTrue, False) - - def test_assert_false(self): - self.assertFalse(False) - self.assertRaises(AssertionError, self.assertFalse, True) - - def test_assert_in(self): - self.assertIn("abc", "hello abc") - self.assertIn("abc", ["xyz", "abc", "foo"]) - self.assertIn("abc", {'abc': 1, 'xyz': 2}) - self.assertRaises(AssertionError, self.assertIn, "abc", "xyz") - self.assertRaises(AssertionError, self.assertIn, "abc", ["x", "xabc"]) - self.assertRaises(AssertionError, self.assertIn, "abc", {'x':'abc'}) - - def test_assert_not_in(self): - self.assertRaises(AssertionError, self.assertNotIn, "abc", "hello abc") - self.assertRaises(AssertionError, - self.assertNotIn, "abc", ["xyz", "abc", "foo"] - ) - self.assertRaises(AssertionError, - self.assertNotIn, "abc", {'abc': 1, 'xyz': 2} - ) - self.assertNotIn("abc", "xyz") - self.assertNotIn("abc", ["x", "xabc"]) - self.assertNotIn("abc", {'x':'abc'}) - - def test_assert_greater(self): - self.assertGreater(10, 9) - self.assertGreater("xyz", "abc") - self.assertRaises(AssertionError, self.assertGreater, 9, 10) - self.assertRaises(AssertionError, self.assertGreater, 10, 10) - self.assertRaises(AssertionError, self.assertGreater, "abc", "xyz") - self.assertRaises(AssertionError, self.assertGreater, "xyz", "xyz") - - -class CoverageTestTest(CoverageTest): - """Test the methods in `CoverageTest`.""" - - def file_text(self, fname): - """Return the text read from a file.""" - return open(fname, "rb").read().decode('ascii') - - def test_make_file(self): - # A simple file. - self.make_file("fooey.boo", "Hello there") - self.assertEqual(open("fooey.boo").read(), "Hello there") - # A file in a sub-directory - self.make_file("sub/another.txt", "Another") - self.assertEqual(open("sub/another.txt").read(), "Another") - # A second file in that sub-directory - self.make_file("sub/second.txt", "Second") - self.assertEqual(open("sub/second.txt").read(), "Second") - # A deeper directory - self.make_file("sub/deeper/evenmore/third.txt") - self.assertEqual(open("sub/deeper/evenmore/third.txt").read(), "") - - def test_make_file_newline(self): - self.make_file("unix.txt", "Hello\n") - self.assertEqual(self.file_text("unix.txt"), "Hello\n") - self.make_file("dos.txt", "Hello\n", newline="\r\n") - self.assertEqual(self.file_text("dos.txt"), "Hello\r\n") - self.make_file("mac.txt", "Hello\n", newline="\r") - self.assertEqual(self.file_text("mac.txt"), "Hello\r") - - def test_make_file_non_ascii(self): - self.make_file("unicode.txt", "tabblo: «ταБЬℓσ»") - self.assertEqual( - open("unicode.txt", "rb").read(), - to_bytes("tabblo: «ταБЬℓσ»") - ) - - def test_file_exists(self): - self.make_file("whoville.txt", "We are here!") - self.assert_exists("whoville.txt") - self.assert_doesnt_exist("shadow.txt") - self.assertRaises( - AssertionError, self.assert_doesnt_exist, "whoville.txt" - ) - self.assertRaises(AssertionError, self.assert_exists, "shadow.txt") - - def test_sub_python_is_this_python(self): - # Try it with a python command. - os.environ['COV_FOOBAR'] = 'XYZZY' - self.make_file("showme.py", """\ - import os, sys - print(sys.executable) - print(os.__file__) - print(os.environ['COV_FOOBAR']) - """) - out = self.run_command("python showme.py").splitlines() - self.assertEqual(out[0], sys.executable) - self.assertEqual(out[1], os.__file__) - self.assertEqual(out[2], 'XYZZY') - - # Try it with a "coverage debug sys" command. - out = self.run_command("coverage debug sys").splitlines() - # "environment: COV_FOOBAR = XYZZY" or "COV_FOOBAR = XYZZY" - executable = [l for l in out if "executable:" in l][0] - executable = executable.split(":", 1)[1].strip() - self.assertEqual(executable, sys.executable) - environ = [l for l in out if "COV_FOOBAR" in l][0] - _, _, environ = rpartition(environ, ":") - self.assertEqual(environ.strip(), "COV_FOOBAR = XYZZY") diff --git a/test/test_xml.py b/test/test_xml.py deleted file mode 100644 index 204b5869..00000000 --- a/test/test_xml.py +++ /dev/null @@ -1,84 +0,0 @@ -"""Tests for XML reports from coverage.py.""" - -import os, re -import coverage - -from test.coveragetest import CoverageTest - -class XmlReportTest(CoverageTest): - """Tests of the XML reports from coverage.py.""" - - def run_mycode(self): - """Run mycode.py, so we can report on it.""" - self.make_file("mycode.py", "print('hello')\n") - self.run_command("coverage run mycode.py") - - def test_default_file_placement(self): - self.run_mycode() - self.run_command("coverage xml") - self.assert_exists("coverage.xml") - - def test_argument_affects_xml_placement(self): - self.run_mycode() - self.run_command("coverage xml -o put_it_there.xml") - self.assert_doesnt_exist("coverage.xml") - self.assert_exists("put_it_there.xml") - - def test_config_affects_xml_placement(self): - self.run_mycode() - self.make_file(".coveragerc", "[xml]\noutput = xml.out\n") - self.run_command("coverage xml") - self.assert_doesnt_exist("coverage.xml") - self.assert_exists("xml.out") - - def test_no_data(self): - # https://bitbucket.org/ned/coveragepy/issue/210 - self.run_command("coverage xml") - self.assert_doesnt_exist("coverage.xml") - - def test_no_source(self): - # Written while investigating a bug, might as well keep it. - # https://bitbucket.org/ned/coveragepy/issue/208 - self.make_file("innocuous.py", "a = 4") - cov = coverage.coverage() - self.start_import_stop(cov, "innocuous") - os.remove("innocuous.py") - cov.xml_report(ignore_errors=True) - self.assert_exists("coverage.xml") - - def run_doit(self): - """Construct a simple sub-package.""" - self.make_file("sub/__init__.py") - self.make_file("sub/doit.py", "print('doit!')") - self.make_file("main.py", "import sub.doit") - cov = coverage.coverage() - self.start_import_stop(cov, "main") - return cov - - def test_filename_format_showing_everything(self): - cov = self.run_doit() - cov.xml_report(outfile="-") - xml = self.stdout() - doit_line = re_line(xml, "class.*doit") - self.assertIn('filename="sub/doit.py"', doit_line) - - def test_filename_format_including_filename(self): - cov = self.run_doit() - cov.xml_report(["sub/doit.py"], outfile="-") - xml = self.stdout() - doit_line = re_line(xml, "class.*doit") - self.assertIn('filename="sub/doit.py"', doit_line) - - def test_filename_format_including_module(self): - cov = self.run_doit() - import sub.doit # pylint: disable=F0401 - cov.xml_report([sub.doit], outfile="-") - xml = self.stdout() - doit_line = re_line(xml, "class.*doit") - self.assertIn('filename="sub/doit.py"', doit_line) - - -def re_line(text, pat): - """Return the one line in `text` that matches regex `pat`.""" - lines = [l for l in text.splitlines() if re.search(pat, l)] - return lines[0] diff --git a/test/try_execfile.py b/test/try_execfile.py deleted file mode 100644 index 9bbabd1a..00000000 --- a/test/try_execfile.py +++ /dev/null @@ -1,34 +0,0 @@ -"""Test file for run_python_file.""" - -import os, pprint, sys - -DATA = "xyzzy" - -import __main__ - -def my_function(a): - """A function to force execution of module-level values.""" - return "my_fn(%r)" % a - -FN_VAL = my_function("fooey") - -try: - pkg = __package__ -except NameError: - pkg = "*No __package__*" - -globals_to_check = { - '__name__': __name__, - '__file__': __file__, - '__doc__': __doc__, - '__builtins__.has_open': hasattr(__builtins__, 'open'), - '__builtins__.dir': dir(__builtins__), - '__package__': pkg, - 'DATA': DATA, - 'FN_VAL': FN_VAL, - '__main__.DATA': getattr(__main__, "DATA", "nothing"), - 'argv': sys.argv, - 'path': [os.path.normcase(p) for p in sys.path], -} - -pprint.pprint(globals_to_check) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 00000000..5a0e30f4 --- /dev/null +++ b/tests/__init__.py @@ -0,0 +1 @@ +"""Automated tests. Run with nosetests.""" diff --git a/tests/backtest.py b/tests/backtest.py new file mode 100644 index 00000000..b17aa242 --- /dev/null +++ b/tests/backtest.py @@ -0,0 +1,49 @@ +"""Add things to old Pythons so I can pretend they are newer, for tests.""" + +# pylint: disable=W0622 +# (Redefining built-in blah) +# The whole point of this file is to redefine built-ins, so shut up about it. + +import os + +# Py2k and 3k don't agree on how to run commands in a subprocess. +try: + import subprocess +except ImportError: + def run_command(cmd, status=0): + """Run a command in a subprocess. + + Returns the exit status code and the combined stdout and stderr. + + """ + _, stdouterr = os.popen4(cmd) + return status, stdouterr.read() + +else: + def run_command(cmd, status=0): + """Run a command in a subprocess. + + Returns the exit status code and the combined stdout and stderr. + + """ + proc = subprocess.Popen(cmd, shell=True, + stdin=subprocess.PIPE, stdout=subprocess.PIPE, + stderr=subprocess.STDOUT + ) + output, _ = proc.communicate() + status = proc.returncode # pylint: disable=E1101 + + # Get the output, and canonicalize it to strings with newlines. + if not isinstance(output, str): + output = output.decode('utf-8') + output = output.replace('\r', '') + + return status, output + +# No more execfile in Py3k +try: + execfile = execfile +except NameError: + def execfile(filename, globs): + """A Python 3 implementation of execfile.""" + exec(compile(open(filename).read(), filename, 'exec'), globs) diff --git a/tests/backunittest.py b/tests/backunittest.py new file mode 100644 index 00000000..30da78eb --- /dev/null +++ b/tests/backunittest.py @@ -0,0 +1,115 @@ +"""Implementations of unittest features from the future.""" + +import difflib, re, sys, unittest + +from coverage.backward import set # pylint: disable=W0622 + + +def _need(method): + """Do we need to define our own `method` method?""" + return not hasattr(unittest.TestCase, method) + + +class TestCase(unittest.TestCase): + """Just like unittest.TestCase, but with assert methods added. + + Designed to be compatible with 3.1 unittest. Methods are only defined if + the builtin `unittest` doesn't have them. + + """ + if _need('assertTrue'): + def assertTrue(self, exp, msg=None): + """Assert that `exp` is true.""" + if not exp: + self.fail(msg) + + if _need('assertFalse'): + def assertFalse(self, exp, msg=None): + """Assert that `exp` is false.""" + if exp: + self.fail(msg) + + if _need('assertIn'): + def assertIn(self, member, container, msg=None): + """Assert that `member` is in `container`.""" + if member not in container: + msg = msg or ('%r not found in %r' % (member, container)) + self.fail(msg) + + if _need('assertNotIn'): + def assertNotIn(self, member, container, msg=None): + """Assert that `member` is not in `container`.""" + if member in container: + msg = msg or ('%r found in %r' % (member, container)) + self.fail(msg) + + if _need('assertGreater'): + def assertGreater(self, a, b, msg=None): + """Assert that `a` is greater than `b`.""" + if not a > b: + msg = msg or ('%r not greater than %r' % (a, b)) + self.fail(msg) + + if _need('assertRaisesRegexp'): + def assertRaisesRegexp(self, excClass, regexp, callobj, *args, **kw): + """ Just like unittest.TestCase.assertRaises, + but checks that the message is right too. + """ + try: + callobj(*args, **kw) + except excClass: + _, exc, _ = sys.exc_info() + excMsg = str(exc) + if re.search(regexp, excMsg): + # Message provided, and we got the right one: it passes. + return + else: + # Message provided, and it didn't match: fail! + raise self.failureException( + "Right exception, wrong message: " + "%r doesn't match %r" % (excMsg, regexp) + ) + # No need to catch other exceptions: They'll fail the test all by + # themselves! + else: + if hasattr(excClass, '__name__'): + excName = excClass.__name__ + else: + excName = str(excClass) + raise self.failureException( + "Expected to raise %s, didn't get an exception at all" % + excName + ) + + if _need('assertSameElements'): + def assertSameElements(self, s1, s2): + """Assert that the two arguments are equal as sets.""" + self.assertEqual(set(s1), set(s2)) + + if _need('assertRegexpMatches'): + def assertRegexpMatches(self, text, regex, msg=None): + """Assert that `text` matches `regex`.""" + m = re.search(regex, text) + if not m: + msg = msg or ("%r doesn't match %r" % (text, regex)) + raise self.failureException(msg) + + if _need('assertMultiLineEqual'): + def assertMultiLineEqual(self, first, second, msg=None): + """Assert that two multi-line strings are equal. + + If they aren't, show a nice diff. + + """ + # Adapted from Py3.1 unittest. + self.assertTrue(isinstance(first, str), + 'First argument is not a string') + self.assertTrue(isinstance(second, str), + 'Second argument is not a string') + + if first != second: + message = ''.join(difflib.ndiff(first.splitlines(True), + second.splitlines(True))) + if msg: + message += " : " + msg + self.fail("Multi-line strings are unequal:\n" + message) diff --git a/tests/coveragetest.py b/tests/coveragetest.py new file mode 100644 index 00000000..6f6217aa --- /dev/null +++ b/tests/coveragetest.py @@ -0,0 +1,465 @@ +"""Base test case class for coverage testing.""" + +import glob, imp, os, random, shlex, shutil, sys, tempfile, textwrap + +import coverage +from coverage.backward import sorted, StringIO # pylint: disable=W0622 +from coverage.backward import to_bytes +from coverage.control import _TEST_NAME_FILE +from test.backtest import run_command +from test.backunittest import TestCase + +class Tee(object): + """A file-like that writes to all the file-likes it has.""" + + def __init__(self, *files): + """Make a Tee that writes to all the files in `files.`""" + self._files = files + if hasattr(files[0], "encoding"): + self.encoding = files[0].encoding + + def write(self, data): + """Write `data` to all the files.""" + for f in self._files: + f.write(data) + + if 0: + # Use this if you need to use a debugger, though it makes some tests + # fail, I'm not sure why... + def __getattr__(self, name): + return getattr(self._files[0], name) + + +# Status returns for the command line. +OK, ERR = 0, 1 + +class CoverageTest(TestCase): + """A base class for Coverage test cases.""" + + run_in_temp_dir = True + + def setUp(self): + super(CoverageTest, self).setUp() + + if _TEST_NAME_FILE: + f = open(_TEST_NAME_FILE, "w") + f.write("%s_%s" % (self.__class__.__name__, self._testMethodName)) + f.close() + + # Tell newer unittest implementations to print long helpful messages. + self.longMessage = True + + # tearDown will restore the original sys.path + self.old_syspath = sys.path[:] + + if self.run_in_temp_dir: + # Create a temporary directory. + self.noise = str(random.random())[2:] + self.temp_root = os.path.join(tempfile.gettempdir(), 'test_cover') + self.temp_dir = os.path.join(self.temp_root, self.noise) + os.makedirs(self.temp_dir) + self.old_dir = os.getcwd() + os.chdir(self.temp_dir) + + # Modules should be importable from this temp directory. + sys.path.insert(0, '') + + # Keep a counter to make every call to check_coverage unique. + self.n = 0 + + # Record environment variables that we changed with set_environ. + self.environ_undos = {} + + # Capture stdout and stderr so we can examine them in tests. + # nose keeps stdout from littering the screen, so we can safely Tee it, + # but it doesn't capture stderr, so we don't want to Tee stderr to the + # real stderr, since it will interfere with our nice field of dots. + self.old_stdout = sys.stdout + self.captured_stdout = StringIO() + sys.stdout = Tee(sys.stdout, self.captured_stdout) + self.old_stderr = sys.stderr + self.captured_stderr = StringIO() + sys.stderr = self.captured_stderr + + # Record sys.modules here so we can restore it in tearDown. + self.old_modules = dict(sys.modules) + + def tearDown(self): + super(CoverageTest, self).tearDown() + + # Restore the original sys.path. + sys.path = self.old_syspath + + if self.run_in_temp_dir: + # Get rid of the temporary directory. + os.chdir(self.old_dir) + shutil.rmtree(self.temp_root) + + # Restore the environment. + self.undo_environ() + + # Restore stdout and stderr + sys.stdout = self.old_stdout + sys.stderr = self.old_stderr + + self.clean_modules() + + def clean_modules(self): + """Remove any new modules imported during the test run. + + This lets us import the same source files for more than one test. + + """ + for m in [m for m in sys.modules if m not in self.old_modules]: + del sys.modules[m] + + def set_environ(self, name, value): + """Set an environment variable `name` to be `value`. + + The environment variable is set, and record is kept that it was set, + so that `tearDown` can restore its original value. + + """ + if name not in self.environ_undos: + self.environ_undos[name] = os.environ.get(name) + os.environ[name] = value + + def original_environ(self, name, if_missing=None): + """The environment variable `name` from when the test started.""" + if name in self.environ_undos: + ret = self.environ_undos[name] + else: + ret = os.environ.get(name) + if ret is None: + ret = if_missing + return ret + + def undo_environ(self): + """Undo all the changes made by `set_environ`.""" + for name, value in self.environ_undos.items(): + if value is None: + del os.environ[name] + else: + os.environ[name] = value + + def stdout(self): + """Return the data written to stdout during the test.""" + return self.captured_stdout.getvalue() + + def stderr(self): + """Return the data written to stderr during the test.""" + return self.captured_stderr.getvalue() + + def make_file(self, filename, text="", newline=None): + """Create a temp file. + + `filename` is the path to the file, including directories if desired, + and `text` is the content. If `newline` is provided, it is a string + that will be used as the line endings in the created file. + + Returns the path to the file. + + """ + # Tests that call `make_file` should be run in a temp environment. + assert self.run_in_temp_dir + text = textwrap.dedent(text) + if newline: + text = text.replace("\n", newline) + + # Make sure the directories are available. + dirs, _ = os.path.split(filename) + if dirs and not os.path.exists(dirs): + os.makedirs(dirs) + + # Create the file. + f = open(filename, 'wb') + try: + f.write(to_bytes(text)) + finally: + f.close() + + return filename + + def clean_local_file_imports(self): + """Clean up the results of calls to `import_local_file`. + + Use this if you need to `import_local_file` the same file twice in + one test. + + """ + # So that we can re-import files, clean them out first. + self.clean_modules() + # Also have to clean out the .pyc file, since the timestamp + # resolution is only one second, a changed file might not be + # picked up. + for pyc in glob.glob('*.pyc'): + os.remove(pyc) + if os.path.exists("__pycache__"): + shutil.rmtree("__pycache__") + + def import_local_file(self, modname): + """Import a local file as a module. + + Opens a file in the current directory named `modname`.py, imports it + as `modname`, and returns the module object. + + """ + modfile = modname + '.py' + f = open(modfile, 'r') + + for suff in imp.get_suffixes(): + if suff[0] == '.py': + break + try: + # pylint: disable=W0631 + # (Using possibly undefined loop variable 'suff') + mod = imp.load_module(modname, f, modfile, suff) + finally: + f.close() + return mod + + def start_import_stop(self, cov, modname): + """Start coverage, import a file, then stop coverage. + + `cov` is started and stopped, with an `import_local_file` of + `modname` in the middle. + + The imported module is returned. + + """ + cov.start() + try: # pragma: nested + # Import the python file, executing it. + mod = self.import_local_file(modname) + finally: # pragma: nested + # Stop Coverage. + cov.stop() + return mod + + def get_module_name(self): + """Return the module name to use for this test run.""" + # We append self.n because otherwise two calls in one test will use the + # same filename and whether the test works or not depends on the + # timestamps in the .pyc file, so it becomes random whether the second + # call will use the compiled version of the first call's code or not! + modname = 'coverage_test_' + self.noise + str(self.n) + self.n += 1 + return modname + + # Map chars to numbers for arcz_to_arcs + _arcz_map = {'.': -1} + _arcz_map.update(dict([(c, ord(c)-ord('0')) for c in '123456789'])) + _arcz_map.update(dict( + [(c, 10+ord(c)-ord('A')) for c in 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'] + )) + + def arcz_to_arcs(self, arcz): + """Convert a compact textual representation of arcs to a list of pairs. + + The text has space-separated pairs of letters. Period is -1, 1-9 are + 1-9, A-Z are 10 through 36. The resulting list is sorted regardless of + the order of the input pairs. + + ".1 12 2." --> [(-1,1), (1,2), (2,-1)] + + Minus signs can be included in the pairs: + + "-11, 12, 2-5" --> [(-1,1), (1,2), (2,-5)] + + """ + arcs = [] + for pair in arcz.split(): + asgn = bsgn = 1 + if len(pair) == 2: + a,b = pair + else: + assert len(pair) == 3 + if pair[0] == '-': + _,a,b = pair + asgn = -1 + else: + assert pair[1] == '-' + a,_,b = pair + bsgn = -1 + arcs.append((asgn*self._arcz_map[a], bsgn*self._arcz_map[b])) + return sorted(arcs) + + def assertEqualArcs(self, a1, a2, msg=None): + """Assert that the arc lists `a1` and `a2` are equal.""" + # Make them into multi-line strings so we can see what's going wrong. + s1 = "\n".join([repr(a) for a in a1]) + "\n" + s2 = "\n".join([repr(a) for a in a2]) + "\n" + self.assertMultiLineEqual(s1, s2, msg) + + def check_coverage(self, text, lines=None, missing="", report="", + excludes=None, partials="", + arcz=None, arcz_missing="", arcz_unpredicted=""): + """Check the coverage measurement of `text`. + + The source `text` is run and measured. `lines` are the line numbers + that are executable, or a list of possible line numbers, any of which + could match. `missing` are the lines not executed, `excludes` are + regexes to match against for excluding lines, and `report` is the text + of the measurement report. + + For arc measurement, `arcz` is a string that can be decoded into arcs + in the code (see `arcz_to_arcs` for the encoding scheme), + `arcz_missing` are the arcs that are not executed, and + `arcs_unpredicted` are the arcs executed in the code, but not deducible + from the code. + + """ + # We write the code into a file so that we can import it. + # Coverage wants to deal with things as modules with file names. + modname = self.get_module_name() + + self.make_file(modname+".py", text) + + arcs = arcs_missing = arcs_unpredicted = None + if arcz is not None: + arcs = self.arcz_to_arcs(arcz) + arcs_missing = self.arcz_to_arcs(arcz_missing or "") + arcs_unpredicted = self.arcz_to_arcs(arcz_unpredicted or "") + + # Start up Coverage. + cov = coverage.coverage(branch=(arcs_missing is not None)) + cov.erase() + for exc in excludes or []: + cov.exclude(exc) + for par in partials or []: + cov.exclude(par, which='partial') + + mod = self.start_import_stop(cov, modname) + + # Clean up our side effects + del sys.modules[modname] + + # Get the analysis results, and check that they are right. + analysis = cov._analyze(mod) + if lines is not None: + if type(lines[0]) == type(1): + # lines is just a list of numbers, it must match the statements + # found in the code. + self.assertEqual(analysis.statements, lines) + else: + # lines is a list of possible line number lists, one of them + # must match. + for line_list in lines: + if analysis.statements == line_list: + break + else: + self.fail("None of the lines choices matched %r" % + analysis.statements + ) + + if type(missing) == type(""): + self.assertEqual(analysis.missing_formatted(), missing) + else: + for missing_list in missing: + if analysis.missing_formatted() == missing_list: + break + else: + self.fail("None of the missing choices matched %r" % + analysis.missing_formatted() + ) + + if arcs is not None: + self.assertEqualArcs( + analysis.arc_possibilities(), arcs, "Possible arcs differ" + ) + + if arcs_missing is not None: + self.assertEqualArcs( + analysis.arcs_missing(), arcs_missing, + "Missing arcs differ" + ) + + if arcs_unpredicted is not None: + self.assertEqualArcs( + analysis.arcs_unpredicted(), arcs_unpredicted, + "Unpredicted arcs differ" + ) + + if report: + frep = StringIO() + cov.report(mod, file=frep) + rep = " ".join(frep.getvalue().split("\n")[2].split()[1:]) + self.assertEqual(report, rep) + + def nice_file(self, *fparts): + """Canonicalize the filename composed of the parts in `fparts`.""" + fname = os.path.join(*fparts) + return os.path.normcase(os.path.abspath(os.path.realpath(fname))) + + def assert_same_files(self, flist1, flist2): + """Assert that `flist1` and `flist2` are the same set of file names.""" + flist1_nice = [self.nice_file(f) for f in flist1] + flist2_nice = [self.nice_file(f) for f in flist2] + self.assertSameElements(flist1_nice, flist2_nice) + + def assert_exists(self, fname): + """Assert that `fname` is a file that exists.""" + msg = "File %r should exist" % fname + self.assert_(os.path.exists(fname), msg) + + def assert_doesnt_exist(self, fname): + """Assert that `fname` is a file that doesn't exist.""" + msg = "File %r shouldn't exist" % fname + self.assert_(not os.path.exists(fname), msg) + + def command_line(self, args, ret=OK, _covpkg=None): + """Run `args` through the command line. + + Use this when you want to run the full coverage machinery, but in the + current process. Exceptions may be thrown from deep in the code. + Asserts that `ret` is returned by `CoverageScript.command_line`. + + Compare with `run_command`. + + Returns None. + + """ + script = coverage.CoverageScript(_covpkg=_covpkg) + ret_actual = script.command_line(shlex.split(args)) + self.assertEqual(ret_actual, ret) + + def run_command(self, cmd): + """Run the command-line `cmd` in a subprocess, and print its output. + + Use this when you need to test the process behavior of coverage. + + Compare with `command_line`. + + Returns the process' stdout text. + + """ + _, output = self.run_command_status(cmd) + return output + + def run_command_status(self, cmd, status=0): + """Run the command-line `cmd` in a subprocess, and print its output. + + Use this when you need to test the process behavior of coverage. + + Compare with `command_line`. + + Returns a pair: the process' exit status and stdout text. + + The `status` argument is returned as the status on older Pythons where + we can't get the actual exit status of the process. + + """ + # Add our test modules directory to PYTHONPATH. I'm sure there's too + # much path munging here, but... + here = os.path.dirname(self.nice_file(coverage.__file__, "..")) + testmods = self.nice_file(here, 'test/modules') + zipfile = self.nice_file(here, 'test/zipmods.zip') + pypath = os.getenv('PYTHONPATH', '') + if pypath: + pypath += os.pathsep + pypath += testmods + os.pathsep + zipfile + self.set_environ('PYTHONPATH', pypath) + + status, output = run_command(cmd, status=status) + print(output) + return status, output diff --git a/tests/covmodzip1.py b/tests/covmodzip1.py new file mode 100644 index 00000000..3ec4cdc4 --- /dev/null +++ b/tests/covmodzip1.py @@ -0,0 +1,3 @@ +"""covmodzip.py: for putting into a zip file.""" +j = 1 +j += 1 diff --git a/tests/eggsrc/egg1/__init__.py b/tests/eggsrc/egg1/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/eggsrc/egg1/egg1.py b/tests/eggsrc/egg1/egg1.py new file mode 100644 index 00000000..3fadde33 --- /dev/null +++ b/tests/eggsrc/egg1/egg1.py @@ -0,0 +1,4 @@ +# My egg file! + +walrus = "Eggman" +says = "coo-coo cachoo" diff --git a/tests/eggsrc/setup.py b/tests/eggsrc/setup.py new file mode 100644 index 00000000..f9b8b9d0 --- /dev/null +++ b/tests/eggsrc/setup.py @@ -0,0 +1,8 @@ +from setuptools import setup + +setup( + name="covtestegg1", + packages=['egg1'], + zip_safe=True, + install_requires=[], + ) diff --git a/tests/farm/annotate/annotate_dir.py b/tests/farm/annotate/annotate_dir.py new file mode 100644 index 00000000..3e37f9ed --- /dev/null +++ b/tests/farm/annotate/annotate_dir.py @@ -0,0 +1,7 @@ +copy("src", "run") +run(""" + coverage -e -x multi.py + coverage -a -d out_anno_dir + """, rundir="run") +compare("run/out_anno_dir", "gold_anno_dir", "*,cover", left_extra=True) +clean("run") diff --git a/tests/farm/annotate/gold/white.py,cover b/tests/farm/annotate/gold/white.py,cover new file mode 100644 index 00000000..36b0b993 --- /dev/null +++ b/tests/farm/annotate/gold/white.py,cover @@ -0,0 +1,33 @@ + # A test case sent to me by Steve White + +> def f(self): +! if self==1: +! pass +! elif self.m('fred'): +! pass +! elif (g==1) and (b==2): +! pass +! elif self.m('fred')==True: +! pass +! elif ((g==1) and (b==2))==True: +! pass +! else: +! pass + +> def g(x): +> if x == 1: +> a = 1 +! else: +! a = 2 + +> g(1) + +> def h(x): +- if 0: #pragma: no cover +- pass +> if x == 1: +! a = 1 +> else: +> a = 2 + +> h(2) diff --git a/tests/farm/annotate/gold_anno_dir/a___init__.py,cover b/tests/farm/annotate/gold_anno_dir/a___init__.py,cover new file mode 100644 index 00000000..e69de29b diff --git a/tests/farm/annotate/gold_anno_dir/a_a.py,cover b/tests/farm/annotate/gold_anno_dir/a_a.py,cover new file mode 100644 index 00000000..d0ff3c0c --- /dev/null +++ b/tests/farm/annotate/gold_anno_dir/a_a.py,cover @@ -0,0 +1,5 @@ +> def a(x): +> if x == 1: +> print("x is 1") +! else: +! print("x is not 1") diff --git a/tests/farm/annotate/gold_anno_dir/b___init__.py,cover b/tests/farm/annotate/gold_anno_dir/b___init__.py,cover new file mode 100644 index 00000000..e69de29b diff --git a/tests/farm/annotate/gold_anno_dir/b_b.py,cover b/tests/farm/annotate/gold_anno_dir/b_b.py,cover new file mode 100644 index 00000000..90d076f1 --- /dev/null +++ b/tests/farm/annotate/gold_anno_dir/b_b.py,cover @@ -0,0 +1,3 @@ +> def b(x): +> msg = "x is %s" % x +> print(msg) diff --git a/tests/farm/annotate/gold_anno_dir/multi.py,cover b/tests/farm/annotate/gold_anno_dir/multi.py,cover new file mode 100644 index 00000000..2a5c59ce --- /dev/null +++ b/tests/farm/annotate/gold_anno_dir/multi.py,cover @@ -0,0 +1,5 @@ +> import a.a +> import b.b + +> a.a.a(1) +> b.b.b(2) diff --git a/tests/farm/annotate/gold_multi/a/__init__.py,cover b/tests/farm/annotate/gold_multi/a/__init__.py,cover new file mode 100644 index 00000000..e69de29b diff --git a/tests/farm/annotate/gold_multi/a/a.py,cover b/tests/farm/annotate/gold_multi/a/a.py,cover new file mode 100644 index 00000000..fb3f5435 --- /dev/null +++ b/tests/farm/annotate/gold_multi/a/a.py,cover @@ -0,0 +1,5 @@ +> def a(x): +> if x == 1: +> print "x is 1" +! else: +! print "x is not 1" diff --git a/tests/farm/annotate/gold_multi/b/__init__.py,cover b/tests/farm/annotate/gold_multi/b/__init__.py,cover new file mode 100644 index 00000000..e69de29b diff --git a/tests/farm/annotate/gold_multi/b/b.py,cover b/tests/farm/annotate/gold_multi/b/b.py,cover new file mode 100644 index 00000000..a3f5daec --- /dev/null +++ b/tests/farm/annotate/gold_multi/b/b.py,cover @@ -0,0 +1,2 @@ +> def b(x): +> print "x is %s" % x diff --git a/tests/farm/annotate/gold_multi/multi.py,cover b/tests/farm/annotate/gold_multi/multi.py,cover new file mode 100644 index 00000000..2a5c59ce --- /dev/null +++ b/tests/farm/annotate/gold_multi/multi.py,cover @@ -0,0 +1,5 @@ +> import a.a +> import b.b + +> a.a.a(1) +> b.b.b(2) diff --git a/tests/farm/annotate/gold_v24/white.py,cover b/tests/farm/annotate/gold_v24/white.py,cover new file mode 100644 index 00000000..bbd8d428 --- /dev/null +++ b/tests/farm/annotate/gold_v24/white.py,cover @@ -0,0 +1,33 @@ + # A test case sent to me by Steve White + +> def f(self): +! if self==1: +! pass +! elif self.m('fred'): +! pass +! elif (g==1) and (b==2): +! pass +! elif self.m('fred')==True: +! pass +! elif ((g==1) and (b==2))==True: +! pass +> else: +! pass + +> def g(x): +> if x == 1: +> a = 1 +! else: +! a = 2 + +> g(1) + +> def h(x): +- if 0: #pragma: no cover +- pass +> if x == 1: +! a = 1 +> else: +> a = 2 + +> h(2) diff --git a/tests/farm/annotate/run.py b/tests/farm/annotate/run.py new file mode 100644 index 00000000..c645f21c --- /dev/null +++ b/tests/farm/annotate/run.py @@ -0,0 +1,7 @@ +copy("src", "out") +run(""" + coverage -e -x white.py + coverage -a white.py + """, rundir="out") +compare("out", "gold", "*,cover") +clean("out") diff --git a/tests/farm/annotate/run_multi.py b/tests/farm/annotate/run_multi.py new file mode 100644 index 00000000..4e8252ed --- /dev/null +++ b/tests/farm/annotate/run_multi.py @@ -0,0 +1,7 @@ +copy("src", "out_multi") +run(""" + coverage -e -x multi.py + coverage -a + """, rundir="out_multi") +compare("out_multi", "gold_multi", "*,cover") +clean("out_multi") diff --git a/tests/farm/annotate/src/a/__init__.py b/tests/farm/annotate/src/a/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/farm/annotate/src/a/a.py b/tests/farm/annotate/src/a/a.py new file mode 100644 index 00000000..c2583d1e --- /dev/null +++ b/tests/farm/annotate/src/a/a.py @@ -0,0 +1,5 @@ +def a(x): + if x == 1: + print("x is 1") + else: + print("x is not 1") diff --git a/tests/farm/annotate/src/b/__init__.py b/tests/farm/annotate/src/b/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/farm/annotate/src/b/b.py b/tests/farm/annotate/src/b/b.py new file mode 100644 index 00000000..625a5490 --- /dev/null +++ b/tests/farm/annotate/src/b/b.py @@ -0,0 +1,3 @@ +def b(x): + msg = "x is %s" % x + print(msg) diff --git a/tests/farm/annotate/src/multi.py b/tests/farm/annotate/src/multi.py new file mode 100644 index 00000000..19a6200c --- /dev/null +++ b/tests/farm/annotate/src/multi.py @@ -0,0 +1,5 @@ +import a.a +import b.b + +a.a.a(1) +b.b.b(2) diff --git a/tests/farm/annotate/src/white.py b/tests/farm/annotate/src/white.py new file mode 100644 index 00000000..ecbbd25a --- /dev/null +++ b/tests/farm/annotate/src/white.py @@ -0,0 +1,33 @@ +# A test case sent to me by Steve White + +def f(self): + if self==1: + pass + elif self.m('fred'): + pass + elif (g==1) and (b==2): + pass + elif self.m('fred')==True: + pass + elif ((g==1) and (b==2))==True: + pass + else: + pass + +def g(x): + if x == 1: + a = 1 + else: + a = 2 + +g(1) + +def h(x): + if 0: #pragma: no cover + pass + if x == 1: + a = 1 + else: + a = 2 + +h(2) diff --git a/tests/farm/html/gold_a/a.html b/tests/farm/html/gold_a/a.html new file mode 100644 index 00000000..c794525e --- /dev/null +++ b/tests/farm/html/gold_a/a.html @@ -0,0 +1,95 @@ + + + + + + + + Coverage for a: 67% + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + r + m + x + p   toggle line displays +

    +

    + j + k   next/prev highlighted chunk +

    +

    + 0   (zero) top of page +

    +

    + 1   (one) first highlighted chunk +

    +
    +
    + +
    + + + + + +
    +

    1

    +

    2

    +

    3

    +

    4

    +

    5

    +

    6

    +

    7

    + +
    +

    # A test file for HTML reporting by coverage. 

    +

     

    +

    if 1 < 2: 

    +

        # Needed a < to look at HTML entities. 

    +

        a = 3 

    +

    else: 

    +

        a = 4 

    + +
    +
    + + + + + diff --git a/tests/farm/html/gold_a/index.html b/tests/farm/html/gold_a/index.html new file mode 100644 index 00000000..a821e9df --- /dev/null +++ b/tests/farm/html/gold_a/index.html @@ -0,0 +1,89 @@ + + + + + Coverage report + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + n + s + m + x + + c   change column sorting +

    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Modulestatementsmissingexcludedcoverage
    Total31067%
    a31067%
    +
    + + + + + diff --git a/tests/farm/html/gold_b_branch/b.html b/tests/farm/html/gold_b_branch/b.html new file mode 100644 index 00000000..0258ad13 --- /dev/null +++ b/tests/farm/html/gold_b_branch/b.html @@ -0,0 +1,139 @@ + + + + + + + + Coverage for b: 76% + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + r + m + x + p   toggle line displays +

    +

    + j + k   next/prev highlighted chunk +

    +

    + 0   (zero) top of page +

    +

    + 1   (one) first highlighted chunk +

    +
    +
    + +
    + + + + + +
    +

    1

    +

    2

    +

    3

    +

    4

    +

    5

    +

    6

    +

    7

    +

    8

    +

    9

    +

    10

    +

    11

    +

    12

    +

    13

    +

    14

    +

    15

    +

    16

    +

    17

    +

    18

    +

    19

    +

    20

    +

    21

    +

    22

    +

    23

    +

    24

    +

    25

    +

    26

    +

    27

    +

    28

    + +
    +

    # A test file for HTML reporting by coverage. 

    +

     

    +

    def one(x): 

    +

        # This will be a branch that misses the else. 

    +

    8    if x < 2: 

    +

            a = 3 

    +

        else: 

    +

            a = 4 

    +

     

    +

    one(1) 

    +

     

    +

    def two(x): 

    +

        # A missed else that branches to "exit" 

    +

    exit    if x: 

    +

            a = 5 

    +

     

    +

    two(1) 

    +

     

    +

    def three_way(): 

    +

        # for-else can be a three-way branch. 

    +

    25   26    for i in range(10): 

    +

            if i == 3: 

    +

                break 

    +

        else: 

    +

            return 23 

    +

        return 17 

    +

     

    +

    three_way() 

    + +
    +
    + + + + + diff --git a/tests/farm/html/gold_b_branch/index.html b/tests/farm/html/gold_b_branch/index.html new file mode 100644 index 00000000..cb6ffa17 --- /dev/null +++ b/tests/farm/html/gold_b_branch/index.html @@ -0,0 +1,101 @@ + + + + + Coverage report + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + n + s + m + x + + b + p + + c   change column sorting +

    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Modulestatementsmissingexcludedbranchespartialcoverage
    Total16209476%
    b16209476%
    +
    + + + + + diff --git a/tests/farm/html/gold_bom/bom.html b/tests/farm/html/gold_bom/bom.html new file mode 100644 index 00000000..1d61a62c --- /dev/null +++ b/tests/farm/html/gold_bom/bom.html @@ -0,0 +1,104 @@ + + + + + + + + Coverage for bom: 71% + + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + r + m + x + p   toggle line displays +

    +

    + j + k   next/prev highlighted chunk +

    +

    + 0   (zero) top of page +

    +

    + 1   (one) first highlighted chunk +

    +
    +
    + +
    + + + + + +
    +

    1

    +

    2

    +

    3

    +

    4

    +

    5

    +

    6

    +

    7

    +

    8

    +

    9

    +

    10

    +

    11

    + +
    +

    # A python source file in utf-8, with BOM 

    +

    math = "3×4 = 12, ÷2 = 6±0" 

    +

     

    +

    import sys 

    +

     

    +

    if sys.version_info >= (3, 0): 

    +

        assert len(math) == 18 

    +

        assert len(math.encode('utf-8')) == 21 

    +

    else: 

    +

        assert len(math) == 21 

    +

        assert len(math.decode('utf-8')) == 18 

    + +
    +
    + + + + + diff --git a/tests/farm/html/gold_bom/index.html b/tests/farm/html/gold_bom/index.html new file mode 100644 index 00000000..8653b23e --- /dev/null +++ b/tests/farm/html/gold_bom/index.html @@ -0,0 +1,90 @@ + + + + + Coverage report + + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + n + s + m + x + + c   change column sorting +

    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Modulestatementsmissingexcludedcoverage
    Total72071%
    bom72071%
    +
    + + + + + diff --git a/tests/farm/html/gold_isolatin1/index.html b/tests/farm/html/gold_isolatin1/index.html new file mode 100644 index 00000000..6e9f3ca7 --- /dev/null +++ b/tests/farm/html/gold_isolatin1/index.html @@ -0,0 +1,89 @@ + + + + + Coverage report + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + n + s + m + x + + c   change column sorting +

    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Modulestatementsmissingexcludedcoverage
    Total200100%
    isolatin1200100%
    +
    + + + + + diff --git a/tests/farm/html/gold_isolatin1/isolatin1.html b/tests/farm/html/gold_isolatin1/isolatin1.html new file mode 100644 index 00000000..276a6c25 --- /dev/null +++ b/tests/farm/html/gold_isolatin1/isolatin1.html @@ -0,0 +1,91 @@ + + + + + + + + Coverage for isolatin1: 100% + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + r + m + x + p   toggle line displays +

    +

    + j + k   next/prev highlighted chunk +

    +

    + 0   (zero) top of page +

    +

    + 1   (one) first highlighted chunk +

    +
    +
    + +
    + + + + + +
    +

    1

    +

    2

    +

    3

    +

    4

    +

    5

    + +
    +

    # A python source file in another encoding. 

    +

    # -*- coding: iso8859-1 -*- 

    +

     

    +

    math = "3×4 = 12, ÷2 = 6±0" 

    +

    assert len(math) == 18 

    + +
    +
    + + + + + diff --git a/tests/farm/html/gold_omit_1/index.html b/tests/farm/html/gold_omit_1/index.html new file mode 100644 index 00000000..5616d012 --- /dev/null +++ b/tests/farm/html/gold_omit_1/index.html @@ -0,0 +1,116 @@ + + + + + Coverage report + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + n + s + m + x + + c   change column sorting +

    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Modulestatementsmissingexcludedcoverage
    Total1400100%
    m1200100%
    m2200100%
    m3200100%
    main800100%
    +
    + + + + + diff --git a/tests/farm/html/gold_omit_1/m1.html b/tests/farm/html/gold_omit_1/m1.html new file mode 100644 index 00000000..62ba1e0a --- /dev/null +++ b/tests/farm/html/gold_omit_1/m1.html @@ -0,0 +1,85 @@ + + + + + + + + Coverage for m1: 100% + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + r + m + x + p   toggle line displays +

    +

    + j + k   next/prev highlighted chunk +

    +

    + 0   (zero) top of page +

    +

    + 1   (one) first highlighted chunk +

    +
    +
    + +
    + + + + + +
    +

    1

    +

    2

    + +
    +

    m1a = 1 

    +

    m1b = 2 

    + +
    +
    + + + + + diff --git a/tests/farm/html/gold_omit_1/m2.html b/tests/farm/html/gold_omit_1/m2.html new file mode 100644 index 00000000..d75a5ba0 --- /dev/null +++ b/tests/farm/html/gold_omit_1/m2.html @@ -0,0 +1,85 @@ + + + + + + + + Coverage for m2: 100% + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + r + m + x + p   toggle line displays +

    +

    + j + k   next/prev highlighted chunk +

    +

    + 0   (zero) top of page +

    +

    + 1   (one) first highlighted chunk +

    +
    +
    + +
    + + + + + +
    +

    1

    +

    2

    + +
    +

    m2a = 1 

    +

    m2b = 2 

    + +
    +
    + + + + + diff --git a/tests/farm/html/gold_omit_1/m3.html b/tests/farm/html/gold_omit_1/m3.html new file mode 100644 index 00000000..bd99138a --- /dev/null +++ b/tests/farm/html/gold_omit_1/m3.html @@ -0,0 +1,85 @@ + + + + + + + + Coverage for m3: 100% + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + r + m + x + p   toggle line displays +

    +

    + j + k   next/prev highlighted chunk +

    +

    + 0   (zero) top of page +

    +

    + 1   (one) first highlighted chunk +

    +
    +
    + +
    + + + + + +
    +

    1

    +

    2

    + +
    +

    m3a = 1 

    +

    m3b = 2 

    + +
    +
    + + + + + diff --git a/tests/farm/html/gold_omit_1/main.html b/tests/farm/html/gold_omit_1/main.html new file mode 100644 index 00000000..03948718 --- /dev/null +++ b/tests/farm/html/gold_omit_1/main.html @@ -0,0 +1,101 @@ + + + + + + + + Coverage for main: 100% + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + r + m + x + p   toggle line displays +

    +

    + j + k   next/prev highlighted chunk +

    +

    + 0   (zero) top of page +

    +

    + 1   (one) first highlighted chunk +

    +
    +
    + +
    + + + + + +
    +

    1

    +

    2

    +

    3

    +

    4

    +

    5

    +

    6

    +

    7

    +

    8

    +

    9

    +

    10

    + +
    +

    import m1 

    +

    import m2 

    +

    import m3 

    +

     

    +

    a = 5 

    +

    b = 6 

    +

     

    +

    assert m1.m1a == 1 

    +

    assert m2.m2a == 1 

    +

    assert m3.m3a == 1 

    + +
    +
    + + + + + diff --git a/tests/farm/html/gold_omit_2/index.html b/tests/farm/html/gold_omit_2/index.html new file mode 100644 index 00000000..3ce5bade --- /dev/null +++ b/tests/farm/html/gold_omit_2/index.html @@ -0,0 +1,107 @@ + + + + + Coverage report + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + n + s + m + x + + c   change column sorting +

    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Modulestatementsmissingexcludedcoverage
    Total1200100%
    m2200100%
    m3200100%
    main800100%
    +
    + + + + + diff --git a/tests/farm/html/gold_omit_2/m2.html b/tests/farm/html/gold_omit_2/m2.html new file mode 100644 index 00000000..d75a5ba0 --- /dev/null +++ b/tests/farm/html/gold_omit_2/m2.html @@ -0,0 +1,85 @@ + + + + + + + + Coverage for m2: 100% + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + r + m + x + p   toggle line displays +

    +

    + j + k   next/prev highlighted chunk +

    +

    + 0   (zero) top of page +

    +

    + 1   (one) first highlighted chunk +

    +
    +
    + +
    + + + + + +
    +

    1

    +

    2

    + +
    +

    m2a = 1 

    +

    m2b = 2 

    + +
    +
    + + + + + diff --git a/tests/farm/html/gold_omit_2/m3.html b/tests/farm/html/gold_omit_2/m3.html new file mode 100644 index 00000000..bd99138a --- /dev/null +++ b/tests/farm/html/gold_omit_2/m3.html @@ -0,0 +1,85 @@ + + + + + + + + Coverage for m3: 100% + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + r + m + x + p   toggle line displays +

    +

    + j + k   next/prev highlighted chunk +

    +

    + 0   (zero) top of page +

    +

    + 1   (one) first highlighted chunk +

    +
    +
    + +
    + + + + + +
    +

    1

    +

    2

    + +
    +

    m3a = 1 

    +

    m3b = 2 

    + +
    +
    + + + + + diff --git a/tests/farm/html/gold_omit_2/main.html b/tests/farm/html/gold_omit_2/main.html new file mode 100644 index 00000000..03948718 --- /dev/null +++ b/tests/farm/html/gold_omit_2/main.html @@ -0,0 +1,101 @@ + + + + + + + + Coverage for main: 100% + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + r + m + x + p   toggle line displays +

    +

    + j + k   next/prev highlighted chunk +

    +

    + 0   (zero) top of page +

    +

    + 1   (one) first highlighted chunk +

    +
    +
    + +
    + + + + + +
    +

    1

    +

    2

    +

    3

    +

    4

    +

    5

    +

    6

    +

    7

    +

    8

    +

    9

    +

    10

    + +
    +

    import m1 

    +

    import m2 

    +

    import m3 

    +

     

    +

    a = 5 

    +

    b = 6 

    +

     

    +

    assert m1.m1a == 1 

    +

    assert m2.m2a == 1 

    +

    assert m3.m3a == 1 

    + +
    +
    + + + + + diff --git a/tests/farm/html/gold_omit_3/index.html b/tests/farm/html/gold_omit_3/index.html new file mode 100644 index 00000000..fb826bf5 --- /dev/null +++ b/tests/farm/html/gold_omit_3/index.html @@ -0,0 +1,98 @@ + + + + + Coverage report + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + n + s + m + x + + c   change column sorting +

    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Modulestatementsmissingexcludedcoverage
    Total1000100%
    m3200100%
    main800100%
    +
    + + + + + diff --git a/tests/farm/html/gold_omit_3/m3.html b/tests/farm/html/gold_omit_3/m3.html new file mode 100644 index 00000000..bd99138a --- /dev/null +++ b/tests/farm/html/gold_omit_3/m3.html @@ -0,0 +1,85 @@ + + + + + + + + Coverage for m3: 100% + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + r + m + x + p   toggle line displays +

    +

    + j + k   next/prev highlighted chunk +

    +

    + 0   (zero) top of page +

    +

    + 1   (one) first highlighted chunk +

    +
    +
    + +
    + + + + + +
    +

    1

    +

    2

    + +
    +

    m3a = 1 

    +

    m3b = 2 

    + +
    +
    + + + + + diff --git a/tests/farm/html/gold_omit_3/main.html b/tests/farm/html/gold_omit_3/main.html new file mode 100644 index 00000000..03948718 --- /dev/null +++ b/tests/farm/html/gold_omit_3/main.html @@ -0,0 +1,101 @@ + + + + + + + + Coverage for main: 100% + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + r + m + x + p   toggle line displays +

    +

    + j + k   next/prev highlighted chunk +

    +

    + 0   (zero) top of page +

    +

    + 1   (one) first highlighted chunk +

    +
    +
    + +
    + + + + + +
    +

    1

    +

    2

    +

    3

    +

    4

    +

    5

    +

    6

    +

    7

    +

    8

    +

    9

    +

    10

    + +
    +

    import m1 

    +

    import m2 

    +

    import m3 

    +

     

    +

    a = 5 

    +

    b = 6 

    +

     

    +

    assert m1.m1a == 1 

    +

    assert m2.m2a == 1 

    +

    assert m3.m3a == 1 

    + +
    +
    + + + + + diff --git a/tests/farm/html/gold_omit_4/index.html b/tests/farm/html/gold_omit_4/index.html new file mode 100644 index 00000000..e437cf10 --- /dev/null +++ b/tests/farm/html/gold_omit_4/index.html @@ -0,0 +1,107 @@ + + + + + Coverage report + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + n + s + m + x + + c   change column sorting +

    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Modulestatementsmissingexcludedcoverage
    Total1200100%
    m1200100%
    m3200100%
    main800100%
    +
    + + + + + diff --git a/tests/farm/html/gold_omit_4/m1.html b/tests/farm/html/gold_omit_4/m1.html new file mode 100644 index 00000000..62ba1e0a --- /dev/null +++ b/tests/farm/html/gold_omit_4/m1.html @@ -0,0 +1,85 @@ + + + + + + + + Coverage for m1: 100% + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + r + m + x + p   toggle line displays +

    +

    + j + k   next/prev highlighted chunk +

    +

    + 0   (zero) top of page +

    +

    + 1   (one) first highlighted chunk +

    +
    +
    + +
    + + + + + +
    +

    1

    +

    2

    + +
    +

    m1a = 1 

    +

    m1b = 2 

    + +
    +
    + + + + + diff --git a/tests/farm/html/gold_omit_4/m3.html b/tests/farm/html/gold_omit_4/m3.html new file mode 100644 index 00000000..bd99138a --- /dev/null +++ b/tests/farm/html/gold_omit_4/m3.html @@ -0,0 +1,85 @@ + + + + + + + + Coverage for m3: 100% + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + r + m + x + p   toggle line displays +

    +

    + j + k   next/prev highlighted chunk +

    +

    + 0   (zero) top of page +

    +

    + 1   (one) first highlighted chunk +

    +
    +
    + +
    + + + + + +
    +

    1

    +

    2

    + +
    +

    m3a = 1 

    +

    m3b = 2 

    + +
    +
    + + + + + diff --git a/tests/farm/html/gold_omit_4/main.html b/tests/farm/html/gold_omit_4/main.html new file mode 100644 index 00000000..03948718 --- /dev/null +++ b/tests/farm/html/gold_omit_4/main.html @@ -0,0 +1,101 @@ + + + + + + + + Coverage for main: 100% + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + r + m + x + p   toggle line displays +

    +

    + j + k   next/prev highlighted chunk +

    +

    + 0   (zero) top of page +

    +

    + 1   (one) first highlighted chunk +

    +
    +
    + +
    + + + + + +
    +

    1

    +

    2

    +

    3

    +

    4

    +

    5

    +

    6

    +

    7

    +

    8

    +

    9

    +

    10

    + +
    +

    import m1 

    +

    import m2 

    +

    import m3 

    +

     

    +

    a = 5 

    +

    b = 6 

    +

     

    +

    assert m1.m1a == 1 

    +

    assert m2.m2a == 1 

    +

    assert m3.m3a == 1 

    + +
    +
    + + + + + diff --git a/tests/farm/html/gold_omit_5/index.html b/tests/farm/html/gold_omit_5/index.html new file mode 100644 index 00000000..4bde6b73 --- /dev/null +++ b/tests/farm/html/gold_omit_5/index.html @@ -0,0 +1,98 @@ + + + + + Coverage report + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + n + s + m + x + + c   change column sorting +

    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Modulestatementsmissingexcludedcoverage
    Total1000100%
    m1200100%
    main800100%
    +
    + + + + + diff --git a/tests/farm/html/gold_omit_5/m1.html b/tests/farm/html/gold_omit_5/m1.html new file mode 100644 index 00000000..62ba1e0a --- /dev/null +++ b/tests/farm/html/gold_omit_5/m1.html @@ -0,0 +1,85 @@ + + + + + + + + Coverage for m1: 100% + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + r + m + x + p   toggle line displays +

    +

    + j + k   next/prev highlighted chunk +

    +

    + 0   (zero) top of page +

    +

    + 1   (one) first highlighted chunk +

    +
    +
    + +
    + + + + + +
    +

    1

    +

    2

    + +
    +

    m1a = 1 

    +

    m1b = 2 

    + +
    +
    + + + + + diff --git a/tests/farm/html/gold_omit_5/main.html b/tests/farm/html/gold_omit_5/main.html new file mode 100644 index 00000000..03948718 --- /dev/null +++ b/tests/farm/html/gold_omit_5/main.html @@ -0,0 +1,101 @@ + + + + + + + + Coverage for main: 100% + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + r + m + x + p   toggle line displays +

    +

    + j + k   next/prev highlighted chunk +

    +

    + 0   (zero) top of page +

    +

    + 1   (one) first highlighted chunk +

    +
    +
    + +
    + + + + + +
    +

    1

    +

    2

    +

    3

    +

    4

    +

    5

    +

    6

    +

    7

    +

    8

    +

    9

    +

    10

    + +
    +

    import m1 

    +

    import m2 

    +

    import m3 

    +

     

    +

    a = 5 

    +

    b = 6 

    +

     

    +

    assert m1.m1a == 1 

    +

    assert m2.m2a == 1 

    +

    assert m3.m3a == 1 

    + +
    +
    + + + + + diff --git a/tests/farm/html/gold_other/blah_blah_other.html b/tests/farm/html/gold_other/blah_blah_other.html new file mode 100644 index 00000000..ab5ae371 --- /dev/null +++ b/tests/farm/html/gold_other/blah_blah_other.html @@ -0,0 +1,89 @@ + + + + + + + + Coverage for /home/ned/coverage/trunk/test/farm/html/othersrc/other: 100% + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + r + m + x + p   toggle line displays +

    +

    + j + k   next/prev highlighted chunk +

    +

    + 0   (zero) top of page +

    +

    + 1   (one) first highlighted chunk +

    +
    +
    + +
    + + + + + +
    +

    1

    +

    2

    +

    3

    +

    4

    + +
    +

    # A file in another directory.  We're checking that it ends up in the 

    +

    # HTML report. 

    +

     

    +

    print("This is the other src!") 

    + +
    +
    + + + + + diff --git a/tests/farm/html/gold_other/here.html b/tests/farm/html/gold_other/here.html new file mode 100644 index 00000000..1da5bcd6 --- /dev/null +++ b/tests/farm/html/gold_other/here.html @@ -0,0 +1,97 @@ + + + + + + + + Coverage for here: 75% + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + r + m + x + p   toggle line displays +

    +

    + j + k   next/prev highlighted chunk +

    +

    + 0   (zero) top of page +

    +

    + 1   (one) first highlighted chunk +

    +
    +
    + +
    + + + + + +
    +

    1

    +

    2

    +

    3

    +

    4

    +

    5

    +

    6

    +

    7

    +

    8

    + +
    +

    # A test file for HTML reporting by coverage. 

    +

     

    +

    import other 

    +

     

    +

    if 1 < 2: 

    +

        h = 3 

    +

    else: 

    +

        h = 4 

    + +
    +
    + + + + + diff --git a/tests/farm/html/gold_other/index.html b/tests/farm/html/gold_other/index.html new file mode 100644 index 00000000..7665cfe4 --- /dev/null +++ b/tests/farm/html/gold_other/index.html @@ -0,0 +1,98 @@ + + + + + Coverage report + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + n + s + m + x + + c   change column sorting +

    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Modulestatementsmissingexcludedcoverage
    Total51080%
    /home/ned/coverage/trunk/test/farm/html/othersrc/other100100%
    here41075%
    +
    + + + + + diff --git a/tests/farm/html/gold_partial/index.html b/tests/farm/html/gold_partial/index.html new file mode 100644 index 00000000..5556150a --- /dev/null +++ b/tests/farm/html/gold_partial/index.html @@ -0,0 +1,101 @@ + + + + + Coverage report + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + n + s + m + x + + b + p + + c   change column sorting +

    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Modulestatementsmissingexcludedbranchespartialcoverage
    Total80060100%
    partial80060100%
    +
    + + + + + diff --git a/tests/farm/html/gold_partial/partial.html b/tests/farm/html/gold_partial/partial.html new file mode 100644 index 00000000..b9640ce4 --- /dev/null +++ b/tests/farm/html/gold_partial/partial.html @@ -0,0 +1,121 @@ + + + + + + + + Coverage for partial: 100% + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + r + m + x + p   toggle line displays +

    +

    + j + k   next/prev highlighted chunk +

    +

    + 0   (zero) top of page +

    +

    + 1   (one) first highlighted chunk +

    +
    +
    + +
    + + + + + +
    +

    1

    +

    2

    +

    3

    +

    4

    +

    5

    +

    6

    +

    7

    +

    8

    +

    9

    +

    10

    +

    11

    +

    12

    +

    13

    +

    14

    +

    15

    +

    16

    +

    17

    +

    18

    +

    19

    + +
    +

    # partial branches 

    +

     

    +

    a = 3 

    +

     

    +

    while True: 

    +

        break 

    +

     

    +

    while 1: 

    +

        break 

    +

     

    +

    while a:        # pragma: no branch 

    +

        break 

    +

     

    +

    if 0: 

    +

        never_happen() 

    +

     

    +

    if 1: 

    +

        a = 13 

    +

     

    + +
    +
    + + + + + diff --git a/tests/farm/html/gold_styled/a.html b/tests/farm/html/gold_styled/a.html new file mode 100644 index 00000000..c794525e --- /dev/null +++ b/tests/farm/html/gold_styled/a.html @@ -0,0 +1,95 @@ + + + + + + + + Coverage for a: 67% + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + r + m + x + p   toggle line displays +

    +

    + j + k   next/prev highlighted chunk +

    +

    + 0   (zero) top of page +

    +

    + 1   (one) first highlighted chunk +

    +
    +
    + +
    + + + + + +
    +

    1

    +

    2

    +

    3

    +

    4

    +

    5

    +

    6

    +

    7

    + +
    +

    # A test file for HTML reporting by coverage. 

    +

     

    +

    if 1 < 2: 

    +

        # Needed a < to look at HTML entities. 

    +

        a = 3 

    +

    else: 

    +

        a = 4 

    + +
    +
    + + + + + diff --git a/tests/farm/html/gold_styled/extra.css b/tests/farm/html/gold_styled/extra.css new file mode 100644 index 00000000..46c41fcd --- /dev/null +++ b/tests/farm/html/gold_styled/extra.css @@ -0,0 +1 @@ +/* Doesn't matter what goes in here, it gets copied. */ diff --git a/tests/farm/html/gold_styled/index.html b/tests/farm/html/gold_styled/index.html new file mode 100644 index 00000000..a821e9df --- /dev/null +++ b/tests/farm/html/gold_styled/index.html @@ -0,0 +1,89 @@ + + + + + Coverage report + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + n + s + m + x + + c   change column sorting +

    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Modulestatementsmissingexcludedcoverage
    Total31067%
    a31067%
    +
    + + + + + diff --git a/tests/farm/html/gold_styled/style.css b/tests/farm/html/gold_styled/style.css new file mode 100644 index 00000000..c40357b8 --- /dev/null +++ b/tests/farm/html/gold_styled/style.css @@ -0,0 +1,275 @@ +/* CSS styles for Coverage. */ +/* Page-wide styles */ +html, body, h1, h2, h3, p, td, th { + margin: 0; + padding: 0; + border: 0; + outline: 0; + font-weight: inherit; + font-style: inherit; + font-size: 100%; + font-family: inherit; + vertical-align: baseline; + } + +/* Set baseline grid to 16 pt. */ +body { + font-family: georgia, serif; + font-size: 1em; + } + +html>body { + font-size: 16px; + } + +/* Set base font size to 12/16 */ +p { + font-size: .75em; /* 12/16 */ + line-height: 1.3333em; /* 16/12 */ + } + +table { + border-collapse: collapse; + } + +a.nav { + text-decoration: none; + color: inherit; + } +a.nav:hover { + text-decoration: underline; + color: inherit; + } + +/* Page structure */ +#header { + background: #f8f8f8; + width: 100%; + border-bottom: 1px solid #eee; + } + +#source { + padding: 1em; + font-family: "courier new", monospace; + } + +#indexfile #footer { + margin: 1em 3em; + } + +#pyfile #footer { + margin: 1em 1em; + } + +#footer .content { + padding: 0; + font-size: 85%; + font-family: verdana, sans-serif; + color: #666666; + font-style: italic; + } + +#index { + margin: 1em 0 0 3em; + } + +/* Header styles */ +#header .content { + padding: 1em 3em; + } + +h1 { + font-size: 1.25em; +} + +h2.stats { + margin-top: .5em; + font-size: 1em; +} +.stats span { + border: 1px solid; + padding: .1em .25em; + margin: 0 .1em; + cursor: pointer; + border-color: #999 #ccc #ccc #999; +} +.stats span.hide_run, .stats span.hide_exc, +.stats span.hide_mis, .stats span.hide_par, +.stats span.par.hide_run.hide_par { + border-color: #ccc #999 #999 #ccc; +} +.stats span.par.hide_run { + border-color: #999 #ccc #ccc #999; +} + +/* Help panel */ +#keyboard_icon { + float: right; + cursor: pointer; +} + +.help_panel { + position: absolute; + background: #ffc; + padding: .5em; + border: 1px solid #883; + display: none; +} + +#indexfile .help_panel { + width: 20em; height: 4em; +} + +#pyfile .help_panel { + width: 16em; height: 8em; +} + +.help_panel .legend { + font-style: italic; + margin-bottom: 1em; +} + +#panel_icon { + float: right; + cursor: pointer; +} + +.keyhelp { + margin: .75em; +} + +.keyhelp .key { + border: 1px solid black; + border-color: #888 #333 #333 #888; + padding: .1em .35em; + font-family: monospace; + font-weight: bold; + background: #eee; +} + +/* Source file styles */ +.linenos p { + text-align: right; + margin: 0; + padding: 0 .5em; + color: #999999; + font-family: verdana, sans-serif; + font-size: .625em; /* 10/16 */ + line-height: 1.6em; /* 16/10 */ + } +.linenos p.highlight { + background: #ffdd00; + } +.linenos p a { + text-decoration: none; + color: #999999; + } +.linenos p a:hover { + text-decoration: underline; + color: #999999; + } + +td.text { + width: 100%; + } +.text p { + margin: 0; + padding: 0 0 0 .5em; + border-left: 2px solid #ffffff; + white-space: nowrap; + } + +.text p.mis { + background: #ffdddd; + border-left: 2px solid #ff0000; + } +.text p.run, .text p.run.hide_par { + background: #ddffdd; + border-left: 2px solid #00ff00; + } +.text p.exc { + background: #eeeeee; + border-left: 2px solid #808080; + } +.text p.par, .text p.par.hide_run { + background: #ffffaa; + border-left: 2px solid #eeee99; + } +.text p.hide_run, .text p.hide_exc, .text p.hide_mis, .text p.hide_par, +.text p.hide_run.hide_par { + background: inherit; + } + +.text span.annotate { + font-family: georgia; + font-style: italic; + color: #666; + float: right; + padding-right: .5em; + } +.text p.hide_par span.annotate { + display: none; + } + +/* Syntax coloring */ +.text .com { + color: green; + font-style: italic; + line-height: 1px; + } +.text .key { + font-weight: bold; + line-height: 1px; + } +.text .str { + color: #000080; + } + +/* index styles */ +#index td, #index th { + text-align: right; + width: 5em; + padding: .25em .5em; + border-bottom: 1px solid #eee; + } +#index th { + font-style: italic; + color: #333; + border-bottom: 1px solid #ccc; + cursor: pointer; + } +#index th:hover { + background: #eee; + border-bottom: 1px solid #999; + } +#index td.left, #index th.left { + padding-left: 0; + } +#index td.right, #index th.right { + padding-right: 0; + } +#index th.headerSortDown, #index th.headerSortUp { + border-bottom: 1px solid #000; + } +#index td.name, #index th.name { + text-align: left; + width: auto; + } +#index td.name a { + text-decoration: none; + color: #000; + } +#index td.name a:hover { + text-decoration: underline; + color: #000; + } +#index tr.total { + } +#index tr.total td { + font-weight: bold; + border-top: 1px solid #ccc; + border-bottom: none; + } +#index tr.file:hover { + background: #eeeeee; + } diff --git a/tests/farm/html/gold_unicode/index.html b/tests/farm/html/gold_unicode/index.html new file mode 100644 index 00000000..9ba1bb39 --- /dev/null +++ b/tests/farm/html/gold_unicode/index.html @@ -0,0 +1,89 @@ + + + + + Coverage report + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + n + s + m + x + + c   change column sorting +

    +
    +
    + +
    + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Modulestatementsmissingexcludedcoverage
    Total100100%
    unicode100100%
    +
    + + + + + diff --git a/tests/farm/html/gold_unicode/unicode.html b/tests/farm/html/gold_unicode/unicode.html new file mode 100644 index 00000000..518a59a1 --- /dev/null +++ b/tests/farm/html/gold_unicode/unicode.html @@ -0,0 +1,91 @@ + + + + + + + + Coverage for unicode: 100% + + + + + + + + + + + +
    + +

    Hot-keys on this page

    +
    +

    + r + m + x + p   toggle line displays +

    +

    + j + k   next/prev highlighted chunk +

    +

    + 0   (zero) top of page +

    +

    + 1   (one) first highlighted chunk +

    +
    +
    + +
    + + + + + +
    +

    1

    +

    2

    +

    3

    +

    4

    +

    5

    + +
    +

    # A python source file with exotic characters 

    +

    # -*- coding: utf-8 -*- 

    +

     

    +

    upside_down = "ʎd˙ǝbɐɹǝʌoɔ" 

    +

    surrogate = "db40,dd00: x�� 󠄀" 

    + +
    +
    + + + + + diff --git a/tests/farm/html/gold_x_xml/coverage.xml b/tests/farm/html/gold_x_xml/coverage.xml new file mode 100644 index 00000000..912112f2 --- /dev/null +++ b/tests/farm/html/gold_x_xml/coverage.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + diff --git a/tests/farm/html/gold_y_xml_branch/coverage.xml b/tests/farm/html/gold_y_xml_branch/coverage.xml new file mode 100644 index 00000000..ecbe0073 --- /dev/null +++ b/tests/farm/html/gold_y_xml_branch/coverage.xml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + + + + + + + + + diff --git a/tests/farm/html/othersrc/other.py b/tests/farm/html/othersrc/other.py new file mode 100644 index 00000000..6d3f86e7 --- /dev/null +++ b/tests/farm/html/othersrc/other.py @@ -0,0 +1,4 @@ +# A file in another directory. We're checking that it ends up in the +# HTML report. + +print("This is the other src!") diff --git a/tests/farm/html/run_a.py b/tests/farm/html/run_a.py new file mode 100644 index 00000000..59cc1703 --- /dev/null +++ b/tests/farm/html/run_a.py @@ -0,0 +1,25 @@ +def html_it(): + """Run coverage and make an HTML report for a.""" + import coverage + cov = coverage.coverage() + cov.start() + import a # pragma: nested + cov.stop() # pragma: nested + cov.html_report(a, directory="../html_a") + +runfunc(html_it, rundir="src") + +# HTML files will change often. Check that the sizes are reasonable, +# and check that certain key strings are in the output. +compare("gold_a", "html_a", size_within=10, file_pattern="*.html") +contains("html_a/a.html", + "if 1 < 2", + "    a = 3", + "67%" + ) +contains("html_a/index.html", + "a", + "67%" + ) + +clean("html_a") diff --git a/tests/farm/html/run_a_xml_1.py b/tests/farm/html/run_a_xml_1.py new file mode 100644 index 00000000..3d187023 --- /dev/null +++ b/tests/farm/html/run_a_xml_1.py @@ -0,0 +1,21 @@ +def html_it(): + """Run coverage and make an XML report for a.""" + import coverage + cov = coverage.coverage() + cov.start() + import a # pragma: nested + cov.stop() # pragma: nested + cov.xml_report(a, outfile="../xml_1/coverage.xml") + +import os +if not os.path.exists("xml_1"): + os.makedirs("xml_1") + +runfunc(html_it, rundir="src") + +compare("gold_x_xml", "xml_1", scrubs=[ + (r' timestamp="\d+"', ' timestamp="TIMESTAMP"'), + (r' version="[-.\w]+"', ' version="VERSION"'), + (r'/code/coverage/?[-.\w]*', '/code/coverage/VER'), + ]) +clean("xml_1") diff --git a/tests/farm/html/run_a_xml_2.py b/tests/farm/html/run_a_xml_2.py new file mode 100644 index 00000000..53691ead --- /dev/null +++ b/tests/farm/html/run_a_xml_2.py @@ -0,0 +1,21 @@ +def html_it(): + """Run coverage and make an XML report for a.""" + import coverage + cov = coverage.coverage(config_file="run_a_xml_2.ini") + cov.start() + import a # pragma: nested + cov.stop() # pragma: nested + cov.xml_report(a) + +import os +if not os.path.exists("xml_2"): + os.makedirs("xml_2") + +runfunc(html_it, rundir="src") + +compare("gold_x_xml", "xml_2", scrubs=[ + (r' timestamp="\d+"', ' timestamp="TIMESTAMP"'), + (r' version="[-.\w]+"', ' version="VERSION"'), + (r'/code/coverage/?[-.\w]*', '/code/coverage/VER'), + ]) +clean("xml_2") diff --git a/tests/farm/html/run_b_branch.py b/tests/farm/html/run_b_branch.py new file mode 100644 index 00000000..d0955a2a --- /dev/null +++ b/tests/farm/html/run_b_branch.py @@ -0,0 +1,28 @@ +def html_it(): + """Run coverage with branches and make an HTML report for b.""" + import coverage + cov = coverage.coverage(branch=True) + cov.start() + import b # pragma: nested + cov.stop() # pragma: nested + cov.html_report(b, directory="../html_b_branch") + +runfunc(html_it, rundir="src") + +# HTML files will change often. Check that the sizes are reasonable, +# and check that certain key strings are in the output. +compare("gold_b_branch", "html_b_branch", size_within=10, file_pattern="*.html") +contains("html_b_branch/b.html", + "if x < 2", + "    a = 3", + "70%", + "8", + "exit", + "23   25", + ) +contains("html_b_branch/index.html", + "b", + "70%" + ) + +clean("html_b_branch") diff --git a/tests/farm/html/run_bom.py b/tests/farm/html/run_bom.py new file mode 100644 index 00000000..c35079be --- /dev/null +++ b/tests/farm/html/run_bom.py @@ -0,0 +1,21 @@ +import sys + +def html_it(): + """Run coverage and make an HTML report for bom.py.""" + import coverage + cov = coverage.coverage() + cov.start() + import bom # pragma: nested + cov.stop() # pragma: nested + cov.html_report(bom, directory="../html_bom") + +runfunc(html_it, rundir="src") + +# HTML files will change often. Check that the sizes are reasonable, +# and check that certain key strings are in the output. +compare("gold_bom", "html_bom", size_within=10, file_pattern="*.html") +contains("html_bom/bom.html", + ""3×4 = 12, ÷2 = 6±0"", + ) + +clean("html_bom") diff --git a/tests/farm/html/run_isolatin1.py b/tests/farm/html/run_isolatin1.py new file mode 100644 index 00000000..063e6e00 --- /dev/null +++ b/tests/farm/html/run_isolatin1.py @@ -0,0 +1,21 @@ +import sys + +def html_it(): + """Run coverage and make an HTML report for isolatin1.py.""" + import coverage + cov = coverage.coverage() + cov.start() + import isolatin1 # pragma: nested + cov.stop() # pragma: nested + cov.html_report(isolatin1, directory="../html_isolatin1") + +runfunc(html_it, rundir="src") + +# HTML files will change often. Check that the sizes are reasonable, +# and check that certain key strings are in the output. +compare("gold_isolatin1", "html_isolatin1", size_within=10, file_pattern="*.html") +contains("html_isolatin1/isolatin1.html", + ""3×4 = 12, ÷2 = 6±0"", + ) + +clean("html_isolatin1") diff --git a/tests/farm/html/run_omit_1.py b/tests/farm/html/run_omit_1.py new file mode 100644 index 00000000..a5556af2 --- /dev/null +++ b/tests/farm/html/run_omit_1.py @@ -0,0 +1,12 @@ +def html_it(): + """Run coverage and make an HTML report for main.""" + import coverage + cov = coverage.coverage() + cov.start() + import main # pragma: nested + cov.stop() # pragma: nested + cov.html_report(directory="../html_omit_1") + +runfunc(html_it, rundir="src") +compare("gold_omit_1", "html_omit_1", size_within=10, file_pattern="*.html") +clean("html_omit_1") diff --git a/tests/farm/html/run_omit_2.py b/tests/farm/html/run_omit_2.py new file mode 100644 index 00000000..19f0ebdc --- /dev/null +++ b/tests/farm/html/run_omit_2.py @@ -0,0 +1,12 @@ +def html_it(): + """Run coverage and make an HTML report for main.""" + import coverage + cov = coverage.coverage() + cov.start() + import main # pragma: nested + cov.stop() # pragma: nested + cov.html_report(directory="../html_omit_2", omit=["m1.py"]) + +runfunc(html_it, rundir="src") +compare("gold_omit_2", "html_omit_2", size_within=10, file_pattern="*.html") +clean("html_omit_2") diff --git a/tests/farm/html/run_omit_3.py b/tests/farm/html/run_omit_3.py new file mode 100644 index 00000000..87ab8c32 --- /dev/null +++ b/tests/farm/html/run_omit_3.py @@ -0,0 +1,12 @@ +def html_it(): + """Run coverage and make an HTML report for main.""" + import coverage + cov = coverage.coverage() + cov.start() + import main # pragma: nested + cov.stop() # pragma: nested + cov.html_report(directory="../html_omit_3", omit=["m1.py", "m2.py"]) + +runfunc(html_it, rundir="src") +compare("gold_omit_3", "html_omit_3", size_within=10, file_pattern="*.html") +clean("html_omit_3") diff --git a/tests/farm/html/run_omit_4.py b/tests/farm/html/run_omit_4.py new file mode 100644 index 00000000..ede223f8 --- /dev/null +++ b/tests/farm/html/run_omit_4.py @@ -0,0 +1,12 @@ +def html_it(): + """Run coverage and make an HTML report for main.""" + import coverage + cov = coverage.coverage(config_file="omit4.ini") + cov.start() + import main # pragma: nested + cov.stop() # pragma: nested + cov.html_report(directory="../html_omit_4") + +runfunc(html_it, rundir="src") +compare("gold_omit_4", "html_omit_4", size_within=10, file_pattern="*.html") +clean("html_omit_4") diff --git a/tests/farm/html/run_omit_5.py b/tests/farm/html/run_omit_5.py new file mode 100644 index 00000000..8da51994 --- /dev/null +++ b/tests/farm/html/run_omit_5.py @@ -0,0 +1,12 @@ +def html_it(): + """Run coverage and make an HTML report for main.""" + import coverage + cov = coverage.coverage(config_file="omit5.ini") + cov.start() + import main # pragma: nested + cov.stop() # pragma: nested + cov.html_report() + +runfunc(html_it, rundir="src") +compare("gold_omit_5", "html_omit_5", size_within=10, file_pattern="*.html") +clean("html_omit_5") diff --git a/tests/farm/html/run_other.py b/tests/farm/html/run_other.py new file mode 100644 index 00000000..72bb3ec1 --- /dev/null +++ b/tests/farm/html/run_other.py @@ -0,0 +1,26 @@ +def html_it(): + """Run coverage and make an HTML report for everything.""" + import coverage + cov = coverage.coverage() + cov.start() + import here # pragma: nested + cov.stop() # pragma: nested + cov.html_report(directory="../html_other") + +runfunc(html_it, rundir="src", addtopath="../othersrc") + +# Different platforms will name the "other" file differently. Rename it +import os, glob + +for p in glob.glob("html_other/*_other.html"): + os.rename(p, "html_other/blah_blah_other.html") + +# HTML files will change often. Check that the sizes are reasonable, +# and check that certain key strings are in the output. +compare("gold_other", "html_other", size_within=10, file_pattern="*.html") +contains("html_other/index.html", + "here", + "other.html'>", "other", + ) + +clean("html_other") diff --git a/tests/farm/html/run_partial.py b/tests/farm/html/run_partial.py new file mode 100644 index 00000000..41e6ba96 --- /dev/null +++ b/tests/farm/html/run_partial.py @@ -0,0 +1,32 @@ +import sys + +def html_it(): + """Run coverage and make an HTML report for partial.""" + import coverage + cov = coverage.coverage(branch=True) + cov.start() + import partial # pragma: nested + cov.stop() # pragma: nested + cov.html_report(partial, directory="../html_partial") + +runfunc(html_it, rundir="src") + +# HTML files will change often. Check that the sizes are reasonable, +# and check that certain key strings are in the output. +compare("gold_partial", "html_partial", size_within=10, file_pattern="*.html") +contains("html_partial/partial.html", + "

    ", + "

    ", + "

    ", + # The "if 0" and "if 1" statements are optimized away. + "

    ", + ) +contains("html_partial/index.html", + "partial", + ) +if sys.version_info >= (2, 4): + contains("html_partial/index.html", + "100%" + ) + +clean("html_partial") diff --git a/tests/farm/html/run_styled.py b/tests/farm/html/run_styled.py new file mode 100644 index 00000000..ac538ff5 --- /dev/null +++ b/tests/farm/html/run_styled.py @@ -0,0 +1,28 @@ +def html_it(): + """Run coverage and make an HTML report for a.""" + import coverage + cov = coverage.coverage() + cov.start() + import a # pragma: nested + cov.stop() # pragma: nested + cov.html_report(a, directory="../html_styled", extra_css="extra.css") + +runfunc(html_it, rundir="src") + +# HTML files will change often. Check that the sizes are reasonable, +# and check that certain key strings are in the output. +compare("gold_styled", "html_styled", size_within=10, file_pattern="*.html") +compare("gold_styled", "html_styled", size_within=10, file_pattern="*.css") +contains("html_styled/a.html", + "", + "if 1 < 2", + "    a = 3", + "67%" + ) +contains("html_styled/index.html", + "", + "a", + "67%" + ) + +clean("html_styled") diff --git a/tests/farm/html/run_tabbed.py b/tests/farm/html/run_tabbed.py new file mode 100644 index 00000000..0e9b5278 --- /dev/null +++ b/tests/farm/html/run_tabbed.py @@ -0,0 +1,24 @@ +def html_it(): + """Run coverage and make an HTML report for tabbed.""" + import coverage + cov = coverage.coverage() + cov.start() + import tabbed # pragma: nested + cov.stop() # pragma: nested + cov.html_report(tabbed, directory="../html_tabbed") + +runfunc(html_it, rundir="src") + +# Editors like to change things, make sure our source file still has tabs. +contains("src/tabbed.py", "\tif x:\t\t\t\t\t# look nice") + +contains("html_tabbed/tabbed.html", + ">        if " + "x:" + "                    " + "               " + "# look nice" + ) + +doesnt_contain("html_tabbed/tabbed.html", "\t") +clean("html_tabbed") diff --git a/tests/farm/html/run_unicode.py b/tests/farm/html/run_unicode.py new file mode 100644 index 00000000..cef26ee5 --- /dev/null +++ b/tests/farm/html/run_unicode.py @@ -0,0 +1,30 @@ +import sys + +def html_it(): + """Run coverage and make an HTML report for unicode.py.""" + import coverage + cov = coverage.coverage() + cov.start() + import unicode # pragma: nested + cov.stop() # pragma: nested + cov.html_report(unicode, directory="../html_unicode") + +runfunc(html_it, rundir="src") + +# HTML files will change often. Check that the sizes are reasonable, +# and check that certain key strings are in the output. +compare("gold_unicode", "html_unicode", size_within=10, file_pattern="*.html") +contains("html_unicode/unicode.html", + ""ʎd˙ǝbɐɹǝʌoɔ"", + ) + +if sys.maxunicode == 65535: + contains("html_unicode/unicode.html", + ""db40,dd00: x��"", + ) +else: + contains("html_unicode/unicode.html", + ""db40,dd00: x󠄀"", + ) + +clean("html_unicode") diff --git a/tests/farm/html/run_y_xml_branch.py b/tests/farm/html/run_y_xml_branch.py new file mode 100644 index 00000000..88a2e44e --- /dev/null +++ b/tests/farm/html/run_y_xml_branch.py @@ -0,0 +1,21 @@ +def xml_it(): + """Run coverage and make an XML report for y.""" + import coverage + cov = coverage.coverage(branch=True) + cov.start() + import y # pragma: nested + cov.stop() # pragma: nested + cov.xml_report(y, outfile="../xml_branch/coverage.xml") + +import os +if not os.path.exists("xml_branch"): + os.makedirs("xml_branch") + +runfunc(xml_it, rundir="src") + +compare("gold_y_xml_branch", "xml_branch", scrubs=[ + (r' timestamp="\d+"', ' timestamp="TIMESTAMP"'), + (r' version="[-.\w]+"', ' version="VERSION"'), + (r'/code/coverage/?[-.\w]*', '/code/coverage/VER'), + ]) +clean("xml_branch") diff --git a/tests/farm/html/src/a.py b/tests/farm/html/src/a.py new file mode 100644 index 00000000..9e71aebd --- /dev/null +++ b/tests/farm/html/src/a.py @@ -0,0 +1,7 @@ +# A test file for HTML reporting by coverage. + +if 1 < 2: + # Needed a < to look at HTML entities. + a = 3 +else: + a = 4 diff --git a/tests/farm/html/src/b.py b/tests/farm/html/src/b.py new file mode 100644 index 00000000..3bf73a9f --- /dev/null +++ b/tests/farm/html/src/b.py @@ -0,0 +1,29 @@ +# A test file for HTML reporting by coverage. + +def one(x): + # This will be a branch that misses the else. + if x < 2: + a = 3 + else: + a = 4 + +one(1) + +def two(x): + # A missed else that branches to "exit" + if x: + a = 5 + +two(1) + +def three(): + try: + # This if has two branches, *neither* one taken. + if name_error_this_variable_doesnt_exist: + a = 1 + else: + a = 2 + except: + pass + +three() diff --git a/tests/farm/html/src/bom.py b/tests/farm/html/src/bom.py new file mode 100644 index 00000000..2db8b717 --- /dev/null +++ b/tests/farm/html/src/bom.py @@ -0,0 +1,11 @@ +# A python source file in utf-8, with BOM +math = "3×4 = 12, ÷2 = 6±0" + +import sys + +if sys.version_info >= (3, 0): + assert len(math) == 18 + assert len(math.encode('utf-8')) == 21 +else: + assert len(math) == 21 + assert len(math.decode('utf-8')) == 18 diff --git a/tests/farm/html/src/coverage.xml b/tests/farm/html/src/coverage.xml new file mode 100644 index 00000000..128cf750 --- /dev/null +++ b/tests/farm/html/src/coverage.xml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + diff --git a/tests/farm/html/src/extra.css b/tests/farm/html/src/extra.css new file mode 100644 index 00000000..46c41fcd --- /dev/null +++ b/tests/farm/html/src/extra.css @@ -0,0 +1 @@ +/* Doesn't matter what goes in here, it gets copied. */ diff --git a/tests/farm/html/src/here.py b/tests/farm/html/src/here.py new file mode 100644 index 00000000..d0d26ea7 --- /dev/null +++ b/tests/farm/html/src/here.py @@ -0,0 +1,8 @@ +# A test file for HTML reporting by coverage. + +import other + +if 1 < 2: + h = 3 +else: + h = 4 diff --git a/tests/farm/html/src/isolatin1.py b/tests/farm/html/src/isolatin1.py new file mode 100644 index 00000000..057c097b --- /dev/null +++ b/tests/farm/html/src/isolatin1.py @@ -0,0 +1,5 @@ +# A python source file in another encoding. +# -*- coding: iso8859-1 -*- + +math = "34 = 12, 2 = 60" +assert len(math) == 18 diff --git a/tests/farm/html/src/m1.py b/tests/farm/html/src/m1.py new file mode 100644 index 00000000..927e1f6b --- /dev/null +++ b/tests/farm/html/src/m1.py @@ -0,0 +1,2 @@ +m1a = 1 +m1b = 2 diff --git a/tests/farm/html/src/m2.py b/tests/farm/html/src/m2.py new file mode 100644 index 00000000..ffddf6cf --- /dev/null +++ b/tests/farm/html/src/m2.py @@ -0,0 +1,2 @@ +m2a = 1 +m2b = 2 diff --git a/tests/farm/html/src/m3.py b/tests/farm/html/src/m3.py new file mode 100644 index 00000000..395d7d25 --- /dev/null +++ b/tests/farm/html/src/m3.py @@ -0,0 +1,2 @@ +m3a = 1 +m3b = 2 diff --git a/tests/farm/html/src/main.py b/tests/farm/html/src/main.py new file mode 100644 index 00000000..ce894465 --- /dev/null +++ b/tests/farm/html/src/main.py @@ -0,0 +1,10 @@ +import m1 +import m2 +import m3 + +a = 5 +b = 6 + +assert m1.m1a == 1 +assert m2.m2a == 1 +assert m3.m3a == 1 diff --git a/tests/farm/html/src/omit4.ini b/tests/farm/html/src/omit4.ini new file mode 100644 index 00000000..6821ecda --- /dev/null +++ b/tests/farm/html/src/omit4.ini @@ -0,0 +1,2 @@ +[report] +omit = m2.py diff --git a/tests/farm/html/src/omit5.ini b/tests/farm/html/src/omit5.ini new file mode 100644 index 00000000..7e32b414 --- /dev/null +++ b/tests/farm/html/src/omit5.ini @@ -0,0 +1,8 @@ +[report] +omit = + fooey + gooey, m[23]*, kablooey + helloworld + +[html] +directory = ../html_omit_5 diff --git a/tests/farm/html/src/partial.py b/tests/farm/html/src/partial.py new file mode 100644 index 00000000..8d62f5c5 --- /dev/null +++ b/tests/farm/html/src/partial.py @@ -0,0 +1,18 @@ +# partial branches + +a = 3 + +while True: + break + +while 1: + break + +while a: # pragma: no branch + break + +if 0: + never_happen() + +if 1: + a = 13 diff --git a/tests/farm/html/src/run_a_xml_2.ini b/tests/farm/html/src/run_a_xml_2.ini new file mode 100644 index 00000000..8d28f97b --- /dev/null +++ b/tests/farm/html/src/run_a_xml_2.ini @@ -0,0 +1,3 @@ +# Put all the XML output in xml_2 +[xml] +output = ../xml_2/coverage.xml diff --git a/tests/farm/html/src/tabbed.py b/tests/farm/html/src/tabbed.py new file mode 100644 index 00000000..2035852f --- /dev/null +++ b/tests/farm/html/src/tabbed.py @@ -0,0 +1,7 @@ +# This file should have tabs. +x = 1 +if x: + a = "Tabbed" # Aligned comments + if x: # look nice + b = "No spaces" # when they + c = "Done" # line up. diff --git a/tests/farm/html/src/unicode.py b/tests/farm/html/src/unicode.py new file mode 100644 index 00000000..f6a9a052 --- /dev/null +++ b/tests/farm/html/src/unicode.py @@ -0,0 +1,5 @@ +# A python source file with exotic characters +# -*- coding: utf-8 -*- + +upside_down = "ʎd˙ǝbɐɹǝʌoɔ" +surrogate = "db40,dd00: x󠄀" diff --git a/tests/farm/html/src/y.py b/tests/farm/html/src/y.py new file mode 100644 index 00000000..af7c9689 --- /dev/null +++ b/tests/farm/html/src/y.py @@ -0,0 +1,9 @@ +# A test file for XML reporting by coverage. + +def choice(x): + if x < 2: + return 3 + else: + return 4 + +assert choice(1) == 3 diff --git a/tests/farm/run/run_chdir.py b/tests/farm/run/run_chdir.py new file mode 100644 index 00000000..f459f500 --- /dev/null +++ b/tests/farm/run/run_chdir.py @@ -0,0 +1,12 @@ +copy("src", "out") +run(""" + coverage run chdir.py + coverage -r + """, rundir="out", outfile="stdout.txt") +contains("out/stdout.txt", + "Line One", + "Line Two", + "chdir" + ) +doesnt_contain("out/stdout.txt", "No such file or directory") +clean("out") diff --git a/tests/farm/run/run_timid.py b/tests/farm/run/run_timid.py new file mode 100644 index 00000000..ce78fff1 --- /dev/null +++ b/tests/farm/run/run_timid.py @@ -0,0 +1,60 @@ +# Test that the --timid command line argument properly swaps the tracer +# function for a simpler one. +# +# This is complicated by the fact that the tests are run twice for each +# version: once with a compiled C-based trace function, and once without +# it, to also test the Python trace function. So this test has to examine +# an environment variable set in igor.py to know whether to expect to see +# the C trace function or not. + +import os + +# When meta-coverage testing, this test doesn't work, because it finds +# coverage.py's own trace function. +if os.environ.get('COVERAGE_COVERAGE', ''): + skip("Can't test timid during coverage measurement.") + +copy("src", "out") +run(""" + python showtrace.py none + coverage -e -x showtrace.py regular + coverage -e -x --timid showtrace.py timid + """, rundir="out", outfile="showtraceout.txt") + +# When running without coverage, no trace function +# When running timidly, the trace function is always Python. +contains("out/showtraceout.txt", + "none None", + "timid PyTracer", + ) + +if os.environ.get('COVERAGE_TEST_TRACER', 'c') == 'c': + # If the C trace function is being tested, then regular running should have + # the C function, which registers itself as f_trace. + contains("out/showtraceout.txt", "regular CTracer") +else: + # If the Python trace function is being tested, then regular running will + # also show the Python function. + contains("out/showtraceout.txt", "regular PyTracer") + +# Try the environment variable. +old_opts = os.environ.get('COVERAGE_OPTIONS') +os.environ['COVERAGE_OPTIONS'] = '--timid' + +run(""" + coverage -e -x showtrace.py regular + coverage -e -x --timid showtrace.py timid + """, rundir="out", outfile="showtraceout.txt") + +contains("out/showtraceout.txt", + "none None", + "timid PyTracer", + "regular PyTracer", + ) + +if old_opts: + os.environ['COVERAGE_OPTIONS'] = old_opts +else: + del os.environ['COVERAGE_OPTIONS'] + +clean("out") diff --git a/tests/farm/run/run_xxx.py b/tests/farm/run/run_xxx.py new file mode 100644 index 00000000..19e94a42 --- /dev/null +++ b/tests/farm/run/run_xxx.py @@ -0,0 +1,12 @@ +copy("src", "out") +run(""" + coverage -e -x xxx + coverage -r + """, rundir="out", outfile="stdout.txt") +contains("out/stdout.txt", + "xxx: 3 4 0 7", + "\nxxx ", # The reporting line for xxx + " 7 1 86%" # The reporting data for xxx + ) +doesnt_contain("out/stdout.txt", "No such file or directory") +clean("out") diff --git a/tests/farm/run/src/chdir.py b/tests/farm/run/src/chdir.py new file mode 100644 index 00000000..6d834924 --- /dev/null +++ b/tests/farm/run/src/chdir.py @@ -0,0 +1,4 @@ +import os +print("Line One") +os.chdir("subdir") +print("Line Two") diff --git a/tests/farm/run/src/showtrace.py b/tests/farm/run/src/showtrace.py new file mode 100644 index 00000000..e97412e0 --- /dev/null +++ b/tests/farm/run/src/showtrace.py @@ -0,0 +1,23 @@ +# Show the current frame's trace function, so that we can test what the +# command-line options do to the trace function used. + +import sys + +# Show what the trace function is. If a C-based function is used, then f_trace +# may be None. +trace_fn = sys._getframe(0).f_trace +if trace_fn is None: + trace_name = "None" +else: + # Get the name of the tracer class. Py3k has a different way to get it. + try: + trace_name = trace_fn.im_class.__name__ + except AttributeError: + try: + trace_name = trace_fn.__self__.__class__.__name__ + except AttributeError: + # A C-based function could also manifest as an f_trace value + # which doesn't have im_class or __self__. + trace_name = trace_fn.__class__.__name__ + +print("%s %s" % (sys.argv[1], trace_name)) diff --git a/tests/farm/run/src/subdir/placeholder b/tests/farm/run/src/subdir/placeholder new file mode 100644 index 00000000..e69de29b diff --git a/tests/farm/run/src/xxx b/tests/farm/run/src/xxx new file mode 100644 index 00000000..8f727f08 --- /dev/null +++ b/tests/farm/run/src/xxx @@ -0,0 +1,8 @@ +# This is a python file though it doesn't look like it, like a main script. +a = b = c = d = 0 +a = 3 +b = 4 +if not b: + c = 6 +d = 7 +print("xxx: %r %r %r %r" % (a, b, c, d)) diff --git a/tests/js/index.html b/tests/js/index.html new file mode 100644 index 00000000..60bdb30a --- /dev/null +++ b/tests/js/index.html @@ -0,0 +1,52 @@ + + + + Coverage.py Javascript Test Suite + + + + + + + + + + + + + + + + + + + + + +

    Coverage.py Javascript Test Suite

    +

    +
    +

    +
      +
      + + diff --git a/tests/js/tests.js b/tests/js/tests.js new file mode 100644 index 00000000..73b4ce2b --- /dev/null +++ b/tests/js/tests.js @@ -0,0 +1,204 @@ +// Tests of coverage.py HTML report chunk navigation. +/*global coverage, test, module, equals, jQuery, $ */ + +// Test helpers + +function selection_is(sel) { + raw_selection_is(sel, true); +} + +function raw_selection_is(sel, check_highlight) { + var beg = sel[0], end = sel[1]; + equals(coverage.sel_begin, beg); + equals(coverage.sel_end, end); + if (check_highlight) { + equals(coverage.code_container().find(".highlight").length, end-beg); + } +} + +function build_fixture(spec) { + var i, data; + $("#fixture-template").tmpl().appendTo("#qunit-fixture"); + for (i = 0; i < spec.length; i++) { + data = {number: i+1, klass: spec.substr(i, 1)}; + $("#lineno-template").tmpl(data).appendTo("#qunit-fixture .linenos"); + $("#text-template").tmpl(data).appendTo("#qunit-fixture .text"); + } + coverage.pyfile_ready(jQuery); +} + +// Tests + +// Zero-chunk tests + +module("Zero-chunk navigation", { + setup: function () { + build_fixture("wwww"); + } +}); + +test("set_sel defaults", function () { + coverage.set_sel(2); + equals(coverage.sel_begin, 2); + equals(coverage.sel_end, 3); +}); + +test("No first chunk to select", function () { + coverage.to_first_chunk(); +}); + +// One-chunk tests + +$.each([ + ['rrrrr', [1,6]], + ['r', [1,2]], + ['wwrrrr', [3,7]], + ['wwrrrrww', [3,7]], + ['rrrrww', [1,5]] +], function (i, params) { + + // Each of these tests uses a fixture with one highlighted chunks. + var id = params[0]; + var c1 = params[1]; + + module("One-chunk navigation - " + id, { + setup: function () { + build_fixture(id); + } + }); + + test("First chunk", function () { + coverage.to_first_chunk(); + selection_is(c1); + }); + + test("Next chunk is first chunk", function () { + coverage.to_next_chunk(); + selection_is(c1); + }); + + test("There is no next chunk", function () { + coverage.to_first_chunk(); + coverage.to_next_chunk(); + selection_is(c1); + }); + + test("There is no prev chunk", function () { + coverage.to_first_chunk(); + coverage.to_prev_chunk(); + selection_is(c1); + }); +}); + +// Two-chunk tests + +$.each([ + ['rrwwrrrr', [1,3], [5,9]], + ['rb', [1,2], [2,3]], + ['rbbbbbbbbbb', [1,2], [2,12]], + ['rrrrrrrrrrb', [1,11], [11,12]], + ['wrrwrrrrw', [2,4], [5,9]], + ['rrrbbb', [1,4], [4,7]] +], function (i, params) { + + // Each of these tests uses a fixture with two highlighted chunks. + var id = params[0]; + var c1 = params[1]; + var c2 = params[2]; + + module("Two-chunk navigation - " + id, { + setup: function () { + build_fixture(id); + } + }); + + test("First chunk", function () { + coverage.to_first_chunk(); + selection_is(c1); + }); + + test("Next chunk is first chunk", function () { + coverage.to_next_chunk(); + selection_is(c1); + }); + + test("Move to next chunk", function () { + coverage.to_first_chunk(); + coverage.to_next_chunk(); + selection_is(c2); + }); + + test("Move to first chunk", function () { + coverage.to_first_chunk(); + coverage.to_next_chunk(); + coverage.to_first_chunk(); + selection_is(c1); + }); + + test("Move to previous chunk", function () { + coverage.to_first_chunk(); + coverage.to_next_chunk(); + coverage.to_prev_chunk(); + selection_is(c1); + }); + + test("Next doesn't move after last chunk", function () { + coverage.to_first_chunk(); + coverage.to_next_chunk(); + coverage.to_next_chunk(); + selection_is(c2); + }); + + test("Prev doesn't move before first chunk", function () { + coverage.to_first_chunk(); + coverage.to_next_chunk(); + coverage.to_prev_chunk(); + coverage.to_prev_chunk(); + selection_is(c1); + }); + +}); + +module("Miscellaneous"); + +test("Jump from a line selected", function () { + build_fixture("rrwwrr"); + coverage.set_sel(3); + coverage.to_next_chunk(); + selection_is([5,7]); +}); + +// Tests of select_line_or_chunk. + +$.each([ + // The data for each test: a spec for the fixture to build, and an array + // of the selection that will be selected by select_line_or_chunk for + // each line in the fixture. + ['rrwwrr', [[1,3], [1,3], [3,4], [4,5], [5,7], [5,7]]], + ['rb', [[1,2], [2,3]]], + ['r', [[1,2]]], + ['w', [[1,2]]], + ['www', [[1,2], [2,3], [3,4]]], + ['wwwrrr', [[1,2], [2,3], [3,4], [4,7], [4,7], [4,7]]], + ['rrrwww', [[1,4], [1,4], [1,4], [4,5], [5,6], [6,7]]], + ['rrrbbb', [[1,4], [1,4], [1,4], [4,7], [4,7], [4,7]]] +], function (i, params) { + + // Each of these tests uses a fixture with two highlighted chunks. + var id = params[0]; + var sels = params[1]; + + module("Select line or chunk - " + id, { + setup: function () { + build_fixture(id); + } + }); + + $.each(sels, function (i, sel) { + i++; + test("Select line " + i, function () { + coverage.select_line_or_chunk(i); + raw_selection_is(sel); + }); + }); +}); diff --git a/tests/modules/aa/__init__.py b/tests/modules/aa/__init__.py new file mode 100644 index 00000000..77593d8f --- /dev/null +++ b/tests/modules/aa/__init__.py @@ -0,0 +1 @@ +# aa diff --git a/tests/modules/aa/afile.odd.py b/tests/modules/aa/afile.odd.py new file mode 100644 index 00000000..c6f49e18 --- /dev/null +++ b/tests/modules/aa/afile.odd.py @@ -0,0 +1 @@ +# afile.odd.py diff --git a/tests/modules/aa/afile.py b/tests/modules/aa/afile.py new file mode 100644 index 00000000..3f0e38d1 --- /dev/null +++ b/tests/modules/aa/afile.py @@ -0,0 +1 @@ +# afile.py diff --git a/tests/modules/aa/bb.odd/bfile.py b/tests/modules/aa/bb.odd/bfile.py new file mode 100644 index 00000000..90875404 --- /dev/null +++ b/tests/modules/aa/bb.odd/bfile.py @@ -0,0 +1 @@ +# bfile.py diff --git a/tests/modules/aa/bb/__init__.py b/tests/modules/aa/bb/__init__.py new file mode 100644 index 00000000..ffbe6240 --- /dev/null +++ b/tests/modules/aa/bb/__init__.py @@ -0,0 +1 @@ +# bb diff --git a/tests/modules/aa/bb/bfile.odd.py b/tests/modules/aa/bb/bfile.odd.py new file mode 100644 index 00000000..b45cba8c --- /dev/null +++ b/tests/modules/aa/bb/bfile.odd.py @@ -0,0 +1 @@ +# bfile.odd.py diff --git a/tests/modules/aa/bb/bfile.py b/tests/modules/aa/bb/bfile.py new file mode 100644 index 00000000..90875404 --- /dev/null +++ b/tests/modules/aa/bb/bfile.py @@ -0,0 +1 @@ +# bfile.py diff --git a/tests/modules/aa/bb/cc/__init__.py b/tests/modules/aa/bb/cc/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/modules/aa/bb/cc/cfile.py b/tests/modules/aa/bb/cc/cfile.py new file mode 100644 index 00000000..79764751 --- /dev/null +++ b/tests/modules/aa/bb/cc/cfile.py @@ -0,0 +1 @@ +# cfile.py diff --git a/tests/modules/aa/zfile.py b/tests/modules/aa/zfile.py new file mode 100644 index 00000000..924f9b77 --- /dev/null +++ b/tests/modules/aa/zfile.py @@ -0,0 +1 @@ +# zfile.py diff --git a/tests/modules/covmod1.py b/tests/modules/covmod1.py new file mode 100644 index 00000000..b3f5e5f2 --- /dev/null +++ b/tests/modules/covmod1.py @@ -0,0 +1,3 @@ +# covmod1.py: Simplest module for testing. +i = 1 +i += 1 diff --git a/tests/modules/pkg1/__init__.py b/tests/modules/pkg1/__init__.py new file mode 100644 index 00000000..2dfeb9c1 --- /dev/null +++ b/tests/modules/pkg1/__init__.py @@ -0,0 +1,3 @@ +# This __init__.py has a module-level docstring, which is counted as a +# statement. +"""A simple package for testing with.""" diff --git a/tests/modules/pkg1/__main__.py b/tests/modules/pkg1/__main__.py new file mode 100644 index 00000000..66ce5956 --- /dev/null +++ b/tests/modules/pkg1/__main__.py @@ -0,0 +1,3 @@ +# Used in the tests for run_python_module +import sys +print("pkg1.__main__: passed %s" % sys.argv[1]) diff --git a/tests/modules/pkg1/p1a.py b/tests/modules/pkg1/p1a.py new file mode 100644 index 00000000..be5fcdd3 --- /dev/null +++ b/tests/modules/pkg1/p1a.py @@ -0,0 +1,5 @@ +import os, sys + +# Invoke functions in os and sys so we can see if we measure code there. +x = sys.getcheckinterval() +y = os.getcwd() diff --git a/tests/modules/pkg1/p1b.py b/tests/modules/pkg1/p1b.py new file mode 100644 index 00000000..59d6fb54 --- /dev/null +++ b/tests/modules/pkg1/p1b.py @@ -0,0 +1,3 @@ +x = 1 +y = 2 +z = 3 diff --git a/tests/modules/pkg1/p1c.py b/tests/modules/pkg1/p1c.py new file mode 100644 index 00000000..a9aeef04 --- /dev/null +++ b/tests/modules/pkg1/p1c.py @@ -0,0 +1,3 @@ +a = 1 +b = 2 +c = 3 diff --git a/tests/modules/pkg1/runmod2.py b/tests/modules/pkg1/runmod2.py new file mode 100644 index 00000000..b52964cb --- /dev/null +++ b/tests/modules/pkg1/runmod2.py @@ -0,0 +1,3 @@ +# Used in the tests for run_python_module +import sys +print("runmod2: passed %s" % sys.argv[1]) diff --git a/tests/modules/pkg1/sub/__init__.py b/tests/modules/pkg1/sub/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/modules/pkg1/sub/__main__.py b/tests/modules/pkg1/sub/__main__.py new file mode 100644 index 00000000..b5be9f1c --- /dev/null +++ b/tests/modules/pkg1/sub/__main__.py @@ -0,0 +1,3 @@ +# Used in the tests for run_python_module +import sys +print("pkg1.sub.__main__: passed %s" % sys.argv[1]) diff --git a/tests/modules/pkg1/sub/ps1a.py b/tests/modules/pkg1/sub/ps1a.py new file mode 100644 index 00000000..4b6a15cc --- /dev/null +++ b/tests/modules/pkg1/sub/ps1a.py @@ -0,0 +1,3 @@ +d = 1 +e = 2 +f = 3 diff --git a/tests/modules/pkg1/sub/runmod3.py b/tests/modules/pkg1/sub/runmod3.py new file mode 100644 index 00000000..3a1ad155 --- /dev/null +++ b/tests/modules/pkg1/sub/runmod3.py @@ -0,0 +1,3 @@ +# Used in the tests for run_python_module +import sys +print("runmod3: passed %s" % sys.argv[1]) diff --git a/tests/modules/pkg2/__init__.py b/tests/modules/pkg2/__init__.py new file mode 100644 index 00000000..090efbf5 --- /dev/null +++ b/tests/modules/pkg2/__init__.py @@ -0,0 +1,2 @@ +# This is an __init__.py file, with no executable statements in it. +# This comment shouldn't confuse the parser. diff --git a/tests/modules/pkg2/p2a.py b/tests/modules/pkg2/p2a.py new file mode 100644 index 00000000..b606711d --- /dev/null +++ b/tests/modules/pkg2/p2a.py @@ -0,0 +1,3 @@ +q = 1 +r = 1 +s = 1 diff --git a/tests/modules/pkg2/p2b.py b/tests/modules/pkg2/p2b.py new file mode 100644 index 00000000..7a34e2c6 --- /dev/null +++ b/tests/modules/pkg2/p2b.py @@ -0,0 +1,3 @@ +t = 1 +u = 1 +v = 1 diff --git a/tests/modules/runmod1.py b/tests/modules/runmod1.py new file mode 100644 index 00000000..671d81ef --- /dev/null +++ b/tests/modules/runmod1.py @@ -0,0 +1,3 @@ +# Used in the tests for run_python_module +import sys +print("runmod1: passed %s" % sys.argv[1]) diff --git a/tests/modules/usepkgs.py b/tests/modules/usepkgs.py new file mode 100644 index 00000000..93c7d904 --- /dev/null +++ b/tests/modules/usepkgs.py @@ -0,0 +1,4 @@ +import pkg1.p1a, pkg1.p1b +import pkg2.p2a, pkg2.p2b +import othermods.othera, othermods.otherb +import othermods.sub.osa, othermods.sub.osb diff --git a/tests/moremodules/othermods/__init__.py b/tests/moremodules/othermods/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/moremodules/othermods/othera.py b/tests/moremodules/othermods/othera.py new file mode 100644 index 00000000..78896928 --- /dev/null +++ b/tests/moremodules/othermods/othera.py @@ -0,0 +1,2 @@ +o = 1 +p = 2 diff --git a/tests/moremodules/othermods/otherb.py b/tests/moremodules/othermods/otherb.py new file mode 100644 index 00000000..2bd8a441 --- /dev/null +++ b/tests/moremodules/othermods/otherb.py @@ -0,0 +1,2 @@ +q = 3 +r = 4 diff --git a/tests/moremodules/othermods/sub/__init__.py b/tests/moremodules/othermods/sub/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/tests/moremodules/othermods/sub/osa.py b/tests/moremodules/othermods/sub/osa.py new file mode 100644 index 00000000..0139d28b --- /dev/null +++ b/tests/moremodules/othermods/sub/osa.py @@ -0,0 +1,2 @@ +s = 5 +t = 6 diff --git a/tests/moremodules/othermods/sub/osb.py b/tests/moremodules/othermods/sub/osb.py new file mode 100644 index 00000000..b024b148 --- /dev/null +++ b/tests/moremodules/othermods/sub/osb.py @@ -0,0 +1,2 @@ +u = 7 +v = 8 diff --git a/tests/osinfo.py b/tests/osinfo.py new file mode 100644 index 00000000..25c3a7c6 --- /dev/null +++ b/tests/osinfo.py @@ -0,0 +1,71 @@ +"""OS information for testing.""" + +import sys + +if sys.version_info >= (2, 5) and sys.platform == 'win32': + # Windows implementation + def process_ram(): + """How much RAM is this process using? (Windows)""" + import ctypes + # lifted from: + # lists.ubuntu.com/archives/bazaar-commits/2009-February/011990.html + class PROCESS_MEMORY_COUNTERS_EX(ctypes.Structure): + """Used by GetProcessMemoryInfo""" + _fields_ = [('cb', ctypes.c_ulong), + ('PageFaultCount', ctypes.c_ulong), + ('PeakWorkingSetSize', ctypes.c_size_t), + ('WorkingSetSize', ctypes.c_size_t), + ('QuotaPeakPagedPoolUsage', ctypes.c_size_t), + ('QuotaPagedPoolUsage', ctypes.c_size_t), + ('QuotaPeakNonPagedPoolUsage', ctypes.c_size_t), + ('QuotaNonPagedPoolUsage', ctypes.c_size_t), + ('PagefileUsage', ctypes.c_size_t), + ('PeakPagefileUsage', ctypes.c_size_t), + ('PrivateUsage', ctypes.c_size_t), + ] + + mem_struct = PROCESS_MEMORY_COUNTERS_EX() + ret = ctypes.windll.psapi.GetProcessMemoryInfo( + ctypes.windll.kernel32.GetCurrentProcess(), + ctypes.byref(mem_struct), + ctypes.sizeof(mem_struct) + ) + if not ret: + return 0 + return mem_struct.PrivateUsage + +elif sys.platform == 'linux2': + # Linux implementation + import os + + _scale = {'kb': 1024, 'mb': 1024*1024} + + def _VmB(key): + """Read the /proc/PID/status file to find memory use.""" + try: + # get pseudo file /proc//status + t = open('/proc/%d/status' % os.getpid()) + try: + v = t.read() + finally: + t.close() + except IOError: + return 0 # non-Linux? + # get VmKey line e.g. 'VmRSS: 9999 kB\n ...' + i = v.index(key) + v = v[i:].split(None, 3) + if len(v) < 3: + return 0 # invalid format? + # convert Vm value to bytes + return int(float(v[1]) * _scale[v[2].lower()]) + + def process_ram(): + """How much RAM is this process using? (Linux implementation)""" + return _VmB('VmRSS') + + +else: + # Don't have an implementation, at least satisfy the interface. + def process_ram(): + """How much RAM is this process using? (placebo implementation)""" + return 0 diff --git a/tests/qunit/jquery.tmpl.min.js b/tests/qunit/jquery.tmpl.min.js new file mode 100644 index 00000000..7438b2ca --- /dev/null +++ b/tests/qunit/jquery.tmpl.min.js @@ -0,0 +1,10 @@ +/* + * jQuery Templates Plugin 1.0.0pre + * http://github.com/jquery/jquery-tmpl + * Requires jQuery 1.4.2 + * + * Copyright Software Freedom Conservancy, Inc. + * Dual licensed under the MIT or GPL Version 2 licenses. + * http://jquery.org/license + */ +(function(a){var r=a.fn.domManip,d="_tmplitem",q=/^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /,b={},f={},e,p={key:0,data:{}},i=0,c=0,l=[];function g(g,d,h,e){var c={data:e||(e===0||e===false)?e:d?d.data:{},_wrap:d?d._wrap:null,tmpl:null,parent:d||null,nodes:[],calls:u,nest:w,wrap:x,html:v,update:t};g&&a.extend(c,g,{nodes:[],parent:d});if(h){c.tmpl=h;c._ctnt=c._ctnt||c.tmpl(a,c);c.key=++i;(l.length?f:b)[i]=c}return c}a.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(f,d){a.fn[f]=function(n){var g=[],i=a(n),k,h,m,l,j=this.length===1&&this[0].parentNode;e=b||{};if(j&&j.nodeType===11&&j.childNodes.length===1&&i.length===1){i[d](this[0]);g=this}else{for(h=0,m=i.length;h0?this.clone(true):this).get();a(i[h])[d](k);g=g.concat(k)}c=0;g=this.pushStack(g,f,i.selector)}l=e;e=null;a.tmpl.complete(l);return g}});a.fn.extend({tmpl:function(d,c,b){return a.tmpl(this[0],d,c,b)},tmplItem:function(){return a.tmplItem(this[0])},template:function(b){return a.template(b,this[0])},domManip:function(d,m,k){if(d[0]&&a.isArray(d[0])){var g=a.makeArray(arguments),h=d[0],j=h.length,i=0,f;while(i").join(">").split('"').join(""").split("'").join("'")}});a.extend(a.tmpl,{tag:{tmpl:{_default:{$2:"null"},open:"if($notnull_1){__=__.concat($item.nest($1,$2));}"},wrap:{_default:{$2:"null"},open:"$item.calls(__,$1,$2);__=[];",close:"call=$item.calls();__=call._.concat($item.wrap(call,__));"},each:{_default:{$2:"$index, $value"},open:"if($notnull_1){$.each($1a,function($2){with(this){",close:"}});}"},"if":{open:"if(($notnull_1) && $1a){",close:"}"},"else":{_default:{$1:"true"},open:"}else if(($notnull_1) && $1a){"},html:{open:"if($notnull_1){__.push($1a);}"},"=":{_default:{$1:"$data"},open:"if($notnull_1){__.push($.encode($1a));}"},"!":{open:""}},complete:function(){b={}},afterManip:function(f,b,d){var e=b.nodeType===11?a.makeArray(b.childNodes):b.nodeType===1?[b]:[];d.call(f,b);m(e);c++}});function j(e,g,f){var b,c=f?a.map(f,function(a){return typeof a==="string"?e.key?a.replace(/(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g,"$1 "+d+'="'+e.key+'" $2'):a:j(a,e,a._ctnt)}):e;if(g)return c;c=c.join("");c.replace(/^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/,function(f,c,e,d){b=a(e).get();m(b);if(c)b=k(c).concat(b);if(d)b=b.concat(k(d))});return b?b:k(c)}function k(c){var b=document.createElement("div");b.innerHTML=c;return a.makeArray(b.childNodes)}function o(b){return new Function("jQuery","$item","var $=jQuery,call,__=[],$data=$item.data;with($data){__.push('"+a.trim(b).replace(/([\\'])/g,"\\$1").replace(/[\r\t\n]/g," ").replace(/\$\{([^\}]*)\}/g,"{{= $1}}").replace(/\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g,function(m,l,k,g,b,c,d){var j=a.tmpl.tag[k],i,e,f;if(!j)throw"Unknown template tag: "+k;i=j._default||[];if(c&&!/\w$/.test(b)){b+=c;c=""}if(b){b=h(b);d=d?","+h(d)+")":c?")":"";e=c?b.indexOf(".")>-1?b+h(c):"("+b+").call($item"+d:b;f=c?e:"(typeof("+b+")==='function'?("+b+").call($item):("+b+"))"}else f=e=i.$1||"null";g=h(g);return"');"+j[l?"close":"open"].split("$notnull_1").join(b?"typeof("+b+")!=='undefined' && ("+b+")!=null":"true").split("$1a").join(f).split("$1").join(e).split("$2").join(g||i.$2||"")+"__.push('"})+"');}return __;")}function n(c,b){c._wrap=j(c,true,a.isArray(b)?b:[q.test(b)?b:a(b).html()]).join("")}function h(a){return a?a.replace(/\\'/g,"'").replace(/\\\\/g,"\\"):null}function s(b){var a=document.createElement("div");a.appendChild(b.cloneNode(true));return a.innerHTML}function m(o){var n="_"+c,k,j,l={},e,p,h;for(e=0,p=o.length;e=0;h--)m(j[h]);m(k)}function m(j){var p,h=j,k,e,m;if(m=j.getAttribute(d)){while(h.parentNode&&(h=h.parentNode).nodeType===1&&!(p=h.getAttribute(d)));if(p!==m){h=h.parentNode?h.nodeType===11?0:h.getAttribute(d)||0:0;if(!(e=b[m])){e=f[m];e=g(e,b[h]||f[h]);e.key=++i;b[i]=e}c&&o(m)}j.removeAttribute(d)}else if(c&&(e=a.data(j,"tmplItem"))){o(e.key);b[e.key]=e;h=a.data(j.parentNode,"tmplItem");h=h?h.key:0}if(e){k=e;while(k&&k.key!=h){k.nodes.push(j);k=k.parent}delete e._ctnt;delete e._wrap;a.data(j,"tmplItem",e)}function o(a){a=a+n;e=l[a]=l[a]||g(e,b[e.parent.key+n]||e.parent)}}}function u(a,d,c,b){if(!a)return l.pop();l.push({_:a,tmpl:d,item:this,data:c,options:b})}function w(d,c,b){return a.tmpl(a.template(d),c,b,this)}function x(b,d){var c=b.options||{};c.wrapped=d;return a.tmpl(a.template(b.tmpl),b.data,c,b.item)}function v(d,c){var b=this._wrap;return a.map(a(a.isArray(b)?b.join(""):b).filter(d||"*"),function(a){return c?a.innerText||a.textContent:a.outerHTML||s(a)})}function t(){var b=this.nodes;a.tmpl(null,null,null,this).insertBefore(b[0]);a(b).remove()}})(jQuery); \ No newline at end of file diff --git a/tests/qunit/qunit.css b/tests/qunit/qunit.css new file mode 100644 index 00000000..b3c6db52 --- /dev/null +++ b/tests/qunit/qunit.css @@ -0,0 +1,225 @@ +/** + * QUnit - A JavaScript Unit Testing Framework + * + * http://docs.jquery.com/QUnit + * + * Copyright (c) 2011 John Resig, Jörn Zaefferer + * Dual licensed under the MIT (MIT-LICENSE.txt) + * or GPL (GPL-LICENSE.txt) licenses. + */ + +/** Font Family and Sizes */ + +#qunit-tests, #qunit-header, #qunit-banner, #qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult { + font-family: "Helvetica Neue Light", "HelveticaNeue-Light", "Helvetica Neue", Calibri, Helvetica, Arial, sans-serif; +} + +#qunit-testrunner-toolbar, #qunit-userAgent, #qunit-testresult, #qunit-tests li { font-size: small; } +#qunit-tests { font-size: smaller; } + + +/** Resets */ + +#qunit-tests, #qunit-tests ol, #qunit-header, #qunit-banner, #qunit-userAgent, #qunit-testresult { + margin: 0; + padding: 0; +} + + +/** Header */ + +#qunit-header { + padding: 0.5em 0 0.5em 1em; + + color: #8699a4; + background-color: #0d3349; + + font-size: 1.5em; + line-height: 1em; + font-weight: normal; + + border-radius: 15px 15px 0 0; + -moz-border-radius: 15px 15px 0 0; + -webkit-border-top-right-radius: 15px; + -webkit-border-top-left-radius: 15px; +} + +#qunit-header a { + text-decoration: none; + color: #c2ccd1; +} + +#qunit-header a:hover, +#qunit-header a:focus { + color: #fff; +} + +#qunit-banner { + height: 5px; +} + +#qunit-testrunner-toolbar { + padding: 0.5em 0 0.5em 2em; + color: #5E740B; + background-color: #eee; +} + +#qunit-userAgent { + padding: 0.5em 0 0.5em 2.5em; + background-color: #2b81af; + color: #fff; + text-shadow: rgba(0, 0, 0, 0.5) 2px 2px 1px; +} + + +/** Tests: Pass/Fail */ + +#qunit-tests { + list-style-position: inside; +} + +#qunit-tests li { + padding: 0.4em 0.5em 0.4em 2.5em; + border-bottom: 1px solid #fff; + list-style-position: inside; +} + +#qunit-tests.hidepass li.pass, #qunit-tests.hidepass li.running { + display: none; +} + +#qunit-tests li strong { + cursor: pointer; +} + +#qunit-tests li a { + padding: 0.5em; + color: #c2ccd1; + text-decoration: none; +} +#qunit-tests li a:hover, +#qunit-tests li a:focus { + color: #000; +} + +#qunit-tests ol { + margin-top: 0.5em; + padding: 0.5em; + + background-color: #fff; + + border-radius: 15px; + -moz-border-radius: 15px; + -webkit-border-radius: 15px; + + box-shadow: inset 0px 2px 13px #999; + -moz-box-shadow: inset 0px 2px 13px #999; + -webkit-box-shadow: inset 0px 2px 13px #999; +} + +#qunit-tests table { + border-collapse: collapse; + margin-top: .2em; +} + +#qunit-tests th { + text-align: right; + vertical-align: top; + padding: 0 .5em 0 0; +} + +#qunit-tests td { + vertical-align: top; +} + +#qunit-tests pre { + margin: 0; + white-space: pre-wrap; + word-wrap: break-word; +} + +#qunit-tests del { + background-color: #e0f2be; + color: #374e0c; + text-decoration: none; +} + +#qunit-tests ins { + background-color: #ffcaca; + color: #500; + text-decoration: none; +} + +/*** Test Counts */ + +#qunit-tests b.counts { color: black; } +#qunit-tests b.passed { color: #5E740B; } +#qunit-tests b.failed { color: #710909; } + +#qunit-tests li li { + margin: 0.5em; + padding: 0.4em 0.5em 0.4em 0.5em; + background-color: #fff; + border-bottom: none; + list-style-position: inside; +} + +/*** Passing Styles */ + +#qunit-tests li li.pass { + color: #5E740B; + background-color: #fff; + border-left: 26px solid #C6E746; +} + +#qunit-tests .pass { color: #528CE0; background-color: #D2E0E6; } +#qunit-tests .pass .test-name { color: #366097; } + +#qunit-tests .pass .test-actual, +#qunit-tests .pass .test-expected { color: #999999; } + +#qunit-banner.qunit-pass { background-color: #C6E746; } + +/*** Failing Styles */ + +#qunit-tests li li.fail { + color: #710909; + background-color: #fff; + border-left: 26px solid #EE5757; +} + +#qunit-tests > li:last-child { + border-radius: 0 0 15px 15px; + -moz-border-radius: 0 0 15px 15px; + -webkit-border-bottom-right-radius: 15px; + -webkit-border-bottom-left-radius: 15px; +} + +#qunit-tests .fail { color: #000000; background-color: #EE5757; } +#qunit-tests .fail .test-name, +#qunit-tests .fail .module-name { color: #000000; } + +#qunit-tests .fail .test-actual { color: #EE5757; } +#qunit-tests .fail .test-expected { color: green; } + +#qunit-banner.qunit-fail { background-color: #EE5757; } + + +/** Result */ + +#qunit-testresult { + padding: 0.5em 0.5em 0.5em 2.5em; + + color: #2b81af; + background-color: #D2E0E6; + + border-bottom: 1px solid white; +} + +/** Fixture */ + +#qunit-fixture { + position: absolute; + top: -10000px; + left: -10000px; +} diff --git a/tests/qunit/qunit.js b/tests/qunit/qunit.js new file mode 100644 index 00000000..e00cca90 --- /dev/null +++ b/tests/qunit/qunit.js @@ -0,0 +1,1448 @@ +/** + * QUnit - A JavaScript Unit Testing Framework + * + * http://docs.jquery.com/QUnit + * + * Copyright (c) 2011 John Resig, Jörn Zaefferer + * Dual licensed under the MIT (MIT-LICENSE.txt) + * or GPL (GPL-LICENSE.txt) licenses. + */ + +(function(window) { + +var defined = { + setTimeout: typeof window.setTimeout !== "undefined", + sessionStorage: (function() { + try { + return !!sessionStorage.getItem; + } catch(e){ + return false; + } + })() +}; + +var testId = 0; + +var Test = function(name, testName, expected, testEnvironmentArg, async, callback) { + this.name = name; + this.testName = testName; + this.expected = expected; + this.testEnvironmentArg = testEnvironmentArg; + this.async = async; + this.callback = callback; + this.assertions = []; +}; +Test.prototype = { + init: function() { + var tests = id("qunit-tests"); + if (tests) { + var b = document.createElement("strong"); + b.innerHTML = "Running " + this.name; + var li = document.createElement("li"); + li.appendChild( b ); + li.className = "running"; + li.id = this.id = "test-output" + testId++; + tests.appendChild( li ); + } + }, + setup: function() { + if (this.module != config.previousModule) { + if ( config.previousModule ) { + QUnit.moduleDone( { + name: config.previousModule, + failed: config.moduleStats.bad, + passed: config.moduleStats.all - config.moduleStats.bad, + total: config.moduleStats.all + } ); + } + config.previousModule = this.module; + config.moduleStats = { all: 0, bad: 0 }; + QUnit.moduleStart( { + name: this.module + } ); + } + + config.current = this; + this.testEnvironment = extend({ + setup: function() {}, + teardown: function() {} + }, this.moduleTestEnvironment); + if (this.testEnvironmentArg) { + extend(this.testEnvironment, this.testEnvironmentArg); + } + + QUnit.testStart( { + name: this.testName + } ); + + // allow utility functions to access the current test environment + // TODO why?? + QUnit.current_testEnvironment = this.testEnvironment; + + try { + if ( !config.pollution ) { + saveGlobal(); + } + + this.testEnvironment.setup.call(this.testEnvironment); + } catch(e) { + QUnit.ok( false, "Setup failed on " + this.testName + ": " + e.message ); + } + }, + run: function() { + if ( this.async ) { + QUnit.stop(); + } + + if ( config.notrycatch ) { + this.callback.call(this.testEnvironment); + return; + } + try { + this.callback.call(this.testEnvironment); + } catch(e) { + fail("Test " + this.testName + " died, exception and test follows", e, this.callback); + QUnit.ok( false, "Died on test #" + (this.assertions.length + 1) + ": " + e.message + " - " + QUnit.jsDump.parse(e) ); + // else next test will carry the responsibility + saveGlobal(); + + // Restart the tests if they're blocking + if ( config.blocking ) { + start(); + } + } + }, + teardown: function() { + try { + this.testEnvironment.teardown.call(this.testEnvironment); + checkPollution(); + } catch(e) { + QUnit.ok( false, "Teardown failed on " + this.testName + ": " + e.message ); + } + }, + finish: function() { + if ( this.expected && this.expected != this.assertions.length ) { + QUnit.ok( false, "Expected " + this.expected + " assertions, but " + this.assertions.length + " were run" ); + } + + var good = 0, bad = 0, + tests = id("qunit-tests"); + + config.stats.all += this.assertions.length; + config.moduleStats.all += this.assertions.length; + + if ( tests ) { + var ol = document.createElement("ol"); + + for ( var i = 0; i < this.assertions.length; i++ ) { + var assertion = this.assertions[i]; + + var li = document.createElement("li"); + li.className = assertion.result ? "pass" : "fail"; + li.innerHTML = assertion.message || (assertion.result ? "okay" : "failed"); + ol.appendChild( li ); + + if ( assertion.result ) { + good++; + } else { + bad++; + config.stats.bad++; + config.moduleStats.bad++; + } + } + + // store result when possible + if ( QUnit.config.reorder && defined.sessionStorage ) { + if (bad) { + sessionStorage.setItem("qunit-" + this.module + "-" + this.testName, bad); + } else { + sessionStorage.removeItem("qunit-" + this.module + "-" + this.testName); + } + } + + if (bad == 0) { + ol.style.display = "none"; + } + + var b = document.createElement("strong"); + b.innerHTML = this.name + " (" + bad + ", " + good + ", " + this.assertions.length + ")"; + + var a = document.createElement("a"); + a.innerHTML = "Rerun"; + a.href = QUnit.url({ filter: getText([b]).replace(/\([^)]+\)$/, "").replace(/(^\s*|\s*$)/g, "") }); + + addEvent(b, "click", function() { + var next = b.nextSibling.nextSibling, + display = next.style.display; + next.style.display = display === "none" ? "block" : "none"; + }); + + addEvent(b, "dblclick", function(e) { + var target = e && e.target ? e.target : window.event.srcElement; + if ( target.nodeName.toLowerCase() == "span" || target.nodeName.toLowerCase() == "b" ) { + target = target.parentNode; + } + if ( window.location && target.nodeName.toLowerCase() === "strong" ) { + window.location = QUnit.url({ filter: getText([target]).replace(/\([^)]+\)$/, "").replace(/(^\s*|\s*$)/g, "") }); + } + }); + + var li = id(this.id); + li.className = bad ? "fail" : "pass"; + li.removeChild( li.firstChild ); + li.appendChild( b ); + li.appendChild( a ); + li.appendChild( ol ); + + } else { + for ( var i = 0; i < this.assertions.length; i++ ) { + if ( !this.assertions[i].result ) { + bad++; + config.stats.bad++; + config.moduleStats.bad++; + } + } + } + + try { + QUnit.reset(); + } catch(e) { + fail("reset() failed, following Test " + this.testName + ", exception and reset fn follows", e, QUnit.reset); + } + + QUnit.testDone( { + name: this.testName, + failed: bad, + passed: this.assertions.length - bad, + total: this.assertions.length + } ); + }, + + queue: function() { + var test = this; + synchronize(function() { + test.init(); + }); + function run() { + // each of these can by async + synchronize(function() { + test.setup(); + }); + synchronize(function() { + test.run(); + }); + synchronize(function() { + test.teardown(); + }); + synchronize(function() { + test.finish(); + }); + } + // defer when previous test run passed, if storage is available + var bad = QUnit.config.reorder && defined.sessionStorage && +sessionStorage.getItem("qunit-" + this.module + "-" + this.testName); + if (bad) { + run(); + } else { + synchronize(run); + }; + } + +}; + +var QUnit = { + + // call on start of module test to prepend name to all tests + module: function(name, testEnvironment) { + config.currentModule = name; + config.currentModuleTestEnviroment = testEnvironment; + }, + + asyncTest: function(testName, expected, callback) { + if ( arguments.length === 2 ) { + callback = expected; + expected = 0; + } + + QUnit.test(testName, expected, callback, true); + }, + + test: function(testName, expected, callback, async) { + var name = '' + testName + '', testEnvironmentArg; + + if ( arguments.length === 2 ) { + callback = expected; + expected = null; + } + // is 2nd argument a testEnvironment? + if ( expected && typeof expected === 'object') { + testEnvironmentArg = expected; + expected = null; + } + + if ( config.currentModule ) { + name = '' + config.currentModule + ": " + name; + } + + if ( !validTest(config.currentModule + ": " + testName) ) { + return; + } + + var test = new Test(name, testName, expected, testEnvironmentArg, async, callback); + test.module = config.currentModule; + test.moduleTestEnvironment = config.currentModuleTestEnviroment; + test.queue(); + }, + + /** + * Specify the number of expected assertions to gurantee that failed test (no assertions are run at all) don't slip through. + */ + expect: function(asserts) { + config.current.expected = asserts; + }, + + /** + * Asserts true. + * @example ok( "asdfasdf".length > 5, "There must be at least 5 chars" ); + */ + ok: function(a, msg) { + a = !!a; + var details = { + result: a, + message: msg + }; + msg = escapeHtml(msg); + QUnit.log(details); + config.current.assertions.push({ + result: a, + message: msg + }); + }, + + /** + * Checks that the first two arguments are equal, with an optional message. + * Prints out both actual and expected values. + * + * Prefered to ok( actual == expected, message ) + * + * @example equal( format("Received {0} bytes.", 2), "Received 2 bytes." ); + * + * @param Object actual + * @param Object expected + * @param String message (optional) + */ + equal: function(actual, expected, message) { + QUnit.push(expected == actual, actual, expected, message); + }, + + notEqual: function(actual, expected, message) { + QUnit.push(expected != actual, actual, expected, message); + }, + + deepEqual: function(actual, expected, message) { + QUnit.push(QUnit.equiv(actual, expected), actual, expected, message); + }, + + notDeepEqual: function(actual, expected, message) { + QUnit.push(!QUnit.equiv(actual, expected), actual, expected, message); + }, + + strictEqual: function(actual, expected, message) { + QUnit.push(expected === actual, actual, expected, message); + }, + + notStrictEqual: function(actual, expected, message) { + QUnit.push(expected !== actual, actual, expected, message); + }, + + raises: function(block, expected, message) { + var actual, ok = false; + + if (typeof expected === 'string') { + message = expected; + expected = null; + } + + try { + block(); + } catch (e) { + actual = e; + } + + if (actual) { + // we don't want to validate thrown error + if (!expected) { + ok = true; + // expected is a regexp + } else if (QUnit.objectType(expected) === "regexp") { + ok = expected.test(actual); + // expected is a constructor + } else if (actual instanceof expected) { + ok = true; + // expected is a validation function which returns true is validation passed + } else if (expected.call({}, actual) === true) { + ok = true; + } + } + + QUnit.ok(ok, message); + }, + + start: function() { + config.semaphore--; + if (config.semaphore > 0) { + // don't start until equal number of stop-calls + return; + } + if (config.semaphore < 0) { + // ignore if start is called more often then stop + config.semaphore = 0; + } + // A slight delay, to avoid any current callbacks + if ( defined.setTimeout ) { + window.setTimeout(function() { + if ( config.timeout ) { + clearTimeout(config.timeout); + } + + config.blocking = false; + process(); + }, 13); + } else { + config.blocking = false; + process(); + } + }, + + stop: function(timeout) { + config.semaphore++; + config.blocking = true; + + if ( timeout && defined.setTimeout ) { + clearTimeout(config.timeout); + config.timeout = window.setTimeout(function() { + QUnit.ok( false, "Test timed out" ); + QUnit.start(); + }, timeout); + } + } +}; + +// Backwards compatibility, deprecated +QUnit.equals = QUnit.equal; +QUnit.same = QUnit.deepEqual; + +// Maintain internal state +var config = { + // The queue of tests to run + queue: [], + + // block until document ready + blocking: true, + + // by default, run previously failed tests first + // very useful in combination with "Hide passed tests" checked + reorder: true, + + noglobals: false, + notrycatch: false +}; + +// Load paramaters +(function() { + var location = window.location || { search: "", protocol: "file:" }, + params = location.search.slice( 1 ).split( "&" ), + length = params.length, + urlParams = {}, + current; + + if ( params[ 0 ] ) { + for ( var i = 0; i < length; i++ ) { + current = params[ i ].split( "=" ); + current[ 0 ] = decodeURIComponent( current[ 0 ] ); + // allow just a key to turn on a flag, e.g., test.html?noglobals + current[ 1 ] = current[ 1 ] ? decodeURIComponent( current[ 1 ] ) : true; + urlParams[ current[ 0 ] ] = current[ 1 ]; + if ( current[ 0 ] in config ) { + config[ current[ 0 ] ] = current[ 1 ]; + } + } + } + + QUnit.urlParams = urlParams; + config.filter = urlParams.filter; + + // Figure out if we're running the tests from a server or not + QUnit.isLocal = !!(location.protocol === 'file:'); +})(); + +// Expose the API as global variables, unless an 'exports' +// object exists, in that case we assume we're in CommonJS +if ( typeof exports === "undefined" || typeof require === "undefined" ) { + extend(window, QUnit); + window.QUnit = QUnit; +} else { + extend(exports, QUnit); + exports.QUnit = QUnit; +} + +// define these after exposing globals to keep them in these QUnit namespace only +extend(QUnit, { + config: config, + + // Initialize the configuration options + init: function() { + extend(config, { + stats: { all: 0, bad: 0 }, + moduleStats: { all: 0, bad: 0 }, + started: +new Date, + updateRate: 1000, + blocking: false, + autostart: true, + autorun: false, + filter: "", + queue: [], + semaphore: 0 + }); + + var tests = id( "qunit-tests" ), + banner = id( "qunit-banner" ), + result = id( "qunit-testresult" ); + + if ( tests ) { + tests.innerHTML = ""; + } + + if ( banner ) { + banner.className = ""; + } + + if ( result ) { + result.parentNode.removeChild( result ); + } + + if ( tests ) { + result = document.createElement( "p" ); + result.id = "qunit-testresult"; + result.className = "result"; + tests.parentNode.insertBefore( result, tests ); + result.innerHTML = 'Running...
       '; + } + }, + + /** + * Resets the test setup. Useful for tests that modify the DOM. + * + * If jQuery is available, uses jQuery's html(), otherwise just innerHTML. + */ + reset: function() { + if ( window.jQuery ) { + jQuery( "#qunit-fixture" ).html( config.fixture ); + } else { + var main = id( 'qunit-fixture' ); + if ( main ) { + main.innerHTML = config.fixture; + } + } + }, + + /** + * Trigger an event on an element. + * + * @example triggerEvent( document.body, "click" ); + * + * @param DOMElement elem + * @param String type + */ + triggerEvent: function( elem, type, event ) { + if ( document.createEvent ) { + event = document.createEvent("MouseEvents"); + event.initMouseEvent(type, true, true, elem.ownerDocument.defaultView, + 0, 0, 0, 0, 0, false, false, false, false, 0, null); + elem.dispatchEvent( event ); + + } else if ( elem.fireEvent ) { + elem.fireEvent("on"+type); + } + }, + + // Safe object type checking + is: function( type, obj ) { + return QUnit.objectType( obj ) == type; + }, + + objectType: function( obj ) { + if (typeof obj === "undefined") { + return "undefined"; + + // consider: typeof null === object + } + if (obj === null) { + return "null"; + } + + var type = Object.prototype.toString.call( obj ) + .match(/^\[object\s(.*)\]$/)[1] || ''; + + switch (type) { + case 'Number': + if (isNaN(obj)) { + return "nan"; + } else { + return "number"; + } + case 'String': + case 'Boolean': + case 'Array': + case 'Date': + case 'RegExp': + case 'Function': + return type.toLowerCase(); + } + if (typeof obj === "object") { + return "object"; + } + return undefined; + }, + + push: function(result, actual, expected, message) { + var details = { + result: result, + message: message, + actual: actual, + expected: expected + }; + + message = escapeHtml(message) || (result ? "okay" : "failed"); + message = '' + message + ""; + expected = escapeHtml(QUnit.jsDump.parse(expected)); + actual = escapeHtml(QUnit.jsDump.parse(actual)); + var output = message + ''; + if (actual != expected) { + output += ''; + output += ''; + } + if (!result) { + var source = sourceFromStacktrace(); + if (source) { + details.source = source; + output += ''; + } + } + output += "
      Expected:
      ' + expected + '
      Result:
      ' + actual + '
      Diff:
      ' + QUnit.diff(expected, actual) +'
      Source:
      ' + escapeHtml(source) + '
      "; + + QUnit.log(details); + + config.current.assertions.push({ + result: !!result, + message: output + }); + }, + + url: function( params ) { + params = extend( extend( {}, QUnit.urlParams ), params ); + var querystring = "?", + key; + for ( key in params ) { + querystring += encodeURIComponent( key ) + "=" + + encodeURIComponent( params[ key ] ) + "&"; + } + return window.location.pathname + querystring.slice( 0, -1 ); + }, + + // Logging callbacks; all receive a single argument with the listed properties + // run test/logs.html for any related changes + begin: function() {}, + // done: { failed, passed, total, runtime } + done: function() {}, + // log: { result, actual, expected, message } + log: function() {}, + // testStart: { name } + testStart: function() {}, + // testDone: { name, failed, passed, total } + testDone: function() {}, + // moduleStart: { name } + moduleStart: function() {}, + // moduleDone: { name, failed, passed, total } + moduleDone: function() {} +}); + +if ( typeof document === "undefined" || document.readyState === "complete" ) { + config.autorun = true; +} + +addEvent(window, "load", function() { + QUnit.begin({}); + + // Initialize the config, saving the execution queue + var oldconfig = extend({}, config); + QUnit.init(); + extend(config, oldconfig); + + config.blocking = false; + + var userAgent = id("qunit-userAgent"); + if ( userAgent ) { + userAgent.innerHTML = navigator.userAgent; + } + var banner = id("qunit-header"); + if ( banner ) { + banner.innerHTML = ' ' + banner.innerHTML + ' ' + + '' + + ''; + addEvent( banner, "change", function( event ) { + var params = {}; + params[ event.target.name ] = event.target.checked ? true : undefined; + window.location = QUnit.url( params ); + }); + } + + var toolbar = id("qunit-testrunner-toolbar"); + if ( toolbar ) { + var filter = document.createElement("input"); + filter.type = "checkbox"; + filter.id = "qunit-filter-pass"; + addEvent( filter, "click", function() { + var ol = document.getElementById("qunit-tests"); + if ( filter.checked ) { + ol.className = ol.className + " hidepass"; + } else { + var tmp = " " + ol.className.replace( /[\n\t\r]/g, " " ) + " "; + ol.className = tmp.replace(/ hidepass /, " "); + } + if ( defined.sessionStorage ) { + if (filter.checked) { + sessionStorage.setItem("qunit-filter-passed-tests", "true"); + } else { + sessionStorage.removeItem("qunit-filter-passed-tests"); + } + } + }); + if ( defined.sessionStorage && sessionStorage.getItem("qunit-filter-passed-tests") ) { + filter.checked = true; + var ol = document.getElementById("qunit-tests"); + ol.className = ol.className + " hidepass"; + } + toolbar.appendChild( filter ); + + var label = document.createElement("label"); + label.setAttribute("for", "qunit-filter-pass"); + label.innerHTML = "Hide passed tests"; + toolbar.appendChild( label ); + } + + var main = id('qunit-fixture'); + if ( main ) { + config.fixture = main.innerHTML; + } + + if (config.autostart) { + QUnit.start(); + } +}); + +function done() { + config.autorun = true; + + // Log the last module results + if ( config.currentModule ) { + QUnit.moduleDone( { + name: config.currentModule, + failed: config.moduleStats.bad, + passed: config.moduleStats.all - config.moduleStats.bad, + total: config.moduleStats.all + } ); + } + + var banner = id("qunit-banner"), + tests = id("qunit-tests"), + runtime = +new Date - config.started, + passed = config.stats.all - config.stats.bad, + html = [ + 'Tests completed in ', + runtime, + ' milliseconds.
      ', + '', + passed, + ' tests of ', + config.stats.all, + ' passed, ', + config.stats.bad, + ' failed.' + ].join(''); + + if ( banner ) { + banner.className = (config.stats.bad ? "qunit-fail" : "qunit-pass"); + } + + if ( tests ) { + id( "qunit-testresult" ).innerHTML = html; + } + + if ( typeof document !== "undefined" && document.title ) { + // show ✖ for good, ✔ for bad suite result in title + // use escape sequences in case file gets loaded with non-utf-8-charset + document.title = (config.stats.bad ? "\u2716" : "\u2714") + " " + document.title; + } + + QUnit.done( { + failed: config.stats.bad, + passed: passed, + total: config.stats.all, + runtime: runtime + } ); +} + +function validTest( name ) { + var filter = config.filter, + run = false; + + if ( !filter ) { + return true; + } + + var not = filter.charAt( 0 ) === "!"; + if ( not ) { + filter = filter.slice( 1 ); + } + + if ( name.indexOf( filter ) !== -1 ) { + return !not; + } + + if ( not ) { + run = true; + } + + return run; +} + +// so far supports only Firefox, Chrome and Opera (buggy) +// could be extended in the future to use something like https://github.com/csnover/TraceKit +function sourceFromStacktrace() { + try { + throw new Error(); + } catch ( e ) { + if (e.stacktrace) { + // Opera + return e.stacktrace.split("\n")[6]; + } else if (e.stack) { + // Firefox, Chrome + return e.stack.split("\n")[4]; + } + } +} + +function escapeHtml(s) { + if (!s) { + return ""; + } + s = s + ""; + return s.replace(/[\&"<>\\]/g, function(s) { + switch(s) { + case "&": return "&"; + case "\\": return "\\\\"; + case '"': return '\"'; + case "<": return "<"; + case ">": return ">"; + default: return s; + } + }); +} + +function synchronize( callback ) { + config.queue.push( callback ); + + if ( config.autorun && !config.blocking ) { + process(); + } +} + +function process() { + var start = (new Date()).getTime(); + + while ( config.queue.length && !config.blocking ) { + if ( config.updateRate <= 0 || (((new Date()).getTime() - start) < config.updateRate) ) { + config.queue.shift()(); + } else { + window.setTimeout( process, 13 ); + break; + } + } + if (!config.blocking && !config.queue.length) { + done(); + } +} + +function saveGlobal() { + config.pollution = []; + + if ( config.noglobals ) { + for ( var key in window ) { + config.pollution.push( key ); + } + } +} + +function checkPollution( name ) { + var old = config.pollution; + saveGlobal(); + + var newGlobals = diff( config.pollution, old ); + if ( newGlobals.length > 0 ) { + ok( false, "Introduced global variable(s): " + newGlobals.join(", ") ); + } + + var deletedGlobals = diff( old, config.pollution ); + if ( deletedGlobals.length > 0 ) { + ok( false, "Deleted global variable(s): " + deletedGlobals.join(", ") ); + } +} + +// returns a new Array with the elements that are in a but not in b +function diff( a, b ) { + var result = a.slice(); + for ( var i = 0; i < result.length; i++ ) { + for ( var j = 0; j < b.length; j++ ) { + if ( result[i] === b[j] ) { + result.splice(i, 1); + i--; + break; + } + } + } + return result; +} + +function fail(message, exception, callback) { + if ( typeof console !== "undefined" && console.error && console.warn ) { + console.error(message); + console.error(exception); + console.warn(callback.toString()); + + } else if ( window.opera && opera.postError ) { + opera.postError(message, exception, callback.toString); + } +} + +function extend(a, b) { + for ( var prop in b ) { + if ( b[prop] === undefined ) { + delete a[prop]; + } else { + a[prop] = b[prop]; + } + } + + return a; +} + +function addEvent(elem, type, fn) { + if ( elem.addEventListener ) { + elem.addEventListener( type, fn, false ); + } else if ( elem.attachEvent ) { + elem.attachEvent( "on" + type, fn ); + } else { + fn(); + } +} + +function id(name) { + return !!(typeof document !== "undefined" && document && document.getElementById) && + document.getElementById( name ); +} + +// Test for equality any JavaScript type. +// Discussions and reference: http://philrathe.com/articles/equiv +// Test suites: http://philrathe.com/tests/equiv +// Author: Philippe Rathé +QUnit.equiv = function () { + + var innerEquiv; // the real equiv function + var callers = []; // stack to decide between skip/abort functions + var parents = []; // stack to avoiding loops from circular referencing + + // Call the o related callback with the given arguments. + function bindCallbacks(o, callbacks, args) { + var prop = QUnit.objectType(o); + if (prop) { + if (QUnit.objectType(callbacks[prop]) === "function") { + return callbacks[prop].apply(callbacks, args); + } else { + return callbacks[prop]; // or undefined + } + } + } + + var callbacks = function () { + + // for string, boolean, number and null + function useStrictEquality(b, a) { + if (b instanceof a.constructor || a instanceof b.constructor) { + // to catch short annotaion VS 'new' annotation of a declaration + // e.g. var i = 1; + // var j = new Number(1); + return a == b; + } else { + return a === b; + } + } + + return { + "string": useStrictEquality, + "boolean": useStrictEquality, + "number": useStrictEquality, + "null": useStrictEquality, + "undefined": useStrictEquality, + + "nan": function (b) { + return isNaN(b); + }, + + "date": function (b, a) { + return QUnit.objectType(b) === "date" && a.valueOf() === b.valueOf(); + }, + + "regexp": function (b, a) { + return QUnit.objectType(b) === "regexp" && + a.source === b.source && // the regex itself + a.global === b.global && // and its modifers (gmi) ... + a.ignoreCase === b.ignoreCase && + a.multiline === b.multiline; + }, + + // - skip when the property is a method of an instance (OOP) + // - abort otherwise, + // initial === would have catch identical references anyway + "function": function () { + var caller = callers[callers.length - 1]; + return caller !== Object && + typeof caller !== "undefined"; + }, + + "array": function (b, a) { + var i, j, loop; + var len; + + // b could be an object literal here + if ( ! (QUnit.objectType(b) === "array")) { + return false; + } + + len = a.length; + if (len !== b.length) { // safe and faster + return false; + } + + //track reference to avoid circular references + parents.push(a); + for (i = 0; i < len; i++) { + loop = false; + for(j=0;j= 0) { + type = "array"; + } else { + type = typeof obj; + } + return type; + }, + separator:function() { + return this.multiline ? this.HTML ? '
      ' : '\n' : this.HTML ? ' ' : ' '; + }, + indent:function( extra ) {// extra can be a number, shortcut for increasing-calling-decreasing + if ( !this.multiline ) + return ''; + var chr = this.indentChar; + if ( this.HTML ) + chr = chr.replace(/\t/g,' ').replace(/ /g,' '); + return Array( this._depth_ + (extra||0) ).join(chr); + }, + up:function( a ) { + this._depth_ += a || 1; + }, + down:function( a ) { + this._depth_ -= a || 1; + }, + setParser:function( name, parser ) { + this.parsers[name] = parser; + }, + // The next 3 are exposed so you can use them + quote:quote, + literal:literal, + join:join, + // + _depth_: 1, + // This is the list of parsers, to modify them, use jsDump.setParser + parsers:{ + window: '[Window]', + document: '[Document]', + error:'[ERROR]', //when no parser is found, shouldn't happen + unknown: '[Unknown]', + 'null':'null', + 'undefined':'undefined', + 'function':function( fn ) { + var ret = 'function', + name = 'name' in fn ? fn.name : (reName.exec(fn)||[])[1];//functions never have name in IE + if ( name ) + ret += ' ' + name; + ret += '('; + + ret = [ ret, QUnit.jsDump.parse( fn, 'functionArgs' ), '){'].join(''); + return join( ret, QUnit.jsDump.parse(fn,'functionCode'), '}' ); + }, + array: array, + nodelist: array, + arguments: array, + object:function( map ) { + var ret = [ ]; + QUnit.jsDump.up(); + for ( var key in map ) + ret.push( QUnit.jsDump.parse(key,'key') + ': ' + QUnit.jsDump.parse(map[key]) ); + QUnit.jsDump.down(); + return join( '{', ret, '}' ); + }, + node:function( node ) { + var open = QUnit.jsDump.HTML ? '<' : '<', + close = QUnit.jsDump.HTML ? '>' : '>'; + + var tag = node.nodeName.toLowerCase(), + ret = open + tag; + + for ( var a in QUnit.jsDump.DOMAttrs ) { + var val = node[QUnit.jsDump.DOMAttrs[a]]; + if ( val ) + ret += ' ' + a + '=' + QUnit.jsDump.parse( val, 'attribute' ); + } + return ret + close + open + '/' + tag + close; + }, + functionArgs:function( fn ) {//function calls it internally, it's the arguments part of the function + var l = fn.length; + if ( !l ) return ''; + + var args = Array(l); + while ( l-- ) + args[l] = String.fromCharCode(97+l);//97 is 'a' + return ' ' + args.join(', ') + ' '; + }, + key:quote, //object calls it internally, the key part of an item in a map + functionCode:'[code]', //function calls it internally, it's the content of the function + attribute:quote, //node calls it internally, it's an html attribute value + string:quote, + date:quote, + regexp:literal, //regex + number:literal, + 'boolean':literal + }, + DOMAttrs:{//attributes to dump from nodes, name=>realName + id:'id', + name:'name', + 'class':'className' + }, + HTML:false,//if true, entities are escaped ( <, >, \t, space and \n ) + indentChar:' ',//indentation unit + multiline:true //if true, items in a collection, are separated by a \n, else just a space. + }; + + return jsDump; +})(); + +// from Sizzle.js +function getText( elems ) { + var ret = "", elem; + + for ( var i = 0; elems[i]; i++ ) { + elem = elems[i]; + + // Get the text from text nodes and CDATA nodes + if ( elem.nodeType === 3 || elem.nodeType === 4 ) { + ret += elem.nodeValue; + + // Traverse everything else, except comment nodes + } else if ( elem.nodeType !== 8 ) { + ret += getText( elem.childNodes ); + } + } + + return ret; +}; + +/* + * Javascript Diff Algorithm + * By John Resig (http://ejohn.org/) + * Modified by Chu Alan "sprite" + * + * Released under the MIT license. + * + * More Info: + * http://ejohn.org/projects/javascript-diff-algorithm/ + * + * Usage: QUnit.diff(expected, actual) + * + * QUnit.diff("the quick brown fox jumped over", "the quick fox jumps over") == "the quick brown fox jumped jumps over" + */ +QUnit.diff = (function() { + function diff(o, n){ + var ns = new Object(); + var os = new Object(); + + for (var i = 0; i < n.length; i++) { + if (ns[n[i]] == null) + ns[n[i]] = { + rows: new Array(), + o: null + }; + ns[n[i]].rows.push(i); + } + + for (var i = 0; i < o.length; i++) { + if (os[o[i]] == null) + os[o[i]] = { + rows: new Array(), + n: null + }; + os[o[i]].rows.push(i); + } + + for (var i in ns) { + if (ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1) { + n[ns[i].rows[0]] = { + text: n[ns[i].rows[0]], + row: os[i].rows[0] + }; + o[os[i].rows[0]] = { + text: o[os[i].rows[0]], + row: ns[i].rows[0] + }; + } + } + + for (var i = 0; i < n.length - 1; i++) { + if (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null && + n[i + 1] == o[n[i].row + 1]) { + n[i + 1] = { + text: n[i + 1], + row: n[i].row + 1 + }; + o[n[i].row + 1] = { + text: o[n[i].row + 1], + row: i + 1 + }; + } + } + + for (var i = n.length - 1; i > 0; i--) { + if (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null && + n[i - 1] == o[n[i].row - 1]) { + n[i - 1] = { + text: n[i - 1], + row: n[i].row - 1 + }; + o[n[i].row - 1] = { + text: o[n[i].row - 1], + row: i - 1 + }; + } + } + + return { + o: o, + n: n + }; + } + + return function(o, n){ + o = o.replace(/\s+$/, ''); + n = n.replace(/\s+$/, ''); + var out = diff(o == "" ? [] : o.split(/\s+/), n == "" ? [] : n.split(/\s+/)); + + var str = ""; + + var oSpace = o.match(/\s+/g); + if (oSpace == null) { + oSpace = [" "]; + } + else { + oSpace.push(" "); + } + var nSpace = n.match(/\s+/g); + if (nSpace == null) { + nSpace = [" "]; + } + else { + nSpace.push(" "); + } + + if (out.n.length == 0) { + for (var i = 0; i < out.o.length; i++) { + str += '' + out.o[i] + oSpace[i] + ""; + } + } + else { + if (out.n[0].text == null) { + for (n = 0; n < out.o.length && out.o[n].text == null; n++) { + str += '' + out.o[n] + oSpace[n] + ""; + } + } + + for (var i = 0; i < out.n.length; i++) { + if (out.n[i].text == null) { + str += '' + out.n[i] + nSpace[i] + ""; + } + else { + var pre = ""; + + for (n = out.n[i].row + 1; n < out.o.length && out.o[n].text == null; n++) { + pre += '' + out.o[n] + oSpace[n] + ""; + } + str += " " + out.n[i].text + nSpace[i] + pre; + } + } + } + + return str; + }; +})(); + +})(this); diff --git a/tests/stress_phystoken.tok b/tests/stress_phystoken.tok new file mode 100644 index 00000000..8d1b6bec --- /dev/null +++ b/tests/stress_phystoken.tok @@ -0,0 +1,52 @@ +# Here's some random Python so that test_tokenize_myself will have some +# stressful stuff to try. This file is .tok instead of .py so pylint won't +# complain about it, check_eol won't look at it, etc. + +first_back = """\ +hey there! +""" + +other_back = """ +hey \ +there +""" + +lots_of_back = """\ +hey \ +there +""" +# This next line is supposed to have trailing whitespace: +fake_back = """\ +ouch +""" + +# Lots of difficulty happens with code like: +# +# fake_back = """\ +# ouch +# """ +# +# Ugh, the edge cases... + +# What about a comment like this\ +"what's this string doing here?" + +class C(object): + def there(): + this = 5 + \ + 7 + that = \ + "a continued line" + +cont1 = "one line of text" + \ + "another line of text" + +a_long_string = \ + "part 1" \ + "2" \ + "3 is longer" + +def hello(): + print("Hello world!") + +hello() diff --git a/tests/stress_phystoken_dos.tok b/tests/stress_phystoken_dos.tok new file mode 100644 index 00000000..b08fd70e --- /dev/null +++ b/tests/stress_phystoken_dos.tok @@ -0,0 +1,52 @@ +# Here's some random Python so that test_tokenize_myself will have some +# stressful stuff to try. This file is .tok instead of .py so pylint won't +# complain about it, check_eol won't look at it, etc. + +first_back = """\ +hey there! +""" + +other_back = """ +hey \ +there +""" + +lots_of_back = """\ +hey \ +there +""" +# This next line is supposed to have trailing whitespace: +fake_back = """\ +ouch +""" + +# Lots of difficulty happens with code like: +# +# fake_back = """\ +# ouch +# """ +# +# Ugh, the edge cases... + +# What about a comment like this\ +"what's this string doing here?" + +class C(object): + def there(): + this = 5 + \ + 7 + that = \ + "a continued line" + +cont1 = "one line of text" + \ + "another line of text" + +a_long_string = \ + "part 1" \ + "2" \ + "3 is longer" + +def hello(): + print("Hello world!") + +hello() diff --git a/tests/test_api.py b/tests/test_api.py new file mode 100644 index 00000000..559684b8 --- /dev/null +++ b/tests/test_api.py @@ -0,0 +1,571 @@ +"""Tests for Coverage's api.""" + +import fnmatch, os, re, sys, textwrap + +import coverage +from coverage.backward import StringIO + +from test.coveragetest import CoverageTest + + +class SingletonApiTest(CoverageTest): + """Tests of the old-fashioned singleton API.""" + + def setUp(self): + super(SingletonApiTest, self).setUp() + # These tests use the singleton module interface. Prevent it from + # writing .coverage files at exit. + coverage.use_cache(0) + + def do_report_work(self, modname): + """Create a module named `modname`, then measure it.""" + coverage.erase() + + self.make_file(modname+".py", """\ + a = 1 + b = 2 + if b == 3: + c = 4 + d = 5 + e = 6 + f = 7 + """) + + # Import the python file, executing it. + self.start_import_stop(coverage, modname) + + def test_simple(self): + coverage.erase() + + self.make_file("mycode.py", """\ + a = 1 + b = 2 + if b == 3: + c = 4 + d = 5 + """) + + # Import the python file, executing it. + self.start_import_stop(coverage, "mycode") + + _, statements, missing, missingtext = coverage.analysis("mycode.py") + self.assertEqual(statements, [1,2,3,4,5]) + self.assertEqual(missing, [4]) + self.assertEqual(missingtext, "4") + + def test_report(self): + self.do_report_work("mycode2") + coverage.report(["mycode2.py"]) + self.assertEqual(self.stdout(), textwrap.dedent("""\ + Name Stmts Miss Cover Missing + --------------------------------------- + mycode2 7 3 57% 4-6 + """)) + + def test_report_file(self): + # The file= argument of coverage.report makes the report go there. + self.do_report_work("mycode3") + fout = StringIO() + coverage.report(["mycode3.py"], file=fout) + self.assertEqual(self.stdout(), "") + self.assertEqual(fout.getvalue(), textwrap.dedent("""\ + Name Stmts Miss Cover Missing + --------------------------------------- + mycode3 7 3 57% 4-6 + """)) + + def test_report_default(self): + # Calling report() with no morfs will report on whatever was executed. + self.do_report_work("mycode4") + coverage.report() + rpt = re.sub(r"\s+", " ", self.stdout()) + self.assertIn("mycode4 7 3 57% 4-6", rpt) + + +class ApiTest(CoverageTest): + """Api-oriented tests for Coverage.""" + + def clean_files(self, files, pats): + """Remove names matching `pats` from `files`, a list of filenames.""" + good = [] + for f in files: + for pat in pats: + if fnmatch.fnmatch(f, pat): + break + else: + good.append(f) + return good + + def assertFiles(self, files): + """Assert that the files here are `files`, ignoring the usual junk.""" + here = os.listdir(".") + here = self.clean_files(here, ["*.pyc", "__pycache__"]) + self.assertSameElements(here, files) + + def test_unexecuted_file(self): + cov = coverage.coverage() + + self.make_file("mycode.py", """\ + a = 1 + b = 2 + if b == 3: + c = 4 + d = 5 + """) + + self.make_file("not_run.py", """\ + fooey = 17 + """) + + # Import the python file, executing it. + self.start_import_stop(cov, "mycode") + + _, statements, missing, _ = cov.analysis("not_run.py") + self.assertEqual(statements, [1]) + self.assertEqual(missing, [1]) + + def test_filenames(self): + + self.make_file("mymain.py", """\ + import mymod + a = 1 + """) + + self.make_file("mymod.py", """\ + fooey = 17 + """) + + # Import the python file, executing it. + cov = coverage.coverage() + self.start_import_stop(cov, "mymain") + + filename, _, _, _ = cov.analysis("mymain.py") + self.assertEqual(os.path.basename(filename), "mymain.py") + filename, _, _, _ = cov.analysis("mymod.py") + self.assertEqual(os.path.basename(filename), "mymod.py") + + filename, _, _, _ = cov.analysis(sys.modules["mymain"]) + self.assertEqual(os.path.basename(filename), "mymain.py") + filename, _, _, _ = cov.analysis(sys.modules["mymod"]) + self.assertEqual(os.path.basename(filename), "mymod.py") + + # Import the python file, executing it again, once it's been compiled + # already. + cov = coverage.coverage() + self.start_import_stop(cov, "mymain") + + filename, _, _, _ = cov.analysis("mymain.py") + self.assertEqual(os.path.basename(filename), "mymain.py") + filename, _, _, _ = cov.analysis("mymod.py") + self.assertEqual(os.path.basename(filename), "mymod.py") + + filename, _, _, _ = cov.analysis(sys.modules["mymain"]) + self.assertEqual(os.path.basename(filename), "mymain.py") + filename, _, _, _ = cov.analysis(sys.modules["mymod"]) + self.assertEqual(os.path.basename(filename), "mymod.py") + + def test_ignore_stdlib(self): + self.make_file("mymain.py", """\ + import colorsys + a = 1 + hls = colorsys.rgb_to_hls(1.0, 0.5, 0.0) + """) + + # Measure without the stdlib. + cov1 = coverage.coverage() + self.assertEqual(cov1.config.cover_pylib, False) + self.start_import_stop(cov1, "mymain") + + # some statements were marked executed in mymain.py + _, statements, missing, _ = cov1.analysis("mymain.py") + self.assertNotEqual(statements, missing) + # but none were in colorsys.py + _, statements, missing, _ = cov1.analysis("colorsys.py") + self.assertEqual(statements, missing) + + # Measure with the stdlib. + cov2 = coverage.coverage(cover_pylib=True) + self.start_import_stop(cov2, "mymain") + + # some statements were marked executed in mymain.py + _, statements, missing, _ = cov2.analysis("mymain.py") + self.assertNotEqual(statements, missing) + # and some were marked executed in colorsys.py + _, statements, missing, _ = cov2.analysis("colorsys.py") + self.assertNotEqual(statements, missing) + + def test_include_can_measure_stdlib(self): + self.make_file("mymain.py", """\ + import colorsys, random + a = 1 + r, g, b = [random.random() for _ in range(3)] + hls = colorsys.rgb_to_hls(r, g, b) + """) + + # Measure without the stdlib, but include colorsys. + cov1 = coverage.coverage(cover_pylib=False, include=["*/colorsys.py"]) + self.start_import_stop(cov1, "mymain") + + # some statements were marked executed in colorsys.py + _, statements, missing, _ = cov1.analysis("colorsys.py") + self.assertNotEqual(statements, missing) + # but none were in random.py + _, statements, missing, _ = cov1.analysis("random.py") + self.assertEqual(statements, missing) + + def test_exclude_list(self): + cov = coverage.coverage() + cov.clear_exclude() + self.assertEqual(cov.get_exclude_list(), []) + cov.exclude("foo") + self.assertEqual(cov.get_exclude_list(), ["foo"]) + cov.exclude("bar") + self.assertEqual(cov.get_exclude_list(), ["foo", "bar"]) + self.assertEqual(cov._exclude_regex('exclude'), "(foo)|(bar)") + cov.clear_exclude() + self.assertEqual(cov.get_exclude_list(), []) + + def test_exclude_partial_list(self): + cov = coverage.coverage() + cov.clear_exclude(which='partial') + self.assertEqual(cov.get_exclude_list(which='partial'), []) + cov.exclude("foo", which='partial') + self.assertEqual(cov.get_exclude_list(which='partial'), ["foo"]) + cov.exclude("bar", which='partial') + self.assertEqual(cov.get_exclude_list(which='partial'), ["foo", "bar"]) + self.assertEqual(cov._exclude_regex(which='partial'), "(foo)|(bar)") + cov.clear_exclude(which='partial') + self.assertEqual(cov.get_exclude_list(which='partial'), []) + + def test_exclude_and_partial_are_separate_lists(self): + cov = coverage.coverage() + cov.clear_exclude(which='partial') + cov.clear_exclude(which='exclude') + cov.exclude("foo", which='partial') + self.assertEqual(cov.get_exclude_list(which='partial'), ['foo']) + self.assertEqual(cov.get_exclude_list(which='exclude'), []) + cov.exclude("bar", which='exclude') + self.assertEqual(cov.get_exclude_list(which='partial'), ['foo']) + self.assertEqual(cov.get_exclude_list(which='exclude'), ['bar']) + cov.exclude("p2", which='partial') + cov.exclude("e2", which='exclude') + self.assertEqual(cov.get_exclude_list(which='partial'), ['foo', 'p2']) + self.assertEqual(cov.get_exclude_list(which='exclude'), ['bar', 'e2']) + cov.clear_exclude(which='partial') + self.assertEqual(cov.get_exclude_list(which='partial'), []) + self.assertEqual(cov.get_exclude_list(which='exclude'), ['bar', 'e2']) + cov.clear_exclude(which='exclude') + self.assertEqual(cov.get_exclude_list(which='partial'), []) + self.assertEqual(cov.get_exclude_list(which='exclude'), []) + + def test_datafile_default(self): + # Default data file behavior: it's .coverage + self.make_file("datatest1.py", """\ + fooey = 17 + """) + + self.assertFiles(["datatest1.py"]) + cov = coverage.coverage() + self.start_import_stop(cov, "datatest1") + cov.save() + self.assertFiles(["datatest1.py", ".coverage"]) + + def test_datafile_specified(self): + # You can specify the data file name. + self.make_file("datatest2.py", """\ + fooey = 17 + """) + + self.assertFiles(["datatest2.py"]) + cov = coverage.coverage(data_file="cov.data") + self.start_import_stop(cov, "datatest2") + cov.save() + self.assertFiles(["datatest2.py", "cov.data"]) + + def test_datafile_and_suffix_specified(self): + # You can specify the data file name and suffix. + self.make_file("datatest3.py", """\ + fooey = 17 + """) + + self.assertFiles(["datatest3.py"]) + cov = coverage.coverage(data_file="cov.data", data_suffix="14") + self.start_import_stop(cov, "datatest3") + cov.save() + self.assertFiles(["datatest3.py", "cov.data.14"]) + + def test_datafile_from_rcfile(self): + # You can specify the data file name in the .coveragerc file + self.make_file("datatest4.py", """\ + fooey = 17 + """) + self.make_file(".coveragerc", """\ + [run] + data_file = mydata.dat + """) + + self.assertFiles(["datatest4.py", ".coveragerc"]) + cov = coverage.coverage() + self.start_import_stop(cov, "datatest4") + cov.save() + self.assertFiles(["datatest4.py", ".coveragerc", "mydata.dat"]) + + def test_empty_reporting(self): + # Used to be you'd get an exception reporting on nothing... + cov = coverage.coverage() + cov.erase() + cov.report() + + def test_start_stop_start_stop(self): + self.make_file("code1.py", """\ + code1 = 1 + """) + self.make_file("code2.py", """\ + code2 = 1 + code2 = 2 + """) + cov = coverage.coverage() + self.start_import_stop(cov, "code1") + cov.save() + self.start_import_stop(cov, "code2") + _, statements, missing, _ = cov.analysis("code1.py") + self.assertEqual(statements, [1]) + self.assertEqual(missing, []) + _, statements, missing, _ = cov.analysis("code2.py") + self.assertEqual(statements, [1, 2]) + self.assertEqual(missing, []) + + if 0: # expected failure + # for https://bitbucket.org/ned/coveragepy/issue/79 + def test_start_save_stop(self): + self.make_file("code1.py", """\ + code1 = 1 + """) + self.make_file("code2.py", """\ + code2 = 1 + code2 = 2 + """) + cov = coverage.coverage() + cov.start() + self.import_local_file("code1") + cov.save() + self.import_local_file("code2") + cov.stop() + + _, statements, missing, _ = cov.analysis("code1.py") + self.assertEqual(statements, [1]) + self.assertEqual(missing, []) + _, statements, missing, _ = cov.analysis("code2.py") + self.assertEqual(statements, [1, 2]) + self.assertEqual(missing, []) + + + +class UsingModulesMixin(object): + """A mixin for importing modules from test/modules and test/moremodules.""" + + run_in_temp_dir = False + + def setUp(self): + super(UsingModulesMixin, self).setUp() + # Parent class saves and restores sys.path, we can just modify it. + self.old_dir = os.getcwd() + os.chdir(self.nice_file(os.path.dirname(__file__), 'modules')) + sys.path.append(".") + sys.path.append("../moremodules") + + def tearDown(self): + os.chdir(self.old_dir) + super(UsingModulesMixin, self).tearDown() + + +class OmitIncludeTestsMixin(UsingModulesMixin): + """Test methods for coverage methods taking include and omit.""" + + def filenames_in(self, summary, filenames): + """Assert the `filenames` are in the keys of `summary`.""" + for filename in filenames.split(): + self.assertIn(filename, summary) + + def filenames_not_in(self, summary, filenames): + """Assert the `filenames` are not in the keys of `summary`.""" + for filename in filenames.split(): + self.assertNotIn(filename, summary) + + def test_nothing_specified(self): + result = self.coverage_usepkgs() + self.filenames_in(result, "p1a p1b p2a p2b othera otherb osa osb") + self.filenames_not_in(result, "p1c") + # Because there was no source= specified, we don't search for + # unexecuted files. + + def test_include(self): + result = self.coverage_usepkgs(include=["*/p1a.py"]) + self.filenames_in(result, "p1a") + self.filenames_not_in(result, "p1b p1c p2a p2b othera otherb osa osb") + + def test_include_2(self): + result = self.coverage_usepkgs(include=["*a.py"]) + self.filenames_in(result, "p1a p2a othera osa") + self.filenames_not_in(result, "p1b p1c p2b otherb osb") + + def test_include_as_string(self): + result = self.coverage_usepkgs(include="*a.py") + self.filenames_in(result, "p1a p2a othera osa") + self.filenames_not_in(result, "p1b p1c p2b otherb osb") + + def test_omit(self): + result = self.coverage_usepkgs(omit=["*/p1a.py"]) + self.filenames_in(result, "p1b p2a p2b") + self.filenames_not_in(result, "p1a p1c") + + def test_omit_2(self): + result = self.coverage_usepkgs(omit=["*a.py"]) + self.filenames_in(result, "p1b p2b otherb osb") + self.filenames_not_in(result, "p1a p1c p2a othera osa") + + def test_omit_as_string(self): + result = self.coverage_usepkgs(omit="*a.py") + self.filenames_in(result, "p1b p2b otherb osb") + self.filenames_not_in(result, "p1a p1c p2a othera osa") + + def test_omit_and_include(self): + result = self.coverage_usepkgs( include=["*/p1*"], omit=["*/p1a.py"]) + self.filenames_in(result, "p1b") + self.filenames_not_in(result, "p1a p1c p2a p2b") + + +class SourceOmitIncludeTest(OmitIncludeTestsMixin, CoverageTest): + """Test using `source`, `omit` and `include` when measuring code.""" + + def coverage_usepkgs(self, **kwargs): + """Run coverage on usepkgs and return the line summary. + + Arguments are passed to the `coverage.coverage` constructor. + + """ + cov = coverage.coverage(**kwargs) + cov.start() + import usepkgs # pragma: nested # pylint: disable=F0401,W0612 + cov.stop() # pragma: nested + cov._harvest_data() # private! sshhh... + summary = cov.data.summary() + for k, v in list(summary.items()): + assert k.endswith(".py") + summary[k[:-3]] = v + return summary + + def test_source_package(self): + lines = self.coverage_usepkgs(source=["pkg1"]) + self.filenames_in(lines, "p1a p1b") + self.filenames_not_in(lines, "p2a p2b othera otherb osa osb") + # Because source= was specified, we do search for unexecuted files. + self.assertEqual(lines['p1c'], 0) + + def test_source_package_dotted(self): + lines = self.coverage_usepkgs(source=["pkg1.p1b"]) + self.filenames_in(lines, "p1b") + self.filenames_not_in(lines, "p1a p1c p2a p2b othera otherb osa osb") + + +class ReportIncludeOmitTest(OmitIncludeTestsMixin, CoverageTest): + """Tests of the report include/omit functionality.""" + + def coverage_usepkgs(self, **kwargs): + """Try coverage.report().""" + cov = coverage.coverage() + cov.start() + import usepkgs # pragma: nested # pylint: disable=F0401,W0612 + cov.stop() # pragma: nested + report = StringIO() + cov.report(file=report, **kwargs) + return report.getvalue() + + +class XmlIncludeOmitTest(OmitIncludeTestsMixin, CoverageTest): + """Tests of the xml include/omit functionality. + + This also takes care of the HTML and annotate include/omit, by virtue + of the structure of the code. + + """ + + def coverage_usepkgs(self, **kwargs): + """Try coverage.xml_report().""" + cov = coverage.coverage() + cov.start() + import usepkgs # pragma: nested # pylint: disable=F0401,W0612 + cov.stop() # pragma: nested + cov.xml_report(outfile="-", **kwargs) + return self.stdout() + + +class AnalysisTest(CoverageTest): + """Test the numerical analysis of results.""" + def test_many_missing_branches(self): + cov = coverage.coverage(branch=True) + + self.make_file("missing.py", """\ + def fun1(x): + if x == 1: + print("one") + else: + print("not one") + print("done") # pragma: nocover + + def fun2(x): + print("x") + + fun2(3) + """) + + # Import the python file, executing it. + self.start_import_stop(cov, "missing") + + nums = cov._analyze("missing.py").numbers + self.assertEqual(nums.n_files, 1) + self.assertEqual(nums.n_statements, 7) + self.assertEqual(nums.n_excluded, 1) + self.assertEqual(nums.n_missing, 3) + self.assertEqual(nums.n_branches, 2) + self.assertEqual(nums.n_partial_branches, 0) + self.assertEqual(nums.n_missing_branches, 2) + + +class PluginTest(CoverageTest): + """Test that the API works properly the way the plugins call it. + + We don't actually use the plugins, but these tests call the API the same + way they do. + + """ + def pretend_to_be_nose_with_cover(self, erase): + """This is what the nose --with-cover plugin does.""" + cov = coverage.coverage() + + self.make_file("no_biggie.py", """\ + a = 1 + b = 2 + if b == 1: + c = 4 + """) + + if erase: + cov.combine() + cov.erase() + cov.load() + self.start_import_stop(cov, "no_biggie") + cov.combine() + cov.save() + cov.report(["no_biggie.py"]) + self.assertEqual(self.stdout(), textwrap.dedent("""\ + Name Stmts Miss Cover Missing + ----------------------------------------- + no_biggie 4 1 75% 4 + """)) + + def test_nose_plugin(self): + self.pretend_to_be_nose_with_cover(erase=False) + + def test_nose_plugin_with_erase(self): + self.pretend_to_be_nose_with_cover(erase=True) diff --git a/tests/test_arcs.py b/tests/test_arcs.py new file mode 100644 index 00000000..69c054cc --- /dev/null +++ b/tests/test_arcs.py @@ -0,0 +1,578 @@ +"""Tests for Coverage.py's arc measurement.""" + +import sys +from test.coveragetest import CoverageTest + + +class SimpleArcTest(CoverageTest): + """Tests for Coverage.py's arc measurement.""" + + def test_simple_sequence(self): + self.check_coverage("""\ + a = 1 + b = 2 + """, + arcz=".1 12 2.") + self.check_coverage("""\ + a = 1 + + b = 3 + """, + arcz=".1 13 3.") + self.check_coverage("""\ + + a = 2 + b = 3 + + c = 5 + """, + arcz=".2 23 35 5-2") + + def test_function_def(self): + self.check_coverage("""\ + def foo(): + a = 2 + + foo() + """, + arcz=".1 .2 14 2. 4.") + + def test_if(self): + self.check_coverage("""\ + a = 1 + if len([]) == 0: + a = 3 + assert a == 3 + """, + arcz=".1 12 23 24 34 4.", arcz_missing="24") + self.check_coverage("""\ + a = 1 + if len([]) == 1: + a = 3 + assert a == 1 + """, + arcz=".1 12 23 24 34 4.", arcz_missing="23 34") + + def test_if_else(self): + self.check_coverage("""\ + if len([]) == 0: + a = 2 + else: + a = 4 + assert a == 2 + """, + arcz=".1 12 25 14 45 5.", arcz_missing="14 45") + self.check_coverage("""\ + if len([]) == 1: + a = 2 + else: + a = 4 + assert a == 4 + """, + arcz=".1 12 25 14 45 5.", arcz_missing="12 25") + + def test_compact_if(self): + self.check_coverage("""\ + a = 1 + if len([]) == 0: a = 2 + assert a == 2 + """, + arcz=".1 12 23 3.", arcz_missing="") + self.check_coverage("""\ + def fn(x): + if x % 2: return True + return False + a = fn(1) + assert a == True + """, + arcz=".1 14 45 5. .2 2. 23 3.", arcz_missing="23 3.") + + def test_multiline(self): + # The firstlineno of the a assignment below differs among Python + # versions. + if sys.version_info >= (2, 5): + arcz = ".1 15 5-2" + else: + arcz = ".1 15 5-1" + self.check_coverage("""\ + a = ( + 2 + + 3 + ) + b = \\ + 6 + """, + arcz=arcz, arcz_missing="") + + def test_if_return(self): + self.check_coverage("""\ + def if_ret(a): + if a: + return 3 + b = 4 + return 5 + x = if_ret(0) + if_ret(1) + assert x == 8 + """, + arcz=".1 16 67 7. .2 23 24 3. 45 5.", arcz_missing="" + ) + + def test_dont_confuse_exit_and_else(self): + self.check_coverage("""\ + def foo(): + if foo: + a = 3 + else: + a = 5 + return a + assert foo() == 3 # 7 + """, + arcz=".1 17 7. .2 23 36 25 56 6.", arcz_missing="25 56" + ) + self.check_coverage("""\ + def foo(): + if foo: + a = 3 + else: + a = 5 + foo() # 6 + """, + arcz=".1 16 6. .2 23 3. 25 5.", arcz_missing="25 5." + ) + + if 0: # expected failure + def test_lambdas_are_confusing_bug_90(self): + self.check_coverage("""\ + a = 1 + fn = lambda x: x + b = 3 + """, + arcz=".1 12 .2 2-2 23 3." + ) + + +if sys.version_info >= (2, 6): + class WithTest(CoverageTest): + """Arc-measuring tests involving context managers.""" + + def test_with(self): + self.check_coverage("""\ + def example(): + with open("test", "w") as f: # exit + f.write("") + return 1 + + example() + """, + arcz=".1 .2 23 34 4. 16 6." + ) + + +class LoopArcTest(CoverageTest): + """Arc-measuring tests involving loops.""" + + def test_loop(self): + self.check_coverage("""\ + for i in range(10): + a = i + assert a == 9 + """, + arcz=".1 12 21 13 3.", arcz_missing="") + self.check_coverage("""\ + a = -1 + for i in range(0): + a = i + assert a == -1 + """, + arcz=".1 12 23 32 24 4.", arcz_missing="23 32") + + def test_nested_loop(self): + self.check_coverage("""\ + for i in range(3): + for j in range(3): + a = i + j + assert a == 4 + """, + arcz=".1 12 23 32 21 14 4.", arcz_missing="") + + def test_break(self): + self.check_coverage("""\ + for i in range(10): + a = i + break # 3 + a = 99 + assert a == 0 # 5 + """, + arcz=".1 12 23 35 15 41 5.", arcz_missing="15 41") + + def test_continue(self): + self.check_coverage("""\ + for i in range(10): + a = i + continue # 3 + a = 99 + assert a == 9 # 5 + """, + arcz=".1 12 23 31 15 41 5.", arcz_missing="41") + + def test_nested_breaks(self): + self.check_coverage("""\ + for i in range(3): + for j in range(3): + a = i + j + break # 4 + if i == 2: + break + assert a == 2 and i == 2 # 7 + """, + arcz=".1 12 23 34 45 25 56 51 67 17 7.", arcz_missing="17 25") + + def test_while_true(self): + # With "while 1", the loop knows it's constant. + self.check_coverage("""\ + a, i = 1, 0 + while 1: + if i >= 3: + a = 4 + break + i += 1 + assert a == 4 and i == 3 + """, + arcz=".1 12 23 34 45 36 63 57 7.", + ) + # With "while True", 2.x thinks it's computation, 3.x thinks it's + # constant. + if sys.version_info >= (3, 0): + arcz = ".1 12 23 34 45 36 63 57 7." + else: + arcz = ".1 12 23 27 34 45 36 62 57 7." + self.check_coverage("""\ + a, i = 1, 0 + while True: + if i >= 3: + a = 4 + break + i += 1 + assert a == 4 and i == 3 + """, + arcz=arcz, + ) + + def test_for_if_else_for(self): + self.check_coverage("""\ + def branches_2(l): + if l: + for e in l: + a = 4 + else: + a = 6 + + def branches_3(l): + for x in l: + if x: + for e in l: + a = 12 + else: + a = 14 + + branches_2([0,1]) + branches_3([0,1]) + """, + arcz= + ".1 18 8G GH H. " + ".2 23 34 43 26 3. 6. " + ".9 9A 9-8 AB BC CB B9 AE E9", + arcz_missing="26 6." + ) + + def test_for_else(self): + self.check_coverage("""\ + def forelse(seq): + for n in seq: + if n > 5: + break + else: + print('None of the values were greater than 5') + print('Done') + forelse([1,2]) + forelse([1,6]) + """, + arcz=".1 .2 23 32 34 47 26 67 7. 18 89 9." + ) + + def test_confusing_for_loop_bug_175(self): + if sys.version_info >= (3, 0): + # Py3 counts the list comp as a separate code object. + arcz = ".1 .2 2-2 12 23 34 45 53 3." + else: + arcz = ".1 12 23 34 45 53 3." + self.check_coverage("""\ + o = [(1,2), (3,4)] + o = [a for a in o] + for tup in o: + x = tup[0] + y = tup[1] + """, + arcz=arcz, arcz_missing="", arcz_unpredicted="") + if sys.version_info >= (3, 0): + arcz = ".1 12 .2 2-2 23 34 42 2." + else: + arcz = ".1 12 23 34 42 2." + self.check_coverage("""\ + o = [(1,2), (3,4)] + for tup in [a for a in o]: + x = tup[0] + y = tup[1] + """, + arcz=arcz, arcz_missing="", arcz_unpredicted="") + + +class ExceptionArcTest(CoverageTest): + """Arc-measuring tests involving exception handling.""" + + def test_try_except(self): + self.check_coverage("""\ + a, b = 1, 1 + try: + a = 3 + except: + b = 5 + assert a == 3 and b == 1 + """, + arcz=".1 12 23 36 45 56 6.", arcz_missing="45 56") + self.check_coverage("""\ + a, b = 1, 1 + try: + a = 3 + raise Exception("Yikes!") + a = 5 + except: + b = 7 + assert a == 3 and b == 7 + """, + arcz=".1 12 23 34 58 67 78 8.", + arcz_missing="58", arcz_unpredicted="46") + + def test_hidden_raise(self): + self.check_coverage("""\ + a, b = 1, 1 + def oops(x): + if x % 2: raise Exception("odd") + try: + a = 5 + oops(1) + a = 7 + except: + b = 9 + assert a == 5 and b == 9 + """, + arcz=".1 12 .3 3-2 24 45 56 67 7A 89 9A A.", + arcz_missing="67 7A", arcz_unpredicted="68") + + def test_except_with_type(self): + self.check_coverage("""\ + a, b = 1, 1 + def oops(x): + if x % 2: raise ValueError("odd") + def try_it(x): + try: + a = 6 + oops(x) + a = 8 + except ValueError: + b = 10 + return a + assert try_it(0) == 8 # C + assert try_it(1) == 6 # D + """, + arcz=".1 12 .3 3-2 24 4C CD D. .5 56 67 78 8B 9A AB B-4", + arcz_missing="", + arcz_unpredicted="79") + + def test_try_finally(self): + self.check_coverage("""\ + a, c = 1, 1 + try: + a = 3 + finally: + c = 5 + assert a == 3 and c == 5 + """, + arcz=".1 12 23 35 56 6.", arcz_missing="") + self.check_coverage("""\ + a, c, d = 1, 1, 1 + try: + try: + a = 4 + finally: + c = 6 + except: + d = 8 + assert a == 4 and c == 6 and d == 1 # 9 + """, + arcz=".1 12 23 34 46 67 78 89 69 9.", + arcz_missing="67 78 89", arcz_unpredicted="") + self.check_coverage("""\ + a, c, d = 1, 1, 1 + try: + try: + a = 4 + raise Exception("Yikes!") + a = 6 + finally: + c = 8 + except: + d = 10 # A + assert a == 4 and c == 8 and d == 10 # B + """, + arcz=".1 12 23 34 45 68 89 8B 9A AB B.", + arcz_missing="68 8B", arcz_unpredicted="58") + + def test_finally_in_loop(self): + self.check_coverage("""\ + a, c, d, i = 1, 1, 1, 99 + try: + for i in range(5): + try: + a = 5 + if i > 0: + raise Exception("Yikes!") + a = 8 + finally: + c = 10 + except: + d = 12 # C + assert a == 5 and c == 10 and d == 12 # D + """, + arcz=".1 12 23 34 3D 45 56 67 68 8A A3 AB AD BC CD D.", + arcz_missing="3D AD", arcz_unpredicted="7A") + self.check_coverage("""\ + a, c, d, i = 1, 1, 1, 99 + try: + for i in range(5): + try: + a = 5 + if i > 10: + raise Exception("Yikes!") + a = 8 + finally: + c = 10 + except: + d = 12 # C + assert a == 8 and c == 10 and d == 1 # D + """, + arcz=".1 12 23 34 3D 45 56 67 68 8A A3 AB AD BC CD D.", + arcz_missing="67 AB AD BC CD", arcz_unpredicted="") + + + def test_break_in_finally(self): + self.check_coverage("""\ + a, c, d, i = 1, 1, 1, 99 + try: + for i in range(5): + try: + a = 5 + if i > 0: + break + a = 8 + finally: + c = 10 + except: + d = 12 # C + assert a == 5 and c == 10 and d == 1 # D + """, + arcz=".1 12 23 34 3D 45 56 67 68 7A 8A A3 AB AD BC CD D.", + arcz_missing="3D AB BC CD", arcz_unpredicted="") + + if 1: # expected failure + def test_finally_in_loop_bug_92(self): + self.check_coverage("""\ + for i in range(5): + try: + j = 3 + finally: + f = 5 + g = 6 + h = 7 + """, + arcz=".1 12 23 35 56 61 17 7.", + arcz_missing="", arcz_unpredicted="") + + if sys.version_info >= (2, 5): + # Try-except-finally was new in 2.5 + def test_except_finally(self): + self.check_coverage("""\ + a, b, c = 1, 1, 1 + try: + a = 3 + except: + b = 5 + finally: + c = 7 + assert a == 3 and b == 1 and c == 7 + """, + arcz=".1 12 23 45 37 57 78 8.", arcz_missing="45 57") + self.check_coverage("""\ + a, b, c = 1, 1, 1 + def oops(x): + if x % 2: raise Exception("odd") + try: + a = 5 + oops(1) + a = 7 + except: + b = 9 + finally: + c = 11 + assert a == 5 and b == 9 and c == 11 + """, + arcz=".1 12 .3 3-2 24 45 56 67 7B 89 9B BC C.", + arcz_missing="67 7B", arcz_unpredicted="68") + + +class MiscArcTest(CoverageTest): + """Miscellaneous arc-measuring tests.""" + + def test_dict_literal(self): + self.check_coverage("""\ + d = { + 'a': 2, + 'b': 3, + 'c': { + 'd': 5, + 'e': 6, + } + } + assert d + """, + arcz=".1 19 9.") + + +class ExcludeTest(CoverageTest): + """Tests of exclusions to indicate known partial branches.""" + + def test_default(self): + # A number of forms of pragma comment are accepted. + self.check_coverage("""\ + a = 1 + if a: #pragma: no branch + b = 3 + c = 4 + if c: # pragma NOBRANCH + d = 6 + e = 7 + """, + [1,2,3,4,5,6,7], + arcz=".1 12 23 24 34 45 56 57 67 7.", arcz_missing="") + + def test_custom_pragmas(self): + self.check_coverage("""\ + a = 1 + while a: # [only some] + c = 3 + break + assert c == 5-2 + """, + [1,2,3,4,5], + partials=["only some"], + arcz=".1 12 23 34 45 25 5.", arcz_missing="") diff --git a/tests/test_cmdline.py b/tests/test_cmdline.py new file mode 100644 index 00000000..33f90212 --- /dev/null +++ b/tests/test_cmdline.py @@ -0,0 +1,702 @@ +"""Test cmdline.py for coverage.""" + +import pprint, re, shlex, sys, textwrap +import mock +import coverage +import coverage.cmdline +from coverage.misc import ExceptionDuringRun + +from test.coveragetest import CoverageTest, OK, ERR + + +class CmdLineTest(CoverageTest): + """Tests of execution paths through the command line interpreter.""" + + run_in_temp_dir = False + + INIT_LOAD = """\ + .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=None) + .load()\n""" + + def model_object(self): + """Return a Mock suitable for use in CoverageScript.""" + mk = mock.Mock() + mk.coverage.return_value = mk + return mk + + def mock_command_line(self, args): + """Run `args` through the command line, with a Mock. + + Returns the Mock it used and the status code returned. + + """ + m = self.model_object() + ret = coverage.CoverageScript( + _covpkg=m, _run_python_file=m.run_python_file, + _run_python_module=m.run_python_module, _help_fn=m.help_fn + ).command_line(shlex.split(args)) + return m, ret + + def cmd_executes(self, args, code, ret=OK): + """Assert that the `args` end up executing the sequence in `code`.""" + m1, r1 = self.mock_command_line(args) + self.assertEqual(r1, ret, + "Wrong status: got %s, wanted %s" % (r1, ret) + ) + + # Remove all indentation, and change ".foo()" to "m2.foo()". + code = re.sub(r"(?m)^\s+", "", code) + code = re.sub(r"(?m)^\.", "m2.", code) + m2 = self.model_object() + code_obj = compile(code, "", "exec") + eval(code_obj, globals(), { 'm2': m2 }) + self.assert_same_method_calls(m1, m2) + + def cmd_executes_same(self, args1, args2): + """Assert that the `args1` executes the same as `args2`.""" + m1, r1 = self.mock_command_line(args1) + m2, r2 = self.mock_command_line(args2) + self.assertEqual(r1, r2) + self.assert_same_method_calls(m1, m2) + + def assert_same_method_calls(self, m1, m2): + """Assert that `m1.method_calls` and `m2.method_calls` are the same.""" + # Use a real equality comparison, but if it fails, use a nicer assert + # so we can tell what's going on. We have to use the real == first due + # to CmdOptionParser.__eq__ + if m1.method_calls != m2.method_calls: + pp1 = pprint.pformat(m1.method_calls) + pp2 = pprint.pformat(m2.method_calls) + self.assertMultiLineEqual(pp1+'\n', pp2+'\n') + + def cmd_help(self, args, help_msg=None, topic=None, ret=ERR): + """Run a command line, and check that it prints the right help. + + Only the last function call in the mock is checked, which should be the + help message that we want to see. + + """ + m, r = self.mock_command_line(args) + self.assertEqual(r, ret, + "Wrong status: got %s, wanted %s" % (r, ret) + ) + if help_msg: + self.assertEqual(m.method_calls[-1], + ('help_fn', (help_msg,), {}) + ) + else: + self.assertEqual(m.method_calls[-1], + ('help_fn', (), {'topic':topic}) + ) + + +class CmdLineTestTest(CmdLineTest): + """Tests that our CmdLineTest helpers work.""" + def test_assert_same_method_calls(self): + # All the other tests here use self.cmd_executes_same in successful + # ways, so here we just check that it fails. + self.assertRaises(AssertionError, self.cmd_executes_same, "-e", "-c") + + +class ClassicCmdLineTest(CmdLineTest): + """Tests of the classic coverage.py command line.""" + + def test_erase(self): + # coverage -e + self.cmd_executes("-e", """\ + .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=None) + .erase() + """) + self.cmd_executes_same("-e", "--erase") + + def test_execute(self): + # coverage -x [-p] [-L] [--timid] MODULE.py [ARG1 ARG2 ...] + + # -x calls coverage.load first. + self.cmd_executes("-x foo.py", """\ + .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=None) + .load() + .start() + .run_python_file('foo.py', ['foo.py']) + .stop() + .save() + """) + # -e -x calls coverage.erase first. + self.cmd_executes("-e -x foo.py", """\ + .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=None) + .erase() + .start() + .run_python_file('foo.py', ['foo.py']) + .stop() + .save() + """) + # --timid sets a flag, and program arguments get passed through. + self.cmd_executes("-x --timid foo.py abc 123", """\ + .coverage(cover_pylib=None, data_suffix=None, timid=True, branch=None, config_file=True, source=None, include=None, omit=None) + .load() + .start() + .run_python_file('foo.py', ['foo.py', 'abc', '123']) + .stop() + .save() + """) + # -L sets a flag, and flags for the program don't confuse us. + self.cmd_executes("-x -p -L foo.py -a -b", """\ + .coverage(cover_pylib=True, data_suffix=True, timid=None, branch=None, config_file=True, source=None, include=None, omit=None) + .load() + .start() + .run_python_file('foo.py', ['foo.py', '-a', '-b']) + .stop() + .save() + """) + + # Check that long forms of flags do the same thing as short forms. + self.cmd_executes_same("-x f.py", "--execute f.py") + self.cmd_executes_same("-e -x f.py", "--erase --execute f.py") + self.cmd_executes_same("-x -p f.py", "-x --parallel-mode f.py") + self.cmd_executes_same("-x -L f.py", "-x --pylib f.py") + + def test_combine(self): + # coverage -c + self.cmd_executes("-c", """\ + .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=None) + .load() + .combine() + .save() + """) + self.cmd_executes_same("-c", "--combine") + + def test_report(self): + # coverage -r [-m] [-i] [-o DIR,...] [FILE1 FILE2 ...] + self.cmd_executes("-r", self.INIT_LOAD + """\ + .report(ignore_errors=None, omit=None, include=None, morfs=[], + show_missing=None) + """) + self.cmd_executes("-r -i", self.INIT_LOAD + """\ + .report(ignore_errors=True, omit=None, include=None, morfs=[], + show_missing=None) + """) + self.cmd_executes("-r -m", self.INIT_LOAD + """\ + .report(ignore_errors=None, omit=None, include=None, morfs=[], + show_missing=True) + """) + self.cmd_executes("-r -o fooey", """\ + .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["fooey"]) + .load() + .report(ignore_errors=None, omit=["fooey"], include=None, + morfs=[], show_missing=None) + """) + self.cmd_executes("-r -o fooey,booey", """\ + .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["fooey", "booey"]) + .load() + .report(ignore_errors=None, omit=["fooey", "booey"], include=None, + morfs=[], show_missing=None) + """) + self.cmd_executes("-r mod1", self.INIT_LOAD + """\ + .report(ignore_errors=None, omit=None, include=None, + morfs=["mod1"], show_missing=None) + """) + self.cmd_executes("-r mod1 mod2 mod3", self.INIT_LOAD + """\ + .report(ignore_errors=None, omit=None, include=None, + morfs=["mod1", "mod2", "mod3"], show_missing=None) + """) + + self.cmd_executes_same("-r", "--report") + self.cmd_executes_same("-r -i", "-r --ignore-errors") + self.cmd_executes_same("-r -m", "-r --show-missing") + self.cmd_executes_same("-r -o f", "-r --omit=f") + self.cmd_executes_same("-r -o f", "-r --omit f") + self.cmd_executes_same("-r -o f,b", "-r --omit=f,b") + self.cmd_executes_same("-r -o f,b", "-r --omit f,b") + self.cmd_executes_same("-r -of", "-r --omit=f") + self.cmd_executes_same("-r -of,b", "-r --omit=f,b") + + def test_annotate(self): + # coverage -a [-d DIR] [-i] [-o DIR,...] [FILE1 FILE2 ...] + self.cmd_executes("-a", self.INIT_LOAD + """\ + .annotate(directory=None, ignore_errors=None, + omit=None, include=None, morfs=[]) + """) + self.cmd_executes("-a -d dir1", self.INIT_LOAD + """\ + .annotate(directory="dir1", ignore_errors=None, + omit=None, include=None, morfs=[]) + """) + self.cmd_executes("-a -i", self.INIT_LOAD + """\ + .annotate(directory=None, ignore_errors=True, + omit=None, include=None, morfs=[]) + """) + self.cmd_executes("-a -o fooey", """\ + .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["fooey"]) + .load() + .annotate(directory=None, ignore_errors=None, + omit=["fooey"], include=None, morfs=[]) + """) + self.cmd_executes("-a -o fooey,booey", """\ + .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["fooey", "booey"]) + .load() + .annotate(directory=None, ignore_errors=None, + omit=["fooey", "booey"], include=None, morfs=[]) + """) + self.cmd_executes("-a mod1", self.INIT_LOAD + """\ + .annotate(directory=None, ignore_errors=None, + omit=None, include=None, morfs=["mod1"]) + """) + self.cmd_executes("-a mod1 mod2 mod3", self.INIT_LOAD + """\ + .annotate(directory=None, ignore_errors=None, + omit=None, include=None, morfs=["mod1", "mod2", "mod3"]) + """) + + self.cmd_executes_same("-a", "--annotate") + self.cmd_executes_same("-a -d d1", "-a --directory=d1") + self.cmd_executes_same("-a -i", "-a --ignore-errors") + self.cmd_executes_same("-a -o f", "-a --omit=f") + self.cmd_executes_same("-a -o f", "-a --omit f") + self.cmd_executes_same("-a -o f,b", "-a --omit=f,b") + self.cmd_executes_same("-a -o f,b", "-a --omit f,b") + self.cmd_executes_same("-a -of", "-a --omit=f") + self.cmd_executes_same("-a -of,b", "-a --omit=f,b") + + def test_html_report(self): + # coverage -b -d DIR [-i] [-o DIR,...] [FILE1 FILE2 ...] + self.cmd_executes("-b", self.INIT_LOAD + """\ + .html_report(directory=None, ignore_errors=None, title=None, + omit=None, include=None, morfs=[]) + """) + self.cmd_executes("-b -d dir1", self.INIT_LOAD + """\ + .html_report(directory="dir1", ignore_errors=None, title=None, + omit=None, include=None, morfs=[]) + """) + self.cmd_executes("-b -i", self.INIT_LOAD + """\ + .html_report(directory=None, ignore_errors=True, title=None, + omit=None, include=None, morfs=[]) + """) + self.cmd_executes("-b -o fooey", """\ + .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["fooey"]) + .load() + .html_report(directory=None, ignore_errors=None, title=None, + omit=["fooey"], include=None, morfs=[]) + """) + self.cmd_executes("-b -o fooey,booey", """\ + .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["fooey", "booey"]) + .load() + .html_report(directory=None, ignore_errors=None, title=None, + omit=["fooey", "booey"], include=None, morfs=[]) + """) + self.cmd_executes("-b mod1", self.INIT_LOAD + """\ + .html_report(directory=None, ignore_errors=None, title=None, + omit=None, include=None, morfs=["mod1"]) + """) + self.cmd_executes("-b mod1 mod2 mod3", self.INIT_LOAD + """\ + .html_report(directory=None, ignore_errors=None, title=None, + omit=None, include=None, morfs=["mod1", "mod2", "mod3"]) + """) + + self.cmd_executes_same("-b", "--html") + self.cmd_executes_same("-b -d d1", "-b --directory=d1") + self.cmd_executes_same("-b -i", "-b --ignore-errors") + self.cmd_executes_same("-b -o f", "-b --omit=f") + self.cmd_executes_same("-b -o f,b", "-b --omit=f,b") + self.cmd_executes_same("-b -of", "-b --omit=f") + self.cmd_executes_same("-b -of,b", "-b --omit=f,b") + + def test_help(self): + # coverage -h + self.cmd_help("-h", topic="help", ret=OK) + self.cmd_help("--help", topic="help", ret=OK) + + def test_version(self): + # coverage --version + self.cmd_help("--version", topic="version", ret=OK) + + ## Error cases + + def test_argless_actions(self): + self.cmd_help("-e foo bar", "Unexpected arguments: foo bar") + self.cmd_help("-c baz quux", "Unexpected arguments: baz quux") + + def test_need_action(self): + self.cmd_help("-p", "You must specify at least one of " + "-e, -x, -c, -r, -a, or -b.") + + def test_bad_action_combinations(self): + self.cmd_help('-e -a', + "You can't specify the 'erase' and 'annotate' " + "options at the same time." + ) + self.cmd_help('-e -r', + "You can't specify the 'erase' and 'report' " + "options at the same time." + ) + self.cmd_help('-e -b', + "You can't specify the 'erase' and 'html' " + "options at the same time." + ) + self.cmd_help('-e -c', + "You can't specify the 'erase' and 'combine' " + "options at the same time." + ) + self.cmd_help('-x -a', + "You can't specify the 'execute' and 'annotate' " + "options at the same time." + ) + self.cmd_help('-x -r', + "You can't specify the 'execute' and 'report' " + "options at the same time." + ) + self.cmd_help('-x -b', + "You can't specify the 'execute' and 'html' " + "options at the same time." + ) + self.cmd_help('-x -c', + "You can't specify the 'execute' and 'combine' " + "options at the same time." + ) + + def test_nothing_to_do(self): + self.cmd_help("-x", "Nothing to do.") + + def test_unknown_option(self): + self.cmd_help("-z", "no such option: -z") + + +class FakeCoverageForDebugData(object): + """Just enough of a fake coverage package for the 'debug data' tests.""" + def __init__(self, summary): + self._summary = summary + self.filename = "FILENAME" + self.data = self + + # package members + def coverage(self, *unused_args, **unused_kwargs): + """The coverage class in the package.""" + return self + + # coverage methods + def load(self): + """Fake coverage().load()""" + pass + + # data methods + def has_arcs(self): + """Fake coverage().data.has_arcs()""" + return False + + def summary(self, fullpath): # pylint: disable=W0613 + """Fake coverage().data.summary()""" + return self._summary + + +class NewCmdLineTest(CmdLineTest): + """Tests of the coverage.py command line.""" + + def test_annotate(self): + self.cmd_executes_same("annotate", "-a") + self.cmd_executes_same("annotate -i", "-a -i") + self.cmd_executes_same("annotate -d d1", "-a -d d1") + self.cmd_executes_same("annotate --omit f", "-a --omit f") + self.cmd_executes_same("annotate --omit f,b", "-a --omit f,b") + self.cmd_executes_same("annotate m1", "-a m1") + self.cmd_executes_same("annotate m1 m2 m3", "-a m1 m2 m3") + + def test_combine(self): + self.cmd_executes_same("combine", "-c") + + def test_debug(self): + self.cmd_help("debug", "What information would you like: data, sys?") + self.cmd_help("debug foo", "Don't know what you mean by 'foo'") + + def test_debug_data(self): + fake = FakeCoverageForDebugData({ + 'file1.py': 17, 'file2.py': 23, + }) + self.command_line("debug data", _covpkg=fake) + self.assertMultiLineEqual(self.stdout(), textwrap.dedent("""\ + -- data --------------------------------------- + path: FILENAME + has_arcs: False + + 2 files: + file1.py: 17 lines + file2.py: 23 lines + """)) + + def test_debug_data_with_no_data(self): + fake = FakeCoverageForDebugData({}) + self.command_line("debug data", _covpkg=fake) + self.assertMultiLineEqual(self.stdout(), textwrap.dedent("""\ + -- data --------------------------------------- + path: FILENAME + has_arcs: False + No data collected + """)) + + def test_debug_sys(self): + self.command_line("debug sys") + out = self.stdout() + assert "version:" in out + assert "data_path:" in out + + def test_erase(self): + self.cmd_executes_same("erase", "-e") + + def test_help(self): + self.cmd_executes("help", ".help_fn(topic='help')") + + def test_cmd_help(self): + self.cmd_executes("run --help", + ".help_fn(parser='')") + self.cmd_executes_same("help run", "run --help") + + def test_html(self): + self.cmd_executes_same("html", "-b") + self.cmd_executes_same("html -i", "-b -i") + self.cmd_executes_same("html -d d1", "-b -d d1") + self.cmd_executes_same("html --omit f", "-b --omit f") + self.cmd_executes_same("html --omit f,b", "-b --omit f,b") + self.cmd_executes_same("html m1", "-b m1") + self.cmd_executes_same("html m1 m2 m3", "-b m1 m2 m3") + self.cmd_executes("html", self.INIT_LOAD + """\ + .html_report(ignore_errors=None, omit=None, include=None, morfs=[], + directory=None, title=None) + """) + self.cmd_executes("html --title=Hello_there", self.INIT_LOAD + """\ + .html_report(ignore_errors=None, omit=None, include=None, morfs=[], + directory=None, title='Hello_there') + """) + + def test_report(self): + self.cmd_executes_same("report", "-r") + self.cmd_executes_same("report -i", "-r -i") + self.cmd_executes_same("report -m", "-r -m") + self.cmd_executes_same("report --omit f", "-r --omit f") + self.cmd_executes_same("report --omit f,b", "-r --omit f,b") + self.cmd_executes_same("report m1", "-r m1") + self.cmd_executes_same("report m1 m2 m3", "-r m1 m2 m3") + + def test_run(self): + self.cmd_executes_same("run f.py", "-e -x f.py") + self.cmd_executes_same("run f.py -a arg -z", "-e -x f.py -a arg -z") + self.cmd_executes_same("run -a f.py", "-x f.py") + self.cmd_executes_same("run -p f.py", "-e -x -p f.py") + self.cmd_executes_same("run -L f.py", "-e -x -L f.py") + self.cmd_executes_same("run --timid f.py", "-e -x --timid f.py") + self.cmd_executes_same("run", "-x") + self.cmd_executes("run --branch foo.py", """\ + .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=True, config_file=True, source=None, include=None, omit=None) + .erase() + .start() + .run_python_file('foo.py', ['foo.py']) + .stop() + .save() + """) + self.cmd_executes("run --rcfile=myrc.rc foo.py", """\ + .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file="myrc.rc", source=None, include=None, omit=None) + .erase() + .start() + .run_python_file('foo.py', ['foo.py']) + .stop() + .save() + """) + self.cmd_executes("run --include=pre1,pre2 foo.py", """\ + .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=["pre1", "pre2"], omit=None) + .erase() + .start() + .run_python_file('foo.py', ['foo.py']) + .stop() + .save() + """) + self.cmd_executes("run --omit=opre1,opre2 foo.py", """\ + .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["opre1", "opre2"]) + .erase() + .start() + .run_python_file('foo.py', ['foo.py']) + .stop() + .save() + """) + self.cmd_executes("run --include=pre1,pre2 --omit=opre1,opre2 foo.py", + """\ + .coverage(cover_pylib=None, data_suffix=None, timid=None, + branch=None, config_file=True, source=None, + include=["pre1", "pre2"], + omit=["opre1", "opre2"]) + .erase() + .start() + .run_python_file('foo.py', ['foo.py']) + .stop() + .save() + """) + self.cmd_executes("run --source=quux,hi.there,/home/bar foo.py", + """\ + .coverage(cover_pylib=None, data_suffix=None, timid=None, + branch=None, config_file=True, + source=["quux", "hi.there", "/home/bar"], include=None, + omit=None) + .erase() + .start() + .run_python_file('foo.py', ['foo.py']) + .stop() + .save() + """) + + def test_run_module(self): + self.cmd_executes("run -m mymodule", """\ + .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=None) + .erase() + .start() + .run_python_module('mymodule', ['mymodule']) + .stop() + .save() + """) + self.cmd_executes("run -m mymodule -qq arg1 arg2", """\ + .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=None) + .erase() + .start() + .run_python_module('mymodule', ['mymodule', '-qq', 'arg1', 'arg2']) + .stop() + .save() + """) + self.cmd_executes("run --branch -m mymodule", """\ + .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=True, config_file=True, source=None, include=None, omit=None) + .erase() + .start() + .run_python_module('mymodule', ['mymodule']) + .stop() + .save() + """) + self.cmd_executes_same("run -m mymodule", "run --module mymodule") + + def test_xml(self): + # coverage xml [-i] [--omit DIR,...] [FILE1 FILE2 ...] + self.cmd_executes("xml", self.INIT_LOAD + """\ + .xml_report(ignore_errors=None, omit=None, include=None, morfs=[], + outfile=None) + """) + self.cmd_executes("xml -i", self.INIT_LOAD + """\ + .xml_report(ignore_errors=True, omit=None, include=None, morfs=[], + outfile=None) + """) + self.cmd_executes("xml -o myxml.foo", self.INIT_LOAD + """\ + .xml_report(ignore_errors=None, omit=None, include=None, morfs=[], + outfile="myxml.foo") + """) + self.cmd_executes("xml -o -", self.INIT_LOAD + """\ + .xml_report(ignore_errors=None, omit=None, include=None, morfs=[], + outfile="-") + """) + self.cmd_executes("xml --omit fooey", """\ + .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["fooey"]) + .load() + .xml_report(ignore_errors=None, omit=["fooey"], include=None, morfs=[], + outfile=None) + """) + self.cmd_executes("xml --omit fooey,booey", """\ + .coverage(cover_pylib=None, data_suffix=None, timid=None, branch=None, config_file=True, source=None, include=None, omit=["fooey", "booey"]) + .load() + .xml_report(ignore_errors=None, omit=["fooey", "booey"], include=None, + morfs=[], outfile=None) + """) + self.cmd_executes("xml mod1", self.INIT_LOAD + """\ + .xml_report(ignore_errors=None, omit=None, include=None, morfs=["mod1"], + outfile=None) + """) + self.cmd_executes("xml mod1 mod2 mod3", self.INIT_LOAD + """\ + .xml_report(ignore_errors=None, omit=None, include=None, + morfs=["mod1", "mod2", "mod3"], outfile=None) + """) + + def test_no_arguments_at_all(self): + self.cmd_help("", topic="minimum_help", ret=OK) + + def test_bad_command(self): + self.cmd_help("xyzzy", "Unknown command: 'xyzzy'") + + +class CmdLineStdoutTest(CmdLineTest): + """Test the command line with real stdout output.""" + + def test_minimum_help(self): + self.command_line("") + out = self.stdout() + assert "Code coverage for Python." in out + assert out.count("\n") < 4 + + def test_version(self): + self.command_line("--version") + out = self.stdout() + assert "ersion " in out + assert out.count("\n") < 4 + + def test_help(self): + self.command_line("help") + out = self.stdout() + assert "nedbatchelder.com" in out + assert out.count("\n") > 10 + + def test_cmd_help(self): + self.command_line("help run") + out = self.stdout() + assert "" in out + assert "--timid" in out + assert out.count("\n") > 10 + + def test_error(self): + self.command_line("fooey kablooey", ret=ERR) + out = self.stdout() + assert "fooey" in out + assert "help" in out + + +class CmdMainTest(CoverageTest): + """Tests of coverage.cmdline.main(), using mocking for isolation.""" + + class CoverageScriptStub(object): + """A stub for coverage.cmdline.CoverageScript, used by CmdMainTest.""" + + def command_line(self, argv): + """Stub for command_line, the arg determines what it will do.""" + if argv[0] == 'hello': + print("Hello, world!") + elif argv[0] == 'raise': + try: + raise Exception("oh noes!") + except: + raise ExceptionDuringRun(*sys.exc_info()) + elif argv[0] == 'internalraise': + raise ValueError("coverage is broken") + elif argv[0] == 'exit': + sys.exit(23) + else: + raise AssertionError("Bad CoverageScriptStub: %r"% (argv,)) + return 0 + + def setUp(self): + super(CmdMainTest, self).setUp() + self.old_CoverageScript = coverage.cmdline.CoverageScript + coverage.cmdline.CoverageScript = self.CoverageScriptStub + + def tearDown(self): + coverage.cmdline.CoverageScript = self.old_CoverageScript + super(CmdMainTest, self).tearDown() + + def test_normal(self): + ret = coverage.cmdline.main(['hello']) + self.assertEqual(ret, 0) + self.assertEqual(self.stdout(), "Hello, world!\n") + + def test_raise(self): + ret = coverage.cmdline.main(['raise']) + self.assertEqual(ret, 1) + self.assertEqual(self.stdout(), "") + err = self.stderr().split('\n') + self.assertEqual(err[0], 'Traceback (most recent call last):') + self.assertEqual(err[-3], ' raise Exception("oh noes!")') + self.assertEqual(err[-2], 'Exception: oh noes!') + + def test_internalraise(self): + self.assertRaisesRegexp(ValueError, + "coverage is broken", + coverage.cmdline.main, ['internalraise'] + ) + + def test_exit(self): + ret = coverage.cmdline.main(['exit']) + self.assertEqual(ret, 23) diff --git a/tests/test_codeunit.py b/tests/test_codeunit.py new file mode 100644 index 00000000..b4caff88 --- /dev/null +++ b/tests/test_codeunit.py @@ -0,0 +1,103 @@ +"""Tests for coverage.codeunit""" + +import os, sys + +from coverage.codeunit import code_unit_factory +from coverage.files import FileLocator + +from test.coveragetest import CoverageTest + +# pylint: disable=F0401 +# Unable to import 'aa' (No module named aa) + +class CodeUnitTest(CoverageTest): + """Tests for coverage.codeunit""" + + run_in_temp_dir = False + + def setUp(self): + super(CodeUnitTest, self).setUp() + # Parent class saves and restores sys.path, we can just modify it. + testmods = self.nice_file(os.path.dirname(__file__), 'modules') + sys.path.append(testmods) + + def test_filenames(self): + acu = code_unit_factory("aa/afile.py", FileLocator()) + bcu = code_unit_factory("aa/bb/bfile.py", FileLocator()) + ccu = code_unit_factory("aa/bb/cc/cfile.py", FileLocator()) + self.assertEqual(acu[0].name, "aa/afile") + self.assertEqual(bcu[0].name, "aa/bb/bfile") + self.assertEqual(ccu[0].name, "aa/bb/cc/cfile") + self.assertEqual(acu[0].flat_rootname(), "aa_afile") + self.assertEqual(bcu[0].flat_rootname(), "aa_bb_bfile") + self.assertEqual(ccu[0].flat_rootname(), "aa_bb_cc_cfile") + self.assertEqual(acu[0].source_file().read(), "# afile.py\n") + self.assertEqual(bcu[0].source_file().read(), "# bfile.py\n") + self.assertEqual(ccu[0].source_file().read(), "# cfile.py\n") + + def test_odd_filenames(self): + acu = code_unit_factory("aa/afile.odd.py", FileLocator()) + bcu = code_unit_factory("aa/bb/bfile.odd.py", FileLocator()) + b2cu = code_unit_factory("aa/bb.odd/bfile.py", FileLocator()) + self.assertEqual(acu[0].name, "aa/afile.odd") + self.assertEqual(bcu[0].name, "aa/bb/bfile.odd") + self.assertEqual(b2cu[0].name, "aa/bb.odd/bfile") + self.assertEqual(acu[0].flat_rootname(), "aa_afile_odd") + self.assertEqual(bcu[0].flat_rootname(), "aa_bb_bfile_odd") + self.assertEqual(b2cu[0].flat_rootname(), "aa_bb_odd_bfile") + self.assertEqual(acu[0].source_file().read(), "# afile.odd.py\n") + self.assertEqual(bcu[0].source_file().read(), "# bfile.odd.py\n") + self.assertEqual(b2cu[0].source_file().read(), "# bfile.py\n") + + def test_modules(self): + import aa, aa.bb, aa.bb.cc + cu = code_unit_factory([aa, aa.bb, aa.bb.cc], FileLocator()) + self.assertEqual(cu[0].name, "aa") + self.assertEqual(cu[1].name, "aa.bb") + self.assertEqual(cu[2].name, "aa.bb.cc") + self.assertEqual(cu[0].flat_rootname(), "aa") + self.assertEqual(cu[1].flat_rootname(), "aa_bb") + self.assertEqual(cu[2].flat_rootname(), "aa_bb_cc") + self.assertEqual(cu[0].source_file().read(), "# aa\n") + self.assertEqual(cu[1].source_file().read(), "# bb\n") + self.assertEqual(cu[2].source_file().read(), "") # yes, empty + + def test_module_files(self): + import aa.afile, aa.bb.bfile, aa.bb.cc.cfile + cu = code_unit_factory([aa.afile, aa.bb.bfile, aa.bb.cc.cfile], + FileLocator()) + self.assertEqual(cu[0].name, "aa.afile") + self.assertEqual(cu[1].name, "aa.bb.bfile") + self.assertEqual(cu[2].name, "aa.bb.cc.cfile") + self.assertEqual(cu[0].flat_rootname(), "aa_afile") + self.assertEqual(cu[1].flat_rootname(), "aa_bb_bfile") + self.assertEqual(cu[2].flat_rootname(), "aa_bb_cc_cfile") + self.assertEqual(cu[0].source_file().read(), "# afile.py\n") + self.assertEqual(cu[1].source_file().read(), "# bfile.py\n") + self.assertEqual(cu[2].source_file().read(), "# cfile.py\n") + + def test_comparison(self): + acu = code_unit_factory("aa/afile.py", FileLocator())[0] + acu2 = code_unit_factory("aa/afile.py", FileLocator())[0] + zcu = code_unit_factory("aa/zfile.py", FileLocator())[0] + bcu = code_unit_factory("aa/bb/bfile.py", FileLocator())[0] + assert acu == acu2 and acu <= acu2 and acu >= acu2 + assert acu < zcu and acu <= zcu and acu != zcu + assert zcu > acu and zcu >= acu and zcu != acu + assert acu < bcu and acu <= bcu and acu != bcu + assert bcu > acu and bcu >= acu and bcu != acu + + def test_egg(self): + # Test that we can get files out of eggs, and read their source files. + # The egg1 module is installed by an action in igor.py. + import egg1, egg1.egg1 + # Verify that we really imported from an egg. If we did, then the + # __file__ won't be an actual file, because one of the "directories" + # in the path is actually the .egg zip file. + self.assert_doesnt_exist(egg1.__file__) + + cu = code_unit_factory([egg1, egg1.egg1], FileLocator()) + self.assertEqual(cu[0].source_file().read(), "") + self.assertEqual(cu[1].source_file().read().split("\n")[0], + "# My egg file!" + ) diff --git a/tests/test_config.py b/tests/test_config.py new file mode 100644 index 00000000..1ca63765 --- /dev/null +++ b/tests/test_config.py @@ -0,0 +1,225 @@ +# -*- coding: utf-8 -*- +"""Test the config file handling for coverage.py""" + +import sys +import coverage +from coverage.misc import CoverageException + +from test.coveragetest import CoverageTest + + +class ConfigTest(CoverageTest): + """Tests of the different sources of configuration settings.""" + + def test_default_config(self): + # Just constructing a coverage() object gets the right defaults. + cov = coverage.coverage() + self.assertFalse(cov.config.timid) + self.assertFalse(cov.config.branch) + self.assertEqual(cov.config.data_file, ".coverage") + + def test_arguments(self): + # Arguments to the constructor are applied to the configuation. + cov = coverage.coverage(timid=True, data_file="fooey.dat") + self.assertTrue(cov.config.timid) + self.assertFalse(cov.config.branch) + self.assertEqual(cov.config.data_file, "fooey.dat") + + def test_config_file(self): + # A .coveragerc file will be read into the configuration. + self.make_file(".coveragerc", """\ + # This is just a bogus .rc file for testing. + [run] + timid = True + data_file = .hello_kitty.data + """) + cov = coverage.coverage() + self.assertTrue(cov.config.timid) + self.assertFalse(cov.config.branch) + self.assertEqual(cov.config.data_file, ".hello_kitty.data") + + def test_named_config_file(self): + # You can name the config file what you like. + self.make_file("my_cov.ini", """\ + [run] + timid = True + ; I wouldn't really use this as a data file... + data_file = delete.me + """) + cov = coverage.coverage(config_file="my_cov.ini") + self.assertTrue(cov.config.timid) + self.assertFalse(cov.config.branch) + self.assertEqual(cov.config.data_file, "delete.me") + + def test_ignored_config_file(self): + # You can disable reading the .coveragerc file. + self.make_file(".coveragerc", """\ + [run] + timid = True + data_file = delete.me + """) + cov = coverage.coverage(config_file=False) + self.assertFalse(cov.config.timid) + self.assertFalse(cov.config.branch) + self.assertEqual(cov.config.data_file, ".coverage") + + def test_config_file_then_args(self): + # The arguments override the .coveragerc file. + self.make_file(".coveragerc", """\ + [run] + timid = True + data_file = weirdo.file + """) + cov = coverage.coverage(timid=False, data_file=".mycov") + self.assertFalse(cov.config.timid) + self.assertFalse(cov.config.branch) + self.assertEqual(cov.config.data_file, ".mycov") + + def test_data_file_from_environment(self): + # There's an environment variable for the data_file. + self.make_file(".coveragerc", """\ + [run] + timid = True + data_file = weirdo.file + """) + self.set_environ("COVERAGE_FILE", "fromenv.dat") + cov = coverage.coverage() + self.assertEqual(cov.config.data_file, "fromenv.dat") + # But the constructor args override the env var. + cov = coverage.coverage(data_file="fromarg.dat") + self.assertEqual(cov.config.data_file, "fromarg.dat") + + def test_parse_errors(self): + # Im-parseable values raise CoverageException + self.make_file(".coveragerc", """\ + [run] + timid = maybe? + """) + self.assertRaises(CoverageException, coverage.coverage) + + def test_environment_vars_in_config(self): + # Config files can have $envvars in them. + self.make_file(".coveragerc", """\ + [run] + data_file = $DATA_FILE.fooey + branch = $OKAY + [report] + exclude_lines = + the_$$one + another${THING} + x${THING}y + x${NOTHING}y + huh$${X}what + """) + self.set_environ("DATA_FILE", "hello-world") + self.set_environ("THING", "ZZZ") + self.set_environ("OKAY", "yes") + cov = coverage.coverage() + self.assertEqual(cov.config.data_file, "hello-world.fooey") + self.assertEqual(cov.config.branch, True) + self.assertEqual(cov.config.exclude_list, + ["the_$one", "anotherZZZ", "xZZZy", "xy", "huh${X}what"] + ) + + +class ConfigFileTest(CoverageTest): + """Tests of the config file settings in particular.""" + + def test_config_file_settings(self): + # This sample file tries to use lots of variation of syntax... + self.make_file(".coveragerc", """\ + # This is a settings file for coverage.py + [run] + timid = yes + data_file = something_or_other.dat + branch = 1 + cover_pylib = TRUE + parallel = on + include = a/ , b/ + + [report] + ; these settings affect reporting. + exclude_lines = + if 0: + + pragma:?\\s+no cover + another_tab + + ignore_errors = TRUE + omit = + one, another, some_more, + yet_more + precision = 3 + + partial_branches = + pragma:?\\s+no branch + partial_branches_always = + if 0: + while True: + + show_missing= TruE + + [html] + + directory = c:\\tricky\\dir.somewhere + extra_css=something/extra.css + title = Title & nums # nums! + [xml] + output=mycov.xml + + [paths] + source = + . + /home/ned/src/ + + other = other, /home/ned/other, c:\\Ned\\etc + + """) + cov = coverage.coverage() + + self.assertTrue(cov.config.timid) + self.assertEqual(cov.config.data_file, "something_or_other.dat") + self.assertTrue(cov.config.branch) + self.assertTrue(cov.config.cover_pylib) + self.assertTrue(cov.config.parallel) + + self.assertEqual(cov.get_exclude_list(), + ["if 0:", r"pragma:?\s+no cover", "another_tab"] + ) + self.assertTrue(cov.config.ignore_errors) + self.assertEqual(cov.config.include, ["a/", "b/"]) + self.assertEqual(cov.config.omit, + ["one", "another", "some_more", "yet_more"] + ) + self.assertEqual(cov.config.precision, 3) + + self.assertEqual(cov.config.partial_list, + [r"pragma:?\s+no branch"] + ) + self.assertEqual(cov.config.partial_always_list, + ["if 0:", "while True:"] + ) + self.assertTrue(cov.config.show_missing) + self.assertEqual(cov.config.html_dir, r"c:\tricky\dir.somewhere") + self.assertEqual(cov.config.extra_css, "something/extra.css") + self.assertEqual(cov.config.html_title, "Title & nums # nums!") + + self.assertEqual(cov.config.xml_output, "mycov.xml") + + self.assertEqual(cov.config.paths, { + 'source': ['.', '/home/ned/src/'], + 'other': ['other', '/home/ned/other', 'c:\\Ned\\etc'] + }) + + if sys.version_info[:2] != (3,1): + def test_one(self): + # This sample file tries to use lots of variation of syntax... + self.make_file(".coveragerc", """\ + [html] + title = tabblo & «ταБЬℓσ» # numbers + """) + cov = coverage.coverage() + + self.assertEqual(cov.config.html_title, + "tabblo & «ταБЬℓσ» # numbers" + ) diff --git a/tests/test_coverage.py b/tests/test_coverage.py new file mode 100644 index 00000000..0918dfe1 --- /dev/null +++ b/tests/test_coverage.py @@ -0,0 +1,1730 @@ +"""Tests for Coverage.""" +# http://nedbatchelder.com/code/coverage + +import sys +import coverage +from coverage.misc import CoverageException +from test.coveragetest import CoverageTest + + +class TestCoverageTest(CoverageTest): + """Make sure our complex self.check_coverage method works.""" + + def test_successful_coverage(self): + # The simplest run possible. + self.check_coverage("""\ + a = 1 + b = 2 + """, + [1,2] + ) + # You can provide a list of possible statement matches. + self.check_coverage("""\ + a = 1 + b = 2 + """, + ([100], [1,2], [1723,47]), + ) + # You can specify missing lines. + self.check_coverage("""\ + a = 1 + if a == 2: + a = 3 + """, + [1,2,3], + missing="3", + ) + # You can specify a list of possible missing lines. + self.check_coverage("""\ + a = 1 + if a == 2: + a = 3 + """, + [1,2,3], + missing=("47-49", "3", "100,102") + ) + + def test_failed_coverage(self): + # If the lines are wrong, the message shows right and wrong. + self.assertRaisesRegexp(AssertionError, + r"\[1, 2] != \[1]", + self.check_coverage, """\ + a = 1 + b = 2 + """, + [1] + ) + # If the list of lines possibilities is wrong, the msg shows right. + self.assertRaisesRegexp(AssertionError, + r"None of the lines choices matched \[1, 2]", + self.check_coverage, """\ + a = 1 + b = 2 + """, + ([1], [2]) + ) + # If the missing lines are wrong, the message shows right and wrong. + self.assertRaisesRegexp(AssertionError, + r"'3' != '37'", + self.check_coverage, """\ + a = 1 + if a == 2: + a = 3 + """, + [1,2,3], + missing="37", + ) + # If the missing lines possibilities are wrong, the msg shows right. + self.assertRaisesRegexp(AssertionError, + r"None of the missing choices matched '3'", + self.check_coverage, """\ + a = 1 + if a == 2: + a = 3 + """, + [1,2,3], + missing=("37", "4-10"), + ) + + +class BasicCoverageTest(CoverageTest): + """The simplest tests, for quick smoke testing of fundamental changes.""" + + def test_simple(self): + self.check_coverage("""\ + a = 1 + b = 2 + + c = 4 + # Nothing here + d = 6 + """, + [1,2,4,6], report="4 0 100%") + + def test_indentation_wackiness(self): + # Partial final lines are OK. + self.check_coverage("""\ + import sys + if not sys.path: + a = 1 + """, + [1,2,3], "3") + + def test_multiline_initializer(self): + self.check_coverage("""\ + d = { + 'foo': 1+2, + 'bar': (lambda x: x+1)(1), + 'baz': str(1), + } + + e = { 'foo': 1, 'bar': 2 } + """, + [1,7], "") + + def test_list_comprehension(self): + self.check_coverage("""\ + l = [ + 2*i for i in range(10) + if i > 5 + ] + assert l == [12, 14, 16, 18] + """, + [1,5], "") + + +class SimpleStatementTest(CoverageTest): + """Testing simple single-line statements.""" + + def test_expression(self): + # Bare expressions as statements are tricky: some implementations + # optimize some of them away. All implementations seem to count + # the implicit return at the end as executable. + self.check_coverage("""\ + 12 + 23 + """, + ([1,2],[2]), "") + self.check_coverage("""\ + 12 + 23 + a = 3 + """, + ([1,2,3],[3]), "") + self.check_coverage("""\ + 1 + 2 + 1 + \\ + 2 + """, + ([1,2], [2]), "") + self.check_coverage("""\ + 1 + 2 + 1 + \\ + 2 + a = 4 + """, + ([1,2,4], [4]), "") + + def test_assert(self): + self.check_coverage("""\ + assert (1 + 2) + assert (1 + + 2) + assert (1 + 2), 'the universe is broken' + assert (1 + + 2), \\ + 'something is amiss' + """, + [1,2,4,5], "") + + def test_assignment(self): + # Simple variable assignment + self.check_coverage("""\ + a = (1 + 2) + b = (1 + + 2) + c = \\ + 1 + """, + [1,2,4], "") + + def test_assign_tuple(self): + self.check_coverage("""\ + a = 1 + a,b,c = 7,8,9 + assert a == 7 and b == 8 and c == 9 + """, + [1,2,3], "") + + def test_attribute_assignment(self): + # Attribute assignment + self.check_coverage("""\ + class obj: pass + o = obj() + o.foo = (1 + 2) + o.foo = (1 + + 2) + o.foo = \\ + 1 + """, + [1,2,3,4,6], "") + + def test_list_of_attribute_assignment(self): + self.check_coverage("""\ + class obj: pass + o = obj() + o.a, o.b = (1 + 2), 3 + o.a, o.b = (1 + + 2), (3 + + 4) + o.a, o.b = \\ + 1, \\ + 2 + """, + [1,2,3,4,7], "") + + def test_augmented_assignment(self): + self.check_coverage("""\ + a = 1 + a += 1 + a += (1 + + 2) + a += \\ + 1 + """, + [1,2,3,5], "") + + def test_triple_string_stuff(self): + self.check_coverage("""\ + a = ''' + a multiline + string. + ''' + b = ''' + long expression + ''' + ''' + on many + lines. + ''' + c = len(''' + long expression + ''' + + ''' + on many + lines. + ''') + """, + [1,5,11], "") + + def test_pass(self): + # pass is tricky: if it's the only statement in a block, then it is + # "executed". But if it is not the only statement, then it is not. + self.check_coverage("""\ + if 1==1: + pass + """, + [1,2], "") + self.check_coverage("""\ + def foo(): + pass + foo() + """, + [1,2,3], "") + self.check_coverage("""\ + def foo(): + "doc" + pass + foo() + """, + ([1,3,4], [1,4]), "") + self.check_coverage("""\ + class Foo: + def foo(self): + pass + Foo().foo() + """, + [1,2,3,4], "") + self.check_coverage("""\ + class Foo: + def foo(self): + "Huh?" + pass + Foo().foo() + """, + ([1,2,4,5], [1,2,5]), "") + + def test_del(self): + self.check_coverage("""\ + d = { 'a': 1, 'b': 1, 'c': 1, 'd': 1, 'e': 1 } + del d['a'] + del d[ + 'b' + ] + del d['c'], \\ + d['d'], \\ + d['e'] + assert(len(d.keys()) == 0) + """, + [1,2,3,6,9], "") + + if sys.version_info < (3, 0): # Print statement is gone in Py3k. + def test_print(self): + self.check_coverage("""\ + print "hello, world!" + print ("hey: %d" % + 17) + print "goodbye" + print "hello, world!", + print ("hey: %d" % + 17), + print "goodbye", + """, + [1,2,4,5,6,8], "") + + def test_raise(self): + self.check_coverage("""\ + try: + raise Exception( + "hello %d" % + 17) + except: + pass + """, + [1,2,5,6], "") + + def test_return(self): + self.check_coverage("""\ + def fn(): + a = 1 + return a + + x = fn() + assert(x == 1) + """, + [1,2,3,5,6], "") + self.check_coverage("""\ + def fn(): + a = 1 + return ( + a + + 1) + + x = fn() + assert(x == 2) + """, + [1,2,3,7,8], "") + self.check_coverage("""\ + def fn(): + a = 1 + return (a, + a + 1, + a + 2) + + x,y,z = fn() + assert x == 1 and y == 2 and z == 3 + """, + [1,2,3,7,8], "") + + def test_yield(self): + self.check_coverage("""\ + from __future__ import generators + def gen(): + yield 1 + yield (2+ + 3+ + 4) + yield 1, \\ + 2 + a,b,c = gen() + assert a == 1 and b == 9 and c == (1,2) + """, + [1,2,3,4,7,9,10], "") + + def test_break(self): + self.check_coverage("""\ + for x in range(10): + a = 2 + x + break + a = 4 + assert a == 2 + """, + [1,2,3,4,5], "4") + + def test_continue(self): + self.check_coverage("""\ + for x in range(10): + a = 2 + x + continue + a = 4 + assert a == 11 + """, + [1,2,3,4,5], "4") + + if 0: # expected failure + # Peephole optimization of jumps to jumps can mean that some statements + # never hit the line tracer. The behavior is different in different + # versions of Python, so don't run this test: + def test_strange_unexecuted_continue(self): + self.check_coverage("""\ + a = b = c = 0 + for n in range(100): + if n % 2: + if n % 4: + a += 1 + continue # <-- This line may not be hit. + else: + b += 1 + c += 1 + assert a == 50 and b == 50 and c == 50 + + a = b = c = 0 + for n in range(100): + if n % 2: + if n % 3: + a += 1 + continue # <-- This line is always hit. + else: + b += 1 + c += 1 + assert a == 33 and b == 50 and c == 50 + """, + [1,2,3,4,5,6,8,9,10, 12,13,14,15,16,17,19,20,21], "") + + def test_import(self): + self.check_coverage("""\ + import string + from sys import path + a = 1 + """, + [1,2,3], "") + self.check_coverage("""\ + import string + if 1 == 2: + from sys import path + a = 1 + """, + [1,2,3,4], "3") + self.check_coverage("""\ + import string, \\ + os, \\ + re + from sys import path, \\ + stdout + a = 1 + """, + [1,4,6], "") + self.check_coverage("""\ + import sys, sys as s + assert s.path == sys.path + """, + [1,2], "") + self.check_coverage("""\ + import sys, \\ + sys as s + assert s.path == sys.path + """, + [1,3], "") + self.check_coverage("""\ + from sys import path, \\ + path as p + assert p == path + """, + [1,3], "") + self.check_coverage("""\ + from sys import \\ + * + assert len(path) > 0 + """, + [1,3], "") + + def test_global(self): + self.check_coverage("""\ + g = h = i = 1 + def fn(): + global g + global h, \\ + i + g = h = i = 2 + fn() + assert g == 2 and h == 2 and i == 2 + """, + [1,2,6,7,8], "") + self.check_coverage("""\ + g = h = i = 1 + def fn(): + global g; g = 2 + fn() + assert g == 2 and h == 1 and i == 1 + """, + [1,2,3,4,5], "") + + if sys.version_info < (3, 0): + # In Python 2.x, exec is a statement. + def test_exec(self): + self.check_coverage("""\ + a = b = c = 1 + exec "a = 2" + exec ("b = " + + "c = " + + "2") + assert a == 2 and b == 2 and c == 2 + """, + [1,2,3,6], "") + self.check_coverage("""\ + vars = {'a': 1, 'b': 1, 'c': 1} + exec "a = 2" in vars + exec ("b = " + + "c = " + + "2") in vars + assert vars['a'] == 2 and vars['b'] == 2 and vars['c'] == 2 + """, + [1,2,3,6], "") + self.check_coverage("""\ + globs = {} + locs = {'a': 1, 'b': 1, 'c': 1} + exec "a = 2" in globs, locs + exec ("b = " + + "c = " + + "2") in globs, locs + assert locs['a'] == 2 and locs['b'] == 2 and locs['c'] == 2 + """, + [1,2,3,4,7], "") + else: + # In Python 3.x, exec is a function. + def test_exec(self): + self.check_coverage("""\ + a = b = c = 1 + exec("a = 2") + exec("b = " + + "c = " + + "2") + assert a == 2 and b == 2 and c == 2 + """, + [1,2,3,6], "") + self.check_coverage("""\ + vars = {'a': 1, 'b': 1, 'c': 1} + exec("a = 2", vars) + exec("b = " + + "c = " + + "2", vars) + assert vars['a'] == 2 and vars['b'] == 2 and vars['c'] == 2 + """, + [1,2,3,6], "") + self.check_coverage("""\ + globs = {} + locs = {'a': 1, 'b': 1, 'c': 1} + exec("a = 2", globs, locs) + exec("b = " + + "c = " + + "2", globs, locs) + assert locs['a'] == 2 and locs['b'] == 2 and locs['c'] == 2 + """, + [1,2,3,4,7], "") + + def test_extra_doc_string(self): + self.check_coverage("""\ + a = 1 + "An extra docstring, should be a comment." + b = 3 + assert (a,b) == (1,3) + """, + [1,3,4], "") + self.check_coverage("""\ + a = 1 + "An extra docstring, should be a comment." + b = 3 + 123 # A number for some reason: ignored + 1+1 # An expression: executed. + c = 6 + assert (a,b,c) == (1,3,6) + """, + ([1,3,6,7], [1,3,5,6,7], [1,3,4,5,6,7]), "") + + +class CompoundStatementTest(CoverageTest): + """Testing coverage of multi-line compound statements.""" + + def test_statement_list(self): + self.check_coverage("""\ + a = 1; + b = 2; c = 3 + d = 4; e = 5; + + assert (a,b,c,d,e) == (1,2,3,4,5) + """, + [1,2,3,5], "") + + def test_if(self): + self.check_coverage("""\ + a = 1 + if a == 1: + x = 3 + assert x == 3 + if (a == + 1): + x = 7 + assert x == 7 + """, + [1,2,3,4,5,7,8], "") + self.check_coverage("""\ + a = 1 + if a == 1: + x = 3 + else: + y = 5 + assert x == 3 + """, + [1,2,3,5,6], "5") + self.check_coverage("""\ + a = 1 + if a != 1: + x = 3 + else: + y = 5 + assert y == 5 + """, + [1,2,3,5,6], "3") + self.check_coverage("""\ + a = 1; b = 2 + if a == 1: + if b == 2: + x = 4 + else: + y = 6 + else: + z = 8 + assert x == 4 + """, + [1,2,3,4,6,8,9], "6-8") + + def test_elif(self): + self.check_coverage("""\ + a = 1; b = 2; c = 3; + if a == 1: + x = 3 + elif b == 2: + y = 5 + else: + z = 7 + assert x == 3 + """, + [1,2,3,4,5,7,8], "4-7", report="7 3 57% 4-7") + self.check_coverage("""\ + a = 1; b = 2; c = 3; + if a != 1: + x = 3 + elif b == 2: + y = 5 + else: + z = 7 + assert y == 5 + """, + [1,2,3,4,5,7,8], "3, 7", report="7 2 71% 3, 7") + self.check_coverage("""\ + a = 1; b = 2; c = 3; + if a != 1: + x = 3 + elif b != 2: + y = 5 + else: + z = 7 + assert z == 7 + """, + [1,2,3,4,5,7,8], "3, 5", report="7 2 71% 3, 5") + + def test_elif_no_else(self): + self.check_coverage("""\ + a = 1; b = 2; c = 3; + if a == 1: + x = 3 + elif b == 2: + y = 5 + assert x == 3 + """, + [1,2,3,4,5,6], "4-5", report="6 2 67% 4-5") + self.check_coverage("""\ + a = 1; b = 2; c = 3; + if a != 1: + x = 3 + elif b == 2: + y = 5 + assert y == 5 + """, + [1,2,3,4,5,6], "3", report="6 1 83% 3") + + def test_elif_bizarre(self): + self.check_coverage("""\ + def f(self): + if self==1: + x = 3 + elif self.m('fred'): + x = 5 + elif (g==1) and (b==2): + x = 7 + elif self.m('fred')==True: + x = 9 + elif ((g==1) and (b==2))==True: + x = 11 + else: + x = 13 + """, + [1,2,3,4,5,6,7,8,9,10,11,13], "2-13") + + def test_split_if(self): + self.check_coverage("""\ + a = 1; b = 2; c = 3; + if \\ + a == 1: + x = 3 + elif \\ + b == 2: + y = 5 + else: + z = 7 + assert x == 3 + """, + [1,2,4,5,7,9,10], "5-9") + self.check_coverage("""\ + a = 1; b = 2; c = 3; + if \\ + a != 1: + x = 3 + elif \\ + b == 2: + y = 5 + else: + z = 7 + assert y == 5 + """, + [1,2,4,5,7,9,10], "4, 9") + self.check_coverage("""\ + a = 1; b = 2; c = 3; + if \\ + a != 1: + x = 3 + elif \\ + b != 2: + y = 5 + else: + z = 7 + assert z == 7 + """, + [1,2,4,5,7,9,10], "4, 7") + + def test_pathological_split_if(self): + self.check_coverage("""\ + a = 1; b = 2; c = 3; + if ( + a == 1 + ): + x = 3 + elif ( + b == 2 + ): + y = 5 + else: + z = 7 + assert x == 3 + """, + [1,2,5,6,9,11,12], "6-11") + self.check_coverage("""\ + a = 1; b = 2; c = 3; + if ( + a != 1 + ): + x = 3 + elif ( + b == 2 + ): + y = 5 + else: + z = 7 + assert y == 5 + """, + [1,2,5,6,9,11,12], "5, 11") + self.check_coverage("""\ + a = 1; b = 2; c = 3; + if ( + a != 1 + ): + x = 3 + elif ( + b != 2 + ): + y = 5 + else: + z = 7 + assert z == 7 + """, + [1,2,5,6,9,11,12], "5, 9") + + def test_absurd_split_if(self): + self.check_coverage("""\ + a = 1; b = 2; c = 3; + if a == 1 \\ + : + x = 3 + elif b == 2 \\ + : + y = 5 + else: + z = 7 + assert x == 3 + """, + [1,2,4,5,7,9,10], "5-9") + self.check_coverage("""\ + a = 1; b = 2; c = 3; + if a != 1 \\ + : + x = 3 + elif b == 2 \\ + : + y = 5 + else: + z = 7 + assert y == 5 + """, + [1,2,4,5,7,9,10], "4, 9") + self.check_coverage("""\ + a = 1; b = 2; c = 3; + if a != 1 \\ + : + x = 3 + elif b != 2 \\ + : + y = 5 + else: + z = 7 + assert z == 7 + """, + [1,2,4,5,7,9,10], "4, 7") + + if sys.version_info >= (2, 4): + # In 2.4 and up, constant if's were compiled away. + def test_constant_if(self): + self.check_coverage("""\ + if 1: + a = 2 + assert a == 2 + """, + [2,3], "") + + def test_while(self): + self.check_coverage("""\ + a = 3; b = 0 + while a: + b += 1 + a -= 1 + assert a == 0 and b == 3 + """, + [1,2,3,4,5], "") + self.check_coverage("""\ + a = 3; b = 0 + while a: + b += 1 + break + b = 99 + assert a == 3 and b == 1 + """, + [1,2,3,4,5,6], "5") + + def test_while_else(self): + # Take the else branch. + self.check_coverage("""\ + a = 3; b = 0 + while a: + b += 1 + a -= 1 + else: + b = 99 + assert a == 0 and b == 99 + """, + [1,2,3,4,6,7], "") + # Don't take the else branch. + self.check_coverage("""\ + a = 3; b = 0 + while a: + b += 1 + a -= 1 + break + b = 123 + else: + b = 99 + assert a == 2 and b == 1 + """, + [1,2,3,4,5,6,8,9], "6-8") + + def test_split_while(self): + self.check_coverage("""\ + a = 3; b = 0 + while \\ + a: + b += 1 + a -= 1 + assert a == 0 and b == 3 + """, + [1,2,4,5,6], "") + self.check_coverage("""\ + a = 3; b = 0 + while ( + a + ): + b += 1 + a -= 1 + assert a == 0 and b == 3 + """, + [1,2,5,6,7], "") + + def test_for(self): + self.check_coverage("""\ + a = 0 + for i in [1,2,3,4,5]: + a += i + assert a == 15 + """, + [1,2,3,4], "") + self.check_coverage("""\ + a = 0 + for i in [1, + 2,3,4, + 5]: + a += i + assert a == 15 + """, + [1,2,5,6], "") + self.check_coverage("""\ + a = 0 + for i in [1,2,3,4,5]: + a += i + break + a = 99 + assert a == 1 + """, + [1,2,3,4,5,6], "5") + + def test_for_else(self): + self.check_coverage("""\ + a = 0 + for i in range(5): + a += i+1 + else: + a = 99 + assert a == 99 + """, + [1,2,3,5,6], "") + self.check_coverage("""\ + a = 0 + for i in range(5): + a += i+1 + break + a = 99 + else: + a = 123 + assert a == 1 + """, + [1,2,3,4,5,7,8], "5-7") + + def test_split_for(self): + self.check_coverage("""\ + a = 0 + for \\ + i in [1,2,3,4,5]: + a += i + assert a == 15 + """, + [1,2,4,5], "") + self.check_coverage("""\ + a = 0 + for \\ + i in [1, + 2,3,4, + 5]: + a += i + assert a == 15 + """, + [1,2,6,7], "") + + def test_try_except(self): + self.check_coverage("""\ + a = 0 + try: + a = 1 + except: + a = 99 + assert a == 1 + """, + [1,2,3,4,5,6], "4-5") + self.check_coverage("""\ + a = 0 + try: + a = 1 + raise Exception("foo") + except: + a = 99 + assert a == 99 + """, + [1,2,3,4,5,6,7], "") + self.check_coverage("""\ + a = 0 + try: + a = 1 + raise Exception("foo") + except ImportError: + a = 99 + except: + a = 123 + assert a == 123 + """, + [1,2,3,4,5,6,7,8,9], "6") + self.check_coverage("""\ + a = 0 + try: + a = 1 + raise IOError("foo") + except ImportError: + a = 99 + except IOError: + a = 17 + except: + a = 123 + assert a == 17 + """, + [1,2,3,4,5,6,7,8,9,10,11], "6, 9-10") + self.check_coverage("""\ + a = 0 + try: + a = 1 + except: + a = 99 + else: + a = 123 + assert a == 123 + """, + [1,2,3,4,5,7,8], "4-5") + self.check_coverage("""\ + a = 0 + try: + a = 1 + raise Exception("foo") + except: + a = 99 + else: + a = 123 + assert a == 99 + """, + [1,2,3,4,5,6,8,9], "8") + + def test_try_finally(self): + self.check_coverage("""\ + a = 0 + try: + a = 1 + finally: + a = 99 + assert a == 99 + """, + [1,2,3,5,6], "") + self.check_coverage("""\ + a = 0; b = 0 + try: + a = 1 + try: + raise Exception("foo") + finally: + b = 123 + except: + a = 99 + assert a == 99 and b == 123 + """, + [1,2,3,4,5,7,8,9,10], "") + + def test_function_def(self): + self.check_coverage("""\ + a = 99 + def foo(): + ''' docstring + ''' + return 1 + + a = foo() + assert a == 1 + """, + [1,2,5,7,8], "") + self.check_coverage("""\ + def foo( + a, + b + ): + ''' docstring + ''' + return a+b + + x = foo(17, 23) + assert x == 40 + """, + [1,7,9,10], "") + self.check_coverage("""\ + def foo( + a = (lambda x: x*2)(10), + b = ( + lambda x: + x+1 + )(1) + ): + ''' docstring + ''' + return a+b + + x = foo() + assert x == 22 + """, + [1,10,12,13], "") + + def test_class_def(self): + self.check_coverage("""\ + # A comment. + class theClass: + ''' the docstring. + Don't be fooled. + ''' + def __init__(self): + ''' Another docstring. ''' + self.a = 1 + + def foo(self): + return self.a + + x = theClass().foo() + assert x == 1 + """, + [2,6,8,10,11,13,14], "") + + +class ExcludeTest(CoverageTest): + """Tests of the exclusion feature to mark lines as not covered.""" + + def test_default(self): + # A number of forms of pragma comment are accepted. + self.check_coverage("""\ + a = 1 + b = 2 # pragma: no cover + c = 3 + d = 4 #pragma NOCOVER + e = 5 + """, + [1,3,5] + ) + + def test_simple(self): + self.check_coverage("""\ + a = 1; b = 2 + + if 0: + a = 4 # -cc + """, + [1,3], "", excludes=['-cc']) + + def test_two_excludes(self): + self.check_coverage("""\ + a = 1; b = 2 + + if a == 99: + a = 4 # -cc + b = 5 + c = 6 # -xx + assert a == 1 and b == 2 + """, + [1,3,5,7], "5", excludes=['-cc', '-xx']) + + def test_excluding_if_suite(self): + self.check_coverage("""\ + a = 1; b = 2 + + if 0: + a = 4 + b = 5 + c = 6 + assert a == 1 and b == 2 + """, + [1,7], "", excludes=['if 0:']) + + def test_excluding_if_but_not_else_suite(self): + self.check_coverage("""\ + a = 1; b = 2 + + if 0: + a = 4 + b = 5 + c = 6 + else: + a = 8 + b = 9 + assert a == 8 and b == 9 + """, + [1,8,9,10], "", excludes=['if 0:']) + + def test_excluding_else_suite(self): + self.check_coverage("""\ + a = 1; b = 2 + + if 1==1: + a = 4 + b = 5 + c = 6 + else: #pragma: NO COVER + a = 8 + b = 9 + assert a == 4 and b == 5 and c == 6 + """, + [1,3,4,5,6,10], "", excludes=['#pragma: NO COVER']) + self.check_coverage("""\ + a = 1; b = 2 + + if 1==1: + a = 4 + b = 5 + c = 6 + + # Lots of comments to confuse the else handler. + # more. + + else: #pragma: NO COVER + + # Comments here too. + + a = 8 + b = 9 + assert a == 4 and b == 5 and c == 6 + """, + [1,3,4,5,6,17], "", excludes=['#pragma: NO COVER']) + + def test_excluding_elif_suites(self): + self.check_coverage("""\ + a = 1; b = 2 + + if 1==1: + a = 4 + b = 5 + c = 6 + elif 1==0: #pragma: NO COVER + a = 8 + b = 9 + else: + a = 11 + b = 12 + assert a == 4 and b == 5 and c == 6 + """, + [1,3,4,5,6,11,12,13], "11-12", excludes=['#pragma: NO COVER']) + + def test_excluding_oneline_if(self): + self.check_coverage("""\ + def foo(): + a = 2 + if 0: x = 3 # no cover + b = 4 + + foo() + """, + [1,2,4,6], "", excludes=["no cover"]) + + def test_excluding_a_colon_not_a_suite(self): + self.check_coverage("""\ + def foo(): + l = list(range(10)) + a = l[:3] # no cover + b = 4 + + foo() + """, + [1,2,4,6], "", excludes=["no cover"]) + + def test_excluding_for_suite(self): + self.check_coverage("""\ + a = 0 + for i in [1,2,3,4,5]: #pragma: NO COVER + a += i + assert a == 15 + """, + [1,4], "", excludes=['#pragma: NO COVER']) + self.check_coverage("""\ + a = 0 + for i in [1, + 2,3,4, + 5]: #pragma: NO COVER + a += i + assert a == 15 + """, + [1,6], "", excludes=['#pragma: NO COVER']) + self.check_coverage("""\ + a = 0 + for i in [1,2,3,4,5 + ]: #pragma: NO COVER + a += i + break + a = 99 + assert a == 1 + """, + [1,7], "", excludes=['#pragma: NO COVER']) + + def test_excluding_for_else(self): + self.check_coverage("""\ + a = 0 + for i in range(5): + a += i+1 + break + a = 99 + else: #pragma: NO COVER + a = 123 + assert a == 1 + """, + [1,2,3,4,5,8], "5", excludes=['#pragma: NO COVER']) + + def test_excluding_while(self): + self.check_coverage("""\ + a = 3; b = 0 + while a*b: #pragma: NO COVER + b += 1 + break + b = 99 + assert a == 3 and b == 0 + """, + [1,6], "", excludes=['#pragma: NO COVER']) + self.check_coverage("""\ + a = 3; b = 0 + while ( + a*b + ): #pragma: NO COVER + b += 1 + break + b = 99 + assert a == 3 and b == 0 + """, + [1,8], "", excludes=['#pragma: NO COVER']) + + def test_excluding_while_else(self): + self.check_coverage("""\ + a = 3; b = 0 + while a: + b += 1 + break + b = 99 + else: #pragma: NO COVER + b = 123 + assert a == 3 and b == 1 + """, + [1,2,3,4,5,8], "5", excludes=['#pragma: NO COVER']) + + def test_excluding_try_except(self): + self.check_coverage("""\ + a = 0 + try: + a = 1 + except: #pragma: NO COVER + a = 99 + assert a == 1 + """, + [1,2,3,6], "", excludes=['#pragma: NO COVER']) + self.check_coverage("""\ + a = 0 + try: + a = 1 + raise Exception("foo") + except: + a = 99 + assert a == 99 + """, + [1,2,3,4,5,6,7], "", excludes=['#pragma: NO COVER']) + self.check_coverage("""\ + a = 0 + try: + a = 1 + raise Exception("foo") + except ImportError: #pragma: NO COVER + a = 99 + except: + a = 123 + assert a == 123 + """, + [1,2,3,4,7,8,9], "", excludes=['#pragma: NO COVER']) + self.check_coverage("""\ + a = 0 + try: + a = 1 + except: #pragma: NO COVER + a = 99 + else: + a = 123 + assert a == 123 + """, + [1,2,3,7,8], "", excludes=['#pragma: NO COVER']) + self.check_coverage("""\ + a = 0 + try: + a = 1 + raise Exception("foo") + except: + a = 99 + else: #pragma: NO COVER + a = 123 + assert a == 99 + """, + [1,2,3,4,5,6,9], "", excludes=['#pragma: NO COVER']) + + def test_excluding_try_except_pass(self): + self.check_coverage("""\ + a = 0 + try: + a = 1 + except: #pragma: NO COVER + x = 2 + assert a == 1 + """, + [1,2,3,6], "", excludes=['#pragma: NO COVER']) + self.check_coverage("""\ + a = 0 + try: + a = 1 + raise Exception("foo") + except ImportError: #pragma: NO COVER + x = 2 + except: + a = 123 + assert a == 123 + """, + [1,2,3,4,7,8,9], "", excludes=['#pragma: NO COVER']) + self.check_coverage("""\ + a = 0 + try: + a = 1 + except: #pragma: NO COVER + x = 2 + else: + a = 123 + assert a == 123 + """, + [1,2,3,7,8], "", excludes=['#pragma: NO COVER']) + self.check_coverage("""\ + a = 0 + try: + a = 1 + raise Exception("foo") + except: + a = 99 + else: #pragma: NO COVER + x = 2 + assert a == 99 + """, + [1,2,3,4,5,6,9], "", excludes=['#pragma: NO COVER']) + + def test_excluding_if_pass(self): + # From a comment on the coverage page by Michael McNeil Forbes: + self.check_coverage("""\ + def f(): + if False: # pragma: no cover + pass # This line still reported as missing + if False: # pragma: no cover + x = 1 # Now it is skipped. + + f() + """, + [1,7], "", excludes=["no cover"]) + + def test_excluding_function(self): + self.check_coverage("""\ + def fn(foo): #pragma: NO COVER + a = 1 + b = 2 + c = 3 + + x = 1 + assert x == 1 + """, + [6,7], "", excludes=['#pragma: NO COVER']) + + def test_excluding_method(self): + self.check_coverage("""\ + class Fooey: + def __init__(self): + self.a = 1 + + def foo(self): #pragma: NO COVER + return self.a + + x = Fooey() + assert x.a == 1 + """, + [1,2,3,8,9], "", excludes=['#pragma: NO COVER']) + + def test_excluding_class(self): + self.check_coverage("""\ + class Fooey: #pragma: NO COVER + def __init__(self): + self.a = 1 + + def foo(self): + return self.a + + x = 1 + assert x == 1 + """, + [8,9], "", excludes=['#pragma: NO COVER']) + + +if sys.version_info >= (2, 4): + class Py24Test(CoverageTest): + """Tests of new syntax in Python 2.4.""" + + def test_function_decorators(self): + self.check_coverage("""\ + def require_int(func): + def wrapper(arg): + assert isinstance(arg, int) + return func(arg) + + return wrapper + + @require_int + def p1(arg): + return arg*2 + + assert p1(10) == 20 + """, + [1,2,3,4,6,8,10,12], "") + + def test_function_decorators_with_args(self): + self.check_coverage("""\ + def boost_by(extra): + def decorator(func): + def wrapper(arg): + return extra*func(arg) + return wrapper + return decorator + + @boost_by(10) + def boosted(arg): + return arg*2 + + assert boosted(10) == 200 + """, + [1,2,3,4,5,6,8,10,12], "") + + def test_double_function_decorators(self): + self.check_coverage("""\ + def require_int(func): + def wrapper(arg): + assert isinstance(arg, int) + return func(arg) + return wrapper + + def boost_by(extra): + def decorator(func): + def wrapper(arg): + return extra*func(arg) + return wrapper + return decorator + + @require_int + @boost_by(10) + def boosted1(arg): + return arg*2 + + assert boosted1(10) == 200 + + @boost_by(10) + @require_int + def boosted2(arg): + return arg*2 + + assert boosted2(10) == 200 + """, + ([1,2,3,4,5,7,8,9,10,11,12,14,15,17,19,21,22,24,26], + [1,2,3,4,5,7,8,9,10,11,12,14, 17,19,21, 24,26]), "") + + +if sys.version_info >= (2, 5): + class Py25Test(CoverageTest): + """Tests of new syntax in Python 2.5.""" + + def test_with_statement(self): + self.check_coverage("""\ + from __future__ import with_statement + + class Managed: + def __enter__(self): + desc = "enter" + + def __exit__(self, type, value, tb): + desc = "exit" + + m = Managed() + with m: + desc = "block1a" + desc = "block1b" + + try: + with m: + desc = "block2" + raise Exception("Boo!") + except: + desc = "caught" + """, + [1,3,4,5,7,8,10,11,12,13,15,16,17,18,19,20], "") + + def test_try_except_finally(self): + self.check_coverage("""\ + a = 0; b = 0 + try: + a = 1 + except: + a = 99 + finally: + b = 2 + assert a == 1 and b == 2 + """, + [1,2,3,4,5,7,8], "4-5") + self.check_coverage("""\ + a = 0; b = 0 + try: + a = 1 + raise Exception("foo") + except: + a = 99 + finally: + b = 2 + assert a == 99 and b == 2 + """, + [1,2,3,4,5,6,8,9], "") + self.check_coverage("""\ + a = 0; b = 0 + try: + a = 1 + raise Exception("foo") + except ImportError: + a = 99 + except: + a = 123 + finally: + b = 2 + assert a == 123 and b == 2 + """, + [1,2,3,4,5,6,7,8,10,11], "6") + self.check_coverage("""\ + a = 0; b = 0 + try: + a = 1 + raise IOError("foo") + except ImportError: + a = 99 + except IOError: + a = 17 + except: + a = 123 + finally: + b = 2 + assert a == 17 and b == 2 + """, + [1,2,3,4,5,6,7,8,9,10,12,13], "6, 9-10") + self.check_coverage("""\ + a = 0; b = 0 + try: + a = 1 + except: + a = 99 + else: + a = 123 + finally: + b = 2 + assert a == 123 and b == 2 + """, + [1,2,3,4,5,7,9,10], "4-5") + self.check_coverage("""\ + a = 0; b = 0 + try: + a = 1 + raise Exception("foo") + except: + a = 99 + else: + a = 123 + finally: + b = 2 + assert a == 99 and b == 2 + """, + [1,2,3,4,5,6,8,10,11], "8") + + +class ModuleTest(CoverageTest): + """Tests for the module-level behavior of the `coverage` module.""" + + def test_not_singleton(self): + # You *can* create another coverage object. + coverage.coverage() + coverage.coverage() + + +class ReportingTest(CoverageTest): + """Tests of some reporting behavior.""" + + def test_no_data_to_report_on_annotate(self): + # Reporting with no data produces a nice message and no output dir. + self.assertRaisesRegexp( + CoverageException, "No data to report.", + self.command_line, "annotate -d ann" + ) + self.assert_doesnt_exist("ann") + + def test_no_data_to_report_on_html(self): + # Reporting with no data produces a nice message and no output dir. + self.assertRaisesRegexp( + CoverageException, "No data to report.", + self.command_line, "html -d htmlcov" + ) + self.assert_doesnt_exist("htmlcov") + + def test_no_data_to_report_on_xml(self): + # Reporting with no data produces a nice message. + self.assertRaisesRegexp( + CoverageException, "No data to report.", + self.command_line, "xml" + ) + # Currently, this leaves an empty coverage.xml file... :( diff --git a/tests/test_data.py b/tests/test_data.py new file mode 100644 index 00000000..9281ccc7 --- /dev/null +++ b/tests/test_data.py @@ -0,0 +1,146 @@ +"""Tests for coverage.data""" + +from coverage.backward import pickle +from coverage.data import CoverageData +from coverage.files import PathAliases + +from test.coveragetest import CoverageTest + + +DATA_1 = { 'a.py': {1:None, 2:None}, 'b.py': {3:None} } +SUMMARY_1 = { 'a.py':2, 'b.py':1 } +MEASURED_FILES_1 = [ 'a.py', 'b.py' ] +A_PY_LINES_1 = [1,2] +B_PY_LINES_1 = [3] + +DATA_2 = { 'a.py': {1:None, 5:None}, 'c.py': {17:None} } +SUMMARY_1_2 = { 'a.py':3, 'b.py':1, 'c.py':1 } +MEASURED_FILES_1_2 = [ 'a.py', 'b.py', 'c.py' ] + +ARC_DATA_3 = { 'x.py': {(1,2):None, (2,3):None}, 'y.py': {(17,23):None} } +X_PY_ARCS_3 = [(1,2), (2,3)] +Y_PY_ARCS_3 = [(17,23)] + + +class DataTest(CoverageTest): + """Test cases for coverage.data.""" + + def assert_summary(self, covdata, summary, fullpath=False): + """Check that the summary of `covdata` is `summary`.""" + self.assertEqual(covdata.summary(fullpath), summary) + + def assert_measured_files(self, covdata, measured): + """Check that `covdata`'s measured files are `measured`.""" + self.assertSameElements(covdata.measured_files(), measured) + + def test_reading_empty(self): + covdata = CoverageData() + covdata.read() + self.assert_summary(covdata, {}) + + def test_adding_data(self): + covdata = CoverageData() + covdata.add_line_data(DATA_1) + self.assert_summary(covdata, SUMMARY_1) + self.assert_measured_files(covdata, MEASURED_FILES_1) + + def test_touch_file(self): + covdata = CoverageData() + covdata.add_line_data(DATA_1) + covdata.touch_file('x.py') + self.assert_measured_files(covdata, MEASURED_FILES_1 + ['x.py']) + + def test_writing_and_reading(self): + covdata1 = CoverageData() + covdata1.add_line_data(DATA_1) + covdata1.write() + + covdata2 = CoverageData() + covdata2.read() + self.assert_summary(covdata2, SUMMARY_1) + + def test_combining(self): + covdata1 = CoverageData() + covdata1.add_line_data(DATA_1) + covdata1.write(suffix='1') + + covdata2 = CoverageData() + covdata2.add_line_data(DATA_2) + covdata2.write(suffix='2') + + covdata3 = CoverageData() + covdata3.combine_parallel_data() + self.assert_summary(covdata3, SUMMARY_1_2) + self.assert_measured_files(covdata3, MEASURED_FILES_1_2) + + def test_erasing(self): + covdata1 = CoverageData() + covdata1.add_line_data(DATA_1) + covdata1.write() + covdata1.erase() + self.assert_summary(covdata1, {}) + + covdata2 = CoverageData() + covdata2.read() + self.assert_summary(covdata2, {}) + + def test_file_format(self): + # Write with CoverageData, then read the pickle explicitly. + covdata = CoverageData() + covdata.add_line_data(DATA_1) + covdata.write() + + fdata = open(".coverage", 'rb') + try: + data = pickle.load(fdata) + finally: + fdata.close() + + lines = data['lines'] + self.assertSameElements(lines.keys(), MEASURED_FILES_1) + self.assertSameElements(lines['a.py'], A_PY_LINES_1) + self.assertSameElements(lines['b.py'], B_PY_LINES_1) + # If not measuring branches, there's no arcs entry. + self.assertEqual(data.get('arcs', 'not there'), 'not there') + + def test_file_format_with_arcs(self): + # Write with CoverageData, then read the pickle explicitly. + covdata = CoverageData() + covdata.add_arc_data(ARC_DATA_3) + covdata.write() + + fdata = open(".coverage", 'rb') + try: + data = pickle.load(fdata) + finally: + fdata.close() + + self.assertSameElements(data['lines'].keys(), []) + arcs = data['arcs'] + self.assertSameElements(arcs['x.py'], X_PY_ARCS_3) + self.assertSameElements(arcs['y.py'], Y_PY_ARCS_3) + + def test_combining_with_aliases(self): + covdata1 = CoverageData() + covdata1.add_line_data({ + '/home/ned/proj/src/a.py': {1:None, 2:None}, + '/home/ned/proj/src/sub/b.py': {3:None}, + }) + covdata1.write(suffix='1') + + covdata2 = CoverageData() + covdata2.add_line_data({ + r'c:\ned\test\a.py': {4:None, 5:None}, + r'c:\ned\test\sub\b.py': {6:None}, + }) + covdata2.write(suffix='2') + + covdata3 = CoverageData() + aliases = PathAliases() + aliases.add("/home/ned/proj/src/", "./") + aliases.add(r"c:\ned\test", "./") + covdata3.combine_parallel_data(aliases=aliases) + self.assert_summary( + covdata3, { './a.py':4, './sub/b.py':2 }, fullpath=True + ) + self.assert_measured_files(covdata3, [ './a.py', './sub/b.py' ]) diff --git a/tests/test_execfile.py b/tests/test_execfile.py new file mode 100644 index 00000000..e7d7041f --- /dev/null +++ b/tests/test_execfile.py @@ -0,0 +1,116 @@ +"""Tests for coverage.execfile""" + +import os, sys + +from coverage.execfile import run_python_file, run_python_module +from coverage.misc import NoSource + +from test.coveragetest import CoverageTest + +here = os.path.dirname(__file__) + +class RunFileTest(CoverageTest): + """Test cases for `run_python_file`.""" + + def test_run_python_file(self): + tryfile = os.path.join(here, "try_execfile.py") + run_python_file(tryfile, [tryfile, "arg1", "arg2"]) + mod_globs = eval(self.stdout()) + + # The file should think it is __main__ + self.assertEqual(mod_globs['__name__'], "__main__") + + # It should seem to come from a file named try_execfile.py + dunder_file = os.path.basename(mod_globs['__file__']) + self.assertEqual(dunder_file, "try_execfile.py") + + # It should have its correct module data. + self.assertEqual(mod_globs['__doc__'], + "Test file for run_python_file.") + self.assertEqual(mod_globs['DATA'], "xyzzy") + self.assertEqual(mod_globs['FN_VAL'], "my_fn('fooey')") + + # It must be self-importable as __main__. + self.assertEqual(mod_globs['__main__.DATA'], "xyzzy") + + # Argv should have the proper values. + self.assertEqual(mod_globs['argv'], [tryfile, "arg1", "arg2"]) + + # __builtins__ should have the right values, like open(). + self.assertEqual(mod_globs['__builtins__.has_open'], True) + + def test_no_extra_file(self): + # Make sure that running a file doesn't create an extra compiled file. + self.make_file("xxx", """\ + desc = "a non-.py file!" + """) + + self.assertEqual(os.listdir("."), ["xxx"]) + run_python_file("xxx", ["xxx"]) + self.assertEqual(os.listdir("."), ["xxx"]) + + def test_universal_newlines(self): + # Make sure we can read any sort of line ending. + pylines = """# try newlines|print('Hello, world!')|""".split('|') + for nl in ('\n', '\r\n', '\r'): + fpy = open('nl.py', 'wb') + try: + fpy.write(nl.join(pylines).encode('utf-8')) + finally: + fpy.close() + run_python_file('nl.py', ['nl.py']) + self.assertEqual(self.stdout(), "Hello, world!\n"*3) + + def test_missing_final_newline(self): + # Make sure we can deal with a Python file with no final newline. + self.make_file("abrupt.py", """\ + if 1: + a = 1 + print("a is %r" % a) + #""") + abrupt = open("abrupt.py").read() + self.assertEqual(abrupt[-1], '#') + run_python_file("abrupt.py", ["abrupt.py"]) + self.assertEqual(self.stdout(), "a is 1\n") + + def test_no_such_file(self): + self.assertRaises(NoSource, run_python_file, "xyzzy.py", []) + + +class RunModuleTest(CoverageTest): + """Test run_python_module.""" + + run_in_temp_dir = False + + def setUp(self): + super(RunModuleTest, self).setUp() + # Parent class saves and restores sys.path, we can just modify it. + sys.path.append(self.nice_file(os.path.dirname(__file__), 'modules')) + + def test_runmod1(self): + run_python_module("runmod1", ["runmod1", "hello"]) + self.assertEqual(self.stdout(), "runmod1: passed hello\n") + + def test_runmod2(self): + run_python_module("pkg1.runmod2", ["runmod2", "hello"]) + self.assertEqual(self.stdout(), "runmod2: passed hello\n") + + def test_runmod3(self): + run_python_module("pkg1.sub.runmod3", ["runmod3", "hello"]) + self.assertEqual(self.stdout(), "runmod3: passed hello\n") + + def test_pkg1_main(self): + run_python_module("pkg1", ["pkg1", "hello"]) + self.assertEqual(self.stdout(), "pkg1.__main__: passed hello\n") + + def test_pkg1_sub_main(self): + run_python_module("pkg1.sub", ["pkg1.sub", "hello"]) + self.assertEqual(self.stdout(), "pkg1.sub.__main__: passed hello\n") + + def test_no_such_module(self): + self.assertRaises(NoSource, run_python_module, "i_dont_exist", []) + self.assertRaises(NoSource, run_python_module, "i.dont_exist", []) + self.assertRaises(NoSource, run_python_module, "i.dont.exist", []) + + def test_no_main(self): + self.assertRaises(NoSource, run_python_module, "pkg2", ["pkg2", "hi"]) diff --git a/tests/test_farm.py b/tests/test_farm.py new file mode 100644 index 00000000..f25d6109 --- /dev/null +++ b/tests/test_farm.py @@ -0,0 +1,366 @@ +"""Run tests in the farm subdirectory. Designed for nose.""" + +import difflib, filecmp, fnmatch, glob, os, re, shutil, sys +from nose.plugins.skip import SkipTest + +from test.backtest import run_command, execfile # pylint: disable=W0622 + +from coverage.control import _TEST_NAME_FILE + + +def test_farm(clean_only=False): + """A test-generating function for nose to find and run.""" + for fname in glob.glob("test/farm/*/*.py"): + case = FarmTestCase(fname, clean_only) + yield (case,) + + +class FarmTestCase(object): + """A test case from the farm tree. + + Tests are short Python script files, often called run.py: + + copy("src", "out") + run(''' + coverage -x white.py + coverage -a white.py + ''', rundir="out") + compare("out", "gold", "*,cover") + clean("out") + + Verbs (copy, run, compare, clean) are methods in this class. FarmTestCase + has options to allow various uses of the test cases (normal execution, + cleaning-only, or run and leave the results for debugging). + + """ + def __init__(self, runpy, clean_only=False, dont_clean=False): + """Create a test case from a run.py file. + + `clean_only` means that only the clean() action is executed. + `dont_clean` means that the clean() action is not executed. + + """ + self.description = runpy + self.dir, self.runpy = os.path.split(runpy) + self.clean_only = clean_only + self.dont_clean = dont_clean + + def cd(self, newdir): + """Change the current directory, and return the old one.""" + cwd = os.getcwd() + os.chdir(newdir) + return cwd + + def addtopath(self, directory): + """Add `directory` to the path, and return the old path.""" + oldpath = sys.path[:] + if directory is not None: + sys.path.insert(0, directory) + return oldpath + + def restorepath(self, path): + """Restore the system path to `path`.""" + sys.path = path + + def __call__(self): + """Execute the test from the run.py file. + + """ + if _TEST_NAME_FILE: + f = open(_TEST_NAME_FILE, "w") + f.write(self.description.replace("/", "_")) + f.close() + + cwd = self.cd(self.dir) + + # Prepare a dictionary of globals for the run.py files to use. + fns = """ + copy run runfunc compare contains doesnt_contain clean skip + """.split() + if self.clean_only: + glo = dict([(fn, self.noop) for fn in fns]) + glo['clean'] = self.clean + else: + glo = dict([(fn, getattr(self, fn)) for fn in fns]) + if self.dont_clean: # pragma: not covered + glo['clean'] = self.noop + + old_mods = dict(sys.modules) + try: + execfile(self.runpy, glo) + finally: + self.cd(cwd) + # Remove any new modules imported during the test run. This lets us + # import the same source files for more than one test. + to_del = [m for m in sys.modules if m not in old_mods] + for m in to_del: + del sys.modules[m] + + def run_fully(self): # pragma: not covered + """Run as a full test case, with setUp and tearDown.""" + self.setUp() + try: + self() + finally: + self.tearDown() + + def fnmatch_list(self, files, file_pattern): + """Filter the list of `files` to only those that match `file_pattern`. + + If `file_pattern` is None, then return the entire list of files. + + Returns a list of the filtered files. + + """ + if file_pattern: + files = [f for f in files if fnmatch.fnmatch(f, file_pattern)] + return files + + def setUp(self): + """Test set up, run by nose before __call__.""" + + # Modules should be importable from the current directory. + self.old_syspath = sys.path[:] + sys.path.insert(0, '') + + def tearDown(self): + """Test tear down, run by nose after __call__.""" + # Make sure no matter what, the test is cleaned up. + if not self.dont_clean: # pragma: part covered + self.clean_only = True + self() + + # Restore the original sys.path + sys.path = self.old_syspath + + # Functions usable inside farm run.py files + + def noop(self, *args, **kwargs): + """A no-op function to stub out run, copy, etc, when only cleaning.""" + pass + + def copy(self, src, dst): + """Copy a directory.""" + + if os.path.exists(dst): + shutil.rmtree(dst) + shutil.copytree(src, dst) + + def run(self, cmds, rundir="src", outfile=None): + """Run a list of commands. + + `cmds` is a string, commands separated by newlines. + `rundir` is the directory in which to run the commands. + `outfile` is a filename to redirect stdout to. + + """ + cwd = self.cd(rundir) + if outfile: + fout = open(outfile, "a+") + try: + for cmd in cmds.split("\n"): + cmd = cmd.strip() + if not cmd: + continue + retcode, output = run_command(cmd) + print(output.rstrip()) + if outfile: + fout.write(output) + if retcode: + raise Exception("command exited abnormally") + finally: + if outfile: + fout.close() + self.cd(cwd) + + def runfunc(self, fn, rundir="src", addtopath=None): + """Run a function. + + `fn` is a callable. + `rundir` is the directory in which to run the function. + + """ + + cwd = self.cd(rundir) + oldpath = self.addtopath(addtopath) + try: + fn() + finally: + self.cd(cwd) + self.restorepath(oldpath) + + def compare(self, dir1, dir2, file_pattern=None, size_within=0, + left_extra=False, right_extra=False, scrubs=None + ): + """Compare files matching `file_pattern` in `dir1` and `dir2`. + + `dir2` is interpreted as a prefix, with Python version numbers appended + to find the actual directory to compare with. "foo" will compare against + "foo_v241", "foo_v24", "foo_v2", or "foo", depending on which directory + is found first. + + `size_within` is a percentage delta for the file sizes. If non-zero, + then the file contents are not compared (since they are expected to + often be different), but the file sizes must be within this amount. + For example, size_within=10 means that the two files' sizes must be + within 10 percent of each other to compare equal. + + `left_extra` true means the left directory can have extra files in it + without triggering an assertion. `right_extra` means the right + directory can. + + `scrubs` is a list of pairs, regex find and replace patterns to use to + scrub the files of unimportant differences. + + An assertion will be raised if the directories fail one of their + matches. + + """ + # Search for a dir2 with a version suffix. + version_suff = ''.join(map(str, sys.version_info[:3])) + while version_suff: + trydir = dir2 + '_v' + version_suff + if os.path.exists(trydir): + dir2 = trydir + break + version_suff = version_suff[:-1] + + assert os.path.exists(dir1), "Left directory missing: %s" % dir1 + assert os.path.exists(dir2), "Right directory missing: %s" % dir2 + + dc = filecmp.dircmp(dir1, dir2) + diff_files = self.fnmatch_list(dc.diff_files, file_pattern) + left_only = self.fnmatch_list(dc.left_only, file_pattern) + right_only = self.fnmatch_list(dc.right_only, file_pattern) + + if size_within: + # The files were already compared, use the diff_files list as a + # guide for size comparison. + wrong_size = [] + for f in diff_files: + left = open(os.path.join(dir1, f), "rb").read() + right = open(os.path.join(dir2, f), "rb").read() + size_l, size_r = len(left), len(right) + big, little = max(size_l, size_r), min(size_l, size_r) + if (big - little) / float(little) > size_within/100.0: + # print "%d %d" % (big, little) + # print "Left: ---\n%s\n-----\n%s" % (left, right) + wrong_size.append(f) + assert not wrong_size, ( + "File sizes differ between %s and %s: %s" % ( + dir1, dir2, wrong_size + )) + else: + # filecmp only compares in binary mode, but we want text mode. So + # look through the list of different files, and compare them + # ourselves. + text_diff = [] + for f in diff_files: + left = open(os.path.join(dir1, f), "rU").readlines() + right = open(os.path.join(dir2, f), "rU").readlines() + if scrubs: + left = self._scrub(left, scrubs) + right = self._scrub(right, scrubs) + if left != right: + text_diff.append(f) + print("".join(list(difflib.Differ().compare(left, right)))) + assert not text_diff, "Files differ: %s" % text_diff + + if not left_extra: + assert not left_only, "Files in %s only: %s" % (dir1, left_only) + if not right_extra: + assert not right_only, "Files in %s only: %s" % (dir2, right_only) + + def _scrub(self, strlist, scrubs): + """Scrub uninteresting data from the strings in `strlist`. + + `scrubs is a list of (find, replace) pairs of regexes that are used on + each string in `strlist`. A list of scrubbed strings is returned. + + """ + scrubbed = [] + for s in strlist: + for rgx_find, rgx_replace in scrubs: + s = re.sub(rgx_find, rgx_replace, s) + scrubbed.append(s) + return scrubbed + + def contains(self, filename, *strlist): + """Check that the file contains all of a list of strings. + + An assert will be raised if one of the arguments in `strlist` is + missing in `filename`. + + """ + text = open(filename, "r").read() + for s in strlist: + assert s in text, "Missing content in %s: %r" % (filename, s) + + def doesnt_contain(self, filename, *strlist): + """Check that the file contains none of a list of strings. + + An assert will be raised if any of the strings in strlist appears in + `filename`. + + """ + text = open(filename, "r").read() + for s in strlist: + assert s not in text, "Forbidden content in %s: %r" % (filename, s) + + def clean(self, cleandir): + """Clean `cleandir` by removing it and all its children completely.""" + # rmtree gives mysterious failures on Win7, so retry a "few" times. + # I've seen it take over 100 tries, so, 1000! This is probably the + # most unpleasant hack I've written in a long time... + tries = 1000 + while tries: # pragma: part covered + if os.path.exists(cleandir): + try: + shutil.rmtree(cleandir) + except OSError: # pragma: not covered + if tries == 1: + raise + else: + tries -= 1 + continue + break + + def skip(self, msg=None): + """Skip the current test.""" + raise SkipTest(msg) + + +def main(): # pragma: not covered + """Command-line access to test_farm. + + Commands: + + run testcase - Run a single test case. + out testcase - Run a test case, but don't clean up, to see the output. + clean - Clean all the output for all tests. + + """ + op = 'help' + try: + op = sys.argv[1] + except IndexError: + pass + + if op == 'run': + # Run the test for real. + case = FarmTestCase(sys.argv[2]) + case.run_fully() + elif op == 'out': + # Run the test, but don't clean up, so we can examine the output. + case = FarmTestCase(sys.argv[2], dont_clean=True) + case.run_fully() + elif op == 'clean': + # Run all the tests, but just clean. + for test in test_farm(clean_only=True): + test[0].run_fully() + else: + print(main.__doc__) + +# So that we can run just one farm run.py at a time. +if __name__ == '__main__': + main() diff --git a/tests/test_files.py b/tests/test_files.py new file mode 100644 index 00000000..051b2743 --- /dev/null +++ b/tests/test_files.py @@ -0,0 +1,169 @@ +"""Tests for files.py""" + +import os + +from coverage.files import FileLocator, TreeMatcher, FnmatchMatcher +from coverage.files import PathAliases, find_python_files, abs_file +from coverage.backward import set # pylint: disable=W0622 +from coverage.misc import CoverageException + +from test.coveragetest import CoverageTest + + +class FileLocatorTest(CoverageTest): + """Tests of `FileLocator`.""" + + def abs_path(self, p): + """Return the absolute path for `p`.""" + return os.path.join(os.getcwd(), os.path.normpath(p)) + + def test_simple(self): + self.make_file("hello.py") + fl = FileLocator() + self.assertEqual(fl.relative_filename("hello.py"), "hello.py") + a = self.abs_path("hello.py") + self.assertNotEqual(a, "hello.py") + self.assertEqual(fl.relative_filename(a), "hello.py") + + def test_peer_directories(self): + self.make_file("sub/proj1/file1.py") + self.make_file("sub/proj2/file2.py") + a1 = self.abs_path("sub/proj1/file1.py") + a2 = self.abs_path("sub/proj2/file2.py") + d = os.path.normpath("sub/proj1") + os.chdir(d) + fl = FileLocator() + self.assertEqual(fl.relative_filename(a1), "file1.py") + self.assertEqual(fl.relative_filename(a2), a2) + + def test_filepath_contains_absolute_prefix_twice(self): + # https://bitbucket.org/ned/coveragepy/issue/194 + # Build a path that has two pieces matching the absolute path prefix. + # Technically, this test doesn't do that on Windows, but drive + # letters make that impractical to acheive. + fl = FileLocator() + d = abs_file(os.curdir) + trick = os.path.splitdrive(d)[1].lstrip(os.path.sep) + rel = os.path.join('sub', trick, 'file1.py') + self.assertEqual(fl.relative_filename(abs_file(rel)), rel) + + +class MatcherTest(CoverageTest): + """Tests of file matchers.""" + + def test_tree_matcher(self): + file1 = self.make_file("sub/file1.py") + file2 = self.make_file("sub/file2.c") + file3 = self.make_file("sub2/file3.h") + file4 = self.make_file("sub3/file4.py") + file5 = self.make_file("sub3/file5.c") + fl = FileLocator() + tm = TreeMatcher([ + fl.canonical_filename("sub"), + fl.canonical_filename(file4), + ]) + self.assertTrue(tm.match(fl.canonical_filename(file1))) + self.assertTrue(tm.match(fl.canonical_filename(file2))) + self.assertFalse(tm.match(fl.canonical_filename(file3))) + self.assertTrue(tm.match(fl.canonical_filename(file4))) + self.assertFalse(tm.match(fl.canonical_filename(file5))) + + def test_fnmatch_matcher(self): + file1 = self.make_file("sub/file1.py") + file2 = self.make_file("sub/file2.c") + file3 = self.make_file("sub2/file3.h") + file4 = self.make_file("sub3/file4.py") + file5 = self.make_file("sub3/file5.c") + fl = FileLocator() + fnm = FnmatchMatcher(["*.py", "*/sub2/*"]) + self.assertTrue(fnm.match(fl.canonical_filename(file1))) + self.assertFalse(fnm.match(fl.canonical_filename(file2))) + self.assertTrue(fnm.match(fl.canonical_filename(file3))) + self.assertTrue(fnm.match(fl.canonical_filename(file4))) + self.assertFalse(fnm.match(fl.canonical_filename(file5))) + + +class PathAliasesTest(CoverageTest): + """Tests for coverage/files.py:PathAliases""" + + def test_noop(self): + aliases = PathAliases() + self.assertEqual(aliases.map('/ned/home/a.py'), '/ned/home/a.py') + + def test_nomatch(self): + aliases = PathAliases() + aliases.add('/home/*/src', './mysrc') + self.assertEqual(aliases.map('/home/foo/a.py'), '/home/foo/a.py') + + def test_wildcard(self): + aliases = PathAliases() + aliases.add('/ned/home/*/src', './mysrc') + self.assertEqual(aliases.map('/ned/home/foo/src/a.py'), './mysrc/a.py') + aliases = PathAliases() + aliases.add('/ned/home/*/src/', './mysrc') + self.assertEqual(aliases.map('/ned/home/foo/src/a.py'), './mysrc/a.py') + + def test_no_accidental_match(self): + aliases = PathAliases() + aliases.add('/home/*/src', './mysrc') + self.assertEqual(aliases.map('/home/foo/srcetc'), '/home/foo/srcetc') + + def test_multiple_patterns(self): + aliases = PathAliases() + aliases.add('/home/*/src', './mysrc') + aliases.add('/lib/*/libsrc', './mylib') + self.assertEqual(aliases.map('/home/foo/src/a.py'), './mysrc/a.py') + self.assertEqual(aliases.map('/lib/foo/libsrc/a.py'), './mylib/a.py') + + def test_cant_have_wildcard_at_end(self): + aliases = PathAliases() + self.assertRaisesRegexp( + CoverageException, "Pattern must not end with wildcards.", + aliases.add, "/ned/home/*", "fooey" + ) + self.assertRaisesRegexp( + CoverageException, "Pattern must not end with wildcards.", + aliases.add, "/ned/home/*/", "fooey" + ) + self.assertRaisesRegexp( + CoverageException, "Pattern must not end with wildcards.", + aliases.add, "/ned/home/*/*/", "fooey" + ) + + def test_no_accidental_munging(self): + aliases = PathAliases() + aliases.add(r'c:\Zoo\boo', 'src/') + aliases.add('/home/ned$', 'src/') + self.assertEqual(aliases.map(r'c:\Zoo\boo\foo.py'), 'src/foo.py') + self.assertEqual(aliases.map(r'/home/ned$/foo.py'), 'src/foo.py') + + def test_paths_are_os_corrected(self): + aliases = PathAliases() + aliases.add('/home/ned/*/src', './mysrc') + aliases.add(r'c:\ned\src', './mysrc') + mapped = aliases.map(r'C:\Ned\src\sub\a.py') + self.assertEqual(mapped, './mysrc/sub/a.py') + + aliases = PathAliases() + aliases.add('/home/ned/*/src', r'.\mysrc') + aliases.add(r'c:\ned\src', r'.\mysrc') + mapped = aliases.map(r'/home/ned/foo/src/sub/a.py') + self.assertEqual(mapped, r'.\mysrc\sub\a.py') + + +class FindPythonFilesTest(CoverageTest): + """Tests of `find_python_files`.""" + + def test_find_python_files(self): + self.make_file("sub/a.py") + self.make_file("sub/b.py") + self.make_file("sub/x.c") # nope: not .py + self.make_file("sub/ssub/__init__.py") + self.make_file("sub/ssub/s.py") + self.make_file("sub/ssub/~s.py") # nope: editor effluvia + self.make_file("sub/lab/exp.py") # nope: no __init__.py + py_files = set(find_python_files("sub")) + self.assert_same_files(py_files, [ + "sub/a.py", "sub/b.py", + "sub/ssub/__init__.py", "sub/ssub/s.py", + ]) diff --git a/tests/test_html.py b/tests/test_html.py new file mode 100644 index 00000000..66d1bd7d --- /dev/null +++ b/tests/test_html.py @@ -0,0 +1,297 @@ +# -*- coding: utf-8 -*- +"""Tests that HTML generation is awesome.""" + +import os.path, re, sys +import coverage +from coverage.misc import NotPython, NoSource + +from test.coveragetest import CoverageTest + +class HtmlTestHelpers(CoverageTest): + """Methods that help with HTML tests.""" + + def create_initial_files(self): + """Create the source files we need to run these tests.""" + self.make_file("main_file.py", """\ + import helper1, helper2 + helper1.func1(12) + helper2.func2(12) + """) + self.make_file("helper1.py", """\ + def func1(x): + if x % 2: + print("odd") + """) + self.make_file("helper2.py", """\ + def func2(x): + print("x is %d" % x) + """) + + def run_coverage(self, covargs=None, htmlargs=None): + """Run coverage on main_file.py, and create an HTML report.""" + self.clean_local_file_imports() + cov = coverage.coverage(**(covargs or {})) + self.start_import_stop(cov, "main_file") + cov.html_report(**(htmlargs or {})) + + def remove_html_files(self): + """Remove the HTML files created as part of the HTML report.""" + os.remove("htmlcov/index.html") + os.remove("htmlcov/main_file.html") + os.remove("htmlcov/helper1.html") + os.remove("htmlcov/helper2.html") + + +class HtmlDeltaTest(HtmlTestHelpers, CoverageTest): + """Tests of the HTML delta speed-ups.""" + + def setUp(self): + super(HtmlDeltaTest, self).setUp() + + # At least one of our tests monkey-patches the version of coverage, + # so grab it here to restore it later. + self.real_coverage_version = coverage.__version__ + + self.maxDiff = None + + def tearDown(self): + coverage.__version__ = self.real_coverage_version + super(HtmlDeltaTest, self).tearDown() + + def test_html_created(self): + # Test basic HTML generation: files should be created. + self.create_initial_files() + self.run_coverage() + + self.assert_exists("htmlcov/index.html") + self.assert_exists("htmlcov/main_file.html") + self.assert_exists("htmlcov/helper1.html") + self.assert_exists("htmlcov/helper2.html") + self.assert_exists("htmlcov/style.css") + self.assert_exists("htmlcov/coverage_html.js") + + def test_html_delta_from_source_change(self): + # HTML generation can create only the files that have changed. + # In this case, helper1 changes because its source is different. + self.create_initial_files() + self.run_coverage() + index1 = open("htmlcov/index.html").read() + self.remove_html_files() + + # Now change a file and do it again + self.make_file("helper1.py", """\ + def func1(x): # A nice function + if x % 2: + print("odd") + """) + + self.run_coverage() + + # Only the changed files should have been created. + self.assert_exists("htmlcov/index.html") + self.assert_exists("htmlcov/helper1.html") + self.assert_doesnt_exist("htmlcov/main_file.html") + self.assert_doesnt_exist("htmlcov/helper2.html") + index2 = open("htmlcov/index.html").read() + self.assertMultiLineEqual(index1, index2) + + def test_html_delta_from_coverage_change(self): + # HTML generation can create only the files that have changed. + # In this case, helper1 changes because its coverage is different. + self.create_initial_files() + self.run_coverage() + self.remove_html_files() + + # Now change a file and do it again + self.make_file("main_file.py", """\ + import helper1, helper2 + helper1.func1(23) + helper2.func2(23) + """) + + self.run_coverage() + + # Only the changed files should have been created. + self.assert_exists("htmlcov/index.html") + self.assert_exists("htmlcov/helper1.html") + self.assert_exists("htmlcov/main_file.html") + self.assert_doesnt_exist("htmlcov/helper2.html") + + def test_html_delta_from_settings_change(self): + # HTML generation can create only the files that have changed. + # In this case, everything changes because the coverage settings have + # changed. + self.create_initial_files() + self.run_coverage(covargs=dict(omit=[])) + index1 = open("htmlcov/index.html").read() + self.remove_html_files() + + self.run_coverage(covargs=dict(omit=['xyzzy*'])) + + # All the files have been reported again. + self.assert_exists("htmlcov/index.html") + self.assert_exists("htmlcov/helper1.html") + self.assert_exists("htmlcov/main_file.html") + self.assert_exists("htmlcov/helper2.html") + index2 = open("htmlcov/index.html").read() + self.assertMultiLineEqual(index1, index2) + + def test_html_delta_from_coverage_version_change(self): + # HTML generation can create only the files that have changed. + # In this case, everything changes because the coverage version has + # changed. + self.create_initial_files() + self.run_coverage() + index1 = open("htmlcov/index.html").read() + self.remove_html_files() + + # "Upgrade" coverage.py! + coverage.__version__ = "XYZZY" + + self.run_coverage() + + # All the files have been reported again. + self.assert_exists("htmlcov/index.html") + self.assert_exists("htmlcov/helper1.html") + self.assert_exists("htmlcov/main_file.html") + self.assert_exists("htmlcov/helper2.html") + index2 = open("htmlcov/index.html").read() + fixed_index2 = index2.replace("XYZZY", self.real_coverage_version) + self.assertMultiLineEqual(index1, fixed_index2) + + +class HtmlTitleTests(HtmlTestHelpers, CoverageTest): + """Tests of the HTML title support.""" + + def test_default_title(self): + self.create_initial_files() + self.run_coverage() + index = open("htmlcov/index.html").read() + self.assertIn("Coverage report", index) + self.assertIn("

      Coverage report:", index) + + def test_title_set_in_config_file(self): + self.create_initial_files() + self.make_file(".coveragerc", "[html]\ntitle = Metrics & stuff!\n") + self.run_coverage() + index = open("htmlcov/index.html").read() + self.assertIn("Metrics & stuff!", index) + self.assertIn("

      Metrics & stuff!:", index) + + if sys.version_info[:2] != (3,1): + def test_non_ascii_title_set_in_config_file(self): + self.create_initial_files() + self.make_file(".coveragerc", + "[html]\ntitle = «ταБЬℓσ» numbers" + ) + self.run_coverage() + index = open("htmlcov/index.html").read() + self.assertIn( + "«ταБЬℓσ»" + " numbers", index + ) + self.assertIn( + "<h1>«ταБЬℓσ»" + " numbers", index + ) + + def test_title_set_in_args(self): + self.create_initial_files() + self.make_file(".coveragerc", "[html]\ntitle = Good title\n") + self.run_coverage(htmlargs=dict(title="«ταБЬℓσ» & stüff!")) + index = open("htmlcov/index.html").read() + self.assertIn( + "<title>«ταБЬℓσ»" + " & stüff!", index + ) + self.assertIn( + "

      «ταБЬℓσ»" + " & stüff!:", index + ) + + +class HtmlWithUnparsableFilesTest(CoverageTest): + """Test the behavior when measuring unparsable files.""" + + def test_dotpy_not_python(self): + self.make_file("innocuous.py", "a = 1") + cov = coverage.coverage() + self.start_import_stop(cov, "innocuous") + self.make_file("innocuous.py", "

      This isn't python!

      ") + self.assertRaisesRegexp( + NotPython, + "Couldn't parse '.*innocuous.py' as Python source: '.*' at line 1", + cov.html_report + ) + + def test_dotpy_not_python_ignored(self): + self.make_file("innocuous.py", "a = 2") + cov = coverage.coverage() + self.start_import_stop(cov, "innocuous") + self.make_file("innocuous.py", "

      This isn't python!

      ") + cov.html_report(ignore_errors=True) + self.assert_exists("htmlcov/index.html") + # this would be better as a glob, if the html layout changes: + self.assert_doesnt_exist("htmlcov/innocuous.html") + + def test_dothtml_not_python(self): + # We run a .html file, and when reporting, we can't parse it as + # Python. Since it wasn't .py, no error is reported. + + # Run an "html" file + self.make_file("innocuous.html", "a = 3") + self.run_command("coverage run innocuous.html") + # Before reporting, change it to be an HTML file. + self.make_file("innocuous.html", "

      This isn't python at all!

      ") + output = self.run_command("coverage html") + self.assertEqual(output.strip(), "No data to report.") + + def test_execed_liar_ignored(self): + # Jinja2 sets __file__ to be a non-Python file, and then execs code. + # If that file contains non-Python code, a TokenError shouldn't + # have been raised when writing the HTML report. + if sys.version_info < (3, 0): + source = "exec compile('','','exec') in {'__file__': 'liar.html'}" + else: + source = "exec(compile('','','exec'), {'__file__': 'liar.html'})" + self.make_file("liar.py", source) + self.make_file("liar.html", "{# Whoops, not python code #}") + cov = coverage.coverage() + self.start_import_stop(cov, "liar") + cov.html_report() + self.assert_exists("htmlcov/index.html") + + def test_execed_liar_ignored_indentation_error(self): + # Jinja2 sets __file__ to be a non-Python file, and then execs code. + # If that file contains untokenizable code, we shouldn't get an + # exception. + if sys.version_info < (3, 0): + source = "exec compile('','','exec') in {'__file__': 'liar.html'}" + else: + source = "exec(compile('','','exec'), {'__file__': 'liar.html'})" + self.make_file("liar.py", source) + # Tokenize will raise an IndentationError if it can't dedent. + self.make_file("liar.html", "0\n 2\n 1\n") + cov = coverage.coverage() + self.start_import_stop(cov, "liar") + cov.html_report() + self.assert_exists("htmlcov/index.html") + + +class HtmlTest(CoverageTest): + """Moar HTML tests.""" + + def test_missing_source_file_incorrect_message(self): + # https://bitbucket.org/ned/coveragepy/issue/60 + self.make_file("thefile.py", "import sub.another\n") + self.make_file("sub/__init__.py", "") + self.make_file("sub/another.py", "print('another')\n") + cov = coverage.coverage() + self.start_import_stop(cov, 'thefile') + os.remove("sub/another.py") + + missing_file = os.path.join(self.temp_dir, "sub", "another.py") + self.assertRaisesRegexp(NoSource, + "(?i)No source for code: '%s'" % re.escape(missing_file), + cov.html_report + ) diff --git a/tests/test_misc.py b/tests/test_misc.py new file mode 100644 index 00000000..a32030ca --- /dev/null +++ b/tests/test_misc.py @@ -0,0 +1,73 @@ +"""Tests of miscellaneous stuff.""" + +from coverage.misc import Hasher, file_be_gone +from coverage import __version__, __url__ +from test.coveragetest import CoverageTest + +class HasherTest(CoverageTest): + """Test our wrapper of md5 hashing.""" + + def test_string_hashing(self): + h1 = Hasher() + h1.update("Hello, world!") + h2 = Hasher() + h2.update("Goodbye!") + h3 = Hasher() + h3.update("Hello, world!") + self.assertNotEqual(h1.digest(), h2.digest()) + self.assertEqual(h1.digest(), h3.digest()) + + def test_dict_hashing(self): + h1 = Hasher() + h1.update({'a': 17, 'b': 23}) + h2 = Hasher() + h2.update({'b': 23, 'a': 17}) + self.assertEqual(h1.digest(), h2.digest()) + + +class RemoveFileTest(CoverageTest): + """Tests of misc.file_be_gone.""" + + def test_remove_nonexistent_file(self): + # it's ok to try to remove a file that doesn't exist. + file_be_gone("not_here.txt") + + def test_remove_actual_file(self): + # it really does remove a file that does exist. + self.make_file("here.txt", "We are here, we are here, we are here!") + file_be_gone("here.txt") + self.assert_doesnt_exist("here.txt") + + def test_actual_errors(self): + # Errors can still happen. + # ". is a directory" on Unix, or "Access denied" on Windows + self.assertRaises(OSError, file_be_gone, ".") + + +class SetupPyTest(CoverageTest): + """Tests of setup.py""" + + run_in_temp_dir = False + + def test_metadata(self): + status, output = self.run_command_status( + "python setup.py --description --version --url --author" + ) + self.assertEqual(status, 0) + out = output.splitlines() + self.assertIn("measurement", out[0]) + self.assertEqual(out[1], __version__) + self.assertEqual(out[2], __url__) + self.assertIn("Ned Batchelder", out[3]) + + def test_more_metadata(self): + from setup import setup_args + + classifiers = setup_args['classifiers'] + self.assertGreater(len(classifiers), 7) + self.assertTrue(classifiers[-1].startswith("Development Status ::")) + + long_description = setup_args['long_description'].splitlines() + self.assertGreater(len(long_description), 7) + self.assertNotEqual(long_description[0].strip(), "") + self.assertNotEqual(long_description[-1].strip(), "") diff --git a/tests/test_oddball.py b/tests/test_oddball.py new file mode 100644 index 00000000..113328bb --- /dev/null +++ b/tests/test_oddball.py @@ -0,0 +1,386 @@ +"""Oddball cases for testing coverage.py""" + +import os, sys +import coverage + +from test.coveragetest import CoverageTest +from test import osinfo + +class ThreadingTest(CoverageTest): + """Tests of the threading support.""" + + def test_threading(self): + self.check_coverage("""\ + import threading + + def fromMainThread(): + return "called from main thread" + + def fromOtherThread(): + return "called from other thread" + + def neverCalled(): + return "no one calls me" + + other = threading.Thread(target=fromOtherThread) + other.start() + fromMainThread() + other.join() + """, + [1,3,4,6,7,9,10,12,13,14,15], "10") + + def test_thread_run(self): + self.check_coverage("""\ + import threading + + class TestThread(threading.Thread): + def run(self): + self.a = 5 + self.do_work() + self.a = 7 + + def do_work(self): + self.a = 10 + + thd = TestThread() + thd.start() + thd.join() + """, + [1,3,4,5,6,7,9,10,12,13,14], "") + + +class RecursionTest(CoverageTest): + """Check what happens when recursive code gets near limits.""" + + def test_short_recursion(self): + # We can definitely get close to 500 stack frames. + self.check_coverage("""\ + def recur(n): + if n == 0: + return 0 + else: + return recur(n-1)+1 + + recur(495) # We can get at least this many stack frames. + i = 8 # and this line will be traced + """, + [1,2,3,5,7,8], "") + + def test_long_recursion(self): + # We can't finish a very deep recursion, but we don't crash. + self.assertRaises(RuntimeError, self.check_coverage, + """\ + def recur(n): + if n == 0: + return 0 + else: + return recur(n-1)+1 + + recur(100000) # This is definitely too many frames. + """, + [1,2,3,5,7], "") + + def test_long_recursion_recovery(self): + # Test the core of bug 93: http://bitbucket.org/ned/coveragepy/issue/93 + # When recovering from a stack overflow, the Python trace function is + # disabled, but the C trace function is not. So if we're using a + # Python trace function, we won't trace anything after the stack + # overflow, and there should be a warning about it. If we're using + # the C trace function, only line 3 will be missing, and all else + # will be traced. + + self.make_file("recur.py", """\ + def recur(n): + if n == 0: + return 0 # never hit + else: + return recur(n-1)+1 + + try: + recur(100000) # This is definitely too many frames. + except RuntimeError: + i = 10 + i = 11 + """) + + cov = coverage.coverage() + self.start_import_stop(cov, "recur") + + pytrace = (cov.collector.tracer_name() == "PyTracer") + expected_missing = [3] + if pytrace: + expected_missing += [9,10,11] + + _, statements, missing, _ = cov.analysis("recur.py") + self.assertEqual(statements, [1,2,3,5,7,8,9,10,11]) + self.assertEqual(missing, expected_missing) + + # We can get a warning about the stackoverflow effect on the tracing + # function only if we have sys.gettrace + if pytrace and hasattr(sys, "gettrace"): + self.assertEqual(cov._warnings, + ["Trace function changed, measurement is likely wrong: None"] + ) + else: + self.assertEqual(cov._warnings, []) + + +class MemoryLeakTest(CoverageTest): + """Attempt the impossible: test that memory doesn't leak. + + Note: this test is truly unusual, and may fail unexpectedly. + In particular, it is known to fail on PyPy if test_oddball.py is run in + isolation: https://bitbucket.org/ned/coveragepy/issue/186 + + """ + + def test_for_leaks(self): + lines = list(range(301, 315)) + lines.remove(306) + # Ugly string mumbo jumbo to get 300 blank lines at the beginning.. + code = """\ + # blank line\n""" * 300 + """\ + def once(x): + if x % 100 == 0: + raise Exception("100!") + elif x % 2: + return 10 + else: + return 11 + i = 0 # Portable loop without alloc'ing memory. + while i < ITERS: + try: + once(i) + except: + pass + i += 1 + """ + ram_0 = osinfo.process_ram() + self.check_coverage(code.replace("ITERS", "10"), lines, "") + ram_1 = osinfo.process_ram() + self.check_coverage(code.replace("ITERS", "10000"), lines, "") + ram_2 = osinfo.process_ram() + ram_growth = (ram_2 - ram_1) - (ram_1 - ram_0) + self.assertTrue(ram_growth < 100000, "RAM grew by %d" % (ram_growth)) + + +class PyexpatTest(CoverageTest): + """Pyexpat screws up tracing. Make sure we've counter-defended properly.""" + + def test_pyexpat(self): + # pyexpat calls the trace function explicitly (inexplicably), and does + # it wrong for exceptions. Parsing a DOCTYPE for some reason throws + # an exception internally, and triggers its wrong behavior. This test + # checks that our fake PyTrace_RETURN hack in tracer.c works. It will + # also detect if the pyexpat bug is fixed unbeknownst to us, meaning + # we'd see two RETURNs where there should only be one. + + self.make_file("trydom.py", """\ + import xml.dom.minidom + + XML = '''\\ + + + ''' + + def foo(): + dom = xml.dom.minidom.parseString(XML) + assert len(dom.getElementsByTagName('child')) == 2 + a = 11 + + foo() + """) + + self.make_file("outer.py", "\n"*100 + "import trydom\na = 102\n") + + cov = coverage.coverage() + cov.erase() + + # Import the python file, executing it. + self.start_import_stop(cov, "outer") + + _, statements, missing, _ = cov.analysis("trydom.py") + self.assertEqual(statements, [1,3,8,9,10,11,13]) + self.assertEqual(missing, []) + + _, statements, missing, _ = cov.analysis("outer.py") + self.assertEqual(statements, [101,102]) + self.assertEqual(missing, []) + + +class ExceptionTest(CoverageTest): + """I suspect different versions of Python deal with exceptions differently + in the trace function. + """ + + def test_exception(self): + # Python 2.3's trace function doesn't get called with "return" if the + # scope is exiting due to an exception. This confounds our trace + # function which relies on scope announcements to track which files to + # trace. + # + # This test is designed to sniff this out. Each function in the call + # stack is in a different file, to try to trip up the tracer. Each + # file has active lines in a different range so we'll see if the lines + # get attributed to the wrong file. + + self.make_file("oops.py", """\ + def oops(args): + a = 2 + raise Exception("oops") + a = 4 + """) + + self.make_file("fly.py", "\n"*100 + """\ + def fly(calls): + a = 2 + calls[0](calls[1:]) + a = 4 + """) + + self.make_file("catch.py", "\n"*200 + """\ + def catch(calls): + try: + a = 3 + calls[0](calls[1:]) + a = 5 + except: + a = 7 + """) + + self.make_file("doit.py", "\n"*300 + """\ + def doit(calls): + try: + calls[0](calls[1:]) + except: + a = 5 + """) + + # Import all the modules before starting coverage, so the def lines + # won't be in all the results. + for mod in "oops fly catch doit".split(): + self.import_local_file(mod) + + # Each run nests the functions differently to get different + # combinations of catching exceptions and letting them fly. + runs = [ + ("doit fly oops", { + 'doit.py': [302,303,304,305], + 'fly.py': [102,103], + 'oops.py': [2,3], + }), + ("doit catch oops", { + 'doit.py': [302,303], + 'catch.py': [202,203,204,206,207], + 'oops.py': [2,3], + }), + ("doit fly catch oops", { + 'doit.py': [302,303], + 'fly.py': [102,103,104], + 'catch.py': [202,203,204,206,207], + 'oops.py': [2,3], + }), + ("doit catch fly oops", { + 'doit.py': [302,303], + 'catch.py': [202,203,204,206,207], + 'fly.py': [102,103], + 'oops.py': [2,3], + }), + ] + + for callnames, lines_expected in runs: + + # Make the list of functions we'll call for this test. + calls = [getattr(sys.modules[cn], cn) for cn in callnames.split()] + + cov = coverage.coverage() + cov.start() + # Call our list of functions: invoke the first, with the rest as + # an argument. + calls[0](calls[1:]) # pragma: nested + cov.stop() # pragma: nested + + # Clean the line data and compare to expected results. + # The filenames are absolute, so keep just the base. + cov._harvest_data() # private! sshhh... + lines = cov.data.line_data() + clean_lines = {} + for f, llist in lines.items(): + if f == __file__: + # ignore this file. + continue + clean_lines[os.path.basename(f)] = llist + self.assertEqual(clean_lines, lines_expected) + + +if sys.version_info >= (2, 5): + class DoctestTest(CoverageTest): + """Tests invoked with doctest should measure properly.""" + + def setUp(self): + super(DoctestTest, self).setUp() + + # Oh, the irony! This test case exists because Python 2.4's + # doctest module doesn't play well with coverage. But nose fixes + # the problem by monkeypatching doctest. I want to undo the + # monkeypatch to be sure I'm getting the doctest module that users + # of coverage will get. Deleting the imported module here is + # enough: when the test imports doctest again, it will get a fresh + # copy without the monkeypatch. + del sys.modules['doctest'] + + def test_doctest(self): + self.check_coverage('''\ + def return_arg_or_void(arg): + """If is None, return "Void"; otherwise return + + >>> return_arg_or_void(None) + 'Void' + >>> return_arg_or_void("arg") + 'arg' + >>> return_arg_or_void("None") + 'None' + """ + if arg is None: + return "Void" + else: + return arg + + import doctest, sys + doctest.testmod(sys.modules[__name__]) # we're not __main__ :( + ''', + [1,11,12,14,16,17], "") + + +if hasattr(sys, 'gettrace'): + class GettraceTest(CoverageTest): + """Tests that we work properly with `sys.gettrace()`.""" + def test_round_trip(self): + self.check_coverage('''\ + import sys + def foo(n): + return 3*n + def bar(n): + return 5*n + a = foo(6) + sys.settrace(sys.gettrace()) + a = bar(8) + ''', + [1,2,3,4,5,6,7,8], "") + + def test_multi_layers(self): + self.check_coverage('''\ + import sys + def level1(): + a = 3 + level2() + b = 5 + def level2(): + c = 7 + sys.settrace(sys.gettrace()) + d = 9 + e = 10 + level1() + f = 12 + ''', + [1,2,3,4,5,6,7,8,9,10,11,12], "") diff --git a/tests/test_parser.py b/tests/test_parser.py new file mode 100644 index 00000000..6ccef206 --- /dev/null +++ b/tests/test_parser.py @@ -0,0 +1,131 @@ +"""Tests for Coverage.py's code parsing.""" + +import textwrap +from test.coveragetest import CoverageTest +from coverage.parser import CodeParser + + +class ParserTest(CoverageTest): + """Tests for Coverage.py's code parsing.""" + + run_in_temp_dir = False + + def parse_source(self, text): + """Parse `text` as source, and return the `CodeParser` used.""" + text = textwrap.dedent(text) + cp = CodeParser(text=text, exclude="nocover") + cp.parse_source() + return cp + + def test_exit_counts(self): + cp = self.parse_source("""\ + # check some basic branch counting + class Foo: + def foo(self, a): + if a: + return 5 + else: + return 7 + + class Bar: + pass + """) + self.assertEqual(cp.exit_counts(), { + 2:1, 3:1, 4:2, 5:1, 7:1, 9:1, 10:1 + }) + + def test_try_except(self): + cp = self.parse_source("""\ + try: + a = 2 + except ValueError: + a = 4 + except ZeroDivideError: + a = 6 + except: + a = 8 + b = 9 + """) + self.assertEqual(cp.exit_counts(), { + 1: 1, 2:1, 3:1, 4:1, 5:1, 6:1, 7:1, 8:1, 9:1 + }) + + def test_excluded_classes(self): + cp = self.parse_source("""\ + class Foo: + def __init__(self): + pass + + if 0: # nocover + class Bar: + pass + """) + self.assertEqual(cp.exit_counts(), { + 1:0, 2:1, 3:1 + }) + + def test_missing_branch_to_excluded_code(self): + cp = self.parse_source("""\ + if fooey: + a = 2 + else: # nocover + a = 4 + b = 5 + """) + self.assertEqual(cp.exit_counts(), { 1:1, 2:1, 5:1 }) + cp = self.parse_source("""\ + def foo(): + if fooey: + a = 3 + else: + a = 5 + b = 6 + """) + self.assertEqual(cp.exit_counts(), { 1:1, 2:2, 3:1, 5:1, 6:1 }) + cp = self.parse_source("""\ + def foo(): + if fooey: + a = 3 + else: # nocover + a = 5 + b = 6 + """) + self.assertEqual(cp.exit_counts(), { 1:1, 2:1, 3:1, 6:1 }) + + +class ParserFileTest(CoverageTest): + """Tests for Coverage.py's code parsing from files.""" + + def parse_file(self, filename): + """Parse `text` as source, and return the `CodeParser` used.""" + cp = CodeParser(filename=filename, exclude="nocover") + cp.parse_source() + return cp + + def test_line_endings(self): + text = """\ + # check some basic branch counting + class Foo: + def foo(self, a): + if a: + return 5 + else: + return 7 + + class Bar: + pass + """ + counts = { 2:1, 3:1, 4:2, 5:1, 7:1, 9:1, 10:1 } + name_endings = (("unix", "\n"), ("dos", "\r\n"), ("mac", "\r")) + for fname, newline in name_endings: + fname = fname + ".py" + self.make_file(fname, text, newline=newline) + cp = self.parse_file(fname) + self.assertEqual(cp.exit_counts(), counts) + + def test_encoding(self): + self.make_file("encoded.py", """\ + coverage = "\xe7\xf6v\xear\xe3g\xe9" + """) + cp = self.parse_file("encoded.py") + cp.exit_counts() diff --git a/tests/test_phystokens.py b/tests/test_phystokens.py new file mode 100644 index 00000000..e4834e4c --- /dev/null +++ b/tests/test_phystokens.py @@ -0,0 +1,79 @@ +"""Tests for Coverage.py's improved tokenizer.""" + +import os, re +from test.coveragetest import CoverageTest +from coverage.phystokens import source_token_lines + + +SIMPLE = """\ +# yay! +def foo(): + say('two = %d' % 2) +""" + +MIXED_WS = """\ +def hello(): + a="Hello world!" +\tb="indented" +""" + +HERE = os.path.split(__file__)[0] + + +class PhysTokensTest(CoverageTest): + """Tests for Coverage.py's improver tokenizer.""" + + run_in_temp_dir = False + + def check_tokenization(self, source): + """Tokenize `source`, then put it back together, should be the same.""" + tokenized = "" + for line in source_token_lines(source): + text = "".join([t for _,t in line]) + tokenized += text + "\n" + # source_token_lines doesn't preserve trailing spaces, so trim all that + # before comparing. + source = source.replace('\r\n', '\n') + source = re.sub(r"(?m)[ \t]+$", "", source) + tokenized = re.sub(r"(?m)[ \t]+$", "", tokenized) + self.assertMultiLineEqual(source, tokenized) + + def check_file_tokenization(self, fname): + """Use the contents of `fname` for `check_tokenization`.""" + self.check_tokenization(open(fname).read()) + + def test_simple(self): + self.assertEqual(list(source_token_lines(SIMPLE)), + [ + [('com', "# yay!")], + [('key', 'def'), ('ws', ' '), ('nam', 'foo'), ('op', '('), + ('op', ')'), ('op', ':')], + [('ws', ' '), ('nam', 'say'), ('op', '('), + ('str', "'two = %d'"), ('ws', ' '), ('op', '%'), + ('ws', ' '), ('num', '2'), ('op', ')')] + ]) + self.check_tokenization(SIMPLE) + + def test_tab_indentation(self): + # Mixed tabs and spaces... + self.assertEqual(list(source_token_lines(MIXED_WS)), + [ + [('key', 'def'), ('ws', ' '), ('nam', 'hello'), ('op', '('), + ('op', ')'), ('op', ':')], + [('ws', ' '), ('nam', 'a'), ('op', '='), + ('str', '"Hello world!"')], + [('ws', ' '), ('nam', 'b'), ('op', '='), + ('str', '"indented"')], + ]) + + def test_tokenize_real_file(self): + # Check the tokenization of a real file (large, btw). + real_file = os.path.join(HERE, "test_coverage.py") + self.check_file_tokenization(real_file) + + def test_stress(self): + # Check the tokenization of a stress-test file. + stress = os.path.join(HERE, "stress_phystoken.tok") + self.check_file_tokenization(stress) + stress = os.path.join(HERE, "stress_phystoken_dos.tok") + self.check_file_tokenization(stress) diff --git a/tests/test_process.py b/tests/test_process.py new file mode 100644 index 00000000..bf22cc9d --- /dev/null +++ b/tests/test_process.py @@ -0,0 +1,575 @@ +"""Tests for process behavior of coverage.py.""" + +import glob, os, sys, textwrap +from nose.plugins.skip import SkipTest +import coverage + +from test.coveragetest import CoverageTest + +here = os.path.dirname(__file__) + +class ProcessTest(CoverageTest): + """Tests of the per-process behavior of coverage.py.""" + + def number_of_data_files(self): + """Return the number of coverage data files in this directory.""" + num = 0 + for f in os.listdir('.'): + if f.startswith('.coverage.') or f == '.coverage': + num += 1 + return num + + def test_save_on_exit(self): + self.make_file("mycode.py", """\ + h = "Hello" + w = "world" + """) + + self.assert_doesnt_exist(".coverage") + self.run_command("coverage -x mycode.py") + self.assert_exists(".coverage") + + def test_environment(self): + # Checks that we can import modules from the test directory at all! + self.make_file("mycode.py", """\ + import covmod1 + import covmodzip1 + a = 1 + print ('done') + """) + + self.assert_doesnt_exist(".coverage") + out = self.run_command("coverage -x mycode.py") + self.assert_exists(".coverage") + self.assertEqual(out, 'done\n') + + def test_combine_parallel_data(self): + self.make_file("b_or_c.py", """\ + import sys + a = 1 + if sys.argv[1] == 'b': + b = 1 + else: + c = 1 + d = 1 + print ('done') + """) + + out = self.run_command("coverage -x -p b_or_c.py b") + self.assertEqual(out, 'done\n') + self.assert_doesnt_exist(".coverage") + + out = self.run_command("coverage -x -p b_or_c.py c") + self.assertEqual(out, 'done\n') + self.assert_doesnt_exist(".coverage") + + # After two -p runs, there should be two .coverage.machine.123 files. + self.assertEqual(self.number_of_data_files(), 2) + + # Combine the parallel coverage data files into .coverage . + self.run_command("coverage -c") + self.assert_exists(".coverage") + + # After combining, there should be only the .coverage file. + self.assertEqual(self.number_of_data_files(), 1) + + # Read the coverage file and see that b_or_c.py has all 7 lines + # executed. + data = coverage.CoverageData() + data.read_file(".coverage") + self.assertEqual(data.summary()['b_or_c.py'], 7) + + def test_combine_parallel_data_in_two_steps(self): + self.make_file("b_or_c.py", """\ + import sys + a = 1 + if sys.argv[1] == 'b': + b = 1 + else: + c = 1 + d = 1 + print ('done') + """) + + out = self.run_command("coverage -x -p b_or_c.py b") + self.assertEqual(out, 'done\n') + self.assert_doesnt_exist(".coverage") + self.assertEqual(self.number_of_data_files(), 1) + + # Combine the (one) parallel coverage data file into .coverage . + self.run_command("coverage -c") + self.assert_exists(".coverage") + self.assertEqual(self.number_of_data_files(), 1) + + out = self.run_command("coverage -x -p b_or_c.py c") + self.assertEqual(out, 'done\n') + self.assert_exists(".coverage") + self.assertEqual(self.number_of_data_files(), 2) + + # Combine the parallel coverage data files into .coverage . + self.run_command("coverage -c") + self.assert_exists(".coverage") + + # After combining, there should be only the .coverage file. + self.assertEqual(self.number_of_data_files(), 1) + + # Read the coverage file and see that b_or_c.py has all 7 lines + # executed. + data = coverage.CoverageData() + data.read_file(".coverage") + self.assertEqual(data.summary()['b_or_c.py'], 7) + + def test_combine_with_rc(self): + self.make_file("b_or_c.py", """\ + import sys + a = 1 + if sys.argv[1] == 'b': + b = 1 + else: + c = 1 + d = 1 + print ('done') + """) + + self.make_file(".coveragerc", """\ + [run] + parallel = true + """) + + out = self.run_command("coverage run b_or_c.py b") + self.assertEqual(out, 'done\n') + self.assert_doesnt_exist(".coverage") + + out = self.run_command("coverage run b_or_c.py c") + self.assertEqual(out, 'done\n') + self.assert_doesnt_exist(".coverage") + + # After two runs, there should be two .coverage.machine.123 files. + self.assertEqual(self.number_of_data_files(), 2) + + # Combine the parallel coverage data files into .coverage . + self.run_command("coverage combine") + self.assert_exists(".coverage") + self.assert_exists(".coveragerc") + + # After combining, there should be only the .coverage file. + self.assertEqual(self.number_of_data_files(), 1) + + # Read the coverage file and see that b_or_c.py has all 7 lines + # executed. + data = coverage.CoverageData() + data.read_file(".coverage") + self.assertEqual(data.summary()['b_or_c.py'], 7) + + # Reporting should still work even with the .rc file + out = self.run_command("coverage report") + self.assertMultiLineEqual(out, textwrap.dedent("""\ + Name Stmts Miss Cover + ---------------------------- + b_or_c 7 0 100% + """)) + + def test_combine_with_aliases(self): + self.make_file("d1/x.py", """\ + a = 1 + b = 2 + print("%s %s" % (a, b)) + """) + + self.make_file("d2/x.py", """\ + # 1 + # 2 + # 3 + c = 4 + d = 5 + print("%s %s" % (c, d)) + """) + + self.make_file(".coveragerc", """\ + [run] + parallel = True + + [paths] + source = + src + */d1 + */d2 + """) + + out = self.run_command("coverage run " + os.path.normpath("d1/x.py")) + self.assertEqual(out, '1 2\n') + out = self.run_command("coverage run " + os.path.normpath("d2/x.py")) + self.assertEqual(out, '4 5\n') + + self.assertEqual(self.number_of_data_files(), 2) + + self.run_command("coverage combine") + self.assert_exists(".coverage") + + # After combining, there should be only the .coverage file. + self.assertEqual(self.number_of_data_files(), 1) + + # Read the coverage data file and see that the two different x.py + # files have been combined together. + data = coverage.CoverageData() + data.read_file(".coverage") + summary = data.summary(fullpath=True) + self.assertEqual(len(summary), 1) + actual = os.path.normcase(os.path.abspath(list(summary.keys())[0])) + expected = os.path.normcase(os.path.abspath('src/x.py')) + self.assertEqual(actual, expected) + self.assertEqual(list(summary.values())[0], 6) + + def test_missing_source_file(self): + # Check what happens if the source is missing when reporting happens. + self.make_file("fleeting.py", """\ + s = 'goodbye, cruel world!' + """) + + self.run_command("coverage run fleeting.py") + os.remove("fleeting.py") + out = self.run_command("coverage html -d htmlcov") + self.assertRegexpMatches(out, "No source for code: '.*fleeting.py'") + self.assertNotIn("Traceback", out) + + # It happens that the code paths are different for *.py and other + # files, so try again with no extension. + self.make_file("fleeting", """\ + s = 'goodbye, cruel world!' + """) + + self.run_command("coverage run fleeting") + os.remove("fleeting") + status, out = self.run_command_status("coverage html -d htmlcov", 1) + self.assertRegexpMatches(out, "No source for code: '.*fleeting'") + self.assertNotIn("Traceback", out) + self.assertEqual(status, 1) + + def test_running_missing_file(self): + status, out = self.run_command_status("coverage run xyzzy.py", 1) + self.assertRegexpMatches(out, "No file to run: .*xyzzy.py") + self.assertNotIn("raceback", out) + self.assertNotIn("rror", out) + self.assertEqual(status, 1) + + def test_code_throws(self): + self.make_file("throw.py", """\ + def f1(): + raise Exception("hey!") + + def f2(): + f1() + + f2() + """) + + # The important thing is for "coverage run" and "python" to report the + # same traceback. + status, out = self.run_command_status("coverage run throw.py", 1) + out2 = self.run_command("python throw.py") + if '__pypy__' in sys.builtin_module_names: + # Pypy has an extra frame in the traceback for some reason + lines2 = out2.splitlines() + out2 = "".join([l+"\n" for l in lines2 if "toplevel" not in l]) + self.assertMultiLineEqual(out, out2) + + # But also make sure that the output is what we expect. + self.assertIn('File "throw.py", line 5, in f2', out) + self.assertIn('raise Exception("hey!")', out) + self.assertNotIn('coverage', out) + self.assertEqual(status, 1) + + def test_code_exits(self): + self.make_file("exit.py", """\ + import sys + def f1(): + print("about to exit..") + sys.exit(17) + + def f2(): + f1() + + f2() + """) + + # The important thing is for "coverage run" and "python" to have the + # same output. No traceback. + status, out = self.run_command_status("coverage run exit.py", 17) + status2, out2 = self.run_command_status("python exit.py", 17) + self.assertMultiLineEqual(out, out2) + self.assertMultiLineEqual(out, "about to exit..\n") + self.assertEqual(status, status2) + self.assertEqual(status, 17) + + def test_code_exits_no_arg(self): + self.make_file("exit_none.py", """\ + import sys + def f1(): + print("about to exit quietly..") + sys.exit() + + f1() + """) + status, out = self.run_command_status("coverage run exit_none.py", 0) + status2, out2 = self.run_command_status("python exit_none.py", 0) + self.assertMultiLineEqual(out, out2) + self.assertMultiLineEqual(out, "about to exit quietly..\n") + self.assertEqual(status, status2) + self.assertEqual(status, 0) + + def test_coverage_run_is_like_python(self): + tryfile = os.path.join(here, "try_execfile.py") + self.make_file("run_me.py", open(tryfile).read()) + out = self.run_command("coverage run run_me.py") + out2 = self.run_command("python run_me.py") + self.assertMultiLineEqual(out, out2) + + if sys.version_info >= (2, 6): # Doesn't work in 2.5, and I don't care! + def test_coverage_run_dashm_is_like_python_dashm(self): + # These -m commands assume the coverage tree is on the path. + out = self.run_command("coverage run -m test.try_execfile") + out2 = self.run_command("python -m test.try_execfile") + self.assertMultiLineEqual(out, out2) + + if 0: # Expected failure + # For https://bitbucket.org/ned/coveragepy/issue/207 + def test_coverage_run_dashm_is_like_python_dashm_with__main__207(self): + self.make_file("package/__init__.py") # empty + self.make_file("package/__main__.py", "#\n") # empty + out = self.run_command("coverage run -m package") + out2 = self.run_command("python -m package") + self.assertMultiLineEqual(out, out2) + + if hasattr(os, 'fork'): + def test_fork(self): + self.make_file("fork.py", """\ + import os + + def child(): + print('Child!') + + def main(): + ret = os.fork() + + if ret == 0: + child() + else: + os.waitpid(ret, 0) + + main() + """) + + out = self.run_command("coverage run -p fork.py") + self.assertEqual(out, 'Child!\n') + self.assert_doesnt_exist(".coverage") + + # After running the forking program, there should be two + # .coverage.machine.123 files. + self.assertEqual(self.number_of_data_files(), 2) + + # Combine the parallel coverage data files into .coverage . + self.run_command("coverage -c") + self.assert_exists(".coverage") + + # After combining, there should be only the .coverage file. + self.assertEqual(self.number_of_data_files(), 1) + + # Read the coverage file and see that b_or_c.py has all 7 lines + # executed. + data = coverage.CoverageData() + data.read_file(".coverage") + self.assertEqual(data.summary()['fork.py'], 9) + + def test_warnings(self): + self.make_file("hello.py", """\ + import sys, os + print("Hello") + """) + out = self.run_command("coverage run --source=sys,xyzzy,quux hello.py") + + self.assertIn("Hello\n", out) + self.assertIn(textwrap.dedent("""\ + Coverage.py warning: Module sys has no Python source. + Coverage.py warning: Module xyzzy was never imported. + Coverage.py warning: Module quux was never imported. + Coverage.py warning: No data was collected. + """), out) + + def test_warnings_during_reporting(self): + # While fixing issue #224, the warnings were being printed far too + # often. Make sure they're not any more. + self.make_file("hello.py", """\ + import sys, os, the_other + print("Hello") + """) + self.make_file("the_other.py", """\ + print("What?") + """) + self.make_file(".coveragerc", """\ + [run] + source = + . + xyzzy + """) + + self.run_command("coverage run hello.py") + out = self.run_command("coverage html") + self.assertEqual(out.count("Module xyzzy was never imported."), 0) + + def test_warnings_if_never_run(self): + out = self.run_command("coverage run i_dont_exist.py") + self.assertIn("No file to run: 'i_dont_exist.py'", out) + self.assertNotIn("warning", out) + self.assertNotIn("Exception", out) + + out = self.run_command("coverage run -m no_such_module") + self.assertTrue( + ("No module named no_such_module" in out) or + ("No module named 'no_such_module'" in out) + ) + self.assertNotIn("warning", out) + self.assertNotIn("Exception", out) + + if sys.version_info >= (3, 0): # This only works on 3.x for now. + # It only works with the C tracer, + c_tracer = os.getenv('COVERAGE_TEST_TRACER', 'c') == 'c' + # and if we aren't measuring ourselves. + metacov = os.getenv('COVERAGE_COVERAGE', '') != '' + if c_tracer and not metacov: # pragma: not covered + def test_fullcoverage(self): + # fullcoverage is a trick to get stdlib modules measured from + # the very beginning of the process. Here we import os and + # then check how many lines are measured. + self.make_file("getenv.py", """\ + import os + print("FOOEY == %s" % os.getenv("FOOEY")) + """) + + fullcov = os.path.join( + os.path.dirname(coverage.__file__), "fullcoverage" + ) + self.set_environ("FOOEY", "BOO") + self.set_environ("PYTHONPATH", fullcov) + out = self.run_command("python -m coverage run -L getenv.py") + self.assertEqual(out, "FOOEY == BOO\n") + data = coverage.CoverageData() + data.read_file(".coverage") + # The actual number of executed lines in os.py when it's + # imported is 120 or so. Just running os.getenv executes + # about 5. + self.assertGreater(data.summary()['os.py'], 50) + + +class AliasedCommandTests(CoverageTest): + """Tests of the version-specific command aliases.""" + + def test_major_version_works(self): + # "coverage2" works on py2 + cmd = "coverage%d" % sys.version_info[0] + out = self.run_command(cmd) + self.assertIn("Code coverage for Python", out) + + def test_wrong_alias_doesnt_work(self): + # "coverage3" doesn't work on py2 + badcmd = "coverage%d" % (5 - sys.version_info[0]) + out = self.run_command(badcmd) + self.assertNotIn("Code coverage for Python", out) + + def test_specific_alias_works(self): + # "coverage-2.7" works on py2.7 + cmd = "coverage-%d.%d" % sys.version_info[:2] + out = self.run_command(cmd) + self.assertIn("Code coverage for Python", out) + + +class FailUnderTest(CoverageTest): + """Tests of the --fail-under switch.""" + + def setUp(self): + super(FailUnderTest, self).setUp() + self.make_file("fifty.py", """\ + # I have 50% coverage! + a = 1 + if a > 2: + b = 3 + c = 4 + """) + st, _ = self.run_command_status("coverage run fifty.py", 0) + self.assertEqual(st, 0) + + def test_report(self): + st, _ = self.run_command_status("coverage report --fail-under=50", 0) + self.assertEqual(st, 0) + st, _ = self.run_command_status("coverage report --fail-under=51", 2) + self.assertEqual(st, 2) + + def test_html_report(self): + st, _ = self.run_command_status("coverage html --fail-under=50", 0) + self.assertEqual(st, 0) + st, _ = self.run_command_status("coverage html --fail-under=51", 2) + self.assertEqual(st, 2) + + def test_xml_report(self): + st, _ = self.run_command_status("coverage xml --fail-under=50", 0) + self.assertEqual(st, 0) + st, _ = self.run_command_status("coverage xml --fail-under=51", 2) + self.assertEqual(st, 2) + + +class ProcessStartupTest(CoverageTest): + """Test that we can measure coverage in subprocesses.""" + + def setUp(self): + super(ProcessStartupTest, self).setUp() + # Find a place to put a .pth file. + pth_contents = "import coverage; coverage.process_startup()\n" + for d in sys.path: # pragma: part covered + g = glob.glob(os.path.join(d, "*.pth")) + if g: + pth_path = os.path.join(d, "subcover.pth") + pth = open(pth_path, "w") + try: + try: + pth.write(pth_contents) + self.pth_path = pth_path + break + except (IOError, OSError): # pragma: not covered + pass + finally: + pth.close() + else: # pragma: not covered + raise Exception("Couldn't find a place for the .pth file") + + def tearDown(self): + super(ProcessStartupTest, self).tearDown() + # Clean up the .pth file we made. + os.remove(self.pth_path) + + def test_subprocess_with_pth_files(self): # pragma: not covered + if os.environ.get('COVERAGE_COVERAGE', ''): + raise SkipTest( + "Can't test subprocess pth file suppport during metacoverage" + ) + # Main will run sub.py + self.make_file("main.py", """\ + import os + os.system("python sub.py") + """) + # sub.py will write a few lines. + self.make_file("sub.py", """\ + f = open("out.txt", "w") + f.write("Hello, world!\\n") + f.close() + """) + self.make_file("coverage.ini", """\ + [run] + data_file = .mycovdata + """) + self.set_environ("COVERAGE_PROCESS_START", "coverage.ini") + import main # pylint: disable=F0401,W0612 + + self.assertEqual(open("out.txt").read(), "Hello, world!\n") + # Read the data from .coverage + data = coverage.CoverageData() + data.read_file(".mycovdata") + self.assertEqual(data.summary()['sub.py'], 3) diff --git a/tests/test_results.py b/tests/test_results.py new file mode 100644 index 00000000..3caa5a66 --- /dev/null +++ b/tests/test_results.py @@ -0,0 +1,60 @@ +"""Tests for Coverage.py's results analysis.""" + +from coverage.results import Numbers +from test.coveragetest import CoverageTest + + +class NumbersTest(CoverageTest): + """Tests for Coverage.py's numeric measurement summaries.""" + + run_in_temp_dir = False + + def test_basic(self): + n1 = Numbers(n_files=1, n_statements=200, n_missing=20) + self.assertEqual(n1.n_statements, 200) + self.assertEqual(n1.n_executed, 180) + self.assertEqual(n1.n_missing, 20) + self.assertEqual(n1.pc_covered, 90) + + def test_addition(self): + n1 = Numbers(n_files=1, n_statements=200, n_missing=20) + n2 = Numbers(n_files=1, n_statements=10, n_missing=8) + n3 = n1 + n2 + self.assertEqual(n3.n_files, 2) + self.assertEqual(n3.n_statements, 210) + self.assertEqual(n3.n_executed, 182) + self.assertEqual(n3.n_missing, 28) + self.assertAlmostEqual(n3.pc_covered, 86.666666666) + + def test_sum(self): + n1 = Numbers(n_files=1, n_statements=200, n_missing=20) + n2 = Numbers(n_files=1, n_statements=10, n_missing=8) + n3 = sum([n1, n2]) + self.assertEqual(n3.n_files, 2) + self.assertEqual(n3.n_statements, 210) + self.assertEqual(n3.n_executed, 182) + self.assertEqual(n3.n_missing, 28) + self.assertAlmostEqual(n3.pc_covered, 86.666666666) + + def test_pc_covered_str(self): + n0 = Numbers(n_files=1, n_statements=1000, n_missing=0) + n1 = Numbers(n_files=1, n_statements=1000, n_missing=1) + n999 = Numbers(n_files=1, n_statements=1000, n_missing=999) + n1000 = Numbers(n_files=1, n_statements=1000, n_missing=1000) + self.assertEqual(n0.pc_covered_str, "100") + self.assertEqual(n1.pc_covered_str, "99") + self.assertEqual(n999.pc_covered_str, "1") + self.assertEqual(n1000.pc_covered_str, "0") + + def test_pc_covered_str_precision(self): + assert Numbers._precision == 0 + Numbers.set_precision(1) + n0 = Numbers(n_files=1, n_statements=10000, n_missing=0) + n1 = Numbers(n_files=1, n_statements=10000, n_missing=1) + n9999 = Numbers(n_files=1, n_statements=10000, n_missing=9999) + n10000 = Numbers(n_files=1, n_statements=10000, n_missing=10000) + self.assertEqual(n0.pc_covered_str, "100.0") + self.assertEqual(n1.pc_covered_str, "99.9") + self.assertEqual(n9999.pc_covered_str, "0.1") + self.assertEqual(n10000.pc_covered_str, "0.0") + Numbers.set_precision(0) diff --git a/tests/test_summary.py b/tests/test_summary.py new file mode 100644 index 00000000..5bb903a6 --- /dev/null +++ b/tests/test_summary.py @@ -0,0 +1,298 @@ +"""Test text-based summary reporting for coverage.py""" + +import os, re, sys + +import coverage +from coverage.backward import StringIO + +from test.coveragetest import CoverageTest + +class SummaryTest(CoverageTest): + """Tests of the text summary reporting for coverage.py.""" + + def setUp(self): + super(SummaryTest, self).setUp() + self.make_file("mycode.py", """\ + import covmod1 + import covmodzip1 + a = 1 + print ('done') + """) + # Parent class saves and restores sys.path, we can just modify it. + sys.path.append(self.nice_file(os.path.dirname(__file__), 'modules')) + + def report_from_command(self, cmd): + """Return the report from the `cmd`, with some convenience added.""" + report = self.run_command(cmd).replace('\\', '/') + self.assertNotIn("error", report.lower()) + return report + + def line_count(self, report): + """How many lines are in `report`?""" + self.assertEqual(report.split('\n')[-1], "") + return len(report.split('\n')) - 1 + + def last_line_squeezed(self, report): + """Return the last line of `report` with the spaces squeezed down.""" + last_line = report.split('\n')[-2] + return re.sub(r"\s+", " ", last_line) + + def test_report(self): + out = self.run_command("coverage -x mycode.py") + self.assertEqual(out, 'done\n') + report = self.report_from_command("coverage -r") + + # Name Stmts Miss Cover + # --------------------------------------------------------------------- + # c:/ned/coverage/trunk/test/modules/covmod1 2 0 100% + # c:/ned/coverage/trunk/test/zipmods.zip/covmodzip1 2 0 100% + # mycode 4 0 100% + # --------------------------------------------------------------------- + # TOTAL 8 0 100% + + self.assertNotIn("/coverage/__init__/", report) + self.assertIn("/test/modules/covmod1 ", report) + self.assertIn("/test/zipmods.zip/covmodzip1 ", report) + self.assertIn("mycode ", report) + self.assertEqual(self.last_line_squeezed(report), "TOTAL 8 0 100%") + + def test_report_just_one(self): + # Try reporting just one module + self.run_command("coverage -x mycode.py") + report = self.report_from_command("coverage -r mycode.py") + + # Name Stmts Miss Cover + # ---------------------------- + # mycode 4 0 100% + + self.assertEqual(self.line_count(report), 3) + self.assertNotIn("/coverage/", report) + self.assertNotIn("/test/modules/covmod1 ", report) + self.assertNotIn("/test/zipmods.zip/covmodzip1 ", report) + self.assertIn("mycode ", report) + self.assertEqual(self.last_line_squeezed(report), "mycode 4 0 100%") + + def test_report_omitting(self): + # Try reporting while omitting some modules + prefix = os.path.split(__file__)[0] + self.run_command("coverage -x mycode.py") + report = self.report_from_command("coverage -r -o '%s/*'" % prefix) + + # Name Stmts Miss Cover + # ---------------------------- + # mycode 4 0 100% + + self.assertEqual(self.line_count(report), 3) + self.assertNotIn("/coverage/", report) + self.assertNotIn("/test/modules/covmod1 ", report) + self.assertNotIn("/test/zipmods.zip/covmodzip1 ", report) + self.assertIn("mycode ", report) + self.assertEqual(self.last_line_squeezed(report), "mycode 4 0 100%") + + def test_report_including(self): + # Try reporting while including some modules + self.run_command("coverage run mycode.py") + report = self.report_from_command("coverage report --include=mycode*") + + # Name Stmts Miss Cover + # ---------------------------- + # mycode 4 0 100% + + self.assertEqual(self.line_count(report), 3) + self.assertNotIn("/coverage/", report) + self.assertNotIn("/test/modules/covmod1 ", report) + self.assertNotIn("/test/zipmods.zip/covmodzip1 ", report) + self.assertIn("mycode ", report) + self.assertEqual(self.last_line_squeezed(report), "mycode 4 0 100%") + + def test_report_branches(self): + self.make_file("mybranch.py", """\ + def branch(x): + if x: + print("x") + return x + branch(1) + """) + out = self.run_command("coverage run --branch mybranch.py") + self.assertEqual(out, 'x\n') + report = self.report_from_command("coverage report") + + # Name Stmts Miss Branch BrMiss Cover + # -------------------------------------------- + # mybranch 5 0 2 1 85% + + self.assertEqual(self.line_count(report), 3) + self.assertIn("mybranch ", report) + self.assertEqual(self.last_line_squeezed(report), + "mybranch 5 0 2 1 86%") + + def test_dotpy_not_python(self): + # We run a .py file, and when reporting, we can't parse it as Python. + # We should get an error message in the report. + + self.run_command("coverage run mycode.py") + self.make_file("mycode.py", "This isn't python at all!") + report = self.report_from_command("coverage -r mycode.py") + + # pylint: disable=C0301 + # Name Stmts Miss Cover + # ---------------------------- + # mycode NotPython: Couldn't parse '/tmp/test_cover/63354509363/mycode.py' as Python source: 'invalid syntax' at line 1 + + last = self.last_line_squeezed(report) + # The actual file name varies run to run. + last = re.sub(r"parse '.*mycode.py", "parse 'mycode.py", last) + # The actual error message varies version to version + last = re.sub(r": '.*' at", ": 'error' at", last) + self.assertEqual(last, + "mycode NotPython: " + "Couldn't parse 'mycode.py' as Python source: " + "'error' at line 1" + ) + + def test_dotpy_not_python_ignored(self): + # We run a .py file, and when reporting, we can't parse it as Python, + # but we've said to ignore errors, so there's no error reported. + self.run_command("coverage run mycode.py") + self.make_file("mycode.py", "This isn't python at all!") + report = self.report_from_command("coverage -r -i mycode.py") + + # Name Stmts Miss Cover + # ---------------------------- + + self.assertEqual(self.line_count(report), 2) + + def test_dothtml_not_python(self): + # We run a .html file, and when reporting, we can't parse it as + # Python. Since it wasn't .py, no error is reported. + + # Run an "html" file + self.make_file("mycode.html", "a = 1") + self.run_command("coverage run mycode.html") + # Before reporting, change it to be an HTML file. + self.make_file("mycode.html", "

      This isn't python at all!

      ") + report = self.report_from_command("coverage -r mycode.html") + + # Name Stmts Miss Cover + # ---------------------------- + + self.assertEqual(self.line_count(report), 2) + + def get_report(self, cov): + """Get the report from `cov`, and canonicalize it.""" + repout = StringIO() + cov.report(file=repout, show_missing=False) + report = repout.getvalue().replace('\\', '/') + report = re.sub(r" +", " ", report) + return report + + def test_bug_156_file_not_run_should_be_zero(self): + # https://bitbucket.org/ned/coveragepy/issue/156 + self.make_file("mybranch.py", """\ + def branch(x): + if x: + print("x") + return x + branch(1) + """) + self.make_file("main.py", """\ + print("y") + """) + cov = coverage.coverage(branch=True, source=["."]) + cov.start() + import main # pragma: nested # pylint: disable=F0401,W0612 + cov.stop() # pragma: nested + report = self.get_report(cov).splitlines() + self.assertIn("mybranch 5 5 2 2 0%", report) + + def run_TheCode_and_report_it(self): + """A helper for the next few tests.""" + cov = coverage.coverage() + cov.start() + import TheCode # pragma: nested # pylint: disable=F0401,W0612 + cov.stop() # pragma: nested + return self.get_report(cov) + + def test_bug_203_mixed_case_listed_twice_with_rc(self): + self.make_file("TheCode.py", "a = 1\n") + self.make_file(".coveragerc", "[run]\nsource = .\n") + + report = self.run_TheCode_and_report_it() + + self.assertIn("TheCode", report) + self.assertNotIn("thecode", report) + + def test_bug_203_mixed_case_listed_twice(self): + self.make_file("TheCode.py", "a = 1\n") + + report = self.run_TheCode_and_report_it() + + self.assertIn("TheCode", report) + self.assertNotIn("thecode", report) + + +class SummaryTest2(CoverageTest): + """Another bunch of summary tests.""" + # This class exists because tests naturally clump into classes based on the + # needs of their setUp and tearDown, rather than the product features they + # are testing. There's probably a better way to organize these. + + run_in_temp_dir = False + + def setUp(self): + super(SummaryTest2, self).setUp() + # Parent class saves and restores sys.path, we can just modify it. + this_dir = os.path.dirname(__file__) + sys.path.append(self.nice_file(this_dir, 'modules')) + sys.path.append(self.nice_file(this_dir, 'moremodules')) + + def test_empty_files(self): + # Shows that empty files like __init__.py are listed as having zero + # statements, not one statement. + cov = coverage.coverage() + cov.start() + import usepkgs # pragma: nested # pylint: disable=F0401,W0612 + cov.stop() # pragma: nested + + repout = StringIO() + cov.report(file=repout, show_missing=False) + + report = repout.getvalue().replace('\\', '/') + report = re.sub(r"\s+", " ", report) + self.assertIn("test/modules/pkg1/__init__ 1 0 100%", report) + self.assertIn("test/modules/pkg2/__init__ 0 0 100%", report) + + +class ReportingReturnValue(CoverageTest): + """Tests of reporting functions returning values.""" + + def run_coverage(self): + """Run coverage on doit.py and return the coverage object.""" + self.make_file("doit.py", """\ + a = 1 + b = 2 + c = 3 + d = 4 + if a > 10: + f = 6 + g = 7 + """) + + cov = coverage.coverage() + self.start_import_stop(cov, "doit") + return cov + + def test_report(self): + cov = self.run_coverage() + val = cov.report(include="*/doit.py") + self.assertAlmostEqual(val, 85.7, 1) + + def test_html(self): + cov = self.run_coverage() + val = cov.html_report(include="*/doit.py") + self.assertAlmostEqual(val, 85.7, 1) + + def test_xml(self): + cov = self.run_coverage() + val = cov.xml_report(include="*/doit.py") + self.assertAlmostEqual(val, 85.7, 1) diff --git a/tests/test_templite.py b/tests/test_templite.py new file mode 100644 index 00000000..0435c545 --- /dev/null +++ b/tests/test_templite.py @@ -0,0 +1,204 @@ +"""Tests for coverage.templite.""" + +from coverage.templite import Templite +import unittest + +# pylint: disable=W0612,E1101 +# Disable W0612 (Unused variable) and +# E1101 (Instance of 'foo' has no 'bar' member) + +class AnyOldObject(object): + """Simple testing object. + + Use keyword arguments in the constructor to set attributes on the object. + + """ + def __init__(self, **attrs): + for n, v in attrs.items(): + setattr(self, n, v) + + +class TempliteTest(unittest.TestCase): + """Tests for Templite.""" + + def try_render(self, text, ctx, result): + """Render `text` through `ctx`, and it had better be `result`.""" + self.assertEqual(Templite(text).render(ctx), result) + + def test_passthrough(self): + # Strings without variables are passed through unchanged. + self.assertEqual(Templite("Hello").render(), "Hello") + self.assertEqual( + Templite("Hello, 20% fun time!").render(), + "Hello, 20% fun time!" + ) + + def test_variables(self): + # Variables use {{var}} syntax. + self.try_render("Hello, {{name}}!", {'name':'Ned'}, "Hello, Ned!") + + def test_pipes(self): + # Variables can be filtered with pipes. + data = { + 'name': 'Ned', + 'upper': lambda x: x.upper(), + 'second': lambda x: x[1], + } + self.try_render("Hello, {{name|upper}}!", data, "Hello, NED!") + + # Pipes can be concatenated. + self.try_render("Hello, {{name|upper|second}}!", data, "Hello, E!") + + def test_reusability(self): + # A single Templite can be used more than once with different data. + globs = { + 'upper': lambda x: x.upper(), + 'punct': '!', + } + + template = Templite("This is {{name|upper}}{{punct}}", globs) + self.assertEqual(template.render({'name':'Ned'}), "This is NED!") + self.assertEqual(template.render({'name':'Ben'}), "This is BEN!") + + def test_attribute(self): + # Variables' attributes can be accessed with dots. + obj = AnyOldObject(a="Ay") + self.try_render("{{obj.a}}", locals(), "Ay") + + obj2 = AnyOldObject(obj=obj, b="Bee") + self.try_render("{{obj2.obj.a}} {{obj2.b}}", locals(), "Ay Bee") + + def test_member_function(self): + # Variables' member functions can be used, as long as they are nullary. + class WithMemberFns(AnyOldObject): + """A class to try out member function access.""" + def ditto(self): + """Return twice the .txt attribute.""" + return self.txt + self.txt + obj = WithMemberFns(txt="Once") + self.try_render("{{obj.ditto}}", locals(), "OnceOnce") + + def test_item_access(self): + # Variables' items can be used. + d = {'a':17, 'b':23} + self.try_render("{{d.a}} < {{d.b}}", locals(), "17 < 23") + + def test_loops(self): + # Loops work like in Django. + nums = [1,2,3,4] + self.try_render( + "Look: {% for n in nums %}{{n}}, {% endfor %}done.", + locals(), + "Look: 1, 2, 3, 4, done." + ) + # Loop iterables can be filtered. + def rev(l): + """Return the reverse of `l`.""" + l = l[:] + l.reverse() + return l + + self.try_render( + "Look: {% for n in nums|rev %}{{n}}, {% endfor %}done.", + locals(), + "Look: 4, 3, 2, 1, done." + ) + + def test_empty_loops(self): + self.try_render( + "Empty: {% for n in nums %}{{n}}, {% endfor %}done.", + {'nums':[]}, + "Empty: done." + ) + + def test_multiline_loops(self): + self.try_render( + "Look: \n{% for n in nums %}\n{{n}}, \n{% endfor %}done.", + {'nums':[1,2,3]}, + "Look: \n\n1, \n\n2, \n\n3, \ndone." + ) + + def test_multiple_loops(self): + self.try_render( + "{% for n in nums %}{{n}}{% endfor %} and " + "{% for n in nums %}{{n}}{% endfor %}", + {'nums': [1,2,3]}, + "123 and 123" + ) + + def test_comments(self): + # Single-line comments work: + self.try_render( + "Hello, {# Name goes here: #}{{name}}!", + {'name':'Ned'}, "Hello, Ned!" + ) + # and so do multi-line comments: + self.try_render( + "Hello, {# Name\ngoes\nhere: #}{{name}}!", + {'name':'Ned'}, "Hello, Ned!" + ) + + def test_if(self): + self.try_render( + "Hi, {% if ned %}NED{% endif %}{% if ben %}BEN{% endif %}!", + {'ned': 1, 'ben': 0}, + "Hi, NED!" + ) + self.try_render( + "Hi, {% if ned %}NED{% endif %}{% if ben %}BEN{% endif %}!", + {'ned': 0, 'ben': 1}, + "Hi, BEN!" + ) + self.try_render( + "Hi, {% if ned %}NED{% if ben %}BEN{% endif %}{% endif %}!", + {'ned': 0, 'ben': 0}, + "Hi, !" + ) + self.try_render( + "Hi, {% if ned %}NED{% if ben %}BEN{% endif %}{% endif %}!", + {'ned': 1, 'ben': 0}, + "Hi, NED!" + ) + self.try_render( + "Hi, {% if ned %}NED{% if ben %}BEN{% endif %}{% endif %}!", + {'ned': 1, 'ben': 1}, + "Hi, NEDBEN!" + ) + + def test_loop_if(self): + self.try_render( + "@{% for n in nums %}{% if n %}Z{% endif %}{{n}}{% endfor %}!", + {'nums': [0,1,2]}, + "@0Z1Z2!" + ) + self.try_render( + "X{%if nums%}@{% for n in nums %}{{n}}{% endfor %}{%endif%}!", + {'nums': [0,1,2]}, + "X@012!" + ) + self.try_render( + "X{%if nums%}@{% for n in nums %}{{n}}{% endfor %}{%endif%}!", + {'nums': []}, + "X!" + ) + + def test_nested_loops(self): + self.try_render( + "@{% for n in nums %}" + "{% for a in abc %}{{a}}{{n}}{% endfor %}" + "{% endfor %}!", + {'nums': [0,1,2], 'abc': ['a', 'b', 'c']}, + "@a0b0c0a1b1c1a2b2c2!" + ) + + def test_exception_during_evaluation(self): + # TypeError: Couldn't evaluate {{ foo.bar.baz }}: + # 'NoneType' object is unsubscriptable + self.assertRaises(TypeError, self.try_render, + "Hey {{foo.bar.baz}} there", {'foo': None}, "Hey ??? there" + ) + + def test_bogus_tag_syntax(self): + self.assertRaises(SyntaxError, self.try_render, + "Huh: {% bogus %}!!{% endbogus %}??", {}, "" + ) diff --git a/tests/test_testing.py b/tests/test_testing.py new file mode 100644 index 00000000..c2d1453d --- /dev/null +++ b/tests/test_testing.py @@ -0,0 +1,192 @@ +# -*- coding: utf-8 -*- +"""Tests that our test infrastructure is really working!""" + +import os, sys +from coverage.backward import to_bytes, rpartition +from test.backunittest import TestCase +from test.coveragetest import CoverageTest + +from coverage.backward import set # pylint: disable=W0622 + +class TestingTest(TestCase): + """Tests of helper methods on `backunittest.TestCase`.""" + + run_in_temp_dir = False + + def please_raise(self, exc, msg): + """Raise an exception for testing assertRaisesRegexp.""" + raise exc(msg) + + def please_succeed(self): + """A simple successful method for testing assertRaisesRegexp.""" + return "All is well" + + def test_assert_same_elements(self): + self.assertSameElements(set(), set()) + self.assertSameElements(set([1,2,3]), set([3,1,2])) + self.assertRaises(AssertionError, self.assertSameElements, + set([1,2,3]), set() + ) + self.assertRaises(AssertionError, self.assertSameElements, + set([1,2,3]), set([4,5,6]) + ) + + def test_assert_regexp_matches(self): + self.assertRegexpMatches("hello", "hel*o") + self.assertRegexpMatches("Oh, hello there!", "hel*o") + self.assertRaises(AssertionError, self.assertRegexpMatches, + "hello there", "^hello$" + ) + + def test_assert_multiline_equal(self): + self.assertMultiLineEqual("hello", "hello") + self.assertRaises(AssertionError, self.assertMultiLineEqual, + "hello there", "Hello there" + ) + self.assertRaises(AssertionError, self.assertMultiLineEqual, + "hello\nthere", "hello\nThere" + ) + # With messages also. + self.assertMultiLineEqual("hi", "hi", "it's ok") + self.assertRaisesRegexp( + AssertionError, "my message", + self.assertMultiLineEqual, "xyz", "abc", "my message" + ) + + def test_assert_raises_regexp(self): + # Raising the right error with the right message passes. + self.assertRaisesRegexp( + ZeroDivisionError, "Wow! Zero!", + self.please_raise, ZeroDivisionError, "Wow! Zero!" + ) + # Raising the right error with a match passes. + self.assertRaisesRegexp( + ZeroDivisionError, "Zero", + self.please_raise, ZeroDivisionError, "Wow! Zero!" + ) + # Raising the right error with a mismatch fails. + self.assertRaises(AssertionError, + self.assertRaisesRegexp, ZeroDivisionError, "XYZ", + self.please_raise, ZeroDivisionError, "Wow! Zero!" + ) + # Raising the right error with a mismatch fails. + self.assertRaises(AssertionError, + self.assertRaisesRegexp, ZeroDivisionError, "XYZ", + self.please_raise, ZeroDivisionError, "Wow! Zero!" + ) + # Raising the wrong error raises the error itself. + self.assertRaises(ZeroDivisionError, + self.assertRaisesRegexp, IOError, "Wow! Zero!", + self.please_raise, ZeroDivisionError, "Wow! Zero!" + ) + # Raising no error fails. + self.assertRaises(AssertionError, + self.assertRaisesRegexp, ZeroDivisionError, "XYZ", + self.please_succeed + ) + + def test_assert_true(self): + self.assertTrue(True) + self.assertRaises(AssertionError, self.assertTrue, False) + + def test_assert_false(self): + self.assertFalse(False) + self.assertRaises(AssertionError, self.assertFalse, True) + + def test_assert_in(self): + self.assertIn("abc", "hello abc") + self.assertIn("abc", ["xyz", "abc", "foo"]) + self.assertIn("abc", {'abc': 1, 'xyz': 2}) + self.assertRaises(AssertionError, self.assertIn, "abc", "xyz") + self.assertRaises(AssertionError, self.assertIn, "abc", ["x", "xabc"]) + self.assertRaises(AssertionError, self.assertIn, "abc", {'x':'abc'}) + + def test_assert_not_in(self): + self.assertRaises(AssertionError, self.assertNotIn, "abc", "hello abc") + self.assertRaises(AssertionError, + self.assertNotIn, "abc", ["xyz", "abc", "foo"] + ) + self.assertRaises(AssertionError, + self.assertNotIn, "abc", {'abc': 1, 'xyz': 2} + ) + self.assertNotIn("abc", "xyz") + self.assertNotIn("abc", ["x", "xabc"]) + self.assertNotIn("abc", {'x':'abc'}) + + def test_assert_greater(self): + self.assertGreater(10, 9) + self.assertGreater("xyz", "abc") + self.assertRaises(AssertionError, self.assertGreater, 9, 10) + self.assertRaises(AssertionError, self.assertGreater, 10, 10) + self.assertRaises(AssertionError, self.assertGreater, "abc", "xyz") + self.assertRaises(AssertionError, self.assertGreater, "xyz", "xyz") + + +class CoverageTestTest(CoverageTest): + """Test the methods in `CoverageTest`.""" + + def file_text(self, fname): + """Return the text read from a file.""" + return open(fname, "rb").read().decode('ascii') + + def test_make_file(self): + # A simple file. + self.make_file("fooey.boo", "Hello there") + self.assertEqual(open("fooey.boo").read(), "Hello there") + # A file in a sub-directory + self.make_file("sub/another.txt", "Another") + self.assertEqual(open("sub/another.txt").read(), "Another") + # A second file in that sub-directory + self.make_file("sub/second.txt", "Second") + self.assertEqual(open("sub/second.txt").read(), "Second") + # A deeper directory + self.make_file("sub/deeper/evenmore/third.txt") + self.assertEqual(open("sub/deeper/evenmore/third.txt").read(), "") + + def test_make_file_newline(self): + self.make_file("unix.txt", "Hello\n") + self.assertEqual(self.file_text("unix.txt"), "Hello\n") + self.make_file("dos.txt", "Hello\n", newline="\r\n") + self.assertEqual(self.file_text("dos.txt"), "Hello\r\n") + self.make_file("mac.txt", "Hello\n", newline="\r") + self.assertEqual(self.file_text("mac.txt"), "Hello\r") + + def test_make_file_non_ascii(self): + self.make_file("unicode.txt", "tabblo: «ταБЬℓσ»") + self.assertEqual( + open("unicode.txt", "rb").read(), + to_bytes("tabblo: «ταБЬℓσ»") + ) + + def test_file_exists(self): + self.make_file("whoville.txt", "We are here!") + self.assert_exists("whoville.txt") + self.assert_doesnt_exist("shadow.txt") + self.assertRaises( + AssertionError, self.assert_doesnt_exist, "whoville.txt" + ) + self.assertRaises(AssertionError, self.assert_exists, "shadow.txt") + + def test_sub_python_is_this_python(self): + # Try it with a python command. + os.environ['COV_FOOBAR'] = 'XYZZY' + self.make_file("showme.py", """\ + import os, sys + print(sys.executable) + print(os.__file__) + print(os.environ['COV_FOOBAR']) + """) + out = self.run_command("python showme.py").splitlines() + self.assertEqual(out[0], sys.executable) + self.assertEqual(out[1], os.__file__) + self.assertEqual(out[2], 'XYZZY') + + # Try it with a "coverage debug sys" command. + out = self.run_command("coverage debug sys").splitlines() + # "environment: COV_FOOBAR = XYZZY" or "COV_FOOBAR = XYZZY" + executable = [l for l in out if "executable:" in l][0] + executable = executable.split(":", 1)[1].strip() + self.assertEqual(executable, sys.executable) + environ = [l for l in out if "COV_FOOBAR" in l][0] + _, _, environ = rpartition(environ, ":") + self.assertEqual(environ.strip(), "COV_FOOBAR = XYZZY") diff --git a/tests/test_xml.py b/tests/test_xml.py new file mode 100644 index 00000000..204b5869 --- /dev/null +++ b/tests/test_xml.py @@ -0,0 +1,84 @@ +"""Tests for XML reports from coverage.py.""" + +import os, re +import coverage + +from test.coveragetest import CoverageTest + +class XmlReportTest(CoverageTest): + """Tests of the XML reports from coverage.py.""" + + def run_mycode(self): + """Run mycode.py, so we can report on it.""" + self.make_file("mycode.py", "print('hello')\n") + self.run_command("coverage run mycode.py") + + def test_default_file_placement(self): + self.run_mycode() + self.run_command("coverage xml") + self.assert_exists("coverage.xml") + + def test_argument_affects_xml_placement(self): + self.run_mycode() + self.run_command("coverage xml -o put_it_there.xml") + self.assert_doesnt_exist("coverage.xml") + self.assert_exists("put_it_there.xml") + + def test_config_affects_xml_placement(self): + self.run_mycode() + self.make_file(".coveragerc", "[xml]\noutput = xml.out\n") + self.run_command("coverage xml") + self.assert_doesnt_exist("coverage.xml") + self.assert_exists("xml.out") + + def test_no_data(self): + # https://bitbucket.org/ned/coveragepy/issue/210 + self.run_command("coverage xml") + self.assert_doesnt_exist("coverage.xml") + + def test_no_source(self): + # Written while investigating a bug, might as well keep it. + # https://bitbucket.org/ned/coveragepy/issue/208 + self.make_file("innocuous.py", "a = 4") + cov = coverage.coverage() + self.start_import_stop(cov, "innocuous") + os.remove("innocuous.py") + cov.xml_report(ignore_errors=True) + self.assert_exists("coverage.xml") + + def run_doit(self): + """Construct a simple sub-package.""" + self.make_file("sub/__init__.py") + self.make_file("sub/doit.py", "print('doit!')") + self.make_file("main.py", "import sub.doit") + cov = coverage.coverage() + self.start_import_stop(cov, "main") + return cov + + def test_filename_format_showing_everything(self): + cov = self.run_doit() + cov.xml_report(outfile="-") + xml = self.stdout() + doit_line = re_line(xml, "class.*doit") + self.assertIn('filename="sub/doit.py"', doit_line) + + def test_filename_format_including_filename(self): + cov = self.run_doit() + cov.xml_report(["sub/doit.py"], outfile="-") + xml = self.stdout() + doit_line = re_line(xml, "class.*doit") + self.assertIn('filename="sub/doit.py"', doit_line) + + def test_filename_format_including_module(self): + cov = self.run_doit() + import sub.doit # pylint: disable=F0401 + cov.xml_report([sub.doit], outfile="-") + xml = self.stdout() + doit_line = re_line(xml, "class.*doit") + self.assertIn('filename="sub/doit.py"', doit_line) + + +def re_line(text, pat): + """Return the one line in `text` that matches regex `pat`.""" + lines = [l for l in text.splitlines() if re.search(pat, l)] + return lines[0] diff --git a/tests/try_execfile.py b/tests/try_execfile.py new file mode 100644 index 00000000..9bbabd1a --- /dev/null +++ b/tests/try_execfile.py @@ -0,0 +1,34 @@ +"""Test file for run_python_file.""" + +import os, pprint, sys + +DATA = "xyzzy" + +import __main__ + +def my_function(a): + """A function to force execution of module-level values.""" + return "my_fn(%r)" % a + +FN_VAL = my_function("fooey") + +try: + pkg = __package__ +except NameError: + pkg = "*No __package__*" + +globals_to_check = { + '__name__': __name__, + '__file__': __file__, + '__doc__': __doc__, + '__builtins__.has_open': hasattr(__builtins__, 'open'), + '__builtins__.dir': dir(__builtins__), + '__package__': pkg, + 'DATA': DATA, + 'FN_VAL': FN_VAL, + '__main__.DATA': getattr(__main__, "DATA", "nothing"), + 'argv': sys.argv, + 'path': [os.path.normcase(p) for p in sys.path], +} + +pprint.pprint(globals_to_check) -- cgit v1.2.1