From 296a660a7391157c9317517e568d576ddb9d8a39 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Fri, 26 Jun 2009 17:48:46 +0200 Subject: [PATCH 1/5] doc refinements introduce '__channelexec__' + docs --HG-- branch : 1.0.x --- CHANGELOG | 2 ++ doc/announce/release-1.0.0.txt | 21 +++++++++++++-------- doc/execnet.txt | 16 ++++++++++++++++ py/__init__.py | 2 +- py/execnet/gateway.py | 2 +- py/execnet/testing/test_gateway.py | 5 +++++ 6 files changed, 38 insertions(+), 10 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index f0a0e9e91..c1154857d 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -15,6 +15,8 @@ Changes between 1.0.0b3 and 1.0.0 * resolve issue #18, multiprocessing.Manager() and redirection clash +* make __name__ == "__channelexec__" for remote_exec code + Changes between 1.0.0b1 and 1.0.0b3 ============================================= diff --git a/doc/announce/release-1.0.0.txt b/doc/announce/release-1.0.0.txt index 372eaf9aa..b2eef241d 100644 --- a/doc/announce/release-1.0.0.txt +++ b/doc/announce/release-1.0.0.txt @@ -1,32 +1,37 @@ -py.test / py lib 1.0.0: distributed testing and dynamic code deployment +py.test / py lib 1.0.0: new test plugins, funcargs and cleanups ============================================================================ Welcome to the 1.0 release bringing new flexibility and power to testing with Python! Main news: -* new py.test plugin architecture, some examples: +* improved architecture, featuring simple single-file plugins, e.g: + pytest_unittest.py: run traditional unittest.py tests pytest_xfail.py: mark tests as "expected to fail" pytest_pocoo.py: automatically send tracebacks to pocoo paste service pytest_monkeypatch.py: safely patch parts of your environment in a test function pytest_figleaf.py: generate html coverage reports pytest_resultlog.py: generate buildbot-friendly output - and much more! + and many more! -* funcargs - the new flexible mechanism for managing all your test setup/fixture needs! +* funcargs - powerful mechanism for all your setup needs -* flexibly distribute tests to multiple computers from the command line +* distributed testing: ad-hoc send and run tests on many platforms + +* remove first round of non-test related code, notably + greenlets and apigen (documentation generation) that + now live on their own See the py.test documentation for more info: http://pytest.org -The py lib contains the py.test tool and offers its well-tested code -independently from the testing tool, mainly: +The py lib also got smaller and focuses on offering much of the +well-tested py.test code in independent namespaces: * py.execnet: ad-hoc code distribution to SSH, Socket and local sub processes -* py.code: support for dynamically running and debugging python code +* py.code: higher-level introspection and dynamic generation of python code * py.path: path abstractions over local and subversion files The whole package works well with Linux, OSX and Win32, on diff --git a/doc/execnet.txt b/doc/execnet.txt index 9a013dff8..baa8b7d41 100644 --- a/doc/execnet.txt +++ b/doc/execnet.txt @@ -233,3 +233,19 @@ socketserver:: socketgw = py.execnet.SocketGateway.new_remote(popengw, ("127.0.0.1", 0)) print socketgw._rinfo() # print some info about the remote environment + + +Sending a module / checking if run through remote_exec +-------------------------------------------------------------- + +You can pass a module object to ``remote_exec`` in which case +its source code will be sent. No dependencies will be transferred +so the module must be self-contained or only use modules that are +installed on the "other" side. Module code can detect if it is +running in a remote_exec situation by checking for the special +``__name__`` attribute like this:: + + if __name__ == '__channelexec__': + # ... call module functions ... + + diff --git a/py/__init__.py b/py/__init__.py index 1d156dacf..840f77681 100644 --- a/py/__init__.py +++ b/py/__init__.py @@ -19,7 +19,7 @@ For questions please check out http://pylib.org/contact.html """ from initpkg import initpkg -version = "1.0.0b5" +version = "1.0.0b6" initpkg(__name__, description = "py.test and pylib: advanced testing tool and networking lib", diff --git a/py/execnet/gateway.py b/py/execnet/gateway.py index 6a23c0d24..2ea35ae91 100644 --- a/py/execnet/gateway.py +++ b/py/execnet/gateway.py @@ -230,7 +230,7 @@ class Gateway(object): from sys import exc_info channel, (source, outid, errid) = item try: - loc = { 'channel' : channel } + loc = { 'channel' : channel, '__name__': '__channelexec__'} self._trace("execution starts:", repr(source)[:50]) close = self._local_redirect_thread_output(outid, errid) try: diff --git a/py/execnet/testing/test_gateway.py b/py/execnet/testing/test_gateway.py index f5bba5b90..750b3c964 100644 --- a/py/execnet/testing/test_gateway.py +++ b/py/execnet/testing/test_gateway.py @@ -92,6 +92,11 @@ class BasicRemoteExecution: def test_repr_doesnt_crash(self): assert isinstance(repr(self), str) + def test_attribute__name__(self): + channel = self.gw.remote_exec("channel.send(__name__)") + name = channel.receive() + assert name == "__channelexec__" + def test_correct_setup_no_py(self): channel = self.gw.remote_exec(""" import sys From 937e51b4ae8196733c80729a09f1a6aa7d973807 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Fri, 26 Jun 2009 18:12:06 +0200 Subject: [PATCH 2/5] improve docs some further, cleaner release announcement --HG-- branch : 1.0.x --- doc/announce/release-1.0.0.txt | 38 +++++++++++++++++++++------------- doc/test/funcargs.txt | 2 +- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/doc/announce/release-1.0.0.txt b/doc/announce/release-1.0.0.txt index b2eef241d..bf697a77d 100644 --- a/doc/announce/release-1.0.0.txt +++ b/doc/announce/release-1.0.0.txt @@ -2,26 +2,32 @@ py.test / py lib 1.0.0: new test plugins, funcargs and cleanups ============================================================================ Welcome to the 1.0 release bringing new flexibility and -power to testing with Python! Main news: +power to testing with Python. Main news: -* improved architecture, featuring simple single-file plugins, e.g: +* improved test architecture, featuring super-simple project + specific or cross-project single-file plugins, e.g: - pytest_unittest.py: run traditional unittest.py tests - pytest_xfail.py: mark tests as "expected to fail" - pytest_pocoo.py: automatically send tracebacks to pocoo paste service - pytest_monkeypatch.py: safely patch parts of your environment in a test function - pytest_figleaf.py: generate html coverage reports - pytest_resultlog.py: generate buildbot-friendly output + * pytest_unittest.py: run traditional unittest.py tests + * pytest_xfail.py: mark tests as "expected to fail" + * pytest_pocoo.py: automatically send tracebacks to pocoo paste service + * pytest_monkeypatch.py: safely patch parts of your environment in a test function + * pytest_figleaf.py: generate html coverage reports + * pytest_resultlog.py: generate buildbot-friendly output - and many more! + and many more! -* funcargs - powerful mechanism for all your setup needs +* funcargs - bringing new flexibilty and zero-boilerplate to Python testing: -* distributed testing: ad-hoc send and run tests on many platforms + - cleanly separated test code and test configuration and test value setup + - ideal for integration and functional tests + - new generative tests -> deprecation of yield-generated tests + +* distributed testing and distributed execution (py.execnet): + + - new unified "TX" URL scheme for specifying remote resources + - new sync/async ways to handle multiple remote processes + - much improved documentation -* remove first round of non-test related code, notably - greenlets and apigen (documentation generation) that - now live on their own See the py.test documentation for more info: @@ -34,6 +40,10 @@ well-tested py.test code in independent namespaces: * py.code: higher-level introspection and dynamic generation of python code * py.path: path abstractions over local and subversion files +Some non-strictly-test related code, notably greenlets/co-routines +and apigen now live on their own and have been removed, also simplifying +the installation procedures. + The whole package works well with Linux, OSX and Win32, on Python 2.3, 2.4, 2.5 and 2.6. (Expect Python3 compatibility soon!) diff --git a/doc/test/funcargs.txt b/doc/test/funcargs.txt index 45cdb137b..187771f0a 100644 --- a/doc/test/funcargs.txt +++ b/doc/test/funcargs.txt @@ -39,7 +39,7 @@ convenient enough to .. _`funcarg provider`: -funcarg providers: setting up test function arguments +funcarg providers: instantiating test function arguments ============================================================== Test functions can specify one ore more arguments ("funcargs") From 88a0714dfac0dea34f16d0a96d9e30ffd0eeb477 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Wed, 8 Jul 2009 16:41:30 +0200 Subject: [PATCH 3/5] * refix handling of partial setup failures * shuffle / consolidate related tests * re-gen setup.py --HG-- branch : 1.0.x --- CHANGELOG | 3 ++- MANIFEST | 9 +++---- py/__init__.py | 2 +- py/test/plugin/pytest_restdoc.py | 1 + py/test/plugin/pytest_runner.py | 23 +++++++++--------- py/test/plugin/test_pytest_runner.py | 7 +++--- .../test_pytest_runner_xunit.py} | 1 + py/test/testing/test_pluginmanager.py | 24 ------------------- py/test/testing/test_pycollect.py | 11 ++++++++- setup.py | 8 +++---- 10 files changed, 40 insertions(+), 49 deletions(-) rename py/test/{testing/test_setup_functional.py => plugin/test_pytest_runner_xunit.py} (99%) diff --git a/CHANGELOG b/CHANGELOG index d2dc1fad4..68f9ba4f6 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -6,7 +6,8 @@ Changes between 1.0.0b7 and 1.0.0b8 talk/tutorial doc page * fixed teardown problem related to partially failing funcarg setups - (thanks MrTopf for reporting) + (thanks MrTopf for reporting), "pytest_runtest_teardown" is now + always invoked even if the "pytest_runtest_setup" failed. * tweaked doctest output for docstrings in py modules, thanks Radomir. diff --git a/MANIFEST b/MANIFEST index 1df6326bc..a0df0384f 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,8 +1,6 @@ -MANIFEST -py/__init__.py -setup.py CHANGELOG LICENSE +MANIFEST README.txt _findpy.py doc/announce/release-0.9.0.txt @@ -31,6 +29,7 @@ doc/test/extend.txt doc/test/features.txt doc/test/funcargs.txt doc/test/quickstart.txt +doc/test/talks.txt doc/test/test.txt doc/test/xunit_setup.txt doc/xml.txt @@ -58,6 +57,7 @@ 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 py/bin/_findpy.py py/bin/_genscripts.py @@ -333,6 +333,7 @@ py/test/plugin/pytest_tmpdir.py py/test/plugin/pytest_unittest.py py/test/plugin/pytest_xfail.py py/test/plugin/test_pytest_runner.py +py/test/plugin/test_pytest_runner_xunit.py py/test/pluginmanager.py py/test/pycollect.py py/test/session.py @@ -358,7 +359,6 @@ py/test/testing/test_pluginmanager.py py/test/testing/test_pycollect.py py/test/testing/test_recording.py py/test/testing/test_session.py -py/test/testing/test_setup_functional.py py/test/testing/test_traceback.py py/test/web/__init__.py py/test/web/exception.py @@ -382,3 +382,4 @@ py/xmlobj/testing/test_html.py py/xmlobj/testing/test_xml.py py/xmlobj/visit.py py/xmlobj/xml.py +setup.py \ No newline at end of file diff --git a/py/__init__.py b/py/__init__.py index d042266d4..f63c95ad4 100644 --- a/py/__init__.py +++ b/py/__init__.py @@ -19,7 +19,7 @@ For questions please check out http://pylib.org/contact.html """ from initpkg import initpkg -version = "1.0.0b7" +version = "1.0.0b8" initpkg(__name__, description = "py.test and pylib: advanced testing tool and networking lib", diff --git a/py/test/plugin/pytest_restdoc.py b/py/test/plugin/pytest_restdoc.py index 9b0e91b55..baaeb6b98 100644 --- a/py/test/plugin/pytest_restdoc.py +++ b/py/test/plugin/pytest_restdoc.py @@ -362,6 +362,7 @@ def test_deindent(): class TestApigenLinkRole: disabled = True + # these tests are moved here from the former py/doc/conftest.py def test_resolve_linkrole(self): from py.__.doc.conftest import get_apigen_relpath diff --git a/py/test/plugin/pytest_runner.py b/py/test/plugin/pytest_runner.py index 5358066c2..fcb16573b 100644 --- a/py/test/plugin/pytest_runner.py +++ b/py/test/plugin/pytest_runner.py @@ -1,9 +1,5 @@ """ - collect and run test items. - - * executing test items - * running collectors - * and generating report events about it +collect and run test items and creating reports. """ import py @@ -53,7 +49,7 @@ def runtestprotocol(item, log=True): reports = [rep] if rep.passed: reports.append(call_and_report(item, "call", log)) - reports.append(call_and_report(item, "teardown", log)) + reports.append(call_and_report(item, "teardown", log)) return reports def pytest_runtest_setup(item): @@ -225,11 +221,14 @@ class SetupState(object): colitem = self.stack.pop() self._teardown_with_finalization(colitem) - def _teardown_with_finalization(self, colitem): + def _callfinalizers(self, colitem): finalizers = self._finalizers.pop(colitem, None) while finalizers: fin = finalizers.pop() fin() + + def _teardown_with_finalization(self, colitem): + self._callfinalizers(colitem) if colitem: colitem.teardown() for colitem in self._finalizers: @@ -242,17 +241,19 @@ class SetupState(object): assert not self._finalizers def teardown_exact(self, item): - assert self.stack and self.stack[-1] == item - self._pop_and_teardown() + if item == self.stack[-1]: + self._pop_and_teardown() + else: + self._callfinalizers(item) def prepare(self, colitem): """ setup objects along the collector chain to the test-method - Teardown any unneccessary previously setup objects.""" + and teardown previously setup objects.""" needed_collectors = colitem.listchain() while self.stack: if self.stack == needed_collectors[:len(self.stack)]: break self._pop_and_teardown() for col in needed_collectors[len(self.stack):]: - self.stack.append(col) col.setup() + self.stack.append(col) diff --git a/py/test/plugin/test_pytest_runner.py b/py/test/plugin/test_pytest_runner.py index 3b82de301..9286cad57 100644 --- a/py/test/plugin/test_pytest_runner.py +++ b/py/test/plugin/test_pytest_runner.py @@ -86,7 +86,8 @@ class BaseFunctionalTests: #assert rep.skipped.reason == "hello" #assert rep.skipped.location.lineno == 3 #assert rep.skipped.location.lineno == 3 - assert len(reports) == 1 + assert len(reports) == 2 + assert reports[1].passed # teardown def test_failure_in_setup_function(self, testdir): reports = testdir.runitem(""" @@ -101,7 +102,7 @@ class BaseFunctionalTests: assert not rep.passed assert rep.failed assert rep.when == "setup" - assert len(reports) == 1 + assert len(reports) == 2 def test_failure_in_teardown_function(self, testdir): reports = testdir.runitem(""" @@ -156,7 +157,7 @@ class BaseFunctionalTests: def test_func(): pass """) - assert len(reports) == 1 + assert len(reports) == 2 rep = reports[0] print rep assert not rep.skipped diff --git a/py/test/testing/test_setup_functional.py b/py/test/plugin/test_pytest_runner_xunit.py similarity index 99% rename from py/test/testing/test_setup_functional.py rename to py/test/plugin/test_pytest_runner_xunit.py index a8d17e45a..4ecf08d5c 100644 --- a/py/test/testing/test_setup_functional.py +++ b/py/test/plugin/test_pytest_runner_xunit.py @@ -55,6 +55,7 @@ def test_class_setup(testdir): """) reprec.assertoutcome(passed=1+2+1) + def test_method_setup(testdir): reprec = testdir.inline_runsource(""" class TestSetupMethod: diff --git a/py/test/testing/test_pluginmanager.py b/py/test/testing/test_pluginmanager.py index b1fc23f28..bec5d3fe9 100644 --- a/py/test/testing/test_pluginmanager.py +++ b/py/test/testing/test_pluginmanager.py @@ -221,30 +221,6 @@ class TestPytestPluginInteractions: assert not pluginmanager.listattr("hello") assert pluginmanager.listattr("x") == [42] - @py.test.mark.xfail # setup call methods - def test_call_setup_participants(self, testdir): - testdir.makepyfile( - conftest=""" - import py - def pytest_method(self, x): - return x+1 - pytest_plugin = "pytest_someplugin", - """ - ) - testdir.makepyfile(pytest_someplugin=""" - def pytest_method(self, x): - return x+1 - """) - modcol = testdir.getmodulecol(""" - def pytest_method(x): - return x+0 - """) - l = [] - call = modcol.config.pluginmanager.setupcall(modcol, "pytest_method", 1) - assert len(call.methods) == 3 - results = call.execute() - assert results == [1,2,2] - def test_collectattr(): class A: def pytest_hello(self): diff --git a/py/test/testing/test_pycollect.py b/py/test/testing/test_pycollect.py index 2a6c44463..e2dc190a8 100644 --- a/py/test/testing/test_pycollect.py +++ b/py/test/testing/test_pycollect.py @@ -39,6 +39,7 @@ class TestModule: modcol = testdir.getmodulecol("pytest_plugins='xasdlkj',") py.test.raises(ImportError, "modcol.obj") +class TestDisabled: def test_disabled_module(self, testdir): modcol = testdir.getmodulecol(""" disabled = True @@ -51,7 +52,6 @@ class TestModule: assert len(l) == 1 py.test.raises(Skipped, "modcol.setup()") -class TestClass: def test_disabled_class(self, testdir): modcol = testdir.getmodulecol(""" class TestClass: @@ -67,6 +67,15 @@ class TestClass: assert len(l) == 1 py.test.raises(Skipped, "modcol.setup()") + def test_disabled_class_functional(self, testdir): + reprec = testdir.inline_runsource(""" + class TestSimpleClassSetup: + disabled = True + def test_classlevel(self): pass + def test_classlevel2(self): pass + """) + reprec.assertoutcome(skipped=2) + class TestGenerator: def test_generative_functions(self, testdir): modcol = testdir.getmodulecol(""" diff --git a/setup.py b/setup.py index 3adf30e07..726a4ea47 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,6 @@ """ -autogenerated by gensetup.py - +py lib / py.test setup.py file, autogenerated by gensetup.py + """ import os, sys @@ -30,7 +30,7 @@ def main(): name='py', description='py.test and pylib: advanced testing tool and networking lib', long_description = long_description, - version='1.0.0b7', + version='1.0.0b8', url='http://pylib.org', license='MIT license', platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'], @@ -144,4 +144,4 @@ def main(): if __name__ == '__main__': main() - + \ No newline at end of file From 8f0a85aee12ce810fa224b5b25bc2412fed92b7a Mon Sep 17 00:00:00 2001 From: holger krekel Date: Wed, 8 Jul 2009 19:18:26 +0200 Subject: [PATCH 4/5] * 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() From 2603a0b76ede575243a009ef2ff3f9587f660012 Mon Sep 17 00:00:00 2001 From: holger krekel Date: Wed, 8 Jul 2009 19:57:45 +0200 Subject: [PATCH 5/5] fix figleaf plugin import --HG-- branch : 1.0.x --- py/test/plugin/pytest_figleaf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/py/test/plugin/pytest_figleaf.py b/py/test/plugin/pytest_figleaf.py index d7b5c7492..c259b9262 100644 --- a/py/test/plugin/pytest_figleaf.py +++ b/py/test/plugin/pytest_figleaf.py @@ -3,7 +3,7 @@ write and report coverage data using the 'figleaf' module. """ import py -figleaf = py.test.importorskip("figleaf.annote_html") +figleaf = py.test.importorskip("figleaf.annotate_html") def pytest_addoption(parser): group = parser.addgroup('figleaf options')