diff --git a/CHANGELOG b/CHANGELOG index d2dc1fad4..0d144a762 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,12 +1,19 @@ 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) + (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. @@ -34,6 +41,8 @@ Changes between 1.0.0b3 and 1.0.0b7 * 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/MANIFEST b/MANIFEST index 2e24a076c..c6f2b9c3d 100644 --- a/MANIFEST +++ b/MANIFEST @@ -1,32 +1,18 @@ -.hgtags CHANGELOG -MANIFEST -doc/announce/release-1.0.0.txt -doc/download.txt -doc/test/funcargs.txt -py/__init__.py -py/io/stdcapture.py -py/io/testing/test_stdcapture.py -py/test/collect.py -py/test/funcargs.py -py/test/plugin/pytest_runner.py -py/test/plugin/pytest_terminal.py -py/test/pycollect.py -py/test/testing/test_funcargs.py -py/test/testing/test_genitems.py -setup.py -.hgignore LICENSE +MANIFEST README.txt _findpy.py doc/announce/release-0.9.0.txt doc/announce/release-0.9.2.txt +doc/announce/release-1.0.0.txt doc/announce/releases.txt doc/bin.txt doc/code.txt doc/confrest.py doc/conftest.py doc/contact.txt +doc/download.txt doc/execnet.txt doc/img/pylib.png doc/index.txt @@ -41,11 +27,19 @@ doc/test/dist.txt doc/test/examples.txt 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 +example/assertion/failure_demo.py +example/assertion/test_failures.py +example/assertion/test_setup_flow_example.py example/execnet/popen_read_multiple.py +example/execnet/svn-sync-repo.py +example/execnet/sysinfo.py +example/funcarg/conftest.py example/funcarg/costlysetup/conftest.py example/funcarg/costlysetup/sub1/test_quick.py example/funcarg/costlysetup/sub2/test_two.py @@ -65,10 +59,8 @@ 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 py/bin/_findpy.py py/bin/_genscripts.py @@ -174,10 +166,12 @@ py/initpkg.py py/io/__init__.py py/io/dupfile.py py/io/fdcapture.py +py/io/stdcapture.py py/io/terminalwriter.py py/io/testing/__init__.py py/io/testing/test_dupfile.py py/io/testing/test_fdcapture.py +py/io/testing/test_stdcapture.py py/io/testing/test_terminalwriter.py py/log/__init__.py py/log/consumer.py @@ -292,6 +286,7 @@ py/rest/testing/test_transform.py py/rest/transform.py py/test/__init__.py py/test/cmdline.py +py/test/collect.py py/test/compat.py py/test/config.py py/test/conftesthandle.py @@ -306,6 +301,7 @@ py/test/dist/testing/test_mypickle.py py/test/dist/testing/test_nodemanage.py py/test/dist/testing/test_txnode.py py/test/dist/txnode.py +py/test/funcargs.py py/test/looponfail/__init__.py py/test/looponfail/remote.py py/test/looponfail/testing/__init__.py @@ -334,11 +330,15 @@ py/test/plugin/pytest_recwarn.py py/test/plugin/pytest_restdoc.py py/test/plugin/pytest_resultdb.py py/test/plugin/pytest_resultlog.py +py/test/plugin/pytest_runner.py +py/test/plugin/pytest_terminal.py 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 py/test/testing/__init__.py py/test/testing/acceptance_test.py @@ -353,6 +353,8 @@ py/test/testing/test_compat.py py/test/testing/test_config.py py/test/testing/test_conftesthandle.py py/test/testing/test_deprecated_api.py +py/test/testing/test_funcargs.py +py/test/testing/test_genitems.py py/test/testing/test_outcome.py py/test/testing/test_parseopt.py py/test/testing/test_pickling.py @@ -360,7 +362,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 @@ -384,3 +385,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/doc/announce/release-1.0.0.txt b/doc/announce/release-1.0.0.txt index 372eaf9aa..bf697a77d 100644 --- a/doc/announce/release-1.0.0.txt +++ b/doc/announce/release-1.0.0.txt @@ -1,34 +1,49 @@ -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: +power to testing with Python. Main news: -* new py.test plugin architecture, some examples: +* improved test architecture, featuring super-simple project + specific or cross-project single-file plugins, e.g: - 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 much more! + and many more! -* funcargs - the new flexible mechanism for managing all your test setup/fixture needs! +* funcargs - bringing new flexibilty and zero-boilerplate to Python testing: + + - 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 -* flexibly distribute tests to multiple computers from the command line 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 +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/execnet.txt b/doc/execnet.txt index 1d1373654..fb7835fec 100644 --- a/doc/execnet.txt +++ b/doc/execnet.txt @@ -238,3 +238,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/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/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 7b8514e38..4792354a0 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 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..c259b9262 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.annotate_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 9b0e91b55..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) @@ -362,6 +361,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..039d45899 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 create 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/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/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/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 b1fc23f28..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() @@ -221,30 +236,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 dd0b80da8..b0fddd36a 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,5 @@ """ -autogenerated by gensetup.py -setup file for 'py' package based on: +py lib / py.test setup.py file, autogenerated by gensetup.py """ import os, sys @@ -145,4 +144,4 @@ def main(): if __name__ == '__main__': main() - + \ No newline at end of file