commit
						8a085c035a
					
				
							
								
								
									
										17
									
								
								CHANGELOG
								
								
								
								
							
							
						
						
									
										17
									
								
								CHANGELOG
								
								
								
								
							|  | @ -1,12 +1,19 @@ | ||||||
| Changes between 1.0.0b7 and 1.0.0b8 | Changes between 1.0.0b7 and 1.0.0b8 | ||||||
| ===================================== | ===================================== | ||||||
| 
 | 
 | ||||||
| * docs: refined funcargs doc, use the term  | * if plugins use "py.test.importorskip" for importing  | ||||||
|   "factory" instead of "provider",  added a new  |   a dependency only a warning will be issued instead  | ||||||
|   talk/tutorial doc page  |   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  | * 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,  | * tweaked doctest output for docstrings in py modules,  | ||||||
|   thanks Radomir.  |   thanks Radomir.  | ||||||
|  | @ -34,6 +41,8 @@ Changes between 1.0.0b3 and 1.0.0b7 | ||||||
| * resolve issue #18, multiprocessing.Manager() and  | * resolve issue #18, multiprocessing.Manager() and  | ||||||
|   redirection clash  |   redirection clash  | ||||||
| 
 | 
 | ||||||
|  | * make __name__ == "__channelexec__" for remote_exec code | ||||||
|  | 
 | ||||||
| Changes between 1.0.0b1 and 1.0.0b3 | Changes between 1.0.0b1 and 1.0.0b3 | ||||||
| ============================================= | ============================================= | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										44
									
								
								MANIFEST
								
								
								
								
							
							
						
						
									
										44
									
								
								MANIFEST
								
								
								
								
							|  | @ -1,32 +1,18 @@ | ||||||
| .hgtags |  | ||||||
| CHANGELOG | 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 | LICENSE | ||||||
|  | MANIFEST | ||||||
| README.txt | README.txt | ||||||
| _findpy.py | _findpy.py | ||||||
| doc/announce/release-0.9.0.txt | doc/announce/release-0.9.0.txt | ||||||
| doc/announce/release-0.9.2.txt | doc/announce/release-0.9.2.txt | ||||||
|  | doc/announce/release-1.0.0.txt | ||||||
| doc/announce/releases.txt | doc/announce/releases.txt | ||||||
| doc/bin.txt | doc/bin.txt | ||||||
| doc/code.txt | doc/code.txt | ||||||
| doc/confrest.py | doc/confrest.py | ||||||
| doc/conftest.py | doc/conftest.py | ||||||
| doc/contact.txt | doc/contact.txt | ||||||
|  | doc/download.txt | ||||||
| doc/execnet.txt | doc/execnet.txt | ||||||
| doc/img/pylib.png | doc/img/pylib.png | ||||||
| doc/index.txt | doc/index.txt | ||||||
|  | @ -41,11 +27,19 @@ doc/test/dist.txt | ||||||
| doc/test/examples.txt | doc/test/examples.txt | ||||||
| doc/test/extend.txt | doc/test/extend.txt | ||||||
| doc/test/features.txt | doc/test/features.txt | ||||||
|  | doc/test/funcargs.txt | ||||||
| doc/test/quickstart.txt | doc/test/quickstart.txt | ||||||
|  | doc/test/talks.txt | ||||||
| doc/test/test.txt | doc/test/test.txt | ||||||
| doc/test/xunit_setup.txt | doc/test/xunit_setup.txt | ||||||
| doc/xml.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/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/conftest.py | ||||||
| example/funcarg/costlysetup/sub1/test_quick.py | example/funcarg/costlysetup/sub1/test_quick.py | ||||||
| example/funcarg/costlysetup/sub2/test_two.py | example/funcarg/costlysetup/sub2/test_two.py | ||||||
|  | @ -65,10 +59,8 @@ example/funcarg/test_simpleprovider.py | ||||||
| example/genhtml.py | example/genhtml.py | ||||||
| example/genhtmlcss.py | example/genhtmlcss.py | ||||||
| example/genxml.py | example/genxml.py | ||||||
| example/pytest/failure_demo.py |  | ||||||
| example/pytest/test_failures.py |  | ||||||
| example/pytest/test_setup_flow_example.py |  | ||||||
| py/LICENSE | py/LICENSE | ||||||
|  | py/__init__.py | ||||||
| py/_com.py | py/_com.py | ||||||
| py/bin/_findpy.py | py/bin/_findpy.py | ||||||
| py/bin/_genscripts.py | py/bin/_genscripts.py | ||||||
|  | @ -174,10 +166,12 @@ py/initpkg.py | ||||||
| py/io/__init__.py | py/io/__init__.py | ||||||
| py/io/dupfile.py | py/io/dupfile.py | ||||||
| py/io/fdcapture.py | py/io/fdcapture.py | ||||||
|  | py/io/stdcapture.py | ||||||
| py/io/terminalwriter.py | py/io/terminalwriter.py | ||||||
| py/io/testing/__init__.py | py/io/testing/__init__.py | ||||||
| py/io/testing/test_dupfile.py | py/io/testing/test_dupfile.py | ||||||
| py/io/testing/test_fdcapture.py | py/io/testing/test_fdcapture.py | ||||||
|  | py/io/testing/test_stdcapture.py | ||||||
| py/io/testing/test_terminalwriter.py | py/io/testing/test_terminalwriter.py | ||||||
| py/log/__init__.py | py/log/__init__.py | ||||||
| py/log/consumer.py | py/log/consumer.py | ||||||
|  | @ -292,6 +286,7 @@ py/rest/testing/test_transform.py | ||||||
| py/rest/transform.py | py/rest/transform.py | ||||||
| py/test/__init__.py | py/test/__init__.py | ||||||
| py/test/cmdline.py | py/test/cmdline.py | ||||||
|  | py/test/collect.py | ||||||
| py/test/compat.py | py/test/compat.py | ||||||
| py/test/config.py | py/test/config.py | ||||||
| py/test/conftesthandle.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_nodemanage.py | ||||||
| py/test/dist/testing/test_txnode.py | py/test/dist/testing/test_txnode.py | ||||||
| py/test/dist/txnode.py | py/test/dist/txnode.py | ||||||
|  | py/test/funcargs.py | ||||||
| py/test/looponfail/__init__.py | py/test/looponfail/__init__.py | ||||||
| py/test/looponfail/remote.py | py/test/looponfail/remote.py | ||||||
| py/test/looponfail/testing/__init__.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_restdoc.py | ||||||
| py/test/plugin/pytest_resultdb.py | py/test/plugin/pytest_resultdb.py | ||||||
| py/test/plugin/pytest_resultlog.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_tmpdir.py | ||||||
| py/test/plugin/pytest_unittest.py | py/test/plugin/pytest_unittest.py | ||||||
| py/test/plugin/pytest_xfail.py | py/test/plugin/pytest_xfail.py | ||||||
| py/test/plugin/test_pytest_runner.py | py/test/plugin/test_pytest_runner.py | ||||||
|  | py/test/plugin/test_pytest_runner_xunit.py | ||||||
| py/test/pluginmanager.py | py/test/pluginmanager.py | ||||||
|  | py/test/pycollect.py | ||||||
| py/test/session.py | py/test/session.py | ||||||
| py/test/testing/__init__.py | py/test/testing/__init__.py | ||||||
| py/test/testing/acceptance_test.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_config.py | ||||||
| py/test/testing/test_conftesthandle.py | py/test/testing/test_conftesthandle.py | ||||||
| py/test/testing/test_deprecated_api.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_outcome.py | ||||||
| py/test/testing/test_parseopt.py | py/test/testing/test_parseopt.py | ||||||
| py/test/testing/test_pickling.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_pycollect.py | ||||||
| py/test/testing/test_recording.py | py/test/testing/test_recording.py | ||||||
| py/test/testing/test_session.py | py/test/testing/test_session.py | ||||||
| py/test/testing/test_setup_functional.py |  | ||||||
| py/test/testing/test_traceback.py | py/test/testing/test_traceback.py | ||||||
| py/test/web/__init__.py | py/test/web/__init__.py | ||||||
| py/test/web/exception.py | py/test/web/exception.py | ||||||
|  | @ -384,3 +385,4 @@ py/xmlobj/testing/test_html.py | ||||||
| py/xmlobj/testing/test_xml.py | py/xmlobj/testing/test_xml.py | ||||||
| py/xmlobj/visit.py | py/xmlobj/visit.py | ||||||
| py/xmlobj/xml.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  | 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_unittest.py: run traditional unittest.py tests  | ||||||
|   pytest_pocoo.py: automatically send tracebacks to pocoo paste service  |   * pytest_xfail.py: mark tests as "expected to fail"  | ||||||
|   pytest_monkeypatch.py: safely patch parts of your environment in a test function |   * pytest_pocoo.py: automatically send tracebacks to pocoo paste service  | ||||||
|   pytest_figleaf.py: generate html coverage reports  |   * pytest_monkeypatch.py: safely patch parts of your environment in a test function | ||||||
|   pytest_resultlog.py: generate buildbot-friendly output  |   * 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:  | See the py.test documentation for more info:  | ||||||
| 
 | 
 | ||||||
|     http://pytest.org |     http://pytest.org | ||||||
| 
 | 
 | ||||||
| The py lib contains the py.test tool and offers its well-tested code  | The py lib also got smaller and focuses on offering much of the  | ||||||
| independently from the testing tool, mainly: | well-tested py.test code in independent namespaces:  | ||||||
| 
 | 
 | ||||||
| * py.execnet: ad-hoc code distribution to SSH, Socket and local sub processes | * 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  | * 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  | 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!)  | 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)) |     socketgw = py.execnet.SocketGateway.new_remote(popengw, ("127.0.0.1", 0)) | ||||||
| 
 | 
 | ||||||
|     print socketgw._rinfo() # print some info about the remote environment |     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()  |     passed, skipped, failed = reprec.countoutcomes()  | ||||||
|     assert passed == 0  |     assert passed == 0  | ||||||
|     assert failed == 20, failed |     assert failed == 20, failed | ||||||
|     colreports = reprec.getnamed("collectionreport") |     colreports = reprec.getreports("pytest_collectreport") | ||||||
|     failed = len([x.failed for x in colreports]) |     failed = len([x.failed for x in colreports]) | ||||||
|     assert failed == 5 |     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 |         from sys import exc_info | ||||||
|         channel, (source, outid, errid) = item  |         channel, (source, outid, errid) = item  | ||||||
|         try: |         try: | ||||||
|             loc = { 'channel' : channel } |             loc = { 'channel' : channel, '__name__': '__channelexec__'} | ||||||
|             self._trace("execution starts:", repr(source)[:50]) |             self._trace("execution starts:", repr(source)[:50]) | ||||||
|             close = self._local_redirect_thread_output(outid, errid)  |             close = self._local_redirect_thread_output(outid, errid)  | ||||||
|             try: |             try: | ||||||
|  |  | ||||||
|  | @ -92,6 +92,11 @@ class BasicRemoteExecution: | ||||||
|     def test_repr_doesnt_crash(self): |     def test_repr_doesnt_crash(self): | ||||||
|         assert isinstance(repr(self), str) |         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): |     def test_correct_setup_no_py(self): | ||||||
|         channel = self.gw.remote_exec(""" |         channel = self.gw.remote_exec(""" | ||||||
|             import sys |             import sys | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| """ Plugin implementing defaults and general options. """  | """ default hooks and general py.test options. """  | ||||||
| 
 | 
 | ||||||
| import py | import py | ||||||
| 
 | 
 | ||||||
|  | @ -115,7 +115,7 @@ def pytest_addoption(parser): | ||||||
| def pytest_configure(config): | def pytest_configure(config): | ||||||
|     fixoptions(config) |     fixoptions(config) | ||||||
|     setsession(config) |     setsession(config) | ||||||
|     loadplugins(config) |     #xxxloadplugins(config) | ||||||
| 
 | 
 | ||||||
| def fixoptions(config): | def fixoptions(config): | ||||||
|     if config.option.numprocesses: |     if config.option.numprocesses: | ||||||
|  | @ -124,7 +124,7 @@ def fixoptions(config): | ||||||
|     if config.option.distload: |     if config.option.distload: | ||||||
|         config.option.dist = "load" |         config.option.dist = "load" | ||||||
| 
 | 
 | ||||||
| def loadplugins(config): | def xxxloadplugins(config): | ||||||
|     for name in config.getvalue("plugin"): |     for name in config.getvalue("plugin"): | ||||||
|         print "importing", name |         print "importing", name | ||||||
|         config.pluginmanager.import_plugin(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 | 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 | import py | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -3,8 +3,7 @@ write and report coverage data using the 'figleaf' module. | ||||||
| """ | """ | ||||||
| import py | import py | ||||||
| 
 | 
 | ||||||
| figleaf = py.test.importorskip("figleaf") | figleaf = py.test.importorskip("figleaf.annotate_html") | ||||||
| import figleaf.annotate_html |  | ||||||
| 
 | 
 | ||||||
| def pytest_addoption(parser): | def pytest_addoption(parser): | ||||||
|     group = parser.addgroup('figleaf options') |     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 | import py | ||||||
| 
 | 
 | ||||||
| def pytest_addoption(parser): | def pytest_addoption(parser): | ||||||
|  |  | ||||||
|  | @ -1,6 +1,5 @@ | ||||||
| """ | """ | ||||||
| 'capsys' and 'capfd' funcargs for capturing stdout/stderror either | 'capsys' and 'capfd' funcargs for capturing stdout/stderror. | ||||||
| by intercepting sys.stdout/stderr or File Descriptors 1/2.  |  | ||||||
| 
 | 
 | ||||||
| Calling the reset() method of the capture funcargs gives  | Calling the reset() method of the capture funcargs gives  | ||||||
| a out/err tuple of strings representing the captured streams.  | a out/err tuple of strings representing the captured streams.  | ||||||
|  |  | ||||||
|  | @ -1,6 +1,5 @@ | ||||||
| """ | """ | ||||||
|     py.test.mark / keyword plugin  |     py.test.mark / keyword plugin  | ||||||
| 
 |  | ||||||
| """ | """ | ||||||
| import py | import py | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,13 +1,13 @@ | ||||||
| """ | """ | ||||||
|     "monkeypatch" funcarg for safely patching objects,  | safely patch object attributes, dicts and environment variables.  | ||||||
|     dictionaries and environment variables during the execution of  |  | ||||||
|     a test.  "monkeypatch" has three helper functions:  |  | ||||||
| 
 | 
 | ||||||
|         monkeypatch.setattr(obj, name, value)  | the "monkeypatch" funcarg has three helper functions:  | ||||||
|         monkeypatch.setitem(obj, name, value)  |  | ||||||
|         monkeypatch.setenv(name, value)  |  | ||||||
| 
 | 
 | ||||||
|     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 | import os | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,6 +1,5 @@ | ||||||
| """ | """ | ||||||
| interactive debugging with a PDB prompt.  | interactive debugging with the Python Debugger. | ||||||
| 
 |  | ||||||
| """ | """ | ||||||
| import py | import py | ||||||
| import pdb, sys, linecache | 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 | 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 | 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 |     recwarn: function argument where one can call recwarn.pop() to get | ||||||
|              the last warning that would have been shown.  |              the last warning that would have been shown.  | ||||||
|  |  | ||||||
|  | @ -1,6 +1,5 @@ | ||||||
| """ | """ | ||||||
| perform ReST specific tests on .txt files, including | perform ReST syntax, local and remote reference tests on .rst/.txt files.  | ||||||
| linkchecks and remote URL checks.  |  | ||||||
| """ | """ | ||||||
| import py | import py | ||||||
| 
 | 
 | ||||||
|  | @ -17,7 +16,7 @@ def pytest_addoption(parser): | ||||||
|            help="force generation of html files.") |            help="force generation of html files.") | ||||||
| 
 | 
 | ||||||
| def pytest_collect_file(path, parent): | def pytest_collect_file(path, parent): | ||||||
|     if path.ext == ".txt": |     if path.ext in (".txt", ".rst"): | ||||||
|         project = getproject(path) |         project = getproject(path) | ||||||
|         if project is not None: |         if project is not None: | ||||||
|             return ReSTFile(path, parent=parent, project=project) |             return ReSTFile(path, parent=parent, project=project) | ||||||
|  | @ -362,6 +361,7 @@ def test_deindent(): | ||||||
| 
 | 
 | ||||||
| class TestApigenLinkRole: | class TestApigenLinkRole: | ||||||
|     disabled = True |     disabled = True | ||||||
|  | 
 | ||||||
|     # these tests are moved here from the former py/doc/conftest.py |     # these tests are moved here from the former py/doc/conftest.py | ||||||
|     def test_resolve_linkrole(self): |     def test_resolve_linkrole(self): | ||||||
|         from py.__.doc.conftest import get_apigen_relpath |         from py.__.doc.conftest import get_apigen_relpath | ||||||
|  |  | ||||||
|  | @ -1,9 +1,5 @@ | ||||||
| """  | """  | ||||||
|     collect and run test items.  | collect and run test items and create reports.  | ||||||
| 
 |  | ||||||
|     * executing test items  |  | ||||||
|     * running collectors  |  | ||||||
|     * and generating report events about it  |  | ||||||
| """ | """ | ||||||
| 
 | 
 | ||||||
| import py | import py | ||||||
|  | @ -53,7 +49,7 @@ def runtestprotocol(item, log=True): | ||||||
|     reports = [rep] |     reports = [rep] | ||||||
|     if rep.passed: |     if rep.passed: | ||||||
|         reports.append(call_and_report(item, "call", log)) |         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 |     return reports | ||||||
| 
 | 
 | ||||||
| def pytest_runtest_setup(item): | def pytest_runtest_setup(item): | ||||||
|  | @ -225,11 +221,14 @@ class SetupState(object): | ||||||
|         colitem = self.stack.pop() |         colitem = self.stack.pop() | ||||||
|         self._teardown_with_finalization(colitem) |         self._teardown_with_finalization(colitem) | ||||||
| 
 | 
 | ||||||
|     def _teardown_with_finalization(self, colitem):  |     def _callfinalizers(self, colitem): | ||||||
|         finalizers = self._finalizers.pop(colitem, None) |         finalizers = self._finalizers.pop(colitem, None) | ||||||
|         while finalizers: |         while finalizers: | ||||||
|             fin = finalizers.pop() |             fin = finalizers.pop() | ||||||
|             fin() |             fin() | ||||||
|  | 
 | ||||||
|  |     def _teardown_with_finalization(self, colitem):  | ||||||
|  |         self._callfinalizers(colitem)  | ||||||
|         if colitem:  |         if colitem:  | ||||||
|             colitem.teardown() |             colitem.teardown() | ||||||
|         for colitem in self._finalizers: |         for colitem in self._finalizers: | ||||||
|  | @ -242,17 +241,19 @@ class SetupState(object): | ||||||
|         assert not self._finalizers |         assert not self._finalizers | ||||||
| 
 | 
 | ||||||
|     def teardown_exact(self, item): |     def teardown_exact(self, item): | ||||||
|         assert self.stack and self.stack[-1] == item |         if item == self.stack[-1]: | ||||||
|         self._pop_and_teardown() |             self._pop_and_teardown() | ||||||
|  |         else: | ||||||
|  |             self._callfinalizers(item) | ||||||
|       |       | ||||||
|     def prepare(self, colitem):  |     def prepare(self, colitem):  | ||||||
|         """ setup objects along the collector chain to the test-method |         """ 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()  |         needed_collectors = colitem.listchain()  | ||||||
|         while self.stack:  |         while self.stack:  | ||||||
|             if self.stack == needed_collectors[:len(self.stack)]:  |             if self.stack == needed_collectors[:len(self.stack)]:  | ||||||
|                 break  |                 break  | ||||||
|             self._pop_and_teardown() |             self._pop_and_teardown() | ||||||
|         for col in needed_collectors[len(self.stack):]:  |         for col in needed_collectors[len(self.stack):]:  | ||||||
|             self.stack.append(col)  |  | ||||||
|             col.setup()  |             col.setup()  | ||||||
|  |             self.stack.append(col)  | ||||||
|  |  | ||||||
|  | @ -1,3 +1,6 @@ | ||||||
|  | """ | ||||||
|  | terminal reporting of the full testing process. | ||||||
|  | """ | ||||||
| import py | import py | ||||||
| import sys | import sys | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -86,7 +86,8 @@ class BaseFunctionalTests: | ||||||
|         #assert rep.skipped.reason == "hello" |         #assert rep.skipped.reason == "hello" | ||||||
|         #assert rep.skipped.location.lineno == 3 |         #assert rep.skipped.location.lineno == 3 | ||||||
|         #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): |     def test_failure_in_setup_function(self, testdir): | ||||||
|         reports = testdir.runitem(""" |         reports = testdir.runitem(""" | ||||||
|  | @ -101,7 +102,7 @@ class BaseFunctionalTests: | ||||||
|         assert not rep.passed  |         assert not rep.passed  | ||||||
|         assert rep.failed  |         assert rep.failed  | ||||||
|         assert rep.when == "setup" |         assert rep.when == "setup" | ||||||
|         assert len(reports) == 1 |         assert len(reports) == 2 | ||||||
| 
 | 
 | ||||||
|     def test_failure_in_teardown_function(self, testdir): |     def test_failure_in_teardown_function(self, testdir): | ||||||
|         reports = testdir.runitem(""" |         reports = testdir.runitem(""" | ||||||
|  | @ -156,7 +157,7 @@ class BaseFunctionalTests: | ||||||
|             def test_func(): |             def test_func(): | ||||||
|                 pass |                 pass | ||||||
|         """) |         """) | ||||||
|         assert len(reports) == 1 |         assert len(reports) == 2 | ||||||
|         rep = reports[0] |         rep = reports[0] | ||||||
|         print rep |         print rep | ||||||
|         assert not rep.skipped  |         assert not rep.skipped  | ||||||
|  |  | ||||||
|  | @ -55,6 +55,7 @@ def test_class_setup(testdir): | ||||||
|     """) |     """) | ||||||
|     reprec.assertoutcome(passed=1+2+1) |     reprec.assertoutcome(passed=1+2+1) | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
| def test_method_setup(testdir): | def test_method_setup(testdir): | ||||||
|     reprec = testdir.inline_runsource(""" |     reprec = testdir.inline_runsource(""" | ||||||
|         class TestSetupMethod: |         class TestSetupMethod: | ||||||
|  | @ -3,6 +3,7 @@ managing loading and interacting with pytest plugins. | ||||||
| """ | """ | ||||||
| import py | import py | ||||||
| from py.__.test.plugin import hookspec | from py.__.test.plugin import hookspec | ||||||
|  | from py.__.test.outcome import Skipped | ||||||
| 
 | 
 | ||||||
| def check_old_use(mod, modname): | def check_old_use(mod, modname): | ||||||
|     clsname = modname[len('pytest_'):].capitalize() + "Plugin"  |     clsname = modname[len('pytest_'):].capitalize() + "Plugin"  | ||||||
|  | @ -96,10 +97,20 @@ class PluginManager(object): | ||||||
|         modname = canonical_importname(spec) |         modname = canonical_importname(spec) | ||||||
|         if modname in self.impname2plugin: |         if modname in self.impname2plugin: | ||||||
|             return |             return | ||||||
|         mod = importplugin(modname) |         try: | ||||||
|         check_old_use(mod, modname)  |             mod = importplugin(modname) | ||||||
|         self.register(mod) |         except KeyboardInterrupt: | ||||||
|         self.consider_module(mod) |             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): |     def _checkplugin(self, plugin): | ||||||
|         # ===================================================== |         # ===================================================== | ||||||
|  | @ -243,3 +254,36 @@ def formatdef(func): | ||||||
|         py.std.inspect.formatargspec(*py.std.inspect.getargspec(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') |         monkeypatch.setitem(os.environ, 'PYTEST_PLUGINS', 'nonexistingmodule') | ||||||
|         py.test.raises(ImportError, "pluginmanager.consider_env()") |         py.test.raises(ImportError, "pluginmanager.consider_env()") | ||||||
| 
 | 
 | ||||||
|     def test_preparse_args(self, monkeypatch): |     def test_preparse_args(self): | ||||||
|         pluginmanager = PluginManager() |         pluginmanager = PluginManager() | ||||||
|         py.test.raises(ImportError, """ |         py.test.raises(ImportError, """ | ||||||
|             pluginmanager.consider_preparse(["xyz", "-p", "hello123"]) |             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): |     def test_consider_env_plugin_instantiation(self, testdir, monkeypatch): | ||||||
|         pluginmanager = PluginManager() |         pluginmanager = PluginManager() | ||||||
|         testdir.syspathinsert() |         testdir.syspathinsert() | ||||||
|  | @ -221,30 +236,6 @@ class TestPytestPluginInteractions: | ||||||
|         assert not pluginmanager.listattr("hello") |         assert not pluginmanager.listattr("hello") | ||||||
|         assert pluginmanager.listattr("x") == [42] |         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(): | def test_collectattr(): | ||||||
|     class A: |     class A: | ||||||
|         def pytest_hello(self): |         def pytest_hello(self): | ||||||
|  |  | ||||||
|  | @ -39,6 +39,7 @@ class TestModule: | ||||||
|         modcol = testdir.getmodulecol("pytest_plugins='xasdlkj',") |         modcol = testdir.getmodulecol("pytest_plugins='xasdlkj',") | ||||||
|         py.test.raises(ImportError, "modcol.obj") |         py.test.raises(ImportError, "modcol.obj") | ||||||
| 
 | 
 | ||||||
|  | class TestDisabled: | ||||||
|     def test_disabled_module(self, testdir): |     def test_disabled_module(self, testdir): | ||||||
|         modcol = testdir.getmodulecol(""" |         modcol = testdir.getmodulecol(""" | ||||||
|             disabled = True |             disabled = True | ||||||
|  | @ -51,7 +52,6 @@ class TestModule: | ||||||
|         assert len(l) == 1 |         assert len(l) == 1 | ||||||
|         py.test.raises(Skipped, "modcol.setup()") |         py.test.raises(Skipped, "modcol.setup()") | ||||||
| 
 | 
 | ||||||
| class TestClass: |  | ||||||
|     def test_disabled_class(self, testdir): |     def test_disabled_class(self, testdir): | ||||||
|         modcol = testdir.getmodulecol(""" |         modcol = testdir.getmodulecol(""" | ||||||
|             class TestClass: |             class TestClass: | ||||||
|  | @ -67,6 +67,15 @@ class TestClass: | ||||||
|         assert len(l) == 1 |         assert len(l) == 1 | ||||||
|         py.test.raises(Skipped, "modcol.setup()") |         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: | class TestGenerator: | ||||||
|     def test_generative_functions(self, testdir):  |     def test_generative_functions(self, testdir):  | ||||||
|         modcol = testdir.getmodulecol(""" |         modcol = testdir.getmodulecol(""" | ||||||
|  |  | ||||||
							
								
								
									
										5
									
								
								setup.py
								
								
								
								
							
							
						
						
									
										5
									
								
								setup.py
								
								
								
								
							|  | @ -1,6 +1,5 @@ | ||||||
| """ | """ | ||||||
| autogenerated by gensetup.py | py lib / py.test setup.py file, autogenerated by gensetup.py | ||||||
| setup file for 'py' package based on: |  | ||||||
|          |          | ||||||
| """ | """ | ||||||
| import os, sys | import os, sys | ||||||
|  | @ -145,4 +144,4 @@ def main(): | ||||||
| 
 | 
 | ||||||
| if __name__ == '__main__': | if __name__ == '__main__': | ||||||
|     main() |     main() | ||||||
|          |          | ||||||
		Loading…
	
		Reference in New Issue