From 8f0a85aee12ce810fa224b5b25bc2412fed92b7a Mon Sep 17 00:00:00 2001 From: holger krekel Date: Wed, 8 Jul 2009 19:18:26 +0200 Subject: [PATCH] * streamlining plugin docstrings * better organisation of example directory, also does not break whole-test run anymore --HG-- branch : 1.0.x --- CHANGELOG | 12 +++-- MANIFEST | 7 +-- example/{pytest => assertion}/failure_demo.py | 0 .../{pytest => assertion}/test_failures.py | 2 +- .../test_setup_flow_example.py | 0 example/funcarg/conftest.py | 3 ++ py/test/plugin/pytest_default.py | 6 +-- py/test/plugin/pytest_doctest.py | 2 +- py/test/plugin/pytest_execnetcleanup.py | 2 +- py/test/plugin/pytest_figleaf.py | 3 +- py/test/plugin/pytest_hooklog.py | 2 +- py/test/plugin/pytest_iocapture.py | 3 +- py/test/plugin/pytest_keyword.py | 1 - py/test/plugin/pytest_monkeypatch.py | 14 ++--- py/test/plugin/pytest_pdb.py | 3 +- py/test/plugin/pytest_pocoo.py | 2 +- py/test/plugin/pytest_pytester.py | 2 +- py/test/plugin/pytest_recwarn.py | 2 +- py/test/plugin/pytest_restdoc.py | 5 +- py/test/plugin/pytest_runner.py | 2 +- py/test/plugin/pytest_terminal.py | 3 ++ py/test/pluginmanager.py | 52 +++++++++++++++++-- py/test/testing/test_pluginmanager.py | 17 +++++- 23 files changed, 106 insertions(+), 39 deletions(-) rename example/{pytest => assertion}/failure_demo.py (100%) rename example/{pytest => assertion}/test_failures.py (86%) rename example/{pytest => assertion}/test_setup_flow_example.py (100%) create mode 100644 example/funcarg/conftest.py diff --git a/CHANGELOG b/CHANGELOG index f25cd8a18..0d144a762 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,9 +1,15 @@ Changes between 1.0.0b7 and 1.0.0b8 ===================================== -* docs: refined funcargs doc, use the term - "factory" instead of "provider", added a new - talk/tutorial doc page +* if plugins use "py.test.importorskip" for importing + a dependency only a warning will be issued instead + of exiting the testing process. + +* docs: + - refined funcargs doc , use the term "factory" instead + of "provider" + - added a new talk/tutorial doc page + - better plugin docstrings * fixed teardown problem related to partially failing funcarg setups (thanks MrTopf for reporting), "pytest_runtest_teardown" is now diff --git a/MANIFEST b/MANIFEST index a0df0384f..ebfbd684a 100644 --- a/MANIFEST +++ b/MANIFEST @@ -33,7 +33,11 @@ doc/test/talks.txt doc/test/test.txt doc/test/xunit_setup.txt doc/xml.txt +example/assertion/failure_demo.py +example/assertion/test_failures.py +example/assertion/test_setup_flow_example.py example/execnet/popen_read_multiple.py +example/funcarg/conftest.py example/funcarg/costlysetup/conftest.py example/funcarg/costlysetup/sub1/test_quick.py example/funcarg/costlysetup/sub2/test_two.py @@ -53,9 +57,6 @@ example/funcarg/test_simpleprovider.py example/genhtml.py example/genhtmlcss.py example/genxml.py -example/pytest/failure_demo.py -example/pytest/test_failures.py -example/pytest/test_setup_flow_example.py py/LICENSE py/__init__.py py/_com.py diff --git a/example/pytest/failure_demo.py b/example/assertion/failure_demo.py similarity index 100% rename from example/pytest/failure_demo.py rename to example/assertion/failure_demo.py diff --git a/example/pytest/test_failures.py b/example/assertion/test_failures.py similarity index 86% rename from example/pytest/test_failures.py rename to example/assertion/test_failures.py index bc56b82c1..b5a05fffb 100644 --- a/example/pytest/test_failures.py +++ b/example/assertion/test_failures.py @@ -9,6 +9,6 @@ def test_failure_demo_fails_properly(testdir): passed, skipped, failed = reprec.countoutcomes() assert passed == 0 assert failed == 20, failed - colreports = reprec.getnamed("collectionreport") + colreports = reprec.getreports("pytest_collectreport") failed = len([x.failed for x in colreports]) assert failed == 5 diff --git a/example/pytest/test_setup_flow_example.py b/example/assertion/test_setup_flow_example.py similarity index 100% rename from example/pytest/test_setup_flow_example.py rename to example/assertion/test_setup_flow_example.py diff --git a/example/funcarg/conftest.py b/example/funcarg/conftest.py new file mode 100644 index 000000000..79336142a --- /dev/null +++ b/example/funcarg/conftest.py @@ -0,0 +1,3 @@ +import py + +collect_ignore = 'mysetup', 'mysetup2', 'test_simpleprovider.py', 'parametrize' diff --git a/py/test/plugin/pytest_default.py b/py/test/plugin/pytest_default.py index d13c7077a..7b9959339 100644 --- a/py/test/plugin/pytest_default.py +++ b/py/test/plugin/pytest_default.py @@ -1,4 +1,4 @@ -""" Plugin implementing defaults and general options. """ +""" default hooks and general py.test options. """ import py @@ -115,7 +115,7 @@ def pytest_addoption(parser): def pytest_configure(config): fixoptions(config) setsession(config) - loadplugins(config) + #xxxloadplugins(config) def fixoptions(config): if config.option.numprocesses: @@ -124,7 +124,7 @@ def fixoptions(config): if config.option.distload: config.option.dist = "load" -def loadplugins(config): +def xxxloadplugins(config): for name in config.getvalue("plugin"): print "importing", name config.pluginmanager.import_plugin(name) diff --git a/py/test/plugin/pytest_doctest.py b/py/test/plugin/pytest_doctest.py index 2e51a4bfe..fc8d75f7e 100644 --- a/py/test/plugin/pytest_doctest.py +++ b/py/test/plugin/pytest_doctest.py @@ -1,5 +1,5 @@ """ -automatically collect and execute doctests. +collect and execute doctests from modules and test files. """ import py diff --git a/py/test/plugin/pytest_execnetcleanup.py b/py/test/plugin/pytest_execnetcleanup.py index 7e8ed0408..184f3e89a 100644 --- a/py/test/plugin/pytest_execnetcleanup.py +++ b/py/test/plugin/pytest_execnetcleanup.py @@ -1,5 +1,5 @@ """ -cleanup gateways that were instantiated during a test function run. +cleanup execnet gateways during test function runs. """ import py diff --git a/py/test/plugin/pytest_figleaf.py b/py/test/plugin/pytest_figleaf.py index 7fc71a194..d7b5c7492 100644 --- a/py/test/plugin/pytest_figleaf.py +++ b/py/test/plugin/pytest_figleaf.py @@ -3,8 +3,7 @@ write and report coverage data using the 'figleaf' module. """ import py -figleaf = py.test.importorskip("figleaf") -import figleaf.annotate_html +figleaf = py.test.importorskip("figleaf.annote_html") def pytest_addoption(parser): group = parser.addgroup('figleaf options') diff --git a/py/test/plugin/pytest_hooklog.py b/py/test/plugin/pytest_hooklog.py index 6befb3c26..c00b39151 100644 --- a/py/test/plugin/pytest_hooklog.py +++ b/py/test/plugin/pytest_hooklog.py @@ -1,4 +1,4 @@ -""" log calling of plugin hooks to a file. """ +""" log invocations of extension hooks to a file. """ import py def pytest_addoption(parser): diff --git a/py/test/plugin/pytest_iocapture.py b/py/test/plugin/pytest_iocapture.py index 7695ac0df..aa64aa599 100644 --- a/py/test/plugin/pytest_iocapture.py +++ b/py/test/plugin/pytest_iocapture.py @@ -1,6 +1,5 @@ """ -'capsys' and 'capfd' funcargs for capturing stdout/stderror either -by intercepting sys.stdout/stderr or File Descriptors 1/2. +'capsys' and 'capfd' funcargs for capturing stdout/stderror. Calling the reset() method of the capture funcargs gives a out/err tuple of strings representing the captured streams. diff --git a/py/test/plugin/pytest_keyword.py b/py/test/plugin/pytest_keyword.py index 290187226..4b326bcc6 100644 --- a/py/test/plugin/pytest_keyword.py +++ b/py/test/plugin/pytest_keyword.py @@ -1,6 +1,5 @@ """ py.test.mark / keyword plugin - """ import py diff --git a/py/test/plugin/pytest_monkeypatch.py b/py/test/plugin/pytest_monkeypatch.py index 9e6936989..b337bb3bf 100644 --- a/py/test/plugin/pytest_monkeypatch.py +++ b/py/test/plugin/pytest_monkeypatch.py @@ -1,13 +1,13 @@ """ - "monkeypatch" funcarg for safely patching objects, - dictionaries and environment variables during the execution of - a test. "monkeypatch" has three helper functions: +safely patch object attributes, dicts and environment variables. - monkeypatch.setattr(obj, name, value) - monkeypatch.setitem(obj, name, value) - monkeypatch.setenv(name, value) +the "monkeypatch" funcarg has three helper functions: - After the test has run modifications will be undone. + monkeypatch.setattr(obj, name, value) + monkeypatch.setitem(obj, name, value) + monkeypatch.setenv(name, value) + +After the test has run modifications will be undone. """ import os diff --git a/py/test/plugin/pytest_pdb.py b/py/test/plugin/pytest_pdb.py index e49ba7fd0..a7266ecbd 100644 --- a/py/test/plugin/pytest_pdb.py +++ b/py/test/plugin/pytest_pdb.py @@ -1,6 +1,5 @@ """ -interactive debugging with a PDB prompt. - +interactive debugging with the Python Debugger. """ import py import pdb, sys, linecache diff --git a/py/test/plugin/pytest_pocoo.py b/py/test/plugin/pytest_pocoo.py index 07aa22964..4f48269c8 100644 --- a/py/test/plugin/pytest_pocoo.py +++ b/py/test/plugin/pytest_pocoo.py @@ -1,5 +1,5 @@ """ -py.test plugin for sending testing failure information to paste.pocoo.org +submit failure information to paste.pocoo.org """ import py diff --git a/py/test/plugin/pytest_pytester.py b/py/test/plugin/pytest_pytester.py index 6f289fade..0c3d77af7 100644 --- a/py/test/plugin/pytest_pytester.py +++ b/py/test/plugin/pytest_pytester.py @@ -1,5 +1,5 @@ """ -funcargs and support code for testing py.test functionality. +funcargs and support code for testing py.test's own functionality. """ import py diff --git a/py/test/plugin/pytest_recwarn.py b/py/test/plugin/pytest_recwarn.py index 913cd7b40..756bce569 100644 --- a/py/test/plugin/pytest_recwarn.py +++ b/py/test/plugin/pytest_recwarn.py @@ -1,5 +1,5 @@ """ -help performing checks for deprecation and other warnings. Provides: +helpers for asserting deprecation and other warnings. recwarn: function argument where one can call recwarn.pop() to get the last warning that would have been shown. diff --git a/py/test/plugin/pytest_restdoc.py b/py/test/plugin/pytest_restdoc.py index baaeb6b98..427ae2dee 100644 --- a/py/test/plugin/pytest_restdoc.py +++ b/py/test/plugin/pytest_restdoc.py @@ -1,6 +1,5 @@ """ -perform ReST specific tests on .txt files, including -linkchecks and remote URL checks. +perform ReST syntax, local and remote reference tests on .rst/.txt files. """ import py @@ -17,7 +16,7 @@ def pytest_addoption(parser): help="force generation of html files.") def pytest_collect_file(path, parent): - if path.ext == ".txt": + if path.ext in (".txt", ".rst"): project = getproject(path) if project is not None: return ReSTFile(path, parent=parent, project=project) diff --git a/py/test/plugin/pytest_runner.py b/py/test/plugin/pytest_runner.py index fcb16573b..039d45899 100644 --- a/py/test/plugin/pytest_runner.py +++ b/py/test/plugin/pytest_runner.py @@ -1,5 +1,5 @@ """ -collect and run test items and creating reports. +collect and run test items and create reports. """ import py diff --git a/py/test/plugin/pytest_terminal.py b/py/test/plugin/pytest_terminal.py index 1133efbbd..fb45c2365 100644 --- a/py/test/plugin/pytest_terminal.py +++ b/py/test/plugin/pytest_terminal.py @@ -1,3 +1,6 @@ +""" +terminal reporting of the full testing process. +""" import py import sys diff --git a/py/test/pluginmanager.py b/py/test/pluginmanager.py index d0c55cbe0..4ab5a4a66 100644 --- a/py/test/pluginmanager.py +++ b/py/test/pluginmanager.py @@ -3,6 +3,7 @@ managing loading and interacting with pytest plugins. """ import py from py.__.test.plugin import hookspec +from py.__.test.outcome import Skipped def check_old_use(mod, modname): clsname = modname[len('pytest_'):].capitalize() + "Plugin" @@ -96,10 +97,20 @@ class PluginManager(object): modname = canonical_importname(spec) if modname in self.impname2plugin: return - mod = importplugin(modname) - check_old_use(mod, modname) - self.register(mod) - self.consider_module(mod) + try: + mod = importplugin(modname) + except KeyboardInterrupt: + raise + except Skipped, e: + self._warn("could not import plugin %r, reason: %r" %( + (modname, e.msg))) + else: + check_old_use(mod, modname) + self.register(mod) + self.consider_module(mod) + + def _warn(self, msg): + print "===WARNING=== %s" % (msg,) def _checkplugin(self, plugin): # ===================================================== @@ -243,3 +254,36 @@ def formatdef(func): py.std.inspect.formatargspec(*py.std.inspect.getargspec(func)) ) +if __name__ == "__main__": + import py.__.test.plugin + basedir = py.path.local(py.__.test.plugin.__file__).dirpath() + name2text = {} + for p in basedir.listdir("pytest_*"): + if p.ext == ".py" or ( + p.check(dir=1) and p.join("__init__.py").check()): + impname = p.purebasename + if impname.find("__") != -1: + continue + try: + plugin = importplugin(impname) + except (ImportError, py.__.test.outcome.Skipped): + name2text[impname] = "IMPORT ERROR" + else: + doc = plugin.__doc__ or "" + doc = doc.strip() + name2text[impname] = doc + + for name in sorted(name2text.keys()): + text = name2text[name] + if name[0] == "_": + continue + print "%-20s %s" % (name, text.split("\n")[0]) + + #text = py.std.textwrap.wrap(name2text[name], + # width = 80, + # initial_indent="%s: " % name, + # replace_whitespace = False) + #for line in text: + # print line + + diff --git a/py/test/testing/test_pluginmanager.py b/py/test/testing/test_pluginmanager.py index bec5d3fe9..38ba3959a 100644 --- a/py/test/testing/test_pluginmanager.py +++ b/py/test/testing/test_pluginmanager.py @@ -7,12 +7,27 @@ class TestBootstrapping: monkeypatch.setitem(os.environ, 'PYTEST_PLUGINS', 'nonexistingmodule') py.test.raises(ImportError, "pluginmanager.consider_env()") - def test_preparse_args(self, monkeypatch): + def test_preparse_args(self): pluginmanager = PluginManager() py.test.raises(ImportError, """ pluginmanager.consider_preparse(["xyz", "-p", "hello123"]) """) + def test_plugin_skip(self, testdir, monkeypatch): + testdir.makepyfile(pytest_skipping1=""" + import py + py.test.skip("hello") + """) + result = testdir.runpytest("-p", "skipping1") + result.stdout.fnmatch_lines([ + "*WARNING*could not import plugin*skipping1*hello*" + ]) + monkeypatch.setenv("PYTEST_PLUGINS", "skipping1") + result = testdir.runpytest() + result.stdout.fnmatch_lines([ + "*WARNING*could not import plugin*skipping1*hello*" + ]) + def test_consider_env_plugin_instantiation(self, testdir, monkeypatch): pluginmanager = PluginManager() testdir.syspathinsert()