commit
58db35e70c
16
CHANGELOG
16
CHANGELOG
|
@ -1,3 +1,19 @@
|
||||||
|
Changes between 1.0.0 and 1.0.1
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
* various unicode fixes: capturing and prints of unicode strings now
|
||||||
|
work within tests, they are encoded as "utf8" by default, terminalwriting
|
||||||
|
was adapted and somewhat unified between windows and linux
|
||||||
|
|
||||||
|
* fix issue #27: better reporting on non-collectable items given on commandline
|
||||||
|
(e.g. pyc files)
|
||||||
|
|
||||||
|
* "Test" prefixed classes with an __init__ method are *not* collected by default anymore
|
||||||
|
|
||||||
|
* terser reporting of collection error tracebacks
|
||||||
|
|
||||||
|
* renaming of arguments to some special rather internal hooks
|
||||||
|
|
||||||
Changes between 1.0.0b9 and 1.0.0
|
Changes between 1.0.0b9 and 1.0.0
|
||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
|
|
|
@ -21,7 +21,7 @@ on CPython 2.3 - CPython 2.6.
|
||||||
automatically collects and executes tests
|
automatically collects and executes tests
|
||||||
===============================================
|
===============================================
|
||||||
|
|
||||||
py.test discovers tests automatically by inspect specified
|
py.test discovers tests automatically by inspecting specified
|
||||||
directories or files. By default, it collects all python
|
directories or files. By default, it collects all python
|
||||||
modules a leading ``test_`` or trailing ``_test`` filename.
|
modules a leading ``test_`` or trailing ``_test`` filename.
|
||||||
From each test module every function with a leading ``test_``
|
From each test module every function with a leading ``test_``
|
||||||
|
|
|
@ -289,6 +289,7 @@ Funcarg Tutorial Examples
|
||||||
|
|
||||||
|
|
||||||
.. _`application setup tutorial example`:
|
.. _`application setup tutorial example`:
|
||||||
|
.. _appsetup:
|
||||||
|
|
||||||
application specific test setup
|
application specific test setup
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
@ -494,12 +495,13 @@ example: decorating a funcarg in a test module
|
||||||
|
|
||||||
For larger scale setups it's sometimes useful to decorare
|
For larger scale setups it's sometimes useful to decorare
|
||||||
a funcarg just for a particular test module. We can
|
a funcarg just for a particular test module. We can
|
||||||
extend the `accept example`_ by putting this in our test class:
|
extend the `accept example`_ by putting this in our test module:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
def pytest_funcarg__accept(self, request):
|
def pytest_funcarg__accept(request):
|
||||||
arg = request.getfuncargvalue("accept") # call the next factory
|
# call the next factory (living in our conftest.py)
|
||||||
|
arg = request.getfuncargvalue("accept")
|
||||||
# create a special layout in our tempdir
|
# create a special layout in our tempdir
|
||||||
arg.tmpdir.mkdir("special")
|
arg.tmpdir.mkdir("special")
|
||||||
return arg
|
return arg
|
||||||
|
|
|
@ -1,33 +1,33 @@
|
||||||
.. _`terminal`: terminal.html
|
.. _`terminal`: terminal.html
|
||||||
.. _`pytest_recwarn.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_recwarn.py
|
.. _`pytest_recwarn.py`: http://bitbucket.org/hpk42/py-trunk/raw/caf81a2cdf5083be3bfb715d7e56273330a54843/py/test/plugin/pytest_recwarn.py
|
||||||
.. _`unittest`: unittest.html
|
.. _`unittest`: unittest.html
|
||||||
.. _`pytest_monkeypatch.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_monkeypatch.py
|
.. _`pytest_monkeypatch.py`: http://bitbucket.org/hpk42/py-trunk/raw/caf81a2cdf5083be3bfb715d7e56273330a54843/py/test/plugin/pytest_monkeypatch.py
|
||||||
.. _`pytest_keyword.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_keyword.py
|
.. _`pytest_keyword.py`: http://bitbucket.org/hpk42/py-trunk/raw/caf81a2cdf5083be3bfb715d7e56273330a54843/py/test/plugin/pytest_keyword.py
|
||||||
.. _`pastebin`: pastebin.html
|
.. _`pastebin`: pastebin.html
|
||||||
.. _`plugins`: index.html
|
.. _`plugins`: index.html
|
||||||
.. _`pytest_capture.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_capture.py
|
.. _`pytest_capture.py`: http://bitbucket.org/hpk42/py-trunk/raw/caf81a2cdf5083be3bfb715d7e56273330a54843/py/test/plugin/pytest_capture.py
|
||||||
.. _`pytest_doctest.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_doctest.py
|
.. _`pytest_doctest.py`: http://bitbucket.org/hpk42/py-trunk/raw/caf81a2cdf5083be3bfb715d7e56273330a54843/py/test/plugin/pytest_doctest.py
|
||||||
.. _`capture`: capture.html
|
.. _`capture`: capture.html
|
||||||
.. _`hooklog`: hooklog.html
|
.. _`hooklog`: hooklog.html
|
||||||
.. _`pytest_restdoc.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_restdoc.py
|
.. _`pytest_restdoc.py`: http://bitbucket.org/hpk42/py-trunk/raw/caf81a2cdf5083be3bfb715d7e56273330a54843/py/test/plugin/pytest_restdoc.py
|
||||||
.. _`pytest_hooklog.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_hooklog.py
|
.. _`pytest_hooklog.py`: http://bitbucket.org/hpk42/py-trunk/raw/caf81a2cdf5083be3bfb715d7e56273330a54843/py/test/plugin/pytest_hooklog.py
|
||||||
.. _`pytest_pastebin.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_pastebin.py
|
.. _`pytest_pastebin.py`: http://bitbucket.org/hpk42/py-trunk/raw/caf81a2cdf5083be3bfb715d7e56273330a54843/py/test/plugin/pytest_pastebin.py
|
||||||
.. _`pytest_figleaf.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_figleaf.py
|
.. _`pytest_figleaf.py`: http://bitbucket.org/hpk42/py-trunk/raw/caf81a2cdf5083be3bfb715d7e56273330a54843/py/test/plugin/pytest_figleaf.py
|
||||||
.. _`xfail`: xfail.html
|
.. _`xfail`: xfail.html
|
||||||
.. _`contact`: ../../contact.html
|
.. _`contact`: ../../contact.html
|
||||||
.. _`checkout the py.test development version`: ../../download.html#checkout
|
.. _`checkout the py.test development version`: ../../download.html#checkout
|
||||||
.. _`oejskit`: oejskit.html
|
.. _`oejskit`: oejskit.html
|
||||||
.. _`pytest_xfail.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_xfail.py
|
.. _`pytest_xfail.py`: http://bitbucket.org/hpk42/py-trunk/raw/caf81a2cdf5083be3bfb715d7e56273330a54843/py/test/plugin/pytest_xfail.py
|
||||||
.. _`figleaf`: figleaf.html
|
.. _`figleaf`: figleaf.html
|
||||||
.. _`extend`: ../extend.html
|
.. _`extend`: ../extend.html
|
||||||
.. _`pytest_terminal.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_terminal.py
|
.. _`pytest_terminal.py`: http://bitbucket.org/hpk42/py-trunk/raw/caf81a2cdf5083be3bfb715d7e56273330a54843/py/test/plugin/pytest_terminal.py
|
||||||
.. _`recwarn`: recwarn.html
|
.. _`recwarn`: recwarn.html
|
||||||
.. _`pytest_pdb.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_pdb.py
|
.. _`pytest_pdb.py`: http://bitbucket.org/hpk42/py-trunk/raw/caf81a2cdf5083be3bfb715d7e56273330a54843/py/test/plugin/pytest_pdb.py
|
||||||
.. _`monkeypatch`: monkeypatch.html
|
.. _`monkeypatch`: monkeypatch.html
|
||||||
.. _`resultlog`: resultlog.html
|
.. _`resultlog`: resultlog.html
|
||||||
.. _`keyword`: keyword.html
|
.. _`keyword`: keyword.html
|
||||||
.. _`restdoc`: restdoc.html
|
.. _`restdoc`: restdoc.html
|
||||||
.. _`pytest_unittest.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_unittest.py
|
.. _`pytest_unittest.py`: http://bitbucket.org/hpk42/py-trunk/raw/caf81a2cdf5083be3bfb715d7e56273330a54843/py/test/plugin/pytest_unittest.py
|
||||||
.. _`doctest`: doctest.html
|
.. _`doctest`: doctest.html
|
||||||
.. _`pytest_resultlog.py`: http://bitbucket.org/hpk42/py-trunk/raw/3b3ea41060652c47739450a590c4d71625bc05bd/py/test/plugin/pytest_resultlog.py
|
.. _`pytest_resultlog.py`: http://bitbucket.org/hpk42/py-trunk/raw/caf81a2cdf5083be3bfb715d7e56273330a54843/py/test/plugin/pytest_resultlog.py
|
||||||
.. _`pdb`: pdb.html
|
.. _`pdb`: pdb.html
|
||||||
|
|
|
@ -4,7 +4,40 @@ Talks and Tutorials
|
||||||
|
|
||||||
.. _`funcargs`: funcargs.html
|
.. _`funcargs`: funcargs.html
|
||||||
|
|
||||||
a list of the latest talk and tutorial material:
|
tutorial examples and blog postings
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
function arguments:
|
||||||
|
|
||||||
|
- `application setup in test functions with funcargs`_ (doc link)
|
||||||
|
- `monkey patching done right`_ (blog post, consult `monkeypatch
|
||||||
|
plugin`_ for actual 1.0 API)
|
||||||
|
|
||||||
|
test parametrization:
|
||||||
|
|
||||||
|
- `generating parametrized tests with funcargs`_ (doc link)
|
||||||
|
- `parametrizing tests, generalized`_ (blog entry)
|
||||||
|
- `putting test-hooks into local or global plugins`_ (blog entry)
|
||||||
|
|
||||||
|
distributed testing:
|
||||||
|
|
||||||
|
- `simultanously test your code on all platforms`_ (blog entry)
|
||||||
|
|
||||||
|
plugins:
|
||||||
|
|
||||||
|
- usage examples are in most of the referenced `plugins`_ docs
|
||||||
|
|
||||||
|
.. _plugins: plugin/index.html
|
||||||
|
.. _`monkeypatch plugin`: plugin/monkeypatch.html
|
||||||
|
.. _`application setup in test functions with funcargs`: funcargs.html#appsetup
|
||||||
|
.. _`simultanously test your code on all platforms`: http://tetamap.wordpress.com/2009/03/23/new-simultanously-test-your-code-on-all-platforms/
|
||||||
|
.. _`monkey patching done right`: http://tetamap.wordpress.com/2009/03/03/monkeypatching-in-unit-tests-done-right/
|
||||||
|
.. _`putting test-hooks into local or global plugins`: http://tetamap.wordpress.com/2009/05/14/putting-test-hooks-into-local-and-global-plugins/
|
||||||
|
.. _`parametrizing tests, generalized`: http://tetamap.wordpress.com/2009/05/13/parametrizing-python-tests-generalized/
|
||||||
|
.. _`generating parametrized tests with funcargs`: funcargs.html#test-generators
|
||||||
|
|
||||||
|
conference talks and tutorials
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
- `ep2009-rapidtesting.pdf`_ tutorial slides (July 2009):
|
- `ep2009-rapidtesting.pdf`_ tutorial slides (July 2009):
|
||||||
|
|
||||||
|
|
|
@ -13,6 +13,8 @@ quickstart_: for getting started immediately.
|
||||||
|
|
||||||
features_: a walk through basic features and usage.
|
features_: a walk through basic features and usage.
|
||||||
|
|
||||||
|
`talks, tutorials, examples`_: tutorial examples, slides
|
||||||
|
|
||||||
`available plugins`_: list of py.test plugins
|
`available plugins`_: list of py.test plugins
|
||||||
|
|
||||||
funcargs_: powerful parametrized test function setup
|
funcargs_: powerful parametrized test function setup
|
||||||
|
@ -23,10 +25,9 @@ extend_: intro to extend and customize py.test runs
|
||||||
|
|
||||||
config_: ``conftest.py`` files and the config object
|
config_: ``conftest.py`` files and the config object
|
||||||
|
|
||||||
talks_: talk and tutorial slides
|
|
||||||
|
|
||||||
.. _`available plugins`: plugin/index.html
|
.. _`available plugins`: plugin/index.html
|
||||||
.. _talks: talks.html
|
.. _`talks, tutorials, examples`: talks.html
|
||||||
.. _quickstart: quickstart.html
|
.. _quickstart: quickstart.html
|
||||||
.. _features: features.html
|
.. _features: features.html
|
||||||
.. _funcargs: funcargs.html
|
.. _funcargs: funcargs.html
|
||||||
|
|
|
@ -20,7 +20,7 @@ For questions please check out http://pylib.org/contact.html
|
||||||
from initpkg import initpkg
|
from initpkg import initpkg
|
||||||
trunk = None
|
trunk = None
|
||||||
|
|
||||||
version = trunk or "1.0.0"
|
version = trunk or "1.0.1"
|
||||||
|
|
||||||
initpkg(__name__,
|
initpkg(__name__,
|
||||||
description = "py.test and pylib: advanced testing tool and networking lib",
|
description = "py.test and pylib: advanced testing tool and networking lib",
|
||||||
|
|
10
py/_com.py
10
py/_com.py
|
@ -17,6 +17,16 @@ class MultiCall:
|
||||||
self.kwargs = kwargs
|
self.kwargs = kwargs
|
||||||
self.results = []
|
self.results = []
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
args = []
|
||||||
|
if self.args:
|
||||||
|
args.append("posargs=%r" %(self.args,))
|
||||||
|
kw = self.kwargs
|
||||||
|
args.append(", ".join(["%s=%r" % x for x in self.kwargs.items()]))
|
||||||
|
args = " ".join(args)
|
||||||
|
status = "results: %r, rmethods: %r" % (self.results, self.methods)
|
||||||
|
return "<MultiCall %s %s>" %(args, status)
|
||||||
|
|
||||||
def execute(self, firstresult=False):
|
def execute(self, firstresult=False):
|
||||||
while self.methods:
|
while self.methods:
|
||||||
currentmethod = self.methods.pop()
|
currentmethod = self.methods.pop()
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
License for modules in py/compat directory
|
License for modules in py/compat directory
|
||||||
==============================================================
|
==============================================================
|
||||||
|
|
||||||
The "*.py" files in py/compat/ and subdirectories are are all
|
The "*.py" files in py/compat/ and subdirectories are all
|
||||||
- except when otherwise stated at the beginning of the file -
|
- except when otherwise stated at the beginning of the file -
|
||||||
copyrighted by the Python Software Foundation and licensed
|
copyrighted by the Python Software Foundation and licensed
|
||||||
under the Python Software License of which you can find a copy
|
under the Python Software License of which you can find a copy
|
||||||
|
|
|
@ -76,7 +76,7 @@ class StdCaptureFD(Capture):
|
||||||
os.close(fd)
|
os.close(fd)
|
||||||
if out:
|
if out:
|
||||||
tmpfile = None
|
tmpfile = None
|
||||||
if isinstance(out, file):
|
if hasattr(out, 'write'):
|
||||||
tmpfile = out
|
tmpfile = out
|
||||||
self.out = py.io.FDCapture(1, tmpfile=tmpfile)
|
self.out = py.io.FDCapture(1, tmpfile=tmpfile)
|
||||||
if patchsys:
|
if patchsys:
|
||||||
|
@ -84,7 +84,7 @@ class StdCaptureFD(Capture):
|
||||||
if err:
|
if err:
|
||||||
if mixed and out:
|
if mixed and out:
|
||||||
tmpfile = self.out.tmpfile
|
tmpfile = self.out.tmpfile
|
||||||
elif isinstance(err, file):
|
elif hasattr(err, 'write'):
|
||||||
tmpfile = err
|
tmpfile = err
|
||||||
else:
|
else:
|
||||||
tmpfile = None
|
tmpfile = None
|
||||||
|
|
|
@ -139,6 +139,7 @@ class TerminalWriter(object):
|
||||||
Black=40, Red=41, Green=42, Yellow=43,
|
Black=40, Red=41, Green=42, Yellow=43,
|
||||||
Blue=44, Purple=45, Cyan=46, White=47,
|
Blue=44, Purple=45, Cyan=46, White=47,
|
||||||
bold=1, light=2, blink=5, invert=7)
|
bold=1, light=2, blink=5, invert=7)
|
||||||
|
_encoding = "utf-8"
|
||||||
|
|
||||||
def __init__(self, file=None, stringio=False):
|
def __init__(self, file=None, stringio=False):
|
||||||
if file is None:
|
if file is None:
|
||||||
|
@ -194,58 +195,27 @@ class TerminalWriter(object):
|
||||||
|
|
||||||
def write(self, s, **kw):
|
def write(self, s, **kw):
|
||||||
if s:
|
if s:
|
||||||
s = str(s)
|
s = self._getbytestring(s)
|
||||||
if self.hasmarkup and kw:
|
if self.hasmarkup and kw:
|
||||||
s = self.markup(s, **kw)
|
s = self.markup(s, **kw)
|
||||||
self._file.write(s)
|
self._file.write(s)
|
||||||
self._file.flush()
|
self._file.flush()
|
||||||
|
|
||||||
|
def _getbytestring(self, s):
|
||||||
|
if isinstance(s, unicode):
|
||||||
|
return s.encode(self._encoding)
|
||||||
|
elif not isinstance(s, str):
|
||||||
|
return str(s)
|
||||||
|
return s
|
||||||
|
|
||||||
def line(self, s='', **kw):
|
def line(self, s='', **kw):
|
||||||
self.write(s, **kw)
|
self.write(s, **kw)
|
||||||
self.write('\n')
|
self.write('\n')
|
||||||
|
|
||||||
class Win32ConsoleWriter(object):
|
class Win32ConsoleWriter(TerminalWriter):
|
||||||
|
|
||||||
def __init__(self, file=None, stringio=False):
|
|
||||||
if file is None:
|
|
||||||
if stringio:
|
|
||||||
self.stringio = file = py.std.cStringIO.StringIO()
|
|
||||||
else:
|
|
||||||
file = py.std.sys.stdout
|
|
||||||
elif callable(file):
|
|
||||||
file = WriteFile(file)
|
|
||||||
self._file = file
|
|
||||||
self.fullwidth = get_terminal_width()
|
|
||||||
self.hasmarkup = should_do_markup(file)
|
|
||||||
|
|
||||||
def sep(self, sepchar, title=None, fullwidth=None, **kw):
|
|
||||||
if fullwidth is None:
|
|
||||||
fullwidth = self.fullwidth
|
|
||||||
# the goal is to have the line be as long as possible
|
|
||||||
# under the condition that len(line) <= fullwidth
|
|
||||||
if title is not None:
|
|
||||||
# we want 2 + 2*len(fill) + len(title) <= fullwidth
|
|
||||||
# i.e. 2 + 2*len(sepchar)*N + len(title) <= fullwidth
|
|
||||||
# 2*len(sepchar)*N <= fullwidth - len(title) - 2
|
|
||||||
# N <= (fullwidth - len(title) - 2) // (2*len(sepchar))
|
|
||||||
N = (fullwidth - len(title) - 2) // (2*len(sepchar))
|
|
||||||
fill = sepchar * N
|
|
||||||
line = "%s %s %s" % (fill, title, fill)
|
|
||||||
else:
|
|
||||||
# we want len(sepchar)*N <= fullwidth
|
|
||||||
# i.e. N <= fullwidth // len(sepchar)
|
|
||||||
line = sepchar * (fullwidth // len(sepchar))
|
|
||||||
# in some situations there is room for an extra sepchar at the right,
|
|
||||||
# in particular if we consider that with a sepchar like "_ " the
|
|
||||||
# trailing space is not important at the end of the line
|
|
||||||
if len(line) + len(sepchar.rstrip()) <= fullwidth:
|
|
||||||
line += sepchar.rstrip()
|
|
||||||
|
|
||||||
self.line(line, **kw)
|
|
||||||
|
|
||||||
def write(self, s, **kw):
|
def write(self, s, **kw):
|
||||||
if s:
|
if s:
|
||||||
s = str(s)
|
s = self._getbytestring(s)
|
||||||
if self.hasmarkup:
|
if self.hasmarkup:
|
||||||
handle = GetStdHandle(STD_OUTPUT_HANDLE)
|
handle = GetStdHandle(STD_OUTPUT_HANDLE)
|
||||||
|
|
||||||
|
@ -269,8 +239,8 @@ class Win32ConsoleWriter(object):
|
||||||
if self.hasmarkup:
|
if self.hasmarkup:
|
||||||
SetConsoleTextAttribute(handle, FOREGROUND_WHITE)
|
SetConsoleTextAttribute(handle, FOREGROUND_WHITE)
|
||||||
|
|
||||||
def line(self, s='', **kw):
|
def line(self, s="", **kw):
|
||||||
self.write(s + '\n', **kw)
|
self.write(s+"\n", **kw)
|
||||||
|
|
||||||
if sys.platform == 'win32':
|
if sys.platform == 'win32':
|
||||||
TerminalWriter = Win32ConsoleWriter
|
TerminalWriter = Win32ConsoleWriter
|
||||||
|
|
|
@ -37,6 +37,16 @@ class BaseTests:
|
||||||
assert len(l) == 1
|
assert len(l) == 1
|
||||||
assert l[0] == "hello\n"
|
assert l[0] == "hello\n"
|
||||||
|
|
||||||
|
def test_line_unicode(self):
|
||||||
|
tw = self.getwriter()
|
||||||
|
for encoding in 'utf8', 'latin1':
|
||||||
|
tw._encoding = encoding
|
||||||
|
msg = unicode('b\u00f6y', 'utf8')
|
||||||
|
tw.line(msg)
|
||||||
|
l = self.getlines()
|
||||||
|
assert not isinstance(l[0], unicode)
|
||||||
|
assert unicode(l[0], encoding) == msg + "\n"
|
||||||
|
|
||||||
def test_sep_no_title(self):
|
def test_sep_no_title(self):
|
||||||
tw = self.getwriter()
|
tw = self.getwriter()
|
||||||
tw.sep("-", fullwidth=60)
|
tw.sep("-", fullwidth=60)
|
||||||
|
@ -85,6 +95,16 @@ class BaseTests:
|
||||||
l = self.getlines()
|
l = self.getlines()
|
||||||
assert len(l[0]) == len(l[1])
|
assert len(l[0]) == len(l[1])
|
||||||
|
|
||||||
|
class TestTmpfile(BaseTests):
|
||||||
|
def getwriter(self):
|
||||||
|
self.path = py.test.config.ensuretemp("terminalwriter").ensure("tmpfile")
|
||||||
|
self.tw = py.io.TerminalWriter(self.path.open('w+'))
|
||||||
|
return self.tw
|
||||||
|
def getlines(self):
|
||||||
|
io = self.tw._file
|
||||||
|
io.flush()
|
||||||
|
return self.path.open('r').readlines()
|
||||||
|
|
||||||
class TestStringIO(BaseTests):
|
class TestStringIO(BaseTests):
|
||||||
def getwriter(self):
|
def getwriter(self):
|
||||||
self.tw = py.io.TerminalWriter(stringio=True)
|
self.tw = py.io.TerminalWriter(stringio=True)
|
||||||
|
|
|
@ -10,6 +10,7 @@ class TestMultiCall:
|
||||||
def test_uses_copy_of_methods(self):
|
def test_uses_copy_of_methods(self):
|
||||||
l = [lambda: 42]
|
l = [lambda: 42]
|
||||||
mc = MultiCall(l)
|
mc = MultiCall(l)
|
||||||
|
repr(mc)
|
||||||
l[:] = []
|
l[:] = []
|
||||||
res = mc.execute()
|
res = mc.execute()
|
||||||
return res == 42
|
return res == 42
|
||||||
|
@ -33,16 +34,27 @@ class TestMultiCall:
|
||||||
p1 = P1()
|
p1 = P1()
|
||||||
p2 = P2()
|
p2 = P2()
|
||||||
multicall = MultiCall([p1.m, p2.m], 23)
|
multicall = MultiCall([p1.m, p2.m], 23)
|
||||||
|
assert "23" in repr(multicall)
|
||||||
reslist = multicall.execute()
|
reslist = multicall.execute()
|
||||||
assert len(reslist) == 2
|
assert len(reslist) == 2
|
||||||
# ensure reversed order
|
# ensure reversed order
|
||||||
assert reslist == [23, 17]
|
assert reslist == [23, 17]
|
||||||
|
|
||||||
|
def test_keyword_args(self):
|
||||||
|
def f(x):
|
||||||
|
return x + 1
|
||||||
|
multicall = MultiCall([f], x=23)
|
||||||
|
assert "x=23" in repr(multicall)
|
||||||
|
reslist = multicall.execute()
|
||||||
|
assert reslist == [24]
|
||||||
|
assert "24" in repr(multicall)
|
||||||
|
|
||||||
def test_optionalcallarg(self):
|
def test_optionalcallarg(self):
|
||||||
class P1:
|
class P1:
|
||||||
def m(self, x):
|
def m(self, x):
|
||||||
return x
|
return x
|
||||||
call = MultiCall([P1().m], 23)
|
call = MultiCall([P1().m], 23)
|
||||||
|
assert "23" in repr(call)
|
||||||
assert call.execute() == [23]
|
assert call.execute() == [23]
|
||||||
assert call.execute(firstresult=True) == 23
|
assert call.execute(firstresult=True) == 23
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@ Collectors and test Items form a tree
|
||||||
that is usually built iteratively.
|
that is usually built iteratively.
|
||||||
"""
|
"""
|
||||||
import py
|
import py
|
||||||
|
pydir = py.path.local(py.__file__).dirpath()
|
||||||
|
|
||||||
def configproperty(name):
|
def configproperty(name):
|
||||||
def fget(self):
|
def fget(self):
|
||||||
|
@ -166,16 +167,13 @@ class Node(object):
|
||||||
if colitem.fspath == fspath or colitem.name == basename:
|
if colitem.fspath == fspath or colitem.name == basename:
|
||||||
l.append(colitem)
|
l.append(colitem)
|
||||||
if not l:
|
if not l:
|
||||||
msg = ("Collector %r does not provide %r colitem "
|
raise self.config.Error("can't collect: %s" %(fspath,))
|
||||||
"existing colitems are: %s" %
|
|
||||||
(cur, fspath, colitems))
|
|
||||||
raise AssertionError(msg)
|
|
||||||
if basenames:
|
if basenames:
|
||||||
if len(l) > 1:
|
if len(l) > 1:
|
||||||
msg = ("Collector %r has more than one %r colitem "
|
msg = ("Collector %r has more than one %r colitem "
|
||||||
"existing colitems are: %s" %
|
"existing colitems are: %s" %
|
||||||
(cur, fspath, colitems))
|
(cur, fspath, colitems))
|
||||||
raise AssertionError(msg)
|
raise self.config.Error("xxx-too many test types for: %s" % (fspath, ))
|
||||||
cur = l[0]
|
cur = l[0]
|
||||||
else:
|
else:
|
||||||
if len(l) > 1:
|
if len(l) > 1:
|
||||||
|
@ -332,6 +330,15 @@ class Collector(Node):
|
||||||
"""
|
"""
|
||||||
return self.collect_by_name(name)
|
return self.collect_by_name(name)
|
||||||
|
|
||||||
|
def _prunetraceback(self, traceback):
|
||||||
|
if hasattr(self, 'fspath'):
|
||||||
|
path = self.fspath
|
||||||
|
ntraceback = traceback.cut(path=self.fspath)
|
||||||
|
if ntraceback == traceback:
|
||||||
|
ntraceback = ntraceback.cut(excludepath=pydir)
|
||||||
|
traceback = ntraceback.filter()
|
||||||
|
return traceback
|
||||||
|
|
||||||
class FSCollector(Collector):
|
class FSCollector(Collector):
|
||||||
def __init__(self, fspath, parent=None):
|
def __init__(self, fspath, parent=None):
|
||||||
fspath = py.path.local(fspath)
|
fspath = py.path.local(fspath)
|
||||||
|
|
|
@ -145,11 +145,9 @@ class SlaveNode(object):
|
||||||
if call.excinfo:
|
if call.excinfo:
|
||||||
# likely it is not collectable here because of
|
# likely it is not collectable here because of
|
||||||
# platform/import-dependency induced skips
|
# platform/import-dependency induced skips
|
||||||
# XXX somewhat ugly shortcuts - also makes a collection
|
# we fake a setup-error report with the obtained exception
|
||||||
# failure into an ItemTestReport - this might confuse
|
# and do not care about capturing or non-runner hooks
|
||||||
# pytest_runtest_logreport hooks
|
|
||||||
rep = self.runner.pytest_runtest_makereport(item=item, call=call)
|
rep = self.runner.pytest_runtest_makereport(item=item, call=call)
|
||||||
self.pytest_runtest_logreport(rep)
|
self.pytest_runtest_logreport(rep)
|
||||||
return
|
return
|
||||||
item.config.hook.pytest_runtest_protocol(item=item)
|
item.config.hook.pytest_runtest_protocol(item=item)
|
||||||
|
|
||||||
|
|
|
@ -91,7 +91,7 @@ def pytest__teardown_final(session):
|
||||||
""" called before test session finishes. """
|
""" called before test session finishes. """
|
||||||
pytest__teardown_final.firstresult = True
|
pytest__teardown_final.firstresult = True
|
||||||
|
|
||||||
def pytest__teardown_final_logerror(rep):
|
def pytest__teardown_final_logerror(report):
|
||||||
""" called if runtest_teardown_final failed. """
|
""" called if runtest_teardown_final failed. """
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
@ -108,8 +108,8 @@ def pytest_sessionfinish(session, exitstatus):
|
||||||
# hooks for influencing reporting (invoked from pytest_terminal)
|
# hooks for influencing reporting (invoked from pytest_terminal)
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
def pytest_report_teststatus(rep):
|
def pytest_report_teststatus(report):
|
||||||
""" return shortletter and verbose word. """
|
""" return result-category, shortletter and verbose word for reporting."""
|
||||||
pytest_report_teststatus.firstresult = True
|
pytest_report_teststatus.firstresult = True
|
||||||
|
|
||||||
def pytest_terminal_summary(terminalreporter):
|
def pytest_terminal_summary(terminalreporter):
|
||||||
|
|
|
@ -107,11 +107,24 @@ class CaptureManager:
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self._method2capture = {}
|
self._method2capture = {}
|
||||||
|
|
||||||
|
def _maketempfile(self):
|
||||||
|
f = py.std.tempfile.TemporaryFile()
|
||||||
|
newf = py.io.dupfile(f)
|
||||||
|
f.close()
|
||||||
|
return ustream(newf)
|
||||||
|
|
||||||
|
def _makestringio(self):
|
||||||
|
return py.std.StringIO.StringIO()
|
||||||
|
|
||||||
def _startcapture(self, method):
|
def _startcapture(self, method):
|
||||||
if method == "fd":
|
if method == "fd":
|
||||||
return py.io.StdCaptureFD()
|
return py.io.StdCaptureFD(
|
||||||
|
out=self._maketempfile(), err=self._maketempfile()
|
||||||
|
)
|
||||||
elif method == "sys":
|
elif method == "sys":
|
||||||
return py.io.StdCapture()
|
return py.io.StdCapture(
|
||||||
|
out=self._makestringio(), err=self._makestringio()
|
||||||
|
)
|
||||||
else:
|
else:
|
||||||
raise ValueError("unknown capturing method: %r" % method)
|
raise ValueError("unknown capturing method: %r" % method)
|
||||||
|
|
||||||
|
@ -252,3 +265,13 @@ class CaptureFuncarg:
|
||||||
def close(self):
|
def close(self):
|
||||||
self.capture.reset()
|
self.capture.reset()
|
||||||
del self.capture
|
del self.capture
|
||||||
|
|
||||||
|
def ustream(f):
|
||||||
|
import codecs
|
||||||
|
encoding = getattr(f, 'encoding', None) or "UTF-8"
|
||||||
|
reader = codecs.getreader(encoding)
|
||||||
|
writer = codecs.getwriter(encoding)
|
||||||
|
srw = codecs.StreamReaderWriter(f, reader, writer)
|
||||||
|
srw.encoding = encoding
|
||||||
|
return srw
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ def pytest_sessionfinish(session, exitstatus):
|
||||||
hook = session.config.hook
|
hook = session.config.hook
|
||||||
rep = hook.pytest__teardown_final(session=session)
|
rep = hook.pytest__teardown_final(session=session)
|
||||||
if rep:
|
if rep:
|
||||||
hook.pytest__teardown_final_logerror(rep=rep)
|
hook.pytest__teardown_final_logerror(report=rep)
|
||||||
|
|
||||||
def pytest_make_collect_report(collector):
|
def pytest_make_collect_report(collector):
|
||||||
result = excinfo = None
|
result = excinfo = None
|
||||||
|
@ -72,12 +72,12 @@ def pytest__teardown_final(session):
|
||||||
rep = TeardownErrorReport(call.excinfo)
|
rep = TeardownErrorReport(call.excinfo)
|
||||||
return rep
|
return rep
|
||||||
|
|
||||||
def pytest_report_teststatus(rep):
|
def pytest_report_teststatus(report):
|
||||||
if rep.when in ("setup", "teardown"):
|
if report.when in ("setup", "teardown"):
|
||||||
if rep.failed:
|
if report.failed:
|
||||||
# category, shortletter, verbose-word
|
# category, shortletter, verbose-word
|
||||||
return "error", "E", "ERROR"
|
return "error", "E", "ERROR"
|
||||||
elif rep.skipped:
|
elif report.skipped:
|
||||||
return "skipped", "s", "SKIPPED"
|
return "skipped", "s", "SKIPPED"
|
||||||
else:
|
else:
|
||||||
return "", "", ""
|
return "", "", ""
|
||||||
|
@ -108,6 +108,13 @@ class CallInfo:
|
||||||
except:
|
except:
|
||||||
self.excinfo = py.code.ExceptionInfo()
|
self.excinfo = py.code.ExceptionInfo()
|
||||||
|
|
||||||
|
def __repr__(self):
|
||||||
|
if self.excinfo:
|
||||||
|
status = "exception: %s" % str(self.excinfo.value)
|
||||||
|
else:
|
||||||
|
status = "result: %r" % (self.result,)
|
||||||
|
return "<CallInfo when=%r %s>" % (self.when, status)
|
||||||
|
|
||||||
def forked_run_report(item):
|
def forked_run_report(item):
|
||||||
# for now, we run setup/teardown in the subprocess
|
# for now, we run setup/teardown in the subprocess
|
||||||
# XXX optionally allow sharing of setup/teardown
|
# XXX optionally allow sharing of setup/teardown
|
||||||
|
|
|
@ -82,7 +82,7 @@ class TerminalReporter:
|
||||||
self._tw.sep(sep, title, **markup)
|
self._tw.sep(sep, title, **markup)
|
||||||
|
|
||||||
def getcategoryletterword(self, rep):
|
def getcategoryletterword(self, rep):
|
||||||
res = self.config.hook.pytest_report_teststatus(rep=rep)
|
res = self.config.hook.pytest_report_teststatus(report=rep)
|
||||||
if res:
|
if res:
|
||||||
return res
|
return res
|
||||||
for cat in 'skipped failed passed ???'.split():
|
for cat in 'skipped failed passed ???'.split():
|
||||||
|
@ -184,8 +184,8 @@ class TerminalReporter:
|
||||||
fspath, lineno, msg = self._getreportinfo(item)
|
fspath, lineno, msg = self._getreportinfo(item)
|
||||||
self.write_fspath_result(fspath, "")
|
self.write_fspath_result(fspath, "")
|
||||||
|
|
||||||
def pytest__teardown_final_logerror(self, rep):
|
def pytest__teardown_final_logerror(self, report):
|
||||||
self.stats.setdefault("error", []).append(rep)
|
self.stats.setdefault("error", []).append(report)
|
||||||
|
|
||||||
def pytest_runtest_logreport(self, report):
|
def pytest_runtest_logreport(self, report):
|
||||||
rep = report
|
rep = report
|
||||||
|
|
|
@ -35,12 +35,11 @@ def pytest_runtest_makereport(__call__, item, call):
|
||||||
res.failed = True
|
res.failed = True
|
||||||
return res
|
return res
|
||||||
|
|
||||||
def pytest_report_teststatus(rep):
|
def pytest_report_teststatus(report):
|
||||||
""" return shortletter and verbose word. """
|
if 'xfail' in report.keywords:
|
||||||
if 'xfail' in rep.keywords:
|
if report.skipped:
|
||||||
if rep.skipped:
|
|
||||||
return "xfailed", "x", "xfail"
|
return "xfailed", "x", "xfail"
|
||||||
elif rep.failed:
|
elif report.failed:
|
||||||
return "xpassed", "P", "xpass"
|
return "xpassed", "P", "xpass"
|
||||||
|
|
||||||
# called by the terminalreporter instance/plugin
|
# called by the terminalreporter instance/plugin
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
import py, os, sys
|
import py, os, sys
|
||||||
from py.__.test.plugin.pytest_capture import CaptureManager
|
from py.__.test.plugin.pytest_capture import CaptureManager, ustream
|
||||||
|
|
||||||
class TestCaptureManager:
|
class TestCaptureManager:
|
||||||
|
|
||||||
|
@ -54,6 +54,29 @@ class TestCaptureManager:
|
||||||
finally:
|
finally:
|
||||||
capouter.reset()
|
capouter.reset()
|
||||||
|
|
||||||
|
@py.test.mark.multi(method=['fd', 'sys'])
|
||||||
|
def test_capturing_unicode(testdir, method):
|
||||||
|
testdir.makepyfile("""
|
||||||
|
# taken from issue 227 from nosests
|
||||||
|
def test_unicode():
|
||||||
|
import sys
|
||||||
|
print sys.stdout
|
||||||
|
print u'b\\u00f6y'
|
||||||
|
""")
|
||||||
|
result = testdir.runpytest("--capture=%s" % method)
|
||||||
|
result.stdout.fnmatch_lines([
|
||||||
|
"*1 passed*"
|
||||||
|
])
|
||||||
|
|
||||||
|
def test_ustream_helper(testdir):
|
||||||
|
p = testdir.makepyfile("hello")
|
||||||
|
f = p.open('w')
|
||||||
|
#f.encoding = "utf8"
|
||||||
|
x = ustream(f)
|
||||||
|
x.write(u'b\\00f6y')
|
||||||
|
x.close()
|
||||||
|
|
||||||
|
|
||||||
def test_collect_capturing(testdir):
|
def test_collect_capturing(testdir):
|
||||||
p = testdir.makepyfile("""
|
p = testdir.makepyfile("""
|
||||||
print "collect %s failure" % 13
|
print "collect %s failure" % 13
|
||||||
|
|
|
@ -271,3 +271,13 @@ def test_functional_boxed(testdir):
|
||||||
"*1 failed*"
|
"*1 failed*"
|
||||||
])
|
])
|
||||||
|
|
||||||
|
def test_callinfo():
|
||||||
|
ci = runner.CallInfo(lambda: 0, '123')
|
||||||
|
assert ci.when == "123"
|
||||||
|
assert ci.result == 0
|
||||||
|
assert "result" in repr(ci)
|
||||||
|
ci = runner.CallInfo(lambda: 0/0, '123')
|
||||||
|
assert ci.when == "123"
|
||||||
|
assert not hasattr(ci, 'result')
|
||||||
|
assert ci.excinfo
|
||||||
|
assert "exc" in repr(ci)
|
||||||
|
|
|
@ -125,18 +125,12 @@ def test_func_generator_setup(testdir):
|
||||||
def test_method_setup_uses_fresh_instances(testdir):
|
def test_method_setup_uses_fresh_instances(testdir):
|
||||||
reprec = testdir.inline_runsource("""
|
reprec = testdir.inline_runsource("""
|
||||||
class TestSelfState1:
|
class TestSelfState1:
|
||||||
def __init__(self):
|
memory = []
|
||||||
self.hello = 42
|
|
||||||
def test_hello(self):
|
def test_hello(self):
|
||||||
self.world = 23
|
self.memory.append(self)
|
||||||
def test_afterhello(self):
|
|
||||||
assert not hasattr(self, 'world')
|
def test_afterhello(self):
|
||||||
assert self.hello == 42
|
assert self != self.memory[0]
|
||||||
class TestSelfState2:
|
""")
|
||||||
def test_hello(self):
|
reprec.assertoutcome(passed=2, failed=0)
|
||||||
self.world = 10
|
|
||||||
def test_world(self):
|
|
||||||
assert not hasattr(self, 'world')
|
|
||||||
""")
|
|
||||||
reprec.assertoutcome(passed=4, failed=0)
|
|
||||||
|
|
||||||
|
|
|
@ -123,8 +123,7 @@ class PyCollectorMixin(PyobjMixin, py.test.collect.Collector):
|
||||||
collector=self, name=name, obj=obj)
|
collector=self, name=name, obj=obj)
|
||||||
if res is not None:
|
if res is not None:
|
||||||
return res
|
return res
|
||||||
if (self.classnamefilter(name)) and \
|
if self._istestclasscandidate(name, obj):
|
||||||
py.std.inspect.isclass(obj):
|
|
||||||
res = self._deprecated_join(name)
|
res = self._deprecated_join(name)
|
||||||
if res is not None:
|
if res is not None:
|
||||||
return res
|
return res
|
||||||
|
@ -139,14 +138,25 @@ class PyCollectorMixin(PyobjMixin, py.test.collect.Collector):
|
||||||
else:
|
else:
|
||||||
return self._genfunctions(name, obj)
|
return self._genfunctions(name, obj)
|
||||||
|
|
||||||
|
def _istestclasscandidate(self, name, obj):
|
||||||
|
if self.classnamefilter(name) and \
|
||||||
|
py.std.inspect.isclass(obj):
|
||||||
|
if hasinit(obj):
|
||||||
|
# XXX WARN
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def _genfunctions(self, name, funcobj):
|
def _genfunctions(self, name, funcobj):
|
||||||
module = self.getparent(Module).obj
|
module = self.getparent(Module).obj
|
||||||
# due to _buildname2items funcobj is the raw function, we need
|
# due to _buildname2items funcobj is the raw function, we need
|
||||||
# to work to get at the class
|
# to work to get at the class
|
||||||
clscol = self.getparent(Class)
|
clscol = self.getparent(Class)
|
||||||
cls = clscol and clscol.obj or None
|
cls = clscol and clscol.obj or None
|
||||||
metafunc = funcargs.Metafunc(funcobj, config=self.config, cls=cls, module=module)
|
metafunc = funcargs.Metafunc(funcobj, config=self.config,
|
||||||
gentesthook = self.config.hook.pytest_generate_tests.clone(extralookup=module)
|
cls=cls, module=module)
|
||||||
|
gentesthook = self.config.hook.pytest_generate_tests.clone(
|
||||||
|
extralookup=module)
|
||||||
gentesthook(metafunc=metafunc)
|
gentesthook(metafunc=metafunc)
|
||||||
if not metafunc._calls:
|
if not metafunc._calls:
|
||||||
return self.Function(name, parent=self)
|
return self.Function(name, parent=self)
|
||||||
|
@ -371,3 +381,9 @@ class Function(FunctionMixin, py.test.collect.Item):
|
||||||
def __ne__(self, other):
|
def __ne__(self, other):
|
||||||
return not self == other
|
return not self == other
|
||||||
|
|
||||||
|
|
||||||
|
def hasinit(obj):
|
||||||
|
init = getattr(obj, '__init__', None)
|
||||||
|
if init:
|
||||||
|
if not isinstance(init, type(object.__init__)):
|
||||||
|
return True
|
||||||
|
|
|
@ -67,3 +67,12 @@ class TestGeneralUsage:
|
||||||
"E ImportError: No module named does_not_work",
|
"E ImportError: No module named does_not_work",
|
||||||
])
|
])
|
||||||
assert result.ret == 1
|
assert result.ret == 1
|
||||||
|
|
||||||
|
def test_not_collectable_arguments(self, testdir):
|
||||||
|
p1 = testdir.makepyfile("")
|
||||||
|
p2 = testdir.makefile(".pyc", "123")
|
||||||
|
result = testdir.runpytest(p1, p2)
|
||||||
|
assert result.ret != 0
|
||||||
|
assert result.stderr.fnmatch_lines([
|
||||||
|
"*ERROR: can't collect: %s" %(p2,)
|
||||||
|
])
|
||||||
|
|
|
@ -179,6 +179,18 @@ class TestCollectPluginHooks:
|
||||||
names = [rep.collector.name for rep in colreports]
|
names = [rep.collector.name for rep in colreports]
|
||||||
assert names.count("hello") == 1
|
assert names.count("hello") == 1
|
||||||
|
|
||||||
|
class TestPrunetraceback:
|
||||||
|
def test_collection_error(self, testdir):
|
||||||
|
p = testdir.makepyfile("""
|
||||||
|
import not_exists
|
||||||
|
""")
|
||||||
|
result = testdir.runpytest(p)
|
||||||
|
assert "__import__" not in result.stdout.str(), "too long traceback"
|
||||||
|
result.stdout.fnmatch_lines([
|
||||||
|
"*ERROR during collection*",
|
||||||
|
">*import not_exists*"
|
||||||
|
])
|
||||||
|
|
||||||
class TestCustomConftests:
|
class TestCustomConftests:
|
||||||
def test_non_python_files(self, testdir):
|
def test_non_python_files(self, testdir):
|
||||||
testdir.makepyfile(conftest="""
|
testdir.makepyfile(conftest="""
|
||||||
|
|
|
@ -39,6 +39,19 @@ 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 TestClass:
|
||||||
|
def test_class_with_init_not_collected(self, testdir):
|
||||||
|
modcol = testdir.getmodulecol("""
|
||||||
|
class TestClass1:
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
class TestClass2(object):
|
||||||
|
def __init__(self):
|
||||||
|
pass
|
||||||
|
""")
|
||||||
|
l = modcol.collect()
|
||||||
|
assert len(l) == 0
|
||||||
|
|
||||||
class TestDisabled:
|
class TestDisabled:
|
||||||
def test_disabled_module(self, testdir):
|
def test_disabled_module(self, testdir):
|
||||||
modcol = testdir.getmodulecol("""
|
modcol = testdir.getmodulecol("""
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -31,7 +31,7 @@ def main():
|
||||||
name='py',
|
name='py',
|
||||||
description='py.test and pylib: advanced testing tool and networking lib',
|
description='py.test and pylib: advanced testing tool and networking lib',
|
||||||
long_description = long_description,
|
long_description = long_description,
|
||||||
version= trunk or '1.0.0',
|
version= trunk or '1.0.1',
|
||||||
url='http://pylib.org',
|
url='http://pylib.org',
|
||||||
license='MIT license',
|
license='MIT license',
|
||||||
platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
|
platforms=['unix', 'linux', 'osx', 'cygwin', 'win32'],
|
||||||
|
|
Loading…
Reference in New Issue