merging 1.0.x changes

--HG--
branch : trunk
This commit is contained in:
holger krekel 2009-07-08 20:08:07 +02:00
commit 8a085c035a
31 changed files with 209 additions and 114 deletions

View File

@ -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
============================================= =============================================

View File

@ -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

View File

@ -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!)

View File

@ -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 ...

View File

@ -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

View File

@ -0,0 +1,3 @@
import py
collect_ignore = 'mysetup', 'mysetup2', 'test_simpleprovider.py', 'parametrize'

View File

@ -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:

View File

@ -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

View File

@ -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)

View File

@ -1,5 +1,5 @@
""" """
automatically collect and execute doctests. collect and execute doctests from modules and test files.
""" """
import py import py

View File

@ -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

View File

@ -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')

View File

@ -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):

View File

@ -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.

View File

@ -1,6 +1,5 @@
""" """
py.test.mark / keyword plugin py.test.mark / keyword plugin
""" """
import py import py

View File

@ -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: the "monkeypatch" funcarg has three helper functions:
monkeypatch.setattr(obj, name, value) monkeypatch.setattr(obj, name, value)
monkeypatch.setitem(obj, name, value) monkeypatch.setitem(obj, name, value)
monkeypatch.setenv(name, value) monkeypatch.setenv(name, value)
After the test has run modifications will be undone. After the test has run modifications will be undone.
""" """
import os import os

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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.

View File

@ -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

View File

@ -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
@ -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)

View File

@ -1,3 +1,6 @@
"""
terminal reporting of the full testing process.
"""
import py import py
import sys import sys

View File

@ -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

View File

@ -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:

View File

@ -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,11 +97,21 @@ class PluginManager(object):
modname = canonical_importname(spec) modname = canonical_importname(spec)
if modname in self.impname2plugin: if modname in self.impname2plugin:
return return
try:
mod = importplugin(modname) mod = importplugin(modname)
except KeyboardInterrupt:
raise
except Skipped, e:
self._warn("could not import plugin %r, reason: %r" %(
(modname, e.msg)))
else:
check_old_use(mod, modname) check_old_use(mod, modname)
self.register(mod) self.register(mod)
self.consider_module(mod) self.consider_module(mod)
def _warn(self, msg):
print "===WARNING=== %s" % (msg,)
def _checkplugin(self, plugin): def _checkplugin(self, plugin):
# ===================================================== # =====================================================
# check plugin hooks # check plugin hooks
@ -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

View File

@ -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):

View File

@ -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("""

View File

@ -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