* rename "rep" to "report" in reporting hooks
* refine docs * bump version data * improve announcement --HG-- branch : 1.0.x
This commit is contained in:
		
							parent
							
								
									67c4503d1b
								
							
						
					
					
						commit
						8c8617c354
					
				|  | @ -1,3 +1,9 @@ | |||
| Changes between 1.0.0b9 and 1.0.0 | ||||
| ===================================== | ||||
| 
 | ||||
| * more terse reporting try to show filesystem path relatively to current dir  | ||||
| * improve xfail output a bit | ||||
| 
 | ||||
| Changes between 1.0.0b8 and 1.0.0b9 | ||||
| ===================================== | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										2
									
								
								MANIFEST
								
								
								
								
							
							
						
						
									
										2
									
								
								MANIFEST
								
								
								
								
							|  | @ -60,7 +60,9 @@ example/execnet/svn-sync-repo.py | |||
| example/execnet/sysinfo.py | ||||
| example/funcarg/conftest.py | ||||
| example/funcarg/costlysetup/conftest.py | ||||
| example/funcarg/costlysetup/sub1/__init__.py | ||||
| example/funcarg/costlysetup/sub1/test_quick.py | ||||
| example/funcarg/costlysetup/sub2/__init__.py | ||||
| example/funcarg/costlysetup/sub2/test_two.py | ||||
| example/funcarg/mysetup/__init__.py | ||||
| example/funcarg/mysetup/conftest.py | ||||
|  |  | |||
|  | @ -1,54 +1,63 @@ | |||
| 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:  | ||||
| pylib 1.0.0 released: testing-with-python innovations continue | ||||
| -------------------------------------------------------------------- | ||||
| 
 | ||||
| * funcargs - new flexibilty and zero-boilerplate fixtures for Python testing:  | ||||
| Took a few betas but finally i uploaded a `1.0.0 py lib release`_, | ||||
| featuring the mature and powerful py.test tool and "execnet-style" | ||||
| *elastic* distributed programming.  With the new release, there are | ||||
| many new advanced automated testing features - here is a quick summary: | ||||
| 
 | ||||
|   - separate test code, configuration and setup  | ||||
| * funcargs_ - pythonic zero-boilerplate fixtures for Python test functions : | ||||
| 
 | ||||
|   - totally separates test code, test configuration and test setup  | ||||
|   - ideal for integration and functional tests | ||||
|   - more powerful dynamic generation of tests | ||||
|   - allows for flexible and natural test parametrization schemes | ||||
| 
 | ||||
| * new plugin architecture, allowing project-specific and  | ||||
|   cross-project single-file plugins.  Many useful examples | ||||
|   shipped by default: | ||||
| * new `plugin architecture`_, allowing easy-to-write project-specific and cross-project single-file plugins.   The most notable new external plugin is `oejskit`_ which naturally enables **running and reporting of javascript-unittests in real-life browsers**.  | ||||
| 
 | ||||
|   * pytest_unittest.py: run and integrate traditional unittest.py tests  | ||||
|   * pytest_xfail.py: mark tests as "expected to fail" and report separately. | ||||
|   * pytest_pocoo.py: automatically send tracebacks to pocoo paste service  | ||||
|   * pytest_monkeypatch.py: safely monkeypatch from tests | ||||
|   * pytest_figleaf.py: generate html coverage reports  | ||||
|   * pytest_resultlog.py: generate buildbot-friendly reporting output  | ||||
| * many new features done in easy-to-improve `default plugins`_, highlights: | ||||
| 
 | ||||
|   and many more! | ||||
|   * xfail: mark tests as "expected to fail" and report separately. | ||||
|   * pastebin: automatically send tracebacks to pocoo paste service  | ||||
|   * capture: flexibly capture stdout/stderr of subprocesses, per-test ... | ||||
|   * monkeypatch: safely monkeypatch modules/classes from within tests | ||||
|   * unittest: run and integrate traditional unittest.py tests  | ||||
|   * figleaf: generate html coverage reports with the figleaf module | ||||
|   * resultlog: generate buildbot-friendly reporting output  | ||||
|   * ... | ||||
| 
 | ||||
| * distributed testing and distributed execution (py.execnet):  | ||||
| * `distributed testing`_ and `elastic distributed execution`_:  | ||||
| 
 | ||||
|   - new unified "TX" URL scheme for specifying remote resources  | ||||
|   - new sync/async ways to handle multiple remote processes  | ||||
|   - new unified "TX" URL scheme for specifying remote processes  | ||||
|   - new distribution modes "--dist=each" and "--dist=load"  | ||||
|   - new sync/async ways to handle 1:N communication  | ||||
|   - improved documentation  | ||||
| 
 | ||||
| See the py.test and py lib documentation for more info:  | ||||
| The py lib continues to offer most of the functionality used by | ||||
| the testing tool in `independent namespaces`_.   | ||||
| 
 | ||||
| Some non-test related code, notably greenlets/co-routines and | ||||
| api-generation now live as their own projects which simplifies the | ||||
| installation procedure because no C-Extensions are required anymore.  | ||||
| 
 | ||||
| The whole package should work well with Linux, Win32 and OSX, on Python | ||||
| 2.3, 2.4, 2.5 and 2.6.  (Expect Python3 compatibility soon!)  | ||||
| 
 | ||||
| For more info, see the py.test and py lib documentation:  | ||||
| 
 | ||||
|     http://pytest.org | ||||
| 
 | ||||
|     http://pylib.org | ||||
| 
 | ||||
| The py lib now is smaller and focuses more on offering  | ||||
| functionality used by the py.test tool in independent  | ||||
| namespaces:  | ||||
| 
 | ||||
| * py.execnet: elastic code deployment to SSH, Socket and local sub processes | ||||
| * 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!)  | ||||
| 
 | ||||
| best,  | ||||
| have fun,  | ||||
| holger | ||||
| 
 | ||||
| .. _`independent namespaces`: http://pylib.org | ||||
| .. _`funcargs`: http://codespeak.net/py/dist/test/funcargs.html | ||||
| .. _`plugin architecture`: http://codespeak.net/py/dist/test/extend.html | ||||
| .. _`default plugins`: http://codespeak.net/py/dist/test/plugin/index.html | ||||
| .. _`distributed testing`: http://codespeak.net/py/dist/test/dist.html | ||||
| .. _`elastic distributed execution`: http://codespeak.net/py/dist/execnet.html | ||||
| .. _`1.0.0 py lib release`: http://pypi.python.org/pypi/py  | ||||
| .. _`oejskit`: http://codespeak.net/py/dist/test/plugin/oejskit.html | ||||
| 
 | ||||
|  |  | |||
|  | @ -14,6 +14,17 @@ class css: | |||
| class Page(object):  | ||||
|     doctype = ('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"' | ||||
|                ' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n') | ||||
|     googlefragment = """ | ||||
| <script type="text/javascript"> | ||||
| var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www."); | ||||
| document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E")); | ||||
| </script> | ||||
| <script type="text/javascript"> | ||||
| try { | ||||
| var pageTracker = _gat._getTracker("UA-7597274-3"); | ||||
| pageTracker._trackPageview(); | ||||
| } catch(err) {}</script> | ||||
| """ | ||||
| 
 | ||||
|     def __init__(self, project, title, targetpath, stylesheeturl=None, | ||||
|                  type="text/html", encoding="ISO-8859-1"):  | ||||
|  | @ -47,8 +58,10 @@ class Page(object): | |||
|     def fill_menubar(self): | ||||
|         items = [ | ||||
|             self.a_docref("pylib index", "index.html"), | ||||
|             self.a_docref("py.test index", "test/test.html"), | ||||
|             self.a_docref("py.test plugins", "test/plugin/index.html"), | ||||
|             self.a_docref("test doc-index", "test/test.html"), | ||||
|             self.a_docref("test quickstart", "test/quickstart.html"), | ||||
|             self.a_docref("test features", "test/features.html"), | ||||
|             self.a_docref("test plugins", "test/plugin/index.html"), | ||||
|             self.a_docref("py.execnet", "execnet.html"), | ||||
|             #self.a_docref("py.code", "code.html"), | ||||
|             #self.a_apigenref("api", "api/index.html"), | ||||
|  | @ -91,6 +104,7 @@ class Page(object): | |||
| 
 | ||||
|     def unicode(self, doctype=True):  | ||||
|         page = self._root.unicode()  | ||||
|         page = page.replace("</body>", self.googlefragment + "</body>") | ||||
|         if doctype:  | ||||
|             return self.doctype + page  | ||||
|         else:  | ||||
|  |  | |||
|  | @ -27,7 +27,7 @@ Other (minor) support functionality | |||
| `miscellaneous features`_ describes some small but nice py lib features. | ||||
| 
 | ||||
| 
 | ||||
| .. _`PyPI project page`: http://pypi.python.org/pypi?%3Aaction=pkg_edit&name=py | ||||
| .. _`PyPI project page`: http://pypi.python.org/pypi/py/ | ||||
| 
 | ||||
| For the latest Release, see `PyPI project page`_ | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,19 +3,21 @@ | |||
| ========================================================== | ||||
| 
 | ||||
| Since version 1.0 py.test features the "funcarg" mechanism which | ||||
| allows a test function to take arguments which will be independently | ||||
| provided by factory functions.  Factory functions are automatically  | ||||
| discovered and allow to encapsulate all neccessary setup and glue code  | ||||
| for running tests.  Compared to `xUnit style`_ the new mechanism is | ||||
| meant to: | ||||
| allows a test function to take arguments independently provided  | ||||
| by factory functions.  Factory functions allow to encapsulate  | ||||
| all setup and fixture glue code into nicely separated objects | ||||
| and provide a natural way for writing python test functions.   | ||||
| Compared to `xUnit style`_ the new mechanism is meant to: | ||||
| 
 | ||||
| * make test functions easier to write and to read  | ||||
| * isolate test fixture creation to a single place  | ||||
| * bring new flexibility and power to test state management  | ||||
| * enable running of a test function with different values  | ||||
| * naturally extend towards parametrizing test functions | ||||
|   with multiple argument sets  | ||||
|   (superseding `old-style generative tests`_) | ||||
| * to enable creation of helper objects that interact with the execution  | ||||
|   of a test function, see the `blog post about the monkeypatch funcarg`_.  | ||||
| * enable creation of zero-boilerplate test helper objects that  | ||||
|   interact with the execution of a test function, see the  | ||||
|   `blog post about the monkeypatch funcarg`_.  | ||||
| 
 | ||||
| If you find issues or have further suggestions for improving | ||||
| the mechanism you are welcome to checkout `contact possibilities`_ page.  | ||||
|  |  | |||
|  | @ -39,7 +39,7 @@ hook specification sourcecode | |||
|     def pytest_collectstart(collector): | ||||
|         """ collector starts collecting. """ | ||||
|      | ||||
|     def pytest_collectreport(rep): | ||||
|     def pytest_collectreport(report): | ||||
|         """ collector finished collecting. """ | ||||
|      | ||||
|     def pytest_deselected(items): | ||||
|  | @ -89,7 +89,7 @@ hook specification sourcecode | |||
|         """ make ItemTestReport for the given item and call outcome. """  | ||||
|     pytest_runtest_makereport.firstresult = True | ||||
|      | ||||
|     def pytest_runtest_logreport(rep): | ||||
|     def pytest_runtest_logreport(report): | ||||
|         """ process item test report. """  | ||||
|      | ||||
|     # special handling for final teardown - somewhat internal for now | ||||
|  |  | |||
|  | @ -1,33 +1,33 @@ | |||
| .. _`terminal`: terminal.html | ||||
| .. _`pytest_recwarn.py`: http://bitbucket.org/hpk42/py-trunk/raw/4ac3aa2d7ea5f3fdcb5a28d4ca70040d9180ef04/py/test/plugin/pytest_recwarn.py | ||||
| .. _`pytest_recwarn.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_recwarn.py | ||||
| .. _`unittest`: unittest.html | ||||
| .. _`pytest_monkeypatch.py`: http://bitbucket.org/hpk42/py-trunk/raw/4ac3aa2d7ea5f3fdcb5a28d4ca70040d9180ef04/py/test/plugin/pytest_monkeypatch.py | ||||
| .. _`pytest_keyword.py`: http://bitbucket.org/hpk42/py-trunk/raw/4ac3aa2d7ea5f3fdcb5a28d4ca70040d9180ef04/py/test/plugin/pytest_keyword.py | ||||
| .. _`pytest_monkeypatch.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_monkeypatch.py | ||||
| .. _`pytest_keyword.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_keyword.py | ||||
| .. _`pastebin`: pastebin.html | ||||
| .. _`plugins`: index.html | ||||
| .. _`pytest_capture.py`: http://bitbucket.org/hpk42/py-trunk/raw/4ac3aa2d7ea5f3fdcb5a28d4ca70040d9180ef04/py/test/plugin/pytest_capture.py | ||||
| .. _`pytest_doctest.py`: http://bitbucket.org/hpk42/py-trunk/raw/4ac3aa2d7ea5f3fdcb5a28d4ca70040d9180ef04/py/test/plugin/pytest_doctest.py | ||||
| .. _`pytest_capture.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_capture.py | ||||
| .. _`pytest_doctest.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_doctest.py | ||||
| .. _`capture`: capture.html | ||||
| .. _`hooklog`: hooklog.html | ||||
| .. _`pytest_restdoc.py`: http://bitbucket.org/hpk42/py-trunk/raw/4ac3aa2d7ea5f3fdcb5a28d4ca70040d9180ef04/py/test/plugin/pytest_restdoc.py | ||||
| .. _`pytest_hooklog.py`: http://bitbucket.org/hpk42/py-trunk/raw/4ac3aa2d7ea5f3fdcb5a28d4ca70040d9180ef04/py/test/plugin/pytest_hooklog.py | ||||
| .. _`pytest_pastebin.py`: http://bitbucket.org/hpk42/py-trunk/raw/4ac3aa2d7ea5f3fdcb5a28d4ca70040d9180ef04/py/test/plugin/pytest_pastebin.py | ||||
| .. _`pytest_figleaf.py`: http://bitbucket.org/hpk42/py-trunk/raw/4ac3aa2d7ea5f3fdcb5a28d4ca70040d9180ef04/py/test/plugin/pytest_figleaf.py | ||||
| .. _`pytest_restdoc.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_restdoc.py | ||||
| .. _`pytest_hooklog.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_hooklog.py | ||||
| .. _`pytest_pastebin.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_pastebin.py | ||||
| .. _`pytest_figleaf.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_figleaf.py | ||||
| .. _`xfail`: xfail.html | ||||
| .. _`contact`: ../../contact.html | ||||
| .. _`checkout the py.test development version`: ../../download.html#checkout | ||||
| .. _`oejskit`: oejskit.html | ||||
| .. _`pytest_xfail.py`: http://bitbucket.org/hpk42/py-trunk/raw/4ac3aa2d7ea5f3fdcb5a28d4ca70040d9180ef04/py/test/plugin/pytest_xfail.py | ||||
| .. _`pytest_xfail.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_xfail.py | ||||
| .. _`figleaf`: figleaf.html | ||||
| .. _`extend`: ../extend.html | ||||
| .. _`pytest_terminal.py`: http://bitbucket.org/hpk42/py-trunk/raw/4ac3aa2d7ea5f3fdcb5a28d4ca70040d9180ef04/py/test/plugin/pytest_terminal.py | ||||
| .. _`pytest_terminal.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_terminal.py | ||||
| .. _`recwarn`: recwarn.html | ||||
| .. _`pytest_pdb.py`: http://bitbucket.org/hpk42/py-trunk/raw/4ac3aa2d7ea5f3fdcb5a28d4ca70040d9180ef04/py/test/plugin/pytest_pdb.py | ||||
| .. _`pytest_pdb.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_pdb.py | ||||
| .. _`monkeypatch`: monkeypatch.html | ||||
| .. _`resultlog`: resultlog.html | ||||
| .. _`keyword`: keyword.html | ||||
| .. _`restdoc`: restdoc.html | ||||
| .. _`pytest_unittest.py`: http://bitbucket.org/hpk42/py-trunk/raw/4ac3aa2d7ea5f3fdcb5a28d4ca70040d9180ef04/py/test/plugin/pytest_unittest.py | ||||
| .. _`pytest_unittest.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_unittest.py | ||||
| .. _`doctest`: doctest.html | ||||
| .. _`pytest_resultlog.py`: http://bitbucket.org/hpk42/py-trunk/raw/4ac3aa2d7ea5f3fdcb5a28d4ca70040d9180ef04/py/test/plugin/pytest_resultlog.py | ||||
| .. _`pytest_resultlog.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_resultlog.py | ||||
| .. _`pdb`: pdb.html | ||||
|  |  | |||
|  | @ -0,0 +1 @@ | |||
| # | ||||
|  | @ -0,0 +1 @@ | |||
| # | ||||
|  | @ -32,7 +32,7 @@ initpkg(__name__, | |||
|     author_email = "holger at merlinux.eu, py-dev at codespeak.net", | ||||
|     long_description = globals()['__doc__'], | ||||
|     classifiers = [ | ||||
|         "Development Status :: 4 - Beta",  | ||||
|         "Development Status :: 5 - Stable",  | ||||
|         "Intended Audience :: Developers",  | ||||
|         "License :: OSI Approved :: MIT License", | ||||
|         "Operating System :: POSIX", | ||||
|  |  | |||
|  | @ -34,16 +34,16 @@ class LoopState(object): | |||
|         return "<LoopState exitstatus=%r shuttingdown=%r len(colitems)=%d>" % ( | ||||
|             self.exitstatus, self.shuttingdown, len(self.colitems)) | ||||
| 
 | ||||
|     def pytest_runtest_logreport(self, rep): | ||||
|         if rep.item in self.dsession.item2nodes: | ||||
|             if rep.when != "teardown": # otherwise we have already managed it | ||||
|                 self.dsession.removeitem(rep.item, rep.node) | ||||
|         if rep.failed: | ||||
|     def pytest_runtest_logreport(self, report): | ||||
|         if report.item in self.dsession.item2nodes: | ||||
|             if report.when != "teardown": # otherwise we already managed it | ||||
|                 self.dsession.removeitem(report.item, report.node) | ||||
|         if report.failed: | ||||
|             self.testsfailed = True | ||||
| 
 | ||||
|     def pytest_collectreport(self, rep): | ||||
|         if rep.passed: | ||||
|             self.colitems.extend(rep.result) | ||||
|     def pytest_collectreport(self, report): | ||||
|         if report.passed: | ||||
|             self.colitems.extend(report.result) | ||||
| 
 | ||||
|     def pytest_testnodeready(self, node): | ||||
|         self.dsession.addnode(node) | ||||
|  | @ -199,7 +199,7 @@ class DSession(Session): | |||
|             else: | ||||
|                 self.config.hook.pytest_collectstart(collector=next) | ||||
|                 colrep = self.config.hook.pytest_make_collect_report(collector=next) | ||||
|                 self.queueevent("pytest_collectreport", rep=colrep) | ||||
|                 self.queueevent("pytest_collectreport", report=colrep) | ||||
|         if self.config.option.dist == "each": | ||||
|             self.senditems_each(senditems) | ||||
|         else: | ||||
|  | @ -267,7 +267,7 @@ class DSession(Session): | |||
|         info = "!!! Node %r crashed during running of test %r" %(node, item) | ||||
|         rep = runner.ItemTestReport(item=item, excinfo=info, when="???") | ||||
|         rep.node = node | ||||
|         self.config.hook.pytest_runtest_logreport(rep=rep) | ||||
|         self.config.hook.pytest_runtest_logreport(report=rep) | ||||
| 
 | ||||
|     def setup(self): | ||||
|         """ setup any neccessary resources ahead of the test run. """ | ||||
|  |  | |||
|  | @ -1,242 +1,5 @@ | |||
| import py | ||||
| 
 | ||||
| EXPECTTIMEOUT=10.0 | ||||
| 
 | ||||
| class TestGeneralUsage: | ||||
|     def test_config_error(self, testdir): | ||||
|         testdir.makeconftest(""" | ||||
|             def pytest_configure(config): | ||||
|                 raise config.Error("hello") | ||||
|         """) | ||||
|         result = testdir.runpytest(testdir.tmpdir) | ||||
|         assert result.ret != 0 | ||||
|         assert result.stderr.fnmatch_lines([ | ||||
|             '*ERROR: hello' | ||||
|         ]) | ||||
| 
 | ||||
|     def test_config_preparse_plugin_option(self, testdir): | ||||
|         testdir.makepyfile(pytest_xyz=""" | ||||
|             def pytest_addoption(parser): | ||||
|                 parser.addoption("--xyz", dest="xyz", action="store") | ||||
|         """) | ||||
|         testdir.makepyfile(test_one=""" | ||||
|             import py | ||||
|             def test_option(): | ||||
|                 assert py.test.config.option.xyz == "123" | ||||
|         """) | ||||
|         result = testdir.runpytest("-p", "xyz", "--xyz=123") | ||||
|         assert result.ret == 0 | ||||
|         assert result.stdout.fnmatch_lines([ | ||||
|             '*1 passed*', | ||||
|         ]) | ||||
| 
 | ||||
|     def test_basetemp(self, testdir): | ||||
|         mytemp = testdir.tmpdir.mkdir("mytemp") | ||||
|         p = testdir.makepyfile(""" | ||||
|             import py | ||||
|             def test_1():  | ||||
|                 py.test.ensuretemp('xyz') | ||||
|         """) | ||||
|         result = testdir.runpytest(p, '--basetemp=%s' %mytemp) | ||||
|         assert result.ret == 0 | ||||
|         assert mytemp.join('xyz').check(dir=1) | ||||
|                  | ||||
|     def test_assertion_magic(self, testdir): | ||||
|         p = testdir.makepyfile(""" | ||||
|             def test_this(): | ||||
|                 x = 0 | ||||
|                 assert x | ||||
|         """) | ||||
|         result = testdir.runpytest(p) | ||||
|         extra = result.stdout.fnmatch_lines([ | ||||
|             ">       assert x",  | ||||
|             "E       assert 0", | ||||
|         ]) | ||||
|         assert result.ret == 1 | ||||
| 
 | ||||
|     def test_nested_import_error(self, testdir): | ||||
|         p = testdir.makepyfile(""" | ||||
|                 import import_fails | ||||
|                 def test_this(): | ||||
|                     assert import_fails.a == 1 | ||||
|         """) | ||||
|         testdir.makepyfile(import_fails="import does_not_work") | ||||
|         result = testdir.runpytest(p) | ||||
|         extra = result.stdout.fnmatch_lines([ | ||||
|             ">   import import_fails", | ||||
|             "E   ImportError: No module named does_not_work", | ||||
|         ]) | ||||
|         assert result.ret == 1 | ||||
| 
 | ||||
|     def test_skipped_reasons(self, testdir): | ||||
|         testdir.makepyfile( | ||||
|             test_one=""" | ||||
|                 from conftest import doskip | ||||
|                 def setup_function(func): | ||||
|                     doskip() | ||||
|                 def test_func(): | ||||
|                     pass | ||||
|                 class TestClass: | ||||
|                     def test_method(self): | ||||
|                         doskip() | ||||
|            """, | ||||
|            test_two = """ | ||||
|                 from conftest import doskip | ||||
|                 doskip() | ||||
|            """, | ||||
|            conftest = """ | ||||
|                 import py | ||||
|                 def doskip(): | ||||
|                     py.test.skip('test') | ||||
|             """ | ||||
|         ) | ||||
|         result = testdir.runpytest()  | ||||
|         extra = result.stdout.fnmatch_lines([ | ||||
|             "*test_one.py ss", | ||||
|             "*test_two.py S", | ||||
|             "___* skipped test summary *_",  | ||||
|             "*conftest.py:3: *3* Skipped: 'test'",  | ||||
|         ]) | ||||
|         assert result.ret == 0 | ||||
| 
 | ||||
|     def test_deselected(self, testdir): | ||||
|         testpath = testdir.makepyfile(""" | ||||
|                 def test_one(): | ||||
|                     pass | ||||
|                 def test_two(): | ||||
|                     pass | ||||
|                 def test_three(): | ||||
|                     pass | ||||
|            """ | ||||
|         ) | ||||
|         result = testdir.runpytest("-k", "test_two:", testpath) | ||||
|         extra = result.stdout.fnmatch_lines([ | ||||
|             "*test_deselected.py ..",  | ||||
|             "=* 1 test*deselected by 'test_two:'*=",  | ||||
|         ]) | ||||
|         assert result.ret == 0 | ||||
| 
 | ||||
|     def test_no_skip_summary_if_failure(self, testdir): | ||||
|         testdir.makepyfile(""" | ||||
|             import py | ||||
|             def test_ok(): | ||||
|                 pass | ||||
|             def test_fail(): | ||||
|                 assert 0 | ||||
|             def test_skip(): | ||||
|                 py.test.skip("dontshow") | ||||
|         """) | ||||
|         result = testdir.runpytest()  | ||||
|         assert result.stdout.str().find("skip test summary") == -1 | ||||
|         assert result.ret == 1 | ||||
| 
 | ||||
|     def test_passes(self, testdir): | ||||
|         p1 = testdir.makepyfile(""" | ||||
|             def test_passes(): | ||||
|                 pass | ||||
|             class TestClass: | ||||
|                 def test_method(self): | ||||
|                     pass | ||||
|         """) | ||||
|         old = p1.dirpath().chdir() | ||||
|         try: | ||||
|             result = testdir.runpytest() | ||||
|         finally: | ||||
|             old.chdir() | ||||
|         extra = result.stdout.fnmatch_lines([ | ||||
|             "test_passes.py ..",  | ||||
|             "* 2 pass*", | ||||
|         ]) | ||||
|         assert result.ret == 0 | ||||
| 
 | ||||
|     def test_header_trailer_info(self, testdir): | ||||
|         p1 = testdir.makepyfile(""" | ||||
|             def test_passes(): | ||||
|                 pass | ||||
|         """) | ||||
|         result = testdir.runpytest() | ||||
|         verinfo = ".".join(map(str, py.std.sys.version_info[:3])) | ||||
|         extra = result.stdout.fnmatch_lines([ | ||||
|             "*===== test session starts ====*", | ||||
|             "python: platform %s -- Python %s*" %( | ||||
|                     py.std.sys.platform, verinfo), # , py.std.sys.executable), | ||||
|             "*test_header_trailer_info.py .", | ||||
|             "=* 1 passed in *.[0-9][0-9] seconds *=",  | ||||
|         ]) | ||||
| 
 | ||||
|     def test_traceback_failure(self, testdir): | ||||
|         p1 = testdir.makepyfile(""" | ||||
|             def g(): | ||||
|                 return 2 | ||||
|             def f(x): | ||||
|                 assert x == g() | ||||
|             def test_onefails(): | ||||
|                 f(3) | ||||
|         """) | ||||
|         result = testdir.runpytest(p1) | ||||
|         result.stdout.fnmatch_lines([ | ||||
|             "*test_traceback_failure.py F",  | ||||
|             "====* FAILURES *====", | ||||
|             "____*____",  | ||||
|             "", | ||||
|             "    def test_onefails():", | ||||
|             ">       f(3)", | ||||
|             "", | ||||
|             "*test_*.py:6: ", | ||||
|             "_ _ _ *", | ||||
|             #"", | ||||
|             "    def f(x):", | ||||
|             ">       assert x == g()", | ||||
|             "E       assert 3 == 2", | ||||
|             "E        +  where 2 = g()", | ||||
|             "", | ||||
|             "*test_traceback_failure.py:4: AssertionError" | ||||
|         ]) | ||||
| 
 | ||||
| 
 | ||||
|     def test_showlocals(self, testdir):  | ||||
|         p1 = testdir.makepyfile(""" | ||||
|             def test_showlocals(): | ||||
|                 x = 3 | ||||
|                 y = "x" * 5000  | ||||
|                 assert 0 | ||||
|         """) | ||||
|         result = testdir.runpytest(p1, '-l') | ||||
|         result.stdout.fnmatch_lines([ | ||||
|             #"_ _ * Locals *",  | ||||
|             "x* = 3", | ||||
|             "y* = 'xxxxxx*" | ||||
|         ]) | ||||
| 
 | ||||
|     def test_verbose_reporting(self, testdir): | ||||
|         p1 = testdir.makepyfile(""" | ||||
|             import py | ||||
|             def test_fail(): | ||||
|                 raise ValueError() | ||||
|             def test_pass(): | ||||
|                 pass | ||||
|             class TestClass: | ||||
|                 def test_skip(self): | ||||
|                     py.test.skip("hello") | ||||
|             def test_gen(): | ||||
|                 def check(x): | ||||
|                     assert x == 1 | ||||
|                 yield check, 0 | ||||
|         """) | ||||
|         result = testdir.runpytest(p1, '-v') | ||||
|         result.stdout.fnmatch_lines([ | ||||
|             "*test_verbose_reporting.py:2: test_fail*FAIL*",  | ||||
|             "*test_verbose_reporting.py:4: test_pass*PASS*", | ||||
|             "*test_verbose_reporting.py:7: TestClass.test_skip*SKIP*", | ||||
|             "*test_verbose_reporting.py:10: test_gen*FAIL*", | ||||
|         ]) | ||||
|         assert result.ret == 1 | ||||
|         result = testdir.runpytest(p1, '-v', '-n 1') | ||||
|         result.stdout.fnmatch_lines([ | ||||
|             "*FAIL*test_verbose_reporting.py:2: test_fail*",  | ||||
|         ]) | ||||
|         assert result.ret == 1 | ||||
| 
 | ||||
| class TestDistribution: | ||||
|     def test_dist_conftest_options(self, testdir): | ||||
|         p1 = testdir.tmpdir.ensure("dir", 'p1.py') | ||||
|  | @ -383,40 +146,3 @@ class TestDistribution: | |||
|         result.stdout.fnmatch_lines(["2...4"]) | ||||
|         result.stdout.fnmatch_lines(["2...5"]) | ||||
| 
 | ||||
| 
 | ||||
| class TestInteractive: | ||||
|     def test_simple_looponfail_interaction(self, testdir): | ||||
|         p1 = testdir.makepyfile(""" | ||||
|             def test_1(): | ||||
|                 assert 1 == 0  | ||||
|         """) | ||||
|         p1.setmtime(p1.mtime() - 50.0)   | ||||
|         child = testdir.spawn_pytest("--looponfail %s" % p1) | ||||
|         child.expect("assert 1 == 0") | ||||
|         child.expect("test_simple_looponfail_interaction.py:") | ||||
|         child.expect("1 failed") | ||||
|         child.expect("waiting for changes") | ||||
|         p1.write(py.code.Source(""" | ||||
|             def test_1(): | ||||
|                 assert 1 == 1 | ||||
|         """)) | ||||
|         child.expect("MODIFIED.*test_simple_looponfail_interaction.py", timeout=4.0) | ||||
|         child.expect("1 passed", timeout=5.0) | ||||
|         child.kill(15) | ||||
|         | ||||
| class TestKeyboardInterrupt:  | ||||
|     def test_raised_in_testfunction(self, testdir): | ||||
|         p1 = testdir.makepyfile(""" | ||||
|             import py | ||||
|             def test_fail(): | ||||
|                 raise ValueError() | ||||
|             def test_inter(): | ||||
|                 raise KeyboardInterrupt() | ||||
|         """) | ||||
|         result = testdir.runpytest(p1) | ||||
|         result.stdout.fnmatch_lines([ | ||||
|             #"*test_inter() INTERRUPTED", | ||||
|             "*KEYBOARD INTERRUPT*", | ||||
|             "*1 failed*",  | ||||
|         ]) | ||||
| 
 | ||||
|  |  | |||
|  | @ -81,8 +81,8 @@ class TestDSession: | |||
|         session.triggertesting([modcol]) | ||||
|         name, args, kwargs = session.queue.get(block=False) | ||||
|         assert name == 'pytest_collectreport' | ||||
|         rep = kwargs['rep']   | ||||
|         assert len(rep.result) == 1 | ||||
|         report = kwargs['report']   | ||||
|         assert len(report.result) == 1 | ||||
| 
 | ||||
|     def test_triggertesting_item(self, testdir): | ||||
|         item = testdir.getitem("def test_func(): pass") | ||||
|  | @ -134,7 +134,7 @@ class TestDSession: | |||
|         session.queueevent(None) | ||||
|         session.loop_once(loopstate) | ||||
|         assert node.sent == [[item]] | ||||
|         session.queueevent("pytest_runtest_logreport", rep=run(item, node)) | ||||
|         session.queueevent("pytest_runtest_logreport", report=run(item, node)) | ||||
|         session.loop_once(loopstate) | ||||
|         assert loopstate.shuttingdown  | ||||
|         assert not loopstate.testsfailed  | ||||
|  | @ -182,7 +182,7 @@ class TestDSession: | |||
|             item = item1 | ||||
|             node = nodes[0] | ||||
|             when = "call" | ||||
|         session.queueevent("pytest_runtest_logreport", rep=rep) | ||||
|         session.queueevent("pytest_runtest_logreport", report=rep) | ||||
|         reprec = testdir.getreportrecorder(session) | ||||
|         print session.item2nodes | ||||
|         loopstate = session._initloopstate([]) | ||||
|  | @ -190,7 +190,7 @@ class TestDSession: | |||
|         session.loop_once(loopstate) | ||||
|         assert len(session.item2nodes[item1]) == 1 | ||||
|         rep.when = "teardown" | ||||
|         session.queueevent("pytest_runtest_logreport", rep=rep) | ||||
|         session.queueevent("pytest_runtest_logreport", report=rep) | ||||
|         session.loop_once(loopstate) | ||||
|         assert len(session.item2nodes[item1]) == 1 | ||||
| 
 | ||||
|  | @ -249,7 +249,7 @@ class TestDSession: | |||
| 
 | ||||
|         assert node.sent == [[item]] | ||||
|         ev = run(item, node, excinfo=excinfo)  | ||||
|         session.queueevent("pytest_runtest_logreport", rep=ev) | ||||
|         session.queueevent("pytest_runtest_logreport", report=ev) | ||||
|         session.loop_once(loopstate) | ||||
|         assert loopstate.shuttingdown   | ||||
|         session.queueevent("pytest_testnodedown", node=node, error=None) | ||||
|  | @ -286,8 +286,8 @@ class TestDSession: | |||
|         # run tests ourselves and produce reports  | ||||
|         ev1 = run(items[0], node, "fail") | ||||
|         ev2 = run(items[1], node, None) | ||||
|         session.queueevent("pytest_runtest_logreport", rep=ev1) # a failing one | ||||
|         session.queueevent("pytest_runtest_logreport", rep=ev2) | ||||
|         session.queueevent("pytest_runtest_logreport", report=ev1) # a failing one | ||||
|         session.queueevent("pytest_runtest_logreport", report=ev2) | ||||
|         # now call the loop | ||||
|         loopstate = session._initloopstate(items) | ||||
|         session.loop_once(loopstate) | ||||
|  | @ -302,7 +302,7 @@ class TestDSession: | |||
|         loopstate = session._initloopstate([]) | ||||
|         loopstate.shuttingdown = True | ||||
|         reprec = testdir.getreportrecorder(session) | ||||
|         session.queueevent("pytest_runtest_logreport", rep=run(item, node)) | ||||
|         session.queueevent("pytest_runtest_logreport", report=run(item, node)) | ||||
|         session.loop_once(loopstate) | ||||
|         assert not reprec.getcalls("pytest_testnodedown") | ||||
|         session.queueevent("pytest_testnodedown", node=node, error=None) | ||||
|  | @ -343,7 +343,7 @@ class TestDSession: | |||
|         node = MockNode() | ||||
|         session.addnode(node) | ||||
|         session.senditems_load([item]) | ||||
|         session.queueevent("pytest_runtest_logreport", rep=run(item, node)) | ||||
|         session.queueevent("pytest_runtest_logreport", report=run(item, node)) | ||||
|         loopstate = session._initloopstate([]) | ||||
|         session.loop_once(loopstate) | ||||
|         assert node._shutdown is True | ||||
|  | @ -369,10 +369,10 @@ class TestDSession: | |||
|         session.senditems_load([item1]) | ||||
|         # node2pending will become empty when the loop sees the report  | ||||
|         rep = run(item1, node) | ||||
|         session.queueevent("pytest_runtest_logreport", rep=run(item1, node))  | ||||
|         session.queueevent("pytest_runtest_logreport", report=run(item1, node))  | ||||
| 
 | ||||
|         # but we have a collection pending | ||||
|         session.queueevent("pytest_collectreport", rep=colreport)  | ||||
|         session.queueevent("pytest_collectreport", report=colreport)  | ||||
| 
 | ||||
|         loopstate = session._initloopstate([]) | ||||
|         session.loop_once(loopstate) | ||||
|  | @ -396,11 +396,11 @@ class TestDSession: | |||
|         dsession = DSession(config) | ||||
|         hookrecorder = testdir.getreportrecorder(config).hookrecorder | ||||
|         dsession.main([config.getfsnode(p1)]) | ||||
|         rep = hookrecorder.popcall("pytest_runtest_logreport").rep  | ||||
|         rep = hookrecorder.popcall("pytest_runtest_logreport").report | ||||
|         assert rep.passed | ||||
|         rep = hookrecorder.popcall("pytest_runtest_logreport").rep | ||||
|         rep = hookrecorder.popcall("pytest_runtest_logreport").report | ||||
|         assert rep.skipped | ||||
|         rep = hookrecorder.popcall("pytest_runtest_logreport").rep | ||||
|         rep = hookrecorder.popcall("pytest_runtest_logreport").report | ||||
|         assert rep.failed | ||||
|         # see that the node is really down  | ||||
|         node = hookrecorder.popcall("pytest_testnodedown").node | ||||
|  |  | |||
|  | @ -115,7 +115,7 @@ class TestMasterSlaveConnection: | |||
|         node = mysetup.makenode(item.config) | ||||
|         node.send(item) | ||||
|         kwargs = mysetup.geteventargs("pytest_runtest_logreport") | ||||
|         rep = kwargs['rep']  | ||||
|         rep = kwargs['report']  | ||||
|         assert rep.passed  | ||||
|         print rep | ||||
|         assert rep.item == item | ||||
|  | @ -135,10 +135,10 @@ class TestMasterSlaveConnection: | |||
|             node.send(item) | ||||
|         for outcome in "passed failed skipped".split(): | ||||
|             kwargs = mysetup.geteventargs("pytest_runtest_logreport") | ||||
|             rep = kwargs['rep'] | ||||
|             assert getattr(rep, outcome)  | ||||
|             report = kwargs['report'] | ||||
|             assert getattr(report, outcome)  | ||||
| 
 | ||||
|         node.sendlist(items) | ||||
|         for outcome in "passed failed skipped".split(): | ||||
|             rep = mysetup.geteventargs("pytest_runtest_logreport")['rep'] | ||||
|             rep = mysetup.geteventargs("pytest_runtest_logreport")['report'] | ||||
|             assert getattr(rep, outcome)  | ||||
|  |  | |||
|  | @ -56,9 +56,9 @@ class TXNode(object): | |||
|                 self._down = True | ||||
|                 self.notify("pytest_testnodedown", error=None, node=self) | ||||
|             elif eventname == "pytest_runtest_logreport": | ||||
|                 rep = kwargs['rep'] | ||||
|                 rep = kwargs['report'] | ||||
|                 rep.node = self | ||||
|                 self.notify("pytest_runtest_logreport", rep=rep) | ||||
|                 self.notify("pytest_runtest_logreport", report=rep) | ||||
|             else: | ||||
|                 self.notify(eventname, *args, **kwargs) | ||||
|         except KeyboardInterrupt:  | ||||
|  | @ -110,8 +110,8 @@ class SlaveNode(object): | |||
|     def sendevent(self, eventname, *args, **kwargs): | ||||
|         self.channel.send((eventname, args, kwargs)) | ||||
| 
 | ||||
|     def pytest_runtest_logreport(self, rep): | ||||
|         self.sendevent("pytest_runtest_logreport", rep=rep) | ||||
|     def pytest_runtest_logreport(self, report): | ||||
|         self.sendevent("pytest_runtest_logreport", report=report) | ||||
| 
 | ||||
|     def run(self): | ||||
|         channel = self.channel | ||||
|  |  | |||
|  | @ -137,9 +137,9 @@ def slave_runsession(channel, config, fullwidth, hasmarkup): | |||
|     session.shouldclose = channel.isclosed  | ||||
|     | ||||
|     class Failures(list): | ||||
|         def pytest_runtest_logreport(self, rep): | ||||
|             if rep.failed: | ||||
|                 self.append(rep) | ||||
|         def pytest_runtest_logreport(self, report): | ||||
|             if report.failed: | ||||
|                 self.append(report) | ||||
|         pytest_collectreport = pytest_runtest_logreport | ||||
|          | ||||
|     failreports = Failures() | ||||
|  |  | |||
|  | @ -33,7 +33,7 @@ def pytest_collect_file(path, parent): | |||
| def pytest_collectstart(collector): | ||||
|     """ collector starts collecting. """ | ||||
| 
 | ||||
| def pytest_collectreport(rep): | ||||
| def pytest_collectreport(report): | ||||
|     """ collector finished collecting. """ | ||||
| 
 | ||||
| def pytest_deselected(items): | ||||
|  | @ -83,7 +83,7 @@ def pytest_runtest_makereport(item, call): | |||
|     """ make ItemTestReport for the given item and call outcome. """  | ||||
| pytest_runtest_makereport.firstresult = True | ||||
| 
 | ||||
| def pytest_runtest_logreport(rep): | ||||
| def pytest_runtest_logreport(report): | ||||
|     """ process item test report. """  | ||||
| 
 | ||||
| # special handling for final teardown - somewhat internal for now | ||||
|  |  | |||
|  | @ -132,8 +132,8 @@ class TestDoctests: | |||
|         """) | ||||
|         reprec = testdir.inline_run(p) | ||||
|         call = reprec.getcall("pytest_runtest_logreport") | ||||
|         assert call.rep.failed | ||||
|         assert call.rep.longrepr  | ||||
|         assert call.report.failed | ||||
|         assert call.report.longrepr  | ||||
|         # XXX  | ||||
|         #testitem, = items | ||||
|         #excinfo = py.test.raises(Failed, "testitem.runtest()") | ||||
|  |  | |||
|  | @ -341,7 +341,7 @@ class ReportRecorder(object): | |||
|     # functionality for test reports  | ||||
| 
 | ||||
|     def getreports(self, names="pytest_runtest_logreport pytest_collectreport"): | ||||
|         return [x.rep for x in self.getcalls(names)] | ||||
|         return [x.report for x in self.getcalls(names)] | ||||
| 
 | ||||
|     def matchreport(self, inamepart="", names="pytest_runtest_logreport pytest_collectreport"): | ||||
|         """ return a testreport whose dotted import path matches """ | ||||
|  | @ -406,7 +406,7 @@ def test_reportrecorder(testdir): | |||
|         skipped = False | ||||
|         when = "call"  | ||||
| 
 | ||||
|     recorder.hook.pytest_runtest_logreport(rep=rep) | ||||
|     recorder.hook.pytest_runtest_logreport(report=rep) | ||||
|     failures = recorder.getfailures() | ||||
|     assert failures == [rep] | ||||
|     failures = recorder.getfailures() | ||||
|  | @ -420,14 +420,14 @@ def test_reportrecorder(testdir): | |||
|         when = "call"  | ||||
|     rep.passed = False | ||||
|     rep.skipped = True | ||||
|     recorder.hook.pytest_runtest_logreport(rep=rep) | ||||
|     recorder.hook.pytest_runtest_logreport(report=rep) | ||||
| 
 | ||||
|     modcol = testdir.getmodulecol("") | ||||
|     rep = modcol.config.hook.pytest_make_collect_report(collector=modcol) | ||||
|     rep.passed = False | ||||
|     rep.failed = True | ||||
|     rep.skipped = False | ||||
|     recorder.hook.pytest_collectreport(rep=rep) | ||||
|     recorder.hook.pytest_collectreport(report=rep) | ||||
| 
 | ||||
|     passed, skipped, failed = recorder.listoutcomes() | ||||
|     assert not passed and skipped and failed | ||||
|  | @ -440,7 +440,7 @@ def test_reportrecorder(testdir): | |||
| 
 | ||||
|     recorder.unregister() | ||||
|     recorder.clear()  | ||||
|     recorder.hook.pytest_runtest_logreport(rep=rep) | ||||
|     recorder.hook.pytest_runtest_logreport(report=rep) | ||||
|     py.test.raises(ValueError, "recorder.getfailures()") | ||||
| 
 | ||||
| class LineComp: | ||||
|  |  | |||
|  | @ -59,25 +59,25 @@ class ResultLog(object): | |||
|         testpath = generic_path(node) | ||||
|         self.write_log_entry(testpath, shortrepr, longrepr)  | ||||
| 
 | ||||
|     def pytest_runtest_logreport(self, rep): | ||||
|         code = rep.shortrepr  | ||||
|         if rep.passed: | ||||
|     def pytest_runtest_logreport(self, report): | ||||
|         code = report.shortrepr  | ||||
|         if report.passed: | ||||
|             longrepr = "" | ||||
|         elif rep.failed: | ||||
|             longrepr = str(rep.longrepr)  | ||||
|         elif rep.skipped: | ||||
|             longrepr = str(rep.longrepr.reprcrash.message) | ||||
|         self.log_outcome(rep.item, code, longrepr)  | ||||
|         elif report.failed: | ||||
|             longrepr = str(report.longrepr)  | ||||
|         elif report.skipped: | ||||
|             longrepr = str(report.longrepr.reprcrash.message) | ||||
|         self.log_outcome(report.item, code, longrepr)  | ||||
| 
 | ||||
|     def pytest_collectreport(self, rep): | ||||
|         if not rep.passed: | ||||
|             if rep.failed:  | ||||
|     def pytest_collectreport(self, report): | ||||
|         if not report.passed: | ||||
|             if report.failed:  | ||||
|                 code = "F" | ||||
|             else: | ||||
|                 assert rep.skipped | ||||
|                 assert report.skipped | ||||
|                 code = "S" | ||||
|             longrepr = str(rep.longrepr.reprcrash) | ||||
|             self.log_outcome(rep.collector, code, longrepr)     | ||||
|             longrepr = str(report.longrepr.reprcrash) | ||||
|             self.log_outcome(report.collector, code, longrepr)     | ||||
| 
 | ||||
|     def pytest_internalerror(self, excrepr): | ||||
|         path = excrepr.reprcrash.path  | ||||
|  |  | |||
|  | @ -40,7 +40,7 @@ def pytest_runtest_protocol(item): | |||
|     if item.config.getvalue("boxed"): | ||||
|         reports = forked_run_report(item)  | ||||
|         for rep in reports: | ||||
|             item.config.hook.pytest_runtest_logreport(rep=rep) | ||||
|             item.config.hook.pytest_runtest_logreport(report=rep) | ||||
|     else: | ||||
|         runtestprotocol(item) | ||||
|     return True | ||||
|  | @ -89,7 +89,7 @@ def call_and_report(item, when, log=True): | |||
|     hook = item.config.hook | ||||
|     report = hook.pytest_runtest_makereport(item=item, call=call) | ||||
|     if log and (when == "call" or not report.passed): | ||||
|         hook.pytest_runtest_logreport(rep=report)  | ||||
|         hook.pytest_runtest_logreport(report=report)  | ||||
|     return report | ||||
| 
 | ||||
| def call_runtest_hook(item, when): | ||||
|  |  | |||
|  | @ -187,7 +187,8 @@ class TerminalReporter: | |||
|     def pytest__teardown_final_logerror(self, rep): | ||||
|         self.stats.setdefault("error", []).append(rep) | ||||
|   | ||||
|     def pytest_runtest_logreport(self, rep): | ||||
|     def pytest_runtest_logreport(self, report): | ||||
|         rep = report | ||||
|         cat, letter, word = self.getcategoryletterword(rep) | ||||
|         if not letter and not word: | ||||
|             # probably passed setup/teardown | ||||
|  | @ -212,15 +213,15 @@ class TerminalReporter: | |||
|                 self._tw.write(" " + line) | ||||
|                 self.currentfspath = -2 | ||||
| 
 | ||||
|     def pytest_collectreport(self, rep): | ||||
|         if not rep.passed: | ||||
|             if rep.failed: | ||||
|                 self.stats.setdefault("error", []).append(rep) | ||||
|                 msg = rep.longrepr.reprcrash.message  | ||||
|                 self.write_fspath_result(rep.collector.fspath, "E") | ||||
|             elif rep.skipped: | ||||
|                 self.stats.setdefault("skipped", []).append(rep) | ||||
|                 self.write_fspath_result(rep.collector.fspath, "S") | ||||
|     def pytest_collectreport(self, report): | ||||
|         if not report.passed: | ||||
|             if report.failed: | ||||
|                 self.stats.setdefault("error", []).append(report) | ||||
|                 msg = report.longrepr.reprcrash.message  | ||||
|                 self.write_fspath_result(report.collector.fspath, "E") | ||||
|             elif report.skipped: | ||||
|                 self.stats.setdefault("skipped", []).append(report) | ||||
|                 self.write_fspath_result(report.collector.fspath, "S") | ||||
| 
 | ||||
|     def pytest_sessionstart(self, session): | ||||
|         self.write_sep("=", "test session starts", bold=True) | ||||
|  | @ -417,10 +418,10 @@ class CollectonlyReporter: | |||
|     def pytest_itemstart(self, item, node=None): | ||||
|         self.outindent(item) | ||||
| 
 | ||||
|     def pytest_collectreport(self, rep): | ||||
|         if not rep.passed: | ||||
|             self.outindent("!!! %s !!!" % rep.longrepr.reprcrash.message) | ||||
|             self._failed.append(rep) | ||||
|     def pytest_collectreport(self, report): | ||||
|         if not report.passed: | ||||
|             self.outindent("!!! %s !!!" % report.longrepr.reprcrash.message) | ||||
|             self._failed.append(report) | ||||
|         self.indent = self.indent[:-len(self.INDENT)] | ||||
| 
 | ||||
|     def pytest_sessionfinish(self, session, exitstatus): | ||||
|  |  | |||
|  | @ -311,7 +311,7 @@ class TestCollectonly: | |||
|            "  <Function 'test_func'>",  | ||||
|         ]) | ||||
|         rep.config.hook.pytest_collectreport( | ||||
|             rep=runner.CollectReport(modcol, [], excinfo=None)) | ||||
|             report=runner.CollectReport(modcol, [], excinfo=None)) | ||||
|         assert rep.indent == indent  | ||||
| 
 | ||||
|     def test_collectonly_skipped_module(self, testdir, linecomp): | ||||
|  |  | |||
|  | @ -45,7 +45,7 @@ class Session(object): | |||
|                 if rep.passed: | ||||
|                     for x in self.genitems(rep.result, keywordexpr): | ||||
|                         yield x  | ||||
|                 self.config.hook.pytest_collectreport(rep=rep) | ||||
|                 self.config.hook.pytest_collectreport(report=rep) | ||||
|             if self.shouldstop: | ||||
|                 break | ||||
| 
 | ||||
|  | @ -79,8 +79,8 @@ class Session(object): | |||
|         """ setup any neccessary resources ahead of the test run. """ | ||||
|         self.config.hook.pytest_sessionstart(session=self) | ||||
|          | ||||
|     def pytest_runtest_logreport(self, rep): | ||||
|         if rep.failed: | ||||
|     def pytest_runtest_logreport(self, report): | ||||
|         if report.failed: | ||||
|             self._testsfailed = True | ||||
|             if self.config.option.exitfirst: | ||||
|                 self.shouldstop = True | ||||
|  |  | |||
|  | @ -67,187 +67,3 @@ class TestGeneralUsage: | |||
|             "E   ImportError: No module named does_not_work", | ||||
|         ]) | ||||
|         assert result.ret == 1 | ||||
| 
 | ||||
| class TestDistribution: | ||||
|     def test_dist_conftest_options(self, testdir): | ||||
|         p1 = testdir.tmpdir.ensure("dir", 'p1.py') | ||||
|         p1.dirpath("__init__.py").write("") | ||||
|         p1.dirpath("conftest.py").write(py.code.Source(""" | ||||
|             print "importing conftest", __file__ | ||||
|             import py | ||||
|             Option = py.test.config.Option  | ||||
|             option = py.test.config.addoptions("someopt",  | ||||
|                 Option('--someopt', action="store_true", dest="someopt", default=False)) | ||||
|             dist_rsync_roots = ['../dir'] | ||||
|             print "added options", option | ||||
|             print "config file seen from conftest", py.test.config | ||||
|         """)) | ||||
|         p1.write(py.code.Source(""" | ||||
|             import py, conftest | ||||
|             def test_1():  | ||||
|                 print "config from test_1", py.test.config | ||||
|                 print "conftest from test_1", conftest.__file__ | ||||
|                 print "test_1: py.test.config.option.someopt", py.test.config.option.someopt | ||||
|                 print "test_1: conftest", conftest | ||||
|                 print "test_1: conftest.option.someopt", conftest.option.someopt | ||||
|                 assert conftest.option.someopt  | ||||
|         """)) | ||||
|         result = testdir.runpytest('-d', '--tx=popen', p1, '--someopt') | ||||
|         assert result.ret == 0 | ||||
|         extra = result.stdout.fnmatch_lines([ | ||||
|             "*1 passed*",  | ||||
|         ]) | ||||
| 
 | ||||
|     def test_manytests_to_one_popen(self, testdir): | ||||
|         p1 = testdir.makepyfile(""" | ||||
|                 import py | ||||
|                 def test_fail0(): | ||||
|                     assert 0 | ||||
|                 def test_fail1(): | ||||
|                     raise ValueError() | ||||
|                 def test_ok(): | ||||
|                     pass | ||||
|                 def test_skip(): | ||||
|                     py.test.skip("hello") | ||||
|             """,  | ||||
|         ) | ||||
|         result = testdir.runpytest(p1, '-d', '--tx=popen', '--tx=popen') | ||||
|         result.stdout.fnmatch_lines([ | ||||
|             "*1*popen*Python*", | ||||
|             "*2*popen*Python*", | ||||
|             "*2 failed, 1 passed, 1 skipped*", | ||||
|         ]) | ||||
|         assert result.ret == 1 | ||||
| 
 | ||||
|     def test_dist_conftest_specified(self, testdir): | ||||
|         p1 = testdir.makepyfile(""" | ||||
|                 import py | ||||
|                 def test_fail0(): | ||||
|                     assert 0 | ||||
|                 def test_fail1(): | ||||
|                     raise ValueError() | ||||
|                 def test_ok(): | ||||
|                     pass | ||||
|                 def test_skip(): | ||||
|                     py.test.skip("hello") | ||||
|             """,  | ||||
|         ) | ||||
|         testdir.makeconftest(""" | ||||
|             pytest_option_tx = 'popen popen popen'.split() | ||||
|         """) | ||||
|         result = testdir.runpytest(p1, '-d') | ||||
|         result.stdout.fnmatch_lines([ | ||||
|             "*1*popen*Python*", | ||||
|             "*2*popen*Python*", | ||||
|             "*3*popen*Python*", | ||||
|             "*2 failed, 1 passed, 1 skipped*", | ||||
|         ]) | ||||
|         assert result.ret == 1 | ||||
| 
 | ||||
|     def test_dist_tests_with_crash(self, testdir): | ||||
|         if not hasattr(py.std.os, 'kill'): | ||||
|             py.test.skip("no os.kill") | ||||
|          | ||||
|         p1 = testdir.makepyfile(""" | ||||
|                 import py | ||||
|                 def test_fail0(): | ||||
|                     assert 0 | ||||
|                 def test_fail1(): | ||||
|                     raise ValueError() | ||||
|                 def test_ok(): | ||||
|                     pass | ||||
|                 def test_skip(): | ||||
|                     py.test.skip("hello") | ||||
|                 def test_crash(): | ||||
|                     import time | ||||
|                     import os | ||||
|                     time.sleep(0.5) | ||||
|                     os.kill(os.getpid(), 15) | ||||
|             """ | ||||
|         ) | ||||
|         result = testdir.runpytest(p1, '-d', '--tx=3*popen') | ||||
|         result.stdout.fnmatch_lines([ | ||||
|             "*popen*Python*", | ||||
|             "*popen*Python*", | ||||
|             "*popen*Python*", | ||||
|             "*node down*", | ||||
|             "*3 failed, 1 passed, 1 skipped*" | ||||
|         ]) | ||||
|         assert result.ret == 1 | ||||
| 
 | ||||
|     def test_distribution_rsyncdirs_example(self, testdir): | ||||
|         source = testdir.mkdir("source") | ||||
|         dest = testdir.mkdir("dest") | ||||
|         subdir = source.mkdir("example_pkg") | ||||
|         subdir.ensure("__init__.py") | ||||
|         p = subdir.join("test_one.py") | ||||
|         p.write("def test_5(): assert not __file__.startswith(%r)" % str(p)) | ||||
|         result = testdir.runpytest("-d", "--rsyncdir=%(subdir)s" % locals(),  | ||||
|             "--tx=popen//chdir=%(dest)s" % locals(), p) | ||||
|         assert result.ret == 0 | ||||
|         result.stdout.fnmatch_lines([ | ||||
|             "*1* *popen*platform*", | ||||
|             #"RSyncStart: [G1]", | ||||
|             #"RSyncFinished: [G1]", | ||||
|             "*1 passed*" | ||||
|         ]) | ||||
|         assert dest.join(subdir.basename).check(dir=1) | ||||
| 
 | ||||
|     def test_dist_each(self, testdir): | ||||
|         interpreters = [] | ||||
|         for name in ("python2.4", "python2.5"): | ||||
|             interp = py.path.local.sysfind(name) | ||||
|             if interp is None: | ||||
|                 py.test.skip("%s not found" % name) | ||||
|             interpreters.append(interp) | ||||
| 
 | ||||
|         testdir.makepyfile(__init__="", test_one=""" | ||||
|             import sys | ||||
|             def test_hello(): | ||||
|                 print "%s...%s" % sys.version_info[:2] | ||||
|                 assert 0 | ||||
|         """) | ||||
|         args = ["--dist=each"] | ||||
|         args += ["--tx", "popen//python=%s" % interpreters[0]] | ||||
|         args += ["--tx", "popen//python=%s" % interpreters[1]] | ||||
|         result = testdir.runpytest(*args) | ||||
|         result.stdout.fnmatch_lines(["2...4"]) | ||||
|         result.stdout.fnmatch_lines(["2...5"]) | ||||
| 
 | ||||
| 
 | ||||
| class TestInteractive: | ||||
|     def test_simple_looponfail_interaction(self, testdir): | ||||
|         p1 = testdir.makepyfile(""" | ||||
|             def test_1(): | ||||
|                 assert 1 == 0  | ||||
|         """) | ||||
|         p1.setmtime(p1.mtime() - 50.0)   | ||||
|         child = testdir.spawn_pytest("--looponfail %s" % p1) | ||||
|         child.expect("assert 1 == 0") | ||||
|         child.expect("test_simple_looponfail_interaction.py:") | ||||
|         child.expect("1 failed") | ||||
|         child.expect("waiting for changes") | ||||
|         p1.write(py.code.Source(""" | ||||
|             def test_1(): | ||||
|                 assert 1 == 1 | ||||
|         """)) | ||||
|         child.expect("MODIFIED.*test_simple_looponfail_interaction.py", timeout=4.0) | ||||
|         child.expect("1 passed", timeout=5.0) | ||||
|         child.kill(15) | ||||
|         | ||||
| class TestKeyboardInterrupt:  | ||||
|     def test_raised_in_testfunction(self, testdir): | ||||
|         p1 = testdir.makepyfile(""" | ||||
|             import py | ||||
|             def test_fail(): | ||||
|                 raise ValueError() | ||||
|             def test_inter(): | ||||
|                 raise KeyboardInterrupt() | ||||
|         """) | ||||
|         result = testdir.runpytest(p1) | ||||
|         result.stdout.fnmatch_lines([ | ||||
|             #"*test_inter() INTERRUPTED", | ||||
|             "*KEYBOARD INTERRUPT*", | ||||
|             "*1 failed*",  | ||||
|         ]) | ||||
| 
 | ||||
|  |  | |||
							
								
								
									
										2
									
								
								setup.py
								
								
								
								
							
							
						
						
									
										2
									
								
								setup.py
								
								
								
								
							|  | @ -45,7 +45,7 @@ def main(): | |||
|                                           'py.svnwcrevert = py.cmdline:pysvnwcrevert', | ||||
|                                           'py.test = py.cmdline:pytest', | ||||
|                                           'py.which = py.cmdline:pywhich']}, | ||||
|         classifiers=['Development Status :: 4 - Beta', | ||||
|         classifiers=['Development Status :: 5 - Stable', | ||||
|                      'Intended Audience :: Developers', | ||||
|                      'License :: OSI Approved :: MIT License', | ||||
|                      'Operating System :: POSIX', | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue