remove trailing whitespace everywhere
--HG-- branch : trunk
This commit is contained in:
parent
1693b9c407
commit
677f7c0a6a
|
@ -4,6 +4,8 @@ Changes between 1.3.2 and 1.3.3a1
|
||||||
- fix weirdness: make terminal width detection work on stdout instead of stdin
|
- fix weirdness: make terminal width detection work on stdout instead of stdin
|
||||||
(thanks Armin Ronacher for reporting)
|
(thanks Armin Ronacher for reporting)
|
||||||
|
|
||||||
|
- remove trailing whitespace in all py/text files
|
||||||
|
|
||||||
Changes between 1.3.1 and 1.3.2
|
Changes between 1.3.1 and 1.3.2
|
||||||
==================================================
|
==================================================
|
||||||
|
|
||||||
|
|
168
ISSUES.txt
168
ISSUES.txt
|
@ -1,78 +1,78 @@
|
||||||
refine session initialization / fix custom collect crash
|
refine session initialization / fix custom collect crash
|
||||||
---------------------------------------------------------------
|
---------------------------------------------------------------
|
||||||
tags: bug 1.4 core xdist
|
tags: bug 1.4 core xdist
|
||||||
|
|
||||||
When calling "py.test path/X" py.test can crash if the collection
|
When calling "py.test path/X" py.test can crash if the collection
|
||||||
of that directory is skipped. Calling "py.test path" will give
|
of that directory is skipped. Calling "py.test path" will give
|
||||||
proper output. The reason is that for the very first colitems
|
proper output. The reason is that for the very first colitems
|
||||||
getinitialnodes() and a collection is done before the fully
|
getinitialnodes() and a collection is done before the fully
|
||||||
controlled session and pytest_make_collect_report protocol takes over.
|
controlled session and pytest_make_collect_report protocol takes over.
|
||||||
Try to remove the redundant getinitialnodes related logic and amend
|
Try to remove the redundant getinitialnodes related logic and amend
|
||||||
the session collect logic to care for this "initial" case as well.
|
the session collect logic to care for this "initial" case as well.
|
||||||
Apart from simplification a side effect the dsession's session
|
Apart from simplification a side effect the dsession's session
|
||||||
and the core session probably converge some more.
|
and the core session probably converge some more.
|
||||||
|
|
||||||
do early-teardown of test modules
|
do early-teardown of test modules
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
tags: feature 1.3
|
tags: feature 1.3
|
||||||
|
|
||||||
currently teardowns are called when the next tests is setup
|
currently teardowns are called when the next tests is setup
|
||||||
except for the function/method level where interally
|
except for the function/method level where interally
|
||||||
"teardown_exact" tears down immediately. Generalize
|
"teardown_exact" tears down immediately. Generalize
|
||||||
this to perform the "neccessary" teardown compared to
|
this to perform the "neccessary" teardown compared to
|
||||||
the "next" test item during teardown - this should
|
the "next" test item during teardown - this should
|
||||||
get rid of some irritations because otherwise e.g.
|
get rid of some irritations because otherwise e.g.
|
||||||
prints of teardown-code appear in the setup of the next test.
|
prints of teardown-code appear in the setup of the next test.
|
||||||
|
|
||||||
consider and document __init__ file usage in test directories
|
consider and document __init__ file usage in test directories
|
||||||
---------------------------------------------------------------
|
---------------------------------------------------------------
|
||||||
tags: bug 1.4 core
|
tags: bug 1.4 core
|
||||||
|
|
||||||
Currently, a test module is imported with its fully qualified
|
Currently, a test module is imported with its fully qualified
|
||||||
package path, determined by checking __init__ files upwards.
|
package path, determined by checking __init__ files upwards.
|
||||||
This has the side effect that a source package at the root
|
This has the side effect that a source package at the root
|
||||||
of the test dir could be imported as well. This is somewhat
|
of the test dir could be imported as well. This is somewhat
|
||||||
convenient but complicates the picture for running tests against
|
convenient but complicates the picture for running tests against
|
||||||
different versions of a package. Also, implicit sys.path
|
different versions of a package. Also, implicit sys.path
|
||||||
manipulations are problematic per-se. Maybe factorting out
|
manipulations are problematic per-se. Maybe factorting out
|
||||||
a pytest_addsyspath hook which can be disabled from the command line
|
a pytest_addsyspath hook which can be disabled from the command line
|
||||||
makes sense. In any case documentation/recommendations for
|
makes sense. In any case documentation/recommendations for
|
||||||
certain scenarios makes sense.
|
certain scenarios makes sense.
|
||||||
|
|
||||||
relax requirement to have tests/testing contain an __init__
|
relax requirement to have tests/testing contain an __init__
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
tags: feature 1.4
|
tags: feature 1.4
|
||||||
bb: http://bitbucket.org/hpk42/py-trunk/issue/64
|
bb: http://bitbucket.org/hpk42/py-trunk/issue/64
|
||||||
|
|
||||||
A local test run of a "tests" directory may work
|
A local test run of a "tests" directory may work
|
||||||
but a remote one fail because the tests directory
|
but a remote one fail because the tests directory
|
||||||
does not contain an "__init__.py". Either give
|
does not contain an "__init__.py". Either give
|
||||||
an error or make it work without the __init__.py
|
an error or make it work without the __init__.py
|
||||||
i.e. port the nose-logic of unloading a test module.
|
i.e. port the nose-logic of unloading a test module.
|
||||||
|
|
||||||
customize test function collection
|
customize test function collection
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
tags: feature 1.4
|
tags: feature 1.4
|
||||||
|
|
||||||
- introduce py.test.mark.nocollect for not considering a function for
|
- introduce py.test.mark.nocollect for not considering a function for
|
||||||
test collection at all. maybe also introduce a py.test.mark.test to
|
test collection at all. maybe also introduce a py.test.mark.test to
|
||||||
explicitely mark a function to become a tested one. Lookup JUnit ways
|
explicitely mark a function to become a tested one. Lookup JUnit ways
|
||||||
of tagging tests.
|
of tagging tests.
|
||||||
|
|
||||||
- allow an easy way to customize "test_", "Test" prefixes for file paths
|
- allow an easy way to customize "test_", "Test" prefixes for file paths
|
||||||
and test function/class names. the current customizable Item requires
|
and test function/class names. the current customizable Item requires
|
||||||
too much code/concepts to influence this collection matching.
|
too much code/concepts to influence this collection matching.
|
||||||
maybe introduce pytest_pycollect_filters = {
|
maybe introduce pytest_pycollect_filters = {
|
||||||
'file': 'test*.py',
|
'file': 'test*.py',
|
||||||
'function': 'test*',
|
'function': 'test*',
|
||||||
'class': 'Test*',
|
'class': 'Test*',
|
||||||
}
|
}
|
||||||
|
|
||||||
introduce py.test.mark.platform
|
introduce py.test.mark.platform
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
tags: feature 1.4
|
tags: feature 1.4
|
||||||
|
|
||||||
Introduce nice-to-spell platform-skipping, examples:
|
Introduce nice-to-spell platform-skipping, examples:
|
||||||
|
|
||||||
@py.test.mark.platform("python3")
|
@py.test.mark.platform("python3")
|
||||||
@py.test.mark.platform("not python3")
|
@py.test.mark.platform("not python3")
|
||||||
|
@ -82,8 +82,8 @@ Introduce nice-to-spell platform-skipping, examples:
|
||||||
@py.test.mark.platform("not (jython and win32)", xfail=True)
|
@py.test.mark.platform("not (jython and win32)", xfail=True)
|
||||||
|
|
||||||
etc. Idea is to allow Python expressions which can operate
|
etc. Idea is to allow Python expressions which can operate
|
||||||
on common spellings for operating systems and python
|
on common spellings for operating systems and python
|
||||||
interpreter versions.
|
interpreter versions.
|
||||||
|
|
||||||
introduce py.test.mark registration
|
introduce py.test.mark registration
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
@ -92,73 +92,73 @@ tags: feature 1.4
|
||||||
introduce a hook that allows to register a named mark decorator
|
introduce a hook that allows to register a named mark decorator
|
||||||
with documentation and add "py.test --marks" to get
|
with documentation and add "py.test --marks" to get
|
||||||
a list of available marks. Deprecate "dynamic" mark
|
a list of available marks. Deprecate "dynamic" mark
|
||||||
definitions.
|
definitions.
|
||||||
|
|
||||||
allow to non-intrusively apply skipfs/xfail/marks
|
allow to non-intrusively apply skipfs/xfail/marks
|
||||||
---------------------------------------------------
|
---------------------------------------------------
|
||||||
tags: feature 1.4
|
tags: feature 1.4
|
||||||
|
|
||||||
use case: mark a module or directory structures
|
use case: mark a module or directory structures
|
||||||
to be skipped on certain platforms (i.e. no import
|
to be skipped on certain platforms (i.e. no import
|
||||||
attempt will be made).
|
attempt will be made).
|
||||||
|
|
||||||
consider introducing a hook/mechanism that allows to apply marks
|
consider introducing a hook/mechanism that allows to apply marks
|
||||||
from conftests or plugins.
|
from conftests or plugins.
|
||||||
|
|
||||||
explicit referencing of conftest.py files
|
explicit referencing of conftest.py files
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
tags: feature 1.4
|
tags: feature 1.4
|
||||||
|
|
||||||
allow to name conftest.py files (in sub directories) that should
|
allow to name conftest.py files (in sub directories) that should
|
||||||
be imported early, as to include command line options.
|
be imported early, as to include command line options.
|
||||||
|
|
||||||
a central py.test ini/yml file
|
a central py.test ini/yml file
|
||||||
----------------------------------
|
----------------------------------
|
||||||
tags: feature 1.4
|
tags: feature 1.4
|
||||||
|
|
||||||
introduce a declarative configuration file that allows:
|
introduce a declarative configuration file that allows:
|
||||||
- default options
|
- default options
|
||||||
- to-be-collected test directories
|
- to-be-collected test directories
|
||||||
- required plugins
|
- required plugins
|
||||||
- test func/class/file matching patterns
|
- test func/class/file matching patterns
|
||||||
- skip/xfail (non-intrusive)
|
- skip/xfail (non-intrusive)
|
||||||
- pytest.ini and tox.ini and setup.cfg configuration in the same file
|
- pytest.ini and tox.ini and setup.cfg configuration in the same file
|
||||||
|
|
||||||
new documentation
|
new documentation
|
||||||
----------------------------------
|
----------------------------------
|
||||||
tags: feature 1.4
|
tags: feature 1.4
|
||||||
|
|
||||||
- logo py.test
|
- logo py.test
|
||||||
- reference / customization
|
- reference / customization
|
||||||
- writing a (local or global) plugin
|
- writing a (local or global) plugin
|
||||||
- examples for unittest or functional testing
|
- examples for unittest or functional testing
|
||||||
- resource management for functional testing
|
- resource management for functional testing
|
||||||
- patterns: page object
|
- patterns: page object
|
||||||
- parametrized testing
|
- parametrized testing
|
||||||
- better / more integrated plugin docs
|
- better / more integrated plugin docs
|
||||||
i.e. not per-plugin but per-feature referencing a plugin
|
i.e. not per-plugin but per-feature referencing a plugin
|
||||||
|
|
||||||
generalize parametrized testing to generate combinations
|
generalize parametrized testing to generate combinations
|
||||||
-------------------------------------------------------------
|
-------------------------------------------------------------
|
||||||
tags: feature 1.4
|
tags: feature 1.4
|
||||||
|
|
||||||
think about extending metafunc.addcall or add a new method to allow to
|
think about extending metafunc.addcall or add a new method to allow to
|
||||||
generate tests with combinations of all generated versions - what to do
|
generate tests with combinations of all generated versions - what to do
|
||||||
about "id" and "param" in such combinations though?
|
about "id" and "param" in such combinations though?
|
||||||
|
|
||||||
introduce py.test.mark.multi
|
introduce py.test.mark.multi
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
tags: feature 1.3
|
tags: feature 1.3
|
||||||
|
|
||||||
introduce py.test.mark.multi to specify a number
|
introduce py.test.mark.multi to specify a number
|
||||||
of values for a given function argument.
|
of values for a given function argument.
|
||||||
|
|
||||||
have imported module mismatch honour relative paths
|
have imported module mismatch honour relative paths
|
||||||
--------------------------------------------------------
|
--------------------------------------------------------
|
||||||
tags: bug 1.4
|
tags: bug 1.4
|
||||||
|
|
||||||
With 1.1.1 py.test fails at least on windows if an import
|
With 1.1.1 py.test fails at least on windows if an import
|
||||||
is relative and compared against an absolute conftest.py
|
is relative and compared against an absolute conftest.py
|
||||||
path. Normalize.
|
path. Normalize.
|
||||||
|
|
||||||
make node._checkcollectable more robust
|
make node._checkcollectable more robust
|
||||||
|
@ -167,8 +167,8 @@ tags: bug 1.4
|
||||||
|
|
||||||
currently node._checkcollectable() can raise
|
currently node._checkcollectable() can raise
|
||||||
exceptions for all kinds of reasons ('conftest.py' loading
|
exceptions for all kinds of reasons ('conftest.py' loading
|
||||||
problems, missing rsync-dirs, platform-skip-at-import-level
|
problems, missing rsync-dirs, platform-skip-at-import-level
|
||||||
issues, ...). It should just return True/False and cause
|
issues, ...). It should just return True/False and cause
|
||||||
a good error message.
|
a good error message.
|
||||||
|
|
||||||
call termination with small timeout
|
call termination with small timeout
|
||||||
|
@ -176,15 +176,15 @@ call termination with small timeout
|
||||||
tags: feature 1.4
|
tags: feature 1.4
|
||||||
test: testing/pytest/dist/test_dsession.py - test_terminate_on_hanging_node
|
test: testing/pytest/dist/test_dsession.py - test_terminate_on_hanging_node
|
||||||
|
|
||||||
Call gateway group termination with a small timeout if available.
|
Call gateway group termination with a small timeout if available.
|
||||||
Should make dist-testing less likely to leave lost processes.
|
Should make dist-testing less likely to leave lost processes.
|
||||||
|
|
||||||
consider globals: py.test.ensuretemp and config
|
consider globals: py.test.ensuretemp and config
|
||||||
--------------------------------------------------------------
|
--------------------------------------------------------------
|
||||||
tags: experimental-wish 1.4
|
tags: experimental-wish 1.4
|
||||||
|
|
||||||
consider deprecating py.test.ensuretemp and py.test.config
|
consider deprecating py.test.ensuretemp and py.test.config
|
||||||
to further reduce py.test globality. Also consider
|
to further reduce py.test globality. Also consider
|
||||||
having py.test.config and ensuretemp coming from
|
having py.test.config and ensuretemp coming from
|
||||||
a plugin rather than being there from the start.
|
a plugin rather than being there from the start.
|
||||||
|
|
||||||
|
@ -192,16 +192,16 @@ consider allowing funcargs for setup methods
|
||||||
--------------------------------------------------------------
|
--------------------------------------------------------------
|
||||||
tags: experimental-wish 1.4
|
tags: experimental-wish 1.4
|
||||||
|
|
||||||
Users have expressed the wish to have funcargs available to setup
|
Users have expressed the wish to have funcargs available to setup
|
||||||
functions. Experiment with allowing funcargs there - it might
|
functions. Experiment with allowing funcargs there - it might
|
||||||
also help to make the py.test.ensuretemp and config deprecation.
|
also help to make the py.test.ensuretemp and config deprecation.
|
||||||
For filling funcargs for setup methods, we could call funcarg
|
For filling funcargs for setup methods, we could call funcarg
|
||||||
factories with a request object that not have a cls/function
|
factories with a request object that not have a cls/function
|
||||||
attributes. However, how to handle parametrized test functions
|
attributes. However, how to handle parametrized test functions
|
||||||
and funcargs?
|
and funcargs?
|
||||||
|
|
||||||
setup_function -> request can be like it is now
|
setup_function -> request can be like it is now
|
||||||
setup_class -> request has no request.function
|
setup_class -> request has no request.function
|
||||||
setup_module -> request has no request.cls
|
setup_module -> request has no request.cls
|
||||||
|
|
||||||
consider pytest_addsyspath hook
|
consider pytest_addsyspath hook
|
||||||
|
@ -210,31 +210,31 @@ tags: 1.4
|
||||||
|
|
||||||
py.test could call a new pytest_addsyspath() in order to systematically
|
py.test could call a new pytest_addsyspath() in order to systematically
|
||||||
allow manipulation of sys.path and to inhibit it via --no-addsyspath
|
allow manipulation of sys.path and to inhibit it via --no-addsyspath
|
||||||
in order to more easily run against installed packages.
|
in order to more easily run against installed packages.
|
||||||
|
|
||||||
Alternatively it could also be done via the config object
|
Alternatively it could also be done via the config object
|
||||||
and pytest_configure.
|
and pytest_configure.
|
||||||
|
|
||||||
|
|
||||||
show plugin information in test header
|
show plugin information in test header
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
tags: feature 1.4
|
tags: feature 1.4
|
||||||
|
|
||||||
Now that external plugins are becoming more numerous
|
Now that external plugins are becoming more numerous
|
||||||
it would be useful to have external plugins along with
|
it would be useful to have external plugins along with
|
||||||
their versions displayed as a header line.
|
their versions displayed as a header line.
|
||||||
|
|
||||||
deprecate global py.test.config usage
|
deprecate global py.test.config usage
|
||||||
----------------------------------------------------------------
|
----------------------------------------------------------------
|
||||||
tags: feature 1.4
|
tags: feature 1.4
|
||||||
|
|
||||||
py.test.ensuretemp and py.test.config are probably the last
|
py.test.ensuretemp and py.test.config are probably the last
|
||||||
objects containing global state. Often using them is not
|
objects containing global state. Often using them is not
|
||||||
neccessary. This is about trying to get rid of them, i.e.
|
neccessary. This is about trying to get rid of them, i.e.
|
||||||
deprecating them and checking with PyPy's usages as well
|
deprecating them and checking with PyPy's usages as well
|
||||||
as others.
|
as others.
|
||||||
|
|
||||||
remove deprecated bits in collect.py
|
remove deprecated bits in collect.py
|
||||||
-------------------------------------------------------------------
|
-------------------------------------------------------------------
|
||||||
tags: feature 1.4
|
tags: feature 1.4
|
||||||
|
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
The py lib is a Python development support library featuring
|
The py lib is a Python development support library featuring
|
||||||
the following tools and modules:
|
the following tools and modules:
|
||||||
|
|
||||||
* py.test: tool for distributed automated testing
|
* py.test: tool for distributed automated testing
|
||||||
* py.code: dynamic code generation and introspection
|
* py.code: dynamic code generation and introspection
|
||||||
* py.path: uniform local and svn path objects
|
* py.path: uniform local and svn path objects
|
||||||
|
|
||||||
For questions and more information please visit http://pylib.org
|
For questions and more information please visit http://pylib.org
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
import py
|
import py
|
||||||
import inspect
|
import inspect
|
||||||
|
@ -73,4 +73,4 @@ if __name__ == '__main__':
|
||||||
for name, obj in all_exported:
|
for name, obj in all_exported:
|
||||||
if isinstance(obj, type):
|
if isinstance(obj, type):
|
||||||
report_different_parameter_names(name, obj)
|
report_different_parameter_names(name, obj)
|
||||||
|
|
||||||
|
|
|
@ -16,11 +16,11 @@ BIN=os.path.abspath(os.path.join(BUILDNAME, 'bin'))
|
||||||
if not os.path.exists(BIN):
|
if not os.path.exists(BIN):
|
||||||
BIN=os.path.abspath(os.path.join(BUILDNAME, 'Scripts'))
|
BIN=os.path.abspath(os.path.join(BUILDNAME, 'Scripts'))
|
||||||
assert os.path.exists(BIN)
|
assert os.path.exists(BIN)
|
||||||
|
|
||||||
PYTHON=os.path.join(BIN, 'python')
|
PYTHON=os.path.join(BIN, 'python')
|
||||||
bincall("python", "setup.py", "develop", "-q")
|
bincall("python", "setup.py", "develop", "-q")
|
||||||
bincall("pip", "install", "-r", "testing/pip-reqs1.txt",
|
bincall("pip", "install", "-r", "testing/pip-reqs1.txt",
|
||||||
"-q", "--download-cache=download")
|
"-q", "--download-cache=download")
|
||||||
bincall("py.test", "--ignore", BUILDNAME,
|
bincall("py.test", "--ignore", BUILDNAME,
|
||||||
"--xml=junit.xml",
|
"--xml=junit.xml",
|
||||||
"--report=skipped", "--runslowtest", *sys.argv[1:])
|
"--report=skipped", "--runslowtest", *sys.argv[1:])
|
||||||
|
|
|
@ -3,30 +3,30 @@ import os, sys
|
||||||
WIDTH = 75
|
WIDTH = 75
|
||||||
|
|
||||||
plugins = [
|
plugins = [
|
||||||
('advanced python testing',
|
('advanced python testing',
|
||||||
'skipping mark pdb figleaf '
|
'skipping mark pdb figleaf '
|
||||||
'monkeypatch coverage cov capture capturelog recwarn tmpdir',),
|
'monkeypatch coverage cov capture capturelog recwarn tmpdir',),
|
||||||
('distributed testing, CI and deployment',
|
('distributed testing, CI and deployment',
|
||||||
'xdist pastebin junitxml resultlog genscript',),
|
'xdist pastebin junitxml resultlog genscript',),
|
||||||
('testing domains and conventions codecheckers',
|
('testing domains and conventions codecheckers',
|
||||||
'oejskit django unittest nose doctest restdoc'),
|
'oejskit django unittest nose doctest restdoc'),
|
||||||
('internal, debugging, help functionality',
|
('internal, debugging, help functionality',
|
||||||
'helpconfig terminal hooklog')
|
'helpconfig terminal hooklog')
|
||||||
#('internal plugins / core functionality',
|
#('internal plugins / core functionality',
|
||||||
# #'runner execnetcleanup # pytester',
|
# #'runner execnetcleanup # pytester',
|
||||||
# 'runner execnetcleanup' # pytester',
|
# 'runner execnetcleanup' # pytester',
|
||||||
#)
|
#)
|
||||||
]
|
]
|
||||||
|
|
||||||
externals = {
|
externals = {
|
||||||
'oejskit': "run javascript tests in real life browsers",
|
'oejskit': "run javascript tests in real life browsers",
|
||||||
'xdist': None,
|
'xdist': None,
|
||||||
'figleaf': None,
|
'figleaf': None,
|
||||||
'capturelog': None,
|
'capturelog': None,
|
||||||
'coverage': None,
|
'coverage': None,
|
||||||
'cov': None,
|
'cov': None,
|
||||||
'codecheckers': None,
|
'codecheckers': None,
|
||||||
'django': "for testing django applications",
|
'django': "for testing django applications",
|
||||||
}
|
}
|
||||||
|
|
||||||
def warn(*args):
|
def warn(*args):
|
||||||
|
@ -107,7 +107,7 @@ class RestWriter:
|
||||||
assert self._all_links[key] == link[1], (key, link[1])
|
assert self._all_links[key] == link[1], (key, link[1])
|
||||||
else:
|
else:
|
||||||
self._all_links[key] = link[1]
|
self._all_links[key] = link[1]
|
||||||
|
|
||||||
def write_all_links(cls, linkpath):
|
def write_all_links(cls, linkpath):
|
||||||
p = linkpath.new(basename="links.txt")
|
p = linkpath.new(basename="links.txt")
|
||||||
p_writer = RestWriter(p)
|
p_writer = RestWriter(p)
|
||||||
|
@ -142,7 +142,7 @@ class PluginOverview(RestWriter):
|
||||||
self.add_internal_link(name, htmlpath)
|
self.add_internal_link(name, htmlpath)
|
||||||
else:
|
else:
|
||||||
doc = PluginDoc(docpath)
|
doc = PluginDoc(docpath)
|
||||||
doc.make(config=config, name=name)
|
doc.make(config=config, name=name)
|
||||||
self.add_internal_link(name, doc.target)
|
self.add_internal_link(name, doc.target)
|
||||||
if name in externals:
|
if name in externals:
|
||||||
self.para("%s_ (external) %s" %(name, doc.oneliner))
|
self.para("%s_ (external) %s" %(name, doc.oneliner))
|
||||||
|
@ -173,9 +173,9 @@ class PluginDoc(RestWriter):
|
||||||
moduledoc = doc[i+1:].strip()
|
moduledoc = doc[i+1:].strip()
|
||||||
|
|
||||||
self.name = oneliner # plugin.__name__.split(".")[-1]
|
self.name = oneliner # plugin.__name__.split(".")[-1]
|
||||||
self.oneliner = oneliner
|
self.oneliner = oneliner
|
||||||
self.moduledoc = moduledoc
|
self.moduledoc = moduledoc
|
||||||
|
|
||||||
#self.h1("%s plugin" % self.name) # : %s" %(self.name, self.oneliner))
|
#self.h1("%s plugin" % self.name) # : %s" %(self.name, self.oneliner))
|
||||||
self.h1(oneliner)
|
self.h1(oneliner)
|
||||||
#self.Print(self.oneliner)
|
#self.Print(self.oneliner)
|
||||||
|
@ -185,13 +185,13 @@ class PluginDoc(RestWriter):
|
||||||
self.Print()
|
self.Print()
|
||||||
|
|
||||||
self.Print(moduledoc)
|
self.Print(moduledoc)
|
||||||
|
|
||||||
self.emit_funcargs(plugin)
|
self.emit_funcargs(plugin)
|
||||||
self.emit_options(plugin)
|
self.emit_options(plugin)
|
||||||
if name not in externals:
|
if name not in externals:
|
||||||
self.emit_source(plugin, config.hg_changeset)
|
self.emit_source(plugin, config.hg_changeset)
|
||||||
#self.sourcelink = (purename,
|
#self.sourcelink = (purename,
|
||||||
# "http://bitbucket.org/hpk42/py-trunk/src/tip/py/test/plugin/" +
|
# "http://bitbucket.org/hpk42/py-trunk/src/tip/py/test/plugin/" +
|
||||||
# purename + ".py")
|
# purename + ".py")
|
||||||
#
|
#
|
||||||
def emit_source(self, plugin, hg_changeset):
|
def emit_source(self, plugin, hg_changeset):
|
||||||
|
@ -199,35 +199,35 @@ class PluginDoc(RestWriter):
|
||||||
if basename.endswith("pyc"):
|
if basename.endswith("pyc"):
|
||||||
basename = basename[:-1]
|
basename = basename[:-1]
|
||||||
#self.para("`%s`_ source code" % basename)
|
#self.para("`%s`_ source code" % basename)
|
||||||
#self.links.append((basename,
|
#self.links.append((basename,
|
||||||
# "http://bitbucket.org/hpk42/py-trunk/src/tip/py/test/plugin/" +
|
# "http://bitbucket.org/hpk42/py-trunk/src/tip/py/test/plugin/" +
|
||||||
# basename))
|
# basename))
|
||||||
self.h1("Start improving this plugin in 30 seconds")
|
self.h1("Start improving this plugin in 30 seconds")
|
||||||
self.para(py.code.Source("""
|
self.para(py.code.Source("""
|
||||||
1. Download `%s`_ plugin source code
|
1. Download `%s`_ plugin source code
|
||||||
2. put it somewhere as ``%s`` into your import path
|
2. put it somewhere as ``%s`` into your import path
|
||||||
3. a subsequent ``py.test`` run will use your local version
|
3. a subsequent ``py.test`` run will use your local version
|
||||||
|
|
||||||
Checkout customize_, other plugins_ or `get in contact`_.
|
Checkout customize_, other plugins_ or `get in contact`_.
|
||||||
""" % (basename, basename)))
|
""" % (basename, basename)))
|
||||||
# your work appreciated if you offer back your version. In this case
|
# your work appreciated if you offer back your version. In this case
|
||||||
# it probably makes sense if you `checkout the py.test
|
# it probably makes sense if you `checkout the py.test
|
||||||
# development version`_ and apply your changes to the plugin
|
# development version`_ and apply your changes to the plugin
|
||||||
# version in there.
|
# version in there.
|
||||||
#self.links.append((basename,
|
#self.links.append((basename,
|
||||||
# "http://bitbucket.org/hpk42/py-trunk/raw/%s/"
|
# "http://bitbucket.org/hpk42/py-trunk/raw/%s/"
|
||||||
# "py/test/plugin/%s" %(hg_changeset, basename)))
|
# "py/test/plugin/%s" %(hg_changeset, basename)))
|
||||||
self.links.append((basename,
|
self.links.append((basename,
|
||||||
"http://bitbucket.org/hpk42/py-trunk/raw/%s/"
|
"http://bitbucket.org/hpk42/py-trunk/raw/%s/"
|
||||||
"py/_plugin/%s" %(pyversion, basename)))
|
"py/_plugin/%s" %(pyversion, basename)))
|
||||||
self.links.append(('customize', '../customize.html'))
|
self.links.append(('customize', '../customize.html'))
|
||||||
self.links.append(('plugins', 'index.html'))
|
self.links.append(('plugins', 'index.html'))
|
||||||
self.links.append(('get in contact', '../../contact.html'))
|
self.links.append(('get in contact', '../../contact.html'))
|
||||||
self.links.append(('checkout the py.test development version',
|
self.links.append(('checkout the py.test development version',
|
||||||
'../../install.html#checkout'))
|
'../../install.html#checkout'))
|
||||||
|
|
||||||
if 0: # this breaks the page layout and makes large doc files
|
if 0: # this breaks the page layout and makes large doc files
|
||||||
#self.h2("plugin source code")
|
#self.h2("plugin source code")
|
||||||
self.Print()
|
self.Print()
|
||||||
self.para("For your convenience here is also an inlined version "
|
self.para("For your convenience here is also an inlined version "
|
||||||
"of ``%s``:" %basename)
|
"of ``%s``:" %basename)
|
||||||
|
@ -285,15 +285,15 @@ if __name__ == "__main__":
|
||||||
pydir = py.path.local(py.__file__).dirpath()
|
pydir = py.path.local(py.__file__).dirpath()
|
||||||
pyversion = py.version
|
pyversion = py.version
|
||||||
|
|
||||||
cmd = "hg tip --template '{node}'"
|
cmd = "hg tip --template '{node}'"
|
||||||
old = pydir.dirpath().chdir()
|
old = pydir.dirpath().chdir()
|
||||||
_config.hg_changeset = py.process.cmdexec(cmd).strip()
|
_config.hg_changeset = py.process.cmdexec(cmd).strip()
|
||||||
|
|
||||||
testdir = pydir.dirpath("doc", 'test')
|
testdir = pydir.dirpath("doc", 'test')
|
||||||
|
|
||||||
ov = PluginOverview(testdir.join("plugin", "index.txt"))
|
ov = PluginOverview(testdir.join("plugin", "index.txt"))
|
||||||
ov.make(config=_config)
|
ov.make(config=_config)
|
||||||
|
|
||||||
ov = HookSpec(testdir.join("plugin", "hookspec.txt"))
|
ov = HookSpec(testdir.join("plugin", "hookspec.txt"))
|
||||||
ov.make(config=_config)
|
ov.make(config=_config)
|
||||||
|
|
||||||
|
|
|
@ -13,9 +13,9 @@ pytest_plugins = 'pytest_pytester',
|
||||||
|
|
||||||
def pytest_funcarg__venv(request):
|
def pytest_funcarg__venv(request):
|
||||||
p = request.config.mktemp(request.function.__name__, numbered=True)
|
p = request.config.mktemp(request.function.__name__, numbered=True)
|
||||||
venv = VirtualEnv(str(p))
|
venv = VirtualEnv(str(p))
|
||||||
return venv
|
return venv
|
||||||
|
|
||||||
def pytest_funcarg__py_setup(request):
|
def pytest_funcarg__py_setup(request):
|
||||||
testdir = request.getfuncargvalue('testdir')
|
testdir = request.getfuncargvalue('testdir')
|
||||||
rootdir = py.path.local(py.__file__).dirpath().dirpath()
|
rootdir = py.path.local(py.__file__).dirpath().dirpath()
|
||||||
|
@ -48,14 +48,14 @@ class SetupBuilder:
|
||||||
destdir = py.path.local(destdir)
|
destdir = py.path.local(destdir)
|
||||||
target = destdir.join(sdist.basename)
|
target = destdir.join(sdist.basename)
|
||||||
sdist.copy(target)
|
sdist.copy(target)
|
||||||
return target
|
return target
|
||||||
|
|
||||||
def subcall(args):
|
def subcall(args):
|
||||||
if hasattr(subprocess, 'check_call'):
|
if hasattr(subprocess, 'check_call'):
|
||||||
subprocess.check_call(args)
|
subprocess.check_call(args)
|
||||||
else:
|
else:
|
||||||
subprocess.call(args)
|
subprocess.call(args)
|
||||||
# code taken from Ronny Pfannenschmidt's virtualenvmanager
|
# code taken from Ronny Pfannenschmidt's virtualenvmanager
|
||||||
|
|
||||||
class VirtualEnv(object):
|
class VirtualEnv(object):
|
||||||
def __init__(self, path):
|
def __init__(self, path):
|
||||||
|
@ -119,7 +119,7 @@ class VirtualEnv(object):
|
||||||
|
|
||||||
def test_make_sdist_and_run_it(py_setup, venv):
|
def test_make_sdist_and_run_it(py_setup, venv):
|
||||||
sdist = py_setup.make_sdist(venv.path)
|
sdist = py_setup.make_sdist(venv.path)
|
||||||
venv.easy_install(str(sdist))
|
venv.easy_install(str(sdist))
|
||||||
gw = venv.makegateway()
|
gw = venv.makegateway()
|
||||||
ch = gw.remote_exec("import py ; channel.send(py.__version__)")
|
ch = gw.remote_exec("import py ; channel.send(py.__version__)")
|
||||||
version = ch.receive()
|
version = ch.receive()
|
||||||
|
@ -127,7 +127,7 @@ def test_make_sdist_and_run_it(py_setup, venv):
|
||||||
|
|
||||||
def test_plugin_setuptools_entry_point_integration(py_setup, venv, tmpdir):
|
def test_plugin_setuptools_entry_point_integration(py_setup, venv, tmpdir):
|
||||||
sdist = py_setup.make_sdist(venv.path)
|
sdist = py_setup.make_sdist(venv.path)
|
||||||
venv.easy_install(str(sdist))
|
venv.easy_install(str(sdist))
|
||||||
# create a sample plugin
|
# create a sample plugin
|
||||||
basedir = tmpdir.mkdir("testplugin")
|
basedir = tmpdir.mkdir("testplugin")
|
||||||
basedir.join("setup.py").write("""if 1:
|
basedir.join("setup.py").write("""if 1:
|
||||||
|
@ -151,7 +151,7 @@ def test_cmdline_entrypoints(monkeypatch):
|
||||||
monkeypatch.syspath_prepend(py.path.local(__file__).dirpath().dirpath())
|
monkeypatch.syspath_prepend(py.path.local(__file__).dirpath().dirpath())
|
||||||
from setup import cmdline_entrypoints
|
from setup import cmdline_entrypoints
|
||||||
versioned_scripts = ['py.test', 'py.which']
|
versioned_scripts = ['py.test', 'py.which']
|
||||||
unversioned_scripts = versioned_scripts + [ 'py.cleanup',
|
unversioned_scripts = versioned_scripts + [ 'py.cleanup',
|
||||||
'py.convert_unittest', 'py.countloc', 'py.lookup', 'py.svnwcrevert']
|
'py.convert_unittest', 'py.countloc', 'py.lookup', 'py.svnwcrevert']
|
||||||
for ver in [(2,4,0), (2,5,0), (2,6,0), (2,7,0), (3,0,1), (3,1,1)]:
|
for ver in [(2,4,0), (2,5,0), (2,6,0), (2,7,0), (3,0,1), (3,1,1)]:
|
||||||
for platform in ('posix', 'win32'):
|
for platform in ('posix', 'win32'):
|
||||||
|
@ -187,7 +187,7 @@ def test_slave_popen_needs_no_pylib(testdir, venv, pytestconfig):
|
||||||
def test_func():
|
def test_func():
|
||||||
pass
|
pass
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(p, '--rsyncdir=%s' % str(p),
|
result = testdir.runpytest(p, '--rsyncdir=%s' % str(p),
|
||||||
'--dist=each', '--tx=popen//python=%s' % python)
|
'--dist=each', '--tx=popen//python=%s' % python)
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"*1 passed*"
|
"*1 passed*"
|
||||||
|
@ -215,13 +215,13 @@ def test_slave_needs_no_execnet(testdir, sshhost, pytestconfig):
|
||||||
ch = gw.remote_exec("import execnet")
|
ch = gw.remote_exec("import execnet")
|
||||||
py.test.raises(ch.RemoteError, ch.waitclose)
|
py.test.raises(ch.RemoteError, ch.waitclose)
|
||||||
gw.exit()
|
gw.exit()
|
||||||
|
|
||||||
p = testdir.makepyfile("""
|
p = testdir.makepyfile("""
|
||||||
import py
|
import py
|
||||||
def test_func():
|
def test_func():
|
||||||
pass
|
pass
|
||||||
""")
|
""")
|
||||||
result = testdir.runpytest(p, '--rsyncdir=%s' % str(p),
|
result = testdir.runpytest(p, '--rsyncdir=%s' % str(p),
|
||||||
'--dist=each', '--tx=%s' % newspec)
|
'--dist=each', '--tx=%s' % newspec)
|
||||||
result.stdout.fnmatch_lines([
|
result.stdout.fnmatch_lines([
|
||||||
"*1 passed*"
|
"*1 passed*"
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
#
|
#
|
||||||
# find and import a version of 'py' that exists in a parent dir
|
# find and import a version of 'py' that exists in a parent dir
|
||||||
# of the current working directory. fall back to import a
|
# of the current working directory. fall back to import a
|
||||||
# globally available version
|
# globally available version
|
||||||
#
|
#
|
||||||
import sys
|
import sys
|
||||||
|
@ -31,9 +31,9 @@ def searchpy(current):
|
||||||
if not searchpy(abspath(os.curdir)):
|
if not searchpy(abspath(os.curdir)):
|
||||||
if not searchpy(opd(abspath(sys.argv[0]))):
|
if not searchpy(opd(abspath(sys.argv[0]))):
|
||||||
if not searchpy(opd(__file__)):
|
if not searchpy(opd(__file__)):
|
||||||
pass # let's hope it is just on sys.path
|
pass # let's hope it is just on sys.path
|
||||||
|
|
||||||
import py
|
import py
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
print ("py lib is at %s" % py.__file__)
|
print ("py lib is at %s" % py.__file__)
|
||||||
|
|
10
conftest.py
10
conftest.py
|
@ -12,7 +12,7 @@ pid = os.getpid()
|
||||||
|
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
group = parser.getgroup("pylib", "py lib testing options")
|
group = parser.getgroup("pylib", "py lib testing options")
|
||||||
group.addoption('--sshhost',
|
group.addoption('--sshhost',
|
||||||
action="store", dest="sshhost", default=None,
|
action="store", dest="sshhost", default=None,
|
||||||
help=("ssh xspec for ssh functional tests. "))
|
help=("ssh xspec for ssh functional tests. "))
|
||||||
group.addoption('--runslowtests',
|
group.addoption('--runslowtests',
|
||||||
|
@ -43,7 +43,7 @@ def pytest_funcarg__sshhost(request):
|
||||||
val = request.config.getvalue("sshhost")
|
val = request.config.getvalue("sshhost")
|
||||||
if val:
|
if val:
|
||||||
return val
|
return val
|
||||||
py.test.skip("need --sshhost option")
|
py.test.skip("need --sshhost option")
|
||||||
def pytest_generate_tests(metafunc):
|
def pytest_generate_tests(metafunc):
|
||||||
multi = getattr(metafunc.function, 'multi', None)
|
multi = getattr(metafunc.function, 'multi', None)
|
||||||
if multi is not None:
|
if multi is not None:
|
||||||
|
@ -52,11 +52,11 @@ def pytest_generate_tests(metafunc):
|
||||||
for val in l:
|
for val in l:
|
||||||
metafunc.addcall(funcargs={name: val})
|
metafunc.addcall(funcargs={name: val})
|
||||||
elif 'anypython' in metafunc.funcargnames:
|
elif 'anypython' in metafunc.funcargnames:
|
||||||
for name in ('python2.4', 'python2.5', 'python2.6',
|
for name in ('python2.4', 'python2.5', 'python2.6',
|
||||||
'python2.7', 'python3.1', 'pypy-c', 'jython'):
|
'python2.7', 'python3.1', 'pypy-c', 'jython'):
|
||||||
metafunc.addcall(id=name, param=name)
|
metafunc.addcall(id=name, param=name)
|
||||||
|
|
||||||
# XXX copied from execnet's conftest.py - needs to be merged
|
# XXX copied from execnet's conftest.py - needs to be merged
|
||||||
winpymap = {
|
winpymap = {
|
||||||
'python2.7': r'C:\Python27\python.exe',
|
'python2.7': r'C:\Python27\python.exe',
|
||||||
'python2.6': r'C:\Python26\python.exe',
|
'python2.6': r'C:\Python26\python.exe',
|
||||||
|
@ -73,7 +73,7 @@ def getexecutable(name, cache={}):
|
||||||
if executable:
|
if executable:
|
||||||
if name == "jython":
|
if name == "jython":
|
||||||
import subprocess
|
import subprocess
|
||||||
popen = subprocess.Popen([str(executable), "--version"],
|
popen = subprocess.Popen([str(executable), "--version"],
|
||||||
universal_newlines=True, stderr=subprocess.PIPE)
|
universal_newlines=True, stderr=subprocess.PIPE)
|
||||||
out, err = popen.communicate()
|
out, err = popen.communicate()
|
||||||
if not err or "2.5" not in err:
|
if not err or "2.5" not in err:
|
||||||
|
|
|
@ -5,4 +5,4 @@ def pytest_runtest_call(item, __multicall__):
|
||||||
try:
|
try:
|
||||||
return __multicall__.execute()
|
return __multicall__.execute()
|
||||||
finally:
|
finally:
|
||||||
outerr = cap.reset()
|
outerr = cap.reset()
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
"""XXX in progress: resultdb plugin for database logging of test results.
|
"""XXX in progress: resultdb plugin for database logging of test results.
|
||||||
|
|
||||||
Saves test results to a datastore.
|
Saves test results to a datastore.
|
||||||
|
|
||||||
XXX this needs to be merged with resultlog plugin
|
XXX this needs to be merged with resultlog plugin
|
||||||
|
|
||||||
Also mixes in some early ideas about an archive abstraction for test
|
Also mixes in some early ideas about an archive abstraction for test
|
||||||
results.
|
results.
|
||||||
"""
|
"""
|
||||||
import py
|
import py
|
||||||
|
|
||||||
py.test.skip("XXX needs to be merged with resultlog")
|
py.test.skip("XXX needs to be merged with resultlog")
|
||||||
|
@ -15,15 +15,15 @@ from pytest_resultlog import ResultLog
|
||||||
|
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
group = parser.addgroup("resultdb", "resultdb plugin options")
|
group = parser.addgroup("resultdb", "resultdb plugin options")
|
||||||
group.addoption('--resultdb', action="store", dest="resultdb",
|
group.addoption('--resultdb', action="store", dest="resultdb",
|
||||||
metavar="path",
|
metavar="path",
|
||||||
help="path to the file to store test results.")
|
help="path to the file to store test results.")
|
||||||
group.addoption('--resultdb_format', action="store",
|
group.addoption('--resultdb_format', action="store",
|
||||||
dest="resultdbformat", default='json',
|
dest="resultdbformat", default='json',
|
||||||
help="data format (json, sqlite)")
|
help="data format (json, sqlite)")
|
||||||
|
|
||||||
def pytest_configure(config):
|
def pytest_configure(config):
|
||||||
# XXX using config.XYZ is not good
|
# XXX using config.XYZ is not good
|
||||||
if config.getvalue('resultdb'):
|
if config.getvalue('resultdb'):
|
||||||
if config.option.resultdb:
|
if config.option.resultdb:
|
||||||
# local import so missing module won't crash py.test
|
# local import so missing module won't crash py.test
|
||||||
|
@ -36,14 +36,14 @@ def pytest_configure(config):
|
||||||
except ImportError:
|
except ImportError:
|
||||||
raise config.Error('Could not import simplejson module')
|
raise config.Error('Could not import simplejson module')
|
||||||
if config.option.resultdbformat.lower() == 'json':
|
if config.option.resultdbformat.lower() == 'json':
|
||||||
resultdb = ResultDB(JSONResultArchive,
|
resultdb = ResultDB(JSONResultArchive,
|
||||||
config.option.resultdb)
|
config.option.resultdb)
|
||||||
elif config.option.resultdbformat.lower() == 'sqlite':
|
elif config.option.resultdbformat.lower() == 'sqlite':
|
||||||
resultdb = ResultDB(SQLiteResultArchive,
|
resultdb = ResultDB(SQLiteResultArchive,
|
||||||
config.option.resultdb)
|
config.option.resultdb)
|
||||||
else:
|
else:
|
||||||
raise config.Error('Unknown --resultdb_format: %s' %
|
raise config.Error('Unknown --resultdb_format: %s' %
|
||||||
config.option.resultdbformat)
|
config.option.resultdbformat)
|
||||||
|
|
||||||
config.pluginmanager.register(resultdb)
|
config.pluginmanager.register(resultdb)
|
||||||
|
|
||||||
|
@ -52,7 +52,7 @@ class JSONResultArchive(object):
|
||||||
self.archive_path = archive_path
|
self.archive_path = archive_path
|
||||||
import simplejson
|
import simplejson
|
||||||
self.simplejson = simplejson
|
self.simplejson = simplejson
|
||||||
|
|
||||||
def init_db(self):
|
def init_db(self):
|
||||||
if os.path.exists(self.archive_path):
|
if os.path.exists(self.archive_path):
|
||||||
data_file = open(self.archive_path)
|
data_file = open(self.archive_path)
|
||||||
|
@ -84,7 +84,7 @@ class SQLiteResultArchive(object):
|
||||||
self.archive_path = archive_path
|
self.archive_path = archive_path
|
||||||
import sqlite3
|
import sqlite3
|
||||||
self.sqlite3 = sqlite3
|
self.sqlite3 = sqlite3
|
||||||
|
|
||||||
def init_db(self):
|
def init_db(self):
|
||||||
if not os.path.exists(self.archive_path):
|
if not os.path.exists(self.archive_path):
|
||||||
conn = self.sqlite3.connect(self.archive_path)
|
conn = self.sqlite3.connect(self.archive_path)
|
||||||
|
@ -153,7 +153,7 @@ class ResultDB(ResultLog):
|
||||||
for item in vars(event).keys():
|
for item in vars(event).keys():
|
||||||
if item not in event_excludes:
|
if item not in event_excludes:
|
||||||
data[item] = getattr(event, item)
|
data[item] = getattr(event, item)
|
||||||
# use the locally calculated longrepr & shortrepr
|
# use the locally calculated longrepr & shortrepr
|
||||||
data['longrepr'] = longrepr
|
data['longrepr'] = longrepr
|
||||||
data['shortrepr'] = shortrepr
|
data['shortrepr'] = shortrepr
|
||||||
|
|
||||||
|
@ -185,10 +185,10 @@ insert into pytest_results (
|
||||||
longrepr,
|
longrepr,
|
||||||
fspath,
|
fspath,
|
||||||
itemname)
|
itemname)
|
||||||
values (?, ?, ?, ?, ?, ?, ?, ?, ?);
|
values (?, ?, ?, ?, ?, ?, ?, ?, ?);
|
||||||
"""
|
"""
|
||||||
SQL_SELECT_DATA = """
|
SQL_SELECT_DATA = """
|
||||||
select
|
select
|
||||||
runid,
|
runid,
|
||||||
name,
|
name,
|
||||||
passed,
|
passed,
|
||||||
|
@ -204,7 +204,7 @@ from pytest_results;
|
||||||
|
|
||||||
# ===============================================================================
|
# ===============================================================================
|
||||||
#
|
#
|
||||||
# plugin tests
|
# plugin tests
|
||||||
#
|
#
|
||||||
# ===============================================================================
|
# ===============================================================================
|
||||||
|
|
||||||
|
@ -214,7 +214,7 @@ class BaseResultArchiveTests(object):
|
||||||
cls = None
|
cls = None
|
||||||
|
|
||||||
def setup_class(cls):
|
def setup_class(cls):
|
||||||
# XXX refactor setup into a funcarg?
|
# XXX refactor setup into a funcarg?
|
||||||
cls.tempdb = "test_tempdb"
|
cls.tempdb = "test_tempdb"
|
||||||
|
|
||||||
def test_init_db(self, testdir):
|
def test_init_db(self, testdir):
|
||||||
|
@ -243,7 +243,7 @@ class BaseResultArchiveTests(object):
|
||||||
for key, value in data[0].items():
|
for key, value in data[0].items():
|
||||||
assert value == result[0][key]
|
assert value == result[0][key]
|
||||||
assert 'runid' in result[0]
|
assert 'runid' in result[0]
|
||||||
|
|
||||||
# make sure the data is persisted
|
# make sure the data is persisted
|
||||||
tempdb_path = unicode(testdir.tmpdir.join(self.tempdb))
|
tempdb_path = unicode(testdir.tmpdir.join(self.tempdb))
|
||||||
archive = self.cls(tempdb_path)
|
archive = self.cls(tempdb_path)
|
||||||
|
@ -257,7 +257,7 @@ class TestJSONResultArchive(BaseResultArchiveTests):
|
||||||
def setup_method(self, method):
|
def setup_method(self, method):
|
||||||
py.test.importorskip("simplejson")
|
py.test.importorskip("simplejson")
|
||||||
|
|
||||||
|
|
||||||
class TestSQLiteResultArchive(BaseResultArchiveTests):
|
class TestSQLiteResultArchive(BaseResultArchiveTests):
|
||||||
cls = SQLiteResultArchive
|
cls = SQLiteResultArchive
|
||||||
|
|
||||||
|
@ -270,8 +270,8 @@ class TestSQLiteResultArchive(BaseResultArchiveTests):
|
||||||
archive = self.cls(tempdb_path)
|
archive = self.cls(tempdb_path)
|
||||||
archive.init_db()
|
archive.init_db()
|
||||||
assert os.path.exists(tempdb_path)
|
assert os.path.exists(tempdb_path)
|
||||||
|
|
||||||
# is table in the database?
|
# is table in the database?
|
||||||
import sqlite3
|
import sqlite3
|
||||||
conn = sqlite3.connect(tempdb_path)
|
conn = sqlite3.connect(tempdb_path)
|
||||||
cursor = conn.cursor()
|
cursor = conn.cursor()
|
||||||
|
@ -281,7 +281,7 @@ class TestSQLiteResultArchive(BaseResultArchiveTests):
|
||||||
cursor.close()
|
cursor.close()
|
||||||
conn.close()
|
conn.close()
|
||||||
assert len(tables) == 1
|
assert len(tables) == 1
|
||||||
|
|
||||||
def verify_archive_item_shape(item):
|
def verify_archive_item_shape(item):
|
||||||
names = ("runid name passed skipped failed shortrepr "
|
names = ("runid name passed skipped failed shortrepr "
|
||||||
"longrepr fspath itemname").split()
|
"longrepr fspath itemname").split()
|
||||||
|
@ -299,14 +299,14 @@ class TestWithFunctionIntegration:
|
||||||
archive = SQLiteResultArchive(unicode(resultdb))
|
archive = SQLiteResultArchive(unicode(resultdb))
|
||||||
archive.init_db()
|
archive.init_db()
|
||||||
return archive
|
return archive
|
||||||
|
|
||||||
def test_collection_report(self, testdir):
|
def test_collection_report(self, testdir):
|
||||||
py.test.skip("Needs a rewrite for db version.")
|
py.test.skip("Needs a rewrite for db version.")
|
||||||
ok = testdir.makepyfile(test_collection_ok="")
|
ok = testdir.makepyfile(test_collection_ok="")
|
||||||
skip = testdir.makepyfile(test_collection_skip="import py ; py.test.skip('hello')")
|
skip = testdir.makepyfile(test_collection_skip="import py ; py.test.skip('hello')")
|
||||||
fail = testdir.makepyfile(test_collection_fail="XXX")
|
fail = testdir.makepyfile(test_collection_fail="XXX")
|
||||||
|
|
||||||
lines = self.getresultdb(testdir, ok)
|
lines = self.getresultdb(testdir, ok)
|
||||||
assert not lines
|
assert not lines
|
||||||
|
|
||||||
lines = self.getresultdb(testdir, skip)
|
lines = self.getresultdb(testdir, skip)
|
||||||
|
@ -326,7 +326,7 @@ class TestWithFunctionIntegration:
|
||||||
|
|
||||||
def test_log_test_outcomes(self, testdir):
|
def test_log_test_outcomes(self, testdir):
|
||||||
mod = testdir.makepyfile(test_mod="""
|
mod = testdir.makepyfile(test_mod="""
|
||||||
import py
|
import py
|
||||||
def test_pass(): pass
|
def test_pass(): pass
|
||||||
def test_skip(): py.test.skip("hello")
|
def test_skip(): py.test.skip("hello")
|
||||||
def test_fail(): raise ValueError("val")
|
def test_fail(): raise ValueError("val")
|
||||||
|
@ -349,7 +349,7 @@ class TestWithFunctionIntegration:
|
||||||
raise ValueError
|
raise ValueError
|
||||||
except ValueError:
|
except ValueError:
|
||||||
excinfo = py.code.ExceptionInfo()
|
excinfo = py.code.ExceptionInfo()
|
||||||
reslog = ResultDB(StringIO.StringIO())
|
reslog = ResultDB(StringIO.StringIO())
|
||||||
reslog.pytest_internalerror(excinfo.getrepr)
|
reslog.pytest_internalerror(excinfo.getrepr)
|
||||||
entry = reslog.logfile.getvalue()
|
entry = reslog.logfile.getvalue()
|
||||||
entry_lines = entry.splitlines()
|
entry_lines = entry.splitlines()
|
||||||
|
@ -357,7 +357,7 @@ class TestWithFunctionIntegration:
|
||||||
assert entry_lines[0].startswith('! ')
|
assert entry_lines[0].startswith('! ')
|
||||||
assert os.path.basename(__file__)[:-1] in entry_lines[0] #.py/.pyc
|
assert os.path.basename(__file__)[:-1] in entry_lines[0] #.py/.pyc
|
||||||
assert entry_lines[-1][0] == ' '
|
assert entry_lines[-1][0] == ' '
|
||||||
assert 'ValueError' in entry
|
assert 'ValueError' in entry
|
||||||
|
|
||||||
def test_generic(testdir):
|
def test_generic(testdir):
|
||||||
testdir.makepyfile("""
|
testdir.makepyfile("""
|
||||||
|
@ -371,4 +371,4 @@ def test_generic(testdir):
|
||||||
""")
|
""")
|
||||||
testdir.runpytest("--resultdb=result.sqlite")
|
testdir.runpytest("--resultdb=result.sqlite")
|
||||||
#testdir.tmpdir.join("result.sqlite")
|
#testdir.tmpdir.join("result.sqlite")
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,7 @@ try:
|
||||||
from greenlet import greenlet
|
from greenlet import greenlet
|
||||||
except ImportError:
|
except ImportError:
|
||||||
print "Since pylib 1.0 greenlet are removed and separately packaged: " \
|
print "Since pylib 1.0 greenlet are removed and separately packaged: " \
|
||||||
"http://pypi.python.org/pypi/greenlet"
|
"http://pypi.python.org/pypi/greenlet"
|
||||||
sys.exit(10)
|
sys.exit(10)
|
||||||
|
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ def _run_twisted(logging=False):
|
||||||
failure.Failure.cleanFailure = lambda *args: None
|
failure.Failure.cleanFailure = lambda *args: None
|
||||||
if logging:
|
if logging:
|
||||||
_start_twisted_logging()
|
_start_twisted_logging()
|
||||||
|
|
||||||
def fix_signal_handling():
|
def fix_signal_handling():
|
||||||
# see http://twistedmatrix.com/trac/ticket/733
|
# see http://twistedmatrix.com/trac/ticket/733
|
||||||
import signal
|
import signal
|
||||||
|
@ -54,7 +54,7 @@ def _run_twisted(logging=False):
|
||||||
def start():
|
def start():
|
||||||
fix_signal_handling()
|
fix_signal_handling()
|
||||||
doit(None)
|
doit(None)
|
||||||
|
|
||||||
# recursively called for each test-function/method due done()
|
# recursively called for each test-function/method due done()
|
||||||
def doit(val): # val always None
|
def doit(val): # val always None
|
||||||
# switch context to wait that wrapper() passes back to test-method
|
# switch context to wait that wrapper() passes back to test-method
|
||||||
|
@ -68,7 +68,7 @@ def _run_twisted(logging=False):
|
||||||
|
|
||||||
def err(res):
|
def err(res):
|
||||||
reactor.callLater(0.0, doit, res)
|
reactor.callLater(0.0, doit, res)
|
||||||
|
|
||||||
# the test-function *may* return a deferred
|
# the test-function *may* return a deferred
|
||||||
# here the test-function will actually been called
|
# here the test-function will actually been called
|
||||||
# done() is finalizing a test-process by assuring recursive invoking
|
# done() is finalizing a test-process by assuring recursive invoking
|
||||||
|
@ -92,19 +92,19 @@ def pytest_unconfigure(config):
|
||||||
gr_twisted.switch(None)
|
gr_twisted.switch(None)
|
||||||
|
|
||||||
def pytest_pyfunc_call(pyfuncitem):
|
def pytest_pyfunc_call(pyfuncitem):
|
||||||
# XXX1 kwargs?
|
# XXX1 kwargs?
|
||||||
# XXX2 we want to delegate actual call to next plugin
|
# XXX2 we want to delegate actual call to next plugin
|
||||||
# (which may want to produce test coverage, etc.)
|
# (which may want to produce test coverage, etc.)
|
||||||
res = gr_twisted.switch(lambda: pyfuncitem.call())
|
res = gr_twisted.switch(lambda: pyfuncitem.call())
|
||||||
if res:
|
if res:
|
||||||
res.raiseException()
|
res.raiseException()
|
||||||
return True # indicates that we performed the function call
|
return True # indicates that we performed the function call
|
||||||
|
|
||||||
gr_twisted = greenlet(_run_twisted)
|
gr_twisted = greenlet(_run_twisted)
|
||||||
gr_tests = greenlet.getcurrent()
|
gr_tests = greenlet.getcurrent()
|
||||||
|
|
||||||
# ===============================================================================
|
# ===============================================================================
|
||||||
# plugin tests
|
# plugin tests
|
||||||
# ===============================================================================
|
# ===============================================================================
|
||||||
|
|
||||||
def test_generic(testdir):
|
def test_generic(testdir):
|
||||||
|
@ -125,7 +125,7 @@ def test_generic(testdir):
|
||||||
def done():
|
def done():
|
||||||
log.msg("test_deferred.done() CALLBACK DONE")
|
log.msg("test_deferred.done() CALLBACK DONE")
|
||||||
d.callback(None)
|
d.callback(None)
|
||||||
|
|
||||||
reactor.callLater(2.5, done)
|
reactor.callLater(2.5, done)
|
||||||
log.msg("test_deferred() returning deferred: %r" % (d,))
|
log.msg("test_deferred() returning deferred: %r" % (d,))
|
||||||
return d
|
return d
|
||||||
|
@ -136,7 +136,7 @@ def test_generic(testdir):
|
||||||
def done():
|
def done():
|
||||||
log.msg("test_deferred2.done() CALLBACK DONE")
|
log.msg("test_deferred2.done() CALLBACK DONE")
|
||||||
d.callback(None)
|
d.callback(None)
|
||||||
|
|
||||||
reactor.callLater(2.5, done)
|
reactor.callLater(2.5, done)
|
||||||
log.msg("test_deferred2() returning deferred: %r" % (d,))
|
log.msg("test_deferred2() returning deferred: %r" % (d,))
|
||||||
return d
|
return d
|
||||||
|
@ -157,7 +157,7 @@ def test_generic(testdir):
|
||||||
def done():
|
def done():
|
||||||
log.msg("test_deferred3.done() CALLBACK DONE")
|
log.msg("test_deferred3.done() CALLBACK DONE")
|
||||||
d.callback(None)
|
d.callback(None)
|
||||||
|
|
||||||
reactor.callLater(2.5, done)
|
reactor.callLater(2.5, done)
|
||||||
log.msg("test_deferred3() returning deferred: %r" % (d,))
|
log.msg("test_deferred3() returning deferred: %r" % (d,))
|
||||||
return d
|
return d
|
||||||
|
@ -172,7 +172,7 @@ def test_generic(testdir):
|
||||||
def done():
|
def done():
|
||||||
log.msg("TestTwistedSetupMethod.test_deferred() CALLBACK DONE")
|
log.msg("TestTwistedSetupMethod.test_deferred() CALLBACK DONE")
|
||||||
d.callback(None)
|
d.callback(None)
|
||||||
|
|
||||||
reactor.callLater(2.5, done)
|
reactor.callLater(2.5, done)
|
||||||
log.msg("TestTwistedSetupMethod.test_deferred() returning deferred: %r" % (d,))
|
log.msg("TestTwistedSetupMethod.test_deferred() returning deferred: %r" % (d,))
|
||||||
return d
|
return d
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
|
|
||||||
pygreen: experimental IO and execnet operations through greenlets
|
pygreen: experimental IO and execnet operations through greenlets
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
"""
|
"""
|
||||||
this little helper allows to run tests multiple times
|
this little helper allows to run tests multiple times
|
||||||
in the same process. useful for running tests from
|
in the same process. useful for running tests from
|
||||||
a console.
|
a console.
|
||||||
|
|
||||||
NOTE: since 1.3.1 you can just call py.test.cmdline.main()
|
NOTE: since 1.3.1 you can just call py.test.cmdline.main()
|
||||||
multiple times - no special logic needed.
|
multiple times - no special logic needed.
|
||||||
"""
|
"""
|
||||||
import py, sys
|
import py, sys
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
py lib 1.0.0: XXX
|
py lib 1.0.0: XXX
|
||||||
======================================================================
|
======================================================================
|
||||||
|
|
||||||
Welcome to the 1.0.0 py lib release - a library aiming to
|
Welcome to the 1.0.0 py lib release - a library aiming to
|
||||||
support agile and test-driven python development on various levels.
|
support agile and test-driven python development on various levels.
|
||||||
|
|
||||||
XXX
|
XXX
|
||||||
|
|
|
@ -1,17 +1,17 @@
|
||||||
py lib 0.9.2: bugfix release
|
py lib 0.9.2: bugfix release
|
||||||
=============================
|
=============================
|
||||||
|
|
||||||
Welcome to the 0.9.2 py lib and py.test release -
|
Welcome to the 0.9.2 py lib and py.test release -
|
||||||
mainly fixing Windows issues, providing better
|
mainly fixing Windows issues, providing better
|
||||||
packaging and integration with setuptools.
|
packaging and integration with setuptools.
|
||||||
|
|
||||||
Here is a quick summary of what the py lib provides:
|
Here is a quick summary of what the py lib provides:
|
||||||
|
|
||||||
* py.test: cross-project testing tool with many advanced features
|
* py.test: cross-project testing tool with many advanced features
|
||||||
* 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.magic.greenlet: micro-threads on standard CPython ("stackless-light")
|
* py.magic.greenlet: micro-threads on standard CPython ("stackless-light")
|
||||||
* py.path: path abstractions over local and subversion files
|
* py.path: path abstractions over local and subversion files
|
||||||
* rich documentation of py's exported API
|
* rich documentation of py's exported API
|
||||||
* tested against Linux, Win32, OSX, works on python 2.3-2.6
|
* tested against Linux, Win32, OSX, works on python 2.3-2.6
|
||||||
|
|
||||||
See here for more information:
|
See here for more information:
|
||||||
|
|
|
@ -9,47 +9,47 @@ many new advanced automated testing features - here is a quick summary:
|
||||||
|
|
||||||
* funcargs_ - pythonic zero-boilerplate fixtures for Python test functions :
|
* funcargs_ - pythonic zero-boilerplate fixtures for Python test functions :
|
||||||
|
|
||||||
- totally separates test code, test configuration and test setup
|
- totally separates test code, test configuration and test setup
|
||||||
- ideal for integration and functional tests
|
- ideal for integration and functional tests
|
||||||
- allows for flexible and natural test parametrization schemes
|
- allows for flexible and natural test parametrization schemes
|
||||||
|
|
||||||
* 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**.
|
* 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**.
|
||||||
|
|
||||||
* many new features done in easy-to-improve `default plugins`_, highlights:
|
* many new features done in easy-to-improve `default plugins`_, highlights:
|
||||||
|
|
||||||
* xfail: mark tests as "expected to fail" and report separately.
|
* xfail: mark tests as "expected to fail" and report separately.
|
||||||
* pastebin: automatically send tracebacks to pocoo paste service
|
* pastebin: automatically send tracebacks to pocoo paste service
|
||||||
* capture: flexibly capture stdout/stderr of subprocesses, per-test ...
|
* capture: flexibly capture stdout/stderr of subprocesses, per-test ...
|
||||||
* monkeypatch: safely monkeypatch modules/classes from within tests
|
* monkeypatch: safely monkeypatch modules/classes from within tests
|
||||||
* unittest: run and integrate traditional unittest.py tests
|
* unittest: run and integrate traditional unittest.py tests
|
||||||
* figleaf: generate html coverage reports with the figleaf module
|
* figleaf: generate html coverage reports with the figleaf module
|
||||||
* resultlog: generate buildbot-friendly reporting output
|
* resultlog: generate buildbot-friendly reporting output
|
||||||
* ...
|
* ...
|
||||||
|
|
||||||
* `distributed testing`_ and `elastic distributed execution`_:
|
* `distributed testing`_ and `elastic distributed execution`_:
|
||||||
|
|
||||||
- new unified "TX" URL scheme for specifying remote processes
|
- new unified "TX" URL scheme for specifying remote processes
|
||||||
- new distribution modes "--dist=each" and "--dist=load"
|
- new distribution modes "--dist=each" and "--dist=load"
|
||||||
- new sync/async ways to handle 1:N communication
|
- new sync/async ways to handle 1:N communication
|
||||||
- improved documentation
|
- improved documentation
|
||||||
|
|
||||||
The py lib continues to offer most of the functionality used by
|
The py lib continues to offer most of the functionality used by
|
||||||
the testing tool in `independent namespaces`_.
|
the testing tool in `independent namespaces`_.
|
||||||
|
|
||||||
Some non-test related code, notably greenlets/co-routines and
|
Some non-test related code, notably greenlets/co-routines and
|
||||||
api-generation now live as their own projects which simplifies the
|
api-generation now live as their own projects which simplifies the
|
||||||
installation procedure because no C-Extensions are required anymore.
|
installation procedure because no C-Extensions are required anymore.
|
||||||
|
|
||||||
The whole package should work well with Linux, Win32 and OSX, on Python
|
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!)
|
2.3, 2.4, 2.5 and 2.6. (Expect Python3 compatibility soon!)
|
||||||
|
|
||||||
For more info, see the py.test and py lib documentation:
|
For more info, see the py.test and py lib documentation:
|
||||||
|
|
||||||
http://pytest.org
|
http://pytest.org
|
||||||
|
|
||||||
http://pylib.org
|
http://pylib.org
|
||||||
|
|
||||||
have fun,
|
have fun,
|
||||||
holger
|
holger
|
||||||
|
|
||||||
.. _`independent namespaces`: http://pylib.org
|
.. _`independent namespaces`: http://pylib.org
|
||||||
|
@ -58,6 +58,6 @@ holger
|
||||||
.. _`default plugins`: http://codespeak.net/py/dist/test/plugin/index.html
|
.. _`default plugins`: http://codespeak.net/py/dist/test/plugin/index.html
|
||||||
.. _`distributed testing`: http://codespeak.net/py/dist/test/dist.html
|
.. _`distributed testing`: http://codespeak.net/py/dist/test/dist.html
|
||||||
.. _`elastic distributed execution`: http://codespeak.net/py/dist/execnet.html
|
.. _`elastic distributed execution`: http://codespeak.net/py/dist/execnet.html
|
||||||
.. _`1.0.0 py lib release`: http://pypi.python.org/pypi/py
|
.. _`1.0.0 py lib release`: http://pypi.python.org/pypi/py
|
||||||
.. _`oejskit`: http://codespeak.net/py/dist/test/plugin/oejskit.html
|
.. _`oejskit`: http://codespeak.net/py/dist/test/plugin/oejskit.html
|
||||||
|
|
||||||
|
|
|
@ -1,48 +1,48 @@
|
||||||
1.0.1: improved reporting, nose/unittest.py support, bug fixes
|
1.0.1: improved reporting, nose/unittest.py support, bug fixes
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
This is a bugfix release of pylib/py.test also coming with:
|
This is a bugfix release of pylib/py.test also coming with:
|
||||||
|
|
||||||
* improved documentation, improved navigation
|
* improved documentation, improved navigation
|
||||||
* test failure reporting improvements
|
* test failure reporting improvements
|
||||||
* support for directly running existing nose/unittest.py style tests
|
* support for directly running existing nose/unittest.py style tests
|
||||||
|
|
||||||
visit here for more info, including quickstart and tutorials:
|
visit here for more info, including quickstart and tutorials:
|
||||||
|
|
||||||
http://pytest.org and http://pylib.org
|
http://pytest.org and http://pylib.org
|
||||||
|
|
||||||
|
|
||||||
Changelog 1.0.0 to 1.0.1
|
Changelog 1.0.0 to 1.0.1
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
* added a default 'pytest_nose' plugin which handles nose.SkipTest,
|
* added a default 'pytest_nose' plugin which handles nose.SkipTest,
|
||||||
nose-style function/method/generator setup/teardown and
|
nose-style function/method/generator setup/teardown and
|
||||||
tries to report functions correctly.
|
tries to report functions correctly.
|
||||||
|
|
||||||
* improved documentation, better navigation: see http://pytest.org
|
* improved documentation, better navigation: see http://pytest.org
|
||||||
|
|
||||||
* added a "--help-config" option to show conftest.py / ENV-var names for
|
* added a "--help-config" option to show conftest.py / ENV-var names for
|
||||||
all longopt cmdline options, and some special conftest.py variables.
|
all longopt cmdline options, and some special conftest.py variables.
|
||||||
renamed 'conf_capture' conftest setting to 'option_capture' accordingly.
|
renamed 'conf_capture' conftest setting to 'option_capture' accordingly.
|
||||||
|
|
||||||
* unicode fixes: capturing and unicode writes to sys.stdout
|
* unicode fixes: capturing and unicode writes to sys.stdout
|
||||||
(through e.g a print statement) now work within tests,
|
(through e.g a print statement) now work within tests,
|
||||||
they are encoded as "utf8" by default, also terminalwriting
|
they are encoded as "utf8" by default, also terminalwriting
|
||||||
was adapted and somewhat unified between windows and linux
|
was adapted and somewhat unified between windows and linux
|
||||||
|
|
||||||
* fix issue #27: better reporting on non-collectable items given on commandline
|
* fix issue #27: better reporting on non-collectable items given on commandline
|
||||||
(e.g. pyc files)
|
(e.g. pyc files)
|
||||||
|
|
||||||
* fix issue #33: added --version flag (thanks Benjamin Peterson)
|
* fix issue #33: added --version flag (thanks Benjamin Peterson)
|
||||||
|
|
||||||
* fix issue #32: adding support for "incomplete" paths to wcpath.status()
|
* fix issue #32: adding support for "incomplete" paths to wcpath.status()
|
||||||
|
|
||||||
* "Test" prefixed classes are *not* collected by default anymore if they
|
* "Test" prefixed classes are *not* collected by default anymore if they
|
||||||
have an __init__ method
|
have an __init__ method
|
||||||
|
|
||||||
* monkeypatch setenv() now accepts a "prepend" parameter
|
* monkeypatch setenv() now accepts a "prepend" parameter
|
||||||
|
|
||||||
* improved reporting of collection error tracebacks
|
* improved reporting of collection error tracebacks
|
||||||
|
|
||||||
* simplified multicall mechanism and plugin architecture,
|
* simplified multicall mechanism and plugin architecture,
|
||||||
renamed some internal methods and argnames
|
renamed some internal methods and argnames
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
1.0.2: packaging fixes
|
1.0.2: packaging fixes
|
||||||
-----------------------------------------------------------------------
|
-----------------------------------------------------------------------
|
||||||
|
|
||||||
this release is purely a release for fixing packaging issues.
|
this release is purely a release for fixing packaging issues.
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
py.test/pylib 1.1.0: Python3, Jython, advanced skipping, cleanups ...
|
py.test/pylib 1.1.0: Python3, Jython, advanced skipping, cleanups ...
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
Features:
|
Features:
|
||||||
|
@ -10,16 +10,16 @@ Features:
|
||||||
Fixes:
|
Fixes:
|
||||||
|
|
||||||
* code reduction and "de-magification" (e.g. 23 KLoc -> 11 KLOC)
|
* code reduction and "de-magification" (e.g. 23 KLoc -> 11 KLOC)
|
||||||
* distribute testing requires the now separately released execnet_ package
|
* distribute testing requires the now separately released execnet_ package
|
||||||
* funcarg-setup/caching, "same-name" test modules now cause an exlicit error
|
* funcarg-setup/caching, "same-name" test modules now cause an exlicit error
|
||||||
* de-cluttered reporting options, --report for skipped/xfail details
|
* de-cluttered reporting options, --report for skipped/xfail details
|
||||||
|
|
||||||
Compatibilities
|
Compatibilities
|
||||||
|
|
||||||
1.1.0 should allow running test code that already worked well with 1.0.2
|
1.1.0 should allow running test code that already worked well with 1.0.2
|
||||||
plus some more due to improved unittest/nose compatibility.
|
plus some more due to improved unittest/nose compatibility.
|
||||||
|
|
||||||
More information: http://pytest.org
|
More information: http://pytest.org
|
||||||
|
|
||||||
thanks and have fun,
|
thanks and have fun,
|
||||||
|
|
||||||
|
@ -36,16 +36,16 @@ Changelog 1.0.2 -> 1.1.0
|
||||||
|
|
||||||
* remove py.rest tool and internal namespace - it was
|
* remove py.rest tool and internal namespace - it was
|
||||||
never really advertised and can still be used with
|
never really advertised and can still be used with
|
||||||
the old release if needed. If there is interest
|
the old release if needed. If there is interest
|
||||||
it could be revived into its own tool i guess.
|
it could be revived into its own tool i guess.
|
||||||
|
|
||||||
* fix issue48 and issue59: raise an Error if the module
|
* fix issue48 and issue59: raise an Error if the module
|
||||||
from an imported test file does not seem to come from
|
from an imported test file does not seem to come from
|
||||||
the filepath - avoids "same-name" confusion that has
|
the filepath - avoids "same-name" confusion that has
|
||||||
been reported repeatedly
|
been reported repeatedly
|
||||||
|
|
||||||
* merged Ronny's nose-compatibility hacks: now
|
* merged Ronny's nose-compatibility hacks: now
|
||||||
nose-style setup_module() and setup() functions are
|
nose-style setup_module() and setup() functions are
|
||||||
supported
|
supported
|
||||||
|
|
||||||
* introduce generalized py.test.mark function marking
|
* introduce generalized py.test.mark function marking
|
||||||
|
@ -54,62 +54,62 @@ Changelog 1.0.2 -> 1.1.0
|
||||||
|
|
||||||
* deprecate parser.addgroup in favour of getgroup which creates option group
|
* deprecate parser.addgroup in favour of getgroup which creates option group
|
||||||
|
|
||||||
* add --report command line option that allows to control showing of skipped/xfailed sections
|
* add --report command line option that allows to control showing of skipped/xfailed sections
|
||||||
|
|
||||||
* generalized skipping: a new way to mark python functions with skipif or xfail
|
* generalized skipping: a new way to mark python functions with skipif or xfail
|
||||||
at function, class and modules level based on platform or sys-module attributes.
|
at function, class and modules level based on platform or sys-module attributes.
|
||||||
|
|
||||||
* extend py.test.mark decorator to allow for positional args
|
* extend py.test.mark decorator to allow for positional args
|
||||||
|
|
||||||
* introduce and test "py.cleanup -d" to remove empty directories
|
* introduce and test "py.cleanup -d" to remove empty directories
|
||||||
|
|
||||||
* fix issue #59 - robustify unittest test collection
|
* fix issue #59 - robustify unittest test collection
|
||||||
|
|
||||||
* make bpython/help interaction work by adding an __all__ attribute
|
* make bpython/help interaction work by adding an __all__ attribute
|
||||||
to ApiModule, cleanup initpkg
|
to ApiModule, cleanup initpkg
|
||||||
|
|
||||||
* use MIT license for pylib, add some contributors
|
* use MIT license for pylib, add some contributors
|
||||||
|
|
||||||
* remove py.execnet code and substitute all usages with 'execnet' proper
|
* remove py.execnet code and substitute all usages with 'execnet' proper
|
||||||
|
|
||||||
* fix issue50 - cached_setup now caches more to expectations
|
* fix issue50 - cached_setup now caches more to expectations
|
||||||
for test functions with multiple arguments.
|
for test functions with multiple arguments.
|
||||||
|
|
||||||
* merge Jarko's fixes, issue #45 and #46
|
* merge Jarko's fixes, issue #45 and #46
|
||||||
|
|
||||||
* add the ability to specify a path for py.lookup to search in
|
* add the ability to specify a path for py.lookup to search in
|
||||||
|
|
||||||
* fix a funcarg cached_setup bug probably only occuring
|
* fix a funcarg cached_setup bug probably only occuring
|
||||||
in distributed testing and "module" scope with teardown.
|
in distributed testing and "module" scope with teardown.
|
||||||
|
|
||||||
* many fixes and changes for making the code base python3 compatible,
|
* many fixes and changes for making the code base python3 compatible,
|
||||||
many thanks to Benjamin Peterson for helping with this.
|
many thanks to Benjamin Peterson for helping with this.
|
||||||
|
|
||||||
* consolidate builtins implementation to be compatible with >=2.3,
|
* consolidate builtins implementation to be compatible with >=2.3,
|
||||||
add helpers to ease keeping 2 and 3k compatible code
|
add helpers to ease keeping 2 and 3k compatible code
|
||||||
|
|
||||||
* deprecate py.compat.doctest|subprocess|textwrap|optparse
|
* deprecate py.compat.doctest|subprocess|textwrap|optparse
|
||||||
|
|
||||||
* deprecate py.magic.autopath, remove py/magic directory
|
* deprecate py.magic.autopath, remove py/magic directory
|
||||||
|
|
||||||
* move pytest assertion handling to py/code and a pytest_assertion
|
* move pytest assertion handling to py/code and a pytest_assertion
|
||||||
plugin, add "--no-assert" option, deprecate py.magic namespaces
|
plugin, add "--no-assert" option, deprecate py.magic namespaces
|
||||||
in favour of (less) py.code ones.
|
in favour of (less) py.code ones.
|
||||||
|
|
||||||
* consolidate and cleanup py/code classes and files
|
* consolidate and cleanup py/code classes and files
|
||||||
|
|
||||||
* cleanup py/misc, move tests to bin-for-dist
|
* cleanup py/misc, move tests to bin-for-dist
|
||||||
|
|
||||||
* introduce delattr/delitem/delenv methods to py.test's monkeypatch funcarg
|
* introduce delattr/delitem/delenv methods to py.test's monkeypatch funcarg
|
||||||
|
|
||||||
* consolidate py.log implementation, remove old approach.
|
* consolidate py.log implementation, remove old approach.
|
||||||
|
|
||||||
* introduce py.io.TextIO and py.io.BytesIO for distinguishing between
|
* introduce py.io.TextIO and py.io.BytesIO for distinguishing between
|
||||||
text/unicode and byte-streams (uses underlying standard lib io.*
|
text/unicode and byte-streams (uses underlying standard lib io.*
|
||||||
if available)
|
if available)
|
||||||
|
|
||||||
* make py.unittest_convert helper script available which converts "unittest.py"
|
* make py.unittest_convert helper script available which converts "unittest.py"
|
||||||
style files into the simpler assert/direct-test-classes py.test/nosetests
|
style files into the simpler assert/direct-test-classes py.test/nosetests
|
||||||
style. The script was written by Laura Creighton.
|
style. The script was written by Laura Creighton.
|
||||||
|
|
||||||
* simplified internal localpath implementation
|
* simplified internal localpath implementation
|
||||||
|
|
|
@ -5,19 +5,19 @@ This is a compatibility fixing release of pylib/py.test to work
|
||||||
better with previous 1.0.x test code bases. It also contains fixes
|
better with previous 1.0.x test code bases. It also contains fixes
|
||||||
and changes to work with `execnet>=1.0.0`_ to provide distributed
|
and changes to work with `execnet>=1.0.0`_ to provide distributed
|
||||||
testing and looponfailing testing modes. py-1.1.1 also introduces
|
testing and looponfailing testing modes. py-1.1.1 also introduces
|
||||||
a new mechanism for registering plugins via setuptools.
|
a new mechanism for registering plugins via setuptools.
|
||||||
|
|
||||||
What is pylib/py.test?
|
What is pylib/py.test?
|
||||||
-----------------------
|
-----------------------
|
||||||
|
|
||||||
py.test is an advanced automated testing tool working with
|
py.test is an advanced automated testing tool working with
|
||||||
Python2, Python3 and Jython versions on all major operating
|
Python2, Python3 and Jython versions on all major operating
|
||||||
systems. It has an extensive plugin architecture and can run many
|
systems. It has an extensive plugin architecture and can run many
|
||||||
existing common Python test suites without modification. Moreover,
|
existing common Python test suites without modification. Moreover,
|
||||||
it offers some unique features not found in other
|
it offers some unique features not found in other
|
||||||
testing tools. See http://pytest.org for more info.
|
testing tools. See http://pytest.org for more info.
|
||||||
|
|
||||||
The pylib also contains a localpath and svnpath implementation
|
The pylib also contains a localpath and svnpath implementation
|
||||||
and some developer-oriented command line tools. See
|
and some developer-oriented command line tools. See
|
||||||
http://pylib.org for more info.
|
http://pylib.org for more info.
|
||||||
|
|
||||||
|
@ -31,15 +31,15 @@ holger (http://twitter.com/hpk42)
|
||||||
Changes between 1.1.1 and 1.1.0
|
Changes between 1.1.1 and 1.1.0
|
||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
- introduce automatic plugin registration via 'pytest11'
|
- introduce automatic plugin registration via 'pytest11'
|
||||||
entrypoints via setuptools' pkg_resources.iter_entry_points
|
entrypoints via setuptools' pkg_resources.iter_entry_points
|
||||||
|
|
||||||
- fix py.test dist-testing to work with execnet >= 1.0.0b4
|
- fix py.test dist-testing to work with execnet >= 1.0.0b4
|
||||||
|
|
||||||
- re-introduce py.test.cmdline.main() for better backward compatibility
|
- re-introduce py.test.cmdline.main() for better backward compatibility
|
||||||
|
|
||||||
- svn paths: fix a bug with path.check(versioned=True) for svn paths,
|
- svn paths: fix a bug with path.check(versioned=True) for svn paths,
|
||||||
allow '%' in svn paths, make svnwc.update() default to interactive mode
|
allow '%' in svn paths, make svnwc.update() default to interactive mode
|
||||||
like in 1.0.x and add svnwc.update(interactive=False) to inhibit interaction.
|
like in 1.0.x and add svnwc.update(interactive=False) to inhibit interaction.
|
||||||
|
|
||||||
- refine distributed tarball to contain test and no pyc files
|
- refine distributed tarball to contain test and no pyc files
|
||||||
|
|
|
@ -3,28 +3,28 @@ py.test/pylib 1.2.0: junitxml, standalone test scripts, pluginization
|
||||||
|
|
||||||
py.test is an advanced automated testing tool working with
|
py.test is an advanced automated testing tool working with
|
||||||
Python2, Python3 and Jython versions on all major operating
|
Python2, Python3 and Jython versions on all major operating
|
||||||
systems. It has a simple plugin architecture and can run many
|
systems. It has a simple plugin architecture and can run many
|
||||||
existing common Python test suites without modification. It offers
|
existing common Python test suites without modification. It offers
|
||||||
some unique features not found in other testing tools.
|
some unique features not found in other testing tools.
|
||||||
See http://pytest.org for more info.
|
See http://pytest.org for more info.
|
||||||
|
|
||||||
py.test 1.2.0 brings many bug fixes and interesting new abilities:
|
py.test 1.2.0 brings many bug fixes and interesting new abilities:
|
||||||
|
|
||||||
* --junitxml=path will create an XML file for use with CI processing
|
* --junitxml=path will create an XML file for use with CI processing
|
||||||
* --genscript=path creates a standalone py.test-equivalent test-script
|
* --genscript=path creates a standalone py.test-equivalent test-script
|
||||||
* --ignore=path prevents collection of anything below that path
|
* --ignore=path prevents collection of anything below that path
|
||||||
* --confcutdir=path only lookup conftest.py test configs below that path
|
* --confcutdir=path only lookup conftest.py test configs below that path
|
||||||
* a 'pytest_report_header' hook to add info to the terminal report header
|
* a 'pytest_report_header' hook to add info to the terminal report header
|
||||||
* a 'pytestconfig' function argument gives direct access to option values
|
* a 'pytestconfig' function argument gives direct access to option values
|
||||||
* 'pytest_generate_tests' can now be put into a class as well
|
* 'pytest_generate_tests' can now be put into a class as well
|
||||||
* on CPython py.test additionally installs as "py.test-VERSION", on
|
* on CPython py.test additionally installs as "py.test-VERSION", on
|
||||||
Jython as py.test-jython and on PyPy as py.test-pypy-XYZ
|
Jython as py.test-jython and on PyPy as py.test-pypy-XYZ
|
||||||
|
|
||||||
Apart from many bug fixes 1.2.0 also has better pluginization:
|
Apart from many bug fixes 1.2.0 also has better pluginization:
|
||||||
Distributed testing and looponfailing testing now live in the
|
Distributed testing and looponfailing testing now live in the
|
||||||
separately installable 'pytest-xdist' plugin. The same is true for
|
separately installable 'pytest-xdist' plugin. The same is true for
|
||||||
'pytest-figleaf' for doing coverage reporting. Those two plugins
|
'pytest-figleaf' for doing coverage reporting. Those two plugins
|
||||||
can serve well now as blue prints for doing your own.
|
can serve well now as blue prints for doing your own.
|
||||||
|
|
||||||
thanks to all who helped and gave feedback,
|
thanks to all who helped and gave feedback,
|
||||||
have fun,
|
have fun,
|
||||||
|
@ -34,45 +34,45 @@ holger krekel, January 2010
|
||||||
Changes between 1.2.0 and 1.1.1
|
Changes between 1.2.0 and 1.1.1
|
||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
- moved dist/looponfailing from py.test core into a new
|
- moved dist/looponfailing from py.test core into a new
|
||||||
separately released pytest-xdist plugin.
|
separately released pytest-xdist plugin.
|
||||||
|
|
||||||
- new junitxml plugin: --junitxml=path will generate a junit style xml file
|
- new junitxml plugin: --junitxml=path will generate a junit style xml file
|
||||||
which is processable e.g. by the Hudson CI system.
|
which is processable e.g. by the Hudson CI system.
|
||||||
|
|
||||||
- new option: --genscript=path will generate a standalone py.test script
|
- new option: --genscript=path will generate a standalone py.test script
|
||||||
which will not need any libraries installed. thanks to Ralf Schmitt.
|
which will not need any libraries installed. thanks to Ralf Schmitt.
|
||||||
|
|
||||||
- new option: --ignore will prevent specified path from collection.
|
- new option: --ignore will prevent specified path from collection.
|
||||||
Can be specified multiple times.
|
Can be specified multiple times.
|
||||||
|
|
||||||
- new option: --confcutdir=dir will make py.test only consider conftest
|
- new option: --confcutdir=dir will make py.test only consider conftest
|
||||||
files that are relative to the specified dir.
|
files that are relative to the specified dir.
|
||||||
|
|
||||||
- new funcarg: "pytestconfig" is the pytest config object for access
|
- new funcarg: "pytestconfig" is the pytest config object for access
|
||||||
to command line args and can now be easily used in a test.
|
to command line args and can now be easily used in a test.
|
||||||
|
|
||||||
- install 'py.test' and `py.which` with a ``-$VERSION`` suffix to
|
- install 'py.test' and `py.which` with a ``-$VERSION`` suffix to
|
||||||
disambiguate between Python3, python2.X, Jython and PyPy installed versions.
|
disambiguate between Python3, python2.X, Jython and PyPy installed versions.
|
||||||
|
|
||||||
- new "pytestconfig" funcarg allows access to test config object
|
- new "pytestconfig" funcarg allows access to test config object
|
||||||
|
|
||||||
- new "pytest_report_header" hook can return additional lines
|
- new "pytest_report_header" hook can return additional lines
|
||||||
to be displayed at the header of a test run.
|
to be displayed at the header of a test run.
|
||||||
|
|
||||||
- (experimental) allow "py.test path::name1::name2::..." for pointing
|
- (experimental) allow "py.test path::name1::name2::..." for pointing
|
||||||
to a test within a test collection directly. This might eventually
|
to a test within a test collection directly. This might eventually
|
||||||
evolve as a full substitute to "-k" specifications.
|
evolve as a full substitute to "-k" specifications.
|
||||||
|
|
||||||
- streamlined plugin loading: order is now as documented in
|
- streamlined plugin loading: order is now as documented in
|
||||||
customize.html: setuptools, ENV, commandline, conftest.
|
customize.html: setuptools, ENV, commandline, conftest.
|
||||||
also setuptools entry point names are turned to canonical namees ("pytest_*")
|
also setuptools entry point names are turned to canonical namees ("pytest_*")
|
||||||
|
|
||||||
- automatically skip tests that need 'capfd' but have no os.dup
|
- automatically skip tests that need 'capfd' but have no os.dup
|
||||||
|
|
||||||
- allow pytest_generate_tests to be defined in classes as well
|
- allow pytest_generate_tests to be defined in classes as well
|
||||||
|
|
||||||
- deprecate usage of 'disabled' attribute in favour of pytestmark
|
- deprecate usage of 'disabled' attribute in favour of pytestmark
|
||||||
- deprecate definition of Directory, Module, Class and Function nodes
|
- deprecate definition of Directory, Module, Class and Function nodes
|
||||||
in conftest.py files. Use pytest collect hooks instead.
|
in conftest.py files. Use pytest collect hooks instead.
|
||||||
|
|
||||||
|
@ -87,28 +87,28 @@ Changes between 1.2.0 and 1.1.1
|
||||||
change its long command line options to be a bit shorter (see py.test -h).
|
change its long command line options to be a bit shorter (see py.test -h).
|
||||||
|
|
||||||
- change: pytest doctest plugin is now enabled by default and has a
|
- change: pytest doctest plugin is now enabled by default and has a
|
||||||
new option --doctest-glob to set a pattern for file matches.
|
new option --doctest-glob to set a pattern for file matches.
|
||||||
|
|
||||||
- change: remove internal py._* helper vars, only keep py._pydir
|
- change: remove internal py._* helper vars, only keep py._pydir
|
||||||
|
|
||||||
- robustify capturing to survive if custom pytest_runtest_setup
|
- robustify capturing to survive if custom pytest_runtest_setup
|
||||||
code failed and prevented the capturing setup code from running.
|
code failed and prevented the capturing setup code from running.
|
||||||
|
|
||||||
- make py.test.* helpers provided by default plugins visible early -
|
- make py.test.* helpers provided by default plugins visible early -
|
||||||
works transparently both for pydoc and for interactive sessions
|
works transparently both for pydoc and for interactive sessions
|
||||||
which will regularly see e.g. py.test.mark and py.test.importorskip.
|
which will regularly see e.g. py.test.mark and py.test.importorskip.
|
||||||
|
|
||||||
- simplify internal plugin manager machinery
|
- simplify internal plugin manager machinery
|
||||||
- simplify internal collection tree by introducing a RootCollector node
|
- simplify internal collection tree by introducing a RootCollector node
|
||||||
|
|
||||||
- fix assert reinterpreation that sees a call containing "keyword=..."
|
- fix assert reinterpreation that sees a call containing "keyword=..."
|
||||||
|
|
||||||
- fix issue66: invoke pytest_sessionstart and pytest_sessionfinish
|
- fix issue66: invoke pytest_sessionstart and pytest_sessionfinish
|
||||||
hooks on slaves during dist-testing, report module/session teardown
|
hooks on slaves during dist-testing, report module/session teardown
|
||||||
hooks correctly.
|
hooks correctly.
|
||||||
|
|
||||||
- fix issue65: properly handle dist-testing if no
|
- fix issue65: properly handle dist-testing if no
|
||||||
execnet/py lib installed remotely.
|
execnet/py lib installed remotely.
|
||||||
|
|
||||||
- skip some install-tests if no execnet is available
|
- skip some install-tests if no execnet is available
|
||||||
|
|
||||||
|
|
|
@ -1,29 +1,29 @@
|
||||||
py.test/pylib 1.2.1: little fixes and improvements
|
py.test/pylib 1.2.1: little fixes and improvements
|
||||||
--------------------------------------------------------------------------------
|
--------------------------------------------------------------------------------
|
||||||
|
|
||||||
py.test is an advanced automated testing tool working with
|
py.test is an advanced automated testing tool working with
|
||||||
Python2, Python3 and Jython versions on all major operating
|
Python2, Python3 and Jython versions on all major operating
|
||||||
systems. It has a simple plugin architecture and can run many
|
systems. It has a simple plugin architecture and can run many
|
||||||
existing common Python test suites without modification. It offers
|
existing common Python test suites without modification. It offers
|
||||||
some unique features not found in other testing tools.
|
some unique features not found in other testing tools.
|
||||||
See http://pytest.org for more info.
|
See http://pytest.org for more info.
|
||||||
|
|
||||||
py.test 1.2.1 brings bug fixes and some new options and abilities triggered
|
py.test 1.2.1 brings bug fixes and some new options and abilities triggered
|
||||||
by user feedback:
|
by user feedback:
|
||||||
|
|
||||||
* --funcargs [testpath] will show available builtin- and project funcargs.
|
* --funcargs [testpath] will show available builtin- and project funcargs.
|
||||||
* display a short and concise traceback if funcarg lookup fails.
|
* display a short and concise traceback if funcarg lookup fails.
|
||||||
* early-load "conftest.py" files in non-dot first-level sub directories.
|
* early-load "conftest.py" files in non-dot first-level sub directories.
|
||||||
* --tb=line will print a single line for each failing test (issue67)
|
* --tb=line will print a single line for each failing test (issue67)
|
||||||
* py.cleanup has a number of new options, cleanups up setup.py related files
|
* py.cleanup has a number of new options, cleanups up setup.py related files
|
||||||
* fix issue78: always call python-level teardown functions even if the
|
* fix issue78: always call python-level teardown functions even if the
|
||||||
according setup failed.
|
according setup failed.
|
||||||
|
|
||||||
For more detailed information see the changelog below.
|
For more detailed information see the changelog below.
|
||||||
|
|
||||||
cheers and have fun,
|
cheers and have fun,
|
||||||
|
|
||||||
holger
|
holger
|
||||||
|
|
||||||
|
|
||||||
Changes between 1.2.1 and 1.2.0
|
Changes between 1.2.1 and 1.2.0
|
||||||
|
@ -34,33 +34,33 @@ Changes between 1.2.1 and 1.2.0
|
||||||
py.cleanup # remove "*.pyc" and "*$py.class" (jython) files
|
py.cleanup # remove "*.pyc" and "*$py.class" (jython) files
|
||||||
py.cleanup -e .swp -e .cache # also remove files with these extensions
|
py.cleanup -e .swp -e .cache # also remove files with these extensions
|
||||||
py.cleanup -s # remove "build" and "dist" directory next to setup.py files
|
py.cleanup -s # remove "build" and "dist" directory next to setup.py files
|
||||||
py.cleanup -d # also remove empty directories
|
py.cleanup -d # also remove empty directories
|
||||||
py.cleanup -a # synonym for "-s -d -e 'pip-log.txt'"
|
py.cleanup -a # synonym for "-s -d -e 'pip-log.txt'"
|
||||||
py.cleanup -n # dry run, only show what would be removed
|
py.cleanup -n # dry run, only show what would be removed
|
||||||
|
|
||||||
- add a new option "py.test --funcargs" which shows available funcargs
|
- add a new option "py.test --funcargs" which shows available funcargs
|
||||||
and their help strings (docstrings on their respective factory function)
|
and their help strings (docstrings on their respective factory function)
|
||||||
for a given test path
|
for a given test path
|
||||||
|
|
||||||
- display a short and concise traceback if a funcarg lookup fails
|
- display a short and concise traceback if a funcarg lookup fails
|
||||||
|
|
||||||
- early-load "conftest.py" files in non-dot first-level sub directories.
|
- early-load "conftest.py" files in non-dot first-level sub directories.
|
||||||
allows to conveniently keep and access test-related options in a ``test``
|
allows to conveniently keep and access test-related options in a ``test``
|
||||||
subdir and still add command line options.
|
subdir and still add command line options.
|
||||||
|
|
||||||
- fix issue67: new super-short traceback-printing option: "--tb=line" will print a single line for each failing (python) test indicating its filename, lineno and the failure value
|
- fix issue67: new super-short traceback-printing option: "--tb=line" will print a single line for each failing (python) test indicating its filename, lineno and the failure value
|
||||||
|
|
||||||
- fix issue78: always call python-level teardown functions even if the
|
- fix issue78: always call python-level teardown functions even if the
|
||||||
according setup failed. This includes refinements for calling setup_module/class functions
|
according setup failed. This includes refinements for calling setup_module/class functions
|
||||||
which will now only be called once instead of the previous behaviour where they'd be called
|
which will now only be called once instead of the previous behaviour where they'd be called
|
||||||
multiple times if they raise an exception (including a Skipped exception). Any exception
|
multiple times if they raise an exception (including a Skipped exception). Any exception
|
||||||
will be re-corded and associated with all tests in the according module/class scope.
|
will be re-corded and associated with all tests in the according module/class scope.
|
||||||
|
|
||||||
- fix issue63: assume <40 columns to be a bogus terminal width, default to 80
|
- fix issue63: assume <40 columns to be a bogus terminal width, default to 80
|
||||||
|
|
||||||
- fix pdb debugging to be in the correct frame on raises-related errors
|
- fix pdb debugging to be in the correct frame on raises-related errors
|
||||||
|
|
||||||
- update apipkg.py to fix an issue where recursive imports might
|
- update apipkg.py to fix an issue where recursive imports might
|
||||||
unnecessarily break importing
|
unnecessarily break importing
|
||||||
|
|
||||||
- fix plugin links
|
- fix plugin links
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
py.test/pylib 1.3.0: new options, per-plugin hooks, fixes ...
|
py.test/pylib 1.3.0: new options, per-plugin hooks, fixes ...
|
||||||
===========================================================================
|
===========================================================================
|
||||||
|
|
||||||
The 1.3.0 release introduces new options, bug fixes and improved compatibility
|
The 1.3.0 release introduces new options, bug fixes and improved compatibility
|
||||||
with Python3 and Jython-2.5.1 on Windows. If you already use py-1.2 chances
|
with Python3 and Jython-2.5.1 on Windows. If you already use py-1.2 chances
|
||||||
are you can use py-1.3.0. See the below CHANGELOG for more details and
|
are you can use py-1.3.0. See the below CHANGELOG for more details and
|
||||||
http://pylib.org/install.html for installation instructions.
|
http://pylib.org/install.html for installation instructions.
|
||||||
|
|
||||||
py.test is an advanced automated testing tool working with Python2,
|
py.test is an advanced automated testing tool working with Python2,
|
||||||
Python3, Jython and PyPy versions on all major operating systems. It
|
Python3, Jython and PyPy versions on all major operating systems. It
|
||||||
|
@ -12,7 +12,7 @@ offers a no-boilerplate testing approach and has inspired other testing
|
||||||
tools and enhancements in the standard Python library for more than five
|
tools and enhancements in the standard Python library for more than five
|
||||||
years. It has a simple and extensive plugin architecture, configurable
|
years. It has a simple and extensive plugin architecture, configurable
|
||||||
reporting and provides unique ways to make it fit to your testing
|
reporting and provides unique ways to make it fit to your testing
|
||||||
process and needs.
|
process and needs.
|
||||||
|
|
||||||
See http://pytest.org for more info.
|
See http://pytest.org for more info.
|
||||||
|
|
||||||
|
@ -26,28 +26,28 @@ Changes between 1.2.1 and 1.3.0
|
||||||
- deprecate --report option in favour of a new shorter and easier to
|
- deprecate --report option in favour of a new shorter and easier to
|
||||||
remember -r option: it takes a string argument consisting of any
|
remember -r option: it takes a string argument consisting of any
|
||||||
combination of 'xfsX' characters. They relate to the single chars
|
combination of 'xfsX' characters. They relate to the single chars
|
||||||
you see during the dotted progress printing and will print an extra line
|
you see during the dotted progress printing and will print an extra line
|
||||||
per test at the end of the test run. This extra line indicates the exact
|
per test at the end of the test run. This extra line indicates the exact
|
||||||
position or test ID that you directly paste to the py.test cmdline in order
|
position or test ID that you directly paste to the py.test cmdline in order
|
||||||
to re-run a particular test.
|
to re-run a particular test.
|
||||||
|
|
||||||
- allow external plugins to register new hooks via the new
|
- allow external plugins to register new hooks via the new
|
||||||
pytest_addhooks(pluginmanager) hook. The new release of
|
pytest_addhooks(pluginmanager) hook. The new release of
|
||||||
the pytest-xdist plugin for distributed and looponfailing
|
the pytest-xdist plugin for distributed and looponfailing
|
||||||
testing requires this feature.
|
testing requires this feature.
|
||||||
|
|
||||||
- add a new pytest_ignore_collect(path, config) hook to allow projects and
|
- add a new pytest_ignore_collect(path, config) hook to allow projects and
|
||||||
plugins to define exclusion behaviour for their directory structure -
|
plugins to define exclusion behaviour for their directory structure -
|
||||||
for example you may define in a conftest.py this method::
|
for example you may define in a conftest.py this method::
|
||||||
|
|
||||||
def pytest_ignore_collect(path):
|
def pytest_ignore_collect(path):
|
||||||
return path.check(link=1)
|
return path.check(link=1)
|
||||||
|
|
||||||
to prevent even collection of any tests in symlinked dirs.
|
to prevent even collection of any tests in symlinked dirs.
|
||||||
|
|
||||||
- new pytest_pycollect_makemodule(path, parent) hook for
|
- new pytest_pycollect_makemodule(path, parent) hook for
|
||||||
allowing customization of the Module collection object for a
|
allowing customization of the Module collection object for a
|
||||||
matching test module.
|
matching test module.
|
||||||
|
|
||||||
- extend and refine xfail mechanism::
|
- extend and refine xfail mechanism::
|
||||||
|
|
||||||
|
@ -55,14 +55,14 @@ Changes between 1.2.1 and 1.3.0
|
||||||
@py.test.mark.xfail(reason="...") prints the reason string in xfail summaries
|
@py.test.mark.xfail(reason="...") prints the reason string in xfail summaries
|
||||||
|
|
||||||
specifiying ``--runxfail`` on command line ignores xfail markers to show
|
specifiying ``--runxfail`` on command line ignores xfail markers to show
|
||||||
you the underlying traceback.
|
you the underlying traceback.
|
||||||
|
|
||||||
- expose (previously internal) commonly useful methods:
|
- expose (previously internal) commonly useful methods:
|
||||||
py.io.get_terminal_with() -> return terminal width
|
py.io.get_terminal_with() -> return terminal width
|
||||||
py.io.ansi_print(...) -> print colored/bold text on linux/win32
|
py.io.ansi_print(...) -> print colored/bold text on linux/win32
|
||||||
py.io.saferepr(obj) -> return limited representation string
|
py.io.saferepr(obj) -> return limited representation string
|
||||||
|
|
||||||
- expose test outcome related exceptions as py.test.skip.Exception,
|
- expose test outcome related exceptions as py.test.skip.Exception,
|
||||||
py.test.raises.Exception etc., useful mostly for plugins
|
py.test.raises.Exception etc., useful mostly for plugins
|
||||||
doing special outcome interpretation/tweaking
|
doing special outcome interpretation/tweaking
|
||||||
|
|
||||||
|
@ -70,22 +70,22 @@ Changes between 1.2.1 and 1.3.0
|
||||||
|
|
||||||
- fix/refine python3 compatibility (thanks Benjamin Peterson)
|
- fix/refine python3 compatibility (thanks Benjamin Peterson)
|
||||||
|
|
||||||
- fixes for making the jython/win32 combination work, note however:
|
- fixes for making the jython/win32 combination work, note however:
|
||||||
jython2.5.1/win32 does not provide a command line launcher, see
|
jython2.5.1/win32 does not provide a command line launcher, see
|
||||||
http://bugs.jython.org/issue1491 . See pylib install documentation
|
http://bugs.jython.org/issue1491 . See pylib install documentation
|
||||||
for how to work around.
|
for how to work around.
|
||||||
|
|
||||||
- fixes for handling of unicode exception values and unprintable objects
|
- fixes for handling of unicode exception values and unprintable objects
|
||||||
|
|
||||||
- (issue87) fix unboundlocal error in assertionold code
|
- (issue87) fix unboundlocal error in assertionold code
|
||||||
|
|
||||||
- (issue86) improve documentation for looponfailing
|
- (issue86) improve documentation for looponfailing
|
||||||
|
|
||||||
- refine IO capturing: stdin-redirect pseudo-file now has a NOP close() method
|
- refine IO capturing: stdin-redirect pseudo-file now has a NOP close() method
|
||||||
|
|
||||||
- ship distribute_setup.py version 0.6.10
|
- ship distribute_setup.py version 0.6.10
|
||||||
|
|
||||||
- added links to the new capturelog and coverage plugins
|
- added links to the new capturelog and coverage plugins
|
||||||
|
|
||||||
|
|
||||||
Changes between 1.2.1 and 1.2.0
|
Changes between 1.2.1 and 1.2.0
|
||||||
|
@ -96,79 +96,79 @@ Changes between 1.2.1 and 1.2.0
|
||||||
py.cleanup # remove "*.pyc" and "*$py.class" (jython) files
|
py.cleanup # remove "*.pyc" and "*$py.class" (jython) files
|
||||||
py.cleanup -e .swp -e .cache # also remove files with these extensions
|
py.cleanup -e .swp -e .cache # also remove files with these extensions
|
||||||
py.cleanup -s # remove "build" and "dist" directory next to setup.py files
|
py.cleanup -s # remove "build" and "dist" directory next to setup.py files
|
||||||
py.cleanup -d # also remove empty directories
|
py.cleanup -d # also remove empty directories
|
||||||
py.cleanup -a # synonym for "-s -d -e 'pip-log.txt'"
|
py.cleanup -a # synonym for "-s -d -e 'pip-log.txt'"
|
||||||
py.cleanup -n # dry run, only show what would be removed
|
py.cleanup -n # dry run, only show what would be removed
|
||||||
|
|
||||||
- add a new option "py.test --funcargs" which shows available funcargs
|
- add a new option "py.test --funcargs" which shows available funcargs
|
||||||
and their help strings (docstrings on their respective factory function)
|
and their help strings (docstrings on their respective factory function)
|
||||||
for a given test path
|
for a given test path
|
||||||
|
|
||||||
- display a short and concise traceback if a funcarg lookup fails
|
- display a short and concise traceback if a funcarg lookup fails
|
||||||
|
|
||||||
- early-load "conftest.py" files in non-dot first-level sub directories.
|
- early-load "conftest.py" files in non-dot first-level sub directories.
|
||||||
allows to conveniently keep and access test-related options in a ``test``
|
allows to conveniently keep and access test-related options in a ``test``
|
||||||
subdir and still add command line options.
|
subdir and still add command line options.
|
||||||
|
|
||||||
- fix issue67: new super-short traceback-printing option: "--tb=line" will print a single line for each failing (python) test indicating its filename, lineno and the failure value
|
- fix issue67: new super-short traceback-printing option: "--tb=line" will print a single line for each failing (python) test indicating its filename, lineno and the failure value
|
||||||
|
|
||||||
- fix issue78: always call python-level teardown functions even if the
|
- fix issue78: always call python-level teardown functions even if the
|
||||||
according setup failed. This includes refinements for calling setup_module/class functions
|
according setup failed. This includes refinements for calling setup_module/class functions
|
||||||
which will now only be called once instead of the previous behaviour where they'd be called
|
which will now only be called once instead of the previous behaviour where they'd be called
|
||||||
multiple times if they raise an exception (including a Skipped exception). Any exception
|
multiple times if they raise an exception (including a Skipped exception). Any exception
|
||||||
will be re-corded and associated with all tests in the according module/class scope.
|
will be re-corded and associated with all tests in the according module/class scope.
|
||||||
|
|
||||||
- fix issue63: assume <40 columns to be a bogus terminal width, default to 80
|
- fix issue63: assume <40 columns to be a bogus terminal width, default to 80
|
||||||
|
|
||||||
- fix pdb debugging to be in the correct frame on raises-related errors
|
- fix pdb debugging to be in the correct frame on raises-related errors
|
||||||
|
|
||||||
- update apipkg.py to fix an issue where recursive imports might
|
- update apipkg.py to fix an issue where recursive imports might
|
||||||
unnecessarily break importing
|
unnecessarily break importing
|
||||||
|
|
||||||
- fix plugin links
|
- fix plugin links
|
||||||
|
|
||||||
Changes between 1.2 and 1.1.1
|
Changes between 1.2 and 1.1.1
|
||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
- moved dist/looponfailing from py.test core into a new
|
- moved dist/looponfailing from py.test core into a new
|
||||||
separately released pytest-xdist plugin.
|
separately released pytest-xdist plugin.
|
||||||
|
|
||||||
- new junitxml plugin: --junitxml=path will generate a junit style xml file
|
- new junitxml plugin: --junitxml=path will generate a junit style xml file
|
||||||
which is processable e.g. by the Hudson CI system.
|
which is processable e.g. by the Hudson CI system.
|
||||||
|
|
||||||
- new option: --genscript=path will generate a standalone py.test script
|
- new option: --genscript=path will generate a standalone py.test script
|
||||||
which will not need any libraries installed. thanks to Ralf Schmitt.
|
which will not need any libraries installed. thanks to Ralf Schmitt.
|
||||||
|
|
||||||
- new option: --ignore will prevent specified path from collection.
|
- new option: --ignore will prevent specified path from collection.
|
||||||
Can be specified multiple times.
|
Can be specified multiple times.
|
||||||
|
|
||||||
- new option: --confcutdir=dir will make py.test only consider conftest
|
- new option: --confcutdir=dir will make py.test only consider conftest
|
||||||
files that are relative to the specified dir.
|
files that are relative to the specified dir.
|
||||||
|
|
||||||
- new funcarg: "pytestconfig" is the pytest config object for access
|
- new funcarg: "pytestconfig" is the pytest config object for access
|
||||||
to command line args and can now be easily used in a test.
|
to command line args and can now be easily used in a test.
|
||||||
|
|
||||||
- install 'py.test' and `py.which` with a ``-$VERSION`` suffix to
|
- install 'py.test' and `py.which` with a ``-$VERSION`` suffix to
|
||||||
disambiguate between Python3, python2.X, Jython and PyPy installed versions.
|
disambiguate between Python3, python2.X, Jython and PyPy installed versions.
|
||||||
|
|
||||||
- new "pytestconfig" funcarg allows access to test config object
|
- new "pytestconfig" funcarg allows access to test config object
|
||||||
|
|
||||||
- new "pytest_report_header" hook can return additional lines
|
- new "pytest_report_header" hook can return additional lines
|
||||||
to be displayed at the header of a test run.
|
to be displayed at the header of a test run.
|
||||||
|
|
||||||
- (experimental) allow "py.test path::name1::name2::..." for pointing
|
- (experimental) allow "py.test path::name1::name2::..." for pointing
|
||||||
to a test within a test collection directly. This might eventually
|
to a test within a test collection directly. This might eventually
|
||||||
evolve as a full substitute to "-k" specifications.
|
evolve as a full substitute to "-k" specifications.
|
||||||
|
|
||||||
- streamlined plugin loading: order is now as documented in
|
- streamlined plugin loading: order is now as documented in
|
||||||
customize.html: setuptools, ENV, commandline, conftest.
|
customize.html: setuptools, ENV, commandline, conftest.
|
||||||
also setuptools entry point names are turned to canonical namees ("pytest_*")
|
also setuptools entry point names are turned to canonical namees ("pytest_*")
|
||||||
|
|
||||||
- automatically skip tests that need 'capfd' but have no os.dup
|
- automatically skip tests that need 'capfd' but have no os.dup
|
||||||
|
|
||||||
- allow pytest_generate_tests to be defined in classes as well
|
- allow pytest_generate_tests to be defined in classes as well
|
||||||
|
|
||||||
- deprecate usage of 'disabled' attribute in favour of pytestmark
|
- deprecate usage of 'disabled' attribute in favour of pytestmark
|
||||||
- deprecate definition of Directory, Module, Class and Function nodes
|
- deprecate definition of Directory, Module, Class and Function nodes
|
||||||
in conftest.py files. Use pytest collect hooks instead.
|
in conftest.py files. Use pytest collect hooks instead.
|
||||||
|
|
||||||
|
@ -183,28 +183,28 @@ Changes between 1.2 and 1.1.1
|
||||||
change its long command line options to be a bit shorter (see py.test -h).
|
change its long command line options to be a bit shorter (see py.test -h).
|
||||||
|
|
||||||
- change: pytest doctest plugin is now enabled by default and has a
|
- change: pytest doctest plugin is now enabled by default and has a
|
||||||
new option --doctest-glob to set a pattern for file matches.
|
new option --doctest-glob to set a pattern for file matches.
|
||||||
|
|
||||||
- change: remove internal py._* helper vars, only keep py._pydir
|
- change: remove internal py._* helper vars, only keep py._pydir
|
||||||
|
|
||||||
- robustify capturing to survive if custom pytest_runtest_setup
|
- robustify capturing to survive if custom pytest_runtest_setup
|
||||||
code failed and prevented the capturing setup code from running.
|
code failed and prevented the capturing setup code from running.
|
||||||
|
|
||||||
- make py.test.* helpers provided by default plugins visible early -
|
- make py.test.* helpers provided by default plugins visible early -
|
||||||
works transparently both for pydoc and for interactive sessions
|
works transparently both for pydoc and for interactive sessions
|
||||||
which will regularly see e.g. py.test.mark and py.test.importorskip.
|
which will regularly see e.g. py.test.mark and py.test.importorskip.
|
||||||
|
|
||||||
- simplify internal plugin manager machinery
|
- simplify internal plugin manager machinery
|
||||||
- simplify internal collection tree by introducing a RootCollector node
|
- simplify internal collection tree by introducing a RootCollector node
|
||||||
|
|
||||||
- fix assert reinterpreation that sees a call containing "keyword=..."
|
- fix assert reinterpreation that sees a call containing "keyword=..."
|
||||||
|
|
||||||
- fix issue66: invoke pytest_sessionstart and pytest_sessionfinish
|
- fix issue66: invoke pytest_sessionstart and pytest_sessionfinish
|
||||||
hooks on slaves during dist-testing, report module/session teardown
|
hooks on slaves during dist-testing, report module/session teardown
|
||||||
hooks correctly.
|
hooks correctly.
|
||||||
|
|
||||||
- fix issue65: properly handle dist-testing if no
|
- fix issue65: properly handle dist-testing if no
|
||||||
execnet/py lib installed remotely.
|
execnet/py lib installed remotely.
|
||||||
|
|
||||||
- skip some install-tests if no execnet is available
|
- skip some install-tests if no execnet is available
|
||||||
|
|
||||||
|
@ -214,15 +214,15 @@ Changes between 1.2 and 1.1.1
|
||||||
Changes between 1.1.1 and 1.1.0
|
Changes between 1.1.1 and 1.1.0
|
||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
- introduce automatic plugin registration via 'pytest11'
|
- introduce automatic plugin registration via 'pytest11'
|
||||||
entrypoints via setuptools' pkg_resources.iter_entry_points
|
entrypoints via setuptools' pkg_resources.iter_entry_points
|
||||||
|
|
||||||
- fix py.test dist-testing to work with execnet >= 1.0.0b4
|
- fix py.test dist-testing to work with execnet >= 1.0.0b4
|
||||||
|
|
||||||
- re-introduce py.test.cmdline.main() for better backward compatibility
|
- re-introduce py.test.cmdline.main() for better backward compatibility
|
||||||
|
|
||||||
- svn paths: fix a bug with path.check(versioned=True) for svn paths,
|
- svn paths: fix a bug with path.check(versioned=True) for svn paths,
|
||||||
allow '%' in svn paths, make svnwc.update() default to interactive mode
|
allow '%' in svn paths, make svnwc.update() default to interactive mode
|
||||||
like in 1.0.x and add svnwc.update(interactive=False) to inhibit interaction.
|
like in 1.0.x and add svnwc.update(interactive=False) to inhibit interaction.
|
||||||
|
|
||||||
- refine distributed tarball to contain test and no pyc files
|
- refine distributed tarball to contain test and no pyc files
|
||||||
|
@ -237,16 +237,16 @@ Changes between 1.1.0 and 1.0.2
|
||||||
|
|
||||||
* remove py.rest tool and internal namespace - it was
|
* remove py.rest tool and internal namespace - it was
|
||||||
never really advertised and can still be used with
|
never really advertised and can still be used with
|
||||||
the old release if needed. If there is interest
|
the old release if needed. If there is interest
|
||||||
it could be revived into its own tool i guess.
|
it could be revived into its own tool i guess.
|
||||||
|
|
||||||
* fix issue48 and issue59: raise an Error if the module
|
* fix issue48 and issue59: raise an Error if the module
|
||||||
from an imported test file does not seem to come from
|
from an imported test file does not seem to come from
|
||||||
the filepath - avoids "same-name" confusion that has
|
the filepath - avoids "same-name" confusion that has
|
||||||
been reported repeatedly
|
been reported repeatedly
|
||||||
|
|
||||||
* merged Ronny's nose-compatibility hacks: now
|
* merged Ronny's nose-compatibility hacks: now
|
||||||
nose-style setup_module() and setup() functions are
|
nose-style setup_module() and setup() functions are
|
||||||
supported
|
supported
|
||||||
|
|
||||||
* introduce generalized py.test.mark function marking
|
* introduce generalized py.test.mark function marking
|
||||||
|
@ -255,112 +255,112 @@ Changes between 1.1.0 and 1.0.2
|
||||||
|
|
||||||
* deprecate parser.addgroup in favour of getgroup which creates option group
|
* deprecate parser.addgroup in favour of getgroup which creates option group
|
||||||
|
|
||||||
* add --report command line option that allows to control showing of skipped/xfailed sections
|
* add --report command line option that allows to control showing of skipped/xfailed sections
|
||||||
|
|
||||||
* generalized skipping: a new way to mark python functions with skipif or xfail
|
* generalized skipping: a new way to mark python functions with skipif or xfail
|
||||||
at function, class and modules level based on platform or sys-module attributes.
|
at function, class and modules level based on platform or sys-module attributes.
|
||||||
|
|
||||||
* extend py.test.mark decorator to allow for positional args
|
* extend py.test.mark decorator to allow for positional args
|
||||||
|
|
||||||
* introduce and test "py.cleanup -d" to remove empty directories
|
* introduce and test "py.cleanup -d" to remove empty directories
|
||||||
|
|
||||||
* fix issue #59 - robustify unittest test collection
|
* fix issue #59 - robustify unittest test collection
|
||||||
|
|
||||||
* make bpython/help interaction work by adding an __all__ attribute
|
* make bpython/help interaction work by adding an __all__ attribute
|
||||||
to ApiModule, cleanup initpkg
|
to ApiModule, cleanup initpkg
|
||||||
|
|
||||||
* use MIT license for pylib, add some contributors
|
* use MIT license for pylib, add some contributors
|
||||||
|
|
||||||
* remove py.execnet code and substitute all usages with 'execnet' proper
|
* remove py.execnet code and substitute all usages with 'execnet' proper
|
||||||
|
|
||||||
* fix issue50 - cached_setup now caches more to expectations
|
* fix issue50 - cached_setup now caches more to expectations
|
||||||
for test functions with multiple arguments.
|
for test functions with multiple arguments.
|
||||||
|
|
||||||
* merge Jarko's fixes, issue #45 and #46
|
* merge Jarko's fixes, issue #45 and #46
|
||||||
|
|
||||||
* add the ability to specify a path for py.lookup to search in
|
* add the ability to specify a path for py.lookup to search in
|
||||||
|
|
||||||
* fix a funcarg cached_setup bug probably only occuring
|
* fix a funcarg cached_setup bug probably only occuring
|
||||||
in distributed testing and "module" scope with teardown.
|
in distributed testing and "module" scope with teardown.
|
||||||
|
|
||||||
* many fixes and changes for making the code base python3 compatible,
|
* many fixes and changes for making the code base python3 compatible,
|
||||||
many thanks to Benjamin Peterson for helping with this.
|
many thanks to Benjamin Peterson for helping with this.
|
||||||
|
|
||||||
* consolidate builtins implementation to be compatible with >=2.3,
|
* consolidate builtins implementation to be compatible with >=2.3,
|
||||||
add helpers to ease keeping 2 and 3k compatible code
|
add helpers to ease keeping 2 and 3k compatible code
|
||||||
|
|
||||||
* deprecate py.compat.doctest|subprocess|textwrap|optparse
|
* deprecate py.compat.doctest|subprocess|textwrap|optparse
|
||||||
|
|
||||||
* deprecate py.magic.autopath, remove py/magic directory
|
* deprecate py.magic.autopath, remove py/magic directory
|
||||||
|
|
||||||
* move pytest assertion handling to py/code and a pytest_assertion
|
* move pytest assertion handling to py/code and a pytest_assertion
|
||||||
plugin, add "--no-assert" option, deprecate py.magic namespaces
|
plugin, add "--no-assert" option, deprecate py.magic namespaces
|
||||||
in favour of (less) py.code ones.
|
in favour of (less) py.code ones.
|
||||||
|
|
||||||
* consolidate and cleanup py/code classes and files
|
* consolidate and cleanup py/code classes and files
|
||||||
|
|
||||||
* cleanup py/misc, move tests to bin-for-dist
|
* cleanup py/misc, move tests to bin-for-dist
|
||||||
|
|
||||||
* introduce delattr/delitem/delenv methods to py.test's monkeypatch funcarg
|
* introduce delattr/delitem/delenv methods to py.test's monkeypatch funcarg
|
||||||
|
|
||||||
* consolidate py.log implementation, remove old approach.
|
* consolidate py.log implementation, remove old approach.
|
||||||
|
|
||||||
* introduce py.io.TextIO and py.io.BytesIO for distinguishing between
|
* introduce py.io.TextIO and py.io.BytesIO for distinguishing between
|
||||||
text/unicode and byte-streams (uses underlying standard lib io.*
|
text/unicode and byte-streams (uses underlying standard lib io.*
|
||||||
if available)
|
if available)
|
||||||
|
|
||||||
* make py.unittest_convert helper script available which converts "unittest.py"
|
* make py.unittest_convert helper script available which converts "unittest.py"
|
||||||
style files into the simpler assert/direct-test-classes py.test/nosetests
|
style files into the simpler assert/direct-test-classes py.test/nosetests
|
||||||
style. The script was written by Laura Creighton.
|
style. The script was written by Laura Creighton.
|
||||||
|
|
||||||
* simplified internal localpath implementation
|
* simplified internal localpath implementation
|
||||||
|
|
||||||
Changes between 1.0.1 and 1.0.2
|
Changes between 1.0.1 and 1.0.2
|
||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
* fixing packaging issues, triggered by fedora redhat packaging,
|
* fixing packaging issues, triggered by fedora redhat packaging,
|
||||||
also added doc, examples and contrib dirs to the tarball.
|
also added doc, examples and contrib dirs to the tarball.
|
||||||
|
|
||||||
* added a documentation link to the new django plugin.
|
* added a documentation link to the new django plugin.
|
||||||
|
|
||||||
Changes between 1.0.0 and 1.0.1
|
Changes between 1.0.0 and 1.0.1
|
||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
* added a 'pytest_nose' plugin which handles nose.SkipTest,
|
* added a 'pytest_nose' plugin which handles nose.SkipTest,
|
||||||
nose-style function/method/generator setup/teardown and
|
nose-style function/method/generator setup/teardown and
|
||||||
tries to report functions correctly.
|
tries to report functions correctly.
|
||||||
|
|
||||||
* capturing of unicode writes or encoded strings to sys.stdout/err
|
* capturing of unicode writes or encoded strings to sys.stdout/err
|
||||||
work better, also terminalwriting was adapted and somewhat
|
work better, also terminalwriting was adapted and somewhat
|
||||||
unified between windows and linux.
|
unified between windows and linux.
|
||||||
|
|
||||||
* improved documentation layout and content a lot
|
* improved documentation layout and content a lot
|
||||||
|
|
||||||
* added a "--help-config" option to show conftest.py / ENV-var names for
|
* added a "--help-config" option to show conftest.py / ENV-var names for
|
||||||
all longopt cmdline options, and some special conftest.py variables.
|
all longopt cmdline options, and some special conftest.py variables.
|
||||||
renamed 'conf_capture' conftest setting to 'option_capture' accordingly.
|
renamed 'conf_capture' conftest setting to 'option_capture' accordingly.
|
||||||
|
|
||||||
* fix issue #27: better reporting on non-collectable items given on commandline
|
* fix issue #27: better reporting on non-collectable items given on commandline
|
||||||
(e.g. pyc files)
|
(e.g. pyc files)
|
||||||
|
|
||||||
* fix issue #33: added --version flag (thanks Benjamin Peterson)
|
* fix issue #33: added --version flag (thanks Benjamin Peterson)
|
||||||
|
|
||||||
* fix issue #32: adding support for "incomplete" paths to wcpath.status()
|
* fix issue #32: adding support for "incomplete" paths to wcpath.status()
|
||||||
|
|
||||||
* "Test" prefixed classes are *not* collected by default anymore if they
|
* "Test" prefixed classes are *not* collected by default anymore if they
|
||||||
have an __init__ method
|
have an __init__ method
|
||||||
|
|
||||||
* monkeypatch setenv() now accepts a "prepend" parameter
|
* monkeypatch setenv() now accepts a "prepend" parameter
|
||||||
|
|
||||||
* improved reporting of collection error tracebacks
|
* improved reporting of collection error tracebacks
|
||||||
|
|
||||||
* simplified multicall mechanism and plugin architecture,
|
* simplified multicall mechanism and plugin architecture,
|
||||||
renamed some internal methods and argnames
|
renamed some internal methods and argnames
|
||||||
|
|
||||||
Changes between 1.0.0b9 and 1.0.0
|
Changes between 1.0.0b9 and 1.0.0
|
||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
* more terse reporting try to show filesystem path relatively to current dir
|
* more terse reporting try to show filesystem path relatively to current dir
|
||||||
* improve xfail output a bit
|
* improve xfail output a bit
|
||||||
|
|
||||||
Changes between 1.0.0b8 and 1.0.0b9
|
Changes between 1.0.0b8 and 1.0.0b9
|
||||||
|
@ -373,26 +373,26 @@ Changes between 1.0.0b8 and 1.0.0b9
|
||||||
|
|
||||||
* setup/teardown or collection problems now show as ERRORs
|
* setup/teardown or collection problems now show as ERRORs
|
||||||
or with big "E"'s in the progress lines. they are reported
|
or with big "E"'s in the progress lines. they are reported
|
||||||
and counted separately.
|
and counted separately.
|
||||||
|
|
||||||
* dist-testing: properly handle test items that get locally
|
* dist-testing: properly handle test items that get locally
|
||||||
collected but cannot be collected on the remote side - often
|
collected but cannot be collected on the remote side - often
|
||||||
due to platform/dependency reasons
|
due to platform/dependency reasons
|
||||||
|
|
||||||
* simplified py.test.mark API - see keyword plugin documentation
|
* simplified py.test.mark API - see keyword plugin documentation
|
||||||
|
|
||||||
* integrate better with logging: capturing now by default captures
|
* integrate better with logging: capturing now by default captures
|
||||||
test functions and their immediate setup/teardown in a single stream
|
test functions and their immediate setup/teardown in a single stream
|
||||||
|
|
||||||
* capsys and capfd funcargs now have a readouterr() and a close() method
|
* capsys and capfd funcargs now have a readouterr() and a close() method
|
||||||
(underlyingly py.io.StdCapture/FD objects are used which grew a
|
(underlyingly py.io.StdCapture/FD objects are used which grew a
|
||||||
readouterr() method as well to return snapshots of captured out/err)
|
readouterr() method as well to return snapshots of captured out/err)
|
||||||
|
|
||||||
* make assert-reinterpretation work better with comparisons not
|
* make assert-reinterpretation work better with comparisons not
|
||||||
returning bools (reported with numpy from thanks maciej fijalkowski)
|
returning bools (reported with numpy from thanks maciej fijalkowski)
|
||||||
|
|
||||||
* reworked per-test output capturing into the pytest_iocapture.py plugin
|
* reworked per-test output capturing into the pytest_iocapture.py plugin
|
||||||
and thus removed capturing code from config object
|
and thus removed capturing code from config object
|
||||||
|
|
||||||
* item.repr_failure(excinfo) instead of item.repr_failure(excinfo, outerr)
|
* item.repr_failure(excinfo) instead of item.repr_failure(excinfo, outerr)
|
||||||
|
|
||||||
|
@ -402,126 +402,126 @@ Changes between 1.0.0b7 and 1.0.0b8
|
||||||
|
|
||||||
* pytest_unittest-plugin is now enabled by default
|
* pytest_unittest-plugin is now enabled by default
|
||||||
|
|
||||||
* introduced pytest_keyboardinterrupt hook and
|
* introduced pytest_keyboardinterrupt hook and
|
||||||
refined pytest_sessionfinish hooked, added tests.
|
refined pytest_sessionfinish hooked, added tests.
|
||||||
|
|
||||||
* workaround a buggy logging module interaction ("closing already closed
|
* workaround a buggy logging module interaction ("closing already closed
|
||||||
files"). Thanks to Sridhar Ratnakumar for triggering.
|
files"). Thanks to Sridhar Ratnakumar for triggering.
|
||||||
|
|
||||||
* if plugins use "py.test.importorskip" for importing
|
* if plugins use "py.test.importorskip" for importing
|
||||||
a dependency only a warning will be issued instead
|
a dependency only a warning will be issued instead
|
||||||
of exiting the testing process.
|
of exiting the testing process.
|
||||||
|
|
||||||
* many improvements to docs:
|
* many improvements to docs:
|
||||||
- refined funcargs doc , use the term "factory" instead of "provider"
|
- refined funcargs doc , use the term "factory" instead of "provider"
|
||||||
- added a new talk/tutorial doc page
|
- added a new talk/tutorial doc page
|
||||||
- better download page
|
- better download page
|
||||||
- better plugin docstrings
|
- better plugin docstrings
|
||||||
- added new plugins page and automatic doc generation script
|
- added new plugins page and automatic doc generation script
|
||||||
|
|
||||||
* fixed teardown problem related to partially failing funcarg setups
|
* fixed teardown problem related to partially failing funcarg setups
|
||||||
(thanks MrTopf for reporting), "pytest_runtest_teardown" is now
|
(thanks MrTopf for reporting), "pytest_runtest_teardown" is now
|
||||||
always invoked even if the "pytest_runtest_setup" failed.
|
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.
|
||||||
|
|
||||||
Changes between 1.0.0b3 and 1.0.0b7
|
Changes between 1.0.0b3 and 1.0.0b7
|
||||||
=============================================
|
=============================================
|
||||||
|
|
||||||
* renamed py.test.xfail back to py.test.mark.xfail to avoid
|
* renamed py.test.xfail back to py.test.mark.xfail to avoid
|
||||||
two ways to decorate for xfail
|
two ways to decorate for xfail
|
||||||
|
|
||||||
* re-added py.test.mark decorator for setting keywords on functions
|
* re-added py.test.mark decorator for setting keywords on functions
|
||||||
(it was actually documented so removing it was not nice)
|
(it was actually documented so removing it was not nice)
|
||||||
|
|
||||||
* remove scope-argument from request.addfinalizer() because
|
* remove scope-argument from request.addfinalizer() because
|
||||||
request.cached_setup has the scope arg. TOOWTDI.
|
request.cached_setup has the scope arg. TOOWTDI.
|
||||||
|
|
||||||
* perform setup finalization before reporting failures
|
* perform setup finalization before reporting failures
|
||||||
|
|
||||||
* apply modified patches from Andreas Kloeckner to allow
|
* apply modified patches from Andreas Kloeckner to allow
|
||||||
test functions to have no func_code (#22) and to make
|
test functions to have no func_code (#22) and to make
|
||||||
"-k" and function keywords work (#20)
|
"-k" and function keywords work (#20)
|
||||||
|
|
||||||
* apply patch from Daniel Peolzleithner (issue #23)
|
* apply patch from Daniel Peolzleithner (issue #23)
|
||||||
|
|
||||||
* resolve issue #18, multiprocessing.Manager() and
|
* resolve issue #18, multiprocessing.Manager() and
|
||||||
redirection clash
|
redirection clash
|
||||||
|
|
||||||
* make __name__ == "__channelexec__" for remote_exec code
|
* 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
|
||||||
=============================================
|
=============================================
|
||||||
|
|
||||||
* plugin classes are removed: one now defines
|
* plugin classes are removed: one now defines
|
||||||
hooks directly in conftest.py or global pytest_*.py
|
hooks directly in conftest.py or global pytest_*.py
|
||||||
files.
|
files.
|
||||||
|
|
||||||
* added new pytest_namespace(config) hook that allows
|
* added new pytest_namespace(config) hook that allows
|
||||||
to inject helpers directly to the py.test.* namespace.
|
to inject helpers directly to the py.test.* namespace.
|
||||||
|
|
||||||
* documented and refined many hooks
|
* documented and refined many hooks
|
||||||
|
|
||||||
|
* added new style of generative tests via
|
||||||
|
pytest_generate_tests hook that integrates
|
||||||
|
well with function arguments.
|
||||||
|
|
||||||
* added new style of generative tests via
|
|
||||||
pytest_generate_tests hook that integrates
|
|
||||||
well with function arguments.
|
|
||||||
|
|
||||||
|
|
||||||
Changes between 0.9.2 and 1.0.0b1
|
Changes between 0.9.2 and 1.0.0b1
|
||||||
=============================================
|
=============================================
|
||||||
|
|
||||||
* introduced new "funcarg" setup method,
|
* introduced new "funcarg" setup method,
|
||||||
see doc/test/funcarg.txt
|
see doc/test/funcarg.txt
|
||||||
|
|
||||||
* introduced plugin architecuture and many
|
* introduced plugin architecuture and many
|
||||||
new py.test plugins, see
|
new py.test plugins, see
|
||||||
doc/test/plugins.txt
|
doc/test/plugins.txt
|
||||||
|
|
||||||
* teardown_method is now guaranteed to get
|
* teardown_method is now guaranteed to get
|
||||||
called after a test method has run.
|
called after a test method has run.
|
||||||
|
|
||||||
* new method: py.test.importorskip(mod,minversion)
|
* new method: py.test.importorskip(mod,minversion)
|
||||||
will either import or call py.test.skip()
|
will either import or call py.test.skip()
|
||||||
|
|
||||||
* completely revised internal py.test architecture
|
* completely revised internal py.test architecture
|
||||||
|
|
||||||
* new py.process.ForkedFunc object allowing to
|
* new py.process.ForkedFunc object allowing to
|
||||||
fork execution of a function to a sub process
|
fork execution of a function to a sub process
|
||||||
and getting a result back.
|
and getting a result back.
|
||||||
|
|
||||||
XXX lots of things missing here XXX
|
XXX lots of things missing here XXX
|
||||||
|
|
||||||
Changes between 0.9.1 and 0.9.2
|
Changes between 0.9.1 and 0.9.2
|
||||||
===============================
|
===============================
|
||||||
|
|
||||||
* refined installation and metadata, created new setup.py,
|
* refined installation and metadata, created new setup.py,
|
||||||
now based on setuptools/ez_setup (thanks to Ralf Schmitt
|
now based on setuptools/ez_setup (thanks to Ralf Schmitt
|
||||||
for his support).
|
for his support).
|
||||||
|
|
||||||
* improved the way of making py.* scripts available in
|
* improved the way of making py.* scripts available in
|
||||||
windows environments, they are now added to the
|
windows environments, they are now added to the
|
||||||
Scripts directory as ".cmd" files.
|
Scripts directory as ".cmd" files.
|
||||||
|
|
||||||
* py.path.svnwc.status() now is more complete and
|
* py.path.svnwc.status() now is more complete and
|
||||||
uses xml output from the 'svn' command if available
|
uses xml output from the 'svn' command if available
|
||||||
(Guido Wesdorp)
|
(Guido Wesdorp)
|
||||||
|
|
||||||
* fix for py.path.svn* to work with svn 1.5
|
* fix for py.path.svn* to work with svn 1.5
|
||||||
(Chris Lamb)
|
(Chris Lamb)
|
||||||
|
|
||||||
* fix path.relto(otherpath) method on windows to
|
* fix path.relto(otherpath) method on windows to
|
||||||
use normcase for checking if a path is relative.
|
use normcase for checking if a path is relative.
|
||||||
|
|
||||||
* py.test's traceback is better parseable from editors
|
* py.test's traceback is better parseable from editors
|
||||||
(follows the filenames:LINENO: MSG convention)
|
(follows the filenames:LINENO: MSG convention)
|
||||||
(thanks to Osmo Salomaa)
|
(thanks to Osmo Salomaa)
|
||||||
|
|
||||||
* fix to javascript-generation, "py.test --runbrowser"
|
* fix to javascript-generation, "py.test --runbrowser"
|
||||||
should work more reliably now
|
should work more reliably now
|
||||||
|
|
||||||
* removed previously accidentally added
|
* removed previously accidentally added
|
||||||
py.test.broken and py.test.notimplemented helpers.
|
py.test.broken and py.test.notimplemented helpers.
|
||||||
|
|
||||||
* there now is a py.__version__ attribute
|
* there now is a py.__version__ attribute
|
||||||
|
|
||||||
|
|
|
@ -1,21 +1,21 @@
|
||||||
py.test/pylib 1.3.1: new py.test.xfail, --maxfail, better reporting
|
py.test/pylib 1.3.1: new py.test.xfail, --maxfail, better reporting
|
||||||
===========================================================================
|
===========================================================================
|
||||||
|
|
||||||
The pylib/py.test 1.3.1 release brings:
|
The pylib/py.test 1.3.1 release brings:
|
||||||
|
|
||||||
- the new imperative ``py.test.xfail()`` helper in order to have a test or
|
- the new imperative ``py.test.xfail()`` helper in order to have a test or
|
||||||
setup function result in an "expected failure"
|
setup function result in an "expected failure"
|
||||||
- a new option ``--maxfail=NUM`` to stop the test run after some failures
|
- a new option ``--maxfail=NUM`` to stop the test run after some failures
|
||||||
- markers/decorators are now applicable to test classes (>=Python2.6)
|
- markers/decorators are now applicable to test classes (>=Python2.6)
|
||||||
- improved reporting, shorter tracebacks in several cases
|
- improved reporting, shorter tracebacks in several cases
|
||||||
- some simplified internals, more compatibility with Jython and PyPy
|
- some simplified internals, more compatibility with Jython and PyPy
|
||||||
- bug fixes and various refinements
|
- bug fixes and various refinements
|
||||||
|
|
||||||
See the below CHANGELOG entry below for more details and
|
See the below CHANGELOG entry below for more details and
|
||||||
http://pylib.org/install.html for installation instructions.
|
http://pylib.org/install.html for installation instructions.
|
||||||
|
|
||||||
If you used older versions of py.test you should be able to upgrade
|
If you used older versions of py.test you should be able to upgrade
|
||||||
to 1.3.1 without changes to your test source code.
|
to 1.3.1 without changes to your test source code.
|
||||||
|
|
||||||
py.test is an automated testing tool working with Python2,
|
py.test is an automated testing tool working with Python2,
|
||||||
Python3, Jython and PyPy versions on all major operating systems. It
|
Python3, Jython and PyPy versions on all major operating systems. It
|
||||||
|
@ -23,7 +23,7 @@ offers a no-boilerplate testing approach and has inspired other testing
|
||||||
tools and enhancements in the standard Python library for more than five
|
tools and enhancements in the standard Python library for more than five
|
||||||
years. It has a simple and extensive plugin architecture, configurable
|
years. It has a simple and extensive plugin architecture, configurable
|
||||||
reporting and provides unique ways to make it fit to your testing
|
reporting and provides unique ways to make it fit to your testing
|
||||||
process and needs.
|
process and needs.
|
||||||
|
|
||||||
See http://pytest.org for more info.
|
See http://pytest.org for more info.
|
||||||
|
|
||||||
|
@ -34,27 +34,27 @@ holger krekel
|
||||||
Changes between 1.3.0 and 1.3.1
|
Changes between 1.3.0 and 1.3.1
|
||||||
==================================================
|
==================================================
|
||||||
|
|
||||||
New features
|
New features
|
||||||
++++++++++++++++++
|
++++++++++++++++++
|
||||||
|
|
||||||
- issue91: introduce new py.test.xfail(reason) helper
|
- issue91: introduce new py.test.xfail(reason) helper
|
||||||
to imperatively mark a test as expected to fail. Can
|
to imperatively mark a test as expected to fail. Can
|
||||||
be used from within setup and test functions. This is
|
be used from within setup and test functions. This is
|
||||||
useful especially for parametrized tests when certain
|
useful especially for parametrized tests when certain
|
||||||
configurations are expected-to-fail. In this case the
|
configurations are expected-to-fail. In this case the
|
||||||
declarative approach with the @py.test.mark.xfail cannot
|
declarative approach with the @py.test.mark.xfail cannot
|
||||||
be used as it would mark all configurations as xfail.
|
be used as it would mark all configurations as xfail.
|
||||||
|
|
||||||
- issue102: introduce new --maxfail=NUM option to stop
|
- issue102: introduce new --maxfail=NUM option to stop
|
||||||
test runs after NUM failures. This is a generalization
|
test runs after NUM failures. This is a generalization
|
||||||
of the '-x' or '--exitfirst' option which is now equivalent
|
of the '-x' or '--exitfirst' option which is now equivalent
|
||||||
to '--maxfail=1'. Both '-x' and '--maxfail' will
|
to '--maxfail=1'. Both '-x' and '--maxfail' will
|
||||||
now also print a line near the end indicating the Interruption.
|
now also print a line near the end indicating the Interruption.
|
||||||
|
|
||||||
- issue89: allow py.test.mark decorators to be used on classes
|
- issue89: allow py.test.mark decorators to be used on classes
|
||||||
(class decorators were introduced with python2.6) and
|
(class decorators were introduced with python2.6) and
|
||||||
also allow to have multiple markers applied at class/module level
|
also allow to have multiple markers applied at class/module level
|
||||||
by specifying a list.
|
by specifying a list.
|
||||||
|
|
||||||
- improve and refine letter reporting in the progress bar:
|
- improve and refine letter reporting in the progress bar:
|
||||||
. pass
|
. pass
|
||||||
|
@ -64,19 +64,19 @@ New features
|
||||||
X xpassed test (test that was expected to fail but passed)
|
X xpassed test (test that was expected to fail but passed)
|
||||||
|
|
||||||
You can use any combination of 'fsxX' with the '-r' extended
|
You can use any combination of 'fsxX' with the '-r' extended
|
||||||
reporting option. The xfail/xpass results will show up as
|
reporting option. The xfail/xpass results will show up as
|
||||||
skipped tests in the junitxml output - which also fixes
|
skipped tests in the junitxml output - which also fixes
|
||||||
issue99.
|
issue99.
|
||||||
|
|
||||||
- make py.test.cmdline.main() return the exitstatus instead of raising
|
- make py.test.cmdline.main() return the exitstatus instead of raising
|
||||||
SystemExit and also allow it to be called multiple times. This of
|
SystemExit and also allow it to be called multiple times. This of
|
||||||
course requires that your application and tests are properly teared
|
course requires that your application and tests are properly teared
|
||||||
down and don't have global state.
|
down and don't have global state.
|
||||||
|
|
||||||
Fixes / Maintenance
|
Fixes / Maintenance
|
||||||
++++++++++++++++++++++
|
++++++++++++++++++++++
|
||||||
|
|
||||||
- improved traceback presentation:
|
- improved traceback presentation:
|
||||||
- improved and unified reporting for "--tb=short" option
|
- improved and unified reporting for "--tb=short" option
|
||||||
- Errors during test module imports are much shorter, (using --tb=short style)
|
- Errors during test module imports are much shorter, (using --tb=short style)
|
||||||
- raises shows shorter more relevant tracebacks
|
- raises shows shorter more relevant tracebacks
|
||||||
|
@ -84,20 +84,20 @@ Fixes / Maintenance
|
||||||
|
|
||||||
- improve support for raises and other dynamically compiled code by
|
- improve support for raises and other dynamically compiled code by
|
||||||
manipulating python's linecache.cache instead of the previous
|
manipulating python's linecache.cache instead of the previous
|
||||||
rather hacky way of creating custom code objects. This makes
|
rather hacky way of creating custom code objects. This makes
|
||||||
it seemlessly work on Jython and PyPy where it previously didn't.
|
it seemlessly work on Jython and PyPy where it previously didn't.
|
||||||
|
|
||||||
- fix issue96: make capturing more resilient against Control-C
|
- fix issue96: make capturing more resilient against Control-C
|
||||||
interruptions (involved somewhat substantial refactoring
|
interruptions (involved somewhat substantial refactoring
|
||||||
to the underlying capturing functionality to avoid race
|
to the underlying capturing functionality to avoid race
|
||||||
conditions).
|
conditions).
|
||||||
|
|
||||||
- fix chaining of conditional skipif/xfail decorators - so it works now
|
- fix chaining of conditional skipif/xfail decorators - so it works now
|
||||||
as expected to use multiple @py.test.mark.skipif(condition) decorators,
|
as expected to use multiple @py.test.mark.skipif(condition) decorators,
|
||||||
including specific reporting which of the conditions lead to skipping.
|
including specific reporting which of the conditions lead to skipping.
|
||||||
|
|
||||||
- fix issue95: late-import zlib so that it's not required
|
- fix issue95: late-import zlib so that it's not required
|
||||||
for general py.test startup.
|
for general py.test startup.
|
||||||
|
|
||||||
- fix issue94: make reporting more robust against bogus source code
|
- fix issue94: make reporting more robust against bogus source code
|
||||||
(and internally be more careful when presenting unexpected byte sequences)
|
(and internally be more careful when presenting unexpected byte sequences)
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
py.test/pylib 1.3.2: API and reporting refinements, many fixes
|
py.test/pylib 1.3.2: API and reporting refinements, many fixes
|
||||||
===========================================================================
|
===========================================================================
|
||||||
|
|
||||||
The pylib/py.test 1.3.2 release brings many bug fixes and some new
|
The pylib/py.test 1.3.2 release brings many bug fixes and some new
|
||||||
|
@ -6,25 +6,25 @@ features. It was refined for and tested against the recently released
|
||||||
Python2.7 and remains compatibile to the usual armada of interpreters
|
Python2.7 and remains compatibile to the usual armada of interpreters
|
||||||
(Python2.4 through to Python3.1.2, Jython and PyPy). Note that for using
|
(Python2.4 through to Python3.1.2, Jython and PyPy). Note that for using
|
||||||
distributed testing features you'll need to upgrade to the jointly released
|
distributed testing features you'll need to upgrade to the jointly released
|
||||||
pytest-xdist-1.4 because of some internal refactorings.
|
pytest-xdist-1.4 because of some internal refactorings.
|
||||||
|
|
||||||
See http://pytest.org for general documentation and below for
|
See http://pytest.org for general documentation and below for
|
||||||
a detailed CHANGELOG.
|
a detailed CHANGELOG.
|
||||||
|
|
||||||
cheers & particular thanks to Benjamin Peterson, Ronny Pfannschmidt
|
cheers & particular thanks to Benjamin Peterson, Ronny Pfannschmidt
|
||||||
and all issue and patch contributors,
|
and all issue and patch contributors,
|
||||||
|
|
||||||
holger krekel
|
holger krekel
|
||||||
|
|
||||||
Changes between 1.3.1 and 1.3.2
|
Changes between 1.3.1 and 1.3.2
|
||||||
==================================================
|
==================================================
|
||||||
|
|
||||||
New features
|
New features
|
||||||
++++++++++++++++++
|
++++++++++++++++++
|
||||||
|
|
||||||
- fix issue103: introduce py.test.raises as context manager, examples::
|
- fix issue103: introduce py.test.raises as context manager, examples::
|
||||||
|
|
||||||
with py.test.raises(ZeroDivisionError):
|
with py.test.raises(ZeroDivisionError):
|
||||||
x = 0
|
x = 0
|
||||||
1 / x
|
1 / x
|
||||||
|
|
||||||
|
@ -33,10 +33,10 @@ New features
|
||||||
|
|
||||||
# you may do extra checks on excinfo.value|type|traceback here
|
# you may do extra checks on excinfo.value|type|traceback here
|
||||||
|
|
||||||
(thanks Ronny Pfannschmidt)
|
(thanks Ronny Pfannschmidt)
|
||||||
|
|
||||||
- Funcarg factories can now dynamically apply a marker to a
|
- Funcarg factories can now dynamically apply a marker to a
|
||||||
test invocation. This is for example useful if a factory
|
test invocation. This is for example useful if a factory
|
||||||
provides parameters to a test which are expected-to-fail::
|
provides parameters to a test which are expected-to-fail::
|
||||||
|
|
||||||
def pytest_funcarg__arg(request):
|
def pytest_funcarg__arg(request):
|
||||||
|
@ -46,75 +46,75 @@ New features
|
||||||
def test_function(arg):
|
def test_function(arg):
|
||||||
...
|
...
|
||||||
|
|
||||||
- improved error reporting on collection and import errors. This makes
|
- improved error reporting on collection and import errors. This makes
|
||||||
use of a more general mechanism, namely that for custom test item/collect
|
use of a more general mechanism, namely that for custom test item/collect
|
||||||
nodes ``node.repr_failure(excinfo)`` is now uniformly called so that you can
|
nodes ``node.repr_failure(excinfo)`` is now uniformly called so that you can
|
||||||
override it to return a string error representation of your choice
|
override it to return a string error representation of your choice
|
||||||
which is going to be reported as a (red) string.
|
which is going to be reported as a (red) string.
|
||||||
|
|
||||||
- introduce '--junitprefix=STR' option to prepend a prefix
|
- introduce '--junitprefix=STR' option to prepend a prefix
|
||||||
to all reports in the junitxml file.
|
to all reports in the junitxml file.
|
||||||
|
|
||||||
Bug fixes / Maintenance
|
Bug fixes / Maintenance
|
||||||
++++++++++++++++++++++++++
|
++++++++++++++++++++++++++
|
||||||
|
|
||||||
- make tests and the ``pytest_recwarn`` plugin in particular fully compatible
|
- make tests and the ``pytest_recwarn`` plugin in particular fully compatible
|
||||||
to Python2.7 (if you use the ``recwarn`` funcarg warnings will be enabled so that
|
to Python2.7 (if you use the ``recwarn`` funcarg warnings will be enabled so that
|
||||||
you can properly check for their existence in a cross-python manner).
|
you can properly check for their existence in a cross-python manner).
|
||||||
- refine --pdb: ignore xfailed tests, unify its TB-reporting and
|
- refine --pdb: ignore xfailed tests, unify its TB-reporting and
|
||||||
don't display failures again at the end.
|
don't display failures again at the end.
|
||||||
- fix assertion interpretation with the ** operator (thanks Benjamin Peterson)
|
- fix assertion interpretation with the ** operator (thanks Benjamin Peterson)
|
||||||
- fix issue105 assignment on the same line as a failing assertion (thanks Benjamin Peterson)
|
- fix issue105 assignment on the same line as a failing assertion (thanks Benjamin Peterson)
|
||||||
- fix issue104 proper escaping for test names in junitxml plugin (thanks anonymous)
|
- fix issue104 proper escaping for test names in junitxml plugin (thanks anonymous)
|
||||||
- fix issue57 -f|--looponfail to work with xpassing tests (thanks Ronny)
|
- fix issue57 -f|--looponfail to work with xpassing tests (thanks Ronny)
|
||||||
- fix issue92 collectonly reporter and --pastebin (thanks Benjamin Peterson)
|
- fix issue92 collectonly reporter and --pastebin (thanks Benjamin Peterson)
|
||||||
- fix py.code.compile(source) to generate unique filenames
|
- fix py.code.compile(source) to generate unique filenames
|
||||||
- fix assertion re-interp problems on PyPy, by defering code
|
- fix assertion re-interp problems on PyPy, by defering code
|
||||||
compilation to the (overridable) Frame.eval class. (thanks Amaury Forgeot)
|
compilation to the (overridable) Frame.eval class. (thanks Amaury Forgeot)
|
||||||
- fix py.path.local.pyimport() to work with directories
|
- fix py.path.local.pyimport() to work with directories
|
||||||
- streamline py.path.local.mkdtemp implementation and usage
|
- streamline py.path.local.mkdtemp implementation and usage
|
||||||
- don't print empty lines when showing junitxml-filename
|
- don't print empty lines when showing junitxml-filename
|
||||||
- add optional boolean ignore_errors parameter to py.path.local.remove
|
- add optional boolean ignore_errors parameter to py.path.local.remove
|
||||||
- fix terminal writing on win32/python2.4
|
- fix terminal writing on win32/python2.4
|
||||||
- py.process.cmdexec() now tries harder to return properly encoded unicode objects
|
- py.process.cmdexec() now tries harder to return properly encoded unicode objects
|
||||||
on all python versions
|
on all python versions
|
||||||
- install plain py.test/py.which scripts also for Jython, this helps to
|
- install plain py.test/py.which scripts also for Jython, this helps to
|
||||||
get canonical script paths in virtualenv situations
|
get canonical script paths in virtualenv situations
|
||||||
- make path.bestrelpath(path) return ".", note that when calling
|
- make path.bestrelpath(path) return ".", note that when calling
|
||||||
X.bestrelpath the assumption is that X is a directory.
|
X.bestrelpath the assumption is that X is a directory.
|
||||||
- make initial conftest discovery ignore "--" prefixed arguments
|
- make initial conftest discovery ignore "--" prefixed arguments
|
||||||
- fix resultlog plugin when used in an multicpu/multihost xdist situation
|
- fix resultlog plugin when used in an multicpu/multihost xdist situation
|
||||||
(thanks Jakub Gustak)
|
(thanks Jakub Gustak)
|
||||||
- perform distributed testing related reporting in the xdist-plugin
|
- perform distributed testing related reporting in the xdist-plugin
|
||||||
rather than having dist-related code in the generic py.test
|
rather than having dist-related code in the generic py.test
|
||||||
distribution
|
distribution
|
||||||
- fix homedir detection on Windows
|
- fix homedir detection on Windows
|
||||||
- ship distribute_setup.py version 0.6.13
|
- ship distribute_setup.py version 0.6.13
|
||||||
|
|
||||||
Changes between 1.3.0 and 1.3.1
|
Changes between 1.3.0 and 1.3.1
|
||||||
==================================================
|
==================================================
|
||||||
|
|
||||||
New features
|
New features
|
||||||
++++++++++++++++++
|
++++++++++++++++++
|
||||||
|
|
||||||
- issue91: introduce new py.test.xfail(reason) helper
|
- issue91: introduce new py.test.xfail(reason) helper
|
||||||
to imperatively mark a test as expected to fail. Can
|
to imperatively mark a test as expected to fail. Can
|
||||||
be used from within setup and test functions. This is
|
be used from within setup and test functions. This is
|
||||||
useful especially for parametrized tests when certain
|
useful especially for parametrized tests when certain
|
||||||
configurations are expected-to-fail. In this case the
|
configurations are expected-to-fail. In this case the
|
||||||
declarative approach with the @py.test.mark.xfail cannot
|
declarative approach with the @py.test.mark.xfail cannot
|
||||||
be used as it would mark all configurations as xfail.
|
be used as it would mark all configurations as xfail.
|
||||||
|
|
||||||
- issue102: introduce new --maxfail=NUM option to stop
|
- issue102: introduce new --maxfail=NUM option to stop
|
||||||
test runs after NUM failures. This is a generalization
|
test runs after NUM failures. This is a generalization
|
||||||
of the '-x' or '--exitfirst' option which is now equivalent
|
of the '-x' or '--exitfirst' option which is now equivalent
|
||||||
to '--maxfail=1'. Both '-x' and '--maxfail' will
|
to '--maxfail=1'. Both '-x' and '--maxfail' will
|
||||||
now also print a line near the end indicating the Interruption.
|
now also print a line near the end indicating the Interruption.
|
||||||
|
|
||||||
- issue89: allow py.test.mark decorators to be used on classes
|
- issue89: allow py.test.mark decorators to be used on classes
|
||||||
(class decorators were introduced with python2.6) and
|
(class decorators were introduced with python2.6) and
|
||||||
also allow to have multiple markers applied at class/module level
|
also allow to have multiple markers applied at class/module level
|
||||||
by specifying a list.
|
by specifying a list.
|
||||||
|
|
||||||
- improve and refine letter reporting in the progress bar:
|
- improve and refine letter reporting in the progress bar:
|
||||||
. pass
|
. pass
|
||||||
|
@ -124,19 +124,19 @@ New features
|
||||||
X xpassed test (test that was expected to fail but passed)
|
X xpassed test (test that was expected to fail but passed)
|
||||||
|
|
||||||
You can use any combination of 'fsxX' with the '-r' extended
|
You can use any combination of 'fsxX' with the '-r' extended
|
||||||
reporting option. The xfail/xpass results will show up as
|
reporting option. The xfail/xpass results will show up as
|
||||||
skipped tests in the junitxml output - which also fixes
|
skipped tests in the junitxml output - which also fixes
|
||||||
issue99.
|
issue99.
|
||||||
|
|
||||||
- make py.test.cmdline.main() return the exitstatus instead of raising
|
- make py.test.cmdline.main() return the exitstatus instead of raising
|
||||||
SystemExit and also allow it to be called multiple times. This of
|
SystemExit and also allow it to be called multiple times. This of
|
||||||
course requires that your application and tests are properly teared
|
course requires that your application and tests are properly teared
|
||||||
down and don't have global state.
|
down and don't have global state.
|
||||||
|
|
||||||
Fixes / Maintenance
|
Fixes / Maintenance
|
||||||
++++++++++++++++++++++
|
++++++++++++++++++++++
|
||||||
|
|
||||||
- improved traceback presentation:
|
- improved traceback presentation:
|
||||||
- improved and unified reporting for "--tb=short" option
|
- improved and unified reporting for "--tb=short" option
|
||||||
- Errors during test module imports are much shorter, (using --tb=short style)
|
- Errors during test module imports are much shorter, (using --tb=short style)
|
||||||
- raises shows shorter more relevant tracebacks
|
- raises shows shorter more relevant tracebacks
|
||||||
|
@ -144,20 +144,20 @@ Fixes / Maintenance
|
||||||
|
|
||||||
- improve support for raises and other dynamically compiled code by
|
- improve support for raises and other dynamically compiled code by
|
||||||
manipulating python's linecache.cache instead of the previous
|
manipulating python's linecache.cache instead of the previous
|
||||||
rather hacky way of creating custom code objects. This makes
|
rather hacky way of creating custom code objects. This makes
|
||||||
it seemlessly work on Jython and PyPy where it previously didn't.
|
it seemlessly work on Jython and PyPy where it previously didn't.
|
||||||
|
|
||||||
- fix issue96: make capturing more resilient against Control-C
|
- fix issue96: make capturing more resilient against Control-C
|
||||||
interruptions (involved somewhat substantial refactoring
|
interruptions (involved somewhat substantial refactoring
|
||||||
to the underlying capturing functionality to avoid race
|
to the underlying capturing functionality to avoid race
|
||||||
conditions).
|
conditions).
|
||||||
|
|
||||||
- fix chaining of conditional skipif/xfail decorators - so it works now
|
- fix chaining of conditional skipif/xfail decorators - so it works now
|
||||||
as expected to use multiple @py.test.mark.skipif(condition) decorators,
|
as expected to use multiple @py.test.mark.skipif(condition) decorators,
|
||||||
including specific reporting which of the conditions lead to skipping.
|
including specific reporting which of the conditions lead to skipping.
|
||||||
|
|
||||||
- fix issue95: late-import zlib so that it's not required
|
- fix issue95: late-import zlib so that it's not required
|
||||||
for general py.test startup.
|
for general py.test startup.
|
||||||
|
|
||||||
- fix issue94: make reporting more robust against bogus source code
|
- fix issue94: make reporting more robust against bogus source code
|
||||||
(and internally be more careful when presenting unexpected byte sequences)
|
(and internally be more careful when presenting unexpected byte sequences)
|
||||||
|
@ -169,40 +169,40 @@ Changes between 1.2.1 and 1.3.0
|
||||||
- deprecate --report option in favour of a new shorter and easier to
|
- deprecate --report option in favour of a new shorter and easier to
|
||||||
remember -r option: it takes a string argument consisting of any
|
remember -r option: it takes a string argument consisting of any
|
||||||
combination of 'xfsX' characters. They relate to the single chars
|
combination of 'xfsX' characters. They relate to the single chars
|
||||||
you see during the dotted progress printing and will print an extra line
|
you see during the dotted progress printing and will print an extra line
|
||||||
per test at the end of the test run. This extra line indicates the exact
|
per test at the end of the test run. This extra line indicates the exact
|
||||||
position or test ID that you directly paste to the py.test cmdline in order
|
position or test ID that you directly paste to the py.test cmdline in order
|
||||||
to re-run a particular test.
|
to re-run a particular test.
|
||||||
|
|
||||||
- allow external plugins to register new hooks via the new
|
- allow external plugins to register new hooks via the new
|
||||||
pytest_addhooks(pluginmanager) hook. The new release of
|
pytest_addhooks(pluginmanager) hook. The new release of
|
||||||
the pytest-xdist plugin for distributed and looponfailing
|
the pytest-xdist plugin for distributed and looponfailing
|
||||||
testing requires this feature.
|
testing requires this feature.
|
||||||
|
|
||||||
- add a new pytest_ignore_collect(path, config) hook to allow projects and
|
- add a new pytest_ignore_collect(path, config) hook to allow projects and
|
||||||
plugins to define exclusion behaviour for their directory structure -
|
plugins to define exclusion behaviour for their directory structure -
|
||||||
for example you may define in a conftest.py this method::
|
for example you may define in a conftest.py this method::
|
||||||
|
|
||||||
def pytest_ignore_collect(path):
|
def pytest_ignore_collect(path):
|
||||||
return path.check(link=1)
|
return path.check(link=1)
|
||||||
|
|
||||||
to prevent even a collection try of any tests in symlinked dirs.
|
to prevent even a collection try of any tests in symlinked dirs.
|
||||||
|
|
||||||
- new pytest_pycollect_makemodule(path, parent) hook for
|
- new pytest_pycollect_makemodule(path, parent) hook for
|
||||||
allowing customization of the Module collection object for a
|
allowing customization of the Module collection object for a
|
||||||
matching test module.
|
matching test module.
|
||||||
|
|
||||||
- extend and refine xfail mechanism:
|
- extend and refine xfail mechanism:
|
||||||
``@py.test.mark.xfail(run=False)`` do not run the decorated test
|
``@py.test.mark.xfail(run=False)`` do not run the decorated test
|
||||||
``@py.test.mark.xfail(reason="...")`` prints the reason string in xfail summaries
|
``@py.test.mark.xfail(reason="...")`` prints the reason string in xfail summaries
|
||||||
specifiying ``--runxfail`` on command line virtually ignores xfail markers
|
specifiying ``--runxfail`` on command line virtually ignores xfail markers
|
||||||
|
|
||||||
- expose (previously internal) commonly useful methods:
|
- expose (previously internal) commonly useful methods:
|
||||||
py.io.get_terminal_with() -> return terminal width
|
py.io.get_terminal_with() -> return terminal width
|
||||||
py.io.ansi_print(...) -> print colored/bold text on linux/win32
|
py.io.ansi_print(...) -> print colored/bold text on linux/win32
|
||||||
py.io.saferepr(obj) -> return limited representation string
|
py.io.saferepr(obj) -> return limited representation string
|
||||||
|
|
||||||
- expose test outcome related exceptions as py.test.skip.Exception,
|
- expose test outcome related exceptions as py.test.skip.Exception,
|
||||||
py.test.raises.Exception etc., useful mostly for plugins
|
py.test.raises.Exception etc., useful mostly for plugins
|
||||||
doing special outcome interpretation/tweaking
|
doing special outcome interpretation/tweaking
|
||||||
|
|
||||||
|
@ -210,22 +210,22 @@ Changes between 1.2.1 and 1.3.0
|
||||||
|
|
||||||
- fix/refine python3 compatibility (thanks Benjamin Peterson)
|
- fix/refine python3 compatibility (thanks Benjamin Peterson)
|
||||||
|
|
||||||
- fixes for making the jython/win32 combination work, note however:
|
- fixes for making the jython/win32 combination work, note however:
|
||||||
jython2.5.1/win32 does not provide a command line launcher, see
|
jython2.5.1/win32 does not provide a command line launcher, see
|
||||||
http://bugs.jython.org/issue1491 . See pylib install documentation
|
http://bugs.jython.org/issue1491 . See pylib install documentation
|
||||||
for how to work around.
|
for how to work around.
|
||||||
|
|
||||||
- fixes for handling of unicode exception values and unprintable objects
|
- fixes for handling of unicode exception values and unprintable objects
|
||||||
|
|
||||||
- (issue87) fix unboundlocal error in assertionold code
|
- (issue87) fix unboundlocal error in assertionold code
|
||||||
|
|
||||||
- (issue86) improve documentation for looponfailing
|
- (issue86) improve documentation for looponfailing
|
||||||
|
|
||||||
- refine IO capturing: stdin-redirect pseudo-file now has a NOP close() method
|
- refine IO capturing: stdin-redirect pseudo-file now has a NOP close() method
|
||||||
|
|
||||||
- ship distribute_setup.py version 0.6.10
|
- ship distribute_setup.py version 0.6.10
|
||||||
|
|
||||||
- added links to the new capturelog and coverage plugins
|
- added links to the new capturelog and coverage plugins
|
||||||
|
|
||||||
|
|
||||||
Changes between 1.2.1 and 1.2.0
|
Changes between 1.2.1 and 1.2.0
|
||||||
|
@ -236,79 +236,79 @@ Changes between 1.2.1 and 1.2.0
|
||||||
py.cleanup # remove "*.pyc" and "*$py.class" (jython) files
|
py.cleanup # remove "*.pyc" and "*$py.class" (jython) files
|
||||||
py.cleanup -e .swp -e .cache # also remove files with these extensions
|
py.cleanup -e .swp -e .cache # also remove files with these extensions
|
||||||
py.cleanup -s # remove "build" and "dist" directory next to setup.py files
|
py.cleanup -s # remove "build" and "dist" directory next to setup.py files
|
||||||
py.cleanup -d # also remove empty directories
|
py.cleanup -d # also remove empty directories
|
||||||
py.cleanup -a # synonym for "-s -d -e 'pip-log.txt'"
|
py.cleanup -a # synonym for "-s -d -e 'pip-log.txt'"
|
||||||
py.cleanup -n # dry run, only show what would be removed
|
py.cleanup -n # dry run, only show what would be removed
|
||||||
|
|
||||||
- add a new option "py.test --funcargs" which shows available funcargs
|
- add a new option "py.test --funcargs" which shows available funcargs
|
||||||
and their help strings (docstrings on their respective factory function)
|
and their help strings (docstrings on their respective factory function)
|
||||||
for a given test path
|
for a given test path
|
||||||
|
|
||||||
- display a short and concise traceback if a funcarg lookup fails
|
- display a short and concise traceback if a funcarg lookup fails
|
||||||
|
|
||||||
- early-load "conftest.py" files in non-dot first-level sub directories.
|
- early-load "conftest.py" files in non-dot first-level sub directories.
|
||||||
allows to conveniently keep and access test-related options in a ``test``
|
allows to conveniently keep and access test-related options in a ``test``
|
||||||
subdir and still add command line options.
|
subdir and still add command line options.
|
||||||
|
|
||||||
- fix issue67: new super-short traceback-printing option: "--tb=line" will print a single line for each failing (python) test indicating its filename, lineno and the failure value
|
- fix issue67: new super-short traceback-printing option: "--tb=line" will print a single line for each failing (python) test indicating its filename, lineno and the failure value
|
||||||
|
|
||||||
- fix issue78: always call python-level teardown functions even if the
|
- fix issue78: always call python-level teardown functions even if the
|
||||||
according setup failed. This includes refinements for calling setup_module/class functions
|
according setup failed. This includes refinements for calling setup_module/class functions
|
||||||
which will now only be called once instead of the previous behaviour where they'd be called
|
which will now only be called once instead of the previous behaviour where they'd be called
|
||||||
multiple times if they raise an exception (including a Skipped exception). Any exception
|
multiple times if they raise an exception (including a Skipped exception). Any exception
|
||||||
will be re-corded and associated with all tests in the according module/class scope.
|
will be re-corded and associated with all tests in the according module/class scope.
|
||||||
|
|
||||||
- fix issue63: assume <40 columns to be a bogus terminal width, default to 80
|
- fix issue63: assume <40 columns to be a bogus terminal width, default to 80
|
||||||
|
|
||||||
- fix pdb debugging to be in the correct frame on raises-related errors
|
- fix pdb debugging to be in the correct frame on raises-related errors
|
||||||
|
|
||||||
- update apipkg.py to fix an issue where recursive imports might
|
- update apipkg.py to fix an issue where recursive imports might
|
||||||
unnecessarily break importing
|
unnecessarily break importing
|
||||||
|
|
||||||
- fix plugin links
|
- fix plugin links
|
||||||
|
|
||||||
Changes between 1.2 and 1.1.1
|
Changes between 1.2 and 1.1.1
|
||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
- moved dist/looponfailing from py.test core into a new
|
- moved dist/looponfailing from py.test core into a new
|
||||||
separately released pytest-xdist plugin.
|
separately released pytest-xdist plugin.
|
||||||
|
|
||||||
- new junitxml plugin: --junitxml=path will generate a junit style xml file
|
- new junitxml plugin: --junitxml=path will generate a junit style xml file
|
||||||
which is processable e.g. by the Hudson CI system.
|
which is processable e.g. by the Hudson CI system.
|
||||||
|
|
||||||
- new option: --genscript=path will generate a standalone py.test script
|
- new option: --genscript=path will generate a standalone py.test script
|
||||||
which will not need any libraries installed. thanks to Ralf Schmitt.
|
which will not need any libraries installed. thanks to Ralf Schmitt.
|
||||||
|
|
||||||
- new option: --ignore will prevent specified path from collection.
|
- new option: --ignore will prevent specified path from collection.
|
||||||
Can be specified multiple times.
|
Can be specified multiple times.
|
||||||
|
|
||||||
- new option: --confcutdir=dir will make py.test only consider conftest
|
- new option: --confcutdir=dir will make py.test only consider conftest
|
||||||
files that are relative to the specified dir.
|
files that are relative to the specified dir.
|
||||||
|
|
||||||
- new funcarg: "pytestconfig" is the pytest config object for access
|
- new funcarg: "pytestconfig" is the pytest config object for access
|
||||||
to command line args and can now be easily used in a test.
|
to command line args and can now be easily used in a test.
|
||||||
|
|
||||||
- install 'py.test' and `py.which` with a ``-$VERSION`` suffix to
|
- install 'py.test' and `py.which` with a ``-$VERSION`` suffix to
|
||||||
disambiguate between Python3, python2.X, Jython and PyPy installed versions.
|
disambiguate between Python3, python2.X, Jython and PyPy installed versions.
|
||||||
|
|
||||||
- new "pytestconfig" funcarg allows access to test config object
|
- new "pytestconfig" funcarg allows access to test config object
|
||||||
|
|
||||||
- new "pytest_report_header" hook can return additional lines
|
- new "pytest_report_header" hook can return additional lines
|
||||||
to be displayed at the header of a test run.
|
to be displayed at the header of a test run.
|
||||||
|
|
||||||
- (experimental) allow "py.test path::name1::name2::..." for pointing
|
- (experimental) allow "py.test path::name1::name2::..." for pointing
|
||||||
to a test within a test collection directly. This might eventually
|
to a test within a test collection directly. This might eventually
|
||||||
evolve as a full substitute to "-k" specifications.
|
evolve as a full substitute to "-k" specifications.
|
||||||
|
|
||||||
- streamlined plugin loading: order is now as documented in
|
- streamlined plugin loading: order is now as documented in
|
||||||
customize.html: setuptools, ENV, commandline, conftest.
|
customize.html: setuptools, ENV, commandline, conftest.
|
||||||
also setuptools entry point names are turned to canonical namees ("pytest_*")
|
also setuptools entry point names are turned to canonical namees ("pytest_*")
|
||||||
|
|
||||||
- automatically skip tests that need 'capfd' but have no os.dup
|
- automatically skip tests that need 'capfd' but have no os.dup
|
||||||
|
|
||||||
- allow pytest_generate_tests to be defined in classes as well
|
- allow pytest_generate_tests to be defined in classes as well
|
||||||
|
|
||||||
- deprecate usage of 'disabled' attribute in favour of pytestmark
|
- deprecate usage of 'disabled' attribute in favour of pytestmark
|
||||||
- deprecate definition of Directory, Module, Class and Function nodes
|
- deprecate definition of Directory, Module, Class and Function nodes
|
||||||
in conftest.py files. Use pytest collect hooks instead.
|
in conftest.py files. Use pytest collect hooks instead.
|
||||||
|
|
||||||
|
@ -323,28 +323,28 @@ Changes between 1.2 and 1.1.1
|
||||||
change its long command line options to be a bit shorter (see py.test -h).
|
change its long command line options to be a bit shorter (see py.test -h).
|
||||||
|
|
||||||
- change: pytest doctest plugin is now enabled by default and has a
|
- change: pytest doctest plugin is now enabled by default and has a
|
||||||
new option --doctest-glob to set a pattern for file matches.
|
new option --doctest-glob to set a pattern for file matches.
|
||||||
|
|
||||||
- change: remove internal py._* helper vars, only keep py._pydir
|
- change: remove internal py._* helper vars, only keep py._pydir
|
||||||
|
|
||||||
- robustify capturing to survive if custom pytest_runtest_setup
|
- robustify capturing to survive if custom pytest_runtest_setup
|
||||||
code failed and prevented the capturing setup code from running.
|
code failed and prevented the capturing setup code from running.
|
||||||
|
|
||||||
- make py.test.* helpers provided by default plugins visible early -
|
- make py.test.* helpers provided by default plugins visible early -
|
||||||
works transparently both for pydoc and for interactive sessions
|
works transparently both for pydoc and for interactive sessions
|
||||||
which will regularly see e.g. py.test.mark and py.test.importorskip.
|
which will regularly see e.g. py.test.mark and py.test.importorskip.
|
||||||
|
|
||||||
- simplify internal plugin manager machinery
|
- simplify internal plugin manager machinery
|
||||||
- simplify internal collection tree by introducing a RootCollector node
|
- simplify internal collection tree by introducing a RootCollector node
|
||||||
|
|
||||||
- fix assert reinterpreation that sees a call containing "keyword=..."
|
- fix assert reinterpreation that sees a call containing "keyword=..."
|
||||||
|
|
||||||
- fix issue66: invoke pytest_sessionstart and pytest_sessionfinish
|
- fix issue66: invoke pytest_sessionstart and pytest_sessionfinish
|
||||||
hooks on slaves during dist-testing, report module/session teardown
|
hooks on slaves during dist-testing, report module/session teardown
|
||||||
hooks correctly.
|
hooks correctly.
|
||||||
|
|
||||||
- fix issue65: properly handle dist-testing if no
|
- fix issue65: properly handle dist-testing if no
|
||||||
execnet/py lib installed remotely.
|
execnet/py lib installed remotely.
|
||||||
|
|
||||||
- skip some install-tests if no execnet is available
|
- skip some install-tests if no execnet is available
|
||||||
|
|
||||||
|
@ -354,15 +354,15 @@ Changes between 1.2 and 1.1.1
|
||||||
Changes between 1.1.1 and 1.1.0
|
Changes between 1.1.1 and 1.1.0
|
||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
- introduce automatic plugin registration via 'pytest11'
|
- introduce automatic plugin registration via 'pytest11'
|
||||||
entrypoints via setuptools' pkg_resources.iter_entry_points
|
entrypoints via setuptools' pkg_resources.iter_entry_points
|
||||||
|
|
||||||
- fix py.test dist-testing to work with execnet >= 1.0.0b4
|
- fix py.test dist-testing to work with execnet >= 1.0.0b4
|
||||||
|
|
||||||
- re-introduce py.test.cmdline.main() for better backward compatibility
|
- re-introduce py.test.cmdline.main() for better backward compatibility
|
||||||
|
|
||||||
- svn paths: fix a bug with path.check(versioned=True) for svn paths,
|
- svn paths: fix a bug with path.check(versioned=True) for svn paths,
|
||||||
allow '%' in svn paths, make svnwc.update() default to interactive mode
|
allow '%' in svn paths, make svnwc.update() default to interactive mode
|
||||||
like in 1.0.x and add svnwc.update(interactive=False) to inhibit interaction.
|
like in 1.0.x and add svnwc.update(interactive=False) to inhibit interaction.
|
||||||
|
|
||||||
- refine distributed tarball to contain test and no pyc files
|
- refine distributed tarball to contain test and no pyc files
|
||||||
|
@ -377,16 +377,16 @@ Changes between 1.1.0 and 1.0.2
|
||||||
|
|
||||||
* remove py.rest tool and internal namespace - it was
|
* remove py.rest tool and internal namespace - it was
|
||||||
never really advertised and can still be used with
|
never really advertised and can still be used with
|
||||||
the old release if needed. If there is interest
|
the old release if needed. If there is interest
|
||||||
it could be revived into its own tool i guess.
|
it could be revived into its own tool i guess.
|
||||||
|
|
||||||
* fix issue48 and issue59: raise an Error if the module
|
* fix issue48 and issue59: raise an Error if the module
|
||||||
from an imported test file does not seem to come from
|
from an imported test file does not seem to come from
|
||||||
the filepath - avoids "same-name" confusion that has
|
the filepath - avoids "same-name" confusion that has
|
||||||
been reported repeatedly
|
been reported repeatedly
|
||||||
|
|
||||||
* merged Ronny's nose-compatibility hacks: now
|
* merged Ronny's nose-compatibility hacks: now
|
||||||
nose-style setup_module() and setup() functions are
|
nose-style setup_module() and setup() functions are
|
||||||
supported
|
supported
|
||||||
|
|
||||||
* introduce generalized py.test.mark function marking
|
* introduce generalized py.test.mark function marking
|
||||||
|
@ -395,112 +395,112 @@ Changes between 1.1.0 and 1.0.2
|
||||||
|
|
||||||
* deprecate parser.addgroup in favour of getgroup which creates option group
|
* deprecate parser.addgroup in favour of getgroup which creates option group
|
||||||
|
|
||||||
* add --report command line option that allows to control showing of skipped/xfailed sections
|
* add --report command line option that allows to control showing of skipped/xfailed sections
|
||||||
|
|
||||||
* generalized skipping: a new way to mark python functions with skipif or xfail
|
* generalized skipping: a new way to mark python functions with skipif or xfail
|
||||||
at function, class and modules level based on platform or sys-module attributes.
|
at function, class and modules level based on platform or sys-module attributes.
|
||||||
|
|
||||||
* extend py.test.mark decorator to allow for positional args
|
* extend py.test.mark decorator to allow for positional args
|
||||||
|
|
||||||
* introduce and test "py.cleanup -d" to remove empty directories
|
* introduce and test "py.cleanup -d" to remove empty directories
|
||||||
|
|
||||||
* fix issue #59 - robustify unittest test collection
|
* fix issue #59 - robustify unittest test collection
|
||||||
|
|
||||||
* make bpython/help interaction work by adding an __all__ attribute
|
* make bpython/help interaction work by adding an __all__ attribute
|
||||||
to ApiModule, cleanup initpkg
|
to ApiModule, cleanup initpkg
|
||||||
|
|
||||||
* use MIT license for pylib, add some contributors
|
* use MIT license for pylib, add some contributors
|
||||||
|
|
||||||
* remove py.execnet code and substitute all usages with 'execnet' proper
|
* remove py.execnet code and substitute all usages with 'execnet' proper
|
||||||
|
|
||||||
* fix issue50 - cached_setup now caches more to expectations
|
* fix issue50 - cached_setup now caches more to expectations
|
||||||
for test functions with multiple arguments.
|
for test functions with multiple arguments.
|
||||||
|
|
||||||
* merge Jarko's fixes, issue #45 and #46
|
* merge Jarko's fixes, issue #45 and #46
|
||||||
|
|
||||||
* add the ability to specify a path for py.lookup to search in
|
* add the ability to specify a path for py.lookup to search in
|
||||||
|
|
||||||
* fix a funcarg cached_setup bug probably only occuring
|
* fix a funcarg cached_setup bug probably only occuring
|
||||||
in distributed testing and "module" scope with teardown.
|
in distributed testing and "module" scope with teardown.
|
||||||
|
|
||||||
* many fixes and changes for making the code base python3 compatible,
|
* many fixes and changes for making the code base python3 compatible,
|
||||||
many thanks to Benjamin Peterson for helping with this.
|
many thanks to Benjamin Peterson for helping with this.
|
||||||
|
|
||||||
* consolidate builtins implementation to be compatible with >=2.3,
|
* consolidate builtins implementation to be compatible with >=2.3,
|
||||||
add helpers to ease keeping 2 and 3k compatible code
|
add helpers to ease keeping 2 and 3k compatible code
|
||||||
|
|
||||||
* deprecate py.compat.doctest|subprocess|textwrap|optparse
|
* deprecate py.compat.doctest|subprocess|textwrap|optparse
|
||||||
|
|
||||||
* deprecate py.magic.autopath, remove py/magic directory
|
* deprecate py.magic.autopath, remove py/magic directory
|
||||||
|
|
||||||
* move pytest assertion handling to py/code and a pytest_assertion
|
* move pytest assertion handling to py/code and a pytest_assertion
|
||||||
plugin, add "--no-assert" option, deprecate py.magic namespaces
|
plugin, add "--no-assert" option, deprecate py.magic namespaces
|
||||||
in favour of (less) py.code ones.
|
in favour of (less) py.code ones.
|
||||||
|
|
||||||
* consolidate and cleanup py/code classes and files
|
* consolidate and cleanup py/code classes and files
|
||||||
|
|
||||||
* cleanup py/misc, move tests to bin-for-dist
|
* cleanup py/misc, move tests to bin-for-dist
|
||||||
|
|
||||||
* introduce delattr/delitem/delenv methods to py.test's monkeypatch funcarg
|
* introduce delattr/delitem/delenv methods to py.test's monkeypatch funcarg
|
||||||
|
|
||||||
* consolidate py.log implementation, remove old approach.
|
* consolidate py.log implementation, remove old approach.
|
||||||
|
|
||||||
* introduce py.io.TextIO and py.io.BytesIO for distinguishing between
|
* introduce py.io.TextIO and py.io.BytesIO for distinguishing between
|
||||||
text/unicode and byte-streams (uses underlying standard lib io.*
|
text/unicode and byte-streams (uses underlying standard lib io.*
|
||||||
if available)
|
if available)
|
||||||
|
|
||||||
* make py.unittest_convert helper script available which converts "unittest.py"
|
* make py.unittest_convert helper script available which converts "unittest.py"
|
||||||
style files into the simpler assert/direct-test-classes py.test/nosetests
|
style files into the simpler assert/direct-test-classes py.test/nosetests
|
||||||
style. The script was written by Laura Creighton.
|
style. The script was written by Laura Creighton.
|
||||||
|
|
||||||
* simplified internal localpath implementation
|
* simplified internal localpath implementation
|
||||||
|
|
||||||
Changes between 1.0.1 and 1.0.2
|
Changes between 1.0.1 and 1.0.2
|
||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
* fixing packaging issues, triggered by fedora redhat packaging,
|
* fixing packaging issues, triggered by fedora redhat packaging,
|
||||||
also added doc, examples and contrib dirs to the tarball.
|
also added doc, examples and contrib dirs to the tarball.
|
||||||
|
|
||||||
* added a documentation link to the new django plugin.
|
* added a documentation link to the new django plugin.
|
||||||
|
|
||||||
Changes between 1.0.0 and 1.0.1
|
Changes between 1.0.0 and 1.0.1
|
||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
* added a 'pytest_nose' plugin which handles nose.SkipTest,
|
* added a 'pytest_nose' plugin which handles nose.SkipTest,
|
||||||
nose-style function/method/generator setup/teardown and
|
nose-style function/method/generator setup/teardown and
|
||||||
tries to report functions correctly.
|
tries to report functions correctly.
|
||||||
|
|
||||||
* capturing of unicode writes or encoded strings to sys.stdout/err
|
* capturing of unicode writes or encoded strings to sys.stdout/err
|
||||||
work better, also terminalwriting was adapted and somewhat
|
work better, also terminalwriting was adapted and somewhat
|
||||||
unified between windows and linux.
|
unified between windows and linux.
|
||||||
|
|
||||||
* improved documentation layout and content a lot
|
* improved documentation layout and content a lot
|
||||||
|
|
||||||
* added a "--help-config" option to show conftest.py / ENV-var names for
|
* added a "--help-config" option to show conftest.py / ENV-var names for
|
||||||
all longopt cmdline options, and some special conftest.py variables.
|
all longopt cmdline options, and some special conftest.py variables.
|
||||||
renamed 'conf_capture' conftest setting to 'option_capture' accordingly.
|
renamed 'conf_capture' conftest setting to 'option_capture' accordingly.
|
||||||
|
|
||||||
* fix issue #27: better reporting on non-collectable items given on commandline
|
* fix issue #27: better reporting on non-collectable items given on commandline
|
||||||
(e.g. pyc files)
|
(e.g. pyc files)
|
||||||
|
|
||||||
* fix issue #33: added --version flag (thanks Benjamin Peterson)
|
* fix issue #33: added --version flag (thanks Benjamin Peterson)
|
||||||
|
|
||||||
* fix issue #32: adding support for "incomplete" paths to wcpath.status()
|
* fix issue #32: adding support for "incomplete" paths to wcpath.status()
|
||||||
|
|
||||||
* "Test" prefixed classes are *not* collected by default anymore if they
|
* "Test" prefixed classes are *not* collected by default anymore if they
|
||||||
have an __init__ method
|
have an __init__ method
|
||||||
|
|
||||||
* monkeypatch setenv() now accepts a "prepend" parameter
|
* monkeypatch setenv() now accepts a "prepend" parameter
|
||||||
|
|
||||||
* improved reporting of collection error tracebacks
|
* improved reporting of collection error tracebacks
|
||||||
|
|
||||||
* simplified multicall mechanism and plugin architecture,
|
* simplified multicall mechanism and plugin architecture,
|
||||||
renamed some internal methods and argnames
|
renamed some internal methods and argnames
|
||||||
|
|
||||||
Changes between 1.0.0b9 and 1.0.0
|
Changes between 1.0.0b9 and 1.0.0
|
||||||
=====================================
|
=====================================
|
||||||
|
|
||||||
* more terse reporting try to show filesystem path relatively to current dir
|
* more terse reporting try to show filesystem path relatively to current dir
|
||||||
* improve xfail output a bit
|
* improve xfail output a bit
|
||||||
|
|
||||||
Changes between 1.0.0b8 and 1.0.0b9
|
Changes between 1.0.0b8 and 1.0.0b9
|
||||||
|
@ -513,26 +513,26 @@ Changes between 1.0.0b8 and 1.0.0b9
|
||||||
|
|
||||||
* setup/teardown or collection problems now show as ERRORs
|
* setup/teardown or collection problems now show as ERRORs
|
||||||
or with big "E"'s in the progress lines. they are reported
|
or with big "E"'s in the progress lines. they are reported
|
||||||
and counted separately.
|
and counted separately.
|
||||||
|
|
||||||
* dist-testing: properly handle test items that get locally
|
* dist-testing: properly handle test items that get locally
|
||||||
collected but cannot be collected on the remote side - often
|
collected but cannot be collected on the remote side - often
|
||||||
due to platform/dependency reasons
|
due to platform/dependency reasons
|
||||||
|
|
||||||
* simplified py.test.mark API - see keyword plugin documentation
|
* simplified py.test.mark API - see keyword plugin documentation
|
||||||
|
|
||||||
* integrate better with logging: capturing now by default captures
|
* integrate better with logging: capturing now by default captures
|
||||||
test functions and their immediate setup/teardown in a single stream
|
test functions and their immediate setup/teardown in a single stream
|
||||||
|
|
||||||
* capsys and capfd funcargs now have a readouterr() and a close() method
|
* capsys and capfd funcargs now have a readouterr() and a close() method
|
||||||
(underlyingly py.io.StdCapture/FD objects are used which grew a
|
(underlyingly py.io.StdCapture/FD objects are used which grew a
|
||||||
readouterr() method as well to return snapshots of captured out/err)
|
readouterr() method as well to return snapshots of captured out/err)
|
||||||
|
|
||||||
* make assert-reinterpretation work better with comparisons not
|
* make assert-reinterpretation work better with comparisons not
|
||||||
returning bools (reported with numpy from thanks maciej fijalkowski)
|
returning bools (reported with numpy from thanks maciej fijalkowski)
|
||||||
|
|
||||||
* reworked per-test output capturing into the pytest_iocapture.py plugin
|
* reworked per-test output capturing into the pytest_iocapture.py plugin
|
||||||
and thus removed capturing code from config object
|
and thus removed capturing code from config object
|
||||||
|
|
||||||
* item.repr_failure(excinfo) instead of item.repr_failure(excinfo, outerr)
|
* item.repr_failure(excinfo) instead of item.repr_failure(excinfo, outerr)
|
||||||
|
|
||||||
|
@ -542,126 +542,126 @@ Changes between 1.0.0b7 and 1.0.0b8
|
||||||
|
|
||||||
* pytest_unittest-plugin is now enabled by default
|
* pytest_unittest-plugin is now enabled by default
|
||||||
|
|
||||||
* introduced pytest_keyboardinterrupt hook and
|
* introduced pytest_keyboardinterrupt hook and
|
||||||
refined pytest_sessionfinish hooked, added tests.
|
refined pytest_sessionfinish hooked, added tests.
|
||||||
|
|
||||||
* workaround a buggy logging module interaction ("closing already closed
|
* workaround a buggy logging module interaction ("closing already closed
|
||||||
files"). Thanks to Sridhar Ratnakumar for triggering.
|
files"). Thanks to Sridhar Ratnakumar for triggering.
|
||||||
|
|
||||||
* if plugins use "py.test.importorskip" for importing
|
* if plugins use "py.test.importorskip" for importing
|
||||||
a dependency only a warning will be issued instead
|
a dependency only a warning will be issued instead
|
||||||
of exiting the testing process.
|
of exiting the testing process.
|
||||||
|
|
||||||
* many improvements to docs:
|
* many improvements to docs:
|
||||||
- refined funcargs doc , use the term "factory" instead of "provider"
|
- refined funcargs doc , use the term "factory" instead of "provider"
|
||||||
- added a new talk/tutorial doc page
|
- added a new talk/tutorial doc page
|
||||||
- better download page
|
- better download page
|
||||||
- better plugin docstrings
|
- better plugin docstrings
|
||||||
- added new plugins page and automatic doc generation script
|
- added new plugins page and automatic doc generation script
|
||||||
|
|
||||||
* fixed teardown problem related to partially failing funcarg setups
|
* fixed teardown problem related to partially failing funcarg setups
|
||||||
(thanks MrTopf for reporting), "pytest_runtest_teardown" is now
|
(thanks MrTopf for reporting), "pytest_runtest_teardown" is now
|
||||||
always invoked even if the "pytest_runtest_setup" failed.
|
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.
|
||||||
|
|
||||||
Changes between 1.0.0b3 and 1.0.0b7
|
Changes between 1.0.0b3 and 1.0.0b7
|
||||||
=============================================
|
=============================================
|
||||||
|
|
||||||
* renamed py.test.xfail back to py.test.mark.xfail to avoid
|
* renamed py.test.xfail back to py.test.mark.xfail to avoid
|
||||||
two ways to decorate for xfail
|
two ways to decorate for xfail
|
||||||
|
|
||||||
* re-added py.test.mark decorator for setting keywords on functions
|
* re-added py.test.mark decorator for setting keywords on functions
|
||||||
(it was actually documented so removing it was not nice)
|
(it was actually documented so removing it was not nice)
|
||||||
|
|
||||||
* remove scope-argument from request.addfinalizer() because
|
* remove scope-argument from request.addfinalizer() because
|
||||||
request.cached_setup has the scope arg. TOOWTDI.
|
request.cached_setup has the scope arg. TOOWTDI.
|
||||||
|
|
||||||
* perform setup finalization before reporting failures
|
* perform setup finalization before reporting failures
|
||||||
|
|
||||||
* apply modified patches from Andreas Kloeckner to allow
|
* apply modified patches from Andreas Kloeckner to allow
|
||||||
test functions to have no func_code (#22) and to make
|
test functions to have no func_code (#22) and to make
|
||||||
"-k" and function keywords work (#20)
|
"-k" and function keywords work (#20)
|
||||||
|
|
||||||
* apply patch from Daniel Peolzleithner (issue #23)
|
* apply patch from Daniel Peolzleithner (issue #23)
|
||||||
|
|
||||||
* resolve issue #18, multiprocessing.Manager() and
|
* resolve issue #18, multiprocessing.Manager() and
|
||||||
redirection clash
|
redirection clash
|
||||||
|
|
||||||
* make __name__ == "__channelexec__" for remote_exec code
|
* 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
|
||||||
=============================================
|
=============================================
|
||||||
|
|
||||||
* plugin classes are removed: one now defines
|
* plugin classes are removed: one now defines
|
||||||
hooks directly in conftest.py or global pytest_*.py
|
hooks directly in conftest.py or global pytest_*.py
|
||||||
files.
|
files.
|
||||||
|
|
||||||
* added new pytest_namespace(config) hook that allows
|
* added new pytest_namespace(config) hook that allows
|
||||||
to inject helpers directly to the py.test.* namespace.
|
to inject helpers directly to the py.test.* namespace.
|
||||||
|
|
||||||
* documented and refined many hooks
|
* documented and refined many hooks
|
||||||
|
|
||||||
|
* added new style of generative tests via
|
||||||
|
pytest_generate_tests hook that integrates
|
||||||
|
well with function arguments.
|
||||||
|
|
||||||
* added new style of generative tests via
|
|
||||||
pytest_generate_tests hook that integrates
|
|
||||||
well with function arguments.
|
|
||||||
|
|
||||||
|
|
||||||
Changes between 0.9.2 and 1.0.0b1
|
Changes between 0.9.2 and 1.0.0b1
|
||||||
=============================================
|
=============================================
|
||||||
|
|
||||||
* introduced new "funcarg" setup method,
|
* introduced new "funcarg" setup method,
|
||||||
see doc/test/funcarg.txt
|
see doc/test/funcarg.txt
|
||||||
|
|
||||||
* introduced plugin architecuture and many
|
* introduced plugin architecuture and many
|
||||||
new py.test plugins, see
|
new py.test plugins, see
|
||||||
doc/test/plugins.txt
|
doc/test/plugins.txt
|
||||||
|
|
||||||
* teardown_method is now guaranteed to get
|
* teardown_method is now guaranteed to get
|
||||||
called after a test method has run.
|
called after a test method has run.
|
||||||
|
|
||||||
* new method: py.test.importorskip(mod,minversion)
|
* new method: py.test.importorskip(mod,minversion)
|
||||||
will either import or call py.test.skip()
|
will either import or call py.test.skip()
|
||||||
|
|
||||||
* completely revised internal py.test architecture
|
* completely revised internal py.test architecture
|
||||||
|
|
||||||
* new py.process.ForkedFunc object allowing to
|
* new py.process.ForkedFunc object allowing to
|
||||||
fork execution of a function to a sub process
|
fork execution of a function to a sub process
|
||||||
and getting a result back.
|
and getting a result back.
|
||||||
|
|
||||||
XXX lots of things missing here XXX
|
XXX lots of things missing here XXX
|
||||||
|
|
||||||
Changes between 0.9.1 and 0.9.2
|
Changes between 0.9.1 and 0.9.2
|
||||||
===============================
|
===============================
|
||||||
|
|
||||||
* refined installation and metadata, created new setup.py,
|
* refined installation and metadata, created new setup.py,
|
||||||
now based on setuptools/ez_setup (thanks to Ralf Schmitt
|
now based on setuptools/ez_setup (thanks to Ralf Schmitt
|
||||||
for his support).
|
for his support).
|
||||||
|
|
||||||
* improved the way of making py.* scripts available in
|
* improved the way of making py.* scripts available in
|
||||||
windows environments, they are now added to the
|
windows environments, they are now added to the
|
||||||
Scripts directory as ".cmd" files.
|
Scripts directory as ".cmd" files.
|
||||||
|
|
||||||
* py.path.svnwc.status() now is more complete and
|
* py.path.svnwc.status() now is more complete and
|
||||||
uses xml output from the 'svn' command if available
|
uses xml output from the 'svn' command if available
|
||||||
(Guido Wesdorp)
|
(Guido Wesdorp)
|
||||||
|
|
||||||
* fix for py.path.svn* to work with svn 1.5
|
* fix for py.path.svn* to work with svn 1.5
|
||||||
(Chris Lamb)
|
(Chris Lamb)
|
||||||
|
|
||||||
* fix path.relto(otherpath) method on windows to
|
* fix path.relto(otherpath) method on windows to
|
||||||
use normcase for checking if a path is relative.
|
use normcase for checking if a path is relative.
|
||||||
|
|
||||||
* py.test's traceback is better parseable from editors
|
* py.test's traceback is better parseable from editors
|
||||||
(follows the filenames:LINENO: MSG convention)
|
(follows the filenames:LINENO: MSG convention)
|
||||||
(thanks to Osmo Salomaa)
|
(thanks to Osmo Salomaa)
|
||||||
|
|
||||||
* fix to javascript-generation, "py.test --runbrowser"
|
* fix to javascript-generation, "py.test --runbrowser"
|
||||||
should work more reliably now
|
should work more reliably now
|
||||||
|
|
||||||
* removed previously accidentally added
|
* removed previously accidentally added
|
||||||
py.test.broken and py.test.notimplemented helpers.
|
py.test.broken and py.test.notimplemented helpers.
|
||||||
|
|
||||||
* there now is a py.__version__ attribute
|
* there now is a py.__version__ attribute
|
||||||
|
|
||||||
|
|
14
doc/bin.txt
14
doc/bin.txt
|
@ -1,11 +1,11 @@
|
||||||
======================
|
======================
|
||||||
pylib scripts
|
pylib scripts
|
||||||
======================
|
======================
|
||||||
|
|
||||||
The pylib installs several scripts to support testing and (python)
|
The pylib installs several scripts to support testing and (python)
|
||||||
development. If working from a checkout you may also add ``bin`` to
|
development. If working from a checkout you may also add ``bin`` to
|
||||||
your ``PATH`` environment variable which makes the scripts available on
|
your ``PATH`` environment variable which makes the scripts available on
|
||||||
your shell prompt.
|
your shell prompt.
|
||||||
|
|
||||||
``py.test`` and ``py.test-$VERSION``
|
``py.test`` and ``py.test-$VERSION``
|
||||||
============================================
|
============================================
|
||||||
|
@ -14,16 +14,16 @@ The ``py.test`` executable is the main tool that the py lib offers;
|
||||||
in fact most code in the py lib is geared towards supporting the
|
in fact most code in the py lib is geared towards supporting the
|
||||||
testing process. See the `py.test documentation`_ for extensive
|
testing process. See the `py.test documentation`_ for extensive
|
||||||
documentation. The ``py.test-$VERSION`` is the same script with
|
documentation. The ``py.test-$VERSION`` is the same script with
|
||||||
an interpreter specific suffix appended to make
|
an interpreter specific suffix appended to make
|
||||||
several versions of py.test for using specific interpreters
|
several versions of py.test for using specific interpreters
|
||||||
accessible:
|
accessible:
|
||||||
|
|
||||||
* CPython2.4: py.test-2.4
|
* CPython2.4: py.test-2.4
|
||||||
* CPython2.5: py.test-2.5
|
* CPython2.5: py.test-2.5
|
||||||
* ...
|
* ...
|
||||||
* CPython3.1: py.test-3.1
|
* CPython3.1: py.test-3.1
|
||||||
* Jython-2.5.1: py.test-jython
|
* Jython-2.5.1: py.test-jython
|
||||||
* pypy-$SUFFIX: py.test-pypy-$SUFFIX
|
* pypy-$SUFFIX: py.test-pypy-$SUFFIX
|
||||||
|
|
||||||
.. _`py.test documentation`: test/index.html
|
.. _`py.test documentation`: test/index.html
|
||||||
|
|
||||||
|
@ -33,7 +33,7 @@ accessible:
|
||||||
Usage: ``py.which modulename``
|
Usage: ``py.which modulename``
|
||||||
|
|
||||||
Print the ``__file__`` of the module that is imported via ``import modulename``.
|
Print the ``__file__`` of the module that is imported via ``import modulename``.
|
||||||
The version-suffix is the same as with ``py.test`` above.
|
The version-suffix is the same as with ``py.test`` above.
|
||||||
|
|
||||||
``py.cleanup``
|
``py.cleanup``
|
||||||
==============
|
==============
|
||||||
|
|
|
@ -18,7 +18,7 @@ Contents of the library
|
||||||
Every object in the ``py.code`` library wraps a code Python object related
|
Every object in the ``py.code`` library wraps a code Python object related
|
||||||
to code objects, source code, frames and tracebacks: the ``py.code.Code``
|
to code objects, source code, frames and tracebacks: the ``py.code.Code``
|
||||||
class wraps code objects, ``py.code.Source`` source snippets,
|
class wraps code objects, ``py.code.Source`` source snippets,
|
||||||
``py.code.Traceback` exception tracebacks, ``py.code.Frame`` frame
|
``py.code.Traceback` exception tracebacks, ``py.code.Frame`` frame
|
||||||
objects (as found in e.g. tracebacks) and ``py.code.ExceptionInfo`` the
|
objects (as found in e.g. tracebacks) and ``py.code.ExceptionInfo`` the
|
||||||
tuple provided by sys.exc_info() (containing exception and traceback
|
tuple provided by sys.exc_info() (containing exception and traceback
|
||||||
information when an exception occurs). Also in the library is a helper function
|
information when an exception occurs). Also in the library is a helper function
|
||||||
|
|
|
@ -2,7 +2,7 @@ import py
|
||||||
|
|
||||||
from py._plugin.pytest_restdoc import convert_rest_html, strip_html_header
|
from py._plugin.pytest_restdoc import convert_rest_html, strip_html_header
|
||||||
|
|
||||||
html = py.xml.html
|
html = py.xml.html
|
||||||
|
|
||||||
class css:
|
class css:
|
||||||
#pagetitle = "pagetitle"
|
#pagetitle = "pagetitle"
|
||||||
|
@ -11,7 +11,7 @@ class css:
|
||||||
navspace = "navspace"
|
navspace = "navspace"
|
||||||
versioninfo = "versioninfo"
|
versioninfo = "versioninfo"
|
||||||
|
|
||||||
class Page(object):
|
class Page(object):
|
||||||
doctype = ('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'
|
doctype = ('<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"'
|
||||||
' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n')
|
' "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n')
|
||||||
googlefragment = """
|
googlefragment = """
|
||||||
|
@ -27,18 +27,18 @@ pageTracker._trackPageview();
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, project, title, targetpath, stylesheeturl=None,
|
def __init__(self, project, title, targetpath, stylesheeturl=None,
|
||||||
type="text/html", encoding="ISO-8859-1"):
|
type="text/html", encoding="ISO-8859-1"):
|
||||||
self.project = project
|
self.project = project
|
||||||
self.title = project.prefix_title + title
|
self.title = project.prefix_title + title
|
||||||
self.targetpath = targetpath
|
self.targetpath = targetpath
|
||||||
self.stylesheeturl = stylesheeturl
|
self.stylesheeturl = stylesheeturl
|
||||||
self.type = type
|
self.type = type
|
||||||
self.encoding = encoding
|
self.encoding = encoding
|
||||||
|
|
||||||
self.body = html.body()
|
self.body = html.body()
|
||||||
self.head = html.head()
|
self.head = html.head()
|
||||||
self._root = html.html(self.head, self.body)
|
self._root = html.html(self.head, self.body)
|
||||||
self.fill()
|
self.fill()
|
||||||
|
|
||||||
def a_href(self, name, url, **kwargs):
|
def a_href(self, name, url, **kwargs):
|
||||||
return html.a(name, class_="menu", href=url, **kwargs)
|
return html.a(name, class_="menu", href=url, **kwargs)
|
||||||
|
@ -54,7 +54,7 @@ pageTracker._trackPageview();
|
||||||
return html.a(name, class_="menu",
|
return html.a(name, class_="menu",
|
||||||
href=relpath(self.targetpath.strpath,
|
href=relpath(self.targetpath.strpath,
|
||||||
apipath.join(relhtmlpath).strpath))
|
apipath.join(relhtmlpath).strpath))
|
||||||
|
|
||||||
def fill_menubar(self):
|
def fill_menubar(self):
|
||||||
items = [
|
items = [
|
||||||
self.a_docref("INSTALL", "install.html"),
|
self.a_docref("INSTALL", "install.html"),
|
||||||
|
@ -73,7 +73,7 @@ pageTracker._trackPageview();
|
||||||
self.a_href("hudson-tests", "http://hudson.testrun.org")
|
self.a_href("hudson-tests", "http://hudson.testrun.org")
|
||||||
),
|
),
|
||||||
html.div(
|
html.div(
|
||||||
html.h3("supporting APIs:"),
|
html.h3("supporting APIs:"),
|
||||||
self.a_docref("Index", "index.html"),
|
self.a_docref("Index", "index.html"),
|
||||||
self.a_docref("py.path", "path.html"),
|
self.a_docref("py.path", "path.html"),
|
||||||
self.a_docref("py.code", "code.html"),
|
self.a_docref("py.code", "code.html"),
|
||||||
|
@ -86,12 +86,12 @@ pageTracker._trackPageview();
|
||||||
self.menubar = html.div(id=css.menubar, *[
|
self.menubar = html.div(id=css.menubar, *[
|
||||||
html.div(item) for item in items])
|
html.div(item) for item in items])
|
||||||
version = py.version
|
version = py.version
|
||||||
announcelink = self.a_docref("%s ANN" % version,
|
announcelink = self.a_docref("%s ANN" % version,
|
||||||
"announce/release-%s.html" %(version,))
|
"announce/release-%s.html" %(version,))
|
||||||
self.menubar.insert(0,
|
self.menubar.insert(0,
|
||||||
html.div(announcelink))
|
html.div(announcelink))
|
||||||
#self.a_href("%s-%s" % (self.title, py.version),
|
#self.a_href("%s-%s" % (self.title, py.version),
|
||||||
# "http://pypi.python.org/pypi/py/%s" % version,
|
# "http://pypi.python.org/pypi/py/%s" % version,
|
||||||
#id="versioninfo",
|
#id="versioninfo",
|
||||||
|
|
||||||
def fill(self):
|
def fill(self):
|
||||||
|
@ -108,31 +108,31 @@ pageTracker._trackPageview();
|
||||||
self.body.append(html.div(
|
self.body.append(html.div(
|
||||||
self.project.logo,
|
self.project.logo,
|
||||||
self.menubar,
|
self.menubar,
|
||||||
id=css.navspace,
|
id=css.navspace,
|
||||||
))
|
))
|
||||||
|
|
||||||
#self.body.append(html.div(self.title, id=css.pagetitle))
|
#self.body.append(html.div(self.title, id=css.pagetitle))
|
||||||
self.contentspace = html.div(id=css.contentspace)
|
self.contentspace = html.div(id=css.contentspace)
|
||||||
self.body.append(self.contentspace)
|
self.body.append(self.contentspace)
|
||||||
|
|
||||||
def unicode(self, doctype=True):
|
def unicode(self, doctype=True):
|
||||||
page = self._root.unicode()
|
page = self._root.unicode()
|
||||||
page = page.replace("</body>", self.googlefragment + "</body>")
|
page = page.replace("</body>", self.googlefragment + "</body>")
|
||||||
if doctype:
|
if doctype:
|
||||||
return self.doctype + page
|
return self.doctype + page
|
||||||
else:
|
else:
|
||||||
return page
|
return page
|
||||||
|
|
||||||
class PyPage(Page):
|
class PyPage(Page):
|
||||||
def get_menubar(self):
|
def get_menubar(self):
|
||||||
menubar = super(PyPage, self).get_menubar()
|
menubar = super(PyPage, self).get_menubar()
|
||||||
# base layout
|
# base layout
|
||||||
menubar.append(
|
menubar.append(
|
||||||
html.a("issue", href="https://codespeak.net/issue/py-dev/",
|
html.a("issue", href="https://codespeak.net/issue/py-dev/",
|
||||||
class_="menu"),
|
class_="menu"),
|
||||||
)
|
)
|
||||||
return menubar
|
return menubar
|
||||||
|
|
||||||
|
|
||||||
def getrealname(username):
|
def getrealname(username):
|
||||||
try:
|
try:
|
||||||
|
@ -143,30 +143,30 @@ def getrealname(username):
|
||||||
user = uconf.system.User(username)
|
user = uconf.system.User(username)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
raise
|
raise
|
||||||
try:
|
try:
|
||||||
return user.realname or username
|
return user.realname or username
|
||||||
except KeyError:
|
except KeyError:
|
||||||
return username
|
return username
|
||||||
|
|
||||||
|
|
||||||
class Project:
|
class Project:
|
||||||
mydir = py.path.local(__file__).dirpath()
|
mydir = py.path.local(__file__).dirpath()
|
||||||
title = "py lib"
|
title = "py lib"
|
||||||
prefix_title = "" # we have a logo already containing "py lib"
|
prefix_title = "" # we have a logo already containing "py lib"
|
||||||
encoding = 'latin1'
|
encoding = 'latin1'
|
||||||
logo = html.div(
|
logo = html.div(
|
||||||
html.a(
|
html.a(
|
||||||
html.img(alt="py lib", id='pyimg', height=114/2, width=154/2,
|
html.img(alt="py lib", id='pyimg', height=114/2, width=154/2,
|
||||||
src="http://codespeak.net/img/pylib.png"),
|
src="http://codespeak.net/img/pylib.png"),
|
||||||
href="http://pylib.org"))
|
href="http://pylib.org"))
|
||||||
Page = PyPage
|
Page = PyPage
|
||||||
|
|
||||||
def __init__(self, sourcepath=None):
|
def __init__(self, sourcepath=None):
|
||||||
if sourcepath is None:
|
if sourcepath is None:
|
||||||
sourcepath = self.mydir
|
sourcepath = self.mydir
|
||||||
self.setpath(sourcepath)
|
self.setpath(sourcepath)
|
||||||
|
|
||||||
def setpath(self, sourcepath, docpath=None,
|
def setpath(self, sourcepath, docpath=None,
|
||||||
apigenpath=None, stylesheet=None):
|
apigenpath=None, stylesheet=None):
|
||||||
self.sourcepath = sourcepath
|
self.sourcepath = sourcepath
|
||||||
if docpath is None:
|
if docpath is None:
|
||||||
|
@ -197,7 +197,7 @@ class Project:
|
||||||
reloutputpath = txtpath.new(ext='.html').relto(self.sourcepath)
|
reloutputpath = txtpath.new(ext='.html').relto(self.sourcepath)
|
||||||
return self.docpath.join(reloutputpath)
|
return self.docpath.join(reloutputpath)
|
||||||
|
|
||||||
def process(self, txtpath):
|
def process(self, txtpath):
|
||||||
encoding = self.encoding
|
encoding = self.encoding
|
||||||
content = self.get_content(txtpath, encoding)
|
content = self.get_content(txtpath, encoding)
|
||||||
outputpath = self.get_htmloutputpath(txtpath)
|
outputpath = self.get_htmloutputpath(txtpath)
|
||||||
|
@ -214,16 +214,16 @@ class Project:
|
||||||
stylesheet=stylesheet, encoding=encoding)
|
stylesheet=stylesheet, encoding=encoding)
|
||||||
content = strip_html_header(content, encoding=encoding)
|
content = strip_html_header(content, encoding=encoding)
|
||||||
|
|
||||||
title = txtpath.purebasename
|
title = txtpath.purebasename
|
||||||
if txtpath.dirpath().basename == "test":
|
if txtpath.dirpath().basename == "test":
|
||||||
title = "py.test " + title
|
title = "py.test " + title
|
||||||
# title = "[%s] %s" % (txtpath.purebasename, py.version)
|
# title = "[%s] %s" % (txtpath.purebasename, py.version)
|
||||||
page = self.Page(self, title,
|
page = self.Page(self, title,
|
||||||
outputpath, stylesheeturl=stylesheet)
|
outputpath, stylesheeturl=stylesheet)
|
||||||
|
|
||||||
try:
|
try:
|
||||||
modified = py.process.cmdexec(
|
modified = py.process.cmdexec(
|
||||||
"hg tip --template 'modified {date|shortdate}'"
|
"hg tip --template 'modified {date|shortdate}'"
|
||||||
)
|
)
|
||||||
except py.process.cmdexec.Error:
|
except py.process.cmdexec.Error:
|
||||||
modified = " "
|
modified = " "
|
||||||
|
@ -231,10 +231,10 @@ class Project:
|
||||||
#page.body.append(html.div(modified, id="docinfoline"))
|
#page.body.append(html.div(modified, id="docinfoline"))
|
||||||
|
|
||||||
page.contentspace.append(py.xml.raw(content))
|
page.contentspace.append(py.xml.raw(content))
|
||||||
outputpath.ensure().write(page.unicode().encode(encoding))
|
outputpath.ensure().write(page.unicode().encode(encoding))
|
||||||
|
|
||||||
# XXX this function comes from apigen/linker.py, put it
|
# XXX this function comes from apigen/linker.py, put it
|
||||||
# somewhere in py lib
|
# somewhere in py lib
|
||||||
import os
|
import os
|
||||||
def relpath(p1, p2, sep=os.path.sep, back='..', normalize=True):
|
def relpath(p1, p2, sep=os.path.sep, back='..', normalize=True):
|
||||||
""" create a relative path from p1 to p2
|
""" create a relative path from p1 to p2
|
||||||
|
@ -268,7 +268,7 @@ def relpath(p1, p2, sep=os.path.sep, back='..', normalize=True):
|
||||||
# AA BB
|
# AA BB
|
||||||
# AA CC -> CC
|
# AA CC -> CC
|
||||||
#
|
#
|
||||||
# AA BB
|
# AA BB
|
||||||
# AA -> ../AA
|
# AA -> ../AA
|
||||||
|
|
||||||
diffindex = 0
|
diffindex = 0
|
||||||
|
|
|
@ -1,50 +1,50 @@
|
||||||
Contact and Communication points
|
Contact and Communication points
|
||||||
===================================
|
===================================
|
||||||
|
|
||||||
- `py-dev developers list`_ announcements and discussions.
|
- `py-dev developers list`_ announcements and discussions.
|
||||||
|
|
||||||
- #pylib on irc.freenode.net IRC channel for random questions.
|
- #pylib on irc.freenode.net IRC channel for random questions.
|
||||||
|
|
||||||
|
|
||||||
- `tetamap`_: Holger Krekel's blog, often about testing and py.test related news.
|
- `tetamap`_: Holger Krekel's blog, often about testing and py.test related news.
|
||||||
|
|
||||||
- `Testing In Python`_: a mailing list for testing tools and discussion.
|
- `Testing In Python`_: a mailing list for testing tools and discussion.
|
||||||
|
|
||||||
- `commit mailing list`_ or `@pylibcommit`_ to follow development commits,
|
- `commit mailing list`_ or `@pylibcommit`_ to follow development commits,
|
||||||
|
|
||||||
- `bitbucket issue tracker`_ use this bitbucket issue tracker to report
|
- `bitbucket issue tracker`_ use this bitbucket issue tracker to report
|
||||||
bugs or request features.
|
bugs or request features.
|
||||||
|
|
||||||
- `merlinux.eu`_ offers on-site teaching and consulting services.
|
- `merlinux.eu`_ offers on-site teaching and consulting services.
|
||||||
|
|
||||||
.. _`bitbucket issue tracker`: http://bitbucket.org/hpk42/py-trunk/issues/
|
.. _`bitbucket issue tracker`: http://bitbucket.org/hpk42/py-trunk/issues/
|
||||||
|
|
||||||
.. _`merlinux.eu`: http://merlinux.eu
|
.. _`merlinux.eu`: http://merlinux.eu
|
||||||
|
|
||||||
.. _`get an account`:
|
.. _`get an account`:
|
||||||
|
|
||||||
.. _tetamap: http://tetamap.wordpress.com
|
.. _tetamap: http://tetamap.wordpress.com
|
||||||
|
|
||||||
.. _`@pylibcommit`: http://twitter.com/pylibcommit
|
.. _`@pylibcommit`: http://twitter.com/pylibcommit
|
||||||
|
|
||||||
|
|
||||||
..
|
..
|
||||||
get an account on codespeak
|
get an account on codespeak
|
||||||
---------------------------
|
---------------------------
|
||||||
|
|
||||||
codespeak_ is where the subversion repository is hosted. If you know
|
codespeak_ is where the subversion repository is hosted. If you know
|
||||||
someone who is active on codespeak already or you are otherwise known in
|
someone who is active on codespeak already or you are otherwise known in
|
||||||
the community (see also: FOAF_) you will get access. But even if
|
the community (see also: FOAF_) you will get access. But even if
|
||||||
you are new to the python developer community please come to the IRC
|
you are new to the python developer community please come to the IRC
|
||||||
or the mailing list and ask questions, get involved.
|
or the mailing list and ask questions, get involved.
|
||||||
|
|
||||||
.. _`Testing in Python`: http://lists.idyll.org/listinfo/testing-in-python
|
.. _`Testing in Python`: http://lists.idyll.org/listinfo/testing-in-python
|
||||||
.. _FOAF: http://en.wikipedia.org/wiki/FOAF
|
.. _FOAF: http://en.wikipedia.org/wiki/FOAF
|
||||||
.. _us: http://codespeak.net/mailman/listinfo/py-dev
|
.. _us: http://codespeak.net/mailman/listinfo/py-dev
|
||||||
.. _codespeak: http://codespeak.net/
|
.. _codespeak: http://codespeak.net/
|
||||||
.. _`py-dev`:
|
.. _`py-dev`:
|
||||||
.. _`development mailing list`:
|
.. _`development mailing list`:
|
||||||
.. _`py-dev developers list`: http://codespeak.net/mailman/listinfo/py-dev
|
.. _`py-dev developers list`: http://codespeak.net/mailman/listinfo/py-dev
|
||||||
.. _`py-svn`:
|
.. _`py-svn`:
|
||||||
.. _`commit mailing list`: http://codespeak.net/mailman/listinfo/py-svn
|
.. _`commit mailing list`: http://codespeak.net/mailman/listinfo/py-svn
|
||||||
|
|
||||||
|
|
|
@ -7,9 +7,9 @@ def otherfunc(a,b):
|
||||||
def somefunc(x,y):
|
def somefunc(x,y):
|
||||||
otherfunc(x,y)
|
otherfunc(x,y)
|
||||||
|
|
||||||
def otherfunc_multi(a,b):
|
def otherfunc_multi(a,b):
|
||||||
assert (a ==
|
assert (a ==
|
||||||
b)
|
b)
|
||||||
|
|
||||||
def test_generative(param1, param2):
|
def test_generative(param1, param2):
|
||||||
assert param1 * 2 < param2
|
assert param1 * 2 < param2
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
hello = "world"
|
hello = "world"
|
||||||
|
|
||||||
def test_func():
|
def test_func():
|
||||||
pass
|
pass
|
||||||
|
|
|
@ -4,7 +4,7 @@ failure_demo = py.path.local(__file__).dirpath('failure_demo.py')
|
||||||
|
|
||||||
pytest_plugins = "pytest_pytester"
|
pytest_plugins = "pytest_pytester"
|
||||||
|
|
||||||
def test_failure_demo_fails_properly(testdir):
|
def test_failure_demo_fails_properly(testdir):
|
||||||
target = testdir.tmpdir.join(failure_demo.basename)
|
target = testdir.tmpdir.join(failure_demo.basename)
|
||||||
failure_demo.copy(target)
|
failure_demo.copy(target)
|
||||||
failure_demo.copy(testdir.tmpdir.join(failure_demo.basename))
|
failure_demo.copy(testdir.tmpdir.join(failure_demo.basename))
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
|
|
||||||
def pytest_funcarg__setup(request):
|
def pytest_funcarg__setup(request):
|
||||||
return request.cached_setup(
|
return request.cached_setup(
|
||||||
setup=lambda: CostlySetup(),
|
setup=lambda: CostlySetup(),
|
||||||
teardown=lambda costlysetup: costlysetup.finalize(),
|
teardown=lambda costlysetup: costlysetup.finalize(),
|
||||||
scope="session",
|
scope="session",
|
||||||
)
|
)
|
||||||
|
@ -13,4 +13,4 @@ class CostlySetup:
|
||||||
self.timecostly = 1
|
self.timecostly = 1
|
||||||
|
|
||||||
def finalize(self):
|
def finalize(self):
|
||||||
del self.timecostly
|
del self.timecostly
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
# XXX this file should not need to be here but is here for proper sys.path mangling
|
# XXX this file should not need to be here but is here for proper sys.path mangling
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
def test_answer(mysetup):
|
def test_answer(mysetup):
|
||||||
app = mysetup.myapp()
|
app = mysetup.myapp()
|
||||||
answer = app.question()
|
answer = app.question()
|
||||||
assert answer == 42
|
assert answer == 42
|
||||||
|
|
|
@ -1 +1 @@
|
||||||
# XXX this file should not need to be here but is here for proper sys.path mangling
|
# XXX this file should not need to be here but is here for proper sys.path mangling
|
||||||
|
|
|
@ -7,11 +7,11 @@ def pytest_funcarg__mysetup(request):
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
parser.addoption("--ssh", action="store", default=None,
|
parser.addoption("--ssh", action="store", default=None,
|
||||||
help="specify ssh host to run tests with")
|
help="specify ssh host to run tests with")
|
||||||
|
|
||||||
|
|
||||||
class MySetup:
|
class MySetup:
|
||||||
def __init__(self, request):
|
def __init__(self, request):
|
||||||
self.config = request.config
|
self.config = request.config
|
||||||
|
|
||||||
def myapp(self):
|
def myapp(self):
|
||||||
return MyApp()
|
return MyApp()
|
||||||
|
@ -21,4 +21,4 @@ class MySetup:
|
||||||
if host is None:
|
if host is None:
|
||||||
py.test.skip("specify ssh host with --ssh")
|
py.test.skip("specify ssh host with --ssh")
|
||||||
return execnet.SshGateway(host)
|
return execnet.SshGateway(host)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
class MyApp:
|
class MyApp:
|
||||||
def question(self):
|
def question(self):
|
||||||
return 6 * 9
|
return 6 * 9
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
def test_answer(mysetup):
|
def test_answer(mysetup):
|
||||||
app = mysetup.myapp()
|
app = mysetup.myapp()
|
||||||
answer = app.question()
|
answer = app.question()
|
||||||
assert answer == 42
|
assert answer == 42
|
||||||
|
|
|
@ -2,4 +2,4 @@
|
||||||
class TestClass:
|
class TestClass:
|
||||||
def test_function(self, mysetup):
|
def test_function(self, mysetup):
|
||||||
conn = mysetup.getsshconnection()
|
conn = mysetup.getsshconnection()
|
||||||
# work with conn
|
# work with conn
|
||||||
|
|
|
@ -3,13 +3,13 @@ import py
|
||||||
def pytest_generate_tests(metafunc):
|
def pytest_generate_tests(metafunc):
|
||||||
for funcargs in metafunc.cls.params[metafunc.function.__name__]:
|
for funcargs in metafunc.cls.params[metafunc.function.__name__]:
|
||||||
metafunc.addcall(funcargs=funcargs)
|
metafunc.addcall(funcargs=funcargs)
|
||||||
|
|
||||||
class TestClass:
|
class TestClass:
|
||||||
params = {
|
params = {
|
||||||
'test_equals': [dict(a=1, b=2), dict(a=3, b=3), dict(a=5, b=4)],
|
'test_equals': [dict(a=1, b=2), dict(a=3, b=3), dict(a=5, b=4)],
|
||||||
'test_zerodivision': [dict(a=1, b=0), dict(a=3, b=2)],
|
'test_zerodivision': [dict(a=1, b=0), dict(a=3, b=2)],
|
||||||
}
|
}
|
||||||
|
|
||||||
def test_equals(self, a, b):
|
def test_equals(self, a, b):
|
||||||
assert a == b
|
assert a == b
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ def pytest_generate_tests(metafunc):
|
||||||
|
|
||||||
|
|
||||||
# actual test code
|
# actual test code
|
||||||
|
|
||||||
class TestClass:
|
class TestClass:
|
||||||
@params([dict(a=1, b=2), dict(a=3, b=3), dict(a=5, b=4)], )
|
@params([dict(a=1, b=2), dict(a=3, b=3), dict(a=5, b=4)], )
|
||||||
def test_equals(self, a, b):
|
def test_equals(self, a, b):
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
|
|
||||||
# following hook can be put unchanged into a local or global plugin
|
# following hook can be put unchanged into a local or global plugin
|
||||||
def pytest_generate_tests(metafunc):
|
def pytest_generate_tests(metafunc):
|
||||||
for scenario in metafunc.cls.scenarios:
|
for scenario in metafunc.cls.scenarios:
|
||||||
metafunc.addcall(id=scenario[0], funcargs=scenario[1])
|
metafunc.addcall(id=scenario[0], funcargs=scenario[1])
|
||||||
|
@ -12,4 +12,4 @@ class TestSampleWithScenarios:
|
||||||
scenarios = [scenario1, scenario2]
|
scenarios = [scenario1, scenario2]
|
||||||
|
|
||||||
def test_demo(self, attribute):
|
def test_demo(self, attribute):
|
||||||
assert isinstance(attribute, str)
|
assert isinstance(attribute, str)
|
||||||
|
|
|
@ -1,22 +1,22 @@
|
||||||
"""
|
"""
|
||||||
|
|
||||||
module containing a parametrized tests testing cross-python
|
module containing a parametrized tests testing cross-python
|
||||||
serialization via the pickle module.
|
serialization via the pickle module.
|
||||||
"""
|
"""
|
||||||
import py
|
import py
|
||||||
|
|
||||||
pythonlist = ['python2.3', 'python2.4', 'python2.5', 'python2.6']
|
pythonlist = ['python2.3', 'python2.4', 'python2.5', 'python2.6']
|
||||||
# 'jython' 'python3.1']
|
# 'jython' 'python3.1']
|
||||||
|
|
||||||
def pytest_generate_tests(metafunc):
|
def pytest_generate_tests(metafunc):
|
||||||
if 'python1' in metafunc.funcargnames:
|
if 'python1' in metafunc.funcargnames:
|
||||||
assert 'python2' in metafunc.funcargnames
|
assert 'python2' in metafunc.funcargnames
|
||||||
for obj in metafunc.function.multiarg.kwargs['obj']:
|
for obj in metafunc.function.multiarg.kwargs['obj']:
|
||||||
for py1 in pythonlist:
|
for py1 in pythonlist:
|
||||||
for py2 in pythonlist:
|
for py2 in pythonlist:
|
||||||
metafunc.addcall(id="%s-%s-%s" % (py1, py2, obj),
|
metafunc.addcall(id="%s-%s-%s" % (py1, py2, obj),
|
||||||
param=(py1, py2, obj))
|
param=(py1, py2, obj))
|
||||||
|
|
||||||
@py.test.mark.multiarg(obj=[42, {}, {1:3},])
|
@py.test.mark.multiarg(obj=[42, {}, {1:3},])
|
||||||
def test_basic_objects(python1, python2, obj):
|
def test_basic_objects(python1, python2, obj):
|
||||||
python1.dumps(obj)
|
python1.dumps(obj)
|
||||||
|
@ -49,7 +49,7 @@ class Python:
|
||||||
f.close()
|
f.close()
|
||||||
""" % (str(self.picklefile), obj)))
|
""" % (str(self.picklefile), obj)))
|
||||||
py.process.cmdexec("%s %s" %(self.pythonpath, dumpfile))
|
py.process.cmdexec("%s %s" %(self.pythonpath, dumpfile))
|
||||||
|
|
||||||
def load_and_is_true(self, expression):
|
def load_and_is_true(self, expression):
|
||||||
loadfile = self.picklefile.dirpath("load.py")
|
loadfile = self.picklefile.dirpath("load.py")
|
||||||
loadfile.write(py.code.Source("""
|
loadfile.write(py.code.Source("""
|
||||||
|
|
|
@ -1,15 +1,15 @@
|
||||||
# conftest.py
|
# conftest.py
|
||||||
import py
|
import py
|
||||||
|
|
||||||
|
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
grp = parser.getgroup("testserver options")
|
grp = parser.getgroup("testserver options")
|
||||||
grp.addoption("--url", action="store", default=None,
|
grp.addoption("--url", action="store", default=None,
|
||||||
help="url for testserver")
|
help="url for testserver")
|
||||||
|
|
||||||
def pytest_funcarg__url(request):
|
def pytest_funcarg__url(request):
|
||||||
url = request.config.getvalue("url")
|
url = request.config.getvalue("url")
|
||||||
if url is None:
|
if url is None:
|
||||||
py.test.skip("need --url")
|
py.test.skip("need --url")
|
||||||
return url
|
return url
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
from py.xml import html
|
from py.xml import html
|
||||||
|
|
||||||
paras = "First Para", "Second para"
|
paras = "First Para", "Second para"
|
||||||
|
|
||||||
doc = html.html(
|
doc = html.html(
|
||||||
html.head(
|
html.head(
|
||||||
html.meta(name="Content-Type", value="text/html; charset=latin1")),
|
html.meta(name="Content-Type", value="text/html; charset=latin1")),
|
||||||
html.body(
|
html.body(
|
||||||
[html.p(p) for p in paras]))
|
[html.p(p) for p in paras]))
|
||||||
|
|
||||||
|
|
|
@ -1,23 +1,23 @@
|
||||||
import py
|
import py
|
||||||
html = py.xml.html
|
html = py.xml.html
|
||||||
|
|
||||||
class my(html):
|
class my(html):
|
||||||
"a custom style"
|
"a custom style"
|
||||||
class body(html.body):
|
class body(html.body):
|
||||||
style = html.Style(font_size = "120%")
|
style = html.Style(font_size = "120%")
|
||||||
|
|
||||||
class h2(html.h2):
|
class h2(html.h2):
|
||||||
style = html.Style(background = "grey")
|
style = html.Style(background = "grey")
|
||||||
|
|
||||||
class p(html.p):
|
class p(html.p):
|
||||||
style = html.Style(font_weight="bold")
|
style = html.Style(font_weight="bold")
|
||||||
|
|
||||||
doc = my.html(
|
doc = my.html(
|
||||||
my.head(),
|
my.head(),
|
||||||
my.body(
|
my.body(
|
||||||
my.h2("hello world"),
|
my.h2("hello world"),
|
||||||
my.p("bold as bold can")
|
my.p("bold as bold can")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
print doc.unicode(indent=2)
|
print doc.unicode(indent=2)
|
||||||
|
|
|
@ -1,16 +1,16 @@
|
||||||
|
|
||||||
import py
|
import py
|
||||||
class ns(py.xml.Namespace):
|
class ns(py.xml.Namespace):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
doc = ns.books(
|
doc = ns.books(
|
||||||
ns.book(
|
ns.book(
|
||||||
ns.author("May Day"),
|
ns.author("May Day"),
|
||||||
ns.title("python for java programmers"),),
|
ns.title("python for java programmers"),),
|
||||||
ns.book(
|
ns.book(
|
||||||
ns.author("why", class_="somecssclass"),
|
ns.author("why", class_="somecssclass"),
|
||||||
ns.title("Java for Python programmers"),),
|
ns.title("Java for Python programmers"),),
|
||||||
publisher="N.N",
|
publisher="N.N",
|
||||||
)
|
)
|
||||||
print doc.unicode(indent=2).encode('utf8')
|
print doc.unicode(indent=2).encode('utf8')
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
==============================================================================
|
==============================================================================
|
||||||
py.execnet: *elastic* distributed programming
|
py.execnet: *elastic* distributed programming
|
||||||
==============================================================================
|
==============================================================================
|
||||||
|
|
||||||
Since pylib 1.1 "py.execnet" ceased to exist and is now available
|
Since pylib 1.1 "py.execnet" ceased to exist and is now available
|
||||||
as a separately developed `execnet standalone package`_.
|
as a separately developed `execnet standalone package`_.
|
||||||
|
|
||||||
If you have previosly used "py.execnet.*" and the 1.0 API just
|
If you have previosly used "py.execnet.*" and the 1.0 API just
|
||||||
rename all occurences of the string "``py.execnet.``" with the
|
rename all occurences of the string "``py.execnet.``" with the
|
||||||
string "``execnet.``" as execnet-1.0 is API compatible.
|
string "``execnet.``" as execnet-1.0 is API compatible.
|
||||||
|
|
||||||
.. _`execnet standalone package`: http://codespeak.net/execnet
|
.. _`execnet standalone package`: http://codespeak.net/execnet
|
||||||
|
|
102
doc/faq.txt
102
doc/faq.txt
|
@ -1,71 +1,71 @@
|
||||||
==================================
|
==================================
|
||||||
Frequently Asked Questions
|
Frequently Asked Questions
|
||||||
==================================
|
==================================
|
||||||
|
|
||||||
.. contents::
|
.. contents::
|
||||||
:local:
|
:local:
|
||||||
:depth: 2
|
:depth: 2
|
||||||
|
|
||||||
|
|
||||||
On naming, nosetests, licensing and magic
|
On naming, nosetests, licensing and magic
|
||||||
===========================================
|
===========================================
|
||||||
|
|
||||||
Why the ``py`` naming? Why not ``pytest``?
|
Why the ``py`` naming? Why not ``pytest``?
|
||||||
----------------------------------------------------
|
----------------------------------------------------
|
||||||
|
|
||||||
This mostly has historic reasons - the aim is
|
This mostly has historic reasons - the aim is
|
||||||
to get away from the somewhat questionable 'py' name
|
to get away from the somewhat questionable 'py' name
|
||||||
at some point. These days (2010) the 'py' library
|
at some point. These days (2010) the 'py' library
|
||||||
almost completely comprises APIs that are used
|
almost completely comprises APIs that are used
|
||||||
by the ``py.test`` tool. There also are some
|
by the ``py.test`` tool. There also are some
|
||||||
other uses, e.g. of the ``py.path.local()`` and
|
other uses, e.g. of the ``py.path.local()`` and
|
||||||
other path implementations. So it requires some
|
other path implementations. So it requires some
|
||||||
work to factor them out and do the shift.
|
work to factor them out and do the shift.
|
||||||
|
|
||||||
Why the ``py.test`` naming?
|
Why the ``py.test`` naming?
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
||||||
because of TAB-completion under Bash/Shells. If you hit
|
because of TAB-completion under Bash/Shells. If you hit
|
||||||
``py.<TAB>`` you'll get a list of available development
|
``py.<TAB>`` you'll get a list of available development
|
||||||
tools that all share the ``py.`` prefix. Another motivation
|
tools that all share the ``py.`` prefix. Another motivation
|
||||||
was to unify the package ("py.test") and tool filename.
|
was to unify the package ("py.test") and tool filename.
|
||||||
|
|
||||||
What's py.test's relation to ``nosetests``?
|
What's py.test's relation to ``nosetests``?
|
||||||
---------------------------------------------
|
---------------------------------------------
|
||||||
|
|
||||||
py.test and nose_ share basic philosophy when it comes
|
py.test and nose_ share basic philosophy when it comes
|
||||||
to running Python tests. In fact,
|
to running Python tests. In fact,
|
||||||
with py.test-1.1.0 it is ever easier to run many test suites
|
with py.test-1.1.0 it is ever easier to run many test suites
|
||||||
that currently work with ``nosetests``. nose_ was created
|
that currently work with ``nosetests``. nose_ was created
|
||||||
as a clone of ``py.test`` when py.test was in the ``0.8`` release
|
as a clone of ``py.test`` when py.test was in the ``0.8`` release
|
||||||
cycle so some of the newer features_ introduced with py.test-1.0
|
cycle so some of the newer features_ introduced with py.test-1.0
|
||||||
and py.test-1.1 have no counterpart in nose_.
|
and py.test-1.1 have no counterpart in nose_.
|
||||||
|
|
||||||
.. _nose: http://somethingaboutorange.com/mrl/projects/nose/0.11.1/
|
.. _nose: http://somethingaboutorange.com/mrl/projects/nose/0.11.1/
|
||||||
.. _features: test/features.html
|
.. _features: test/features.html
|
||||||
.. _apipkg: http://pypi.python.org/pypi/apipkg
|
.. _apipkg: http://pypi.python.org/pypi/apipkg
|
||||||
|
|
||||||
|
|
||||||
What's this "magic" with py.test?
|
What's this "magic" with py.test?
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
issues where people have used the term "magic" in the past:
|
issues where people have used the term "magic" in the past:
|
||||||
|
|
||||||
* `py/__init__.py`_ uses the apipkg_ mechanism for lazy-importing
|
* `py/__init__.py`_ uses the apipkg_ mechanism for lazy-importing
|
||||||
and full control on what API you get when importing "import py".
|
and full control on what API you get when importing "import py".
|
||||||
|
|
||||||
* when an ``assert`` statement fails, py.test re-interprets the expression
|
* when an ``assert`` statement fails, py.test re-interprets the expression
|
||||||
to show intermediate values if a test fails. If your expression
|
to show intermediate values if a test fails. If your expression
|
||||||
has side effects the intermediate values may not be the same, obfuscating
|
has side effects the intermediate values may not be the same, obfuscating
|
||||||
the initial error (this is also explained at the command line if it happens).
|
the initial error (this is also explained at the command line if it happens).
|
||||||
``py.test --no-assert`` turns off assert re-intepretation.
|
``py.test --no-assert`` turns off assert re-intepretation.
|
||||||
Sidenote: it is good practise to avoid asserts with side effects.
|
Sidenote: it is good practise to avoid asserts with side effects.
|
||||||
|
|
||||||
|
|
||||||
.. _`py namespaces`: index.html
|
.. _`py namespaces`: index.html
|
||||||
.. _`py/__init__.py`: http://bitbucket.org/hpk42/py-trunk/src/trunk/py/__init__.py
|
.. _`py/__init__.py`: http://bitbucket.org/hpk42/py-trunk/src/trunk/py/__init__.py
|
||||||
|
|
||||||
Where does my ``py.test`` come/import from?
|
Where does my ``py.test`` come/import from?
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
|
|
||||||
You can issue::
|
You can issue::
|
||||||
|
@ -80,17 +80,17 @@ function arguments, parametrized tests and setup
|
||||||
|
|
||||||
.. _funcargs: test/funcargs.html
|
.. _funcargs: test/funcargs.html
|
||||||
|
|
||||||
Is using funcarg- versus xUnit-based setup a style question?
|
Is using funcarg- versus xUnit-based setup a style question?
|
||||||
---------------------------------------------------------------
|
---------------------------------------------------------------
|
||||||
|
|
||||||
It depends. For simple applications or for people experienced
|
It depends. For simple applications or for people experienced
|
||||||
with nose_ or unittest-style test setup using `xUnit style setup`_
|
with nose_ or unittest-style test setup using `xUnit style setup`_
|
||||||
make some sense. For larger test suites, parametrized testing
|
make some sense. For larger test suites, parametrized testing
|
||||||
or setup of complex test resources using funcargs_ is recommended.
|
or setup of complex test resources using funcargs_ is recommended.
|
||||||
Moreover, funcargs are ideal for writing advanced test support
|
Moreover, funcargs are ideal for writing advanced test support
|
||||||
code (like e.g. the monkeypatch_, the tmpdir_ or capture_ funcargs)
|
code (like e.g. the monkeypatch_, the tmpdir_ or capture_ funcargs)
|
||||||
because the support code can register setup/teardown functions
|
because the support code can register setup/teardown functions
|
||||||
in a managed class/module/function scope.
|
in a managed class/module/function scope.
|
||||||
|
|
||||||
.. _monkeypatch: test/plugin/monkeypatch.html
|
.. _monkeypatch: test/plugin/monkeypatch.html
|
||||||
.. _tmpdir: test/plugin/tmpdir.html
|
.. _tmpdir: test/plugin/tmpdir.html
|
||||||
|
@ -100,65 +100,65 @@ in a managed class/module/function scope.
|
||||||
|
|
||||||
.. _`why pytest_pyfuncarg__ methods?`:
|
.. _`why pytest_pyfuncarg__ methods?`:
|
||||||
|
|
||||||
Why the ``pytest_funcarg__*`` name for funcarg factories?
|
Why the ``pytest_funcarg__*`` name for funcarg factories?
|
||||||
---------------------------------------------------------------
|
---------------------------------------------------------------
|
||||||
|
|
||||||
When experimenting with funcargs an explicit registration mechanism
|
When experimenting with funcargs an explicit registration mechanism
|
||||||
was considered. But lacking a good use case for this indirection and
|
was considered. But lacking a good use case for this indirection and
|
||||||
flexibility we decided to go for `Convention over Configuration`_ and
|
flexibility we decided to go for `Convention over Configuration`_ and
|
||||||
allow to directly specify the factory. Besides removing the need
|
allow to directly specify the factory. Besides removing the need
|
||||||
for an indirection it allows to "grep" for ``pytest_funcarg__MYARG``
|
for an indirection it allows to "grep" for ``pytest_funcarg__MYARG``
|
||||||
and will safely find all factory functions for the ``MYARG`` function
|
and will safely find all factory functions for the ``MYARG`` function
|
||||||
argument. It helps to alleviate the de-coupling of function
|
argument. It helps to alleviate the de-coupling of function
|
||||||
argument usage and creation.
|
argument usage and creation.
|
||||||
|
|
||||||
.. _`Convention over Configuration`: http://en.wikipedia.org/wiki/Convention_over_Configuration
|
.. _`Convention over Configuration`: http://en.wikipedia.org/wiki/Convention_over_Configuration
|
||||||
|
|
||||||
Can I yield multiple values from a factory function?
|
Can I yield multiple values from a factory function?
|
||||||
-----------------------------------------------------
|
-----------------------------------------------------
|
||||||
|
|
||||||
There are two conceptual reasons why yielding from a factory function
|
There are two conceptual reasons why yielding from a factory function
|
||||||
is not possible:
|
is not possible:
|
||||||
|
|
||||||
* Calling factories for obtaining test function arguments
|
* Calling factories for obtaining test function arguments
|
||||||
is part of setting up and running a test. At that
|
is part of setting up and running a test. At that
|
||||||
point it is not possible to add new test calls to
|
point it is not possible to add new test calls to
|
||||||
the test collection anymore.
|
the test collection anymore.
|
||||||
|
|
||||||
* If multiple factories yielded values there would
|
* If multiple factories yielded values there would
|
||||||
be no natural place to determine the combination
|
be no natural place to determine the combination
|
||||||
policy - in real-world examples some combinations
|
policy - in real-world examples some combinations
|
||||||
often should not run.
|
often should not run.
|
||||||
|
|
||||||
Use the `pytest_generate_tests`_ hook to solve both issues
|
Use the `pytest_generate_tests`_ hook to solve both issues
|
||||||
and implement the `parametrization scheme of your choice`_.
|
and implement the `parametrization scheme of your choice`_.
|
||||||
|
|
||||||
.. _`pytest_generate_tests`: test/funcargs.html#parametrizing-tests
|
.. _`pytest_generate_tests`: test/funcargs.html#parametrizing-tests
|
||||||
.. _`parametrization scheme of your choice`: http://tetamap.wordpress.com/2009/05/13/parametrizing-python-tests-generalized/
|
.. _`parametrization scheme of your choice`: http://tetamap.wordpress.com/2009/05/13/parametrizing-python-tests-generalized/
|
||||||
|
|
||||||
|
|
||||||
py.test interaction with other packages
|
py.test interaction with other packages
|
||||||
===============================================
|
===============================================
|
||||||
|
|
||||||
Issues with py.test, multiprocess and setuptools?
|
Issues with py.test, multiprocess and setuptools?
|
||||||
------------------------------------------------------------
|
------------------------------------------------------------
|
||||||
|
|
||||||
On windows the multiprocess package will instantiate sub processes
|
On windows the multiprocess package will instantiate sub processes
|
||||||
by pickling and thus implicitely re-import a lot of local modules.
|
by pickling and thus implicitely re-import a lot of local modules.
|
||||||
Unfortuantely, setuptools-0.6.11 does not ``if __name__=='__main__'``
|
Unfortuantely, setuptools-0.6.11 does not ``if __name__=='__main__'``
|
||||||
protect its generated command line script. This leads to infinite
|
protect its generated command line script. This leads to infinite
|
||||||
recursion when running a test that instantiates Processes.
|
recursion when running a test that instantiates Processes.
|
||||||
There are these workarounds:
|
There are these workarounds:
|
||||||
|
|
||||||
* `install Distribute`_ as a drop-in replacement for setuptools
|
* `install Distribute`_ as a drop-in replacement for setuptools
|
||||||
and install py.test
|
and install py.test
|
||||||
|
|
||||||
* `directly use a checkout`_ which avoids all setuptools/Distribute
|
* `directly use a checkout`_ which avoids all setuptools/Distribute
|
||||||
installation
|
installation
|
||||||
|
|
||||||
If those options are not available to you, you may also manually
|
If those options are not available to you, you may also manually
|
||||||
fix the script that is created by setuptools by inserting an
|
fix the script that is created by setuptools by inserting an
|
||||||
``if __name__ == '__main__'``. Or you can create a "pytest.py"
|
``if __name__ == '__main__'``. Or you can create a "pytest.py"
|
||||||
script with this content and invoke that with the python version::
|
script with this content and invoke that with the python version::
|
||||||
|
|
||||||
import py
|
import py
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
py lib: testing and filesystem abstraction
|
py lib: testing and filesystem abstraction
|
||||||
====================================================
|
====================================================
|
||||||
|
|
||||||
The ``py`` lib has several namespaces which help with automated testing,
|
The ``py`` lib has several namespaces which help with automated testing,
|
||||||
and with accessing filesystems. Here is some documentation on the
|
and with accessing filesystems. Here is some documentation on the
|
||||||
core namespaces:
|
core namespaces:
|
||||||
|
|
||||||
`py.test`_ write and deploy unit- and functional tests to multiple machines.
|
`py.test`_ write and deploy unit- and functional tests to multiple machines.
|
||||||
|
|
||||||
`py.code`_: generate code and use advanced introspection/traceback support.
|
`py.code`_: generate code and use advanced introspection/traceback support.
|
||||||
|
|
||||||
`py.path`_: use path objects to transparently access local and svn filesystems.
|
`py.path`_: use path objects to transparently access local and svn filesystems.
|
||||||
|
|
||||||
Other (minor) support functionality
|
Other (minor) support functionality
|
||||||
===================================
|
===================================
|
||||||
|
|
||||||
`py lib scripts`_ to make python development easier.
|
`py lib scripts`_ to make python development easier.
|
||||||
|
|
||||||
`py.xml`_ for generating in-memory xml/html object trees
|
`py.xml`_ for generating in-memory xml/html object trees
|
||||||
|
|
||||||
`py.io`_: Helper Classes for Capturing of Input/Output
|
`py.io`_: Helper Classes for Capturing of Input/Output
|
||||||
|
|
||||||
`py.log`_: an alpha document about the ad-hoc logging facilities
|
`py.log`_: an alpha document about the ad-hoc logging facilities
|
||||||
|
|
||||||
`miscellaneous features`_ describes some small but nice py lib features.
|
`miscellaneous features`_ describes some small but nice py lib features.
|
||||||
|
|
||||||
|
@ -29,13 +29,13 @@ Other (minor) support functionality
|
||||||
|
|
||||||
For the latest Release, see `PyPI project page`_
|
For the latest Release, see `PyPI project page`_
|
||||||
|
|
||||||
.. _`py-dev at codespeak net`: http://codespeak.net/mailman/listinfo/py-dev
|
.. _`py-dev at codespeak net`: http://codespeak.net/mailman/listinfo/py-dev
|
||||||
.. _`py.log`: log.html
|
.. _`py.log`: log.html
|
||||||
.. _`py.io`: io.html
|
.. _`py.io`: io.html
|
||||||
.. _`py.path`: path.html
|
.. _`py.path`: path.html
|
||||||
.. _`py.code`: code.html
|
.. _`py.code`: code.html
|
||||||
.. _`py.test`: test/index.html
|
.. _`py.test`: test/index.html
|
||||||
.. _`py lib scripts`: bin.html
|
.. _`py lib scripts`: bin.html
|
||||||
.. _`py.xml`: xml.html
|
.. _`py.xml`: xml.html
|
||||||
.. _`miscellaneous features`: misc.html
|
.. _`miscellaneous features`: misc.html
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,9 @@ py.test/pylib installation info in a nutshell
|
||||||
|
|
||||||
**Pythons**: 2.4, 2.5, 2.6, 2.7, 3.0, 3.1.x, Jython-2.5.1, PyPy-1.2
|
**Pythons**: 2.4, 2.5, 2.6, 2.7, 3.0, 3.1.x, Jython-2.5.1, PyPy-1.2
|
||||||
|
|
||||||
**Operating systems**: Linux, Windows, OSX, Unix
|
**Operating systems**: Linux, Windows, OSX, Unix
|
||||||
|
|
||||||
**Requirements**: setuptools_ or Distribute_
|
**Requirements**: setuptools_ or Distribute_
|
||||||
|
|
||||||
**Installers**: easy_install_ and pip_ or `standalone`_ (new for 1.2)
|
**Installers**: easy_install_ and pip_ or `standalone`_ (new for 1.2)
|
||||||
|
|
||||||
|
@ -19,9 +19,9 @@ py.test/pylib installation info in a nutshell
|
||||||
* debian: ``python-codespeak-lib``
|
* debian: ``python-codespeak-lib``
|
||||||
* gentoo: ``pylib``
|
* gentoo: ``pylib``
|
||||||
|
|
||||||
**Installed scripts**: see `bin`_ for which and how scripts are installed.
|
**Installed scripts**: see `bin`_ for which and how scripts are installed.
|
||||||
|
|
||||||
**hg repository**: https://bitbucket.org/hpk42/py-trunk
|
**hg repository**: https://bitbucket.org/hpk42/py-trunk
|
||||||
|
|
||||||
.. _`bin`: bin.html
|
.. _`bin`: bin.html
|
||||||
|
|
||||||
|
@ -29,12 +29,12 @@ py.test/pylib installation info in a nutshell
|
||||||
Best practise: install tool and dependencies virtually
|
Best practise: install tool and dependencies virtually
|
||||||
===========================================================
|
===========================================================
|
||||||
|
|
||||||
It is recommended to work with virtual environments
|
It is recommended to work with virtual environments
|
||||||
(e.g. virtualenv_ or buildout_ based) and use easy_install_
|
(e.g. virtualenv_ or buildout_ based) and use easy_install_
|
||||||
(or pip_) for installing py.test/pylib and any dependencies
|
(or pip_) for installing py.test/pylib and any dependencies
|
||||||
you need to run your tests. Local virtual Python environments
|
you need to run your tests. Local virtual Python environments
|
||||||
(as opposed to system-wide "global" environments) make for a more
|
(as opposed to system-wide "global" environments) make for a more
|
||||||
reproducible and reliable test environment.
|
reproducible and reliable test environment.
|
||||||
|
|
||||||
|
|
||||||
.. _`virtualenv`: http://pypi.python.org/pypi/virtualenv
|
.. _`virtualenv`: http://pypi.python.org/pypi/virtualenv
|
||||||
|
@ -46,22 +46,22 @@ using easy_install (from setuptools or Distribute)
|
||||||
===================================================
|
===================================================
|
||||||
|
|
||||||
Both `Distribute`_ and setuptools_ provide the ``easy_install``
|
Both `Distribute`_ and setuptools_ provide the ``easy_install``
|
||||||
installation tool. While setuptools should work ok with
|
installation tool. While setuptools should work ok with
|
||||||
Python2 interpreters, `Distribute`_ also works with Python3
|
Python2 interpreters, `Distribute`_ also works with Python3
|
||||||
and it avoids some issues on Windows. In both cases you
|
and it avoids some issues on Windows. In both cases you
|
||||||
can open a command line window and then type::
|
can open a command line window and then type::
|
||||||
|
|
||||||
easy_install -U py
|
easy_install -U py
|
||||||
|
|
||||||
to install the latest release of the py lib and py.test. The ``-U`` switch
|
to install the latest release of the py lib and py.test. The ``-U`` switch
|
||||||
will trigger an upgrade if you already have an older version installed.
|
will trigger an upgrade if you already have an older version installed.
|
||||||
|
|
||||||
If you now type::
|
If you now type::
|
||||||
|
|
||||||
py.test --version
|
py.test --version
|
||||||
|
|
||||||
you should see the version number and the import location of the tool.
|
you should see the version number and the import location of the tool.
|
||||||
Maybe you want to head on with the `quickstart`_ now?
|
Maybe you want to head on with the `quickstart`_ now?
|
||||||
|
|
||||||
.. _quickstart: test/quickstart.html
|
.. _quickstart: test/quickstart.html
|
||||||
|
|
||||||
|
@ -70,19 +70,19 @@ Maybe you want to head on with the `quickstart`_ now?
|
||||||
Generating a py.test standalone Script
|
Generating a py.test standalone Script
|
||||||
============================================
|
============================================
|
||||||
|
|
||||||
If you are a maintainer or application developer and want users
|
If you are a maintainer or application developer and want users
|
||||||
to run tests you can use a facility to generate a standalone
|
to run tests you can use a facility to generate a standalone
|
||||||
"py.test" script that you can tell users to run::
|
"py.test" script that you can tell users to run::
|
||||||
|
|
||||||
py.test --genscript=mytest
|
py.test --genscript=mytest
|
||||||
|
|
||||||
will generate a ``mytest`` script that is, in fact, a ``py.test`` under
|
will generate a ``mytest`` script that is, in fact, a ``py.test`` under
|
||||||
disguise. You can tell people to download and then e.g. run it like this::
|
disguise. You can tell people to download and then e.g. run it like this::
|
||||||
|
|
||||||
python mytest --pastebin=all
|
python mytest --pastebin=all
|
||||||
|
|
||||||
and ask them to send you the resulting URL. The resulting script has
|
and ask them to send you the resulting URL. The resulting script has
|
||||||
all core features and runs unchanged under Python2 and Python3 interpreters.
|
all core features and runs unchanged under Python2 and Python3 interpreters.
|
||||||
|
|
||||||
Troubleshooting / known issues
|
Troubleshooting / known issues
|
||||||
===============================
|
===============================
|
||||||
|
@ -90,30 +90,30 @@ Troubleshooting / known issues
|
||||||
.. _`Jython does not create command line launchers`: http://bugs.jython.org/issue1491
|
.. _`Jython does not create command line launchers`: http://bugs.jython.org/issue1491
|
||||||
|
|
||||||
**Jython2.5.1 on XP**: `Jython does not create command line launchers`_
|
**Jython2.5.1 on XP**: `Jython does not create command line launchers`_
|
||||||
so ``py.test`` will not work correctly. You may install py.test on
|
so ``py.test`` will not work correctly. You may install py.test on
|
||||||
CPython and type ``py.test --genscript=mytest`` and then use
|
CPython and type ``py.test --genscript=mytest`` and then use
|
||||||
``jython mytest`` to run py.test for your tests to run in Jython.
|
``jython mytest`` to run py.test for your tests to run in Jython.
|
||||||
|
|
||||||
**On Linux**: If ``easy_install`` fails because it needs to run
|
**On Linux**: If ``easy_install`` fails because it needs to run
|
||||||
as the superuser you are trying to install things globally
|
as the superuser you are trying to install things globally
|
||||||
and need to put ``sudo`` in front of the command.
|
and need to put ``sudo`` in front of the command.
|
||||||
|
|
||||||
**On Windows**: If "easy_install" or "py.test" are not found
|
**On Windows**: If "easy_install" or "py.test" are not found
|
||||||
please see here: `How do i run a Python program under Windows?`_
|
please see here: `How do i run a Python program under Windows?`_
|
||||||
|
|
||||||
.. _`How do i run a Python program under Windows?`: http://www.python.org/doc/faq/windows/#how-do-i-run-a-python-program-under-windows
|
.. _`How do i run a Python program under Windows?`: http://www.python.org/doc/faq/windows/#how-do-i-run-a-python-program-under-windows
|
||||||
|
|
||||||
.. _mercurial: http://mercurial.selenic.com/wiki/
|
.. _mercurial: http://mercurial.selenic.com/wiki/
|
||||||
.. _`Distribute`:
|
.. _`Distribute`:
|
||||||
.. _`Distribute for installation`: http://pypi.python.org/pypi/distribute#installation-instructions
|
.. _`Distribute for installation`: http://pypi.python.org/pypi/distribute#installation-instructions
|
||||||
.. _`distribute installation`: http://pypi.python.org/pypi/distribute
|
.. _`distribute installation`: http://pypi.python.org/pypi/distribute
|
||||||
.. _checkout:
|
.. _checkout:
|
||||||
.. _tarball:
|
.. _tarball:
|
||||||
|
|
||||||
Working from version control or a tarball
|
Working from version control or a tarball
|
||||||
=================================================
|
=================================================
|
||||||
|
|
||||||
To follow development or start experiments, checkout the
|
To follow development or start experiments, checkout the
|
||||||
complete code and documentation source with mercurial_::
|
complete code and documentation source with mercurial_::
|
||||||
|
|
||||||
hg clone https://bitbucket.org/hpk42/py-trunk/
|
hg clone https://bitbucket.org/hpk42/py-trunk/
|
||||||
|
@ -126,45 +126,45 @@ download and unpack a TAR file::
|
||||||
http://pypi.python.org/pypi/py/
|
http://pypi.python.org/pypi/py/
|
||||||
|
|
||||||
|
|
||||||
activating a checkout with setuptools
|
activating a checkout with setuptools
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
|
|
||||||
With a working `Distribute`_ or setuptools_ installation you can type::
|
With a working `Distribute`_ or setuptools_ installation you can type::
|
||||||
|
|
||||||
python setup.py develop
|
python setup.py develop
|
||||||
|
|
||||||
in order to work inline with the tools and the lib of your checkout.
|
in order to work inline with the tools and the lib of your checkout.
|
||||||
|
|
||||||
.. _`no-setuptools`:
|
.. _`no-setuptools`:
|
||||||
|
|
||||||
.. _`directly use a checkout`:
|
.. _`directly use a checkout`:
|
||||||
|
|
||||||
directly use a checkout or tarball / avoid setuptools
|
directly use a checkout or tarball / avoid setuptools
|
||||||
-------------------------------------------------------------
|
-------------------------------------------------------------
|
||||||
|
|
||||||
Get a checkout_ or tarball_ and add paths to your environment variables:
|
Get a checkout_ or tarball_ and add paths to your environment variables:
|
||||||
|
|
||||||
* ``PYTHONPATH`` needs to contain the root directory (where ``py`` resides)
|
* ``PYTHONPATH`` needs to contain the root directory (where ``py`` resides)
|
||||||
* ``PATH`` needs to contain ``ROOT/bin`` or ``ROOT\bin\win32`` respectively.
|
* ``PATH`` needs to contain ``ROOT/bin`` or ``ROOT\bin\win32`` respectively.
|
||||||
|
|
||||||
There also are helper scripts that set the variables accordingly. On windows
|
There also are helper scripts that set the variables accordingly. On windows
|
||||||
execute::
|
execute::
|
||||||
|
|
||||||
# inside autoexec.bat or shell startup
|
# inside autoexec.bat or shell startup
|
||||||
c:\\path\to\checkout\bin\env.cmd
|
c:\\path\to\checkout\bin\env.cmd
|
||||||
|
|
||||||
on linux/OSX add this to your shell initialization::
|
on linux/OSX add this to your shell initialization::
|
||||||
|
|
||||||
# inside e.g. .bashrc
|
# inside e.g. .bashrc
|
||||||
eval `python ~/path/to/checkout/bin/env.py`
|
eval `python ~/path/to/checkout/bin/env.py`
|
||||||
|
|
||||||
both of which which will get you good settings. If you install
|
both of which which will get you good settings. If you install
|
||||||
the pylib this way you can easily ``hg pull && hg up`` or download
|
the pylib this way you can easily ``hg pull && hg up`` or download
|
||||||
a new tarball_ to follow the development tree.
|
a new tarball_ to follow the development tree.
|
||||||
|
|
||||||
|
|
||||||
Note that the scripts manually added like this will look for
|
Note that the scripts manually added like this will look for
|
||||||
py libs in the chain of parent directories of the current working dir.
|
py libs in the chain of parent directories of the current working dir.
|
||||||
For example, if you have a layout like this::
|
For example, if you have a layout like this::
|
||||||
|
|
||||||
mypkg/
|
mypkg/
|
||||||
|
@ -179,7 +179,7 @@ the pylib comes from you can always do::
|
||||||
|
|
||||||
py.test --version
|
py.test --version
|
||||||
|
|
||||||
to see where py.test is imported from.
|
to see where py.test is imported from.
|
||||||
|
|
||||||
.. _`command line scripts`: bin.html
|
.. _`command line scripts`: bin.html
|
||||||
.. _contact: contact.html
|
.. _contact: contact.html
|
||||||
|
|
|
@ -4,7 +4,7 @@ py.io
|
||||||
|
|
||||||
|
|
||||||
The 'py' lib provides helper classes for capturing IO during
|
The 'py' lib provides helper classes for capturing IO during
|
||||||
execution of a program.
|
execution of a program.
|
||||||
|
|
||||||
IO Capturing examples
|
IO Capturing examples
|
||||||
===============================================
|
===============================================
|
||||||
|
@ -21,7 +21,7 @@ Basic Example::
|
||||||
>>> out.strip() == "hello"
|
>>> out.strip() == "hello"
|
||||||
True
|
True
|
||||||
|
|
||||||
For calling functions you may use a shortcut::
|
For calling functions you may use a shortcut::
|
||||||
|
|
||||||
>>> import py
|
>>> import py
|
||||||
>>> def f(): print "hello"
|
>>> def f(): print "hello"
|
||||||
|
|
|
@ -13,10 +13,10 @@ Foreword
|
||||||
|
|
||||||
This document is an attempt to briefly state the actual specification of the
|
This document is an attempt to briefly state the actual specification of the
|
||||||
:code:`py.log` module. It was written by Francois Pinard and also contains
|
:code:`py.log` module. It was written by Francois Pinard and also contains
|
||||||
some ideas for enhancing the py.log facilities.
|
some ideas for enhancing the py.log facilities.
|
||||||
|
|
||||||
NOTE that :code:`py.log` is subject to refactorings, it may change with
|
NOTE that :code:`py.log` is subject to refactorings, it may change with
|
||||||
the next release.
|
the next release.
|
||||||
|
|
||||||
This document is meant to trigger or facilitate discussions. It shamelessly
|
This document is meant to trigger or facilitate discussions. It shamelessly
|
||||||
steals from the `Agile Testing`__ comments, and from other sources as well,
|
steals from the `Agile Testing`__ comments, and from other sources as well,
|
||||||
|
@ -204,5 +204,5 @@ log entry.
|
||||||
.. -------------
|
.. -------------
|
||||||
.. XXX: fill in details
|
.. XXX: fill in details
|
||||||
.. + Should speak about pickle-ability of :code:`py.log`.
|
.. + Should speak about pickle-ability of :code:`py.log`.
|
||||||
..
|
..
|
||||||
.. + What is :code:`log.get` (in :file:`logger.py`)?
|
.. + What is :code:`log.get` (in :file:`logger.py`)?
|
||||||
|
|
64
doc/misc.txt
64
doc/misc.txt
|
@ -1,21 +1,21 @@
|
||||||
====================================
|
====================================
|
||||||
Miscellaneous features of the py lib
|
Miscellaneous features of the py lib
|
||||||
====================================
|
====================================
|
||||||
|
|
||||||
Mapping the standard python library into py
|
Mapping the standard python library into py
|
||||||
===========================================
|
===========================================
|
||||||
|
|
||||||
The ``py.std`` object allows lazy access to
|
The ``py.std`` object allows lazy access to
|
||||||
standard library modules. For example, to get to the print-exception
|
standard library modules. For example, to get to the print-exception
|
||||||
functionality of the standard library you can write::
|
functionality of the standard library you can write::
|
||||||
|
|
||||||
py.std.traceback.print_exc()
|
py.std.traceback.print_exc()
|
||||||
|
|
||||||
without having to do anything else than the usual ``import py``
|
without having to do anything else than the usual ``import py``
|
||||||
at the beginning. You can access any other top-level standard
|
at the beginning. You can access any other top-level standard
|
||||||
library module this way. This means that you will only trigger
|
library module this way. This means that you will only trigger
|
||||||
imports of modules that are actually needed. Note that no attempt
|
imports of modules that are actually needed. Note that no attempt
|
||||||
is made to import submodules.
|
is made to import submodules.
|
||||||
|
|
||||||
Support for interaction with system utilities/binaries
|
Support for interaction with system utilities/binaries
|
||||||
======================================================
|
======================================================
|
||||||
|
@ -23,68 +23,68 @@ Support for interaction with system utilities/binaries
|
||||||
Currently, the py lib offers two ways to interact with
|
Currently, the py lib offers two ways to interact with
|
||||||
system executables. ``py.process.cmdexec()`` invokes
|
system executables. ``py.process.cmdexec()`` invokes
|
||||||
the shell in order to execute a string. The other
|
the shell in order to execute a string. The other
|
||||||
one, ``py.path.local``'s 'sysexec()' method lets you
|
one, ``py.path.local``'s 'sysexec()' method lets you
|
||||||
directly execute a binary.
|
directly execute a binary.
|
||||||
|
|
||||||
Both approaches will raise an exception in case of a return-
|
Both approaches will raise an exception in case of a return-
|
||||||
code other than 0 and otherwise return the stdout-output
|
code other than 0 and otherwise return the stdout-output
|
||||||
of the child process.
|
of the child process.
|
||||||
|
|
||||||
The shell based approach
|
The shell based approach
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
You can execute a command via your system shell
|
You can execute a command via your system shell
|
||||||
by doing something like::
|
by doing something like::
|
||||||
|
|
||||||
out = py.process.cmdexec('ls -v')
|
out = py.process.cmdexec('ls -v')
|
||||||
|
|
||||||
However, the ``cmdexec`` approach has a few shortcomings:
|
However, the ``cmdexec`` approach has a few shortcomings:
|
||||||
|
|
||||||
- it relies on the underlying system shell
|
- it relies on the underlying system shell
|
||||||
- it neccessitates shell-escaping for expressing arguments
|
- it neccessitates shell-escaping for expressing arguments
|
||||||
- it does not easily allow to "fix" the binary you want to run.
|
- it does not easily allow to "fix" the binary you want to run.
|
||||||
- it only allows to execute executables from the local
|
- it only allows to execute executables from the local
|
||||||
filesystem
|
filesystem
|
||||||
|
|
||||||
.. _sysexec:
|
.. _sysexec:
|
||||||
|
|
||||||
local paths have ``sysexec``
|
local paths have ``sysexec``
|
||||||
----------------------------
|
----------------------------
|
||||||
|
|
||||||
In order to synchronously execute an executable file you
|
In order to synchronously execute an executable file you
|
||||||
can use ``sysexec``::
|
can use ``sysexec``::
|
||||||
|
|
||||||
binsvn.sysexec('ls', 'http://codespeak.net/svn')
|
binsvn.sysexec('ls', 'http://codespeak.net/svn')
|
||||||
|
|
||||||
where ``binsvn`` is a path that points to the ``svn`` commandline
|
where ``binsvn`` is a path that points to the ``svn`` commandline
|
||||||
binary. Note that this function does not offer any shell-escaping
|
binary. Note that this function does not offer any shell-escaping
|
||||||
so you have to pass in already separated arguments.
|
so you have to pass in already separated arguments.
|
||||||
|
|
||||||
finding an executable local path
|
finding an executable local path
|
||||||
--------------------------------
|
--------------------------------
|
||||||
|
|
||||||
Finding an executable is quite different on multiple platforms.
|
Finding an executable is quite different on multiple platforms.
|
||||||
Currently, the ``PATH`` environment variable based search on
|
Currently, the ``PATH`` environment variable based search on
|
||||||
unix platforms is supported::
|
unix platforms is supported::
|
||||||
|
|
||||||
py.path.local.sysfind('svn')
|
py.path.local.sysfind('svn')
|
||||||
|
|
||||||
which returns the first path whose ``basename`` matches ``svn``.
|
which returns the first path whose ``basename`` matches ``svn``.
|
||||||
In principle, `sysfind` deploys platform specific algorithms
|
In principle, `sysfind` deploys platform specific algorithms
|
||||||
to perform the search. On Windows, for example, it may look
|
to perform the search. On Windows, for example, it may look
|
||||||
at the registry (XXX).
|
at the registry (XXX).
|
||||||
|
|
||||||
To make the story complete, we allow to pass in a second ``checker``
|
To make the story complete, we allow to pass in a second ``checker``
|
||||||
argument that is called for each found executable. For example, if
|
argument that is called for each found executable. For example, if
|
||||||
you have multiple binaries available you may want to select the
|
you have multiple binaries available you may want to select the
|
||||||
right version::
|
right version::
|
||||||
|
|
||||||
def mysvn(p):
|
def mysvn(p):
|
||||||
""" check that the given svn binary has version 1.1. """
|
""" check that the given svn binary has version 1.1. """
|
||||||
line = p.execute('--version'').readlines()[0]
|
line = p.execute('--version'').readlines()[0]
|
||||||
if line.find('version 1.1'):
|
if line.find('version 1.1'):
|
||||||
return p
|
return p
|
||||||
binsvn = py.path.local.sysfind('svn', checker=mysvn)
|
binsvn = py.path.local.sysfind('svn', checker=mysvn)
|
||||||
|
|
||||||
|
|
||||||
Cross-Python Version compatibility helpers
|
Cross-Python Version compatibility helpers
|
||||||
|
|
60
doc/path.txt
60
doc/path.txt
|
@ -11,7 +11,7 @@ provides a number of implementations of this API.
|
||||||
Path implementations provided by ``py.path``
|
Path implementations provided by ``py.path``
|
||||||
===============================================
|
===============================================
|
||||||
|
|
||||||
.. _`local`:
|
.. _`local`:
|
||||||
|
|
||||||
``py.path.local``
|
``py.path.local``
|
||||||
--------------------
|
--------------------
|
||||||
|
@ -82,16 +82,16 @@ Common vs. specific API
|
||||||
=======================
|
=======================
|
||||||
|
|
||||||
All Path objects support a common set of operations, suitable
|
All Path objects support a common set of operations, suitable
|
||||||
for many use cases and allowing to transparently switch the
|
for many use cases and allowing to transparently switch the
|
||||||
path object within an application (e.g. from "local" to "svnwc").
|
path object within an application (e.g. from "local" to "svnwc").
|
||||||
The common set includes functions such as `path.read()` to read all data
|
The common set includes functions such as `path.read()` to read all data
|
||||||
from a file, `path.write()` to write data, `path.listdir()` to get a list
|
from a file, `path.write()` to write data, `path.listdir()` to get a list
|
||||||
of directory entries, `path.check()` to check if a node exists
|
of directory entries, `path.check()` to check if a node exists
|
||||||
and is of a particular type, `path.join()` to get
|
and is of a particular type, `path.join()` to get
|
||||||
to a (grand)child, `path.visit()` to recursively walk through a node's
|
to a (grand)child, `path.visit()` to recursively walk through a node's
|
||||||
children, etc. Only things that are not common on 'normal' filesystems (yet),
|
children, etc. Only things that are not common on 'normal' filesystems (yet),
|
||||||
such as handling metadata (e.g. the Subversion "properties") require
|
such as handling metadata (e.g. the Subversion "properties") require
|
||||||
using specific APIs.
|
using specific APIs.
|
||||||
|
|
||||||
Examples
|
Examples
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
@ -100,7 +100,7 @@ A quick 'cookbook' of small examples that will be useful 'in real life',
|
||||||
which also presents parts of the 'common' API, and shows some non-common
|
which also presents parts of the 'common' API, and shows some non-common
|
||||||
methods:
|
methods:
|
||||||
|
|
||||||
Searching `.txt` files
|
Searching `.txt` files
|
||||||
..........................
|
..........................
|
||||||
|
|
||||||
Search for a particular string inside all files with a .txt extension in a
|
Search for a particular string inside all files with a .txt extension in a
|
||||||
|
@ -122,7 +122,7 @@ specific directory.
|
||||||
>>> results
|
>>> results
|
||||||
['textfile1.txt', 'textfile2.txt', 'textfile2.txt']
|
['textfile1.txt', 'textfile2.txt', 'textfile2.txt']
|
||||||
|
|
||||||
Working with Paths
|
Working with Paths
|
||||||
.......................
|
.......................
|
||||||
|
|
||||||
This example shows the ``py.path`` features to deal with
|
This example shows the ``py.path`` features to deal with
|
||||||
|
@ -141,12 +141,12 @@ don't have to exist, either):
|
||||||
'baz/qux'
|
'baz/qux'
|
||||||
>>> p2.bestrelpath(p1).replace(sep, '/')
|
>>> p2.bestrelpath(p1).replace(sep, '/')
|
||||||
'../..'
|
'../..'
|
||||||
>>> p2.join(p2.bestrelpath(p1)) == p1
|
>>> p2.join(p2.bestrelpath(p1)) == p1
|
||||||
True
|
True
|
||||||
>>> p3 = p1 / 'baz/qux' # the / operator allows joining, too
|
>>> p3 = p1 / 'baz/qux' # the / operator allows joining, too
|
||||||
>>> p2 == p3
|
>>> p2 == p3
|
||||||
True
|
True
|
||||||
>>> p4 = p1 + ".py"
|
>>> p4 = p1 + ".py"
|
||||||
>>> p4.basename == "bar.py"
|
>>> p4.basename == "bar.py"
|
||||||
True
|
True
|
||||||
>>> p4.ext == ".py"
|
>>> p4.ext == ".py"
|
||||||
|
@ -185,7 +185,7 @@ allows you to check whether a file exists, what type it is, etc.:
|
||||||
>>> file1.check(basename='file1') # we can use all the path's properties here
|
>>> file1.check(basename='file1') # we can use all the path's properties here
|
||||||
True
|
True
|
||||||
|
|
||||||
Setting svn-properties
|
Setting svn-properties
|
||||||
.......................
|
.......................
|
||||||
|
|
||||||
As an example of 'uncommon' methods, we'll show how to read and write
|
As an example of 'uncommon' methods, we'll show how to read and write
|
||||||
|
@ -230,44 +230,44 @@ Known problems / limitations
|
||||||
===================================
|
===================================
|
||||||
|
|
||||||
* The SVN path objects require the "svn" command line,
|
* The SVN path objects require the "svn" command line,
|
||||||
there is currently no support for python bindings.
|
there is currently no support for python bindings.
|
||||||
Parsing the svn output can lead to problems, particularly
|
Parsing the svn output can lead to problems, particularly
|
||||||
regarding if you have a non-english "locales" setting.
|
regarding if you have a non-english "locales" setting.
|
||||||
|
|
||||||
* While the path objects basically work on windows,
|
* While the path objects basically work on windows,
|
||||||
there is no attention yet on making unicode paths
|
there is no attention yet on making unicode paths
|
||||||
work or deal with the famous "8.3" filename issues.
|
work or deal with the famous "8.3" filename issues.
|
||||||
|
|
||||||
Future plans
|
Future plans
|
||||||
============
|
============
|
||||||
|
|
||||||
The Subversion path implementations are based
|
The Subversion path implementations are based
|
||||||
on the `svn` command line, not on the bindings.
|
on the `svn` command line, not on the bindings.
|
||||||
It makes sense now to directly use the bindings.
|
It makes sense now to directly use the bindings.
|
||||||
|
|
||||||
Moreover, it would be good, also considering
|
Moreover, it would be good, also considering
|
||||||
`execnet`_ distribution of programs, to
|
`execnet`_ distribution of programs, to
|
||||||
be able to manipulate Windows Paths on Linux
|
be able to manipulate Windows Paths on Linux
|
||||||
and vice versa. So we'd like to consider
|
and vice versa. So we'd like to consider
|
||||||
refactoring the path implementations
|
refactoring the path implementations
|
||||||
to provide this choice (and getting rid
|
to provide this choice (and getting rid
|
||||||
of platform-dependencies as much as possible).
|
of platform-dependencies as much as possible).
|
||||||
|
|
||||||
There is some experimental small approach
|
There is some experimental small approach
|
||||||
(``py/path/gateway/``) aiming at having
|
(``py/path/gateway/``) aiming at having
|
||||||
a convenient Remote Path implementation.
|
a convenient Remote Path implementation.
|
||||||
|
|
||||||
There are various hacks out there to have
|
There are various hacks out there to have
|
||||||
Memory-Filesystems and even path objects
|
Memory-Filesystems and even path objects
|
||||||
being directly mountable under Linux (via `fuse`).
|
being directly mountable under Linux (via `fuse`).
|
||||||
However, the Path object implementations
|
However, the Path object implementations
|
||||||
do not internally have a clean abstraction
|
do not internally have a clean abstraction
|
||||||
of going to the filesystem - so with some
|
of going to the filesystem - so with some
|
||||||
refactoring it should become easier to
|
refactoring it should become easier to
|
||||||
have very custom Path objects, still offering
|
have very custom Path objects, still offering
|
||||||
the quite full interface without requiring
|
the quite full interface without requiring
|
||||||
to know about all details of the full path
|
to know about all details of the full path
|
||||||
implementation.
|
implementation.
|
||||||
|
|
||||||
.. _`execnet`: execnet.html
|
.. _`execnet`: execnet.html
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
===============================================
|
===============================================
|
||||||
ATTIC documentation
|
ATTIC documentation
|
||||||
===============================================
|
===============================================
|
||||||
|
|
||||||
XXX REVIEW and remove the below XXX
|
XXX REVIEW and remove the below XXX
|
||||||
|
|
||||||
Customizing the testing process
|
Customizing the testing process
|
||||||
===============================
|
===============================
|
||||||
|
|
||||||
writing conftest.py files
|
writing conftest.py files
|
||||||
|
@ -12,69 +12,69 @@ writing conftest.py files
|
||||||
|
|
||||||
You may put conftest.py files containing project-specific
|
You may put conftest.py files containing project-specific
|
||||||
configuration in your project's root directory, it's usually
|
configuration in your project's root directory, it's usually
|
||||||
best to put it just into the same directory level as your
|
best to put it just into the same directory level as your
|
||||||
topmost ``__init__.py``. In fact, ``py.test`` performs
|
topmost ``__init__.py``. In fact, ``py.test`` performs
|
||||||
an "upwards" search starting from the directory that you specify
|
an "upwards" search starting from the directory that you specify
|
||||||
to be tested and will lookup configuration values right-to-left.
|
to be tested and will lookup configuration values right-to-left.
|
||||||
You may have options that reside e.g. in your home directory
|
You may have options that reside e.g. in your home directory
|
||||||
but note that project specific settings will be considered
|
but note that project specific settings will be considered
|
||||||
first. There is a flag that helps you debugging your
|
first. There is a flag that helps you debugging your
|
||||||
conftest.py configurations::
|
conftest.py configurations::
|
||||||
|
|
||||||
py.test --traceconfig
|
py.test --traceconfig
|
||||||
|
|
||||||
|
|
||||||
customizing the collecting and running process
|
customizing the collecting and running process
|
||||||
-----------------------------------------------
|
-----------------------------------------------
|
||||||
|
|
||||||
To introduce different test items you can create
|
To introduce different test items you can create
|
||||||
one or more ``conftest.py`` files in your project.
|
one or more ``conftest.py`` files in your project.
|
||||||
When the collection process traverses directories
|
When the collection process traverses directories
|
||||||
and modules the default collectors will produce
|
and modules the default collectors will produce
|
||||||
custom Collectors and Items if they are found
|
custom Collectors and Items if they are found
|
||||||
in a local ``conftest.py`` file.
|
in a local ``conftest.py`` file.
|
||||||
|
|
||||||
|
|
||||||
Customizing the collection process in a module
|
Customizing the collection process in a module
|
||||||
----------------------------------------------
|
----------------------------------------------
|
||||||
|
|
||||||
If you have a module where you want to take responsibility for
|
If you have a module where you want to take responsibility for
|
||||||
collecting your own test Items and possibly even for executing
|
collecting your own test Items and possibly even for executing
|
||||||
a test then you can provide `generative tests`_ that yield
|
a test then you can provide `generative tests`_ that yield
|
||||||
callables and possibly arguments as a tuple. This is especially
|
callables and possibly arguments as a tuple. This is especially
|
||||||
useful for calling application test machinery with different
|
useful for calling application test machinery with different
|
||||||
parameter sets but counting each of the calls as a separate
|
parameter sets but counting each of the calls as a separate
|
||||||
tests.
|
tests.
|
||||||
|
|
||||||
.. _`generative tests`: features.html#generative-tests
|
.. _`generative tests`: features.html#generative-tests
|
||||||
|
|
||||||
The other extension possibility is about
|
The other extension possibility is about
|
||||||
specifying a custom test ``Item`` class which
|
specifying a custom test ``Item`` class which
|
||||||
is responsible for setting up and executing an underlying
|
is responsible for setting up and executing an underlying
|
||||||
test. Or you can extend the collection process for a whole
|
test. Or you can extend the collection process for a whole
|
||||||
directory tree by putting Items in a ``conftest.py`` configuration file.
|
directory tree by putting Items in a ``conftest.py`` configuration file.
|
||||||
The collection process dynamically consults the *chain of conftest.py*
|
The collection process dynamically consults the *chain of conftest.py*
|
||||||
modules to determine collectors and items at ``Directory``, ``Module``,
|
modules to determine collectors and items at ``Directory``, ``Module``,
|
||||||
``Class``, ``Function`` or ``Generator`` level respectively.
|
``Class``, ``Function`` or ``Generator`` level respectively.
|
||||||
|
|
||||||
Customizing execution of Items and Functions
|
Customizing execution of Items and Functions
|
||||||
----------------------------------------------------
|
----------------------------------------------------
|
||||||
|
|
||||||
- ``py.test.collect.Function`` test items control execution
|
- ``py.test.collect.Function`` test items control execution
|
||||||
of a test function through its ``function.runtest()`` method.
|
of a test function through its ``function.runtest()`` method.
|
||||||
This method is responsible for performing setup and teardown
|
This method is responsible for performing setup and teardown
|
||||||
("Test Fixtures") for a test Function.
|
("Test Fixtures") for a test Function.
|
||||||
|
|
||||||
- ``Function.execute(target, *args)`` methods are invoked by
|
- ``Function.execute(target, *args)`` methods are invoked by
|
||||||
the default ``Function.run()`` to actually execute a python
|
the default ``Function.run()`` to actually execute a python
|
||||||
function with the given (usually empty set of) arguments.
|
function with the given (usually empty set of) arguments.
|
||||||
|
|
||||||
.. _`py-dev mailing list`: http://codespeak.net/mailman/listinfo/py-dev
|
.. _`py-dev mailing list`: http://codespeak.net/mailman/listinfo/py-dev
|
||||||
|
|
||||||
|
|
||||||
.. _`test generators`: funcargs.html#test-generators
|
.. _`test generators`: funcargs.html#test-generators
|
||||||
|
|
||||||
.. _`generative tests`:
|
.. _`generative tests`:
|
||||||
|
|
||||||
generative tests: yielding parametrized tests
|
generative tests: yielding parametrized tests
|
||||||
====================================================
|
====================================================
|
||||||
|
@ -85,33 +85,33 @@ Deprecated since 1.0 in favour of `test generators`_.
|
||||||
``yield`` callables and their arguments. This is useful for running a
|
``yield`` callables and their arguments. This is useful for running a
|
||||||
test function multiple times against different parameters. Example::
|
test function multiple times against different parameters. Example::
|
||||||
|
|
||||||
def test_generative():
|
def test_generative():
|
||||||
for x in (42,17,49):
|
for x in (42,17,49):
|
||||||
yield check, x
|
yield check, x
|
||||||
|
|
||||||
def check(arg):
|
def check(arg):
|
||||||
assert arg % 7 == 0 # second generated tests fails!
|
assert arg % 7 == 0 # second generated tests fails!
|
||||||
|
|
||||||
Note that ``test_generative()`` will cause three tests
|
Note that ``test_generative()`` will cause three tests
|
||||||
to get run, notably ``check(42)``, ``check(17)`` and ``check(49)``
|
to get run, notably ``check(42)``, ``check(17)`` and ``check(49)``
|
||||||
of which the middle one will obviously fail.
|
of which the middle one will obviously fail.
|
||||||
|
|
||||||
To make it easier to distinguish the generated tests it is possible to specify an explicit name for them, like for example::
|
To make it easier to distinguish the generated tests it is possible to specify an explicit name for them, like for example::
|
||||||
|
|
||||||
def test_generative():
|
def test_generative():
|
||||||
for x in (42,17,49):
|
for x in (42,17,49):
|
||||||
yield "case %d" % x, check, x
|
yield "case %d" % x, check, x
|
||||||
|
|
||||||
|
|
||||||
disabling a test class
|
disabling a test class
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
If you want to disable a complete test class you
|
If you want to disable a complete test class you
|
||||||
can set the class-level attribute ``disabled``.
|
can set the class-level attribute ``disabled``.
|
||||||
For example, in order to avoid running some tests on Win32::
|
For example, in order to avoid running some tests on Win32::
|
||||||
|
|
||||||
class TestPosixOnly:
|
class TestPosixOnly:
|
||||||
disabled = sys.platform == 'win32'
|
disabled = sys.platform == 'win32'
|
||||||
|
|
||||||
def test_xxx(self):
|
def test_xxx(self):
|
||||||
...
|
...
|
||||||
|
|
|
@ -1,26 +1,26 @@
|
||||||
================================================
|
================================================
|
||||||
Customizing and Extending py.test
|
Customizing and Extending py.test
|
||||||
================================================
|
================================================
|
||||||
|
|
||||||
.. contents::
|
.. contents::
|
||||||
:local:
|
:local:
|
||||||
:depth: 2
|
:depth: 2
|
||||||
|
|
||||||
basic test configuration
|
basic test configuration
|
||||||
===================================
|
===================================
|
||||||
|
|
||||||
available command line options
|
available command line options
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
You can see command line options by running::
|
You can see command line options by running::
|
||||||
|
|
||||||
py.test -h
|
py.test -h
|
||||||
|
|
||||||
This will display all available command line options
|
This will display all available command line options
|
||||||
in your specific environment.
|
in your specific environment.
|
||||||
|
|
||||||
.. _`project-specific test configuration`:
|
.. _`project-specific test configuration`:
|
||||||
.. _`collect_ignore`:
|
.. _`collect_ignore`:
|
||||||
|
|
||||||
conftest.py: project specific hooks and configuration
|
conftest.py: project specific hooks and configuration
|
||||||
--------------------------------------------------------
|
--------------------------------------------------------
|
||||||
|
@ -36,33 +36,33 @@ allow to:
|
||||||
|
|
||||||
or set particular variables to influence the testing process:
|
or set particular variables to influence the testing process:
|
||||||
|
|
||||||
* ``pytest_plugins``: list of named plugins to load
|
* ``pytest_plugins``: list of named plugins to load
|
||||||
|
|
||||||
* ``collect_ignore``: list of paths to ignore during test collection, relative to the containing ``conftest.py`` file
|
* ``collect_ignore``: list of paths to ignore during test collection, relative to the containing ``conftest.py`` file
|
||||||
|
|
||||||
* ``rsyncdirs``: list of to-be-rsynced directories for distributed
|
* ``rsyncdirs``: list of to-be-rsynced directories for distributed
|
||||||
testing, relative to the containing ``conftest.py`` file.
|
testing, relative to the containing ``conftest.py`` file.
|
||||||
|
|
||||||
You may put a conftest.py files in your project root directory or into
|
You may put a conftest.py files in your project root directory or into
|
||||||
your package directory if you want to add project-specific test options.
|
your package directory if you want to add project-specific test options.
|
||||||
|
|
||||||
``py.test`` loads all ``conftest.py`` files upwards from the command
|
``py.test`` loads all ``conftest.py`` files upwards from the command
|
||||||
line file arguments. It usually looks up configuration values
|
line file arguments. It usually looks up configuration values
|
||||||
right-to-left, i.e. the closer conftest files will be checked first.
|
right-to-left, i.e. the closer conftest files will be checked first.
|
||||||
This means you can have a ``conftest.py`` in your very home directory to
|
This means you can have a ``conftest.py`` in your very home directory to
|
||||||
have some global configuration values.
|
have some global configuration values.
|
||||||
|
|
||||||
.. _`specify funcargs`: funcargs.html#application-setup-tutorial-example
|
.. _`specify funcargs`: funcargs.html#application-setup-tutorial-example
|
||||||
|
|
||||||
.. _`set option defaults`:
|
.. _`set option defaults`:
|
||||||
|
|
||||||
setting persistent option defaults
|
setting persistent option defaults
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
||||||
py.test will lookup option values in this order:
|
py.test will lookup option values in this order:
|
||||||
|
|
||||||
* command line
|
* command line
|
||||||
* conftest.py files
|
* conftest.py files
|
||||||
* environment variables
|
* environment variables
|
||||||
|
|
||||||
To find out about the particular switches and type::
|
To find out about the particular switches and type::
|
||||||
|
@ -70,19 +70,19 @@ To find out about the particular switches and type::
|
||||||
py.test --help-config
|
py.test --help-config
|
||||||
|
|
||||||
This will print information about all options in your
|
This will print information about all options in your
|
||||||
environment, including your local plugins.
|
environment, including your local plugins.
|
||||||
|
|
||||||
.. _`basetemp`:
|
.. _`basetemp`:
|
||||||
|
|
||||||
Temporary directories
|
Temporary directories
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
|
|
||||||
You can create directories by calling one of two methods
|
You can create directories by calling one of two methods
|
||||||
on the config object:
|
on the config object:
|
||||||
|
|
||||||
- ``config.mktemp(basename)``: create and return a new tempdir
|
- ``config.mktemp(basename)``: create and return a new tempdir
|
||||||
|
|
||||||
- ``config.ensuretemp(basename)``: create or return a new tempdir
|
- ``config.ensuretemp(basename)``: create or return a new tempdir
|
||||||
|
|
||||||
temporary directories are created as sub directories of a per-session
|
temporary directories are created as sub directories of a per-session
|
||||||
testdir and will keep around the directories of the last three test
|
testdir and will keep around the directories of the last three test
|
||||||
|
@ -90,12 +90,12 @@ runs. You can set the base temporary directory through the command line
|
||||||
`--basetemp`` option. When distributing tests on the same machine,
|
`--basetemp`` option. When distributing tests on the same machine,
|
||||||
``py.test`` takes care to configure a basetemp directory for the sub
|
``py.test`` takes care to configure a basetemp directory for the sub
|
||||||
processes such that all temporary data lands below below a single
|
processes such that all temporary data lands below below a single
|
||||||
per-test run basetemp directory.
|
per-test run basetemp directory.
|
||||||
|
|
||||||
.. _`function arguments`: funcargs.html
|
.. _`function arguments`: funcargs.html
|
||||||
.. _`extensions`:
|
.. _`extensions`:
|
||||||
|
|
||||||
Plugin basics and project configuration
|
Plugin basics and project configuration
|
||||||
=============================================
|
=============================================
|
||||||
|
|
||||||
.. _`local plugin`:
|
.. _`local plugin`:
|
||||||
|
@ -112,34 +112,34 @@ extensions close to your application. Named plugins are normal python
|
||||||
modules or packages that can be distributed separately. Named plugins
|
modules or packages that can be distributed separately. Named plugins
|
||||||
need to follow a naming pattern; they have an all lowercase ``pytest_``
|
need to follow a naming pattern; they have an all lowercase ``pytest_``
|
||||||
prefixed name. While conftest plugins are discovered automatically,
|
prefixed name. While conftest plugins are discovered automatically,
|
||||||
named plugins must be explicitely specified.
|
named plugins must be explicitely specified.
|
||||||
|
|
||||||
.. _`named plugins`: plugin/index.html
|
.. _`named plugins`: plugin/index.html
|
||||||
|
|
||||||
.. _`tool startup`:
|
.. _`tool startup`:
|
||||||
.. _`loaded at tool startup`:
|
.. _`loaded at tool startup`:
|
||||||
.. _`test tool starts up`:
|
.. _`test tool starts up`:
|
||||||
|
|
||||||
Plugin discovery at tool startup
|
Plugin discovery at tool startup
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
|
|
||||||
py.test loads plugin modules at tool startup in the following way:
|
py.test loads plugin modules at tool startup in the following way:
|
||||||
|
|
||||||
* by loading all plugins registered through `setuptools entry points`_.
|
* by loading all plugins registered through `setuptools entry points`_.
|
||||||
|
|
||||||
* by reading the ``PYTEST_PLUGINS`` environment variable
|
* by reading the ``PYTEST_PLUGINS`` environment variable
|
||||||
and importing the comma-separated list of named plugins.
|
and importing the comma-separated list of named plugins.
|
||||||
|
|
||||||
* by pre-scanning the command line for the ``-p name`` option
|
* by pre-scanning the command line for the ``-p name`` option
|
||||||
and loading the specified plugin before actual command line parsing.
|
and loading the specified plugin before actual command line parsing.
|
||||||
|
|
||||||
* by loading all `conftest.py plugin`_ files as inferred by the command line
|
* by loading all `conftest.py plugin`_ files as inferred by the command line
|
||||||
invocation (test files and all of its parent directories).
|
invocation (test files and all of its parent directories).
|
||||||
Note that ``conftest.py`` files from sub directories are loaded
|
Note that ``conftest.py`` files from sub directories are loaded
|
||||||
during test collection and not at tool startup.
|
during test collection and not at tool startup.
|
||||||
|
|
||||||
* by recursively loading all plugins specified by the
|
* by recursively loading all plugins specified by the
|
||||||
``pytest_plugins`` variable in a ``conftest.py`` file
|
``pytest_plugins`` variable in a ``conftest.py`` file
|
||||||
|
|
||||||
Specifying plugins in a test module or plugin
|
Specifying plugins in a test module or plugin
|
||||||
-----------------------------------------------
|
-----------------------------------------------
|
||||||
|
@ -148,12 +148,12 @@ You can specify plugins in a test module or a plugin like this:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
pytest_plugins = "name1", "name2",
|
pytest_plugins = "name1", "name2",
|
||||||
|
|
||||||
When the test module or plugin is loaded the specified plugins
|
When the test module or plugin is loaded the specified plugins
|
||||||
will be loaded. If you specify plugins without the ``pytest_``
|
will be loaded. If you specify plugins without the ``pytest_``
|
||||||
prefix it will be automatically added. All plugin names
|
prefix it will be automatically added. All plugin names
|
||||||
must be lowercase.
|
must be lowercase.
|
||||||
|
|
||||||
.. _`conftest.py plugin`:
|
.. _`conftest.py plugin`:
|
||||||
.. _`conftestplugin`:
|
.. _`conftestplugin`:
|
||||||
|
@ -161,18 +161,18 @@ must be lowercase.
|
||||||
Writing per-project plugins (conftest.py)
|
Writing per-project plugins (conftest.py)
|
||||||
------------------------------------------------------
|
------------------------------------------------------
|
||||||
|
|
||||||
The purpose of ``conftest.py`` files is to allow `project-specific
|
The purpose of ``conftest.py`` files is to allow `project-specific
|
||||||
test configuration`_. They thus make for a good place to implement
|
test configuration`_. They thus make for a good place to implement
|
||||||
project-specific test related features through hooks. For example you may
|
project-specific test related features through hooks. For example you may
|
||||||
set the `collect_ignore`_ variable depending on a command line option
|
set the `collect_ignore`_ variable depending on a command line option
|
||||||
by defining the following hook in a ``conftest.py`` file:
|
by defining the following hook in a ``conftest.py`` file:
|
||||||
|
|
||||||
.. _`exclude-file-example`:
|
.. _`exclude-file-example`:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
# ./conftest.py in your root or package dir
|
# ./conftest.py in your root or package dir
|
||||||
collect_ignore = ['hello', 'test_world.py']
|
collect_ignore = ['hello', 'test_world.py']
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
parser.addoption("--runall", action="store_true", default=False)
|
parser.addoption("--runall", action="store_true", default=False)
|
||||||
def pytest_configure(config):
|
def pytest_configure(config):
|
||||||
|
@ -181,7 +181,7 @@ by defining the following hook in a ``conftest.py`` file:
|
||||||
|
|
||||||
.. _`setuptools entry points`:
|
.. _`setuptools entry points`:
|
||||||
|
|
||||||
Writing setuptools-registered plugins
|
Writing setuptools-registered plugins
|
||||||
------------------------------------------------------
|
------------------------------------------------------
|
||||||
|
|
||||||
.. _`Distribute`: http://pypi.python.org/pypi/distribute
|
.. _`Distribute`: http://pypi.python.org/pypi/distribute
|
||||||
|
@ -190,13 +190,13 @@ Writing setuptools-registered plugins
|
||||||
If you want to make your plugin publically available, you
|
If you want to make your plugin publically available, you
|
||||||
can use `setuptools`_ or `Distribute`_ which both allow
|
can use `setuptools`_ or `Distribute`_ which both allow
|
||||||
to register an entry point. ``py.test`` will register
|
to register an entry point. ``py.test`` will register
|
||||||
all objects with the ``pytest11`` entry point.
|
all objects with the ``pytest11`` entry point.
|
||||||
To make your plugin available you may insert the following
|
To make your plugin available you may insert the following
|
||||||
lines in your setuptools/distribute-based setup-invocation:
|
lines in your setuptools/distribute-based setup-invocation:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
# sample ./setup.py file
|
# sample ./setup.py file
|
||||||
from setuptools import setup
|
from setuptools import setup
|
||||||
|
|
||||||
setup(
|
setup(
|
||||||
|
@ -204,16 +204,16 @@ lines in your setuptools/distribute-based setup-invocation:
|
||||||
packages = ['myproject']
|
packages = ['myproject']
|
||||||
|
|
||||||
# the following makes a plugin available to py.test
|
# the following makes a plugin available to py.test
|
||||||
entry_points = {
|
entry_points = {
|
||||||
'pytest11': [
|
'pytest11': [
|
||||||
'name_of_plugin = myproject.pluginmodule',
|
'name_of_plugin = myproject.pluginmodule',
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
|
|
||||||
If a package is installed with this setup, py.test will load
|
If a package is installed with this setup, py.test will load
|
||||||
``myproject.pluginmodule`` under the ``name_of_plugin`` name
|
``myproject.pluginmodule`` under the ``name_of_plugin`` name
|
||||||
and use it as a plugin.
|
and use it as a plugin.
|
||||||
|
|
||||||
Accessing another plugin by name
|
Accessing another plugin by name
|
||||||
--------------------------------------------
|
--------------------------------------------
|
||||||
|
@ -226,63 +226,63 @@ the plugin manager like this:
|
||||||
|
|
||||||
plugin = config.pluginmanager.getplugin("name_of_plugin")
|
plugin = config.pluginmanager.getplugin("name_of_plugin")
|
||||||
|
|
||||||
If you want to look at the names of existing plugins, use
|
If you want to look at the names of existing plugins, use
|
||||||
the ``--traceconfig`` option.
|
the ``--traceconfig`` option.
|
||||||
|
|
||||||
.. _`well specified hooks`:
|
.. _`well specified hooks`:
|
||||||
.. _`implement hooks`:
|
.. _`implement hooks`:
|
||||||
|
|
||||||
Important py.test hooks
|
Important py.test hooks
|
||||||
====================================
|
====================================
|
||||||
|
|
||||||
py.test calls hooks functions to implement its `test collection`_,
|
py.test calls hooks functions to implement its `test collection`_,
|
||||||
running and reporting process. When py.test loads a plugin it validates
|
running and reporting process. When py.test loads a plugin it validates
|
||||||
that all hook functions conform to the `hook definition specification`_.
|
that all hook functions conform to the `hook definition specification`_.
|
||||||
|
|
||||||
The hook function name and its
|
The hook function name and its
|
||||||
argument names need to match exactly but it is allowed for an implementation
|
argument names need to match exactly but it is allowed for an implementation
|
||||||
to accept *less* parameters. You'll get useful errors on mistyped hook or
|
to accept *less* parameters. You'll get useful errors on mistyped hook or
|
||||||
argument names. Read on for some introductory information on particular
|
argument names. Read on for some introductory information on particular
|
||||||
hooks. It's sensible to look at existing plugins so see example usages
|
hooks. It's sensible to look at existing plugins so see example usages
|
||||||
and start off with your own plugin.
|
and start off with your own plugin.
|
||||||
|
|
||||||
.. _`hook definition specification`: plugin/hookspec.html
|
.. _`hook definition specification`: plugin/hookspec.html
|
||||||
|
|
||||||
.. _`configuration hooks`:
|
.. _`configuration hooks`:
|
||||||
|
|
||||||
command line parsing and configuration hooks
|
command line parsing and configuration hooks
|
||||||
--------------------------------------------------------------------
|
--------------------------------------------------------------------
|
||||||
|
|
||||||
When the `test tool starts up`_ it will invoke all hooks that add
|
When the `test tool starts up`_ it will invoke all hooks that add
|
||||||
command line options in the python standard optparse style.
|
command line options in the python standard optparse style.
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
""" add command line options. """"
|
""" add command line options. """"
|
||||||
parser.addoption("--myopt", dest="myopt", action="store_true")
|
parser.addoption("--myopt", dest="myopt", action="store_true")
|
||||||
|
|
||||||
After all these hooks have been called, the command line is parser
|
After all these hooks have been called, the command line is parser
|
||||||
and a ``config`` object is created and another hook is invoked,
|
and a ``config`` object is created and another hook is invoked,
|
||||||
for example:
|
for example:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
def pytest_configure(config):
|
def pytest_configure(config):
|
||||||
config.getvalue("myopt")
|
config.getvalue("myopt")
|
||||||
|
|
||||||
When the test run finishes this corresponding finalizer hook is called:
|
When the test run finishes this corresponding finalizer hook is called:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
def pytest_unconfigure(config):
|
def pytest_unconfigure(config):
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
adding global py.test helpers and functionality
|
adding global py.test helpers and functionality
|
||||||
--------------------------------------------------------------------
|
--------------------------------------------------------------------
|
||||||
|
|
||||||
If you want to make global helper functions or objects available
|
If you want to make global helper functions or objects available
|
||||||
to your test code you can implement:
|
to your test code you can implement:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
@ -290,29 +290,29 @@ to your test code you can implement:
|
||||||
def pytest_namespace():
|
def pytest_namespace():
|
||||||
""" return dictionary with items to be made available on py.test. namespace """
|
""" return dictionary with items to be made available on py.test. namespace """
|
||||||
|
|
||||||
All such returned items will be made available directly on
|
All such returned items will be made available directly on
|
||||||
the ``py.test`` namespace.
|
the ``py.test`` namespace.
|
||||||
|
|
||||||
If you want to provide helpers that are specific to a test function run or need
|
If you want to provide helpers that are specific to a test function run or need
|
||||||
to be setup per test function run, please refer to the `funcargs mechanism`_.
|
to be setup per test function run, please refer to the `funcargs mechanism`_.
|
||||||
|
|
||||||
.. _`funcargs mechanism`: funcargs.html
|
.. _`funcargs mechanism`: funcargs.html
|
||||||
|
|
||||||
|
|
||||||
generic "runtest" hooks
|
generic "runtest" hooks
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
Each test item is usually executed by calling the following three hooks:
|
Each test item is usually executed by calling the following three hooks:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
pytest_runtest_setup(item)
|
pytest_runtest_setup(item)
|
||||||
pytest_runtest_call(item)
|
pytest_runtest_call(item)
|
||||||
pytest_runtest_teardown(item)
|
pytest_runtest_teardown(item)
|
||||||
|
|
||||||
For each of the three invocations a `call object`_ encapsulates
|
For each of the three invocations a `call object`_ encapsulates
|
||||||
information about the outcome of the call and is subsequently used
|
information about the outcome of the call and is subsequently used
|
||||||
to make a report object:
|
to make a report object:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
|
@ -320,57 +320,57 @@ to make a report object:
|
||||||
|
|
||||||
For example, the `pytest_pdb plugin`_ uses this hook to activate
|
For example, the `pytest_pdb plugin`_ uses this hook to activate
|
||||||
interactive debugging on failures when ``--pdb`` is specified on the
|
interactive debugging on failures when ``--pdb`` is specified on the
|
||||||
command line.
|
command line.
|
||||||
|
|
||||||
Usually three reports will be generated for a single test item for each
|
Usually three reports will be generated for a single test item for each
|
||||||
of the three runtest hooks respectively. If ``pytest_runtest_setup``
|
of the three runtest hooks respectively. If ``pytest_runtest_setup``
|
||||||
fails then ``pytest_runtest_teardown`` will be called but not
|
fails then ``pytest_runtest_teardown`` will be called but not
|
||||||
``pytest_runtest_call``.
|
``pytest_runtest_call``.
|
||||||
|
|
||||||
Each of the up to three reports is eventually fed to the logreport hook:
|
Each of the up to three reports is eventually fed to the logreport hook:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
pytest_runtest_logreport(report)
|
pytest_runtest_logreport(report)
|
||||||
|
|
||||||
A ``report`` object contains status and reporting information:
|
A ``report`` object contains status and reporting information:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
report.longrepr = string/lines/object to print
|
report.longrepr = string/lines/object to print
|
||||||
report.when = "setup", "call" or "teardown"
|
report.when = "setup", "call" or "teardown"
|
||||||
report.shortrepr = letter for progress-report
|
report.shortrepr = letter for progress-report
|
||||||
report.passed = True or False
|
report.passed = True or False
|
||||||
report.failed = True or False
|
report.failed = True or False
|
||||||
report.skipped = True or False
|
report.skipped = True or False
|
||||||
|
|
||||||
The `terminal plugin`_ uses this hook to print information
|
The `terminal plugin`_ uses this hook to print information
|
||||||
about a test run.
|
about a test run.
|
||||||
|
|
||||||
The whole protocol described here is implemented via this hook:
|
The whole protocol described here is implemented via this hook:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
pytest_runtest_protocol(item) -> True
|
|
||||||
|
|
||||||
.. _`call object`:
|
pytest_runtest_protocol(item) -> True
|
||||||
|
|
||||||
|
.. _`call object`:
|
||||||
|
|
||||||
The call object contains information about a performed call:
|
The call object contains information about a performed call:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
call.excinfo = ExceptionInfo object or None
|
call.excinfo = ExceptionInfo object or None
|
||||||
call.when = "setup", "call" or "teardown"
|
call.when = "setup", "call" or "teardown"
|
||||||
call.outerr = None or tuple of strings representing captured stdout/stderr
|
call.outerr = None or tuple of strings representing captured stdout/stderr
|
||||||
|
|
||||||
.. _`pytest_pdb plugin`: plugin/pdb.html
|
.. _`pytest_pdb plugin`: plugin/pdb.html
|
||||||
.. _`terminal plugin`: plugin/terminal.html
|
.. _`terminal plugin`: plugin/terminal.html
|
||||||
|
|
||||||
|
|
||||||
generic collection hooks
|
generic collection hooks
|
||||||
------------------------------
|
------------------------------
|
||||||
|
|
||||||
py.test calls the following two fundamental hooks for collecting files and directories:
|
py.test calls the following two fundamental hooks for collecting files and directories:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
|
@ -380,17 +380,17 @@ py.test calls the following two fundamental hooks for collecting files and direc
|
||||||
def pytest_collect_file(path, parent):
|
def pytest_collect_file(path, parent):
|
||||||
""" return Collection node or None for the given path. """
|
""" return Collection node or None for the given path. """
|
||||||
|
|
||||||
Both return a `collection node`_ for a given path. All returned
|
Both return a `collection node`_ for a given path. All returned
|
||||||
nodes from all hook implementations will participate in the
|
nodes from all hook implementations will participate in the
|
||||||
collection and running protocol. The ``parent`` object is
|
collection and running protocol. The ``parent`` object is
|
||||||
the parent node and may be used to access command line
|
the parent node and may be used to access command line
|
||||||
options via the ``parent.config`` object.
|
options via the ``parent.config`` object.
|
||||||
|
|
||||||
|
|
||||||
Python test function and module hooks
|
Python test function and module hooks
|
||||||
----------------------------------------------------
|
----------------------------------------------------
|
||||||
|
|
||||||
For influencing the collection of objects in Python modules
|
For influencing the collection of objects in Python modules
|
||||||
you can use the following hook:
|
you can use the following hook:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
@ -399,9 +399,9 @@ you can use the following hook:
|
||||||
""" return custom item/collector for a python object in a module, or None. """
|
""" return custom item/collector for a python object in a module, or None. """
|
||||||
|
|
||||||
This hook will be called for each Python object in a collected
|
This hook will be called for each Python object in a collected
|
||||||
Python module. The return value is a custom `collection node`_ or None.
|
Python module. The return value is a custom `collection node`_ or None.
|
||||||
|
|
||||||
.. XXX or ``False`` if you want to indicate that the given item should not be collected.
|
.. XXX or ``False`` if you want to indicate that the given item should not be collected.
|
||||||
|
|
||||||
|
|
||||||
Gateway initialization (distributed testing)
|
Gateway initialization (distributed testing)
|
||||||
|
@ -415,32 +415,32 @@ remote environment. For this you can implement the newgateway hook:
|
||||||
def pytest_gwmanage_newgateway(gateway, platinfo):
|
def pytest_gwmanage_newgateway(gateway, platinfo):
|
||||||
""" called after a gateway is instantiated. """
|
""" called after a gateway is instantiated. """
|
||||||
|
|
||||||
The ``gateway`` object here has a ``spec`` attribute which is an ``execnet.XSpec``
|
The ``gateway`` object here has a ``spec`` attribute which is an ``execnet.XSpec``
|
||||||
object, which has attributes that map key/values as specified from a ``--txspec``
|
object, which has attributes that map key/values as specified from a ``--txspec``
|
||||||
option. The platinfo object is a dictionary with information about the remote process:
|
option. The platinfo object is a dictionary with information about the remote process:
|
||||||
|
|
||||||
* ``version``: remote python's ``sys.version_info``
|
* ``version``: remote python's ``sys.version_info``
|
||||||
* ``platform``: remote ``sys.platform``
|
* ``platform``: remote ``sys.platform``
|
||||||
* ``cwd``: remote ``os.getcwd``
|
* ``cwd``: remote ``os.getcwd``
|
||||||
|
|
||||||
|
|
||||||
.. _`collection process`:
|
.. _`collection process`:
|
||||||
.. _`collection node`:
|
.. _`collection node`:
|
||||||
.. _`test collection`:
|
.. _`test collection`:
|
||||||
|
|
||||||
|
|
||||||
Test Collection process
|
Test Collection process
|
||||||
======================================================
|
======================================================
|
||||||
|
|
||||||
the collection tree
|
the collection tree
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
The collecting process is iterative so that distribution
|
The collecting process is iterative so that distribution
|
||||||
and execution of tests can start as soon as the first test
|
and execution of tests can start as soon as the first test
|
||||||
item is collected. Collection nodes with children are
|
item is collected. Collection nodes with children are
|
||||||
called "Collectors" and terminal nodes are called "Items".
|
called "Collectors" and terminal nodes are called "Items".
|
||||||
Here is an example of such a tree, generated with the
|
Here is an example of such a tree, generated with the
|
||||||
command ``py.test --collectonly py/xmlobj``::
|
command ``py.test --collectonly py/xmlobj``::
|
||||||
|
|
||||||
<Directory 'xmlobj'>
|
<Directory 'xmlobj'>
|
||||||
<Directory 'testing'>
|
<Directory 'testing'>
|
||||||
|
@ -457,34 +457,34 @@ command ``py.test --collectonly py/xmlobj``::
|
||||||
<Function 'test_tag_nested'>
|
<Function 'test_tag_nested'>
|
||||||
<Function 'test_tag_xmlname'>
|
<Function 'test_tag_xmlname'>
|
||||||
|
|
||||||
By default all directories not starting with a dot are traversed,
|
By default all directories not starting with a dot are traversed,
|
||||||
looking for ``test_*.py`` and ``*_test.py`` files. Those Python
|
looking for ``test_*.py`` and ``*_test.py`` files. Those Python
|
||||||
files are imported under their `package name`_.
|
files are imported under their `package name`_.
|
||||||
|
|
||||||
The Module collector looks for test functions
|
The Module collector looks for test functions
|
||||||
and test classes and methods. Test functions and methods
|
and test classes and methods. Test functions and methods
|
||||||
are prefixed ``test`` by default. Test classes must
|
are prefixed ``test`` by default. Test classes must
|
||||||
start with a capitalized ``Test`` prefix.
|
start with a capitalized ``Test`` prefix.
|
||||||
|
|
||||||
Customizing error messages
|
Customizing error messages
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
|
|
||||||
On test and collection nodes ``py.test`` will invoke
|
On test and collection nodes ``py.test`` will invoke
|
||||||
the ``node.repr_failure(excinfo)`` function which
|
the ``node.repr_failure(excinfo)`` function which
|
||||||
you may override and make it return an error
|
you may override and make it return an error
|
||||||
representation string of your choice. It
|
representation string of your choice. It
|
||||||
will be reported as a (red) string.
|
will be reported as a (red) string.
|
||||||
|
|
||||||
.. _`package name`:
|
.. _`package name`:
|
||||||
|
|
||||||
constructing the package name for test modules
|
constructing the package name for test modules
|
||||||
-------------------------------------------------
|
-------------------------------------------------
|
||||||
|
|
||||||
Test modules are imported under their fully qualified
|
Test modules are imported under their fully qualified
|
||||||
name. Given a filesystem ``fspath`` it is constructed as follows:
|
name. Given a filesystem ``fspath`` it is constructed as follows:
|
||||||
|
|
||||||
* walk the directories up to the last one that contains
|
* walk the directories up to the last one that contains
|
||||||
an ``__init__.py`` file.
|
an ``__init__.py`` file.
|
||||||
|
|
||||||
* perform ``sys.path.insert(0, basedir)``.
|
* perform ``sys.path.insert(0, basedir)``.
|
||||||
|
|
||||||
|
|
|
@ -4,29 +4,29 @@ Learning by examples
|
||||||
adding custom options
|
adding custom options
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
py.test supports adding of standard optparse_ Options.
|
py.test supports adding of standard optparse_ Options.
|
||||||
A plugin may implement the ``addoption`` hook for registering
|
A plugin may implement the ``addoption`` hook for registering
|
||||||
custom options::
|
custom options::
|
||||||
|
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
parser.addoption("-M", "--myopt", action="store",
|
parser.addoption("-M", "--myopt", action="store",
|
||||||
help="specify string to set myopt")
|
help="specify string to set myopt")
|
||||||
|
|
||||||
def pytest_configure(config):
|
def pytest_configure(config):
|
||||||
if config.option.myopt:
|
if config.option.myopt:
|
||||||
# do action based on option value
|
# do action based on option value
|
||||||
#
|
#
|
||||||
|
|
||||||
.. _optparse: http://docs.python.org/library/optparse.html
|
.. _optparse: http://docs.python.org/library/optparse.html
|
||||||
|
|
||||||
Working Examples
|
Working Examples
|
||||||
================
|
================
|
||||||
|
|
||||||
managing state at module, class and method level
|
managing state at module, class and method level
|
||||||
------------------------------------------------------------
|
------------------------------------------------------------
|
||||||
|
|
||||||
Here is a working example for what goes on when you setup modules,
|
Here is a working example for what goes on when you setup modules,
|
||||||
classes and methods::
|
classes and methods::
|
||||||
|
|
||||||
# [[from py/documentation/example/pytest/test_setup_flow_example.py]]
|
# [[from py/documentation/example/pytest/test_setup_flow_example.py]]
|
||||||
|
|
||||||
|
@ -58,17 +58,17 @@ For this example the control flow happens as follows::
|
||||||
|
|
||||||
import test_setup_flow_example
|
import test_setup_flow_example
|
||||||
setup_module(test_setup_flow_example)
|
setup_module(test_setup_flow_example)
|
||||||
setup_class(TestStateFullThing)
|
setup_class(TestStateFullThing)
|
||||||
instance = TestStateFullThing()
|
instance = TestStateFullThing()
|
||||||
setup_method(instance, instance.test_42)
|
setup_method(instance, instance.test_42)
|
||||||
instance.test_42()
|
instance.test_42()
|
||||||
setup_method(instance, instance.test_23)
|
setup_method(instance, instance.test_23)
|
||||||
instance.test_23()
|
instance.test_23()
|
||||||
teardown_class(TestStateFullThing)
|
teardown_class(TestStateFullThing)
|
||||||
teardown_module(test_setup_flow_example)
|
teardown_module(test_setup_flow_example)
|
||||||
|
|
||||||
Note that ``setup_class(TestStateFullThing)`` is called and not
|
Note that ``setup_class(TestStateFullThing)`` is called and not
|
||||||
``TestStateFullThing.setup_class()`` which would require you
|
``TestStateFullThing.setup_class()`` which would require you
|
||||||
to insert ``setup_class = classmethod(setup_class)`` to make
|
to insert ``setup_class = classmethod(setup_class)`` to make
|
||||||
your setup function callable. Did we mention that lazyness
|
your setup function callable. Did we mention that lazyness
|
||||||
is a virtue?
|
is a virtue?
|
||||||
|
|
|
@ -1,35 +1,35 @@
|
||||||
==================================================
|
==================================================
|
||||||
py.test feature overview
|
py.test feature overview
|
||||||
==================================================
|
==================================================
|
||||||
|
|
||||||
.. contents::
|
.. contents::
|
||||||
:local:
|
:local:
|
||||||
:depth: 1
|
:depth: 1
|
||||||
|
|
||||||
mature command line testing tool
|
mature command line testing tool
|
||||||
====================================================
|
====================================================
|
||||||
|
|
||||||
py.test is a command line tool to collect, run and report about automated tests. It runs well on Linux, Windows and OSX and on Python 2.4 through to 3.1 versions.
|
py.test is a command line tool to collect, run and report about automated tests. It runs well on Linux, Windows and OSX and on Python 2.4 through to 3.1 versions.
|
||||||
It is used in many projects, ranging from running 10 thousands of tests
|
It is used in many projects, ranging from running 10 thousands of tests
|
||||||
to a few inlined tests on a command line script. As of version 1.2 you can also
|
to a few inlined tests on a command line script. As of version 1.2 you can also
|
||||||
generate a no-dependency py.test-equivalent standalone script that you
|
generate a no-dependency py.test-equivalent standalone script that you
|
||||||
can distribute along with your application.
|
can distribute along with your application.
|
||||||
|
|
||||||
extensive easy plugin system
|
extensive easy plugin system
|
||||||
======================================================
|
======================================================
|
||||||
|
|
||||||
.. _`suprisingly easy`: http://bruynooghe.blogspot.com/2009/12/skipping-slow-test-by-default-in-pytest.html
|
.. _`suprisingly easy`: http://bruynooghe.blogspot.com/2009/12/skipping-slow-test-by-default-in-pytest.html
|
||||||
|
|
||||||
py.test delegates almost all aspects of its operation to plugins_.
|
py.test delegates almost all aspects of its operation to plugins_.
|
||||||
It is `suprisingly easy`_ to add command line options or
|
It is `suprisingly easy`_ to add command line options or
|
||||||
do other kind of add-ons and customizations. This can
|
do other kind of add-ons and customizations. This can
|
||||||
be done per-project or by distributing a global plugin.
|
be done per-project or by distributing a global plugin.
|
||||||
One can can thus modify or add aspects for purposes such as:
|
One can can thus modify or add aspects for purposes such as:
|
||||||
|
|
||||||
* reporting extensions
|
* reporting extensions
|
||||||
* customizing collection and execution of tests
|
* customizing collection and execution of tests
|
||||||
* running and managing non-python tests
|
* running and managing non-python tests
|
||||||
* managing domain-specific test state setup
|
* managing domain-specific test state setup
|
||||||
* adding non-python tests into the run, e.g. driven by data files
|
* adding non-python tests into the run, e.g. driven by data files
|
||||||
|
|
||||||
.. _`plugins`: plugin/index.html
|
.. _`plugins`: plugin/index.html
|
||||||
|
@ -42,18 +42,18 @@ distributing tests to your CPUs and SSH accounts
|
||||||
Through the use of the separately released `pytest-xdist`_ plugin you
|
Through the use of the separately released `pytest-xdist`_ plugin you
|
||||||
can seemlessly distribute runs to multiple CPUs or remote computers
|
can seemlessly distribute runs to multiple CPUs or remote computers
|
||||||
through SSH and sockets. This plugin also offers a ``--looponfailing``
|
through SSH and sockets. This plugin also offers a ``--looponfailing``
|
||||||
mode which will continously re-run only failing tests in a subprocess.
|
mode which will continously re-run only failing tests in a subprocess.
|
||||||
|
|
||||||
supports several testing practises and methods
|
supports several testing practises and methods
|
||||||
==================================================================
|
==================================================================
|
||||||
|
|
||||||
py.test supports many testing methods conventionally used in
|
py.test supports many testing methods conventionally used in
|
||||||
the Python community. It runs traditional `unittest.py`_,
|
the Python community. It runs traditional `unittest.py`_,
|
||||||
`doctest.py`_, supports `xUnit style setup`_ and nose_ specific
|
`doctest.py`_, supports `xUnit style setup`_ and nose_ specific
|
||||||
setups and test suites. It offers minimal no-boilerplate model
|
setups and test suites. It offers minimal no-boilerplate model
|
||||||
for configuring and deploying tests written as simple Python
|
for configuring and deploying tests written as simple Python
|
||||||
functions or methods. It also integrates `coverage testing
|
functions or methods. It also integrates `coverage testing
|
||||||
with figleaf`_ or `Javasript unit- and functional testing`_.
|
with figleaf`_ or `Javasript unit- and functional testing`_.
|
||||||
|
|
||||||
.. _`Javasript unit- and functional testing`: plugin/oejskit.html
|
.. _`Javasript unit- and functional testing`: plugin/oejskit.html
|
||||||
.. _`coverage testing with figleaf`: plugin/figleaf.html
|
.. _`coverage testing with figleaf`: plugin/figleaf.html
|
||||||
|
@ -63,98 +63,98 @@ integrates well with CI systems
|
||||||
|
|
||||||
py.test can produce JUnitXML style output as well as formatted
|
py.test can produce JUnitXML style output as well as formatted
|
||||||
"resultlog" files that can be postprocessed by Continous Integration
|
"resultlog" files that can be postprocessed by Continous Integration
|
||||||
systems such as Hudson or Buildbot easily. It also provides command
|
systems such as Hudson or Buildbot easily. It also provides command
|
||||||
line options to control test configuration lookup behaviour or ignoring
|
line options to control test configuration lookup behaviour or ignoring
|
||||||
certain tests or directories.
|
certain tests or directories.
|
||||||
|
|
||||||
no-boilerplate test functions with Python
|
no-boilerplate test functions with Python
|
||||||
===================================================
|
===================================================
|
||||||
|
|
||||||
.. _`autocollect`:
|
.. _`autocollect`:
|
||||||
|
|
||||||
automatic Python test discovery
|
automatic Python test discovery
|
||||||
------------------------------------
|
------------------------------------
|
||||||
|
|
||||||
By default, all python modules with a ``test_*.py``
|
By default, all python modules with a ``test_*.py``
|
||||||
filename are inspected for finding tests:
|
filename are inspected for finding tests:
|
||||||
|
|
||||||
* functions with a name beginning with ``test_``
|
* functions with a name beginning with ``test_``
|
||||||
* classes with a leading ``Test`` name and ``test`` prefixed methods.
|
* classes with a leading ``Test`` name and ``test`` prefixed methods.
|
||||||
* ``unittest.TestCase`` subclasses
|
* ``unittest.TestCase`` subclasses
|
||||||
|
|
||||||
parametrizing test functions and functional testing
|
parametrizing test functions and functional testing
|
||||||
--------------------------------------------------------------
|
--------------------------------------------------------------
|
||||||
|
|
||||||
py.test offers the unique `funcargs mechanism`_ for setting up
|
py.test offers the unique `funcargs mechanism`_ for setting up
|
||||||
and passing project-specific objects to Python test functions.
|
and passing project-specific objects to Python test functions.
|
||||||
Test Parametrization happens by triggering a call to the same test
|
Test Parametrization happens by triggering a call to the same test
|
||||||
function with different argument values. For doing fixtures
|
function with different argument values. For doing fixtures
|
||||||
using the funcarg mechanism makes your test and setup code
|
using the funcarg mechanism makes your test and setup code
|
||||||
more efficient and more readable. This is especially true
|
more efficient and more readable. This is especially true
|
||||||
for functional tests which might depend on command line
|
for functional tests which might depend on command line
|
||||||
options and a setup that needs to be shared across
|
options and a setup that needs to be shared across
|
||||||
a whole test run.
|
a whole test run.
|
||||||
|
|
||||||
per-test capturing of output, including subprocesses
|
per-test capturing of output, including subprocesses
|
||||||
----------------------------------------------------
|
----------------------------------------------------
|
||||||
|
|
||||||
By default, ``py.test`` captures all writes to stdout/stderr.
|
By default, ``py.test`` captures all writes to stdout/stderr.
|
||||||
Output from ``print`` statements as well as from subprocesses
|
Output from ``print`` statements as well as from subprocesses
|
||||||
is captured_. When a test fails, the associated captured outputs are shown.
|
is captured_. When a test fails, the associated captured outputs are shown.
|
||||||
This allows you to put debugging print statements in your code without
|
This allows you to put debugging print statements in your code without
|
||||||
being overwhelmed by all the output that might be generated by tests
|
being overwhelmed by all the output that might be generated by tests
|
||||||
that do not fail.
|
that do not fail.
|
||||||
|
|
||||||
.. _captured: plugin/capture.html
|
.. _captured: plugin/capture.html
|
||||||
|
|
||||||
assert with the ``assert`` statement
|
assert with the ``assert`` statement
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
``py.test`` allows to use the standard python
|
``py.test`` allows to use the standard python
|
||||||
``assert statement`` for verifying expectations
|
``assert statement`` for verifying expectations
|
||||||
and values in Python tests. For example, you can
|
and values in Python tests. For example, you can
|
||||||
write the following in your tests::
|
write the following in your tests::
|
||||||
|
|
||||||
assert hasattr(x, 'attribute')
|
assert hasattr(x, 'attribute')
|
||||||
|
|
||||||
to state that your object has a certain ``attribute``. In case this
|
to state that your object has a certain ``attribute``. In case this
|
||||||
assertion fails you will see the value of ``x``. Intermediate
|
assertion fails you will see the value of ``x``. Intermediate
|
||||||
values are computed by executing the assert expression a second time.
|
values are computed by executing the assert expression a second time.
|
||||||
If you execute code with side effects, e.g. read from a file like this::
|
If you execute code with side effects, e.g. read from a file like this::
|
||||||
|
|
||||||
assert f.read() != '...'
|
assert f.read() != '...'
|
||||||
|
|
||||||
then you may get a warning from pytest if that assertions
|
then you may get a warning from pytest if that assertions
|
||||||
first failed and then succeeded.
|
first failed and then succeeded.
|
||||||
|
|
||||||
asserting expected exceptions
|
asserting expected exceptions
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
In order to write assertions about exceptions, you can use
|
In order to write assertions about exceptions, you can use
|
||||||
``py.test.raises`` as a context manager like this:
|
``py.test.raises`` as a context manager like this:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
with py.test.raises(ZeroDivisionError):
|
with py.test.raises(ZeroDivisionError):
|
||||||
1 / 0
|
1 / 0
|
||||||
|
|
||||||
and if you need to have access to the actual exception info you may use:
|
and if you need to have access to the actual exception info you may use:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
with py.test.raises(RuntimeError) as excinfo:
|
with py.test.raises(RuntimeError) as excinfo:
|
||||||
def f():
|
def f():
|
||||||
f()
|
f()
|
||||||
f()
|
f()
|
||||||
|
|
||||||
# do checks related to excinfo.type, excinfo.value, excinfo.traceback
|
# do checks related to excinfo.type, excinfo.value, excinfo.traceback
|
||||||
|
|
||||||
If you want to write test code that works on Python2.4 as well,
|
If you want to write test code that works on Python2.4 as well,
|
||||||
you may also use two other ways to test for an expected exception:
|
you may also use two other ways to test for an expected exception:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
py.test.raises(ExpectedException, func, *args, **kwargs)
|
py.test.raises(ExpectedException, func, *args, **kwargs)
|
||||||
py.test.raises(ExpectedException, "func(*args, **kwargs)")
|
py.test.raises(ExpectedException, "func(*args, **kwargs)")
|
||||||
|
|
||||||
both of which execute the specified function with args and kwargs and
|
both of which execute the specified function with args and kwargs and
|
||||||
|
@ -175,21 +175,21 @@ from nightly runs, i.e. are detached from the actual test
|
||||||
running session. Here are `example tracebacks`_ for a number of failing
|
running session. Here are `example tracebacks`_ for a number of failing
|
||||||
test functions. You can modify traceback printing styles through the
|
test functions. You can modify traceback printing styles through the
|
||||||
command line. Using the `--pdb`` option you can automatically activate
|
command line. Using the `--pdb`` option you can automatically activate
|
||||||
a PDB `Python debugger`_ when a test fails.
|
a PDB `Python debugger`_ when a test fails.
|
||||||
|
|
||||||
skip or expect-to-fail a test
|
skip or expect-to-fail a test
|
||||||
======================================
|
======================================
|
||||||
|
|
||||||
py.test has a dedicated `skipping plugin`_ that allows to define
|
py.test has a dedicated `skipping plugin`_ that allows to define
|
||||||
|
|
||||||
* define "skip" outcomes indicating a platform or a
|
* define "skip" outcomes indicating a platform or a
|
||||||
dependency mismatch.
|
dependency mismatch.
|
||||||
|
|
||||||
* "xfail" outcomes indicating an "expected failure" either with
|
* "xfail" outcomes indicating an "expected failure" either with
|
||||||
with or without running a test.
|
with or without running a test.
|
||||||
|
|
||||||
* skip and xfail outcomes can be applied at module, class or method
|
* skip and xfail outcomes can be applied at module, class or method
|
||||||
level or even only for certain argument sets of a parametrized function.
|
level or even only for certain argument sets of a parametrized function.
|
||||||
|
|
||||||
.. _`skipping plugin`: plugin/skipping.html
|
.. _`skipping plugin`: plugin/skipping.html
|
||||||
.. _`funcargs mechanism`: funcargs.html
|
.. _`funcargs mechanism`: funcargs.html
|
||||||
|
@ -198,52 +198,52 @@ py.test has a dedicated `skipping plugin`_ that allows to define
|
||||||
.. _`xUnit style setup`: xunit_setup.html
|
.. _`xUnit style setup`: xunit_setup.html
|
||||||
.. _`pytest_nose`: plugin/nose.html
|
.. _`pytest_nose`: plugin/nose.html
|
||||||
|
|
||||||
select tests by keyword / test name search
|
select tests by keyword / test name search
|
||||||
=========================================================
|
=========================================================
|
||||||
|
|
||||||
.. _`selection by keyword`:
|
.. _`selection by keyword`:
|
||||||
|
|
||||||
You can selectively run tests by specifiying a keyword
|
You can selectively run tests by specifiying a keyword
|
||||||
on the command line. Examples::
|
on the command line. Examples::
|
||||||
|
|
||||||
py.test -k test_simple
|
py.test -k test_simple
|
||||||
py.test -k "-test_simple"
|
py.test -k "-test_simple"
|
||||||
|
|
||||||
will run all tests matching (or not matching) the
|
will run all tests matching (or not matching) the
|
||||||
"test_simple" keyword. Note that you need to quote
|
"test_simple" keyword. Note that you need to quote
|
||||||
the keyword if "-" is recognized as an indicator
|
the keyword if "-" is recognized as an indicator
|
||||||
for a commandline option. Lastly, you may use::
|
for a commandline option. Lastly, you may use::
|
||||||
|
|
||||||
py.test. -k "test_simple:"
|
py.test. -k "test_simple:"
|
||||||
|
|
||||||
which will run all tests after the expression has *matched once*, i.e.
|
which will run all tests after the expression has *matched once*, i.e.
|
||||||
all tests that are seen after a test that matches the "test_simple"
|
all tests that are seen after a test that matches the "test_simple"
|
||||||
keyword.
|
keyword.
|
||||||
|
|
||||||
By default, all filename parts and
|
By default, all filename parts and
|
||||||
class/function names of a test function are put into the set
|
class/function names of a test function are put into the set
|
||||||
of keywords for a given test. You can specify additional
|
of keywords for a given test. You can specify additional
|
||||||
kewords like this:
|
kewords like this:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
@py.test.mark.webtest
|
@py.test.mark.webtest
|
||||||
def test_send_http():
|
def test_send_http():
|
||||||
...
|
...
|
||||||
|
|
||||||
and then use those keywords to select tests. See the `pytest_keyword`_
|
and then use those keywords to select tests. See the `pytest_keyword`_
|
||||||
plugin for more information.
|
plugin for more information.
|
||||||
|
|
||||||
.. _`pytest_keyword`: plugin/mark.html
|
.. _`pytest_keyword`: plugin/mark.html
|
||||||
|
|
||||||
Looping on the failing test set
|
Looping on the failing test set
|
||||||
=======================================
|
=======================================
|
||||||
|
|
||||||
``py.test --looponfailing`` (implemented through the external
|
``py.test --looponfailing`` (implemented through the external
|
||||||
`pytest-xdist`_ plugin) allows to run a test suite,
|
`pytest-xdist`_ plugin) allows to run a test suite,
|
||||||
memorize all failures and then loop over the failing set
|
memorize all failures and then loop over the failing set
|
||||||
of tests until they all pass. It will re-start running
|
of tests until they all pass. It will re-start running
|
||||||
the tests when it detects file changes in your project.
|
the tests when it detects file changes in your project.
|
||||||
|
|
||||||
|
|
||||||
.. _`reStructured Text`: http://docutils.sourceforge.net
|
.. _`reStructured Text`: http://docutils.sourceforge.net
|
||||||
|
|
|
@ -2,36 +2,36 @@
|
||||||
**funcargs**: advanced test fixtures and parametrization
|
**funcargs**: advanced test fixtures and parametrization
|
||||||
==============================================================
|
==============================================================
|
||||||
|
|
||||||
.. contents::
|
.. contents::
|
||||||
:local:
|
:local:
|
||||||
:depth: 2
|
:depth: 2
|
||||||
|
|
||||||
what is a "funcarg"?
|
what is a "funcarg"?
|
||||||
=================================================
|
=================================================
|
||||||
|
|
||||||
A *funcarg* is the short name for "test function argument". Each python test function invocation may receive one or multiple function arguments. Function argument values can be created next to the test code or in separate test configuration files which allows test functions to remain ignorant of how its base test values are created. A test function can also be called multiple times with different sets of function arguments, allowing for arbitrary parametrization. A Funcarg parameter can be any value, a simple number or an application object.
|
A *funcarg* is the short name for "test function argument". Each python test function invocation may receive one or multiple function arguments. Function argument values can be created next to the test code or in separate test configuration files which allows test functions to remain ignorant of how its base test values are created. A test function can also be called multiple times with different sets of function arguments, allowing for arbitrary parametrization. A Funcarg parameter can be any value, a simple number or an application object.
|
||||||
|
|
||||||
.. _`contact possibilities`: ../contact.html
|
.. _`contact possibilities`: ../contact.html
|
||||||
.. _`parametrizing tests, generalized`: http://tetamap.wordpress.com/2009/05/13/parametrizing-python-tests-generalized/
|
.. _`parametrizing tests, generalized`: http://tetamap.wordpress.com/2009/05/13/parametrizing-python-tests-generalized/
|
||||||
|
|
||||||
.. _`blog post about the monkeypatch funcarg`: http://tetamap.wordpress.com/2009/03/03/monkeypatching-in-unit-tests-done-right/
|
.. _`blog post about the monkeypatch funcarg`: http://tetamap.wordpress.com/2009/03/03/monkeypatching-in-unit-tests-done-right/
|
||||||
.. _`xUnit style`: xunit_setup.html
|
.. _`xUnit style`: xunit_setup.html
|
||||||
|
|
||||||
|
|
||||||
.. _`funcarg factory`:
|
.. _`funcarg factory`:
|
||||||
.. _factory:
|
.. _factory:
|
||||||
|
|
||||||
funcarg factories: creating test function arguments
|
funcarg factories: creating test function arguments
|
||||||
==============================================================
|
==============================================================
|
||||||
|
|
||||||
Test functions can specify one ore more arguments ("funcargs")
|
Test functions can specify one ore more arguments ("funcargs")
|
||||||
and a test module or plugin can define factory functions that provide
|
and a test module or plugin can define factory functions that provide
|
||||||
the function argument. Let's look at a simple self-contained
|
the function argument. Let's look at a simple self-contained
|
||||||
example that you can put into a test module:
|
example that you can put into a test module:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
# ./test_simplefactory.py
|
# ./test_simplefactory.py
|
||||||
def pytest_funcarg__myfuncarg(request):
|
def pytest_funcarg__myfuncarg(request):
|
||||||
return 42
|
return 42
|
||||||
|
|
||||||
|
@ -62,65 +62,65 @@ If you run this with ``py.test test_simplefactory.py`` you see something like th
|
||||||
|
|
||||||
|
|
||||||
This means that the test function was called with a ``myfuncarg`` value
|
This means that the test function was called with a ``myfuncarg`` value
|
||||||
of ``42`` and the assert fails accordingly. Here is how py.test
|
of ``42`` and the assert fails accordingly. Here is how py.test
|
||||||
calls the test function:
|
calls the test function:
|
||||||
|
|
||||||
1. py.test discovers the ``test_function`` because of the ``test_`` prefix.
|
1. py.test discovers the ``test_function`` because of the ``test_`` prefix.
|
||||||
The test function needs a function argument named ``myfuncarg``.
|
The test function needs a function argument named ``myfuncarg``.
|
||||||
A matching factory function is discovered by looking for the
|
A matching factory function is discovered by looking for the
|
||||||
name ``pytest_funcarg__myfuncarg``.
|
name ``pytest_funcarg__myfuncarg``.
|
||||||
|
|
||||||
2. ``pytest_funcarg__myfuncarg(request)`` is called and
|
2. ``pytest_funcarg__myfuncarg(request)`` is called and
|
||||||
returns the value for ``myfuncarg``.
|
returns the value for ``myfuncarg``.
|
||||||
|
|
||||||
3. ``test_function(42)`` call is executed.
|
3. ``test_function(42)`` call is executed.
|
||||||
|
|
||||||
Note that if you misspell a function argument or want
|
Note that if you misspell a function argument or want
|
||||||
to use one that isn't available, you'll see an error
|
to use one that isn't available, you'll see an error
|
||||||
with a list of available function arguments. You can
|
with a list of available function arguments. You can
|
||||||
also issue::
|
also issue::
|
||||||
|
|
||||||
py.test --funcargs test_simplefactory.py
|
py.test --funcargs test_simplefactory.py
|
||||||
|
|
||||||
to see available function arguments (which you can also
|
to see available function arguments (which you can also
|
||||||
think of as "resources").
|
think of as "resources").
|
||||||
|
|
||||||
Factory functions receive a `request object`_
|
Factory functions receive a `request object`_
|
||||||
which they can use to register setup/teardown
|
which they can use to register setup/teardown
|
||||||
functions or access meta data about a test.
|
functions or access meta data about a test.
|
||||||
|
|
||||||
.. _`request object`:
|
.. _`request object`:
|
||||||
|
|
||||||
funcarg factory request objects
|
funcarg factory request objects
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
|
|
||||||
Request objects represents a handle on a specific python test function call. A request object is passed to a funcarg factory and provides access to test configuration and context as well as some `useful caching and finalization helpers`_. Here is a list of attributes:
|
Request objects represents a handle on a specific python test function call. A request object is passed to a funcarg factory and provides access to test configuration and context as well as some `useful caching and finalization helpers`_. Here is a list of attributes:
|
||||||
|
|
||||||
``request.function``: python function object requesting the argument
|
``request.function``: python function object requesting the argument
|
||||||
|
|
||||||
``request.cls``: class object where the test function is defined in or None.
|
``request.cls``: class object where the test function is defined in or None.
|
||||||
|
|
||||||
``request.module``: module object where the test function is defined in.
|
``request.module``: module object where the test function is defined in.
|
||||||
|
|
||||||
``request.config``: access to command line opts and general config
|
``request.config``: access to command line opts and general config
|
||||||
|
|
||||||
``request.param``: if exists was passed by a previous `metafunc.addcall`_
|
``request.param``: if exists was passed by a previous `metafunc.addcall`_
|
||||||
|
|
||||||
.. _`useful caching and finalization helpers`:
|
.. _`useful caching and finalization helpers`:
|
||||||
|
|
||||||
|
|
||||||
registering funcarg related finalizers/cleanup
|
registering funcarg related finalizers/cleanup
|
||||||
----------------------------------------------------
|
----------------------------------------------------
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
def addfinalizer(func):
|
def addfinalizer(func):
|
||||||
""" call a finalizer function when test function finishes. """
|
""" call a finalizer function when test function finishes. """
|
||||||
|
|
||||||
Calling ``request.addfinalizer()`` is useful for scheduling teardown
|
Calling ``request.addfinalizer()`` is useful for scheduling teardown
|
||||||
functions. Here is an example for providing a ``myfile``
|
functions. Here is an example for providing a ``myfile``
|
||||||
object that is to be closed when the execution of a
|
object that is to be closed when the execution of a
|
||||||
test function finishes.
|
test function finishes.
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
|
@ -133,85 +133,85 @@ test function finishes.
|
||||||
managing fixtures across test modules and test runs
|
managing fixtures across test modules and test runs
|
||||||
----------------------------------------------------------
|
----------------------------------------------------------
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
def cached_setup(setup, teardown=None, scope="module", extrakey=None):
|
def cached_setup(setup, teardown=None, scope="module", extrakey=None):
|
||||||
""" cache and return result of calling setup().
|
""" cache and return result of calling setup().
|
||||||
|
|
||||||
The requested argument name, the scope and the ``extrakey``
|
The requested argument name, the scope and the ``extrakey``
|
||||||
determine the cache key. The scope also determines when
|
determine the cache key. The scope also determines when
|
||||||
teardown(result) will be called. valid scopes are:
|
teardown(result) will be called. valid scopes are:
|
||||||
scope == 'function': when the single test function run finishes.
|
scope == 'function': when the single test function run finishes.
|
||||||
scope == 'module': when tests in a different module are run
|
scope == 'module': when tests in a different module are run
|
||||||
scope == 'session': when tests of the session have run.
|
scope == 'session': when tests of the session have run.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
Calling ``request.cached_setup()`` helps you to manage fixture
|
Calling ``request.cached_setup()`` helps you to manage fixture
|
||||||
objects across several scopes. For example, for creating a Database object
|
objects across several scopes. For example, for creating a Database object
|
||||||
that is to be setup only once during a test session you can use the helper
|
that is to be setup only once during a test session you can use the helper
|
||||||
like this:
|
like this:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
def pytest_funcarg__database(request):
|
def pytest_funcarg__database(request):
|
||||||
return request.cached_setup(
|
return request.cached_setup(
|
||||||
setup=lambda: Database("..."),
|
setup=lambda: Database("..."),
|
||||||
teardown=lambda val: val.close(),
|
teardown=lambda val: val.close(),
|
||||||
scope="session"
|
scope="session"
|
||||||
)
|
)
|
||||||
|
|
||||||
dynamically applying a marker
|
dynamically applying a marker
|
||||||
---------------------------------------------
|
---------------------------------------------
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
def applymarker(self, marker):
|
def applymarker(self, marker):
|
||||||
""" apply a marker to a test function invocation.
|
""" apply a marker to a test function invocation.
|
||||||
|
|
||||||
The 'marker' must be created with py.test.mark.* XYZ.
|
The 'marker' must be created with py.test.mark.* XYZ.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
``request.applymarker(marker)`` will mark the test invocation
|
``request.applymarker(marker)`` will mark the test invocation
|
||||||
with the given marker. For example, if your funcarg factory provides
|
with the given marker. For example, if your funcarg factory provides
|
||||||
values which may cause a test function to fail you can call
|
values which may cause a test function to fail you can call
|
||||||
``request.applymarker(py.test.mark.xfail(reason='flaky config'))``
|
``request.applymarker(py.test.mark.xfail(reason='flaky config'))``
|
||||||
and this will cause the test to not show tracebacks. See xfail_
|
and this will cause the test to not show tracebacks. See xfail_
|
||||||
for details.
|
for details.
|
||||||
|
|
||||||
.. _`xfail`: plugin/skipping.html#xfail
|
.. _`xfail`: plugin/skipping.html#xfail
|
||||||
|
|
||||||
requesting values of other funcargs
|
requesting values of other funcargs
|
||||||
---------------------------------------------
|
---------------------------------------------
|
||||||
|
|
||||||
.. sourcecode:: python
|
|
||||||
|
|
||||||
def getfuncargvalue(name):
|
|
||||||
""" Lookup and call function argument factory for the given name.
|
|
||||||
Each function argument is only created once per function setup.
|
|
||||||
"""
|
|
||||||
|
|
||||||
``request.getfuncargvalue(name)`` calls another funcarg factory function.
|
|
||||||
You can use this function if you want to `decorate a funcarg`_, i.e.
|
|
||||||
you want to provide the "normal" value but add something
|
|
||||||
extra. If a factory cannot be found a ``request.Error``
|
|
||||||
exception will be raised.
|
|
||||||
|
|
||||||
.. _`test generators`:
|
|
||||||
.. _`parametrizing-tests`:
|
|
||||||
|
|
||||||
generating parametrized tests
|
|
||||||
===========================================================
|
|
||||||
|
|
||||||
You can parametrize multiple runs of the same test
|
|
||||||
function by adding new test function calls with different
|
|
||||||
function argument values. Let's look at a simple self-contained
|
|
||||||
example:
|
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
# ./test_example.py
|
def getfuncargvalue(name):
|
||||||
|
""" Lookup and call function argument factory for the given name.
|
||||||
|
Each function argument is only created once per function setup.
|
||||||
|
"""
|
||||||
|
|
||||||
|
``request.getfuncargvalue(name)`` calls another funcarg factory function.
|
||||||
|
You can use this function if you want to `decorate a funcarg`_, i.e.
|
||||||
|
you want to provide the "normal" value but add something
|
||||||
|
extra. If a factory cannot be found a ``request.Error``
|
||||||
|
exception will be raised.
|
||||||
|
|
||||||
|
.. _`test generators`:
|
||||||
|
.. _`parametrizing-tests`:
|
||||||
|
|
||||||
|
generating parametrized tests
|
||||||
|
===========================================================
|
||||||
|
|
||||||
|
You can parametrize multiple runs of the same test
|
||||||
|
function by adding new test function calls with different
|
||||||
|
function argument values. Let's look at a simple self-contained
|
||||||
|
example:
|
||||||
|
|
||||||
|
.. sourcecode:: python
|
||||||
|
|
||||||
|
# ./test_example.py
|
||||||
def pytest_generate_tests(metafunc):
|
def pytest_generate_tests(metafunc):
|
||||||
if "numiter" in metafunc.funcargnames:
|
if "numiter" in metafunc.funcargnames:
|
||||||
for i in range(10):
|
for i in range(10):
|
||||||
metafunc.addcall(funcargs=dict(numiter=i))
|
metafunc.addcall(funcargs=dict(numiter=i))
|
||||||
|
|
||||||
|
@ -243,108 +243,108 @@ If you run this with ``py.test test_example.py`` you'll get:
|
||||||
Here is what happens in detail:
|
Here is what happens in detail:
|
||||||
|
|
||||||
1. ``pytest_generate_tests(metafunc)`` hook is called once for each test
|
1. ``pytest_generate_tests(metafunc)`` hook is called once for each test
|
||||||
function. It adds ten new function calls with explicit function arguments.
|
function. It adds ten new function calls with explicit function arguments.
|
||||||
|
|
||||||
2. **execute tests**: ``test_func(numiter)`` is called ten times with
|
2. **execute tests**: ``test_func(numiter)`` is called ten times with
|
||||||
ten different arguments.
|
ten different arguments.
|
||||||
|
|
||||||
.. _`metafunc object`:
|
.. _`metafunc object`:
|
||||||
|
|
||||||
test generators and metafunc objects
|
test generators and metafunc objects
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
|
|
||||||
metafunc objects are passed to the ``pytest_generate_tests`` hook.
|
metafunc objects are passed to the ``pytest_generate_tests`` hook.
|
||||||
They help to inspect a testfunction and to generate tests
|
They help to inspect a testfunction and to generate tests
|
||||||
according to test configuration or values specified
|
according to test configuration or values specified
|
||||||
in the class or module where a test function is defined:
|
in the class or module where a test function is defined:
|
||||||
|
|
||||||
``metafunc.funcargnames``: set of required function arguments for given function
|
``metafunc.funcargnames``: set of required function arguments for given function
|
||||||
|
|
||||||
``metafunc.function``: underlying python test function
|
``metafunc.function``: underlying python test function
|
||||||
|
|
||||||
``metafunc.cls``: class object where the test function is defined in or None.
|
``metafunc.cls``: class object where the test function is defined in or None.
|
||||||
|
|
||||||
``metafunc.module``: the module object where the test function is defined in.
|
``metafunc.module``: the module object where the test function is defined in.
|
||||||
|
|
||||||
``metafunc.config``: access to command line opts and general config
|
``metafunc.config``: access to command line opts and general config
|
||||||
|
|
||||||
|
|
||||||
.. _`metafunc.addcall`:
|
.. _`metafunc.addcall`:
|
||||||
|
|
||||||
the ``metafunc.addcall()`` method
|
the ``metafunc.addcall()`` method
|
||||||
-----------------------------------------------
|
-----------------------------------------------
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
def addcall(funcargs={}, id=None, param=None):
|
def addcall(funcargs={}, id=None, param=None):
|
||||||
""" trigger a new test function call. """
|
""" trigger a new test function call. """
|
||||||
|
|
||||||
``funcargs`` can be a dictionary of argument names
|
``funcargs`` can be a dictionary of argument names
|
||||||
mapped to values - providing it is called *direct parametrization*.
|
mapped to values - providing it is called *direct parametrization*.
|
||||||
|
|
||||||
If you provide an `id`` it will be used for reporting
|
If you provide an `id`` it will be used for reporting
|
||||||
and identification purposes. If you don't supply an `id`
|
and identification purposes. If you don't supply an `id`
|
||||||
the stringified counter of the list of added calls will be used.
|
the stringified counter of the list of added calls will be used.
|
||||||
``id`` values needs to be unique between all
|
``id`` values needs to be unique between all
|
||||||
invocations for a given test function.
|
invocations for a given test function.
|
||||||
|
|
||||||
``param`` if specified will be seen by any
|
``param`` if specified will be seen by any
|
||||||
`funcarg factory`_ as a ``request.param`` attribute.
|
`funcarg factory`_ as a ``request.param`` attribute.
|
||||||
Setting it is called *indirect parametrization*.
|
Setting it is called *indirect parametrization*.
|
||||||
|
|
||||||
Indirect parametrization is preferable if test values are
|
Indirect parametrization is preferable if test values are
|
||||||
expensive to setup or can only be created in certain environments.
|
expensive to setup or can only be created in certain environments.
|
||||||
Test generators and thus ``addcall()`` invocations are performed
|
Test generators and thus ``addcall()`` invocations are performed
|
||||||
during test collection which is separate from the actual test
|
during test collection which is separate from the actual test
|
||||||
setup and test run phase. With distributed testing collection
|
setup and test run phase. With distributed testing collection
|
||||||
and test setup/run happens in different process.
|
and test setup/run happens in different process.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
.. _`tutorial examples`:
|
.. _`tutorial examples`:
|
||||||
|
|
||||||
Tutorial Examples
|
Tutorial Examples
|
||||||
=======================================
|
=======================================
|
||||||
|
|
||||||
To see how you can implement custom paramtrization schemes,
|
To see how you can implement custom paramtrization schemes,
|
||||||
see e.g. `parametrizing tests, generalized`_ (blog post).
|
see e.g. `parametrizing tests, generalized`_ (blog post).
|
||||||
|
|
||||||
To enable creation of test support code that can flexibly
|
To enable creation of test support code that can flexibly
|
||||||
register setup/teardown functions see the `blog post about
|
register setup/teardown functions see the `blog post about
|
||||||
the monkeypatch funcarg`_.
|
the monkeypatch funcarg`_.
|
||||||
|
|
||||||
If you find issues or have further suggestions for improving
|
If you find issues or have further suggestions for improving
|
||||||
the mechanism you are welcome to checkout `contact possibilities`_ page.
|
the mechanism you are welcome to checkout `contact possibilities`_ page.
|
||||||
|
|
||||||
.. _`application setup tutorial example`:
|
.. _`application setup tutorial example`:
|
||||||
.. _appsetup:
|
.. _appsetup:
|
||||||
|
|
||||||
application specific test setup and fixtures
|
application specific test setup and fixtures
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
Here is a basic useful step-wise example for handling application
|
Here is a basic useful step-wise example for handling application
|
||||||
specific test setup. The goal is to have one place where we have the
|
specific test setup. The goal is to have one place where we have the
|
||||||
glue and test support code for bootstrapping and configuring application objects and allow
|
glue and test support code for bootstrapping and configuring application objects and allow
|
||||||
test modules and test functions to stay ignorant of involved details.
|
test modules and test functions to stay ignorant of involved details.
|
||||||
|
|
||||||
step 1: use and implement a test/app-specific "mysetup"
|
step 1: use and implement a test/app-specific "mysetup"
|
||||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
Let's write a simple test function living in a test file
|
Let's write a simple test function living in a test file
|
||||||
``test_sample.py`` that uses a ``mysetup`` funcarg for accessing test
|
``test_sample.py`` that uses a ``mysetup`` funcarg for accessing test
|
||||||
specific setup.
|
specific setup.
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
# ./test_sample.py
|
# ./test_sample.py
|
||||||
def test_answer(mysetup):
|
def test_answer(mysetup):
|
||||||
app = mysetup.myapp()
|
app = mysetup.myapp()
|
||||||
answer = app.question()
|
answer = app.question()
|
||||||
assert answer == 42
|
assert answer == 42
|
||||||
|
|
||||||
To run this test py.test needs to find and call a factory to
|
To run this test py.test needs to find and call a factory to
|
||||||
obtain the required ``mysetup`` function argument. The test
|
obtain the required ``mysetup`` function argument. The test
|
||||||
function interacts with the provided application specific setup.
|
function interacts with the provided application specific setup.
|
||||||
|
|
||||||
To provide the ``mysetup`` function argument we write down
|
To provide the ``mysetup`` function argument we write down
|
||||||
a factory method in a `local plugin`_ by putting the
|
a factory method in a `local plugin`_ by putting the
|
||||||
|
@ -352,8 +352,8 @@ following code into a local ``conftest.py``:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
# ./conftest.py
|
# ./conftest.py
|
||||||
|
|
||||||
from myapp import MyApp
|
from myapp import MyApp
|
||||||
|
|
||||||
def pytest_funcarg__mysetup(request):
|
def pytest_funcarg__mysetup(request):
|
||||||
|
@ -362,7 +362,7 @@ following code into a local ``conftest.py``:
|
||||||
class MySetup:
|
class MySetup:
|
||||||
def myapp(self):
|
def myapp(self):
|
||||||
return MyApp()
|
return MyApp()
|
||||||
|
|
||||||
To run the example we represent our application by putting a pseudo MyApp object into ``myapp.py``:
|
To run the example we represent our application by putting a pseudo MyApp object into ``myapp.py``:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
@ -397,29 +397,29 @@ show this failure:
|
||||||
test_sample.py:5: AssertionError
|
test_sample.py:5: AssertionError
|
||||||
====================== 1 failed in 0.11 seconds =======================
|
====================== 1 failed in 0.11 seconds =======================
|
||||||
|
|
||||||
This means that our ``mysetup`` object was successfully instantiated,
|
This means that our ``mysetup`` object was successfully instantiated,
|
||||||
we asked it to provide an application instance and checking
|
we asked it to provide an application instance and checking
|
||||||
its ``question`` method resulted in the wrong answer. If you are
|
its ``question`` method resulted in the wrong answer. If you are
|
||||||
confused as to what the concrete question or answers actually mean,
|
confused as to what the concrete question or answers actually mean,
|
||||||
please see here_ :) Otherwise proceed to step 2.
|
please see here_ :) Otherwise proceed to step 2.
|
||||||
|
|
||||||
.. _here: http://uncyclopedia.wikia.com/wiki/The_Hitchhiker's_Guide_to_the_Galaxy
|
.. _here: http://uncyclopedia.wikia.com/wiki/The_Hitchhiker's_Guide_to_the_Galaxy
|
||||||
.. _`local plugin`: customize.html#local-plugin
|
.. _`local plugin`: customize.html#local-plugin
|
||||||
|
|
||||||
.. _`tut-cmdlineoption`:
|
.. _`tut-cmdlineoption`:
|
||||||
|
|
||||||
step 2: adding a command line option
|
step 2: adding a command line option
|
||||||
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
If you provide a "funcarg" from a plugin you can easily make methods
|
If you provide a "funcarg" from a plugin you can easily make methods
|
||||||
depend on command line options or environment settings.
|
depend on command line options or environment settings.
|
||||||
To add a command line option we update the conftest.py of
|
To add a command line option we update the conftest.py of
|
||||||
the previous example to add a command line option
|
the previous example to add a command line option
|
||||||
and to offer a new mysetup method:
|
and to offer a new mysetup method:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
# ./conftest.py
|
# ./conftest.py
|
||||||
import py
|
import py
|
||||||
from myapp import MyApp
|
from myapp import MyApp
|
||||||
|
|
||||||
|
@ -429,11 +429,11 @@ and to offer a new mysetup method:
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
parser.addoption("--ssh", action="store", default=None,
|
parser.addoption("--ssh", action="store", default=None,
|
||||||
help="specify ssh host to run tests with")
|
help="specify ssh host to run tests with")
|
||||||
|
|
||||||
|
|
||||||
class MySetup:
|
class MySetup:
|
||||||
def __init__(self, request):
|
def __init__(self, request):
|
||||||
self.config = request.config
|
self.config = request.config
|
||||||
|
|
||||||
def myapp(self):
|
def myapp(self):
|
||||||
return MyApp()
|
return MyApp()
|
||||||
|
@ -449,13 +449,13 @@ Now any test function can use the ``mysetup.getsshconnection()`` method like thi
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
# ./test_ssh.py
|
# ./test_ssh.py
|
||||||
class TestClass:
|
class TestClass:
|
||||||
def test_function(self, mysetup):
|
def test_function(self, mysetup):
|
||||||
conn = mysetup.getsshconnection()
|
conn = mysetup.getsshconnection()
|
||||||
# work with conn
|
# work with conn
|
||||||
|
|
||||||
Running ``py.test test_ssh.py`` without specifying a command line option will result in a skipped test_function:
|
Running ``py.test test_ssh.py`` without specifying a command line option will result in a skipped test_function:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
|
@ -469,21 +469,21 @@ Running ``py.test test_ssh.py`` without specifying a command line option will re
|
||||||
conftest.py:23: [1] Skipped: 'specify ssh host with --ssh'
|
conftest.py:23: [1] Skipped: 'specify ssh host with --ssh'
|
||||||
====================== 1 skipped in 0.11 seconds ======================
|
====================== 1 skipped in 0.11 seconds ======================
|
||||||
|
|
||||||
Note especially how the test function could stay clear knowing about how to construct test state values or when to skip and with what message. The test function can concentrate on actual test code and test state factories can interact with execution of tests.
|
Note especially how the test function could stay clear knowing about how to construct test state values or when to skip and with what message. The test function can concentrate on actual test code and test state factories can interact with execution of tests.
|
||||||
|
|
||||||
If you specify a command line option like ``py.test --ssh=python.org`` the test will get un-skipped and actually execute.
|
If you specify a command line option like ``py.test --ssh=python.org`` the test will get un-skipped and actually execute.
|
||||||
|
|
||||||
.. _`accept example`:
|
.. _`accept example`:
|
||||||
|
|
||||||
example: specifying and selecting acceptance tests
|
example: specifying and selecting acceptance tests
|
||||||
--------------------------------------------------------------
|
--------------------------------------------------------------
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
# ./conftest.py
|
# ./conftest.py
|
||||||
def pytest_option(parser):
|
def pytest_option(parser):
|
||||||
group = parser.getgroup("myproject")
|
group = parser.getgroup("myproject")
|
||||||
group.addoption("-A", dest="acceptance", action="store_true",
|
group.addoption("-A", dest="acceptance", action="store_true",
|
||||||
help="run (slow) acceptance tests")
|
help="run (slow) acceptance tests")
|
||||||
|
|
||||||
def pytest_funcarg__accept(request):
|
def pytest_funcarg__accept(request):
|
||||||
|
@ -494,13 +494,13 @@ example: specifying and selecting acceptance tests
|
||||||
if not request.config.option.acceptance:
|
if not request.config.option.acceptance:
|
||||||
py.test.skip("specify -A to run acceptance tests")
|
py.test.skip("specify -A to run acceptance tests")
|
||||||
self.tmpdir = request.config.mktemp(request.function.__name__, numbered=True)
|
self.tmpdir = request.config.mktemp(request.function.__name__, numbered=True)
|
||||||
|
|
||||||
def run(self, cmd):
|
def run(self, cmd):
|
||||||
""" called by test code to execute an acceptance test. """
|
""" called by test code to execute an acceptance test. """
|
||||||
self.tmpdir.chdir()
|
self.tmpdir.chdir()
|
||||||
return py.process.cmdexec(cmd)
|
return py.process.cmdexec(cmd)
|
||||||
|
|
||||||
|
|
||||||
and the actual test function example:
|
and the actual test function example:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
@ -509,45 +509,45 @@ and the actual test function example:
|
||||||
accept.tmpdir.mkdir("somesub")
|
accept.tmpdir.mkdir("somesub")
|
||||||
result = accept.run("ls -la")
|
result = accept.run("ls -la")
|
||||||
assert "somesub" in result
|
assert "somesub" in result
|
||||||
|
|
||||||
If you run this test without specifying a command line option
|
If you run this test without specifying a command line option
|
||||||
the test will get skipped with an appropriate message. Otherwise
|
the test will get skipped with an appropriate message. Otherwise
|
||||||
you can start to add convenience and test support methods
|
you can start to add convenience and test support methods
|
||||||
to your AcceptFuncarg and drive running of tools or
|
to your AcceptFuncarg and drive running of tools or
|
||||||
applications and provide ways to do assertions about
|
applications and provide ways to do assertions about
|
||||||
the output.
|
the output.
|
||||||
|
|
||||||
.. _`decorate a funcarg`:
|
.. _`decorate a funcarg`:
|
||||||
|
|
||||||
example: decorating a funcarg in a test module
|
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 module:
|
extend the `accept example`_ by putting this in our test module:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
def pytest_funcarg__accept(request):
|
def pytest_funcarg__accept(request):
|
||||||
# call the next factory (living in our conftest.py)
|
# call the next factory (living in our conftest.py)
|
||||||
arg = request.getfuncargvalue("accept")
|
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
|
||||||
|
|
||||||
class TestSpecialAcceptance:
|
class TestSpecialAcceptance:
|
||||||
def test_sometest(self, accept):
|
def test_sometest(self, accept):
|
||||||
assert accept.tmpdir.join("special").check()
|
assert accept.tmpdir.join("special").check()
|
||||||
|
|
||||||
Our module level factory will be invoked first and it can
|
Our module level factory will be invoked first and it can
|
||||||
ask its request object to call the next factory and then
|
ask its request object to call the next factory and then
|
||||||
decorate its result. This mechanism allows us to stay
|
decorate its result. This mechanism allows us to stay
|
||||||
ignorant of how/where the function argument is provided -
|
ignorant of how/where the function argument is provided -
|
||||||
in our example from a `conftest plugin`_.
|
in our example from a `conftest plugin`_.
|
||||||
|
|
||||||
sidenote: the temporary directory used here are instances of
|
sidenote: the temporary directory used here are instances of
|
||||||
the `py.path.local`_ class which provides many of the os.path
|
the `py.path.local`_ class which provides many of the os.path
|
||||||
methods in a convenient way.
|
methods in a convenient way.
|
||||||
|
|
||||||
.. _`py.path.local`: ../path.html#local
|
.. _`py.path.local`: ../path.html#local
|
||||||
.. _`conftest plugin`: customize.html#conftestplugin
|
.. _`conftest plugin`: customize.html#conftestplugin
|
||||||
|
|
|
@ -1,19 +1,19 @@
|
||||||
=======================================
|
=======================================
|
||||||
py.test documentation index
|
py.test documentation index
|
||||||
=======================================
|
=======================================
|
||||||
|
|
||||||
|
|
||||||
features_: overview and discussion of features.
|
features_: overview and discussion of features.
|
||||||
|
|
||||||
quickstart_: getting started with writing a simple test.
|
quickstart_: getting started with writing a simple test.
|
||||||
|
|
||||||
`talks, tutorials, examples`_: tutorial examples, slides
|
`talks, tutorials, examples`_: tutorial examples, slides
|
||||||
|
|
||||||
funcargs_: powerful parametrized test function setup
|
funcargs_: powerful parametrized test function setup
|
||||||
|
|
||||||
`plugins`_: list of available plugins with usage examples and feature details.
|
`plugins`_: list of available plugins with usage examples and feature details.
|
||||||
|
|
||||||
customize_: configuration, customization, extensions
|
customize_: configuration, customization, extensions
|
||||||
|
|
||||||
changelog_: history of changes covering last releases
|
changelog_: history of changes covering last releases
|
||||||
|
|
||||||
|
|
|
@ -1,13 +1,13 @@
|
||||||
|
|
||||||
Mission
|
Mission
|
||||||
====================================
|
====================================
|
||||||
|
|
||||||
py.test strives to make testing a fun and no-boilerplate effort.
|
py.test strives to make testing a fun and no-boilerplate effort.
|
||||||
|
|
||||||
The tool is distributed as part of the `py` package which contains supporting APIs that
|
The tool is distributed as part of the `py` package which contains supporting APIs that
|
||||||
are also useable independently. The project independent ``py.test`` command line tool helps you to:
|
are also useable independently. The project independent ``py.test`` command line tool helps you to:
|
||||||
|
|
||||||
* rapidly collect and run tests
|
* rapidly collect and run tests
|
||||||
* run unit- or doctests, functional or integration tests
|
* run unit- or doctests, functional or integration tests
|
||||||
* distribute tests to multiple environments
|
* distribute tests to multiple environments
|
||||||
* use local or global plugins for custom test types and setup
|
* use local or global plugins for custom test types and setup
|
||||||
|
|
|
@ -6,27 +6,27 @@ configurable per-test stdout/stderr capturing mechanisms.
|
||||||
.. contents::
|
.. contents::
|
||||||
:local:
|
:local:
|
||||||
|
|
||||||
This plugin captures stdout/stderr output for each test separately.
|
This plugin captures stdout/stderr output for each test separately.
|
||||||
In case of test failures this captured output is shown grouped
|
In case of test failures this captured output is shown grouped
|
||||||
togtther with the test.
|
togtther with the test.
|
||||||
|
|
||||||
The plugin also provides test function arguments that help to
|
The plugin also provides test function arguments that help to
|
||||||
assert stdout/stderr output from within your tests, see the
|
assert stdout/stderr output from within your tests, see the
|
||||||
`funcarg example`_.
|
`funcarg example`_.
|
||||||
|
|
||||||
|
|
||||||
Capturing of input/output streams during tests
|
Capturing of input/output streams during tests
|
||||||
---------------------------------------------------
|
---------------------------------------------------
|
||||||
|
|
||||||
By default ``sys.stdout`` and ``sys.stderr`` are substituted with
|
By default ``sys.stdout`` and ``sys.stderr`` are substituted with
|
||||||
temporary streams during the execution of tests and setup/teardown code.
|
temporary streams during the execution of tests and setup/teardown code.
|
||||||
During the whole testing process it will re-use the same temporary
|
During the whole testing process it will re-use the same temporary
|
||||||
streams allowing to play well with the logging module which easily
|
streams allowing to play well with the logging module which easily
|
||||||
takes ownership on these streams.
|
takes ownership on these streams.
|
||||||
|
|
||||||
Also, 'sys.stdin' is substituted with a file-like "null" object that
|
Also, 'sys.stdin' is substituted with a file-like "null" object that
|
||||||
does not return any values. This is to immediately error out
|
does not return any values. This is to immediately error out
|
||||||
on tests that wait on reading something from stdin.
|
on tests that wait on reading something from stdin.
|
||||||
|
|
||||||
You can influence output capturing mechanisms from the command line::
|
You can influence output capturing mechanisms from the command line::
|
||||||
|
|
||||||
|
@ -39,34 +39,34 @@ If you set capturing values in a conftest file like this::
|
||||||
# conftest.py
|
# conftest.py
|
||||||
option_capture = 'fd'
|
option_capture = 'fd'
|
||||||
|
|
||||||
then all tests in that directory will execute with "fd" style capturing.
|
then all tests in that directory will execute with "fd" style capturing.
|
||||||
|
|
||||||
sys-level capturing
|
sys-level capturing
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
|
|
||||||
Capturing on 'sys' level means that ``sys.stdout`` and ``sys.stderr``
|
Capturing on 'sys' level means that ``sys.stdout`` and ``sys.stderr``
|
||||||
will be replaced with in-memory files (``py.io.TextIO`` to be precise)
|
will be replaced with in-memory files (``py.io.TextIO`` to be precise)
|
||||||
that capture writes and decode non-unicode strings to a unicode object
|
that capture writes and decode non-unicode strings to a unicode object
|
||||||
(using a default, usually, UTF-8, encoding).
|
(using a default, usually, UTF-8, encoding).
|
||||||
|
|
||||||
FD-level capturing and subprocesses
|
FD-level capturing and subprocesses
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
|
|
||||||
The ``fd`` based method means that writes going to system level files
|
The ``fd`` based method means that writes going to system level files
|
||||||
based on the standard file descriptors will be captured, for example
|
based on the standard file descriptors will be captured, for example
|
||||||
writes such as ``os.write(1, 'hello')`` will be captured properly.
|
writes such as ``os.write(1, 'hello')`` will be captured properly.
|
||||||
Capturing on fd-level will include output generated from
|
Capturing on fd-level will include output generated from
|
||||||
any subprocesses created during a test.
|
any subprocesses created during a test.
|
||||||
|
|
||||||
.. _`funcarg example`:
|
.. _`funcarg example`:
|
||||||
|
|
||||||
Example Usage of the capturing Function arguments
|
Example Usage of the capturing Function arguments
|
||||||
---------------------------------------------------
|
---------------------------------------------------
|
||||||
|
|
||||||
You can use the `capsys funcarg`_ and `capfd funcarg`_ to
|
You can use the `capsys funcarg`_ and `capfd funcarg`_ to
|
||||||
capture writes to stdout and stderr streams. Using the
|
capture writes to stdout and stderr streams. Using the
|
||||||
funcargs frees your test from having to care about setting/resetting
|
funcargs frees your test from having to care about setting/resetting
|
||||||
the old streams and also interacts well with py.test's own
|
the old streams and also interacts well with py.test's own
|
||||||
per-test capturing. Here is an example test function:
|
per-test capturing. Here is an example test function:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
@ -79,12 +79,12 @@ per-test capturing. Here is an example test function:
|
||||||
assert err == "world\n"
|
assert err == "world\n"
|
||||||
print "next"
|
print "next"
|
||||||
out, err = capsys.readouterr()
|
out, err = capsys.readouterr()
|
||||||
assert out == "next\n"
|
assert out == "next\n"
|
||||||
|
|
||||||
The ``readouterr()`` call snapshots the output so far -
|
The ``readouterr()`` call snapshots the output so far -
|
||||||
and capturing will be continued. After the test
|
and capturing will be continued. After the test
|
||||||
function finishes the original streams will
|
function finishes the original streams will
|
||||||
be restored. If you want to capture on
|
be restored. If you want to capture on
|
||||||
the filedescriptor level you can use the ``capfd`` function
|
the filedescriptor level you can use the ``capfd`` function
|
||||||
argument which offers the same interface.
|
argument which offers the same interface.
|
||||||
|
|
||||||
|
@ -94,9 +94,9 @@ argument which offers the same interface.
|
||||||
the 'capsys' test function argument
|
the 'capsys' test function argument
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
|
|
||||||
captures writes to sys.stdout/sys.stderr and makes
|
captures writes to sys.stdout/sys.stderr and makes
|
||||||
them available successively via a ``capsys.readouterr()`` method
|
them available successively via a ``capsys.readouterr()`` method
|
||||||
which returns a ``(out, err)`` tuple of captured snapshot strings.
|
which returns a ``(out, err)`` tuple of captured snapshot strings.
|
||||||
|
|
||||||
.. _`capfd funcarg`:
|
.. _`capfd funcarg`:
|
||||||
|
|
||||||
|
@ -104,11 +104,11 @@ which returns a ``(out, err)`` tuple of captured snapshot strings.
|
||||||
the 'capfd' test function argument
|
the 'capfd' test function argument
|
||||||
----------------------------------
|
----------------------------------
|
||||||
|
|
||||||
captures writes to file descriptors 1 and 2 and makes
|
captures writes to file descriptors 1 and 2 and makes
|
||||||
snapshotted ``(out, err)`` string tuples available
|
snapshotted ``(out, err)`` string tuples available
|
||||||
via the ``capsys.readouterr()`` method. If the underlying
|
via the ``capsys.readouterr()`` method. If the underlying
|
||||||
platform does not have ``os.dup`` (e.g. Jython) tests using
|
platform does not have ``os.dup`` (e.g. Jython) tests using
|
||||||
this funcarg will automatically skip.
|
this funcarg will automatically skip.
|
||||||
|
|
||||||
command line options
|
command line options
|
||||||
--------------------
|
--------------------
|
||||||
|
@ -123,10 +123,10 @@ Start improving this plugin in 30 seconds
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
|
|
||||||
1. Download `pytest_capture.py`_ plugin source code
|
1. Download `pytest_capture.py`_ plugin source code
|
||||||
2. put it somewhere as ``pytest_capture.py`` into your import path
|
2. put it somewhere as ``pytest_capture.py`` into your import path
|
||||||
3. a subsequent ``py.test`` run will use your local version
|
3. a subsequent ``py.test`` run will use your local version
|
||||||
|
|
||||||
Checkout customize_, other plugins_ or `get in contact`_.
|
Checkout customize_, other plugins_ or `get in contact`_.
|
||||||
|
|
||||||
.. include:: links.txt
|
.. include:: links.txt
|
||||||
|
|
|
@ -9,10 +9,10 @@ capture output of logging module.
|
||||||
Installation
|
Installation
|
||||||
------------
|
------------
|
||||||
|
|
||||||
You can install the `pytest-capturelog pypi`_ package
|
You can install the `pytest-capturelog pypi`_ package
|
||||||
with pip::
|
with pip::
|
||||||
|
|
||||||
pip install pytest-capturelog
|
pip install pytest-capturelog
|
||||||
|
|
||||||
or with easy install::
|
or with easy install::
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ Write and report coverage data with the 'coverage' package.
|
||||||
.. contents::
|
.. contents::
|
||||||
:local:
|
:local:
|
||||||
|
|
||||||
Original code by Ross Lawley.
|
Original code by Ross Lawley.
|
||||||
|
|
||||||
Requires Ned Batchelder's excellent coverage:
|
Requires Ned Batchelder's excellent coverage:
|
||||||
http://nedbatchelder.com/code/coverage/
|
http://nedbatchelder.com/code/coverage/
|
||||||
|
|
|
@ -9,7 +9,7 @@ collect and execute doctests from modules and test files.
|
||||||
Usage
|
Usage
|
||||||
-------------
|
-------------
|
||||||
|
|
||||||
By default all files matching the ``test*.txt`` pattern will
|
By default all files matching the ``test*.txt`` pattern will
|
||||||
be run through the python standard ``doctest`` module. Issue::
|
be run through the python standard ``doctest`` module. Issue::
|
||||||
|
|
||||||
py.test --doctest-glob='*.rst'
|
py.test --doctest-glob='*.rst'
|
||||||
|
@ -19,10 +19,10 @@ tests in all python modules (including regular python test modules)::
|
||||||
|
|
||||||
py.test --doctest-modules
|
py.test --doctest-modules
|
||||||
|
|
||||||
You can also make these changes permanent in your project by
|
You can also make these changes permanent in your project by
|
||||||
putting them into a conftest.py file like this::
|
putting them into a conftest.py file like this::
|
||||||
|
|
||||||
# content of conftest.py
|
# content of conftest.py
|
||||||
option_doctestmodules = True
|
option_doctestmodules = True
|
||||||
option_doctestglob = "*.rst"
|
option_doctestglob = "*.rst"
|
||||||
|
|
||||||
|
@ -39,10 +39,10 @@ Start improving this plugin in 30 seconds
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
|
|
||||||
1. Download `pytest_doctest.py`_ plugin source code
|
1. Download `pytest_doctest.py`_ plugin source code
|
||||||
2. put it somewhere as ``pytest_doctest.py`` into your import path
|
2. put it somewhere as ``pytest_doctest.py`` into your import path
|
||||||
3. a subsequent ``py.test`` run will use your local version
|
3. a subsequent ``py.test`` run will use your local version
|
||||||
|
|
||||||
Checkout customize_, other plugins_ or `get in contact`_.
|
Checkout customize_, other plugins_ or `get in contact`_.
|
||||||
|
|
||||||
.. include:: links.txt
|
.. include:: links.txt
|
||||||
|
|
|
@ -14,7 +14,7 @@ after pip or easy_install mediated installation of ``pytest-figleaf`` you can ty
|
||||||
py.test --figleaf [...]
|
py.test --figleaf [...]
|
||||||
|
|
||||||
to enable figleaf coverage in your test run. A default ".figleaf" data file
|
to enable figleaf coverage in your test run. A default ".figleaf" data file
|
||||||
and "html" directory will be created. You can use ``--fig-data``
|
and "html" directory will be created. You can use ``--fig-data``
|
||||||
and ``fig-html`` to modify the paths.
|
and ``fig-html`` to modify the paths.
|
||||||
|
|
||||||
command line options
|
command line options
|
||||||
|
|
|
@ -19,10 +19,10 @@ Start improving this plugin in 30 seconds
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
|
|
||||||
1. Download `pytest_genscript.py`_ plugin source code
|
1. Download `pytest_genscript.py`_ plugin source code
|
||||||
2. put it somewhere as ``pytest_genscript.py`` into your import path
|
2. put it somewhere as ``pytest_genscript.py`` into your import path
|
||||||
3. a subsequent ``py.test`` run will use your local version
|
3. a subsequent ``py.test`` run will use your local version
|
||||||
|
|
||||||
Checkout customize_, other plugins_ or `get in contact`_.
|
Checkout customize_, other plugins_ or `get in contact`_.
|
||||||
|
|
||||||
.. include:: links.txt
|
.. include:: links.txt
|
||||||
|
|
|
@ -19,7 +19,7 @@ command line options
|
||||||
``--traceconfig``
|
``--traceconfig``
|
||||||
trace considerations of conftest.py files.
|
trace considerations of conftest.py files.
|
||||||
``--nomagic``
|
``--nomagic``
|
||||||
don't reinterpret asserts, no traceback cutting.
|
don't reinterpret asserts, no traceback cutting.
|
||||||
``--debug``
|
``--debug``
|
||||||
generate and show internal debugging information.
|
generate and show internal debugging information.
|
||||||
``--help-config``
|
``--help-config``
|
||||||
|
@ -29,10 +29,10 @@ Start improving this plugin in 30 seconds
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
|
|
||||||
1. Download `pytest_helpconfig.py`_ plugin source code
|
1. Download `pytest_helpconfig.py`_ plugin source code
|
||||||
2. put it somewhere as ``pytest_helpconfig.py`` into your import path
|
2. put it somewhere as ``pytest_helpconfig.py`` into your import path
|
||||||
3. a subsequent ``py.test`` run will use your local version
|
3. a subsequent ``py.test`` run will use your local version
|
||||||
|
|
||||||
Checkout customize_, other plugins_ or `get in contact`_.
|
Checkout customize_, other plugins_ or `get in contact`_.
|
||||||
|
|
||||||
.. include:: links.txt
|
.. include:: links.txt
|
||||||
|
|
|
@ -19,10 +19,10 @@ Start improving this plugin in 30 seconds
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
|
|
||||||
1. Download `pytest_hooklog.py`_ plugin source code
|
1. Download `pytest_hooklog.py`_ plugin source code
|
||||||
2. put it somewhere as ``pytest_hooklog.py`` into your import path
|
2. put it somewhere as ``pytest_hooklog.py`` into your import path
|
||||||
3. a subsequent ``py.test`` run will use your local version
|
3. a subsequent ``py.test`` run will use your local version
|
||||||
|
|
||||||
Checkout customize_, other plugins_ or `get in contact`_.
|
Checkout customize_, other plugins_ or `get in contact`_.
|
||||||
|
|
||||||
.. include:: links.txt
|
.. include:: links.txt
|
||||||
|
|
|
@ -5,202 +5,202 @@ hook specification sourcecode
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
"""
|
"""
|
||||||
hook specifications for py.test plugins
|
hook specifications for py.test plugins
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
# Command line and configuration
|
# Command line and configuration
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
def pytest_namespace():
|
def pytest_namespace():
|
||||||
"return dict of name->object which will get stored at py.test. namespace"
|
"return dict of name->object which will get stored at py.test. namespace"
|
||||||
|
|
||||||
def pytest_addoption(parser):
|
def pytest_addoption(parser):
|
||||||
"add optparse-style options via parser.addoption."
|
"add optparse-style options via parser.addoption."
|
||||||
|
|
||||||
def pytest_addhooks(pluginmanager):
|
def pytest_addhooks(pluginmanager):
|
||||||
"add hooks via pluginmanager.registerhooks(module)"
|
"add hooks via pluginmanager.registerhooks(module)"
|
||||||
|
|
||||||
def pytest_configure(config):
|
def pytest_configure(config):
|
||||||
""" called after command line options have been parsed.
|
""" called after command line options have been parsed.
|
||||||
and all plugins and initial conftest files been loaded.
|
and all plugins and initial conftest files been loaded.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def pytest_unconfigure(config):
|
def pytest_unconfigure(config):
|
||||||
""" called before test process is exited. """
|
""" called before test process is exited. """
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
# collection hooks
|
# collection hooks
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
def pytest_ignore_collect(path, config):
|
def pytest_ignore_collect(path, config):
|
||||||
""" return true value to prevent considering this path for collection.
|
""" return true value to prevent considering this path for collection.
|
||||||
This hook is consulted for all files and directories prior to considering
|
This hook is consulted for all files and directories prior to considering
|
||||||
collection hooks.
|
collection hooks.
|
||||||
"""
|
"""
|
||||||
pytest_ignore_collect.firstresult = True
|
pytest_ignore_collect.firstresult = True
|
||||||
|
|
||||||
def pytest_collect_directory(path, parent):
|
def pytest_collect_directory(path, parent):
|
||||||
""" return Collection node or None for the given path. """
|
""" return Collection node or None for the given path. """
|
||||||
pytest_collect_directory.firstresult = True
|
pytest_collect_directory.firstresult = True
|
||||||
|
|
||||||
def pytest_collect_file(path, parent):
|
def pytest_collect_file(path, parent):
|
||||||
""" return Collection node or None for the given path. """
|
""" return Collection node or None for the given path. """
|
||||||
|
|
||||||
def pytest_collectstart(collector):
|
def pytest_collectstart(collector):
|
||||||
""" collector starts collecting. """
|
""" collector starts collecting. """
|
||||||
|
|
||||||
def pytest_collectreport(report):
|
def pytest_collectreport(report):
|
||||||
""" collector finished collecting. """
|
""" collector finished collecting. """
|
||||||
|
|
||||||
def pytest_deselected(items):
|
def pytest_deselected(items):
|
||||||
""" called for test items deselected by keyword. """
|
""" called for test items deselected by keyword. """
|
||||||
|
|
||||||
def pytest_make_collect_report(collector):
|
def pytest_make_collect_report(collector):
|
||||||
""" perform a collection and return a collection. """
|
""" perform a collection and return a collection. """
|
||||||
pytest_make_collect_report.firstresult = True
|
pytest_make_collect_report.firstresult = True
|
||||||
|
|
||||||
# XXX rename to item_collected()? meaning in distribution context?
|
# XXX rename to item_collected()? meaning in distribution context?
|
||||||
def pytest_itemstart(item, node=None):
|
def pytest_itemstart(item, node=None):
|
||||||
""" test item gets collected. """
|
""" test item gets collected. """
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
# Python test function related hooks
|
# Python test function related hooks
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
def pytest_pycollect_makemodule(path, parent):
|
def pytest_pycollect_makemodule(path, parent):
|
||||||
""" return a Module collector or None for the given path.
|
""" return a Module collector or None for the given path.
|
||||||
This hook will be called for each matching test module path.
|
This hook will be called for each matching test module path.
|
||||||
The pytest_collect_file hook needs to be used if you want to
|
The pytest_collect_file hook needs to be used if you want to
|
||||||
create test modules for files that do not match as a test module.
|
create test modules for files that do not match as a test module.
|
||||||
"""
|
"""
|
||||||
pytest_pycollect_makemodule.firstresult = True
|
pytest_pycollect_makemodule.firstresult = True
|
||||||
|
|
||||||
def pytest_pycollect_makeitem(collector, name, obj):
|
def pytest_pycollect_makeitem(collector, name, obj):
|
||||||
""" return custom item/collector for a python object in a module, or None. """
|
""" return custom item/collector for a python object in a module, or None. """
|
||||||
pytest_pycollect_makeitem.firstresult = True
|
pytest_pycollect_makeitem.firstresult = True
|
||||||
|
|
||||||
def pytest_pyfunc_call(pyfuncitem):
|
def pytest_pyfunc_call(pyfuncitem):
|
||||||
""" call underlying test function. """
|
""" call underlying test function. """
|
||||||
pytest_pyfunc_call.firstresult = True
|
pytest_pyfunc_call.firstresult = True
|
||||||
|
|
||||||
def pytest_generate_tests(metafunc):
|
def pytest_generate_tests(metafunc):
|
||||||
""" generate (multiple) parametrized calls to a test function."""
|
""" generate (multiple) parametrized calls to a test function."""
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
# generic runtest related hooks
|
# generic runtest related hooks
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
def pytest_runtest_protocol(item):
|
def pytest_runtest_protocol(item):
|
||||||
""" implement fixture, run and report about the given test item. """
|
""" implement fixture, run and report about the given test item. """
|
||||||
pytest_runtest_protocol.firstresult = True
|
pytest_runtest_protocol.firstresult = True
|
||||||
|
|
||||||
def pytest_runtest_setup(item):
|
def pytest_runtest_setup(item):
|
||||||
""" called before pytest_runtest_call(). """
|
""" called before pytest_runtest_call(). """
|
||||||
|
|
||||||
def pytest_runtest_call(item):
|
def pytest_runtest_call(item):
|
||||||
""" execute test item. """
|
""" execute test item. """
|
||||||
|
|
||||||
def pytest_runtest_teardown(item):
|
def pytest_runtest_teardown(item):
|
||||||
""" called after pytest_runtest_call(). """
|
""" called after pytest_runtest_call(). """
|
||||||
|
|
||||||
def pytest_runtest_makereport(item, call):
|
def pytest_runtest_makereport(item, call):
|
||||||
""" make a test report for the given item and call outcome. """
|
""" make a test report for the given item and call outcome. """
|
||||||
pytest_runtest_makereport.firstresult = True
|
pytest_runtest_makereport.firstresult = True
|
||||||
|
|
||||||
def pytest_runtest_logreport(report):
|
def pytest_runtest_logreport(report):
|
||||||
""" process item test report. """
|
""" process item test report. """
|
||||||
|
|
||||||
# special handling for final teardown - somewhat internal for now
|
# special handling for final teardown - somewhat internal for now
|
||||||
def pytest__teardown_final(session):
|
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(report):
|
def pytest__teardown_final_logerror(report):
|
||||||
""" called if runtest_teardown_final failed. """
|
""" called if runtest_teardown_final failed. """
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
# test session related hooks
|
# test session related hooks
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
def pytest_sessionstart(session):
|
def pytest_sessionstart(session):
|
||||||
""" before session.main() is called. """
|
""" before session.main() is called. """
|
||||||
|
|
||||||
def pytest_sessionfinish(session, exitstatus):
|
def pytest_sessionfinish(session, exitstatus):
|
||||||
""" whole test run finishes. """
|
""" whole test run finishes. """
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
# hooks for influencing reporting (invoked from pytest_terminal)
|
# hooks for influencing reporting (invoked from pytest_terminal)
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
def pytest_report_header(config):
|
def pytest_report_header(config):
|
||||||
""" return a string to be displayed as header info for terminal reporting."""
|
""" return a string to be displayed as header info for terminal reporting."""
|
||||||
|
|
||||||
def pytest_report_teststatus(report):
|
def pytest_report_teststatus(report):
|
||||||
""" return result-category, shortletter and verbose word for reporting."""
|
""" 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):
|
||||||
""" add additional section in terminal summary reporting. """
|
""" add additional section in terminal summary reporting. """
|
||||||
|
|
||||||
def pytest_report_iteminfo(item):
|
def pytest_report_iteminfo(item):
|
||||||
""" return (fspath, lineno, name) for the item.
|
""" return (fspath, lineno, name) for the item.
|
||||||
the information is used for result display and to sort tests
|
the information is used for result display and to sort tests
|
||||||
"""
|
"""
|
||||||
pytest_report_iteminfo.firstresult = True
|
pytest_report_iteminfo.firstresult = True
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
# doctest hooks
|
# doctest hooks
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
def pytest_doctest_prepare_content(content):
|
def pytest_doctest_prepare_content(content):
|
||||||
""" return processed content for a given doctest"""
|
""" return processed content for a given doctest"""
|
||||||
pytest_doctest_prepare_content.firstresult = True
|
pytest_doctest_prepare_content.firstresult = True
|
||||||
|
|
||||||
|
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
# error handling and internal debugging hooks
|
# error handling and internal debugging hooks
|
||||||
# -------------------------------------------------------------------------
|
# -------------------------------------------------------------------------
|
||||||
|
|
||||||
def pytest_plugin_registered(plugin, manager):
|
def pytest_plugin_registered(plugin, manager):
|
||||||
""" a new py lib plugin got registered. """
|
""" a new py lib plugin got registered. """
|
||||||
|
|
||||||
def pytest_plugin_unregistered(plugin):
|
def pytest_plugin_unregistered(plugin):
|
||||||
""" a py lib plugin got unregistered. """
|
""" a py lib plugin got unregistered. """
|
||||||
|
|
||||||
def pytest_internalerror(excrepr):
|
def pytest_internalerror(excrepr):
|
||||||
""" called for internal errors. """
|
""" called for internal errors. """
|
||||||
|
|
||||||
def pytest_keyboard_interrupt(excinfo):
|
def pytest_keyboard_interrupt(excinfo):
|
||||||
""" called for keyboard interrupt. """
|
""" called for keyboard interrupt. """
|
||||||
|
|
||||||
def pytest_trace(category, msg):
|
def pytest_trace(category, msg):
|
||||||
""" called for debug info. """
|
""" called for debug info. """
|
||||||
|
|
||||||
hook specification sourcecode
|
hook specification sourcecode
|
||||||
=============================
|
=============================
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
|
|
||||||
def pytest_gwmanage_newgateway(gateway, platinfo):
|
def pytest_gwmanage_newgateway(gateway, platinfo):
|
||||||
""" called on new raw gateway creation. """
|
""" called on new raw gateway creation. """
|
||||||
|
|
||||||
def pytest_gwmanage_rsyncstart(source, gateways):
|
def pytest_gwmanage_rsyncstart(source, gateways):
|
||||||
""" called before rsyncing a directory to remote gateways takes place. """
|
""" called before rsyncing a directory to remote gateways takes place. """
|
||||||
|
|
||||||
def pytest_gwmanage_rsyncfinish(source, gateways):
|
def pytest_gwmanage_rsyncfinish(source, gateways):
|
||||||
""" called after rsyncing a directory to remote gateways takes place. """
|
""" called after rsyncing a directory to remote gateways takes place. """
|
||||||
|
|
||||||
def pytest_configure_node(node):
|
def pytest_configure_node(node):
|
||||||
""" configure node information before it gets instantiated. """
|
""" configure node information before it gets instantiated. """
|
||||||
|
|
||||||
def pytest_testnodeready(node):
|
def pytest_testnodeready(node):
|
||||||
""" Test Node is ready to operate. """
|
""" Test Node is ready to operate. """
|
||||||
|
|
||||||
def pytest_testnodedown(node, error):
|
def pytest_testnodedown(node, error):
|
||||||
""" Test Node is down. """
|
""" Test Node is down. """
|
||||||
|
|
||||||
def pytest_rescheduleitems(items):
|
def pytest_rescheduleitems(items):
|
||||||
""" reschedule Items from a node that went down. """
|
""" reschedule Items from a node that went down. """
|
||||||
|
|
||||||
|
|
|
@ -21,10 +21,10 @@ Start improving this plugin in 30 seconds
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
|
|
||||||
1. Download `pytest_junitxml.py`_ plugin source code
|
1. Download `pytest_junitxml.py`_ plugin source code
|
||||||
2. put it somewhere as ``pytest_junitxml.py`` into your import path
|
2. put it somewhere as ``pytest_junitxml.py`` into your import path
|
||||||
3. a subsequent ``py.test`` run will use your local version
|
3. a subsequent ``py.test`` run will use your local version
|
||||||
|
|
||||||
Checkout customize_, other plugins_ or `get in contact`_.
|
Checkout customize_, other plugins_ or `get in contact`_.
|
||||||
|
|
||||||
.. include:: links.txt
|
.. include:: links.txt
|
||||||
|
|
|
@ -7,18 +7,18 @@ generic mechanism for marking python functions.
|
||||||
:local:
|
:local:
|
||||||
|
|
||||||
By using the ``py.test.mark`` helper you can instantiate
|
By using the ``py.test.mark`` helper you can instantiate
|
||||||
decorators that will set named meta data on test functions.
|
decorators that will set named meta data on test functions.
|
||||||
|
|
||||||
Marking a single function
|
Marking a single function
|
||||||
----------------------------------------------------
|
----------------------------------------------------
|
||||||
|
|
||||||
You can "mark" a test function with meta data like this::
|
You can "mark" a test function with meta data like this::
|
||||||
|
|
||||||
@py.test.mark.webtest
|
@py.test.mark.webtest
|
||||||
def test_send_http():
|
def test_send_http():
|
||||||
...
|
...
|
||||||
|
|
||||||
This will set a "Marker" instance as a function attribute named "webtest".
|
This will set a "Marker" instance as a function attribute named "webtest".
|
||||||
You can also specify parametrized meta data like this::
|
You can also specify parametrized meta data like this::
|
||||||
|
|
||||||
@py.test.mark.webtest(firefox=30)
|
@py.test.mark.webtest(firefox=30)
|
||||||
|
@ -39,7 +39,7 @@ and later access it with ``test_receive.webtest.args[0] == 'triangular``.
|
||||||
|
|
||||||
.. _`scoped-marking`:
|
.. _`scoped-marking`:
|
||||||
|
|
||||||
Marking whole classes or modules
|
Marking whole classes or modules
|
||||||
----------------------------------------------------
|
----------------------------------------------------
|
||||||
|
|
||||||
If you are programming with Python2.6 you may use ``py.test.mark`` decorators
|
If you are programming with Python2.6 you may use ``py.test.mark`` decorators
|
||||||
|
@ -53,9 +53,9 @@ with classes to apply markers to all its test methods::
|
||||||
...
|
...
|
||||||
|
|
||||||
This is equivalent to directly applying the decorator to the
|
This is equivalent to directly applying the decorator to the
|
||||||
two test functions.
|
two test functions.
|
||||||
|
|
||||||
To remain compatible with Python2.5 you can also set a
|
To remain compatible with Python2.5 you can also set a
|
||||||
``pytestmark`` attribute on a TestClass like this::
|
``pytestmark`` attribute on a TestClass like this::
|
||||||
|
|
||||||
import py
|
import py
|
||||||
|
@ -75,8 +75,8 @@ You can also set a module level marker::
|
||||||
import py
|
import py
|
||||||
pytestmark = py.test.mark.webtest
|
pytestmark = py.test.mark.webtest
|
||||||
|
|
||||||
in which case it will be applied to all functions and
|
in which case it will be applied to all functions and
|
||||||
methods defined in the module.
|
methods defined in the module.
|
||||||
|
|
||||||
Using "-k MARKNAME" to select tests
|
Using "-k MARKNAME" to select tests
|
||||||
----------------------------------------------------
|
----------------------------------------------------
|
||||||
|
@ -90,10 +90,10 @@ Start improving this plugin in 30 seconds
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
|
|
||||||
1. Download `pytest_mark.py`_ plugin source code
|
1. Download `pytest_mark.py`_ plugin source code
|
||||||
2. put it somewhere as ``pytest_mark.py`` into your import path
|
2. put it somewhere as ``pytest_mark.py`` into your import path
|
||||||
3. a subsequent ``py.test`` run will use your local version
|
3. a subsequent ``py.test`` run will use your local version
|
||||||
|
|
||||||
Checkout customize_, other plugins_ or `get in contact`_.
|
Checkout customize_, other plugins_ or `get in contact`_.
|
||||||
|
|
||||||
.. include:: links.txt
|
.. include:: links.txt
|
||||||
|
|
|
@ -6,54 +6,54 @@ safely patch object attributes, dicts and environment variables.
|
||||||
.. contents::
|
.. contents::
|
||||||
:local:
|
:local:
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
Use the `monkeypatch funcarg`_ to tweak your global test environment
|
Use the `monkeypatch funcarg`_ to tweak your global test environment
|
||||||
for running a particular test. You can safely set/del an attribute,
|
for running a particular test. You can safely set/del an attribute,
|
||||||
dictionary item or environment variable by respective methods
|
dictionary item or environment variable by respective methods
|
||||||
on the monkeypatch funcarg. If you want e.g. to set an ENV1 variable
|
on the monkeypatch funcarg. If you want e.g. to set an ENV1 variable
|
||||||
and have os.path.expanduser return a particular directory, you can
|
and have os.path.expanduser return a particular directory, you can
|
||||||
write it down like this:
|
write it down like this:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
def test_mytest(monkeypatch):
|
def test_mytest(monkeypatch):
|
||||||
monkeypatch.setenv('ENV1', 'myval')
|
monkeypatch.setenv('ENV1', 'myval')
|
||||||
monkeypatch.setattr(os.path, 'expanduser', lambda x: '/tmp/xyz')
|
monkeypatch.setattr(os.path, 'expanduser', lambda x: '/tmp/xyz')
|
||||||
... # your test code that uses those patched values implicitely
|
... # your test code that uses those patched values implicitely
|
||||||
|
|
||||||
After the test function finished all modifications will be undone,
|
After the test function finished all modifications will be undone,
|
||||||
because the ``monkeypatch.undo()`` method is registered as a finalizer.
|
because the ``monkeypatch.undo()`` method is registered as a finalizer.
|
||||||
|
|
||||||
``monkeypatch.setattr/delattr/delitem/delenv()`` all
|
``monkeypatch.setattr/delattr/delitem/delenv()`` all
|
||||||
by default raise an Exception if the target does not exist.
|
by default raise an Exception if the target does not exist.
|
||||||
Pass ``raising=False`` if you want to skip this check.
|
Pass ``raising=False`` if you want to skip this check.
|
||||||
|
|
||||||
prepending to PATH or other environment variables
|
prepending to PATH or other environment variables
|
||||||
---------------------------------------------------------
|
---------------------------------------------------------
|
||||||
|
|
||||||
To prepend a value to an already existing environment parameter:
|
To prepend a value to an already existing environment parameter:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
def test_mypath_finding(monkeypatch):
|
def test_mypath_finding(monkeypatch):
|
||||||
monkeypatch.setenv('PATH', 'x/y', prepend=":")
|
monkeypatch.setenv('PATH', 'x/y', prepend=":")
|
||||||
# in bash language: export PATH=x/y:$PATH
|
# in bash language: export PATH=x/y:$PATH
|
||||||
|
|
||||||
calling "undo" finalization explicitely
|
calling "undo" finalization explicitely
|
||||||
-----------------------------------------
|
-----------------------------------------
|
||||||
|
|
||||||
At the end of function execution py.test invokes
|
At the end of function execution py.test invokes
|
||||||
a teardown hook which undoes all monkeypatch changes.
|
a teardown hook which undoes all monkeypatch changes.
|
||||||
If you do not want to wait that long you can call
|
If you do not want to wait that long you can call
|
||||||
finalization explicitely::
|
finalization explicitely::
|
||||||
|
|
||||||
monkeypatch.undo()
|
monkeypatch.undo()
|
||||||
|
|
||||||
This will undo previous changes. This call consumes the
|
This will undo previous changes. This call consumes the
|
||||||
undo stack. Calling it a second time has no effect unless
|
undo stack. Calling it a second time has no effect unless
|
||||||
you start monkeypatching after the undo call.
|
you start monkeypatching after the undo call.
|
||||||
|
|
||||||
.. _`monkeypatch blog post`: http://tetamap.wordpress.com/2009/03/03/monkeypatching-in-unit-tests-done-right/
|
.. _`monkeypatch blog post`: http://tetamap.wordpress.com/2009/03/03/monkeypatching-in-unit-tests-done-right/
|
||||||
|
|
||||||
|
@ -63,30 +63,30 @@ you start monkeypatching after the undo call.
|
||||||
the 'monkeypatch' test function argument
|
the 'monkeypatch' test function argument
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
The returned ``monkeypatch`` funcarg provides these
|
The returned ``monkeypatch`` funcarg provides these
|
||||||
helper methods to modify objects, dictionaries or os.environ::
|
helper methods to modify objects, dictionaries or os.environ::
|
||||||
|
|
||||||
monkeypatch.setattr(obj, name, value, raising=True)
|
monkeypatch.setattr(obj, name, value, raising=True)
|
||||||
monkeypatch.delattr(obj, name, raising=True)
|
monkeypatch.delattr(obj, name, raising=True)
|
||||||
monkeypatch.setitem(mapping, name, value)
|
monkeypatch.setitem(mapping, name, value)
|
||||||
monkeypatch.delitem(obj, name, raising=True)
|
monkeypatch.delitem(obj, name, raising=True)
|
||||||
monkeypatch.setenv(name, value, prepend=False)
|
monkeypatch.setenv(name, value, prepend=False)
|
||||||
monkeypatch.delenv(name, value, raising=True)
|
monkeypatch.delenv(name, value, raising=True)
|
||||||
monkeypatch.syspath_prepend(path)
|
monkeypatch.syspath_prepend(path)
|
||||||
|
|
||||||
All modifications will be undone when the requesting
|
All modifications will be undone when the requesting
|
||||||
test function finished its execution. The ``raising``
|
test function finished its execution. The ``raising``
|
||||||
parameter determines if a KeyError or AttributeError
|
parameter determines if a KeyError or AttributeError
|
||||||
will be raised if the set/deletion operation has no target.
|
will be raised if the set/deletion operation has no target.
|
||||||
|
|
||||||
Start improving this plugin in 30 seconds
|
Start improving this plugin in 30 seconds
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
|
|
||||||
1. Download `pytest_monkeypatch.py`_ plugin source code
|
1. Download `pytest_monkeypatch.py`_ plugin source code
|
||||||
2. put it somewhere as ``pytest_monkeypatch.py`` into your import path
|
2. put it somewhere as ``pytest_monkeypatch.py`` into your import path
|
||||||
3. a subsequent ``py.test`` run will use your local version
|
3. a subsequent ``py.test`` run will use your local version
|
||||||
|
|
||||||
Checkout customize_, other plugins_ or `get in contact`_.
|
Checkout customize_, other plugins_ or `get in contact`_.
|
||||||
|
|
||||||
.. include:: links.txt
|
.. include:: links.txt
|
||||||
|
|
|
@ -6,8 +6,8 @@ nose-compatibility plugin: allow to run nose test suites natively.
|
||||||
.. contents::
|
.. contents::
|
||||||
:local:
|
:local:
|
||||||
|
|
||||||
This is an experimental plugin for allowing to run tests written
|
This is an experimental plugin for allowing to run tests written
|
||||||
in 'nosetests style with py.test.
|
in 'nosetests style with py.test.
|
||||||
|
|
||||||
Usage
|
Usage
|
||||||
-------------
|
-------------
|
||||||
|
@ -17,28 +17,28 @@ type::
|
||||||
py.test # instead of 'nosetests'
|
py.test # instead of 'nosetests'
|
||||||
|
|
||||||
and you should be able to run nose style tests and at the same
|
and you should be able to run nose style tests and at the same
|
||||||
time can make full use of py.test's capabilities.
|
time can make full use of py.test's capabilities.
|
||||||
|
|
||||||
Supported nose Idioms
|
Supported nose Idioms
|
||||||
----------------------
|
----------------------
|
||||||
|
|
||||||
* setup and teardown at module/class/method level
|
* setup and teardown at module/class/method level
|
||||||
* SkipTest exceptions and markers
|
* SkipTest exceptions and markers
|
||||||
* setup/teardown decorators
|
* setup/teardown decorators
|
||||||
* yield-based tests and their setup
|
* yield-based tests and their setup
|
||||||
* general usage of nose utilities
|
* general usage of nose utilities
|
||||||
|
|
||||||
Unsupported idioms / issues
|
Unsupported idioms / issues
|
||||||
----------------------------------
|
----------------------------------
|
||||||
|
|
||||||
- nose-style doctests are not collected and executed correctly,
|
- nose-style doctests are not collected and executed correctly,
|
||||||
also fixtures don't work.
|
also fixtures don't work.
|
||||||
|
|
||||||
- no nose-configuration is recognized
|
- no nose-configuration is recognized
|
||||||
|
|
||||||
If you find other issues or have suggestions please run::
|
If you find other issues or have suggestions please run::
|
||||||
|
|
||||||
py.test --pastebin=all
|
py.test --pastebin=all
|
||||||
|
|
||||||
and send the resulting URL to a py.test contact channel,
|
and send the resulting URL to a py.test contact channel,
|
||||||
at best to the mailing list.
|
at best to the mailing list.
|
||||||
|
@ -47,10 +47,10 @@ Start improving this plugin in 30 seconds
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
|
|
||||||
1. Download `pytest_nose.py`_ plugin source code
|
1. Download `pytest_nose.py`_ plugin source code
|
||||||
2. put it somewhere as ``pytest_nose.py`` into your import path
|
2. put it somewhere as ``pytest_nose.py`` into your import path
|
||||||
3. a subsequent ``py.test`` run will use your local version
|
3. a subsequent ``py.test`` run will use your local version
|
||||||
|
|
||||||
Checkout customize_, other plugins_ or `get in contact`_.
|
Checkout customize_, other plugins_ or `get in contact`_.
|
||||||
|
|
||||||
.. include:: links.txt
|
.. include:: links.txt
|
||||||
|
|
|
@ -4,9 +4,9 @@ pytest_oejskit plugin (EXTERNAL)
|
||||||
The `oejskit`_ offers a py.test plugin for running Javascript tests in life browers. Running inside the browsers comes with some speed cost, on the other hand it means for example the code is tested against the real-word DOM implementations.
|
The `oejskit`_ offers a py.test plugin for running Javascript tests in life browers. Running inside the browsers comes with some speed cost, on the other hand it means for example the code is tested against the real-word DOM implementations.
|
||||||
The approach enables to write integration tests such that the JavaScript code is tested against server-side Python code mocked as necessary. Any server-side framework that can already be exposed through WSGI (or for which a subset of WSGI can be written to accommodate the jskit own needs) can play along.
|
The approach enables to write integration tests such that the JavaScript code is tested against server-side Python code mocked as necessary. Any server-side framework that can already be exposed through WSGI (or for which a subset of WSGI can be written to accommodate the jskit own needs) can play along.
|
||||||
|
|
||||||
For more info and download please visit the `oejskit PyPI`_ page.
|
For more info and download please visit the `oejskit PyPI`_ page.
|
||||||
|
|
||||||
.. _`oejskit`:
|
.. _`oejskit`:
|
||||||
.. _`oejskit PyPI`: http://pypi.python.org/pypi/oejskit
|
.. _`oejskit PyPI`: http://pypi.python.org/pypi/oejskit
|
||||||
|
|
||||||
.. source link 'http://bitbucket.org/pedronis/js-infrastructure/src/tip/pytest_jstests.py',
|
.. source link 'http://bitbucket.org/pedronis/js-infrastructure/src/tip/pytest_jstests.py',
|
||||||
|
|
|
@ -11,15 +11,15 @@ Usage
|
||||||
|
|
||||||
**Creating a URL for each test failure**::
|
**Creating a URL for each test failure**::
|
||||||
|
|
||||||
py.test --pastebin=failed
|
py.test --pastebin=failed
|
||||||
|
|
||||||
This will submit test run information to a remote Paste service and
|
This will submit test run information to a remote Paste service and
|
||||||
provide a URL for each failure. You may select tests as usual or add
|
provide a URL for each failure. You may select tests as usual or add
|
||||||
for example ``-x`` if you only want to send one particular failure.
|
for example ``-x`` if you only want to send one particular failure.
|
||||||
|
|
||||||
**Creating a URL for a whole test session log**::
|
**Creating a URL for a whole test session log**::
|
||||||
|
|
||||||
py.test --pastebin=all
|
py.test --pastebin=all
|
||||||
|
|
||||||
Currently only pasting to the http://paste.pocoo.org service is implemented.
|
Currently only pasting to the http://paste.pocoo.org service is implemented.
|
||||||
|
|
||||||
|
@ -34,10 +34,10 @@ Start improving this plugin in 30 seconds
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
|
|
||||||
1. Download `pytest_pastebin.py`_ plugin source code
|
1. Download `pytest_pastebin.py`_ plugin source code
|
||||||
2. put it somewhere as ``pytest_pastebin.py`` into your import path
|
2. put it somewhere as ``pytest_pastebin.py`` into your import path
|
||||||
3. a subsequent ``py.test`` run will use your local version
|
3. a subsequent ``py.test`` run will use your local version
|
||||||
|
|
||||||
Checkout customize_, other plugins_ or `get in contact`_.
|
Checkout customize_, other plugins_ or `get in contact`_.
|
||||||
|
|
||||||
.. include:: links.txt
|
.. include:: links.txt
|
||||||
|
|
|
@ -19,10 +19,10 @@ Start improving this plugin in 30 seconds
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
|
|
||||||
1. Download `pytest_pdb.py`_ plugin source code
|
1. Download `pytest_pdb.py`_ plugin source code
|
||||||
2. put it somewhere as ``pytest_pdb.py`` into your import path
|
2. put it somewhere as ``pytest_pdb.py`` into your import path
|
||||||
3. a subsequent ``py.test`` run will use your local version
|
3. a subsequent ``py.test`` run will use your local version
|
||||||
|
|
||||||
Checkout customize_, other plugins_ or `get in contact`_.
|
Checkout customize_, other plugins_ or `get in contact`_.
|
||||||
|
|
||||||
.. include:: links.txt
|
.. include:: links.txt
|
||||||
|
|
|
@ -6,10 +6,10 @@ helpers for asserting deprecation and other warnings.
|
||||||
.. contents::
|
.. contents::
|
||||||
:local:
|
:local:
|
||||||
|
|
||||||
Example usage
|
Example usage
|
||||||
---------------------
|
---------------------
|
||||||
|
|
||||||
You can use the ``recwarn`` funcarg to track
|
You can use the ``recwarn`` funcarg to track
|
||||||
warnings within a test function:
|
warnings within a test function:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
@ -30,7 +30,7 @@ warning:
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
import py
|
import py
|
||||||
|
|
||||||
def test_global():
|
def test_global():
|
||||||
py.test.deprecated_call(myfunction, 17)
|
py.test.deprecated_call(myfunction, 17)
|
||||||
|
|
||||||
|
@ -43,16 +43,16 @@ the 'recwarn' test function argument
|
||||||
Return a WarningsRecorder instance that provides these methods:
|
Return a WarningsRecorder instance that provides these methods:
|
||||||
|
|
||||||
* ``pop(category=None)``: return last warning matching the category.
|
* ``pop(category=None)``: return last warning matching the category.
|
||||||
* ``clear()``: clear list of warnings
|
* ``clear()``: clear list of warnings
|
||||||
|
|
||||||
Start improving this plugin in 30 seconds
|
Start improving this plugin in 30 seconds
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
|
|
||||||
1. Download `pytest_recwarn.py`_ plugin source code
|
1. Download `pytest_recwarn.py`_ plugin source code
|
||||||
2. put it somewhere as ``pytest_recwarn.py`` into your import path
|
2. put it somewhere as ``pytest_recwarn.py`` into your import path
|
||||||
3. a subsequent ``py.test`` run will use your local version
|
3. a subsequent ``py.test`` run will use your local version
|
||||||
|
|
||||||
Checkout customize_, other plugins_ or `get in contact`_.
|
Checkout customize_, other plugins_ or `get in contact`_.
|
||||||
|
|
||||||
.. include:: links.txt
|
.. include:: links.txt
|
||||||
|
|
|
@ -23,10 +23,10 @@ Start improving this plugin in 30 seconds
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
|
|
||||||
1. Download `pytest_restdoc.py`_ plugin source code
|
1. Download `pytest_restdoc.py`_ plugin source code
|
||||||
2. put it somewhere as ``pytest_restdoc.py`` into your import path
|
2. put it somewhere as ``pytest_restdoc.py`` into your import path
|
||||||
3. a subsequent ``py.test`` run will use your local version
|
3. a subsequent ``py.test`` run will use your local version
|
||||||
|
|
||||||
Checkout customize_, other plugins_ or `get in contact`_.
|
Checkout customize_, other plugins_ or `get in contact`_.
|
||||||
|
|
||||||
.. include:: links.txt
|
.. include:: links.txt
|
||||||
|
|
|
@ -6,8 +6,8 @@ non-xml machine-readable logging of test results.
|
||||||
.. contents::
|
.. contents::
|
||||||
:local:
|
:local:
|
||||||
|
|
||||||
Useful for buildbot integration code. See the `PyPy-test`_
|
Useful for buildbot integration code. See the `PyPy-test`_
|
||||||
web page for post-processing.
|
web page for post-processing.
|
||||||
|
|
||||||
.. _`PyPy-test`: http://codespeak.net:8099/summary
|
.. _`PyPy-test`: http://codespeak.net:8099/summary
|
||||||
|
|
||||||
|
@ -22,10 +22,10 @@ Start improving this plugin in 30 seconds
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
|
|
||||||
1. Download `pytest_resultlog.py`_ plugin source code
|
1. Download `pytest_resultlog.py`_ plugin source code
|
||||||
2. put it somewhere as ``pytest_resultlog.py`` into your import path
|
2. put it somewhere as ``pytest_resultlog.py`` into your import path
|
||||||
3. a subsequent ``py.test`` run will use your local version
|
3. a subsequent ``py.test`` run will use your local version
|
||||||
|
|
||||||
Checkout customize_, other plugins_ or `get in contact`_.
|
Checkout customize_, other plugins_ or `get in contact`_.
|
||||||
|
|
||||||
.. include:: links.txt
|
.. include:: links.txt
|
||||||
|
|
|
@ -6,21 +6,21 @@ advanced skipping for python test functions, classes or modules.
|
||||||
.. contents::
|
.. contents::
|
||||||
:local:
|
:local:
|
||||||
|
|
||||||
With this plugin you can mark test functions for conditional skipping
|
With this plugin you can mark test functions for conditional skipping
|
||||||
or as "xfail", expected-to-fail. Skipping a test will avoid running it
|
or as "xfail", expected-to-fail. Skipping a test will avoid running it
|
||||||
while xfail-marked tests will run and result in an inverted outcome:
|
while xfail-marked tests will run and result in an inverted outcome:
|
||||||
a pass becomes a failure and a fail becomes a semi-passing one.
|
a pass becomes a failure and a fail becomes a semi-passing one.
|
||||||
|
|
||||||
The need for skipping a test is usually connected to a condition.
|
The need for skipping a test is usually connected to a condition.
|
||||||
If a test fails under all conditions then it's probably better
|
If a test fails under all conditions then it's probably better
|
||||||
to mark your test as 'xfail'.
|
to mark your test as 'xfail'.
|
||||||
|
|
||||||
By passing ``-rxs`` to the terminal reporter you will see extra
|
By passing ``-rxs`` to the terminal reporter you will see extra
|
||||||
summary information on skips and xfail-run tests at the end of a test run.
|
summary information on skips and xfail-run tests at the end of a test run.
|
||||||
|
|
||||||
.. _skipif:
|
.. _skipif:
|
||||||
|
|
||||||
Skipping a single function
|
Skipping a single function
|
||||||
-------------------------------------------
|
-------------------------------------------
|
||||||
|
|
||||||
Here is an example for marking a test function to be skipped
|
Here is an example for marking a test function to be skipped
|
||||||
|
@ -30,17 +30,17 @@ when run on a Python3 interpreter::
|
||||||
def test_function():
|
def test_function():
|
||||||
...
|
...
|
||||||
|
|
||||||
During test function setup the skipif condition is
|
During test function setup the skipif condition is
|
||||||
evaluated by calling ``eval(expr, namespace)``. The namespace
|
evaluated by calling ``eval(expr, namespace)``. The namespace
|
||||||
contains the ``sys`` and ``os`` modules and the test
|
contains the ``sys`` and ``os`` modules and the test
|
||||||
``config`` object. The latter allows you to skip based
|
``config`` object. The latter allows you to skip based
|
||||||
on a test configuration value e.g. like this::
|
on a test configuration value e.g. like this::
|
||||||
|
|
||||||
@py.test.mark.skipif("not config.getvalue('db')")
|
@py.test.mark.skipif("not config.getvalue('db')")
|
||||||
def test_function(...):
|
def test_function(...):
|
||||||
...
|
...
|
||||||
|
|
||||||
Create a shortcut for your conditional skip decorator
|
Create a shortcut for your conditional skip decorator
|
||||||
at module level like this::
|
at module level like this::
|
||||||
|
|
||||||
win32only = py.test.mark.skipif("sys.platform != 'win32'")
|
win32only = py.test.mark.skipif("sys.platform != 'win32'")
|
||||||
|
@ -50,34 +50,34 @@ at module level like this::
|
||||||
...
|
...
|
||||||
|
|
||||||
|
|
||||||
skip groups of test functions
|
skip groups of test functions
|
||||||
--------------------------------------
|
--------------------------------------
|
||||||
|
|
||||||
As with all metadata function marking you can do it at
|
As with all metadata function marking you can do it at
|
||||||
`whole class- or module level`_. Here is an example
|
`whole class- or module level`_. Here is an example
|
||||||
for skipping all methods of a test class based on platform::
|
for skipping all methods of a test class based on platform::
|
||||||
|
|
||||||
class TestPosixCalls:
|
class TestPosixCalls:
|
||||||
pytestmark = py.test.mark.skipif("sys.platform == 'win32'")
|
pytestmark = py.test.mark.skipif("sys.platform == 'win32'")
|
||||||
|
|
||||||
def test_function(self):
|
def test_function(self):
|
||||||
# will not be setup or run under 'win32' platform
|
# will not be setup or run under 'win32' platform
|
||||||
#
|
#
|
||||||
|
|
||||||
The ``pytestmark`` decorator will be applied to each test function.
|
The ``pytestmark`` decorator will be applied to each test function.
|
||||||
If your code targets python2.6 or above you can equivalently use
|
If your code targets python2.6 or above you can equivalently use
|
||||||
the skipif decorator on classes::
|
the skipif decorator on classes::
|
||||||
|
|
||||||
@py.test.mark.skipif("sys.platform == 'win32'")
|
@py.test.mark.skipif("sys.platform == 'win32'")
|
||||||
class TestPosixCalls:
|
class TestPosixCalls:
|
||||||
|
|
||||||
def test_function(self):
|
def test_function(self):
|
||||||
# will not be setup or run under 'win32' platform
|
# will not be setup or run under 'win32' platform
|
||||||
#
|
#
|
||||||
|
|
||||||
It is fine in general to apply multiple "skipif" decorators
|
It is fine in general to apply multiple "skipif" decorators
|
||||||
on a single function - this means that if any of the conditions
|
on a single function - this means that if any of the conditions
|
||||||
apply the function will be skipped.
|
apply the function will be skipped.
|
||||||
|
|
||||||
.. _`whole class- or module level`: mark.html#scoped-marking
|
.. _`whole class- or module level`: mark.html#scoped-marking
|
||||||
|
|
||||||
|
@ -87,7 +87,7 @@ mark a test function as **expected to fail**
|
||||||
-------------------------------------------------------
|
-------------------------------------------------------
|
||||||
|
|
||||||
You can use the ``xfail`` marker to indicate that you
|
You can use the ``xfail`` marker to indicate that you
|
||||||
expect the test to fail::
|
expect the test to fail::
|
||||||
|
|
||||||
@py.test.mark.xfail
|
@py.test.mark.xfail
|
||||||
def test_function():
|
def test_function():
|
||||||
|
@ -116,7 +116,7 @@ imperative xfail from within a test or setup function
|
||||||
------------------------------------------------------
|
------------------------------------------------------
|
||||||
|
|
||||||
If you cannot declare xfail-conditions at import time
|
If you cannot declare xfail-conditions at import time
|
||||||
you can also imperatively produce an XFail-outcome from
|
you can also imperatively produce an XFail-outcome from
|
||||||
within test or setup code. Example::
|
within test or setup code. Example::
|
||||||
|
|
||||||
def test_function():
|
def test_function():
|
||||||
|
@ -127,7 +127,7 @@ within test or setup code. Example::
|
||||||
skipping on a missing import dependency
|
skipping on a missing import dependency
|
||||||
--------------------------------------------------
|
--------------------------------------------------
|
||||||
|
|
||||||
You can use the following import helper at module level
|
You can use the following import helper at module level
|
||||||
or within a test or test setup function::
|
or within a test or test setup function::
|
||||||
|
|
||||||
docutils = py.test.importorskip("docutils")
|
docutils = py.test.importorskip("docutils")
|
||||||
|
@ -144,7 +144,7 @@ imperative skip from within a test or setup function
|
||||||
------------------------------------------------------
|
------------------------------------------------------
|
||||||
|
|
||||||
If for some reason you cannot declare skip-conditions
|
If for some reason you cannot declare skip-conditions
|
||||||
you can also imperatively produce a Skip-outcome from
|
you can also imperatively produce a Skip-outcome from
|
||||||
within test or setup code. Example::
|
within test or setup code. Example::
|
||||||
|
|
||||||
def test_function():
|
def test_function():
|
||||||
|
@ -162,10 +162,10 @@ Start improving this plugin in 30 seconds
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
|
|
||||||
1. Download `pytest_skipping.py`_ plugin source code
|
1. Download `pytest_skipping.py`_ plugin source code
|
||||||
2. put it somewhere as ``pytest_skipping.py`` into your import path
|
2. put it somewhere as ``pytest_skipping.py`` into your import path
|
||||||
3. a subsequent ``py.test`` run will use your local version
|
3. a subsequent ``py.test`` run will use your local version
|
||||||
|
|
||||||
Checkout customize_, other plugins_ or `get in contact`_.
|
Checkout customize_, other plugins_ or `get in contact`_.
|
||||||
|
|
||||||
.. include:: links.txt
|
.. include:: links.txt
|
||||||
|
|
|
@ -31,10 +31,10 @@ Start improving this plugin in 30 seconds
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
|
|
||||||
1. Download `pytest_terminal.py`_ plugin source code
|
1. Download `pytest_terminal.py`_ plugin source code
|
||||||
2. put it somewhere as ``pytest_terminal.py`` into your import path
|
2. put it somewhere as ``pytest_terminal.py`` into your import path
|
||||||
3. a subsequent ``py.test`` run will use your local version
|
3. a subsequent ``py.test`` run will use your local version
|
||||||
|
|
||||||
Checkout customize_, other plugins_ or `get in contact`_.
|
Checkout customize_, other plugins_ or `get in contact`_.
|
||||||
|
|
||||||
.. include:: links.txt
|
.. include:: links.txt
|
||||||
|
|
|
@ -23,16 +23,16 @@ return a temporary directory path object
|
||||||
unique to each test function invocation,
|
unique to each test function invocation,
|
||||||
created as a sub directory of the base temporary
|
created as a sub directory of the base temporary
|
||||||
directory. The returned object is a `py.path.local`_
|
directory. The returned object is a `py.path.local`_
|
||||||
path object.
|
path object.
|
||||||
|
|
||||||
Start improving this plugin in 30 seconds
|
Start improving this plugin in 30 seconds
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
|
|
||||||
1. Download `pytest_tmpdir.py`_ plugin source code
|
1. Download `pytest_tmpdir.py`_ plugin source code
|
||||||
2. put it somewhere as ``pytest_tmpdir.py`` into your import path
|
2. put it somewhere as ``pytest_tmpdir.py`` into your import path
|
||||||
3. a subsequent ``py.test`` run will use your local version
|
3. a subsequent ``py.test`` run will use your local version
|
||||||
|
|
||||||
Checkout customize_, other plugins_ or `get in contact`_.
|
Checkout customize_, other plugins_ or `get in contact`_.
|
||||||
|
|
||||||
.. include:: links.txt
|
.. include:: links.txt
|
||||||
|
|
|
@ -9,12 +9,12 @@ automatically discover and run traditional "unittest.py" style tests.
|
||||||
Usage
|
Usage
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
This plugin collects and runs Python `unittest.py style`_ tests.
|
This plugin collects and runs Python `unittest.py style`_ tests.
|
||||||
It will automatically collect ``unittest.TestCase`` subclasses
|
It will automatically collect ``unittest.TestCase`` subclasses
|
||||||
and their ``test`` methods from the test modules of a project
|
and their ``test`` methods from the test modules of a project
|
||||||
(usually following the ``test_*.py`` pattern).
|
(usually following the ``test_*.py`` pattern).
|
||||||
|
|
||||||
This plugin is enabled by default.
|
This plugin is enabled by default.
|
||||||
|
|
||||||
.. _`unittest.py style`: http://docs.python.org/library/unittest.html
|
.. _`unittest.py style`: http://docs.python.org/library/unittest.html
|
||||||
|
|
||||||
|
@ -22,10 +22,10 @@ Start improving this plugin in 30 seconds
|
||||||
=========================================
|
=========================================
|
||||||
|
|
||||||
|
|
||||||
1. Download `pytest_unittest.py`_ plugin source code
|
1. Download `pytest_unittest.py`_ plugin source code
|
||||||
2. put it somewhere as ``pytest_unittest.py`` into your import path
|
2. put it somewhere as ``pytest_unittest.py`` into your import path
|
||||||
3. a subsequent ``py.test`` run will use your local version
|
3. a subsequent ``py.test`` run will use your local version
|
||||||
|
|
||||||
Checkout customize_, other plugins_ or `get in contact`_.
|
Checkout customize_, other plugins_ or `get in contact`_.
|
||||||
|
|
||||||
.. include:: links.txt
|
.. include:: links.txt
|
||||||
|
|
|
@ -6,24 +6,24 @@ loop on failing tests, distribute test runs to CPUs and hosts.
|
||||||
.. contents::
|
.. contents::
|
||||||
:local:
|
:local:
|
||||||
|
|
||||||
The `pytest-xdist`_ plugin extends py.test with some unique
|
The `pytest-xdist`_ plugin extends py.test with some unique
|
||||||
test execution modes:
|
test execution modes:
|
||||||
|
|
||||||
* Looponfail: run your tests repeatedly in a subprocess. After each run py.test
|
* Looponfail: run your tests repeatedly in a subprocess. After each run py.test
|
||||||
waits until a file in your project changes and then re-runs the previously
|
waits until a file in your project changes and then re-runs the previously
|
||||||
failing tests. This is repeated until all tests pass after which again
|
failing tests. This is repeated until all tests pass after which again
|
||||||
a full run is performed.
|
a full run is performed.
|
||||||
|
|
||||||
* Load-balancing: if you have multiple CPUs or hosts you can use
|
* Load-balancing: if you have multiple CPUs or hosts you can use
|
||||||
those for a combined test run. This allows to speed up
|
those for a combined test run. This allows to speed up
|
||||||
development or to use special resources of remote machines.
|
development or to use special resources of remote machines.
|
||||||
|
|
||||||
* Multi-Platform coverage: you can specify different Python interpreters
|
* Multi-Platform coverage: you can specify different Python interpreters
|
||||||
or different platforms and run tests in parallel on all of them.
|
or different platforms and run tests in parallel on all of them.
|
||||||
|
|
||||||
Before running tests remotely, ``py.test`` efficiently synchronizes your
|
Before running tests remotely, ``py.test`` efficiently synchronizes your
|
||||||
program source code to the remote place. All test results
|
program source code to the remote place. All test results
|
||||||
are reported back and displayed to your local test session.
|
are reported back and displayed to your local test session.
|
||||||
You may specify different Python versions and interpreters.
|
You may specify different Python versions and interpreters.
|
||||||
|
|
||||||
.. _`pytest-xdist`: http://pypi.python.org/pypi/pytest-xdist
|
.. _`pytest-xdist`: http://pypi.python.org/pypi/pytest-xdist
|
||||||
|
@ -38,11 +38,11 @@ To send tests to multiple CPUs, type::
|
||||||
|
|
||||||
py.test -n NUM
|
py.test -n NUM
|
||||||
|
|
||||||
Especially for longer running tests or tests requiring
|
Especially for longer running tests or tests requiring
|
||||||
a lot of IO this can lead to considerable speed ups.
|
a lot of IO this can lead to considerable speed ups.
|
||||||
|
|
||||||
|
|
||||||
Running tests in a Python subprocess
|
Running tests in a Python subprocess
|
||||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
To instantiate a python2.4 sub process and send tests to it, you may type::
|
To instantiate a python2.4 sub process and send tests to it, you may type::
|
||||||
|
@ -50,51 +50,51 @@ To instantiate a python2.4 sub process and send tests to it, you may type::
|
||||||
py.test -d --tx popen//python=python2.4
|
py.test -d --tx popen//python=python2.4
|
||||||
|
|
||||||
This will start a subprocess which is run with the "python2.4"
|
This will start a subprocess which is run with the "python2.4"
|
||||||
Python interpreter, found in your system binary lookup path.
|
Python interpreter, found in your system binary lookup path.
|
||||||
|
|
||||||
If you prefix the --tx option value like this::
|
If you prefix the --tx option value like this::
|
||||||
|
|
||||||
--tx 3*popen//python=python2.4
|
--tx 3*popen//python=python2.4
|
||||||
|
|
||||||
then three subprocesses would be created and tests
|
then three subprocesses would be created and tests
|
||||||
will be load-balanced across these three processes.
|
will be load-balanced across these three processes.
|
||||||
|
|
||||||
|
|
||||||
Sending tests to remote SSH accounts
|
Sending tests to remote SSH accounts
|
||||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
Suppose you have a package ``mypkg`` which contains some
|
Suppose you have a package ``mypkg`` which contains some
|
||||||
tests that you can successfully run locally. And you
|
tests that you can successfully run locally. And you
|
||||||
have a ssh-reachable machine ``myhost``. Then
|
have a ssh-reachable machine ``myhost``. Then
|
||||||
you can ad-hoc distribute your tests by typing::
|
you can ad-hoc distribute your tests by typing::
|
||||||
|
|
||||||
py.test -d --tx ssh=myhostpopen --rsyncdir mypkg mypkg
|
py.test -d --tx ssh=myhostpopen --rsyncdir mypkg mypkg
|
||||||
|
|
||||||
This will synchronize your ``mypkg`` package directory
|
This will synchronize your ``mypkg`` package directory
|
||||||
to an remote ssh account and then locally collect tests
|
to an remote ssh account and then locally collect tests
|
||||||
and send them to remote places for execution.
|
and send them to remote places for execution.
|
||||||
|
|
||||||
You can specify multiple ``--rsyncdir`` directories
|
You can specify multiple ``--rsyncdir`` directories
|
||||||
to be sent to the remote side.
|
to be sent to the remote side.
|
||||||
|
|
||||||
**NOTE:** For py.test to collect and send tests correctly
|
**NOTE:** For py.test to collect and send tests correctly
|
||||||
you not only need to make sure all code and tests
|
you not only need to make sure all code and tests
|
||||||
directories are rsynced, but that any test (sub) directory
|
directories are rsynced, but that any test (sub) directory
|
||||||
also has an ``__init__.py`` file because internally
|
also has an ``__init__.py`` file because internally
|
||||||
py.test references tests as a fully qualified python
|
py.test references tests as a fully qualified python
|
||||||
module path. **You will otherwise get strange errors**
|
module path. **You will otherwise get strange errors**
|
||||||
during setup of the remote side.
|
during setup of the remote side.
|
||||||
|
|
||||||
Sending tests to remote Socket Servers
|
Sending tests to remote Socket Servers
|
||||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
Download the single-module `socketserver.py`_ Python program
|
Download the single-module `socketserver.py`_ Python program
|
||||||
and run it like this::
|
and run it like this::
|
||||||
|
|
||||||
python socketserver.py
|
python socketserver.py
|
||||||
|
|
||||||
It will tell you that it starts listening on the default
|
It will tell you that it starts listening on the default
|
||||||
port. You can now on your home machine specify this
|
port. You can now on your home machine specify this
|
||||||
new socket host with something like this::
|
new socket host with something like this::
|
||||||
|
|
||||||
py.test -d --tx socket=192.168.1.102:8888 --rsyncdir mypkg mypkg
|
py.test -d --tx socket=192.168.1.102:8888 --rsyncdir mypkg mypkg
|
||||||
|
@ -102,17 +102,17 @@ new socket host with something like this::
|
||||||
|
|
||||||
.. _`atonce`:
|
.. _`atonce`:
|
||||||
|
|
||||||
Running tests on many platforms at once
|
Running tests on many platforms at once
|
||||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
The basic command to run tests on multiple platforms is::
|
The basic command to run tests on multiple platforms is::
|
||||||
|
|
||||||
py.test --dist=each --tx=spec1 --tx=spec2
|
py.test --dist=each --tx=spec1 --tx=spec2
|
||||||
|
|
||||||
If you specify a windows host, an OSX host and a Linux
|
If you specify a windows host, an OSX host and a Linux
|
||||||
environment this command will send each tests to all
|
environment this command will send each tests to all
|
||||||
platforms - and report back failures from all platforms
|
platforms - and report back failures from all platforms
|
||||||
at once. The specifications strings use the `xspec syntax`_.
|
at once. The specifications strings use the `xspec syntax`_.
|
||||||
|
|
||||||
.. _`xspec syntax`: http://codespeak.net/execnet/trunk/basics.html#xspec
|
.. _`xspec syntax`: http://codespeak.net/execnet/trunk/basics.html#xspec
|
||||||
|
|
||||||
|
@ -123,14 +123,14 @@ at once. The specifications strings use the `xspec syntax`_.
|
||||||
Specifying test exec environments in a conftest.py
|
Specifying test exec environments in a conftest.py
|
||||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
Instead of specifying command line options, you can
|
Instead of specifying command line options, you can
|
||||||
put options values in a ``conftest.py`` file like this::
|
put options values in a ``conftest.py`` file like this::
|
||||||
|
|
||||||
option_tx = ['ssh=myhost//python=python2.5', 'popen//python=python2.5']
|
option_tx = ['ssh=myhost//python=python2.5', 'popen//python=python2.5']
|
||||||
option_dist = True
|
option_dist = True
|
||||||
|
|
||||||
Any commandline ``--tx`` specifictions will add to the list of
|
Any commandline ``--tx`` specifictions will add to the list of
|
||||||
available execution environments.
|
available execution environments.
|
||||||
|
|
||||||
Specifying "rsync" dirs in a conftest.py
|
Specifying "rsync" dirs in a conftest.py
|
||||||
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
@ -156,11 +156,11 @@ command line options
|
||||||
box each test run in a separate process (unix)
|
box each test run in a separate process (unix)
|
||||||
``--dist=distmode``
|
``--dist=distmode``
|
||||||
set mode for distributing tests to exec environments.
|
set mode for distributing tests to exec environments.
|
||||||
|
|
||||||
each: send each test to each available environment.
|
each: send each test to each available environment.
|
||||||
|
|
||||||
load: send each test to available environment.
|
load: send each test to available environment.
|
||||||
|
|
||||||
(default) no: run tests inprocess, don't distribute.
|
(default) no: run tests inprocess, don't distribute.
|
||||||
``--tx=xspec``
|
``--tx=xspec``
|
||||||
add a test execution environment. some examples: --tx popen//python=python2.5 --tx socket=192.168.1.102:8888 --tx ssh=user@codespeak.net//chdir=testcache
|
add a test execution environment. some examples: --tx popen//python=python2.5 --tx socket=192.168.1.102:8888 --tx ssh=user@codespeak.net//chdir=testcache
|
||||||
|
|
|
@ -9,13 +9,13 @@ Quickstart
|
||||||
|
|
||||||
If you have the ``easy_install`` tool (otherwise see here_) just type::
|
If you have the ``easy_install`` tool (otherwise see here_) just type::
|
||||||
|
|
||||||
easy_install -U py
|
easy_install -U py
|
||||||
|
|
||||||
Now create a file ``test_sample.py`` with the following content:
|
Now create a file ``test_sample.py`` with the following content:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
# content of test_sample.py
|
# content of test_sample.py
|
||||||
def func(x):
|
def func(x):
|
||||||
return x + 1
|
return x + 1
|
||||||
def test_answer():
|
def test_answer():
|
||||||
|
@ -27,7 +27,7 @@ You can now run the test file like this::
|
||||||
|
|
||||||
and will see output like this:
|
and will see output like this:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
=========================== test session starts ============================
|
=========================== test session starts ============================
|
||||||
python: platform linux2 -- Python 2.6.2 -- pytest-1.1.0
|
python: platform linux2 -- Python 2.6.2 -- pytest-1.1.0
|
||||||
|
@ -46,14 +46,14 @@ and will see output like this:
|
||||||
test_sample.py:6: AssertionError
|
test_sample.py:6: AssertionError
|
||||||
========================= 1 failed in 0.08 seconds =========================
|
========================= 1 failed in 0.08 seconds =========================
|
||||||
|
|
||||||
This output contains Python interpreter information, a list of test objects,
|
This output contains Python interpreter information, a list of test objects,
|
||||||
a progress report and important details of the failure.
|
a progress report and important details of the failure.
|
||||||
|
|
||||||
**Where to go from here**
|
**Where to go from here**
|
||||||
|
|
||||||
`features`_: overview and description of test features
|
`features`_: overview and description of test features
|
||||||
|
|
||||||
`plugins`_: a list of available plugins which each contain usage examples
|
`plugins`_: a list of available plugins which each contain usage examples
|
||||||
|
|
||||||
`tutorials`_: some blog entries and starting points with code examples
|
`tutorials`_: some blog entries and starting points with code examples
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
==========================
|
==========================
|
||||||
Talks and Tutorials
|
Talks and Tutorials
|
||||||
==========================
|
==========================
|
||||||
|
|
||||||
.. _`funcargs`: funcargs.html
|
.. _`funcargs`: funcargs.html
|
||||||
|
@ -10,33 +10,33 @@ tutorial examples and blog postings
|
||||||
.. _`tutorial1 repository`: http://bitbucket.org/hpk42/pytest-tutorial1/
|
.. _`tutorial1 repository`: http://bitbucket.org/hpk42/pytest-tutorial1/
|
||||||
.. _`pycon 2010 tutorial PDF`: http://bitbucket.org/hpk42/pytest-tutorial1/raw/tip/pytest-basic.pdf
|
.. _`pycon 2010 tutorial PDF`: http://bitbucket.org/hpk42/pytest-tutorial1/raw/tip/pytest-basic.pdf
|
||||||
|
|
||||||
basic usage and funcargs:
|
basic usage and funcargs:
|
||||||
|
|
||||||
- `pycon 2010 tutorial PDF`_ and `tutorial1 repository`_
|
- `pycon 2010 tutorial PDF`_ and `tutorial1 repository`_
|
||||||
|
|
||||||
function arguments:
|
function arguments:
|
||||||
|
|
||||||
- `application setup in test functions with funcargs`_
|
- `application setup in test functions with funcargs`_
|
||||||
- `making funcargs dependendent on command line options`_
|
- `making funcargs dependendent on command line options`_
|
||||||
- `monkey patching done right`_ (blog post, consult `monkeypatch
|
- `monkey patching done right`_ (blog post, consult `monkeypatch
|
||||||
plugin`_ for actual 1.0 API)
|
plugin`_ for actual 1.0 API)
|
||||||
|
|
||||||
test parametrization:
|
|
||||||
|
|
||||||
- `generating parametrized tests with funcargs`_
|
test parametrization:
|
||||||
- `test generators and cached setup`_
|
|
||||||
- `parametrizing tests, generalized`_ (blog post)
|
|
||||||
- `putting test-hooks into local or global plugins`_ (blog post)
|
|
||||||
|
|
||||||
distributed testing:
|
- `generating parametrized tests with funcargs`_
|
||||||
|
- `test generators and cached setup`_
|
||||||
|
- `parametrizing tests, generalized`_ (blog post)
|
||||||
|
- `putting test-hooks into local or global plugins`_ (blog post)
|
||||||
|
|
||||||
- `simultanously test your code on all platforms`_ (blog entry)
|
distributed testing:
|
||||||
|
|
||||||
plugin specific examples:
|
- `simultanously test your code on all platforms`_ (blog entry)
|
||||||
|
|
||||||
|
plugin specific examples:
|
||||||
|
|
||||||
- `skipping slow tests by default in py.test`_ (blog entry)
|
- `skipping slow tests by default in py.test`_ (blog entry)
|
||||||
|
|
||||||
- `many examples in the docs for plugins`_
|
- `many examples in the docs for plugins`_
|
||||||
|
|
||||||
.. _`skipping slow tests by default in py.test`: http://bruynooghe.blogspot.com/2009/12/skipping-slow-test-by-default-in-pytest.html
|
.. _`skipping slow tests by default in py.test`: http://bruynooghe.blogspot.com/2009/12/skipping-slow-test-by-default-in-pytest.html
|
||||||
.. _`making funcargs dependendent on command line options`: funcargs.html#tut-cmdlineoption
|
.. _`making funcargs dependendent on command line options`: funcargs.html#tut-cmdlineoption
|
||||||
|
@ -44,28 +44,28 @@ plugin specific examples:
|
||||||
.. _`monkeypatch plugin`: plugin/monkeypatch.html
|
.. _`monkeypatch plugin`: plugin/monkeypatch.html
|
||||||
.. _`application setup in test functions with funcargs`: funcargs.html#appsetup
|
.. _`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/
|
.. _`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/
|
.. _`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/
|
.. _`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/
|
.. _`parametrizing tests, generalized`: http://tetamap.wordpress.com/2009/05/13/parametrizing-python-tests-generalized/
|
||||||
.. _`generating parametrized tests with funcargs`: funcargs.html#test-generators
|
.. _`generating parametrized tests with funcargs`: funcargs.html#test-generators
|
||||||
.. _`test generators and cached setup`: http://bruynooghe.blogspot.com/2010/06/pytest-test-generators-and-cached-setup.html
|
.. _`test generators and cached setup`: http://bruynooghe.blogspot.com/2010/06/pytest-test-generators-and-cached-setup.html
|
||||||
|
|
||||||
conference talks and tutorials
|
conference talks and tutorials
|
||||||
----------------------------------------
|
----------------------------------------
|
||||||
|
|
||||||
- `ep2009-rapidtesting.pdf`_ tutorial slides (July 2009):
|
- `ep2009-rapidtesting.pdf`_ tutorial slides (July 2009):
|
||||||
|
|
||||||
- testing terminology
|
- testing terminology
|
||||||
- basic py.test usage, file system layout
|
- basic py.test usage, file system layout
|
||||||
- test function arguments (funcargs_) and test fixtures
|
- test function arguments (funcargs_) and test fixtures
|
||||||
- existing plugins
|
- existing plugins
|
||||||
- distributed testing
|
- distributed testing
|
||||||
|
|
||||||
- `ep2009-pytest.pdf`_ 60 minute py.test talk, highlighting unique features and a roadmap (July 2009)
|
- `ep2009-pytest.pdf`_ 60 minute py.test talk, highlighting unique features and a roadmap (July 2009)
|
||||||
|
|
||||||
- `pycon2009-pytest-introduction.zip`_ slides and files, extended version of py.test basic introduction, discusses more options, also introduces old-style xUnit setup, looponfailing and other features.
|
- `pycon2009-pytest-introduction.zip`_ slides and files, extended version of py.test basic introduction, discusses more options, also introduces old-style xUnit setup, looponfailing and other features.
|
||||||
|
|
||||||
- `pycon2009-pytest-advanced.pdf`_ contain a slightly older version of funcargs and distributed testing, compared to the EuroPython 2009 slides.
|
- `pycon2009-pytest-advanced.pdf`_ contain a slightly older version of funcargs and distributed testing, compared to the EuroPython 2009 slides.
|
||||||
|
|
||||||
.. _`ep2009-rapidtesting.pdf`: http://codespeak.net/download/py/ep2009-rapidtesting.pdf
|
.. _`ep2009-rapidtesting.pdf`: http://codespeak.net/download/py/ep2009-rapidtesting.pdf
|
||||||
.. _`ep2009-pytest.pdf`: http://codespeak.net/download/py/ep2009-pytest.pdf
|
.. _`ep2009-pytest.pdf`: http://codespeak.net/download/py/ep2009-pytest.pdf
|
||||||
|
|
|
@ -7,29 +7,29 @@ extended xUnit style setup
|
||||||
.. _`unittest plugin`: plugin/unittest.html
|
.. _`unittest plugin`: plugin/unittest.html
|
||||||
.. _`xUnit`: http://en.wikipedia.org/wiki/XUnit
|
.. _`xUnit`: http://en.wikipedia.org/wiki/XUnit
|
||||||
|
|
||||||
Note:
|
Note:
|
||||||
|
|
||||||
Since version 1.0 funcargs_ present the new and
|
Since version 1.0 funcargs_ present the new and
|
||||||
more powerful way to manage test setups with larger
|
more powerful way to manage test setups with larger
|
||||||
test suites. *funcargs* also provide flexible
|
test suites. *funcargs* also provide flexible
|
||||||
`test parametrization`_ which goes way beyond
|
`test parametrization`_ which goes way beyond
|
||||||
what you can do with the xUnit setup/teardown-method
|
what you can do with the xUnit setup/teardown-method
|
||||||
patter.
|
patter.
|
||||||
|
|
||||||
Python, Java and many other languages have a tradition
|
Python, Java and many other languages have a tradition
|
||||||
of using xUnit_ style testing. This typically
|
of using xUnit_ style testing. This typically
|
||||||
involves the call of a ``setup`` method before
|
involves the call of a ``setup`` method before
|
||||||
a test function is run and ``teardown`` after
|
a test function is run and ``teardown`` after
|
||||||
it finishes. With ``py.test`` there are three
|
it finishes. With ``py.test`` there are three
|
||||||
scopes for which you can provide setup/teardown
|
scopes for which you can provide setup/teardown
|
||||||
hooks to provide test fixtures: per-module, per-class
|
hooks to provide test fixtures: per-module, per-class
|
||||||
and per-method/function. ``py.test`` will
|
and per-method/function. ``py.test`` will
|
||||||
discover and call according methods automatically.
|
discover and call according methods automatically.
|
||||||
|
|
||||||
The `unittest plugin`_ also will intregate ``unittest.TestCase``
|
The `unittest plugin`_ also will intregate ``unittest.TestCase``
|
||||||
instances into a test run and call respective setup/teardown methods.
|
instances into a test run and call respective setup/teardown methods.
|
||||||
|
|
||||||
All setup/teardown methods are optional.
|
All setup/teardown methods are optional.
|
||||||
|
|
||||||
The following methods are called at module level if they exist:
|
The following methods are called at module level if they exist:
|
||||||
|
|
||||||
|
@ -37,45 +37,45 @@ The following methods are called at module level if they exist:
|
||||||
|
|
||||||
def setup_module(module):
|
def setup_module(module):
|
||||||
""" setup up any state specific to the execution
|
""" setup up any state specific to the execution
|
||||||
of the given module.
|
of the given module.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def teardown_module(module):
|
def teardown_module(module):
|
||||||
""" teardown any state that was previously setup
|
""" teardown any state that was previously setup
|
||||||
with a setup_module method.
|
with a setup_module method.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
The following hooks are available for test classes:
|
The following hooks are available for test classes:
|
||||||
|
|
||||||
.. sourcecode:: python
|
.. sourcecode:: python
|
||||||
|
|
||||||
def setup_class(cls):
|
def setup_class(cls):
|
||||||
""" setup up any state specific to the execution
|
""" setup up any state specific to the execution
|
||||||
of the given class (which usually contains tests).
|
of the given class (which usually contains tests).
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def teardown_class(cls):
|
def teardown_class(cls):
|
||||||
""" teardown any state that was previously setup
|
""" teardown any state that was previously setup
|
||||||
with a call to setup_class.
|
with a call to setup_class.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def setup_method(self, method):
|
def setup_method(self, method):
|
||||||
""" setup up any state tied to the execution of the given
|
""" setup up any state tied to the execution of the given
|
||||||
method in a class. setup_method is invoked for every
|
method in a class. setup_method is invoked for every
|
||||||
test method of a class.
|
test method of a class.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def teardown_method(self, method):
|
def teardown_method(self, method):
|
||||||
""" teardown any state that was previously setup
|
""" teardown any state that was previously setup
|
||||||
with a setup_method call.
|
with a setup_method call.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
The last two hooks, ``setup_method`` and ``teardown_method``, are
|
The last two hooks, ``setup_method`` and ``teardown_method``, are
|
||||||
equivalent to ``setUp`` and ``tearDown`` in the Python standard
|
equivalent to ``setUp`` and ``tearDown`` in the Python standard
|
||||||
library's `unittest.py module`_.
|
library's `unittest.py module`_.
|
||||||
|
|
||||||
Note that it possible that setup/teardown pairs are invoked multiple
|
Note that it possible that setup/teardown pairs are invoked multiple
|
||||||
times per testing process.
|
times per testing process.
|
||||||
|
|
||||||
.. _`unittest.py module`: http://docs.python.org/library/unittest.html
|
.. _`unittest.py module`: http://docs.python.org/library/unittest.html
|
||||||
|
|
||||||
|
|
132
doc/xml.txt
132
doc/xml.txt
|
@ -1,52 +1,52 @@
|
||||||
====================================================
|
====================================================
|
||||||
py.xml: Lightweight and flexible xml/html generation
|
py.xml: Lightweight and flexible xml/html generation
|
||||||
====================================================
|
====================================================
|
||||||
|
|
||||||
|
|
||||||
Motivation
|
Motivation
|
||||||
==========
|
==========
|
||||||
|
|
||||||
There are a plethora of frameworks and libraries to generate
|
There are a plethora of frameworks and libraries to generate
|
||||||
xml and html trees. However, many of them are large, have a
|
xml and html trees. However, many of them are large, have a
|
||||||
steep learning curve and are often hard to debug. Not to
|
steep learning curve and are often hard to debug. Not to
|
||||||
speak of the fact that they are frameworks to begin with.
|
speak of the fact that they are frameworks to begin with.
|
||||||
|
|
||||||
The py lib strives to offer enough functionality to represent
|
The py lib strives to offer enough functionality to represent
|
||||||
itself and especially its API in html or xml.
|
itself and especially its API in html or xml.
|
||||||
|
|
||||||
.. _xist: http://www.livinglogic.de/Python/xist/index.html
|
.. _xist: http://www.livinglogic.de/Python/xist/index.html
|
||||||
|
|
||||||
a pythonic object model , please
|
a pythonic object model , please
|
||||||
================================
|
================================
|
||||||
|
|
||||||
The py lib offers a pythonic way to generate xml/html, based on
|
The py lib offers a pythonic way to generate xml/html, based on
|
||||||
ideas from xist_ which `uses python class objects`_ to build
|
ideas from xist_ which `uses python class objects`_ to build
|
||||||
xml trees. However, xist_'s implementation is somewhat heavy
|
xml trees. However, xist_'s implementation is somewhat heavy
|
||||||
because it has additional goals like transformations and
|
because it has additional goals like transformations and
|
||||||
supporting many namespaces. But its basic idea is very easy.
|
supporting many namespaces. But its basic idea is very easy.
|
||||||
|
|
||||||
.. _`uses python class objects`: http://www.livinglogic.de/Python/xist/Howto.html
|
.. _`uses python class objects`: http://www.livinglogic.de/Python/xist/Howto.html
|
||||||
|
|
||||||
generating arbitrary xml structures
|
generating arbitrary xml structures
|
||||||
-----------------------------------
|
-----------------------------------
|
||||||
|
|
||||||
With ``py.xml.Namespace`` you have the basis
|
With ``py.xml.Namespace`` you have the basis
|
||||||
to generate custom xml-fragments on the fly::
|
to generate custom xml-fragments on the fly::
|
||||||
|
|
||||||
class ns(py.xml.Namespace):
|
class ns(py.xml.Namespace):
|
||||||
"my custom xml namespace"
|
"my custom xml namespace"
|
||||||
doc = ns.books(
|
doc = ns.books(
|
||||||
ns.book(
|
ns.book(
|
||||||
ns.author("May Day"),
|
ns.author("May Day"),
|
||||||
ns.title("python for java programmers"),),
|
ns.title("python for java programmers"),),
|
||||||
ns.book(
|
ns.book(
|
||||||
ns.author("why"),
|
ns.author("why"),
|
||||||
ns.title("Java for Python programmers"),),
|
ns.title("Java for Python programmers"),),
|
||||||
publisher="N.N",
|
publisher="N.N",
|
||||||
)
|
)
|
||||||
print doc.unicode(indent=2).encode('utf8')
|
print doc.unicode(indent=2).encode('utf8')
|
||||||
|
|
||||||
will give you this representation::
|
will give you this representation::
|
||||||
|
|
||||||
<books publisher="N.N">
|
<books publisher="N.N">
|
||||||
<book>
|
<book>
|
||||||
|
@ -56,42 +56,42 @@ will give you this representation::
|
||||||
<author>why</author>
|
<author>why</author>
|
||||||
<title>Java for Python programmers</title></book></books>
|
<title>Java for Python programmers</title></book></books>
|
||||||
|
|
||||||
In a sentence: positional arguments are child-tags and
|
In a sentence: positional arguments are child-tags and
|
||||||
keyword-arguments are attributes.
|
keyword-arguments are attributes.
|
||||||
|
|
||||||
On a side note, you'll see that the unicode-serializer
|
On a side note, you'll see that the unicode-serializer
|
||||||
supports a nice indentation style which keeps your generated
|
supports a nice indentation style which keeps your generated
|
||||||
html readable, basically through emulating python's white
|
html readable, basically through emulating python's white
|
||||||
space significance by putting closing-tags rightmost and
|
space significance by putting closing-tags rightmost and
|
||||||
almost invisible at first glance :-)
|
almost invisible at first glance :-)
|
||||||
|
|
||||||
basic example for generating html
|
basic example for generating html
|
||||||
---------------------------------
|
---------------------------------
|
||||||
|
|
||||||
Consider this example::
|
Consider this example::
|
||||||
|
|
||||||
from py.xml import html # html namespace
|
from py.xml import html # html namespace
|
||||||
|
|
||||||
paras = "First Para", "Second para"
|
paras = "First Para", "Second para"
|
||||||
|
|
||||||
doc = html.html(
|
doc = html.html(
|
||||||
html.head(
|
html.head(
|
||||||
html.meta(name="Content-Type", value="text/html; charset=latin1")),
|
html.meta(name="Content-Type", value="text/html; charset=latin1")),
|
||||||
html.body(
|
html.body(
|
||||||
[html.p(p) for p in paras]))
|
[html.p(p) for p in paras]))
|
||||||
|
|
||||||
print unicode(doc).encode('latin1')
|
print unicode(doc).encode('latin1')
|
||||||
|
|
||||||
Again, tags are objects which contain tags and have attributes.
|
Again, tags are objects which contain tags and have attributes.
|
||||||
More exactly, Tags inherit from the list type and thus can be
|
More exactly, Tags inherit from the list type and thus can be
|
||||||
manipulated as list objects. They additionally support a default
|
manipulated as list objects. They additionally support a default
|
||||||
way to represent themselves as a serialized unicode object.
|
way to represent themselves as a serialized unicode object.
|
||||||
|
|
||||||
If you happen to look at the py.xml implementation you'll
|
If you happen to look at the py.xml implementation you'll
|
||||||
note that the tag/namespace implementation consumes some 50 lines
|
note that the tag/namespace implementation consumes some 50 lines
|
||||||
with another 50 lines for the unicode serialization code.
|
with another 50 lines for the unicode serialization code.
|
||||||
|
|
||||||
CSS-styling your html Tags
|
CSS-styling your html Tags
|
||||||
--------------------------
|
--------------------------
|
||||||
|
|
||||||
One aspect where many of the huge python xml/html generation
|
One aspect where many of the huge python xml/html generation
|
||||||
|
@ -100,37 +100,37 @@ of CSS styling. Often, developers are left alone with keeping
|
||||||
CSS style definitions in sync with some style files
|
CSS style definitions in sync with some style files
|
||||||
represented as strings (often in a separate .css file). Not
|
represented as strings (often in a separate .css file). Not
|
||||||
only is this hard to debug but the missing abstractions make
|
only is this hard to debug but the missing abstractions make
|
||||||
it hard to modify the styling of your tags or to choose custom
|
it hard to modify the styling of your tags or to choose custom
|
||||||
style representations (inline, html.head or external). Add the
|
style representations (inline, html.head or external). Add the
|
||||||
Browers usual tolerance of messyness and errors in Style
|
Browers usual tolerance of messyness and errors in Style
|
||||||
references and welcome to hell, known as the domain of
|
references and welcome to hell, known as the domain of
|
||||||
developing web applications :-)
|
developing web applications :-)
|
||||||
|
|
||||||
By contrast, consider this CSS styling example::
|
By contrast, consider this CSS styling example::
|
||||||
|
|
||||||
class my(html):
|
class my(html):
|
||||||
"my initial custom style"
|
"my initial custom style"
|
||||||
class body(html.body):
|
class body(html.body):
|
||||||
style = html.Style(font_size = "120%")
|
style = html.Style(font_size = "120%")
|
||||||
|
|
||||||
class h2(html.h2):
|
class h2(html.h2):
|
||||||
style = html.Style(background = "grey")
|
style = html.Style(background = "grey")
|
||||||
|
|
||||||
class p(html.p):
|
class p(html.p):
|
||||||
style = html.Style(font_weight="bold")
|
style = html.Style(font_weight="bold")
|
||||||
|
|
||||||
doc = my.html(
|
doc = my.html(
|
||||||
my.head(),
|
my.head(),
|
||||||
my.body(
|
my.body(
|
||||||
my.h2("hello world"),
|
my.h2("hello world"),
|
||||||
my.p("bold as bold can")
|
my.p("bold as bold can")
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
print doc.unicode(indent=2)
|
|
||||||
|
|
||||||
This will give you a small'n mean self contained
|
print doc.unicode(indent=2)
|
||||||
represenation by default::
|
|
||||||
|
This will give you a small'n mean self contained
|
||||||
|
represenation by default::
|
||||||
|
|
||||||
<html>
|
<html>
|
||||||
<head/>
|
<head/>
|
||||||
|
@ -139,19 +139,19 @@ represenation by default::
|
||||||
<p style="font-weight: bold">bold as bold can</p></body></html>
|
<p style="font-weight: bold">bold as bold can</p></body></html>
|
||||||
|
|
||||||
Most importantly, note that the inline-styling is just an
|
Most importantly, note that the inline-styling is just an
|
||||||
implementation detail of the unicode serialization code.
|
implementation detail of the unicode serialization code.
|
||||||
You can easily modify the serialization to put your styling into the
|
You can easily modify the serialization to put your styling into the
|
||||||
``html.head`` or in a separate file and autogenerate CSS-class
|
``html.head`` or in a separate file and autogenerate CSS-class
|
||||||
names or ids.
|
names or ids.
|
||||||
|
|
||||||
Hey, you could even write tests that you are using correct
|
Hey, you could even write tests that you are using correct
|
||||||
styles suitable for specific browser requirements. Did i mention
|
styles suitable for specific browser requirements. Did i mention
|
||||||
that the ability to easily write tests for your generated
|
that the ability to easily write tests for your generated
|
||||||
html and its serialization could help to develop _stable_ user
|
html and its serialization could help to develop _stable_ user
|
||||||
interfaces?
|
interfaces?
|
||||||
|
|
||||||
More to come ...
|
More to come ...
|
||||||
----------------
|
----------------
|
||||||
|
|
||||||
For now, i don't think we should strive to offer much more
|
For now, i don't think we should strive to offer much more
|
||||||
than the above. However, it is probably not hard to offer
|
than the above. However, it is probably not hard to offer
|
||||||
|
@ -163,6 +163,6 @@ produce a list of unicode objects intermingled with callables.
|
||||||
At HTTP-Request time the callables would get called to
|
At HTTP-Request time the callables would get called to
|
||||||
complete the probably request-specific serialization of
|
complete the probably request-specific serialization of
|
||||||
your Tags. Hum, it's probably harder to explain this than to
|
your Tags. Hum, it's probably harder to explain this than to
|
||||||
actually code it :-)
|
actually code it :-)
|
||||||
|
|
||||||
.. _`py.test`: test/index.html
|
.. _`py.test`: test/index.html
|
||||||
|
|
|
@ -2,25 +2,25 @@ Execnet / Path combination
|
||||||
|
|
||||||
I think the nice code in this directory
|
I think the nice code in this directory
|
||||||
should be refactored so that you can use
|
should be refactored so that you can use
|
||||||
it like this:
|
it like this:
|
||||||
|
|
||||||
rp = gateway.get_remote_path(relpath)
|
rp = gateway.get_remote_path(relpath)
|
||||||
|
|
||||||
and relpath could be absolute, relative (should
|
and relpath could be absolute, relative (should
|
||||||
follow remote-platform syntax) or None/"." (the
|
follow remote-platform syntax) or None/"." (the
|
||||||
current dir on the other side).
|
current dir on the other side).
|
||||||
|
|
||||||
The tricky part probably is defining sensible
|
The tricky part probably is defining sensible
|
||||||
setup/teardown semantics with respect to
|
setup/teardown semantics with respect to
|
||||||
starting the "Path" server on the other side,
|
starting the "Path" server on the other side,
|
||||||
we at least don't want to have multiple threads
|
we at least don't want to have multiple threads
|
||||||
that serve path requests and maybe we want
|
that serve path requests and maybe we want
|
||||||
to be able to explicitely shutdown a once
|
to be able to explicitely shutdown a once
|
||||||
started RemotePath server (not sure though).
|
started RemotePath server (not sure though).
|
||||||
|
|
||||||
For a single-threaded py.execnet it might be helpful to be
|
For a single-threaded py.execnet it might be helpful to be
|
||||||
able to install new network messages (which are lower level
|
able to install new network messages (which are lower level
|
||||||
than remote_exec() and work with callbacks, so don't follow
|
than remote_exec() and work with callbacks, so don't follow
|
||||||
the nice "synchronous" programming model that you get with
|
the nice "synchronous" programming model that you get with
|
||||||
threads/greenlets/tasklets).
|
threads/greenlets/tasklets).
|
||||||
|
|
||||||
|
|
|
@ -24,7 +24,7 @@ URL related notes
|
||||||
characters that aren't allowed in URL paths (such as :, @, %, etc.) should
|
characters that aren't allowed in URL paths (such as :, @, %, etc.) should
|
||||||
be replaced with a % sign following the ASCII value of the character (two
|
be replaced with a % sign following the ASCII value of the character (two
|
||||||
digit HEX)
|
digit HEX)
|
||||||
|
|
||||||
an exception (the only one I could find so far) is the drive letter in a file
|
an exception (the only one I could find so far) is the drive letter in a file
|
||||||
URL in windows, the following path was required to get a file 'bar' from a
|
URL in windows, the following path was required to get a file 'bar' from a
|
||||||
repo in 'c:\\foo'::
|
repo in 'c:\\foo'::
|
||||||
|
|
|
@ -4,7 +4,7 @@ py.test and pylib: rapid testing and development utils
|
||||||
this module uses apipkg.py for lazy-loading sub modules
|
this module uses apipkg.py for lazy-loading sub modules
|
||||||
and classes. The initpkg-dictionary below specifies
|
and classes. The initpkg-dictionary below specifies
|
||||||
name->value mappings where value can be another namespace
|
name->value mappings where value can be another namespace
|
||||||
dictionary or an import path.
|
dictionary or an import path.
|
||||||
|
|
||||||
(c) Holger Krekel and others, 2004-2010
|
(c) Holger Krekel and others, 2004-2010
|
||||||
"""
|
"""
|
||||||
|
@ -137,7 +137,7 @@ py.apipkg.initpkg(__name__, dict(
|
||||||
'StdCapture' : '._io.capture:StdCapture',
|
'StdCapture' : '._io.capture:StdCapture',
|
||||||
'StdCaptureFD' : '._io.capture:StdCaptureFD',
|
'StdCaptureFD' : '._io.capture:StdCaptureFD',
|
||||||
'TerminalWriter' : '._io.terminalwriter:TerminalWriter',
|
'TerminalWriter' : '._io.terminalwriter:TerminalWriter',
|
||||||
'ansi_print' : '._io.terminalwriter:ansi_print',
|
'ansi_print' : '._io.terminalwriter:ansi_print',
|
||||||
'get_terminal_width' : '._io.terminalwriter:get_terminal_width',
|
'get_terminal_width' : '._io.terminalwriter:get_terminal_width',
|
||||||
'saferepr' : '._io.saferepr:saferepr',
|
'saferepr' : '._io.saferepr:saferepr',
|
||||||
},
|
},
|
||||||
|
|
|
@ -67,10 +67,10 @@ except NameError:
|
||||||
try:
|
try:
|
||||||
set, frozenset = set, frozenset
|
set, frozenset = set, frozenset
|
||||||
except NameError:
|
except NameError:
|
||||||
from sets import set, frozenset
|
from sets import set, frozenset
|
||||||
|
|
||||||
# pass through
|
# pass through
|
||||||
enumerate = enumerate
|
enumerate = enumerate
|
||||||
|
|
||||||
try:
|
try:
|
||||||
BaseException = BaseException
|
BaseException = BaseException
|
||||||
|
@ -91,8 +91,8 @@ if sys.version_info >= (3, 0):
|
||||||
exec ("print_ = print ; exec_=exec")
|
exec ("print_ = print ; exec_=exec")
|
||||||
import builtins
|
import builtins
|
||||||
|
|
||||||
# some backward compatibility helpers
|
# some backward compatibility helpers
|
||||||
_basestring = str
|
_basestring = str
|
||||||
def _totext(obj, encoding=None):
|
def _totext(obj, encoding=None):
|
||||||
if isinstance(obj, bytes):
|
if isinstance(obj, bytes):
|
||||||
obj = obj.decode(encoding)
|
obj = obj.decode(encoding)
|
||||||
|
@ -100,9 +100,9 @@ if sys.version_info >= (3, 0):
|
||||||
obj = str(obj)
|
obj = str(obj)
|
||||||
return obj
|
return obj
|
||||||
|
|
||||||
def _isbytes(x):
|
def _isbytes(x):
|
||||||
return isinstance(x, bytes)
|
return isinstance(x, bytes)
|
||||||
def _istext(x):
|
def _istext(x):
|
||||||
return isinstance(x, str)
|
return isinstance(x, str)
|
||||||
|
|
||||||
def _getimself(function):
|
def _getimself(function):
|
||||||
|
@ -135,13 +135,13 @@ if sys.version_info >= (3, 0):
|
||||||
|
|
||||||
else:
|
else:
|
||||||
import __builtin__ as builtins
|
import __builtin__ as builtins
|
||||||
_totext = unicode
|
_totext = unicode
|
||||||
_basestring = basestring
|
_basestring = basestring
|
||||||
execfile = execfile
|
execfile = execfile
|
||||||
callable = callable
|
callable = callable
|
||||||
def _isbytes(x):
|
def _isbytes(x):
|
||||||
return isinstance(x, str)
|
return isinstance(x, str)
|
||||||
def _istext(x):
|
def _istext(x):
|
||||||
return isinstance(x, unicode)
|
return isinstance(x, unicode)
|
||||||
|
|
||||||
def _getimself(function):
|
def _getimself(function):
|
||||||
|
@ -157,7 +157,7 @@ else:
|
||||||
return getattr(function, "func_code", None)
|
return getattr(function, "func_code", None)
|
||||||
|
|
||||||
def print_(*args, **kwargs):
|
def print_(*args, **kwargs):
|
||||||
""" minimal backport of py3k print statement. """
|
""" minimal backport of py3k print statement. """
|
||||||
sep = ' '
|
sep = ' '
|
||||||
if 'sep' in kwargs:
|
if 'sep' in kwargs:
|
||||||
sep = kwargs.pop('sep')
|
sep = kwargs.pop('sep')
|
||||||
|
@ -177,16 +177,16 @@ else:
|
||||||
file.write(end)
|
file.write(end)
|
||||||
|
|
||||||
def exec_(obj, globals=None, locals=None):
|
def exec_(obj, globals=None, locals=None):
|
||||||
""" minimal backport of py3k exec statement. """
|
""" minimal backport of py3k exec statement. """
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
if globals is None:
|
if globals is None:
|
||||||
frame = sys._getframe(1)
|
frame = sys._getframe(1)
|
||||||
globals = frame.f_globals
|
globals = frame.f_globals
|
||||||
if locals is None:
|
if locals is None:
|
||||||
locals = frame.f_locals
|
locals = frame.f_locals
|
||||||
elif locals is None:
|
elif locals is None:
|
||||||
locals = globals
|
locals = globals
|
||||||
exec2(obj, globals, locals)
|
exec2(obj, globals, locals)
|
||||||
|
|
||||||
if sys.version_info >= (3,0):
|
if sys.version_info >= (3,0):
|
||||||
def _reraise(cls, val, tb):
|
def _reraise(cls, val, tb):
|
||||||
|
@ -200,11 +200,11 @@ def _reraise(cls, val, tb):
|
||||||
raise cls, val, tb
|
raise cls, val, tb
|
||||||
def exec2(obj, globals, locals):
|
def exec2(obj, globals, locals):
|
||||||
__tracebackhide__ = True
|
__tracebackhide__ = True
|
||||||
exec obj in globals, locals
|
exec obj in globals, locals
|
||||||
""")
|
""")
|
||||||
|
|
||||||
def _tryimport(*names):
|
def _tryimport(*names):
|
||||||
""" return the first successfully imported module. """
|
""" return the first successfully imported module. """
|
||||||
assert names
|
assert names
|
||||||
for name in names:
|
for name in names:
|
||||||
try:
|
try:
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""\
|
"""\
|
||||||
py.cleanup [PATH] ...
|
py.cleanup [PATH] ...
|
||||||
|
|
||||||
Delete typical python development related files recursively under the specified PATH (which defaults to the current working directory). Don't follow links and don't recurse into directories with a dot. Optionally remove setup.py related files and empty
|
Delete typical python development related files recursively under the specified PATH (which defaults to the current working directory). Don't follow links and don't recurse into directories with a dot. Optionally remove setup.py related files and empty
|
||||||
directories.
|
directories.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
import py
|
import py
|
||||||
|
@ -12,9 +12,9 @@ import sys, subprocess
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
parser = py.std.optparse.OptionParser(usage=__doc__)
|
parser = py.std.optparse.OptionParser(usage=__doc__)
|
||||||
parser.add_option("-e", metavar="ENDING",
|
parser.add_option("-e", metavar="ENDING",
|
||||||
dest="endings", default=[".pyc", "$py.class"], action="append",
|
dest="endings", default=[".pyc", "$py.class"], action="append",
|
||||||
help=("(multi) recursively remove files with the given ending."
|
help=("(multi) recursively remove files with the given ending."
|
||||||
" '.pyc' and '$py.class' are in the default list."))
|
" '.pyc' and '$py.class' are in the default list."))
|
||||||
parser.add_option("-d", action="store_true", dest="removedir",
|
parser.add_option("-d", action="store_true", dest="removedir",
|
||||||
help="remove empty directories.")
|
help="remove empty directories.")
|
||||||
|
@ -22,8 +22,8 @@ def main():
|
||||||
help="remove 'build' and 'dist' directories next to setup.py files")
|
help="remove 'build' and 'dist' directories next to setup.py files")
|
||||||
parser.add_option("-a", action="store_true", dest="all",
|
parser.add_option("-a", action="store_true", dest="all",
|
||||||
help="synonym for '-S -d -e pip-log.txt'")
|
help="synonym for '-S -d -e pip-log.txt'")
|
||||||
parser.add_option("-n", "--dryrun", dest="dryrun", default=False,
|
parser.add_option("-n", "--dryrun", dest="dryrun", default=False,
|
||||||
action="store_true",
|
action="store_true",
|
||||||
help="don't actually delete but display would-be-removed filenames.")
|
help="don't actually delete but display would-be-removed filenames.")
|
||||||
(options, args) = parser.parse_args()
|
(options, args) = parser.parse_args()
|
||||||
|
|
||||||
|
@ -44,9 +44,9 @@ class Cleanup:
|
||||||
if self.options.setup:
|
if self.options.setup:
|
||||||
for arg in self.args:
|
for arg in self.args:
|
||||||
self.setupclean(arg)
|
self.setupclean(arg)
|
||||||
|
|
||||||
for path in self.args:
|
for path in self.args:
|
||||||
py.builtin.print_("cleaning path", path,
|
py.builtin.print_("cleaning path", path,
|
||||||
"of extensions", self.options.endings)
|
"of extensions", self.options.endings)
|
||||||
for x in path.visit(self.shouldremove, self.recursedir):
|
for x in path.visit(self.shouldremove, self.recursedir):
|
||||||
self.remove(x)
|
self.remove(x)
|
||||||
|
@ -78,7 +78,7 @@ class Cleanup:
|
||||||
subprocess.call([sys.executable, str(setup)] + list(args))
|
subprocess.call([sys.executable, str(setup)] + list(args))
|
||||||
finally:
|
finally:
|
||||||
old.chdir()
|
old.chdir()
|
||||||
|
|
||||||
def setupclean(self, path):
|
def setupclean(self, path):
|
||||||
for x in path.visit("setup.py", self.recursedir):
|
for x in path.visit("setup.py", self.recursedir):
|
||||||
basepath = x.dirpath()
|
basepath = x.dirpath()
|
||||||
|
|
|
@ -64,7 +64,7 @@ def blocksplitter(fp):
|
||||||
blockstring = line # reset the block
|
blockstring = line # reset the block
|
||||||
else:
|
else:
|
||||||
blockstring += line
|
blockstring += line
|
||||||
|
|
||||||
blocklist.append(blockstring)
|
blocklist.append(blockstring)
|
||||||
return blocklist
|
return blocklist
|
||||||
|
|
||||||
|
@ -84,7 +84,7 @@ def rewrite_utest(block):
|
||||||
op = d[old][1] # the operator you will use , or '' if there is none.
|
op = d[old][1] # the operator you will use , or '' if there is none.
|
||||||
possible_args = d[old][2] # a list of the number of arguments the
|
possible_args = d[old][2] # a list of the number of arguments the
|
||||||
# unittest function could possibly take.
|
# unittest function could possibly take.
|
||||||
|
|
||||||
if possible_args == ['Any']: # just rename assertRaises & friends
|
if possible_args == ['Any']: # just rename assertRaises & friends
|
||||||
return re.sub('self.'+old, new, block)
|
return re.sub('self.'+old, new, block)
|
||||||
|
|
||||||
|
@ -97,7 +97,7 @@ def rewrite_utest(block):
|
||||||
|
|
||||||
except SyntaxError: # but we couldn't parse it!
|
except SyntaxError: # but we couldn't parse it!
|
||||||
return block
|
return block
|
||||||
|
|
||||||
argnum = len(argl)
|
argnum = len(argl)
|
||||||
if argnum not in possible_args:
|
if argnum not in possible_args:
|
||||||
# sanity check - this one isn't real either
|
# sanity check - this one isn't real either
|
||||||
|
@ -132,12 +132,12 @@ def rewrite_utest(block):
|
||||||
def decompose_unittest(old, block):
|
def decompose_unittest(old, block):
|
||||||
'''decompose the block into its component parts'''
|
'''decompose the block into its component parts'''
|
||||||
|
|
||||||
''' returns indent, arglist, trailer
|
''' returns indent, arglist, trailer
|
||||||
indent -- the indentation
|
indent -- the indentation
|
||||||
arglist -- the arguments to the unittest function
|
arglist -- the arguments to the unittest function
|
||||||
trailer -- any extra junk after the closing paren, such as #commment
|
trailer -- any extra junk after the closing paren, such as #commment
|
||||||
'''
|
'''
|
||||||
|
|
||||||
indent = re.match(r'(\s*)', block).group()
|
indent = re.match(r'(\s*)', block).group()
|
||||||
pat = re.search('self.' + old + r'\(', block)
|
pat = re.search('self.' + old + r'\(', block)
|
||||||
|
|
||||||
|
@ -178,7 +178,7 @@ def get_expr(s, char):
|
||||||
pos.append(i)
|
pos.append(i)
|
||||||
if pos == []:
|
if pos == []:
|
||||||
raise SyntaxError # we didn't find the expected char. Ick.
|
raise SyntaxError # we didn't find the expected char. Ick.
|
||||||
|
|
||||||
for p in pos:
|
for p in pos:
|
||||||
# make the python parser do the hard work of deciding which comma
|
# make the python parser do the hard work of deciding which comma
|
||||||
# splits the string into two expressions
|
# splits the string into two expressions
|
||||||
|
@ -248,6 +248,6 @@ def main():
|
||||||
|
|
||||||
outfile.write(s)
|
outfile.write(s)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
main()
|
main()
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
# hands on script to compute the non-empty Lines of Code
|
# hands on script to compute the non-empty Lines of Code
|
||||||
# for tests and non-test code
|
# for tests and non-test code
|
||||||
|
|
||||||
"""\
|
"""\
|
||||||
py.countloc [PATHS]
|
py.countloc [PATHS]
|
||||||
|
@ -17,18 +17,18 @@ def main():
|
||||||
parser = py.std.optparse.OptionParser(usage=__doc__)
|
parser = py.std.optparse.OptionParser(usage=__doc__)
|
||||||
(options, args) = parser.parse_args()
|
(options, args) = parser.parse_args()
|
||||||
countloc(args)
|
countloc(args)
|
||||||
|
|
||||||
def nodot(p):
|
def nodot(p):
|
||||||
return p.check(dotfile=0)
|
return p.check(dotfile=0)
|
||||||
|
|
||||||
class FileCounter(object):
|
class FileCounter(object):
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.file2numlines = {}
|
self.file2numlines = {}
|
||||||
self.numlines = 0
|
self.numlines = 0
|
||||||
self.numfiles = 0
|
self.numfiles = 0
|
||||||
|
|
||||||
def addrecursive(self, directory, fil="*.py", rec=nodot):
|
def addrecursive(self, directory, fil="*.py", rec=nodot):
|
||||||
for x in directory.visit(fil, rec):
|
for x in directory.visit(fil, rec):
|
||||||
self.addfile(x)
|
self.addfile(x)
|
||||||
|
|
||||||
def addfile(self, fn, emptylines=False):
|
def addfile(self, fn, emptylines=False):
|
||||||
|
@ -39,21 +39,21 @@ class FileCounter(object):
|
||||||
for i in fn.readlines():
|
for i in fn.readlines():
|
||||||
if i.strip():
|
if i.strip():
|
||||||
s += 1
|
s += 1
|
||||||
self.file2numlines[fn] = s
|
self.file2numlines[fn] = s
|
||||||
self.numfiles += 1
|
self.numfiles += 1
|
||||||
self.numlines += s
|
self.numlines += s
|
||||||
|
|
||||||
def getnumlines(self, fil):
|
def getnumlines(self, fil):
|
||||||
numlines = 0
|
numlines = 0
|
||||||
for path, value in self.file2numlines.items():
|
for path, value in self.file2numlines.items():
|
||||||
if fil(path):
|
if fil(path):
|
||||||
numlines += value
|
numlines += value
|
||||||
return numlines
|
return numlines
|
||||||
|
|
||||||
def getnumfiles(self, fil):
|
def getnumfiles(self, fil):
|
||||||
numfiles = 0
|
numfiles = 0
|
||||||
for path in self.file2numlines:
|
for path in self.file2numlines:
|
||||||
if fil(path):
|
if fil(path):
|
||||||
numfiles += 1
|
numfiles += 1
|
||||||
return numfiles
|
return numfiles
|
||||||
|
|
||||||
|
@ -61,18 +61,18 @@ def get_loccount(locations=None):
|
||||||
if locations is None:
|
if locations is None:
|
||||||
localtions = [py.path.local()]
|
localtions = [py.path.local()]
|
||||||
counter = FileCounter()
|
counter = FileCounter()
|
||||||
for loc in locations:
|
for loc in locations:
|
||||||
counter.addrecursive(loc, '*.py', rec=nodot)
|
counter.addrecursive(loc, '*.py', rec=nodot)
|
||||||
|
|
||||||
def istestfile(p):
|
def istestfile(p):
|
||||||
return p.check(fnmatch='test_*.py')
|
return p.check(fnmatch='test_*.py')
|
||||||
isnottestfile = lambda x: not istestfile(x)
|
isnottestfile = lambda x: not istestfile(x)
|
||||||
|
|
||||||
numfiles = counter.getnumfiles(isnottestfile)
|
numfiles = counter.getnumfiles(isnottestfile)
|
||||||
numlines = counter.getnumlines(isnottestfile)
|
numlines = counter.getnumlines(isnottestfile)
|
||||||
numtestfiles = counter.getnumfiles(istestfile)
|
numtestfiles = counter.getnumfiles(istestfile)
|
||||||
numtestlines = counter.getnumlines(istestfile)
|
numtestlines = counter.getnumlines(istestfile)
|
||||||
|
|
||||||
return counter, numfiles, numlines, numtestfiles, numtestlines
|
return counter, numfiles, numlines, numtestfiles, numtestlines
|
||||||
|
|
||||||
def countloc(paths=None):
|
def countloc(paths=None):
|
||||||
|
@ -86,7 +86,7 @@ def countloc(paths=None):
|
||||||
items.sort(lambda x,y: cmp(x[1], y[1]))
|
items.sort(lambda x,y: cmp(x[1], y[1]))
|
||||||
for x, y in items:
|
for x, y in items:
|
||||||
print("%3d %30s" % (y,x))
|
print("%3d %30s" % (y,x))
|
||||||
|
|
||||||
print("%30s %3d" %("number of testfiles", numtestfiles))
|
print("%30s %3d" %("number of testfiles", numtestfiles))
|
||||||
print("%30s %3d" %("number of non-empty testlines", numtestlines))
|
print("%30s %3d" %("number of non-empty testlines", numtestlines))
|
||||||
print("%30s %3d" %("number of files", numfiles))
|
print("%30s %3d" %("number of files", numfiles))
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
|
|
||||||
"""\
|
"""\
|
||||||
py.lookup [search_directory] SEARCH_STRING [options]
|
py.lookup [search_directory] SEARCH_STRING [options]
|
||||||
|
@ -65,7 +65,7 @@ def main():
|
||||||
searchlines = s.lower().splitlines()
|
searchlines = s.lower().splitlines()
|
||||||
else:
|
else:
|
||||||
searchlines = lines
|
searchlines = lines
|
||||||
for i, (line, searchline) in enumerate(zip(lines, searchlines)):
|
for i, (line, searchline) in enumerate(zip(lines, searchlines)):
|
||||||
indexes = find_indexes(searchline, string)
|
indexes = find_indexes(searchline, string)
|
||||||
if not indexes:
|
if not indexes:
|
||||||
continue
|
continue
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue