plugin cleanups
* make pytest_eventlog.py work again by adding a hack to the registry, rename * disable resultdb hook plugin, it needs merging with resultlog * add some docstrings, streamline bits --HG-- branch : trunk
This commit is contained in:
		
							parent
							
								
									219e627f87
								
							
						
					
					
						commit
						d1f24aa251
					
				|  | @ -63,6 +63,7 @@ class Registry: | |||
|     """ | ||||
|         Manage Plugins: Load plugins and manage calls to plugins.  | ||||
|     """ | ||||
|     logfile = None | ||||
|     MultiCall = MultiCall | ||||
| 
 | ||||
|     def __init__(self, plugins=None): | ||||
|  | @ -130,6 +131,11 @@ class HookCall: | |||
|                             "for api call to %r" % self.name) | ||||
|         attr = self.registry.listattr(self.name, extra=self.extralookup) | ||||
|         mc = MultiCall(attr, **kwargs) | ||||
|         # XXX this should be doable from a hook impl: | ||||
|         if self.registry.logfile: | ||||
|             self.registry.logfile.write("%s(**%s) # firstresult=%s\n" % | ||||
|                 (self.name, kwargs, self.firstresult)) | ||||
|             self.registry.logfile.flush() | ||||
|         return mc.execute(firstresult=self.firstresult) | ||||
| 
 | ||||
| comregistry = Registry() | ||||
|  |  | |||
|  | @ -18,6 +18,7 @@ def pytest_funcarg__testdir(request): | |||
|     basename = request.module.__name__.split(".")[-1]  | ||||
|     if basename.startswith("pytest_"): | ||||
|         testdir.plugins.append(vars(request.module)) | ||||
|         testdir.plugins.append(basename)  | ||||
|     else: | ||||
|         pass # raise ValueError("need better support code") | ||||
|     return testdir | ||||
|  |  | |||
|  | @ -1,4 +1,9 @@ | |||
| """ | ||||
| automatically collect and execute doctests.  | ||||
| """ | ||||
| 
 | ||||
| import py | ||||
| from py.__.code.excinfo import Repr, ReprFileLocation | ||||
| 
 | ||||
| def pytest_addoption(parser): | ||||
|     group = parser.addgroup("doctest options") | ||||
|  | @ -13,8 +18,6 @@ def pytest_collect_file(path, parent): | |||
|     if path.check(fnmatch="test_*.txt"): | ||||
|         return DoctestTextfile(path, parent) | ||||
| 
 | ||||
| from py.__.code.excinfo import Repr, ReprFileLocation | ||||
| 
 | ||||
| class ReprFailDoctest(Repr): | ||||
|     def __init__(self, reprlocation, lines): | ||||
|         self.reprlocation = reprlocation | ||||
|  |  | |||
|  | @ -1,45 +0,0 @@ | |||
| import py | ||||
| 
 | ||||
| """ expected to fail.  | ||||
| """ | ||||
| 
 | ||||
| class EventlogPlugin: | ||||
|     """ log pytest events to a file. """ | ||||
|     def pytest_addoption(self, parser): | ||||
|         parser.addoption("--eventlog", dest="eventlog",  | ||||
|             help="write all pytest events to the given file.") | ||||
| 
 | ||||
|     def pytest_configure(self, config): | ||||
|         eventlog = config.getvalue("eventlog") | ||||
|         if eventlog: | ||||
|             self.eventlogfile = open(eventlog, 'w') | ||||
| 
 | ||||
|     def pytest_unconfigure(self, config): | ||||
|         if hasattr(self, 'eventlogfile'): | ||||
|             self.eventlogfile.close() | ||||
|             del self.eventlogfile | ||||
| 
 | ||||
|     def pyevent(self, eventname, args, kwargs): | ||||
|         if hasattr(self, 'eventlogfile'): | ||||
|             f = self.eventlogfile | ||||
|             print >>f, eventname, args, kwargs | ||||
|             f.flush() | ||||
| 
 | ||||
| # =============================================================================== | ||||
| # plugin tests  | ||||
| # =============================================================================== | ||||
| 
 | ||||
| @py.test.mark.xfail | ||||
| def test_generic(plugintester): | ||||
|     plugintester.hookcheck() | ||||
| 
 | ||||
|     testdir = plugintester.testdir() | ||||
|     testdir.makepyfile(""" | ||||
|         def test_pass(): | ||||
|             pass | ||||
|     """) | ||||
|     testdir.runpytest("--eventlog=event.log") | ||||
|     s = testdir.tmpdir.join("event.log").read() | ||||
|     assert s.find("testrunstart") != -1 | ||||
|     assert s.find("ItemTestReport") != -1 | ||||
|     assert s.find("testrunfinish") != -1 | ||||
|  | @ -1,3 +1,6 @@ | |||
| """ | ||||
| cleanup gateways that were instantiated during a test function run.  | ||||
| """ | ||||
| import py | ||||
| 
 | ||||
| def pytest_configure(config): | ||||
|  |  | |||
|  | @ -1,3 +1,6 @@ | |||
| """ | ||||
| write and report coverage data using the 'figleaf' module.  | ||||
| """ | ||||
| import py | ||||
| 
 | ||||
| figleaf = py.test.importorskip("figleaf") | ||||
|  |  | |||
|  | @ -0,0 +1,36 @@ | |||
| """ log calling of plugin hooks to a file. """  | ||||
| import py | ||||
| 
 | ||||
| def pytest_addoption(parser): | ||||
|     parser.addoption("--hooklog", dest="hooklog", default=None,  | ||||
|         help="write hook calls to the given file.") | ||||
| 
 | ||||
| def pytest_configure(config): | ||||
|     hooklog = config.getvalue("hooklog") | ||||
|     if hooklog: | ||||
|         assert not config.pluginmanager.comregistry.logfile | ||||
|         config.pluginmanager.comregistry.logfile = open(hooklog, 'w') | ||||
| 
 | ||||
| def pytest_unconfigure(config): | ||||
|     f = config.pluginmanager.comregistry.logfile | ||||
|     if f: | ||||
|         f.close() | ||||
|         config.pluginmanager.comregistry.logfile = None | ||||
| 
 | ||||
| # =============================================================================== | ||||
| # plugin tests  | ||||
| # =============================================================================== | ||||
| 
 | ||||
| def test_generic(plugintester): | ||||
|     plugintester.hookcheck() | ||||
| 
 | ||||
| def test_functional(testdir): | ||||
|     testdir.makepyfile(""" | ||||
|         def test_pass(): | ||||
|             pass | ||||
|     """) | ||||
|     testdir.runpytest("--hooklog=hook.log") | ||||
|     s = testdir.tmpdir.join("hook.log").read() | ||||
|     assert s.find("pytest_testrunstart") != -1 | ||||
|     assert s.find("ItemTestReport") != -1 | ||||
|     assert s.find("testrunfinish") != -1 | ||||
|  | @ -1,12 +1,22 @@ | |||
| """ | ||||
| 'capsys' and 'capfd' funcargs for capturing stdout/stderror either | ||||
| by intercepting sys.stdout/stderr or File Descriptors 1/2.  | ||||
| 
 | ||||
| Calling the reset() method of the capture funcargs gives  | ||||
| a out/err tuple of strings representing the captured streams.  | ||||
| You can call reset() multiple times each time getting | ||||
| the chunk of output that was captured between the invocations.  | ||||
| 
 | ||||
| """ | ||||
| import py | ||||
| 
 | ||||
| def pytest_funcarg__stdcapture(request): | ||||
| def pytest_funcarg__capsys(request): | ||||
|     """ capture writes to sys.stdout/sys.stderr. """  | ||||
|     capture = Capture(py.io.StdCapture) | ||||
|     request.addfinalizer(capture.finalize) | ||||
|     return capture  | ||||
| 
 | ||||
| def pytest_funcarg__stdcapturefd(request): | ||||
| def pytest_funcarg__capfd(request): | ||||
|     """ capture writes to filedescriptors 1 and 2""" | ||||
|     capture = Capture(py.io.StdCaptureFD) | ||||
|     request.addfinalizer(capture.finalize) | ||||
|  | @ -31,19 +41,19 @@ def test_generic(plugintester): | |||
| class TestCapture: | ||||
|     def test_std_functional(self, testdir):         | ||||
|         reprec = testdir.inline_runsource(""" | ||||
|             def test_hello(stdcapture): | ||||
|             def test_hello(capsys): | ||||
|                 print 42 | ||||
|                 out, err = stdcapture.reset() | ||||
|                 out, err = capsys.reset() | ||||
|                 assert out.startswith("42") | ||||
|         """) | ||||
|         reprec.assertoutcome(passed=1) | ||||
|          | ||||
|     def test_stdfd_functional(self, testdir):         | ||||
|         reprec = testdir.inline_runsource(""" | ||||
|             def test_hello(stdcapturefd): | ||||
|             def test_hello(capfd): | ||||
|                 import os | ||||
|                 os.write(1, "42") | ||||
|                 out, err = stdcapturefd.reset() | ||||
|                 out, err = capfd.reset() | ||||
|                 assert out.startswith("42") | ||||
|         """) | ||||
|         reprec.assertoutcome(passed=1) | ||||
|  |  | |||
|  | @ -1,17 +1,15 @@ | |||
| import os | ||||
| """ | ||||
|     provides the "monkeypatch" funcarg for safely patching objects,  | ||||
|     "monkeypatch" funcarg for safely patching objects,  | ||||
|     dictionaries and environment variables during the execution of  | ||||
|     a test.  There are three helper functions:  | ||||
|     a test.  "monkeypatch" has three helper functions:  | ||||
| 
 | ||||
|         monkeypatch.setattr(obj, name, value)  | ||||
|         monkeypatch.setitem(obj, name, value)  | ||||
|         monkeypatch.setenv(name, value)  | ||||
| 
 | ||||
|     After the test run all such modifications will be undone,  | ||||
|     which may even mean deleting the attribute or dictionary entry  | ||||
|     if it didn't exist before.  | ||||
|     After the test has run modifications will be undone.  | ||||
| """ | ||||
| import os | ||||
| 
 | ||||
| def pytest_funcarg__monkeypatch(request): | ||||
|     monkeypatch = MonkeyPatch() | ||||
|  |  | |||
|  | @ -1,3 +1,4 @@ | |||
| """ XXX should be used sometime. """  | ||||
| from py.__.test.custompdb import post_mortem | ||||
| 
 | ||||
| def pytest_item_runtest_finished(item, excinfo, outerr): | ||||
|  |  | |||
|  | @ -1,6 +1,5 @@ | |||
| """pylint plugin | ||||
| 
 | ||||
| 
 | ||||
| XXX: Currently in progress, NOT IN WORKING STATE. | ||||
| """ | ||||
| import py | ||||
|  |  | |||
|  | @ -1,5 +1,5 @@ | |||
| """ | ||||
| pytes plugin for easing testing of pytest runs themselves.  | ||||
| funcargs and support code for testing py.test functionality.  | ||||
| """ | ||||
| 
 | ||||
| import py | ||||
|  |  | |||
|  | @ -1,8 +1,5 @@ | |||
| """ | ||||
| 
 | ||||
| provides "recwarn" funcarg for asserting warnings to be shown  | ||||
| to a user.  See the test at the bottom for an example.  | ||||
| 
 | ||||
| "recwarn" funcarg for asserting that warnings are shown to a user.   | ||||
| """ | ||||
| import py | ||||
| import os | ||||
|  |  | |||
|  | @ -1,3 +1,7 @@ | |||
| """ | ||||
| perform ReST specific tests on .txt files, including | ||||
| linkchecks and remote URL checks.  | ||||
| """ | ||||
| import py | ||||
| 
 | ||||
| def pytest_addoption(parser): | ||||
|  |  | |||
|  | @ -1,54 +1,51 @@ | |||
| """XXX in progress: resultdb plugin for database logging of test results.  | ||||
| 
 | ||||
| Saves test results to a datastore. | ||||
| 
 | ||||
| XXX this needs to be merged with resultlog plugin | ||||
| 
 | ||||
| Also mixes in some early ideas about an archive abstraction for test  | ||||
| results. | ||||
| """  | ||||
| import py | ||||
| 
 | ||||
| py.test.skip("XXX needs to be merged with resultlog") | ||||
| 
 | ||||
| from pytest_resultlog import ResultLog | ||||
| 
 | ||||
| class ResultdbPlugin: | ||||
|     """XXX in progress: resultdb plugin for database logging of test results.  | ||||
| def pytest_addoption(parser): | ||||
|     group = parser.addgroup("resultdb", "resultdb plugin options") | ||||
|     group.addoption('--resultdb', action="store", dest="resultdb",  | ||||
|             metavar="path", | ||||
|             help="path to the file to store test results.") | ||||
|     group.addoption('--resultdb_format', action="store",  | ||||
|             dest="resultdbformat", default='json', | ||||
|             help="data format (json, sqlite)") | ||||
| 
 | ||||
|     Saves test results to a datastore. | ||||
| 
 | ||||
|     XXX this needs to be merged with resultlog plugin | ||||
| 
 | ||||
|     Also mixes in some early ideas about an archive abstraction for test  | ||||
|     results. | ||||
|     """  | ||||
|     def pytest_addoption(self, parser): | ||||
|         group = parser.addgroup("resultdb", "resultdb plugin options") | ||||
|         group.addoption('--resultdb', action="store", dest="resultdb",  | ||||
|                 metavar="path", | ||||
|                 help="path to the file to store test results.") | ||||
|         group.addoption('--resultdb_format', action="store",  | ||||
|                 dest="resultdbformat", default='json', | ||||
|                 help="data format (json, sqlite)") | ||||
|      | ||||
|     def pytest_configure(self, config): | ||||
|         if config.getvalue('resultdb'): | ||||
|             if config.option.resultdb: | ||||
|                 # local import so missing module won't crash py.test | ||||
|                 try: | ||||
|                     import sqlite3 | ||||
|                 except ImportError: | ||||
|                     raise config.Error('Could not import sqlite3 module') | ||||
|                 try: | ||||
|                     import simplejson | ||||
|                 except ImportError: | ||||
|                     raise config.Error('Could not import simplejson module') | ||||
|                 if config.option.resultdbformat.lower() == 'json': | ||||
|                     self.resultdb = ResultDB(JSONResultArchive,  | ||||
|                             config.option.resultdb)  | ||||
|                 elif config.option.resultdbformat.lower() == 'sqlite': | ||||
|                     self.resultdb = ResultDB(SQLiteResultArchive,  | ||||
|                             config.option.resultdb)  | ||||
|                 else: | ||||
|                     raise config.Error('Unknown --resultdb_format: %s' %  | ||||
|                             config.option.resultdbformat)  | ||||
| 
 | ||||
|                 config.pluginmanager.register(self.resultdb) | ||||
| 
 | ||||
|     def pytest_unconfigure(self, config): | ||||
|         if hasattr(self, 'resultdb'): | ||||
|             del self.resultdb  | ||||
|             #config.pluginmanager.unregister(self.resultdb) | ||||
| def pytest_configure(config): | ||||
|     # XXX using config.XYZ is not good  | ||||
|     if config.getvalue('resultdb'): | ||||
|         if config.option.resultdb: | ||||
|             # local import so missing module won't crash py.test | ||||
|             try: | ||||
|                 import sqlite3 | ||||
|             except ImportError: | ||||
|                 raise config.Error('Could not import sqlite3 module') | ||||
|             try: | ||||
|                 import simplejson | ||||
|             except ImportError: | ||||
|                 raise config.Error('Could not import simplejson module') | ||||
|             if config.option.resultdbformat.lower() == 'json': | ||||
|                 resultdb = ResultDB(JSONResultArchive,  | ||||
|                         config.option.resultdb)  | ||||
|             elif config.option.resultdbformat.lower() == 'sqlite': | ||||
|                 resultdb = ResultDB(SQLiteResultArchive,  | ||||
|                         config.option.resultdb)  | ||||
|             else: | ||||
|                 raise config.Error('Unknown --resultdb_format: %s' %  | ||||
|                         config.option.resultdbformat)  | ||||
| 
 | ||||
|             config.pluginmanager.register(resultdb) | ||||
| 
 | ||||
| class JSONResultArchive(object): | ||||
|     def __init__(self, archive_path): | ||||
|  | @ -328,8 +325,7 @@ class TestWithFunctionIntegration: | |||
|             assert x.startswith(" ") | ||||
|         assert "XXX" in "".join(lines[1:]) | ||||
| 
 | ||||
|     def test_log_test_outcomes(self, plugintester): | ||||
|         testdir = plugintester.testdir() | ||||
|     def test_log_test_outcomes(self, testdir): | ||||
|         mod = testdir.makepyfile(test_mod=""" | ||||
|             import py  | ||||
|             def test_pass(): pass | ||||
|  |  | |||
|  | @ -10,8 +10,6 @@ this code is somewhat derived from Guido Wesdorps | |||
| 
 | ||||
|     http://johnnydebris.net/svn/projects/py_unittest | ||||
| 
 | ||||
| $HeadURL: https://codespeak.net/svn/py/branch/pytestplugin/contrib/py_unittest/conftest.py $ | ||||
| $Id: conftest.py 60979 2009-01-14 22:29:32Z hpk $ | ||||
| """ | ||||
| import py | ||||
| 
 | ||||
|  |  | |||
|  | @ -1,7 +1,8 @@ | |||
| """ | ||||
| mark and report specially about "expected to fail" tests.  | ||||
| mark tests as expected-to-fail and report them separately.  | ||||
| 
 | ||||
| example:  | ||||
| 
 | ||||
| for marking and reporting "expected to fail" tests.  | ||||
|     @py.test.mark.xfail("needs refactoring") | ||||
|     def test_hello(): | ||||
|         ... | ||||
|  | @ -29,7 +30,7 @@ def pytest_report_teststatus(rep): | |||
|         elif rep.failed: | ||||
|             return "xpassed", "P", "xpass"  | ||||
| 
 | ||||
| # a hook implemented called by the terminalreporter instance/plugin | ||||
| # called by the terminalreporter instance/plugin | ||||
| def pytest_terminal_summary(terminalreporter): | ||||
|     tr = terminalreporter | ||||
|     xfailed = tr.stats.get("xfailed") | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue