commit
						8a085c035a
					
				
							
								
								
									
										17
									
								
								CHANGELOG
								
								
								
								
							
							
						
						
									
										17
									
								
								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 | ||||
| ============================================= | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										44
									
								
								MANIFEST
								
								
								
								
							
							
						
						
									
										44
									
								
								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 | ||||
|  | @ -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!)  | ||||
| 
 | ||||
|  |  | |||
|  | @ -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 ...  | ||||
|          | ||||
| 
 | ||||
|  |  | |||
|  | @ -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 | ||||
|  | @ -0,0 +1,3 @@ | |||
| import py | ||||
| 
 | ||||
| collect_ignore = 'mysetup', 'mysetup2', 'test_simpleprovider.py', 'parametrize' | ||||
|  | @ -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: | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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) | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| """ | ||||
| automatically collect and execute doctests.  | ||||
| collect and execute doctests from modules and test files.  | ||||
| """ | ||||
| 
 | ||||
| import py | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| """ | ||||
| cleanup gateways that were instantiated during a test function run.  | ||||
| cleanup execnet gateways during test function runs. | ||||
| """ | ||||
| import 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') | ||||
|  |  | |||
|  | @ -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): | ||||
|  |  | |||
|  | @ -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.  | ||||
|  |  | |||
|  | @ -1,6 +1,5 @@ | |||
| """ | ||||
|     py.test.mark / keyword plugin  | ||||
| 
 | ||||
| """ | ||||
| import 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 | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,6 +1,5 @@ | |||
| """ | ||||
| interactive debugging with a PDB prompt.  | ||||
| 
 | ||||
| interactive debugging with the Python Debugger. | ||||
| """ | ||||
| import py | ||||
| import pdb, sys, linecache | ||||
|  |  | |||
|  | @ -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 | ||||
| 
 | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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.  | ||||
|  |  | |||
|  | @ -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 | ||||
|  |  | |||
|  | @ -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)  | ||||
|  |  | |||
|  | @ -1,3 +1,6 @@ | |||
| """ | ||||
| terminal reporting of the full testing process. | ||||
| """ | ||||
| import py | ||||
| import sys | ||||
| 
 | ||||
|  |  | |||
|  | @ -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  | ||||
|  |  | |||
|  | @ -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: | ||||
|  | @ -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 | ||||
|       | ||||
| 
 | ||||
|  |  | |||
|  | @ -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): | ||||
|  |  | |||
|  | @ -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(""" | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue