added Japanese translation for 2.2.4 (79a5b776a6f3)
This commit is contained in:
parent
b4c2161e35
commit
03a814a859
|
@ -0,0 +1,142 @@
|
||||||
|
# Makefile for Sphinx documentation
|
||||||
|
#
|
||||||
|
|
||||||
|
# You can set these variables from the command line.
|
||||||
|
SPHINXOPTS =
|
||||||
|
SPHINXBUILD = sphinx-build
|
||||||
|
PAPER =
|
||||||
|
BUILDDIR = _build
|
||||||
|
|
||||||
|
# Internal variables.
|
||||||
|
PAPEROPT_a4 = -D latex_paper_size=a4
|
||||||
|
PAPEROPT_letter = -D latex_paper_size=letter
|
||||||
|
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
|
||||||
|
|
||||||
|
.PHONY: help clean html dirhtml singlehtml pickle json htmlhelp qthelp devhelp epub latex latexpdf text man changes linkcheck doctest
|
||||||
|
|
||||||
|
regen:
|
||||||
|
PYTHONDONTWRITEBYTECODE=1 COLUMNS=76 regendoc --update *.txt */*.txt
|
||||||
|
|
||||||
|
help:
|
||||||
|
@echo "Please use \`make <target>' where <target> is one of"
|
||||||
|
@echo " html to make standalone HTML files"
|
||||||
|
@echo " dirhtml to make HTML files named index.html in directories"
|
||||||
|
@echo " singlehtml to make a single large HTML file"
|
||||||
|
@echo " pickle to make pickle files"
|
||||||
|
@echo " json to make JSON files"
|
||||||
|
@echo " htmlhelp to make HTML files and a HTML help project"
|
||||||
|
@echo " qthelp to make HTML files and a qthelp project"
|
||||||
|
@echo " devhelp to make HTML files and a Devhelp project"
|
||||||
|
@echo " epub to make an epub"
|
||||||
|
@echo " latex to make LaTeX files, you can set PAPER=a4 or PAPER=letter"
|
||||||
|
@echo " latexpdf to make LaTeX files and run them through pdflatex"
|
||||||
|
@echo " text to make text files"
|
||||||
|
@echo " man to make manual pages"
|
||||||
|
@echo " changes to make an overview of all changed/added/deprecated items"
|
||||||
|
@echo " linkcheck to check all external links for integrity"
|
||||||
|
@echo " doctest to run all doctests embedded in the documentation (if enabled)"
|
||||||
|
|
||||||
|
clean:
|
||||||
|
-rm -rf $(BUILDDIR)/*
|
||||||
|
|
||||||
|
install: html
|
||||||
|
rsync -avz _build/html/ pytest.org:/www/pytest.org/latest
|
||||||
|
|
||||||
|
installpdf: latexpdf
|
||||||
|
@scp $(BUILDDIR)/latex/pytest.pdf pytest.org:/www/pytest.org/latest
|
||||||
|
|
||||||
|
installall: clean install installpdf
|
||||||
|
@echo "done"
|
||||||
|
|
||||||
|
html:
|
||||||
|
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
|
||||||
|
|
||||||
|
dirhtml:
|
||||||
|
$(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
|
||||||
|
|
||||||
|
singlehtml:
|
||||||
|
$(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
|
||||||
|
|
||||||
|
pickle:
|
||||||
|
$(SPHINXBUILD) -b pickle $(ALLSPHINXOPTS) $(BUILDDIR)/pickle
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; now you can process the pickle files."
|
||||||
|
|
||||||
|
json:
|
||||||
|
$(SPHINXBUILD) -b json $(ALLSPHINXOPTS) $(BUILDDIR)/json
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; now you can process the JSON files."
|
||||||
|
|
||||||
|
htmlhelp:
|
||||||
|
$(SPHINXBUILD) -b htmlhelp $(ALLSPHINXOPTS) $(BUILDDIR)/htmlhelp
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; now you can run HTML Help Workshop with the" \
|
||||||
|
".hhp project file in $(BUILDDIR)/htmlhelp."
|
||||||
|
|
||||||
|
qthelp:
|
||||||
|
$(SPHINXBUILD) -b qthelp $(ALLSPHINXOPTS) $(BUILDDIR)/qthelp
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; now you can run "qcollectiongenerator" with the" \
|
||||||
|
".qhcp project file in $(BUILDDIR)/qthelp, like this:"
|
||||||
|
@echo "# qcollectiongenerator $(BUILDDIR)/qthelp/pytest.qhcp"
|
||||||
|
@echo "To view the help file:"
|
||||||
|
@echo "# assistant -collectionFile $(BUILDDIR)/qthelp/pytest.qhc"
|
||||||
|
|
||||||
|
devhelp:
|
||||||
|
$(SPHINXBUILD) -b devhelp $(ALLSPHINXOPTS) $(BUILDDIR)/devhelp
|
||||||
|
@echo
|
||||||
|
@echo "Build finished."
|
||||||
|
@echo "To view the help file:"
|
||||||
|
@echo "# mkdir -p $$HOME/.local/share/devhelp/pytest"
|
||||||
|
@echo "# ln -s $(BUILDDIR)/devhelp $$HOME/.local/share/devhelp/pytest"
|
||||||
|
@echo "# devhelp"
|
||||||
|
|
||||||
|
epub:
|
||||||
|
$(SPHINXBUILD) -b epub $(ALLSPHINXOPTS) $(BUILDDIR)/epub
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The epub file is in $(BUILDDIR)/epub."
|
||||||
|
|
||||||
|
latex:
|
||||||
|
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||||
|
@echo
|
||||||
|
@echo "Build finished; the LaTeX files are in $(BUILDDIR)/latex."
|
||||||
|
@echo "Run \`make' in that directory to run these through (pdf)latex" \
|
||||||
|
"(use \`make latexpdf' here to do that automatically)."
|
||||||
|
|
||||||
|
latexpdf:
|
||||||
|
$(SPHINXBUILD) -b latex $(ALLSPHINXOPTS) $(BUILDDIR)/latex
|
||||||
|
@echo "Running LaTeX files through pdflatex..."
|
||||||
|
make -C $(BUILDDIR)/latex all-pdf
|
||||||
|
@echo "pdflatex finished; the PDF files are in $(BUILDDIR)/latex."
|
||||||
|
|
||||||
|
text:
|
||||||
|
$(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The text files are in $(BUILDDIR)/text."
|
||||||
|
|
||||||
|
man:
|
||||||
|
$(SPHINXBUILD) -b man $(ALLSPHINXOPTS) $(BUILDDIR)/man
|
||||||
|
@echo
|
||||||
|
@echo "Build finished. The manual pages are in $(BUILDDIR)/man."
|
||||||
|
|
||||||
|
changes:
|
||||||
|
$(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
|
||||||
|
@echo
|
||||||
|
@echo "The overview file is in $(BUILDDIR)/changes."
|
||||||
|
|
||||||
|
linkcheck:
|
||||||
|
$(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
|
||||||
|
@echo
|
||||||
|
@echo "Link check complete; look for any errors in the above output " \
|
||||||
|
"or in $(BUILDDIR)/linkcheck/output.txt."
|
||||||
|
|
||||||
|
doctest:
|
||||||
|
$(SPHINXBUILD) -b doctest $(ALLSPHINXOPTS) $(BUILDDIR)/doctest
|
||||||
|
@echo "Testing of doctests in the sources finished, look at the " \
|
||||||
|
"results in $(BUILDDIR)/doctest/output.txt."
|
|
@ -0,0 +1,343 @@
|
||||||
|
/*
|
||||||
|
* sphinxdoc.css_t
|
||||||
|
* ~~~~~~~~~~~~~~~
|
||||||
|
*
|
||||||
|
* Sphinx stylesheet -- sphinxdoc theme. Originally created by
|
||||||
|
* Armin Ronacher for Werkzeug.
|
||||||
|
*
|
||||||
|
* :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
|
||||||
|
* :license: BSD, see LICENSE for details.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
@import url("basic.css");
|
||||||
|
|
||||||
|
/* -- page layout ----------------------------------------------------------- */
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
|
||||||
|
'Verdana', sans-serif;
|
||||||
|
font-size: 1.1em;
|
||||||
|
letter-spacing: -0.01em;
|
||||||
|
line-height: 150%;
|
||||||
|
text-align: center;
|
||||||
|
background-color: #BFD1D4;
|
||||||
|
color: black;
|
||||||
|
padding: 0;
|
||||||
|
border: 1px solid #aaa;
|
||||||
|
|
||||||
|
margin: 0px 80px 0px 80px;
|
||||||
|
min-width: 740px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.document {
|
||||||
|
background-color: white;
|
||||||
|
text-align: left;
|
||||||
|
background-image: url(contents.png);
|
||||||
|
background-repeat: repeat-x;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.bodywrapper {
|
||||||
|
margin: 0 290px 0 0;
|
||||||
|
border-right: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.5em 20px 20px 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related {
|
||||||
|
font-size: 0.8em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related ul {
|
||||||
|
background-image: url(navigation.png);
|
||||||
|
height: 2em;
|
||||||
|
border-top: 1px solid #ddd;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related ul li {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0;
|
||||||
|
height: 2em;
|
||||||
|
float: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related ul li.right {
|
||||||
|
float: right;
|
||||||
|
margin-right: 5px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related ul li a {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0 5px 0 5px;
|
||||||
|
line-height: 1.75em;
|
||||||
|
color: #EE9816;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.related ul li a:hover {
|
||||||
|
color: #3CA8E7;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebarwrapper {
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.5em 15px 15px 0;
|
||||||
|
width: 260px;
|
||||||
|
float: right;
|
||||||
|
font-size: 1em;
|
||||||
|
text-align: left;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar h3, div.sphinxsidebar h4 {
|
||||||
|
margin: 1em 0 0.5em 0;
|
||||||
|
font-size: 1em;
|
||||||
|
padding: 0.1em 0 0.1em 0.5em;
|
||||||
|
color: white;
|
||||||
|
border: 1px solid #86989B;
|
||||||
|
background-color: #AFC1C4;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar h3 a {
|
||||||
|
color: white;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar ul {
|
||||||
|
padding-left: 1.5em;
|
||||||
|
margin-top: 7px;
|
||||||
|
padding: 0;
|
||||||
|
line-height: 130%;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar ul ul {
|
||||||
|
margin-left: 20px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.sphinxsidebar #searchbox input[type="submit"] {
|
||||||
|
width: 55px;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.footer {
|
||||||
|
background-color: #E3EFF1;
|
||||||
|
color: #86989B;
|
||||||
|
padding: 3px 8px 3px 0;
|
||||||
|
clear: both;
|
||||||
|
font-size: 0.8em;
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.footer a {
|
||||||
|
color: #86989B;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* -- body styles ----------------------------------------------------------- */
|
||||||
|
|
||||||
|
p {
|
||||||
|
margin: 0.8em 0 0.5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
a {
|
||||||
|
color: #CA7900;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
|
||||||
|
a:hover {
|
||||||
|
color: #2491CF;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body a {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.7em 0 0.3em 0;
|
||||||
|
font-size: 1.5em;
|
||||||
|
color: #11557C;
|
||||||
|
}
|
||||||
|
|
||||||
|
h2 {
|
||||||
|
margin: 1.3em 0 0.2em 0;
|
||||||
|
font-size: 1.35em;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
h3 {
|
||||||
|
margin: 1em 0 -0.3em 0;
|
||||||
|
font-size: 1.2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.body h1 a, div.body h2 a, div.body h3 a, div.body h4 a, div.body h5 a, div.body h6 a {
|
||||||
|
color: black!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 a.anchor, h2 a.anchor, h3 a.anchor, h4 a.anchor, h5 a.anchor, h6 a.anchor {
|
||||||
|
display: none;
|
||||||
|
margin: 0 0 0 0.3em;
|
||||||
|
padding: 0 0.2em 0 0.2em;
|
||||||
|
color: #aaa!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1:hover a.anchor, h2:hover a.anchor, h3:hover a.anchor, h4:hover a.anchor,
|
||||||
|
h5:hover a.anchor, h6:hover a.anchor {
|
||||||
|
display: inline;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 a.anchor:hover, h2 a.anchor:hover, h3 a.anchor:hover, h4 a.anchor:hover,
|
||||||
|
h5 a.anchor:hover, h6 a.anchor:hover {
|
||||||
|
color: #777;
|
||||||
|
background-color: #eee;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.headerlink {
|
||||||
|
color: #c60f0f!important;
|
||||||
|
font-size: 1em;
|
||||||
|
margin-left: 6px;
|
||||||
|
padding: 0 4px 0 4px;
|
||||||
|
text-decoration: none!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
a.headerlink:hover {
|
||||||
|
background-color: #ccc;
|
||||||
|
color: white!important;
|
||||||
|
}
|
||||||
|
|
||||||
|
cite, code, tt {
|
||||||
|
font-family: 'Consolas', 'Deja Vu Sans Mono',
|
||||||
|
'Bitstream Vera Sans Mono', monospace;
|
||||||
|
font-size: 0.95em;
|
||||||
|
letter-spacing: 0.01em;
|
||||||
|
}
|
||||||
|
|
||||||
|
tt {
|
||||||
|
background-color: #f2f2f2;
|
||||||
|
border-bottom: 1px solid #ddd;
|
||||||
|
color: #333;
|
||||||
|
}
|
||||||
|
|
||||||
|
tt.descname, tt.descclassname, tt.xref {
|
||||||
|
border: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
hr {
|
||||||
|
border: 1px solid #abc;
|
||||||
|
margin: 2em;
|
||||||
|
}
|
||||||
|
|
||||||
|
a tt {
|
||||||
|
border: 0;
|
||||||
|
color: #CA7900;
|
||||||
|
}
|
||||||
|
|
||||||
|
a tt:hover {
|
||||||
|
color: #2491CF;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre {
|
||||||
|
font-family: 'Consolas', 'Deja Vu Sans Mono',
|
||||||
|
'Bitstream Vera Sans Mono', monospace;
|
||||||
|
font-size: 0.95em;
|
||||||
|
letter-spacing: 0.015em;
|
||||||
|
line-height: 120%;
|
||||||
|
padding: 0.5em;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
pre a {
|
||||||
|
color: inherit;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.linenos pre {
|
||||||
|
padding: 0.5em 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.quotebar {
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
max-width: 250px;
|
||||||
|
float: right;
|
||||||
|
padding: 2px 7px;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.topic {
|
||||||
|
background-color: #f8f8f8;
|
||||||
|
}
|
||||||
|
|
||||||
|
table {
|
||||||
|
border-collapse: collapse;
|
||||||
|
margin: 0 -0.5em 0 -0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
table td, table th {
|
||||||
|
padding: 0.2em 0.5em 0.2em 0.5em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.admonition, div.warning {
|
||||||
|
font-size: 0.9em;
|
||||||
|
margin: 1em 0 1em 0;
|
||||||
|
border: 1px solid #86989B;
|
||||||
|
background-color: #f7f7f7;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.admonition p, div.warning p {
|
||||||
|
margin: 0.5em 1em 0.5em 1em;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.admonition pre, div.warning pre {
|
||||||
|
margin: 0.4em 1em 0.4em 1em;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.admonition p.admonition-title,
|
||||||
|
div.warning p.admonition-title {
|
||||||
|
margin: 0;
|
||||||
|
padding: 0.1em 0 0.1em 0.5em;
|
||||||
|
color: white;
|
||||||
|
border-bottom: 1px solid #86989B;
|
||||||
|
font-weight: bold;
|
||||||
|
background-color: #AFC1C4;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.warning {
|
||||||
|
border: 1px solid #940000;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.warning p.admonition-title {
|
||||||
|
background-color: #CF0000;
|
||||||
|
border-bottom-color: #940000;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.admonition ul, div.admonition ol,
|
||||||
|
div.warning ul, div.warning ol {
|
||||||
|
margin: 0.1em 0.5em 0.5em 3em;
|
||||||
|
padding: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.versioninfo {
|
||||||
|
margin: 1em 0 0 0;
|
||||||
|
border: 1px solid #ccc;
|
||||||
|
background-color: #DDEAF0;
|
||||||
|
padding: 8px;
|
||||||
|
line-height: 1.3em;
|
||||||
|
font-size: 0.9em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.viewcode-back {
|
||||||
|
font-family: 'Lucida Grande', 'Lucida Sans Unicode', 'Geneva',
|
||||||
|
'Verdana', sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
div.viewcode-block:target {
|
||||||
|
background-color: #f4debf;
|
||||||
|
border-top: 1px solid #ac9;
|
||||||
|
border-bottom: 1px solid #ac9;
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
|
||||||
|
..
|
||||||
|
Release announcements
|
||||||
|
===========================================
|
||||||
|
|
||||||
|
リリースアナウンス
|
||||||
|
==================
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
release-2.2.4
|
||||||
|
release-2.2.2
|
||||||
|
release-2.2.1
|
||||||
|
release-2.2.0
|
||||||
|
release-2.1.3
|
||||||
|
release-2.1.2
|
||||||
|
release-2.1.1
|
||||||
|
release-2.1.0
|
||||||
|
release-2.0.3
|
||||||
|
release-2.0.2
|
||||||
|
release-2.0.1
|
||||||
|
release-2.0.0
|
||||||
|
|
|
@ -0,0 +1,129 @@
|
||||||
|
py.test 2.0.0: asserts++, unittest++, reporting++, config++, docs++
|
||||||
|
===========================================================================
|
||||||
|
|
||||||
|
Welcome to pytest-2.0.0, a major new release of "py.test", the rapid
|
||||||
|
easy Python testing tool. There are many new features and enhancements,
|
||||||
|
see below for summary and detailed lists. A lot of long-deprecated code
|
||||||
|
has been removed, resulting in a much smaller and cleaner
|
||||||
|
implementation. See the new docs with examples here:
|
||||||
|
|
||||||
|
http://pytest.org/2.0.0/index.html
|
||||||
|
|
||||||
|
A note on packaging: pytest used to part of the "py" distribution up
|
||||||
|
until version py-1.3.4 but this has changed now: pytest-2.0.0 only
|
||||||
|
contains py.test related code and is expected to be backward-compatible
|
||||||
|
to existing test code. If you want to install pytest, just type one of::
|
||||||
|
|
||||||
|
pip install -U pytest
|
||||||
|
easy_install -U pytest
|
||||||
|
|
||||||
|
Many thanks to all issue reporters and people asking questions or
|
||||||
|
complaining. Particular thanks to Floris Bruynooghe and Ronny Pfannschmidt
|
||||||
|
for their great coding contributions and many others for feedback and help.
|
||||||
|
|
||||||
|
best,
|
||||||
|
holger krekel
|
||||||
|
|
||||||
|
|
||||||
|
New Features
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
- new invocations through Python interpreter and from Python::
|
||||||
|
|
||||||
|
python -m pytest # on all pythons >= 2.5
|
||||||
|
|
||||||
|
or from a python program::
|
||||||
|
|
||||||
|
import pytest ; pytest.main(arglist, pluginlist)
|
||||||
|
|
||||||
|
see http://pytest.org/2.0.0/usage.html for details.
|
||||||
|
|
||||||
|
- new and better reporting information in assert expressions
|
||||||
|
if comparing lists, sequences or strings.
|
||||||
|
|
||||||
|
see http://pytest.org/2.0.0/assert.html#newreport
|
||||||
|
|
||||||
|
- new configuration through ini-files (setup.cfg or tox.ini recognized),
|
||||||
|
for example::
|
||||||
|
|
||||||
|
[pytest]
|
||||||
|
norecursedirs = .hg data* # don't ever recurse in such dirs
|
||||||
|
addopts = -x --pyargs # add these command line options by default
|
||||||
|
|
||||||
|
see http://pytest.org/2.0.0/customize.html
|
||||||
|
|
||||||
|
- improved standard unittest support. In general py.test should now
|
||||||
|
better be able to run custom unittest.TestCases like twisted trial
|
||||||
|
or Django based TestCases. Also you can now run the tests of an
|
||||||
|
installed 'unittest' package with py.test::
|
||||||
|
|
||||||
|
py.test --pyargs unittest
|
||||||
|
|
||||||
|
- new "-q" option which decreases verbosity and prints a more
|
||||||
|
nose/unittest-style "dot" output.
|
||||||
|
|
||||||
|
- many many more detailed improvements details
|
||||||
|
|
||||||
|
Fixes
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
- fix issue126 - introduce py.test.set_trace() to trace execution via
|
||||||
|
PDB during the running of tests even if capturing is ongoing.
|
||||||
|
- fix issue124 - make reporting more resilient against tests opening
|
||||||
|
files on filedescriptor 1 (stdout).
|
||||||
|
- fix issue109 - sibling conftest.py files will not be loaded.
|
||||||
|
(and Directory collectors cannot be customized anymore from a Directory's
|
||||||
|
conftest.py - this needs to happen at least one level up).
|
||||||
|
- fix issue88 (finding custom test nodes from command line arg)
|
||||||
|
- fix issue93 stdout/stderr is captured while importing conftest.py
|
||||||
|
- fix bug: unittest collected functions now also can have "pytestmark"
|
||||||
|
applied at class/module level
|
||||||
|
|
||||||
|
Important Notes
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
* The usual way in pre-2.0 times to use py.test in python code was
|
||||||
|
to import "py" and then e.g. use "py.test.raises" for the helper.
|
||||||
|
This remains valid and is not planned to be deprecated. However,
|
||||||
|
in most examples and internal code you'll find "import pytest"
|
||||||
|
and "pytest.raises" used as the recommended default way.
|
||||||
|
|
||||||
|
* pytest now first performs collection of the complete test suite
|
||||||
|
before running any test. This changes for example the semantics of when
|
||||||
|
pytest_collectstart/pytest_collectreport are called. Some plugins may
|
||||||
|
need upgrading.
|
||||||
|
|
||||||
|
* The pytest package consists of a 400 LOC core.py and about 20 builtin plugins,
|
||||||
|
summing up to roughly 5000 LOCs, including docstrings. To be fair, it also
|
||||||
|
uses generic code from the "pylib", and the new "py" package to help
|
||||||
|
with filesystem and introspection/code manipulation.
|
||||||
|
|
||||||
|
(Incompatible) Removals
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
- py.test.config is now only available if you are in a test run.
|
||||||
|
|
||||||
|
- the following (mostly already deprecated) functionality was removed:
|
||||||
|
|
||||||
|
- removed support for Module/Class/... collection node definitions
|
||||||
|
in conftest.py files. They will cause nothing special.
|
||||||
|
- removed support for calling the pre-1.0 collection API of "run()" and "join"
|
||||||
|
- removed reading option values from conftest.py files or env variables.
|
||||||
|
This can now be done much much better and easier through the ini-file
|
||||||
|
mechanism and the "addopts" entry in particular.
|
||||||
|
- removed the "disabled" attribute in test classes. Use the skipping
|
||||||
|
and pytestmark mechanism to skip or xfail a test class.
|
||||||
|
|
||||||
|
- py.test.collect.Directory does not exist anymore and it
|
||||||
|
is not possible to provide an own "Directory" object.
|
||||||
|
If you have used this and don't know what to do, get
|
||||||
|
in contact. We'll figure something out.
|
||||||
|
|
||||||
|
Note that pytest_collect_directory() is still called but
|
||||||
|
any return value will be ignored. This allows to keep
|
||||||
|
old code working that performed for example "py.test.skip()"
|
||||||
|
in collect() to prevent recursion into directory trees
|
||||||
|
if a certain dependency or command line option is missing.
|
||||||
|
|
||||||
|
|
||||||
|
see :ref:`changelog` for more detailed changes.
|
|
@ -0,0 +1,67 @@
|
||||||
|
py.test 2.0.1: bug fixes
|
||||||
|
===========================================================================
|
||||||
|
|
||||||
|
Welcome to pytest-2.0.1, a maintenance and bug fix release of pytest,
|
||||||
|
a mature testing tool for Python, supporting CPython 2.4-3.2, Jython
|
||||||
|
and latest PyPy interpreters. See extensive docs with tested examples here:
|
||||||
|
|
||||||
|
http://pytest.org/
|
||||||
|
|
||||||
|
If you want to install or upgrade pytest, just type one of::
|
||||||
|
|
||||||
|
pip install -U pytest # or
|
||||||
|
easy_install -U pytest
|
||||||
|
|
||||||
|
Many thanks to all issue reporters and people asking questions or
|
||||||
|
complaining. Particular thanks to Floris Bruynooghe and Ronny Pfannschmidt
|
||||||
|
for their great coding contributions and many others for feedback and help.
|
||||||
|
|
||||||
|
best,
|
||||||
|
holger krekel
|
||||||
|
|
||||||
|
Changes between 2.0.0 and 2.0.1
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
- refine and unify initial capturing so that it works nicely
|
||||||
|
even if the logging module is used on an early-loaded conftest.py
|
||||||
|
file or plugin.
|
||||||
|
- fix issue12 - show plugin versions with "--version" and
|
||||||
|
"--traceconfig" and also document how to add extra information
|
||||||
|
to reporting test header
|
||||||
|
- fix issue17 (import-* reporting issue on python3) by
|
||||||
|
requiring py>1.4.0 (1.4.1 is going to include it)
|
||||||
|
- fix issue10 (numpy arrays truth checking) by refining
|
||||||
|
assertion interpretation in py lib
|
||||||
|
- fix issue15: make nose compatibility tests compatible
|
||||||
|
with python3 (now that nose-1.0 supports python3)
|
||||||
|
- remove somewhat surprising "same-conftest" detection because
|
||||||
|
it ignores conftest.py when they appear in several subdirs.
|
||||||
|
- improve assertions ("not in"), thanks Floris Bruynooghe
|
||||||
|
- improve behaviour/warnings when running on top of "python -OO"
|
||||||
|
(assertions and docstrings are turned off, leading to potential
|
||||||
|
false positives)
|
||||||
|
- introduce a pytest_cmdline_processargs(args) hook
|
||||||
|
to allow dynamic computation of command line arguments.
|
||||||
|
This fixes a regression because py.test prior to 2.0
|
||||||
|
allowed to set command line options from conftest.py
|
||||||
|
files which so far pytest-2.0 only allowed from ini-files now.
|
||||||
|
- fix issue7: assert failures in doctest modules.
|
||||||
|
unexpected failures in doctests will not generally
|
||||||
|
show nicer, i.e. within the doctest failing context.
|
||||||
|
- fix issue9: setup/teardown functions for an xfail-marked
|
||||||
|
test will report as xfail if they fail but report as normally
|
||||||
|
passing (not xpassing) if they succeed. This only is true
|
||||||
|
for "direct" setup/teardown invocations because teardown_class/
|
||||||
|
teardown_module cannot closely relate to a single test.
|
||||||
|
- fix issue14: no logging errors at process exit
|
||||||
|
- refinements to "collecting" output on non-ttys
|
||||||
|
- refine internal plugin registration and --traceconfig output
|
||||||
|
- introduce a mechanism to prevent/unregister plugins from the
|
||||||
|
command line, see http://pytest.org/plugins.html#cmdunregister
|
||||||
|
- activate resultlog plugin by default
|
||||||
|
- fix regression wrt yielded tests which due to the
|
||||||
|
collection-before-running semantics were not
|
||||||
|
setup as with pytest 1.3.4. Note, however, that
|
||||||
|
the recommended and much cleaner way to do test
|
||||||
|
parametrization remains the "pytest_generate_tests"
|
||||||
|
mechanism, see the docs.
|
|
@ -0,0 +1,73 @@
|
||||||
|
py.test 2.0.2: bug fixes, improved xfail/skip expressions, speed ups
|
||||||
|
===========================================================================
|
||||||
|
|
||||||
|
Welcome to pytest-2.0.2, a maintenance and bug fix release of pytest,
|
||||||
|
a mature testing tool for Python, supporting CPython 2.4-3.2, Jython
|
||||||
|
and latest PyPy interpreters. See the extensive docs with tested examples here:
|
||||||
|
|
||||||
|
http://pytest.org/
|
||||||
|
|
||||||
|
If you want to install or upgrade pytest, just type one of::
|
||||||
|
|
||||||
|
pip install -U pytest # or
|
||||||
|
easy_install -U pytest
|
||||||
|
|
||||||
|
Many thanks to all issue reporters and people asking questions
|
||||||
|
or complaining, particularly Jurko for his insistence,
|
||||||
|
Laura, Victor and Brianna for helping with improving
|
||||||
|
and Ronny for his general advise.
|
||||||
|
|
||||||
|
best,
|
||||||
|
holger krekel
|
||||||
|
|
||||||
|
Changes between 2.0.1 and 2.0.2
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
- tackle issue32 - speed up test runs of very quick test functions
|
||||||
|
by reducing the relative overhead
|
||||||
|
|
||||||
|
- fix issue30 - extended xfail/skipif handling and improved reporting.
|
||||||
|
If you have a syntax error in your skip/xfail
|
||||||
|
expressions you now get nice error reports.
|
||||||
|
|
||||||
|
Also you can now access module globals from xfail/skipif
|
||||||
|
expressions so that this for example works now::
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
import mymodule
|
||||||
|
@pytest.mark.skipif("mymodule.__version__[0] == "1")
|
||||||
|
def test_function():
|
||||||
|
pass
|
||||||
|
|
||||||
|
This will not run the test function if the module's version string
|
||||||
|
does not start with a "1". Note that specifying a string instead
|
||||||
|
of a boolean expressions allows py.test to report meaningful information
|
||||||
|
when summarizing a test run as to what conditions lead to skipping
|
||||||
|
(or xfail-ing) tests.
|
||||||
|
|
||||||
|
- fix issue28 - setup_method and pytest_generate_tests work together
|
||||||
|
The setup_method fixture method now gets called also for
|
||||||
|
test function invocations generated from the pytest_generate_tests
|
||||||
|
hook.
|
||||||
|
|
||||||
|
- fix issue27 - collectonly and keyword-selection (-k) now work together
|
||||||
|
Also, if you do "py.test --collectonly -q" you now get a flat list
|
||||||
|
of test ids that you can use to paste to the py.test commandline
|
||||||
|
in order to execute a particular test.
|
||||||
|
|
||||||
|
- fix issue25 avoid reported problems with --pdb and python3.2/encodings output
|
||||||
|
|
||||||
|
- fix issue23 - tmpdir argument now works on Python3.2 and WindowsXP
|
||||||
|
Starting with Python3.2 os.symlink may be supported. By requiring
|
||||||
|
a newer py lib version the py.path.local() implementation acknowledges
|
||||||
|
this.
|
||||||
|
|
||||||
|
- fixed typos in the docs (thanks Victor Garcia, Brianna Laugher) and particular
|
||||||
|
thanks to Laura Creighton who also revieved parts of the documentation.
|
||||||
|
|
||||||
|
- fix slighly wrong output of verbose progress reporting for classes
|
||||||
|
(thanks Amaury)
|
||||||
|
|
||||||
|
- more precise (avoiding of) deprecation warnings for node.Class|Function accesses
|
||||||
|
|
||||||
|
- avoid std unittest assertion helper code in tracebacks (thanks Ronny)
|
|
@ -0,0 +1,40 @@
|
||||||
|
py.test 2.0.3: bug fixes and speed ups
|
||||||
|
===========================================================================
|
||||||
|
|
||||||
|
Welcome to pytest-2.0.3, a maintenance and bug fix release of pytest,
|
||||||
|
a mature testing tool for Python, supporting CPython 2.4-3.2, Jython
|
||||||
|
and latest PyPy interpreters. See the extensive docs with tested examples here:
|
||||||
|
|
||||||
|
http://pytest.org/
|
||||||
|
|
||||||
|
If you want to install or upgrade pytest, just type one of::
|
||||||
|
|
||||||
|
pip install -U pytest # or
|
||||||
|
easy_install -U pytest
|
||||||
|
|
||||||
|
There also is a bugfix release 1.6 of pytest-xdist, the plugin
|
||||||
|
that enables seemless distributed and "looponfail" testing for Python.
|
||||||
|
|
||||||
|
best,
|
||||||
|
holger krekel
|
||||||
|
|
||||||
|
Changes between 2.0.2 and 2.0.3
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
- fix issue38: nicer tracebacks on calls to hooks, particularly early
|
||||||
|
configure/sessionstart ones
|
||||||
|
|
||||||
|
- fix missing skip reason/meta information in junitxml files, reported
|
||||||
|
via http://lists.idyll.org/pipermail/testing-in-python/2011-March/003928.html
|
||||||
|
|
||||||
|
- fix issue34: avoid collection failure with "test" prefixed classes
|
||||||
|
deriving from object.
|
||||||
|
|
||||||
|
- don't require zlib (and other libs) for genscript plugin without
|
||||||
|
--genscript actually being used.
|
||||||
|
|
||||||
|
- speed up skips (by not doing a full traceback represenation
|
||||||
|
internally)
|
||||||
|
|
||||||
|
- fix issue37: avoid invalid characters in junitxml's output
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
py.test 2.1.0: perfected assertions and bug fixes
|
||||||
|
===========================================================================
|
||||||
|
|
||||||
|
Welcome to the release of pytest-2.1, a mature testing tool for Python,
|
||||||
|
supporting CPython 2.4-3.2, Jython and latest PyPy interpreters. See
|
||||||
|
the improved extensive docs (now also as PDF!) with tested examples here:
|
||||||
|
|
||||||
|
http://pytest.org/
|
||||||
|
|
||||||
|
The single biggest news about this release are **perfected assertions**
|
||||||
|
courtesy of Benjamin Peterson. You can now safely use ``assert``
|
||||||
|
statements in test modules without having to worry about side effects
|
||||||
|
or python optimization ("-OO") options. This is achieved by rewriting
|
||||||
|
assert statements in test modules upon import, using a PEP302 hook.
|
||||||
|
See http://pytest.org/assert.html#advanced-assertion-introspection for
|
||||||
|
detailed information. The work has been partly sponsored by my company,
|
||||||
|
merlinux GmbH.
|
||||||
|
|
||||||
|
For further details on bug fixes and smaller enhancements see below.
|
||||||
|
|
||||||
|
If you want to install or upgrade pytest, just type one of::
|
||||||
|
|
||||||
|
pip install -U pytest # or
|
||||||
|
easy_install -U pytest
|
||||||
|
|
||||||
|
best,
|
||||||
|
holger krekel / http://merlinux.eu
|
||||||
|
|
||||||
|
Changes between 2.0.3 and 2.1.0
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
- fix issue53 call nosestyle setup functions with correct ordering
|
||||||
|
- fix issue58 and issue59: new assertion code fixes
|
||||||
|
- merge Benjamin's assertionrewrite branch: now assertions
|
||||||
|
for test modules on python 2.6 and above are done by rewriting
|
||||||
|
the AST and saving the pyc file before the test module is imported.
|
||||||
|
see doc/assert.txt for more info.
|
||||||
|
- fix issue43: improve doctests with better traceback reporting on
|
||||||
|
unexpected exceptions
|
||||||
|
- fix issue47: timing output in junitxml for test cases is now correct
|
||||||
|
- fix issue48: typo in MarkInfo repr leading to exception
|
||||||
|
- fix issue49: avoid confusing error when initialization partially fails
|
||||||
|
- fix issue44: env/username expansion for junitxml file path
|
||||||
|
- show releaselevel information in test runs for pypy
|
||||||
|
- reworked doc pages for better navigation and PDF generation
|
||||||
|
- report KeyboardInterrupt even if interrupted during session startup
|
||||||
|
- fix issue 35 - provide PDF doc version and download link from index page
|
|
@ -0,0 +1,37 @@
|
||||||
|
py.test 2.1.1: assertion fixes and improved junitxml output
|
||||||
|
===========================================================================
|
||||||
|
|
||||||
|
pytest-2.1.1 is a backward compatible maintenance release of the
|
||||||
|
popular py.test testing tool. See extensive docs with examples here:
|
||||||
|
|
||||||
|
http://pytest.org/
|
||||||
|
|
||||||
|
Most bug fixes address remaining issues with the perfected assertions
|
||||||
|
introduced with 2.1.0 - many thanks to the bug reporters and to Benjamin
|
||||||
|
Peterson for helping to fix them. Also, junitxml output now produces
|
||||||
|
system-out/err tags which lead to better displays of tracebacks with Jenkins.
|
||||||
|
|
||||||
|
Also a quick note to package maintainers and others interested: there now
|
||||||
|
is a "pytest" man page which can be generated with "make man" in doc/.
|
||||||
|
|
||||||
|
If you want to install or upgrade pytest, just type one of::
|
||||||
|
|
||||||
|
pip install -U pytest # or
|
||||||
|
easy_install -U pytest
|
||||||
|
|
||||||
|
best,
|
||||||
|
holger krekel / http://merlinux.eu
|
||||||
|
|
||||||
|
Changes between 2.1.0 and 2.1.1
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
- fix issue64 / pytest.set_trace now works within pytest_generate_tests hooks
|
||||||
|
- fix issue60 / fix error conditions involving the creation of __pycache__
|
||||||
|
- fix issue63 / assertion rewriting on inserts involving strings containing '%'
|
||||||
|
- fix assertion rewriting on calls with a ** arg
|
||||||
|
- don't cache rewritten modules if bytecode generation is disabled
|
||||||
|
- fix assertion rewriting in read-only directories
|
||||||
|
- fix issue59: provide system-out/err tags for junitxml output
|
||||||
|
- fix issue61: assertion rewriting on boolean operations with 3 or more operands
|
||||||
|
- you can now build a man page with "cd doc ; make man"
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
py.test 2.1.2: bug fixes and fixes for jython
|
||||||
|
===========================================================================
|
||||||
|
|
||||||
|
pytest-2.1.2 is a minor backward compatible maintenance release of the
|
||||||
|
popular py.test testing tool. pytest is commonly used for unit,
|
||||||
|
functional- and integration testing. See extensive docs with examples
|
||||||
|
here:
|
||||||
|
|
||||||
|
http://pytest.org/
|
||||||
|
|
||||||
|
Most bug fixes address remaining issues with the perfected assertions
|
||||||
|
introduced in the 2.1 series - many thanks to the bug reporters and to Benjamin
|
||||||
|
Peterson for helping to fix them. pytest should also work better with
|
||||||
|
Jython-2.5.1 (and Jython trunk).
|
||||||
|
|
||||||
|
If you want to install or upgrade pytest, just type one of::
|
||||||
|
|
||||||
|
pip install -U pytest # or
|
||||||
|
easy_install -U pytest
|
||||||
|
|
||||||
|
best,
|
||||||
|
holger krekel / http://merlinux.eu
|
||||||
|
|
||||||
|
Changes between 2.1.1 and 2.1.2
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
- fix assertion rewriting on files with windows newlines on some Python versions
|
||||||
|
- refine test discovery by package/module name (--pyargs), thanks Florian Mayer
|
||||||
|
- fix issue69 / assertion rewriting fixed on some boolean operations
|
||||||
|
- fix issue68 / packages now work with assertion rewriting
|
||||||
|
- fix issue66: use different assertion rewriting caches when the -O option is passed
|
||||||
|
- don't try assertion rewriting on Jython, use reinterp
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
py.test 2.1.3: just some more fixes
|
||||||
|
===========================================================================
|
||||||
|
|
||||||
|
pytest-2.1.3 is a minor backward compatible maintenance release of the
|
||||||
|
popular py.test testing tool. It is commonly used for unit, functional-
|
||||||
|
and integration testing. See extensive docs with examples here:
|
||||||
|
|
||||||
|
http://pytest.org/
|
||||||
|
|
||||||
|
The release contains another fix to the perfected assertions introduced
|
||||||
|
with the 2.1 series as well as the new possibility to customize reporting
|
||||||
|
for assertion expressions on a per-directory level.
|
||||||
|
|
||||||
|
If you want to install or upgrade pytest, just type one of::
|
||||||
|
|
||||||
|
pip install -U pytest # or
|
||||||
|
easy_install -U pytest
|
||||||
|
|
||||||
|
Thanks to the bug reporters and to Ronny Pfannschmidt, Benjamin Peterson
|
||||||
|
and Floris Bruynooghe who implemented the fixes.
|
||||||
|
|
||||||
|
best,
|
||||||
|
holger krekel
|
||||||
|
|
||||||
|
Changes between 2.1.2 and 2.1.3
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
- fix issue79: assertion rewriting failed on some comparisons in boolops,
|
||||||
|
- correctly handle zero length arguments (a la pytest '')
|
||||||
|
- fix issue67 / junitxml now contains correct test durations
|
||||||
|
- fix issue75 / skipping test failure on jython
|
||||||
|
- fix issue77 / Allow assertrepr_compare hook to apply to a subset of tests
|
|
@ -0,0 +1,95 @@
|
||||||
|
py.test 2.2.0: test marking++, parametrization++ and duration profiling
|
||||||
|
===========================================================================
|
||||||
|
|
||||||
|
pytest-2.2.0 is a test-suite compatible release of the popular
|
||||||
|
py.test testing tool. Plugins might need upgrades. It comes
|
||||||
|
with these improvements:
|
||||||
|
|
||||||
|
* easier and more powerful parametrization of tests:
|
||||||
|
|
||||||
|
- new @pytest.mark.parametrize decorator to run tests with different arguments
|
||||||
|
- new metafunc.parametrize() API for parametrizing arguments independently
|
||||||
|
- see examples at http://pytest.org/latest/example/parametrize.html
|
||||||
|
- NOTE that parametrize() related APIs are still a bit experimental
|
||||||
|
and might change in future releases.
|
||||||
|
|
||||||
|
* improved handling of test markers and refined marking mechanism:
|
||||||
|
|
||||||
|
- "-m markexpr" option for selecting tests according to their mark
|
||||||
|
- a new "markers" ini-variable for registering test markers for your project
|
||||||
|
- the new "--strict" bails out with an error if using unregistered markers.
|
||||||
|
- see examples at http://pytest.org/latest/example/markers.html
|
||||||
|
|
||||||
|
* duration profiling: new "--duration=N" option showing the N slowest test
|
||||||
|
execution or setup/teardown calls. This is most useful if you want to
|
||||||
|
find out where your slowest test code is.
|
||||||
|
|
||||||
|
* also 2.2.0 performs more eager calling of teardown/finalizers functions
|
||||||
|
resulting in better and more accurate reporting when they fail
|
||||||
|
|
||||||
|
Besides there is the usual set of bug fixes along with a cleanup of
|
||||||
|
pytest's own test suite allowing it to run on a wider range of environments.
|
||||||
|
|
||||||
|
For general information, see extensive docs with examples here:
|
||||||
|
|
||||||
|
http://pytest.org/
|
||||||
|
|
||||||
|
If you want to install or upgrade pytest you might just type::
|
||||||
|
|
||||||
|
pip install -U pytest # or
|
||||||
|
easy_install -U pytest
|
||||||
|
|
||||||
|
Thanks to Ronny Pfannschmidt, David Burns, Jeff Donner, Daniel Nouri, Alfredo Deza and all who gave feedback or sent bug reports.
|
||||||
|
|
||||||
|
best,
|
||||||
|
holger krekel
|
||||||
|
|
||||||
|
|
||||||
|
notes on incompatibility
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
While test suites should work unchanged you might need to upgrade plugins:
|
||||||
|
|
||||||
|
* You need a new version of the pytest-xdist plugin (1.7) for distributing
|
||||||
|
test runs.
|
||||||
|
|
||||||
|
* Other plugins might need an upgrade if they implement
|
||||||
|
the ``pytest_runtest_logreport`` hook which now is called unconditionally
|
||||||
|
for the setup/teardown fixture phases of a test. You may choose to
|
||||||
|
ignore setup/teardown failures by inserting "if rep.when != 'call': return"
|
||||||
|
or something similar. Note that most code probably "just" works because
|
||||||
|
the hook was already called for failing setup/teardown phases of a test
|
||||||
|
so a plugin should have been ready to grok such reports already.
|
||||||
|
|
||||||
|
|
||||||
|
Changes between 2.1.3 and 2.2.0
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
- fix issue90: introduce eager tearing down of test items so that
|
||||||
|
teardown function are called earlier.
|
||||||
|
- add an all-powerful metafunc.parametrize function which allows to
|
||||||
|
parametrize test function arguments in multiple steps and therefore
|
||||||
|
from independent plugins and places.
|
||||||
|
- add a @pytest.mark.parametrize helper which allows to easily
|
||||||
|
call a test function with different argument values.
|
||||||
|
- Add examples to the "parametrize" example page, including a quick port
|
||||||
|
of Test scenarios and the new parametrize function and decorator.
|
||||||
|
- introduce registration for "pytest.mark.*" helpers via ini-files
|
||||||
|
or through plugin hooks. Also introduce a "--strict" option which
|
||||||
|
will treat unregistered markers as errors
|
||||||
|
allowing to avoid typos and maintain a well described set of markers
|
||||||
|
for your test suite. See examples at http://pytest.org/latest/mark.html
|
||||||
|
and its links.
|
||||||
|
- issue50: introduce "-m marker" option to select tests based on markers
|
||||||
|
(this is a stricter and more predictable version of "-k" in that "-m"
|
||||||
|
only matches complete markers and has more obvious rules for and/or
|
||||||
|
semantics.
|
||||||
|
- new feature to help optimizing the speed of your tests:
|
||||||
|
--durations=N option for displaying N slowest test calls
|
||||||
|
and setup/teardown methods.
|
||||||
|
- fix issue87: --pastebin now works with python3
|
||||||
|
- fix issue89: --pdb with unexpected exceptions in doctest work more sensibly
|
||||||
|
- fix and cleanup pytest's own test suite to not leak FDs
|
||||||
|
- fix issue83: link to generated funcarg list
|
||||||
|
- fix issue74: pyarg module names are now checked against imp.find_module false positives
|
||||||
|
- fix compatibility with twisted/trial-11.1.0 use cases
|
|
@ -0,0 +1,41 @@
|
||||||
|
pytest-2.2.1: bug fixes, perfect teardowns
|
||||||
|
===========================================================================
|
||||||
|
|
||||||
|
|
||||||
|
pytest-2.2.1 is a minor backward-compatible release of the the py.test
|
||||||
|
testing tool. It contains bug fixes and little improvements, including
|
||||||
|
documentation fixes. If you are using the distributed testing
|
||||||
|
pluginmake sure to upgrade it to pytest-xdist-1.8.
|
||||||
|
|
||||||
|
For general information see here:
|
||||||
|
|
||||||
|
http://pytest.org/
|
||||||
|
|
||||||
|
To install or upgrade pytest:
|
||||||
|
|
||||||
|
pip install -U pytest # or
|
||||||
|
easy_install -U pytest
|
||||||
|
|
||||||
|
Special thanks for helping on this release to Ronny Pfannschmidt, Jurko
|
||||||
|
Gospodnetic and Ralf Schmitt.
|
||||||
|
|
||||||
|
best,
|
||||||
|
holger krekel
|
||||||
|
|
||||||
|
|
||||||
|
Changes between 2.2.0 and 2.2.1
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
- fix issue99 (in pytest and py) internallerrors with resultlog now
|
||||||
|
produce better output - fixed by normalizing pytest_internalerror
|
||||||
|
input arguments.
|
||||||
|
- fix issue97 / traceback issues (in pytest and py) improve traceback output
|
||||||
|
in conjunction with jinja2 and cython which hack tracebacks
|
||||||
|
- fix issue93 (in pytest and pytest-xdist) avoid "delayed teardowns":
|
||||||
|
the final test in a test node will now run its teardown directly
|
||||||
|
instead of waiting for the end of the session. Thanks Dave Hunt for
|
||||||
|
the good reporting and feedback. The pytest_runtest_protocol as well
|
||||||
|
as the pytest_runtest_teardown hooks now have "nextitem" available
|
||||||
|
which will be None indicating the end of the test run.
|
||||||
|
- fix collection crash due to unknown-source collected items, thanks
|
||||||
|
to Ralf Schmitt (fixed by depending on a more recent pylib)
|
|
@ -0,0 +1,43 @@
|
||||||
|
pytest-2.2.2: bug fixes
|
||||||
|
===========================================================================
|
||||||
|
|
||||||
|
pytest-2.2.2 (updated to 2.2.3 to fix packaging issues) is a minor
|
||||||
|
backward-compatible release of the versatile py.test testing tool. It
|
||||||
|
contains bug fixes and a few refinements particularly to reporting with
|
||||||
|
"--collectonly", see below for betails.
|
||||||
|
|
||||||
|
For general information see here:
|
||||||
|
|
||||||
|
http://pytest.org/
|
||||||
|
|
||||||
|
To install or upgrade pytest:
|
||||||
|
|
||||||
|
pip install -U pytest # or
|
||||||
|
easy_install -U pytest
|
||||||
|
|
||||||
|
Special thanks for helping on this release to Ronny Pfannschmidt
|
||||||
|
and Ralf Schmitt and the contributors of issues.
|
||||||
|
|
||||||
|
best,
|
||||||
|
holger krekel
|
||||||
|
|
||||||
|
|
||||||
|
Changes between 2.2.1 and 2.2.2
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
- fix issue101: wrong args to unittest.TestCase test function now
|
||||||
|
produce better output
|
||||||
|
- fix issue102: report more useful errors and hints for when a
|
||||||
|
test directory was renamed and some pyc/__pycache__ remain
|
||||||
|
- fix issue106: allow parametrize to be applied multiple times
|
||||||
|
e.g. from module, class and at function level.
|
||||||
|
- fix issue107: actually perform session scope finalization
|
||||||
|
- don't check in parametrize if indirect parameters are funcarg names
|
||||||
|
- add chdir method to monkeypatch funcarg
|
||||||
|
- fix crash resulting from calling monkeypatch undo a second time
|
||||||
|
- fix issue115: make --collectonly robust against early failure
|
||||||
|
(missing files/directories)
|
||||||
|
- "-qq --collectonly" now shows only files and the number of tests in them
|
||||||
|
- "-q --collectonly" now shows test ids
|
||||||
|
- allow adding of attributes to test reports such that it also works
|
||||||
|
with distributed testing (no upgrade of pytest-xdist needed)
|
|
@ -0,0 +1,39 @@
|
||||||
|
pytest-2.2.4: bug fixes, better junitxml/unittest/python3 compat
|
||||||
|
===========================================================================
|
||||||
|
|
||||||
|
pytest-2.2.4 is a minor backward-compatible release of the versatile
|
||||||
|
py.test testing tool. It contains bug fixes and a few refinements
|
||||||
|
to junitxml reporting, better unittest- and python3 compatibility.
|
||||||
|
|
||||||
|
For general information see here:
|
||||||
|
|
||||||
|
http://pytest.org/
|
||||||
|
|
||||||
|
To install or upgrade pytest:
|
||||||
|
|
||||||
|
pip install -U pytest # or
|
||||||
|
easy_install -U pytest
|
||||||
|
|
||||||
|
Special thanks for helping on this release to Ronny Pfannschmidt
|
||||||
|
and Benjamin Peterson and the contributors of issues.
|
||||||
|
|
||||||
|
best,
|
||||||
|
holger krekel
|
||||||
|
|
||||||
|
Changes between 2.2.3 and 2.2.4
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
- fix error message for rewritten assertions involving the % operator
|
||||||
|
- fix issue 126: correctly match all invalid xml characters for junitxml
|
||||||
|
binary escape
|
||||||
|
- fix issue with unittest: now @unittest.expectedFailure markers should
|
||||||
|
be processed correctly (you can also use @pytest.mark markers)
|
||||||
|
- document integration with the extended distribute/setuptools test commands
|
||||||
|
- fix issue 140: propperly get the real functions
|
||||||
|
of bound classmethods for setup/teardown_class
|
||||||
|
- fix issue #141: switch from the deceased paste.pocoo.org to bpaste.net
|
||||||
|
- fix issue #143: call unconfigure/sessionfinish always when
|
||||||
|
configure/sessionstart where called
|
||||||
|
- fix issue #144: better mangle test ids to junitxml classnames
|
||||||
|
- upgrade distribute_setup.py to 0.6.27
|
||||||
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
|
||||||
|
.. _apiref:
|
||||||
|
|
||||||
|
py.test リファレンスドキュメント
|
||||||
|
================================
|
||||||
|
|
||||||
|
..
|
||||||
|
py.test reference documentation
|
||||||
|
================================================
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
builtin.txt
|
||||||
|
customize.txt
|
||||||
|
assert.txt
|
||||||
|
funcargs.txt
|
||||||
|
xunit_setup.txt
|
||||||
|
capture.txt
|
||||||
|
monkeypatch.txt
|
||||||
|
xdist.txt
|
||||||
|
tmpdir.txt
|
||||||
|
skipping.txt
|
||||||
|
mark.txt
|
||||||
|
recwarn.txt
|
||||||
|
unittest.txt
|
||||||
|
nose.txt
|
||||||
|
doctest.txt
|
||||||
|
|
|
@ -0,0 +1,362 @@
|
||||||
|
|
||||||
|
..
|
||||||
|
The writing and reporting of assertions in tests
|
||||||
|
==================================================
|
||||||
|
|
||||||
|
テストのアサーションにおける書き込みとレポート
|
||||||
|
==============================================
|
||||||
|
|
||||||
|
.. _`assert with the assert statement`:
|
||||||
|
|
||||||
|
``assert`` 文によるアサーション
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Asserting with the ``assert`` statement
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
``py.test`` allows you to use the standard python ``assert`` for verifying
|
||||||
|
expectations and values in Python tests. For example, you can write the
|
||||||
|
following::
|
||||||
|
|
||||||
|
``py.test`` は、テストで期待値と実際の値を検証するのに Python 標準の ``assert`` 文が使えます。例えば、次のようにテストを作成します::
|
||||||
|
|
||||||
|
# test_assert1.py の内容
|
||||||
|
def f():
|
||||||
|
return 3
|
||||||
|
|
||||||
|
def test_function():
|
||||||
|
assert f() == 4
|
||||||
|
|
||||||
|
..
|
||||||
|
to assert that your function returns a certain value. If this assertion fails
|
||||||
|
you will see the return value of the function call::
|
||||||
|
|
||||||
|
このサンプルは、関数が特定の値を返すのをアサートします。このアサーションが失敗した場合、関数呼び出しの返り値が表示されます::
|
||||||
|
|
||||||
|
$ py.test test_assert1.py
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 1 items
|
||||||
|
|
||||||
|
test_assert1.py F
|
||||||
|
|
||||||
|
================================= FAILURES =================================
|
||||||
|
______________________________ test_function _______________________________
|
||||||
|
|
||||||
|
def test_function():
|
||||||
|
> assert f() == 4
|
||||||
|
E assert 3 == 4
|
||||||
|
E + where 3 = f()
|
||||||
|
|
||||||
|
test_assert1.py:5: AssertionError
|
||||||
|
========================= 1 failed in 0.01 seconds =========================
|
||||||
|
|
||||||
|
..
|
||||||
|
py.test has support for showing the values of the most common subexpressions
|
||||||
|
including calls, attributes, comparisons, and binary and unary
|
||||||
|
operators. (See :ref:`tbreportdemo`). This allows you to use the
|
||||||
|
idiomatic python constructs without boilerplate code while not losing
|
||||||
|
introspection information.
|
||||||
|
|
||||||
|
py.test は、関数呼び出し、属性、比較、バイナリや単項演算子といった処理を含む通常の部分式の値を表示する機能があります (:ref:`tbreportdemo` を参照) 。この機能により、定型的なコードを必要とせず、Python イディオム的な概念も利用できます。その上でイントロスペクション情報を失うこともありません。
|
||||||
|
|
||||||
|
..
|
||||||
|
However, if you specify a message with the assertion like this::
|
||||||
|
|
||||||
|
但し、次のようにアサーションと一緒にメッセージを指定した場合::
|
||||||
|
|
||||||
|
assert a % 2 == 0, "value was odd, should be even"
|
||||||
|
|
||||||
|
..
|
||||||
|
then no assertion introspection takes places at all and the message
|
||||||
|
will be simply shown in the traceback.
|
||||||
|
|
||||||
|
そこでアサートイントロスペクションを行わず、このメッセージは単純にトレースバックで表示されます。
|
||||||
|
|
||||||
|
..
|
||||||
|
See :ref:`assert-details` for more information on assertion introspection.
|
||||||
|
|
||||||
|
アサートイントロスペクションの詳細については :ref:`assert-details` を参照してください。
|
||||||
|
|
||||||
|
..
|
||||||
|
Assertions about expected exceptions
|
||||||
|
------------------------------------------
|
||||||
|
|
||||||
|
例外発生を期待するアサーション
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
In order to write assertions about raised exceptions, you can use
|
||||||
|
``pytest.raises`` as a context manager like this::
|
||||||
|
|
||||||
|
発生した例外のアサーションを行うには、次のようにコンテキスト マネージャーとして ``pytest.raises`` を使います::
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
with pytest.raises(ZeroDivisionError):
|
||||||
|
1 / 0
|
||||||
|
|
||||||
|
..
|
||||||
|
and if you need to have access to the actual exception info you may use::
|
||||||
|
|
||||||
|
もし実際の例外の情報を調べる必要があるなら、次のように行います::
|
||||||
|
|
||||||
|
with pytest.raises(RuntimeError) as excinfo:
|
||||||
|
def f():
|
||||||
|
f()
|
||||||
|
f()
|
||||||
|
|
||||||
|
# excinfo.type, excinfo.value, excinfo.traceback といった関連する値を確認する
|
||||||
|
|
||||||
|
..
|
||||||
|
If you want to write test code that works on Python 2.4 as well,
|
||||||
|
you may also use two other ways to test for an expected exception::
|
||||||
|
|
||||||
|
Python 2.4 でも同じように動作するテストコードを書きたいなら、例外発生を期待するテストを行う別の方法が2つあります::
|
||||||
|
|
||||||
|
pytest.raises(ExpectedException, func, *args, **kwargs)
|
||||||
|
pytest.raises(ExpectedException, "func(*args, **kwargs)")
|
||||||
|
|
||||||
|
..
|
||||||
|
both of which execute the specified function with args and kwargs and
|
||||||
|
asserts that the given ``ExpectedException`` is raised. The reporter will
|
||||||
|
provide you with helpful output in case of failures such as *no
|
||||||
|
exception* or *wrong exception*.
|
||||||
|
|
||||||
|
両方とも指定した関数へ args と kwargs を渡して実行し、引数として与えた ``ExpectedException`` が発生することをアサートします。このレポートは *no exception* または *wrong exception* といったテストに失敗したときに分かりやすい内容を表示します。
|
||||||
|
|
||||||
|
.. _newreport:
|
||||||
|
|
||||||
|
コンテキストに依存した内容の比較
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Making use of context-sensitive comparisons
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
.. versionadded:: 2.0
|
||||||
|
|
||||||
|
..
|
||||||
|
py.test has rich support for providing context-sensitive information
|
||||||
|
when it encounters comparisons. For example::
|
||||||
|
|
||||||
|
py.test は、比較するときにコンテキスト依存の情報を分かりやすく表示します。例えば、::
|
||||||
|
|
||||||
|
# test_assert2.py の内容
|
||||||
|
|
||||||
|
def test_set_comparison():
|
||||||
|
set1 = set("1308")
|
||||||
|
set2 = set("8035")
|
||||||
|
assert set1 == set2
|
||||||
|
|
||||||
|
..
|
||||||
|
if you run this module::
|
||||||
|
|
||||||
|
このモジュールを実行すると::
|
||||||
|
|
||||||
|
$ py.test test_assert2.py
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 1 items
|
||||||
|
|
||||||
|
test_assert2.py F
|
||||||
|
|
||||||
|
================================= FAILURES =================================
|
||||||
|
___________________________ test_set_comparison ____________________________
|
||||||
|
|
||||||
|
def test_set_comparison():
|
||||||
|
set1 = set("1308")
|
||||||
|
set2 = set("8035")
|
||||||
|
> assert set1 == set2
|
||||||
|
E assert set(['0', '1', '3', '8']) == set(['0', '3', '5', '8'])
|
||||||
|
E Extra items in the left set:
|
||||||
|
E '1'
|
||||||
|
E Extra items in the right set:
|
||||||
|
E '5'
|
||||||
|
|
||||||
|
test_assert2.py:5: AssertionError
|
||||||
|
========================= 1 failed in 0.01 seconds =========================
|
||||||
|
|
||||||
|
..
|
||||||
|
Special comparisons are done for a number of cases:
|
||||||
|
|
||||||
|
複数のケースにおいて、特別な比較が行われます:
|
||||||
|
|
||||||
|
..
|
||||||
|
* comparing long strings: a context diff is shown
|
||||||
|
* comparing long sequences: first failing indices
|
||||||
|
* comparing dicts: different entries
|
||||||
|
|
||||||
|
* 長い文字列の比較: コンテキスト diff を表示
|
||||||
|
* 長いシーケンスの比較: 最初に失敗したインデックス
|
||||||
|
* ディクショナリの比較: 異なるエントリ
|
||||||
|
|
||||||
|
..
|
||||||
|
See the :ref:`reporting demo <tbreportdemo>` for many more examples.
|
||||||
|
|
||||||
|
より多くのサンプルについては :ref:`レポートのデモ <tbreportdemo>` 参照してください。
|
||||||
|
|
||||||
|
..
|
||||||
|
Defining your own assertion comparison
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
アサーション比較の定義
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
It is possible to add your own detailed explanations by implementing
|
||||||
|
the ``pytest_assertrepr_compare`` hook.
|
||||||
|
|
||||||
|
``pytest_assertrepr_compare`` フックを実装することで独自の詳細説明を追加できます。
|
||||||
|
|
||||||
|
.. autofunction:: _pytest.hookspec.pytest_assertrepr_compare
|
||||||
|
|
||||||
|
..
|
||||||
|
As an example consider adding the following hook in a conftest.py which
|
||||||
|
provides an alternative explanation for ``Foo`` objects::
|
||||||
|
|
||||||
|
例として、conftest.py に次のフックを追加してみます。これは ``Foo`` オブジェクトの別の説明を提供します::
|
||||||
|
|
||||||
|
# conftest.py の内容
|
||||||
|
from test_foocompare import Foo
|
||||||
|
def pytest_assertrepr_compare(op, left, right):
|
||||||
|
if isinstance(left, Foo) and isinstance(right, Foo) and op == "==":
|
||||||
|
return ['Comparing Foo instances:',
|
||||||
|
' vals: %s != %s' % (left.val, right.val)]
|
||||||
|
|
||||||
|
..
|
||||||
|
now, given this test module::
|
||||||
|
|
||||||
|
ここで次のテストモジュールがあります::
|
||||||
|
|
||||||
|
# test_foocompare.py の内容
|
||||||
|
class Foo:
|
||||||
|
def __init__(self, val):
|
||||||
|
self.val = val
|
||||||
|
|
||||||
|
def test_compare():
|
||||||
|
f1 = Foo(1)
|
||||||
|
f2 = Foo(2)
|
||||||
|
assert f1 == f2
|
||||||
|
|
||||||
|
..
|
||||||
|
you can run the test module and get the custom output defined in
|
||||||
|
the conftest file::
|
||||||
|
|
||||||
|
このテストモジュールを実行すると、conftest ファイルで定義した独自の出力内容が表示されます::
|
||||||
|
|
||||||
|
$ py.test -q test_foocompare.py
|
||||||
|
collecting ... collected 1 items
|
||||||
|
F
|
||||||
|
================================= FAILURES =================================
|
||||||
|
_______________________________ test_compare _______________________________
|
||||||
|
|
||||||
|
def test_compare():
|
||||||
|
f1 = Foo(1)
|
||||||
|
f2 = Foo(2)
|
||||||
|
> assert f1 == f2
|
||||||
|
E assert Comparing Foo instances:
|
||||||
|
E vals: 1 != 2
|
||||||
|
|
||||||
|
test_foocompare.py:8: AssertionError
|
||||||
|
1 failed in 0.01 seconds
|
||||||
|
|
||||||
|
.. _assert-details:
|
||||||
|
.. _`assert introspection`:
|
||||||
|
|
||||||
|
高度なアサートイントロスペクション
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Advanced assertion introspection
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
.. versionadded:: 2.1
|
||||||
|
|
||||||
|
..
|
||||||
|
Reporting details about a failing assertion is achieved either by rewriting
|
||||||
|
assert statements before they are run or re-evaluating the assert expression and
|
||||||
|
recording the intermediate values. Which technique is used depends on the
|
||||||
|
location of the assert, py.test's configuration, and Python version being used
|
||||||
|
to run py.test. Note that for assert statements with a manually provided
|
||||||
|
message, i.e. ``assert expr, message``, no assertion introspection takes place
|
||||||
|
and the manually provided message will be rendered in tracebacks.
|
||||||
|
|
||||||
|
失敗するアサーションに関する詳細のレポートは、実行前に assert 文を書き換えるか、または assert 式を再評価して中間値を記録するかのどちらかの方法で行われます。どちらの方法を使うかは assert の位置、pytest の設定、pytest を実行するのに使われる Python バージョンに依存します。 ``assert expr, message`` のように直接コード内でメッセージを記述した assert 文は、アサートイントロスペクションが行われず、指定したメッセージがトレースバックに表示されることに注意してください。
|
||||||
|
|
||||||
|
..
|
||||||
|
By default, if the Python version is greater than or equal to 2.6, py.test
|
||||||
|
rewrites assert statements in test modules. Rewritten assert statements put
|
||||||
|
introspection information into the assertion failure message. py.test only
|
||||||
|
rewrites test modules directly discovered by its test collection process, so
|
||||||
|
asserts in supporting modules which are not themselves test modules will not be
|
||||||
|
rewritten.
|
||||||
|
|
||||||
|
デフォルトでは、Python バージョンが 2.6 以上の場合、py.test はテストモジュールの assert 文を書き換えます。書き換えられた assert 文は、イントロスペクション情報をアサーションの失敗メッセージに追加します。py.test は、テストコレクション処理で検出したテストモジュールのみを直接書き換えます。そのため、テストモジュールではないサポートライブラリの assert 文は書き換えられません。
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
..
|
||||||
|
py.test rewrites test modules on import. It does this by using an import hook
|
||||||
|
to write a new pyc files. Most of the time this works transparently. However,
|
||||||
|
if you are messing with import yourself, the import hook may interfere. If
|
||||||
|
this is the case, simply use ``--assert=reinterp`` or
|
||||||
|
``--assert=plain``. Additionally, rewriting will fail silently if it cannot
|
||||||
|
write new pycs, i.e. in a read-only filesystem or a zipfile.
|
||||||
|
|
||||||
|
py.test は、インポート時にテストモジュールを書き換えます。新たに pyc ファイルを書き込むためにインポートフックを使うことでこの処理を行います。この処理はほとんど透過的に行われます。但し、自分でインポートを行ってごちゃごちゃになっている場合、そのインポートフックがインターフェースになる可能性があります。このようなケースでは、単純に ``--assert=reinterp`` か ``--assert=plain`` を使ってください。さらに、新たに pyc ファイルを書き込めない場合、書き換えはサイレントモードで失敗します。例えば、読み込み専用ファイルシステムや zip ファイルで行うようなときです。
|
||||||
|
|
||||||
|
..
|
||||||
|
If an assert statement has not been rewritten or the Python version is less than
|
||||||
|
2.6, py.test falls back on assert reinterpretation. In assert reinterpretation,
|
||||||
|
py.test walks the frame of the function containing the assert statement to
|
||||||
|
discover sub-expression results of the failing assert statement. You can force
|
||||||
|
py.test to always use assertion reinterpretation by passing the
|
||||||
|
``--assert=reinterp`` option.
|
||||||
|
|
||||||
|
assert 文が書き換えられない、または Python バージョン 2.6 よりも小さい場合、py.test はアサーションの再解釈を行います。アサーションの再解釈では、py.test が、assert 文の失敗する部分式を見つけるために assert 文を含む関数のフレームを辿ります。py.test にアサーションの再解釈を行うよう強制するには ``--assert=reinterp`` オプションを指定します。
|
||||||
|
|
||||||
|
..
|
||||||
|
Assert reinterpretation has a caveat not present with assert rewriting: If
|
||||||
|
evaluating the assert expression has side effects you may get a warning that the
|
||||||
|
intermediate values could not be determined safely. A common example of this
|
||||||
|
issue is an assertion which reads from a file::
|
||||||
|
|
||||||
|
アサーションの再解釈は、assert 文の書き換えを行わないことの注意が必要です: それは assert 式の評価が副作用をもつ場合、中間値が安全に決定しないという警告を受け取るかもしれません。この問題の一般的な例として、ファイルを読み込むアサーションがあります::
|
||||||
|
|
||||||
|
assert f.read() != '...'
|
||||||
|
|
||||||
|
..
|
||||||
|
If this assertion fails then the re-evaluation will probably succeed!
|
||||||
|
This is because ``f.read()`` will return an empty string when it is
|
||||||
|
called the second time during the re-evaluation. However, it is
|
||||||
|
easy to rewrite the assertion and avoid any trouble::
|
||||||
|
|
||||||
|
このアサーションが失敗した場合、その再評価はおそらく成功します!つまり再評価において2回目に呼び出されたときに ``f.read()`` が空の文字列を返すからです。とはいえ、このアサーションを書き換えて、そういったトラブルを避けるのは簡単です::
|
||||||
|
|
||||||
|
content = f.read()
|
||||||
|
assert content != '...'
|
||||||
|
|
||||||
|
..
|
||||||
|
All assert introspection can be turned off by passing ``--assert=plain``.
|
||||||
|
|
||||||
|
全てのアサートイントロスペクションを無効にするには ``--assert=plain`` を指定します。
|
||||||
|
|
||||||
|
..
|
||||||
|
For further information, Benjamin Peterson wrote up `Behind the scenes of py.test's new assertion rewriting <http://pybites.blogspot.com/2011/07/behind-scenes-of-pytests-new-assertion.html>`_.
|
||||||
|
|
||||||
|
詳細については、Benjamin Peterson が詳しくまとめた `Behind the scenes of py.test's new assertion rewriting <http://pybites.blogspot.com/2011/07/behind-scenes-of-pytests-new-assertion.html>`_ を参照してください。
|
||||||
|
|
||||||
|
..
|
||||||
|
Add assert rewriting as an alternate introspection technique.
|
||||||
|
|
||||||
|
.. versionadded:: 2.1
|
||||||
|
代替イントロスペクション手法として assert 書き換え機能を追加
|
||||||
|
|
||||||
|
..
|
||||||
|
Introduce the ``--assert`` option. Deprecate ``--no-assert`` and
|
||||||
|
``--nomagic``.
|
||||||
|
|
||||||
|
.. versionchanged:: 2.1
|
||||||
|
``--assert`` オプションを追加。 ``--no-assert`` と ``--nomagic`` を廃止。
|
|
@ -0,0 +1,152 @@
|
||||||
|
|
||||||
|
.. _`pytest helpers`:
|
||||||
|
|
||||||
|
Pytest 組み込みヘルパー機能
|
||||||
|
===========================
|
||||||
|
|
||||||
|
..
|
||||||
|
Pytest builtin helpers
|
||||||
|
================================================
|
||||||
|
|
||||||
|
..
|
||||||
|
builtin pytest.* functions and helping objects
|
||||||
|
-----------------------------------------------------
|
||||||
|
|
||||||
|
組み込みの pytest.* 関数とヘルパーオブジェクト
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
You can always use an interactive Python prompt and type::
|
||||||
|
|
||||||
|
Python インタープリターの対話モードから次のように入力すると::
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
help(pytest)
|
||||||
|
|
||||||
|
..
|
||||||
|
to get an overview on the globally available helpers.
|
||||||
|
|
||||||
|
グローバルに利用できるヘルパー機能の概要を把握できます。
|
||||||
|
|
||||||
|
.. automodule:: pytest
|
||||||
|
:members:
|
||||||
|
|
||||||
|
|
||||||
|
.. _builtinfuncargs:
|
||||||
|
|
||||||
|
組み込み関数の引数
|
||||||
|
------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Builtin function arguments
|
||||||
|
-----------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
You can ask for available builtin or project-custom
|
||||||
|
:ref:`function arguments <funcargs>` by typing::
|
||||||
|
|
||||||
|
次のように入力して、利用できる組み込みまたはプロジェクトカスタムの :ref:`関数の引数 <funcargs>` を確認できます。
|
||||||
|
|
||||||
|
| $ py.test --funcargs
|
||||||
|
| ====================== test session starts =======================
|
||||||
|
| platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
| collected 0 items
|
||||||
|
| pytestconfig
|
||||||
|
| pytest の config オブジェクトとコマンドラインオプションへのアクセス
|
||||||
|
|
|
||||||
|
| capsys
|
||||||
|
| sys.stdout/sys.stderr への書き込み内容を取得できる
|
||||||
|
| キャプチャした出力内容は ``(out, err)`` のタプルを返す
|
||||||
|
| ``capsys.readouterr()`` メソッドで利用できる
|
||||||
|
|
|
||||||
|
| capfd
|
||||||
|
| ファイルディスクリプタ 1 と 2 へ書き込み内容を取得できる
|
||||||
|
| キャプチャした出力内容は ``(out, err)`` のタプルを返す
|
||||||
|
| ``capsys.readouterr()`` メソッドで利用できる
|
||||||
|
|
|
||||||
|
| tmpdir
|
||||||
|
| 基本となる一時ディレクトリ配下にサブディレクトリを作成して、
|
||||||
|
| テスト関数の実行毎に一意な一時ディレクトリのオブジェクトを返す
|
||||||
|
| これは py.path.local のパスオブジェクトが返される
|
||||||
|
|
|
||||||
|
| monkeypatch
|
||||||
|
| オブジェクト、ディクショナリ、os.environ を変更する
|
||||||
|
| 次のヘルパーメソッドを提供する ``monkeypatch`` オブジェクトが返される
|
||||||
|
|
|
||||||
|
| monkeypatch.setattr(obj, name, value, raising=True)
|
||||||
|
| monkeypatch.delattr(obj, name, raising=True)
|
||||||
|
| monkeypatch.setitem(mapping, name, value)
|
||||||
|
| monkeypatch.delitem(obj, name, raising=True)
|
||||||
|
| monkeypatch.setenv(name, value, prepend=False)
|
||||||
|
| monkeypatch.delenv(name, value, raising=True)
|
||||||
|
| monkeypatch.syspath_prepend(path)
|
||||||
|
| monkeypatch.chdir(path)
|
||||||
|
|
|
||||||
|
| 全ての変更はテスト関数の呼び出しが終わった後で元に戻ります
|
||||||
|
| ``raising`` パラメーターは、セット/削除の操作対象がないときに
|
||||||
|
| KeyError や AttributeError を発生させるかどうかを決めます
|
||||||
|
|
|
||||||
|
| recwarn
|
||||||
|
| 次のメソッドを提供する WarningsRecorder インスタンスを返す
|
||||||
|
|
|
||||||
|
| * ``pop(category=None)``: category に一致する最後の警告を返す
|
||||||
|
| * ``clear()``: 警告のリストを削除する
|
||||||
|
|
|
||||||
|
| 警告については http://docs.python.org/library/warnings.html を
|
||||||
|
| 参照してください
|
||||||
|
|
|
||||||
|
| ======================== in 0.00 seconds ========================
|
||||||
|
|
||||||
|
..
|
||||||
|
$ py.test --funcargs
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collected 0 items
|
||||||
|
pytestconfig
|
||||||
|
the pytest config object with access to command line opts.
|
||||||
|
capsys
|
||||||
|
enables capturing of writes to sys.stdout/sys.stderr and makes
|
||||||
|
captured output available via ``capsys.readouterr()`` method calls
|
||||||
|
which return a ``(out, err)`` tuple.
|
||||||
|
|
||||||
|
capfd
|
||||||
|
enables capturing of writes to file descriptors 1 and 2 and makes
|
||||||
|
captured output available via ``capsys.readouterr()`` method calls
|
||||||
|
which return a ``(out, err)`` tuple.
|
||||||
|
|
||||||
|
tmpdir
|
||||||
|
return a temporary directory path object
|
||||||
|
which is unique to each test function invocation,
|
||||||
|
created as a sub directory of the base temporary
|
||||||
|
directory. The returned object is a `py.path.local`_
|
||||||
|
path object.
|
||||||
|
|
||||||
|
monkeypatch
|
||||||
|
The returned ``monkeypatch`` funcarg provides these
|
||||||
|
helper methods to modify objects, dictionaries or os.environ::
|
||||||
|
|
||||||
|
monkeypatch.setattr(obj, name, value, raising=True)
|
||||||
|
monkeypatch.delattr(obj, name, raising=True)
|
||||||
|
monkeypatch.setitem(mapping, name, value)
|
||||||
|
monkeypatch.delitem(obj, name, raising=True)
|
||||||
|
monkeypatch.setenv(name, value, prepend=False)
|
||||||
|
monkeypatch.delenv(name, value, raising=True)
|
||||||
|
monkeypatch.syspath_prepend(path)
|
||||||
|
monkeypatch.chdir(path)
|
||||||
|
|
||||||
|
All modifications will be undone after the requesting
|
||||||
|
test function has finished. The ``raising``
|
||||||
|
parameter determines if a KeyError or AttributeError
|
||||||
|
will be raised if the set/deletion operation has no target.
|
||||||
|
|
||||||
|
recwarn
|
||||||
|
Return a WarningsRecorder instance that provides these methods:
|
||||||
|
|
||||||
|
* ``pop(category=None)``: return last warning matching the category.
|
||||||
|
* ``clear()``: clear list of warnings
|
||||||
|
|
||||||
|
See http://docs.python.org/library/warnings.html for information
|
||||||
|
on warning categories.
|
||||||
|
|
||||||
|
|
||||||
|
============================= in 0.00 seconds =============================
|
|
@ -0,0 +1,170 @@
|
||||||
|
|
||||||
|
.. _`captures`:
|
||||||
|
|
||||||
|
標準出力/標準エラーのキャプチャ
|
||||||
|
===============================
|
||||||
|
|
||||||
|
..
|
||||||
|
Capturing of the stdout/stderr output
|
||||||
|
=========================================================
|
||||||
|
|
||||||
|
..
|
||||||
|
Default stdout/stderr/stdin capturing behaviour
|
||||||
|
---------------------------------------------------------
|
||||||
|
|
||||||
|
デフォルトの stdout/stderr/stdin のキャプチャ処理
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
During test execution any output sent to ``stdout`` and ``stderr`` is
|
||||||
|
captured. If a test or a setup method fails its according captured
|
||||||
|
output will usually be shown along with the failure traceback.
|
||||||
|
|
||||||
|
テストの実行中 ``stdout`` と ``stderr`` へ送られる全ての出力内容はキャプチャされます。テストまたはセットアップメソッドが失敗した場合、そこでキャプチャされた出力は、通常、エラートレースバックと一緒に表示されます。
|
||||||
|
|
||||||
|
..
|
||||||
|
In addition, ``stdin`` is set to a "null" object which will
|
||||||
|
fail on attempts to read from it because it is rarely desired
|
||||||
|
to wait for interactive input when running automated tests.
|
||||||
|
|
||||||
|
加えて ``stdin`` は、その読み込みに失敗する "null" オブジェクトがセットされます。その理由は自動テストを実行するときに対話式の入力を待つのを考慮することはほとんどないからです。
|
||||||
|
|
||||||
|
..
|
||||||
|
By default capturing is done by intercepting writes to low level
|
||||||
|
file descriptors. This allows to capture output from simple
|
||||||
|
print statements as well as output from a subprocess started by
|
||||||
|
a test.
|
||||||
|
|
||||||
|
デフォルトのキャプチャは、低レベルのファイルディスクリプタへの書き込みを横取りします。単純な print 文からの出力も、あるテストが生成したサブプロセスからの出力も同じようにキャプチャできます。
|
||||||
|
|
||||||
|
..
|
||||||
|
Setting capturing methods or disabling capturing
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
メソッドをキャプチャする、または無効にする設定
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
There are two ways in which ``py.test`` can perform capturing:
|
||||||
|
|
||||||
|
``py.test`` でキャプチャを実行する方法が2つあります:
|
||||||
|
|
||||||
|
..
|
||||||
|
* file descriptor (FD) level capturing (default): All writes going to the
|
||||||
|
operating system file descriptors 1 and 2 will be captured.
|
||||||
|
|
||||||
|
* ファイルディスクリプタ (FD) レベルのキャプチャ (デフォルト): オペレーティングシステムのファイルディスクリプタ1と2への全ての書き込みをキャプチャする
|
||||||
|
|
||||||
|
..
|
||||||
|
* ``sys`` level capturing: Only writes to Python files ``sys.stdout``
|
||||||
|
and ``sys.stderr`` will be captured. No capturing of writes to
|
||||||
|
filedescriptors is performed.
|
||||||
|
|
||||||
|
* ``sys`` レベルのキャプチャ: Python ファイル ``sys.stdout`` と ``sys.stderr`` への書き込みのみキャプチャする、ファイルディスクリプタへの書き込みはキャプチャしない
|
||||||
|
|
||||||
|
..
|
||||||
|
You can influence output capturing mechanisms from the command line::
|
||||||
|
|
||||||
|
.. _`disable capturing`:
|
||||||
|
|
||||||
|
コマンドラインから出力内容のキャプチャ設定を制御できます::
|
||||||
|
|
||||||
|
py.test -s # 全てのキャプチャを無効にする
|
||||||
|
py.test --capture=sys # sys.stdout/stderr を in-mem ファイルに置き換える
|
||||||
|
py.test --capture=fd # ファイルディスクリプタ1と2を一時ファイルに差し向ける
|
||||||
|
|
||||||
|
.. _printdebugging:
|
||||||
|
|
||||||
|
デバッグに print 文を使う
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Using print statements for debugging
|
||||||
|
---------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
One primary benefit of the default capturing of stdout/stderr output
|
||||||
|
is that you can use print statements for debugging::
|
||||||
|
|
||||||
|
デフォルトで stdout/stderr の出力をキャプチャする主な利点の1つとして、デバッグに print 文が使えます::
|
||||||
|
|
||||||
|
# test_module.py の内容
|
||||||
|
def setup_function(function):
|
||||||
|
print ("setting up %s" % function)
|
||||||
|
|
||||||
|
def test_func1():
|
||||||
|
assert True
|
||||||
|
|
||||||
|
def test_func2():
|
||||||
|
assert False
|
||||||
|
|
||||||
|
..
|
||||||
|
and running this module will show you precisely the output
|
||||||
|
of the failing function and hide the other one::
|
||||||
|
|
||||||
|
このモジュールを実行すると、失敗するテスト関数の出力を適切に表示して、成功するもう1つのテストを非表示にします::
|
||||||
|
|
||||||
|
$ py.test
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 2 items
|
||||||
|
|
||||||
|
test_module.py .F
|
||||||
|
|
||||||
|
================================= FAILURES =================================
|
||||||
|
________________________________ test_func2 ________________________________
|
||||||
|
|
||||||
|
def test_func2():
|
||||||
|
> assert False
|
||||||
|
E assert False
|
||||||
|
|
||||||
|
test_module.py:9: AssertionError
|
||||||
|
----------------------------- Captured stdout ------------------------------
|
||||||
|
setting up <function test_func2 at 0x20160c8>
|
||||||
|
==================== 1 failed, 1 passed in 0.01 seconds ====================
|
||||||
|
|
||||||
|
..
|
||||||
|
Accessing captured output from a test function
|
||||||
|
---------------------------------------------------
|
||||||
|
|
||||||
|
テスト関数からキャプチャされた出力へのアクセス
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
The :ref:`funcarg mechanism` allows test function a very easy
|
||||||
|
way to access the captured output by simply using the names
|
||||||
|
``capsys`` or ``capfd`` in the test function signature. Here
|
||||||
|
is an example test function that performs some output related
|
||||||
|
checks::
|
||||||
|
|
||||||
|
:ref:`funcarg mechanism` により、テスト関数のシグネチャに ``capsys`` または ``capfd`` という名前を使うだけで、簡単にキャプチャされた出力へアクセスできます。次に関連する値の確認を行うテスト関数のサンプルを紹介します::
|
||||||
|
|
||||||
|
def test_myoutput(capsys): # または fd レベルの "capfd" を使う
|
||||||
|
print ("hello")
|
||||||
|
sys.stderr.write("world\n")
|
||||||
|
out, err = capsys.readouterr()
|
||||||
|
assert out == "hello\n"
|
||||||
|
assert err == "world\n"
|
||||||
|
print "next"
|
||||||
|
out, err = capsys.readouterr()
|
||||||
|
assert out == "next\n"
|
||||||
|
|
||||||
|
..
|
||||||
|
The ``readouterr()`` call snapshots the output so far -
|
||||||
|
and capturing will be continued. After the test
|
||||||
|
function finishes the original streams will
|
||||||
|
be restored. Using ``capsys`` this way frees your
|
||||||
|
test from having to care about setting/resetting
|
||||||
|
output streams and also interacts well with py.test's
|
||||||
|
own per-test capturing.
|
||||||
|
|
||||||
|
``readouterr()`` 呼び出しは、その時点での出力内容のスナップショットを返し、その後もキャプチャが続行されます。テスト関数が終了した後、元のストリームが復元されます。 ``capsys`` を使うことで、テスト内で出力ストリームをセット/リセットすることに注意を払わなくてよくなります。また、pytest が保持するテスト単位のキャプチャも扱えます。
|
||||||
|
|
||||||
|
..
|
||||||
|
If you want to capture on ``fd`` level you can use
|
||||||
|
the ``capfd`` function argument which offers the exact
|
||||||
|
same interface.
|
||||||
|
|
||||||
|
``fd`` レベルのキャプチャを行う場合も全く同じインターフェースを提供する ``capfd`` という関数の引数を使います。
|
||||||
|
|
||||||
|
.. include:: links.inc
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
.. _changelog:
|
||||||
|
|
||||||
|
変更履歴
|
||||||
|
========
|
||||||
|
|
||||||
|
..
|
||||||
|
Changelog history
|
||||||
|
=================================
|
||||||
|
|
||||||
|
.. include:: ../../CHANGELOG
|
|
@ -0,0 +1,17 @@
|
||||||
|
import py
|
||||||
|
import subprocess
|
||||||
|
def test_build_docs(tmpdir):
|
||||||
|
doctrees = tmpdir.join("doctrees")
|
||||||
|
htmldir = tmpdir.join("html")
|
||||||
|
subprocess.check_call([
|
||||||
|
"sphinx-build", "-W", "-bhtml",
|
||||||
|
"-d", str(doctrees), ".", str(htmldir)])
|
||||||
|
|
||||||
|
def test_linkcheck(tmpdir):
|
||||||
|
doctrees = tmpdir.join("doctrees")
|
||||||
|
htmldir = tmpdir.join("html")
|
||||||
|
subprocess.check_call(
|
||||||
|
["sphinx-build", "-blinkcheck",
|
||||||
|
"-d", str(doctrees), ".", str(htmldir)])
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,273 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
#
|
||||||
|
# pytest documentation build configuration file, created by
|
||||||
|
# sphinx-quickstart on Fri Oct 8 17:54:28 2010.
|
||||||
|
#
|
||||||
|
# This file is execfile()d with the current directory set to its containing dir.
|
||||||
|
#
|
||||||
|
# Note that not all possible configuration values are present in this
|
||||||
|
# autogenerated file.
|
||||||
|
#
|
||||||
|
# All configuration values have a default; values that are commented out
|
||||||
|
# serve to show the default.
|
||||||
|
|
||||||
|
import sys, os
|
||||||
|
|
||||||
|
# If extensions (or modules to document with autodoc) are in another directory,
|
||||||
|
# add these directories to sys.path here. If the directory is relative to the
|
||||||
|
# documentation root, use os.path.abspath to make it absolute, like shown here.
|
||||||
|
#sys.path.insert(0, os.path.abspath('.'))
|
||||||
|
|
||||||
|
# -- General configuration -----------------------------------------------------
|
||||||
|
|
||||||
|
# If your documentation needs a minimal Sphinx version, state it here.
|
||||||
|
#needs_sphinx = '1.0'
|
||||||
|
|
||||||
|
# Add any Sphinx extension module names here, as strings. They can be extensions
|
||||||
|
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||||
|
extensions = ['sphinx.ext.autodoc', 'sphinx.ext.todo', 'sphinx.ext.autosummary',
|
||||||
|
'sphinx.ext.intersphinx', 'sphinx.ext.viewcode']
|
||||||
|
|
||||||
|
# Add any paths that contain templates here, relative to this directory.
|
||||||
|
templates_path = ['_templates']
|
||||||
|
|
||||||
|
# The suffix of source filenames.
|
||||||
|
source_suffix = '.txt'
|
||||||
|
|
||||||
|
# The encoding of source files.
|
||||||
|
#source_encoding = 'utf-8-sig'
|
||||||
|
|
||||||
|
# The master toctree document.
|
||||||
|
master_doc = 'contents'
|
||||||
|
|
||||||
|
# General information about the project.
|
||||||
|
project = u'pytest'
|
||||||
|
copyright = u'2011, holger krekel et alii'
|
||||||
|
|
||||||
|
# The version info for the project you're documenting, acts as replacement for
|
||||||
|
# |version| and |release|, also used in various other places throughout the
|
||||||
|
# built documents.
|
||||||
|
#
|
||||||
|
# The full version, including alpha/beta/rc tags.
|
||||||
|
import pytest
|
||||||
|
release = pytest.__version__
|
||||||
|
# The short X.Y version.
|
||||||
|
version = ".".join(release.split(".")[:2])
|
||||||
|
|
||||||
|
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||||
|
# for a list of supported languages.
|
||||||
|
language = "ja"
|
||||||
|
|
||||||
|
# There are two options for replacing |today|: either, you set today to some
|
||||||
|
# non-false value, then it is used:
|
||||||
|
#today = ''
|
||||||
|
# Else, today_fmt is used as the format for a strftime call.
|
||||||
|
#today_fmt = '%B %d, %Y'
|
||||||
|
|
||||||
|
# List of patterns, relative to source directory, that match files and
|
||||||
|
# directories to ignore when looking for source files.
|
||||||
|
exclude_patterns = ['links.inc', '_build', 'naming20.txt', 'test/*',
|
||||||
|
'example/attic.txt',
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# The reST default role (used for this markup: `text`) to use for all documents.
|
||||||
|
#default_role = None
|
||||||
|
|
||||||
|
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||||
|
#add_function_parentheses = True
|
||||||
|
|
||||||
|
# If true, the current module name will be prepended to all description
|
||||||
|
# unit titles (such as .. function::).
|
||||||
|
#add_module_names = True
|
||||||
|
|
||||||
|
# If true, sectionauthor and moduleauthor directives will be shown in the
|
||||||
|
# output. They are ignored by default.
|
||||||
|
#show_authors = False
|
||||||
|
|
||||||
|
# The name of the Pygments (syntax highlighting) style to use.
|
||||||
|
pygments_style = 'sphinx'
|
||||||
|
|
||||||
|
# A list of ignored prefixes for module index sorting.
|
||||||
|
#modindex_common_prefix = []
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for HTML output ---------------------------------------------------
|
||||||
|
|
||||||
|
# The theme to use for HTML and HTML Help pages. See the documentation for
|
||||||
|
# a list of builtin themes.
|
||||||
|
html_theme = 'sphinxdoc'
|
||||||
|
|
||||||
|
# Theme options are theme-specific and customize the look and feel of a theme
|
||||||
|
# further. For a list of options available for each theme, see the
|
||||||
|
# documentation.
|
||||||
|
html_theme_options = {}
|
||||||
|
|
||||||
|
# Add any paths that contain custom themes here, relative to this directory.
|
||||||
|
#html_theme_path = []
|
||||||
|
|
||||||
|
# The name for this set of Sphinx documents. If None, it defaults to
|
||||||
|
# "<project> v<release> documentation".
|
||||||
|
html_title = None
|
||||||
|
|
||||||
|
# A shorter title for the navigation bar. Default is the same as html_title.
|
||||||
|
html_short_title = "pytest-%s" % release
|
||||||
|
|
||||||
|
# The name of an image file (relative to this directory) to place at the top
|
||||||
|
# of the sidebar.
|
||||||
|
#html_logo = None
|
||||||
|
|
||||||
|
# The name of an image file (within the static path) to use as favicon of the
|
||||||
|
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
|
||||||
|
# pixels large.
|
||||||
|
#html_favicon = None
|
||||||
|
|
||||||
|
# Add any paths that contain custom static files (such as style sheets) here,
|
||||||
|
# relative to this directory. They are copied after the builtin static files,
|
||||||
|
# so a file named "default.css" will overwrite the builtin "default.css".
|
||||||
|
html_static_path = ['_static']
|
||||||
|
|
||||||
|
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
|
||||||
|
# using the given strftime format.
|
||||||
|
#html_last_updated_fmt = '%b %d, %Y'
|
||||||
|
|
||||||
|
# If true, SmartyPants will be used to convert quotes and dashes to
|
||||||
|
# typographically correct entities.
|
||||||
|
#html_use_smartypants = True
|
||||||
|
|
||||||
|
# Custom sidebar templates, maps document names to template names.
|
||||||
|
#html_sidebars = {}
|
||||||
|
#html_sidebars = {'index': 'indexsidebar.html'}
|
||||||
|
|
||||||
|
# Additional templates that should be rendered to pages, maps page names to
|
||||||
|
# template names.
|
||||||
|
#html_additional_pages = {}
|
||||||
|
#html_additional_pages = {'index': 'index.html'}
|
||||||
|
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
html_domain_indices = True
|
||||||
|
|
||||||
|
# If false, no index is generated.
|
||||||
|
html_use_index = False
|
||||||
|
|
||||||
|
# If true, the index is split into individual pages for each letter.
|
||||||
|
#html_split_index = False
|
||||||
|
|
||||||
|
# If true, links to the reST sources are added to the pages.
|
||||||
|
html_show_sourcelink = False
|
||||||
|
|
||||||
|
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
|
||||||
|
#html_show_sphinx = True
|
||||||
|
|
||||||
|
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
|
||||||
|
#html_show_copyright = True
|
||||||
|
|
||||||
|
# If true, an OpenSearch description file will be output, and all pages will
|
||||||
|
# contain a <link> tag referring to it. The value of this option must be the
|
||||||
|
# base URL from which the finished HTML is served.
|
||||||
|
#html_use_opensearch = ''
|
||||||
|
|
||||||
|
# This is the file name suffix for HTML files (e.g. ".xhtml").
|
||||||
|
#html_file_suffix = None
|
||||||
|
|
||||||
|
# Output file base name for HTML help builder.
|
||||||
|
htmlhelp_basename = 'pytestdoc'
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for LaTeX output --------------------------------------------------
|
||||||
|
|
||||||
|
# The paper size ('letter' or 'a4').
|
||||||
|
#latex_paper_size = 'letter'
|
||||||
|
|
||||||
|
# The font size ('10pt', '11pt' or '12pt').
|
||||||
|
#latex_font_size = '10pt'
|
||||||
|
|
||||||
|
# Grouping the document tree into LaTeX files. List of tuples
|
||||||
|
# (source start file, target name, title, author, documentclass [howto/manual]).
|
||||||
|
latex_documents = [
|
||||||
|
('contents', 'pytest.tex', u'pytest Documentation',
|
||||||
|
u'holger krekel et alii', 'manual'),
|
||||||
|
]
|
||||||
|
|
||||||
|
# The name of an image file (relative to this directory) to place at the top of
|
||||||
|
# the title page.
|
||||||
|
#latex_logo = None
|
||||||
|
|
||||||
|
# For "manual" documents, if this is true, then toplevel headings are parts,
|
||||||
|
# not chapters.
|
||||||
|
#latex_use_parts = False
|
||||||
|
|
||||||
|
# If true, show page references after internal links.
|
||||||
|
#latex_show_pagerefs = False
|
||||||
|
|
||||||
|
# If true, show URL addresses after external links.
|
||||||
|
#latex_show_urls = False
|
||||||
|
|
||||||
|
# Additional stuff for the LaTeX preamble.
|
||||||
|
#latex_preamble = ''
|
||||||
|
|
||||||
|
# Documents to append as an appendix to all manuals.
|
||||||
|
#latex_appendices = []
|
||||||
|
|
||||||
|
# If false, no module index is generated.
|
||||||
|
latex_domain_indices = False
|
||||||
|
|
||||||
|
# -- Options for manual page output --------------------------------------------
|
||||||
|
|
||||||
|
# One entry per manual page. List of tuples
|
||||||
|
# (source start file, name, description, authors, manual section).
|
||||||
|
man_pages = [
|
||||||
|
('usage', 'pytest', u'pytest usage',
|
||||||
|
[u'holger krekel at merlinux eu'], 1)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
# -- Options for Epub output ---------------------------------------------------
|
||||||
|
|
||||||
|
# Bibliographic Dublin Core info.
|
||||||
|
epub_title = u'pytest'
|
||||||
|
epub_author = u'holger krekel at merlinux eu'
|
||||||
|
epub_publisher = u'holger krekel at merlinux eu'
|
||||||
|
epub_copyright = u'2011, holger krekel et alii'
|
||||||
|
|
||||||
|
# The language of the text. It defaults to the language option
|
||||||
|
# or en if the language is not set.
|
||||||
|
#epub_language = ''
|
||||||
|
|
||||||
|
# The scheme of the identifier. Typical schemes are ISBN or URL.
|
||||||
|
#epub_scheme = ''
|
||||||
|
|
||||||
|
# The unique identifier of the text. This can be a ISBN number
|
||||||
|
# or the project homepage.
|
||||||
|
#epub_identifier = ''
|
||||||
|
|
||||||
|
# A unique identification for the text.
|
||||||
|
#epub_uid = ''
|
||||||
|
|
||||||
|
# HTML files that should be inserted before the pages created by sphinx.
|
||||||
|
# The format is a list of tuples containing the path and title.
|
||||||
|
#epub_pre_files = []
|
||||||
|
|
||||||
|
# HTML files shat should be inserted after the pages created by sphinx.
|
||||||
|
# The format is a list of tuples containing the path and title.
|
||||||
|
#epub_post_files = []
|
||||||
|
|
||||||
|
# A list of files that should not be packed into the epub file.
|
||||||
|
#epub_exclude_files = []
|
||||||
|
|
||||||
|
# The depth of the table of contents in toc.ncx.
|
||||||
|
#epub_tocdepth = 3
|
||||||
|
|
||||||
|
# Allow duplicate toc entries.
|
||||||
|
#epub_tocdup = True
|
||||||
|
|
||||||
|
|
||||||
|
# Example configuration for intersphinx: refer to the Python standard library.
|
||||||
|
intersphinx_mapping = {} # 'http://docs.python.org/': None}
|
||||||
|
def setup(app):
|
||||||
|
#from sphinx.ext.autodoc import cut_lines
|
||||||
|
#app.connect('autodoc-process-docstring', cut_lines(4, what=['module']))
|
||||||
|
app.add_description_unit('confval', 'confval',
|
||||||
|
objname='configuration value',
|
||||||
|
indextemplate='pair: %s; configuration value')
|
|
@ -0,0 +1 @@
|
||||||
|
collect_ignore = ["conf.py"]
|
|
@ -0,0 +1,73 @@
|
||||||
|
|
||||||
|
.. _`contact channels`:
|
||||||
|
.. _`contact`:
|
||||||
|
|
||||||
|
連絡先
|
||||||
|
======
|
||||||
|
|
||||||
|
..
|
||||||
|
Contact channels
|
||||||
|
===================================
|
||||||
|
|
||||||
|
..
|
||||||
|
- `new issue tracker`_ to report bugs or suggest features (for version
|
||||||
|
2.0 and above). You may also peek at the `old issue tracker`_ but please
|
||||||
|
don't submit bugs there anymore.
|
||||||
|
|
||||||
|
- バグ報告や機能提案は `新イシュートラッカー`_ を使ってください (バージョン 2.0 以上) 。 `旧イシュートラッカー`_ を覗くこともあるかもしれませんが、そこには登録しないようにしてください。
|
||||||
|
|
||||||
|
..
|
||||||
|
- `Testing In Python`_: a mailing list for Python testing tools and discussion.
|
||||||
|
|
||||||
|
- `Python におけるテスト`_ は Python のテストツールとその議論のためのメーリングリストです。
|
||||||
|
|
||||||
|
..
|
||||||
|
- `py-dev developers list`_ pytest specific announcements and discussions.
|
||||||
|
|
||||||
|
- `py-dev 開発者のメーリングリスト`_ は pytest に特化したアナウンスと議論のメーリングリストです。
|
||||||
|
|
||||||
|
..
|
||||||
|
- #pylib on irc.freenode.net IRC channel for random questions.
|
||||||
|
|
||||||
|
- あれこれ聞くための irc.freenode.net IRC チャネルは #pylib です。
|
||||||
|
|
||||||
|
..
|
||||||
|
- private mail to Holger.Krekel at gmail com if you want to communicate sensitive issues
|
||||||
|
|
||||||
|
- 慎重な対応を求める問題があるなら Holger.Krekel at gmail com 宛へメールしてください。
|
||||||
|
|
||||||
|
..
|
||||||
|
- `commit mailing list`_
|
||||||
|
|
||||||
|
- `コミットメーリングリスト`_ です。
|
||||||
|
|
||||||
|
..
|
||||||
|
- `merlinux.eu`_ offers on-site teaching and consulting services.
|
||||||
|
|
||||||
|
- `merlinux.eu`_ はオンサイト教育とコンサルティングサービスを提供しています。
|
||||||
|
|
||||||
|
.. _`new issue tracker`: http://bitbucket.org/hpk42/pytest/issues/
|
||||||
|
.. _`新イシュートラッカー`: http://bitbucket.org/hpk42/pytest/issues/
|
||||||
|
.. _`old issue tracker`: http://bitbucket.org/hpk42/py-trunk/issues/
|
||||||
|
.. _`旧イシュートラッカー`: http://bitbucket.org/hpk42/py-trunk/issues/
|
||||||
|
|
||||||
|
.. _`merlinux.eu`: http://merlinux.eu
|
||||||
|
|
||||||
|
.. _`get an account`:
|
||||||
|
|
||||||
|
.. _tetamap: http://tetamap.wordpress.com
|
||||||
|
|
||||||
|
.. _`@pylibcommit`: http://twitter.com/pylibcommit
|
||||||
|
|
||||||
|
|
||||||
|
.. _`Testing in Python`: http://lists.idyll.org/listinfo/testing-in-python
|
||||||
|
.. _`Python におけるテスト`: http://lists.idyll.org/listinfo/testing-in-python
|
||||||
|
.. _FOAF: http://en.wikipedia.org/wiki/FOAF
|
||||||
|
.. _`py-dev`:
|
||||||
|
.. _`development mailing list`:
|
||||||
|
.. _`py-dev developers list`: http://codespeak.net/mailman/listinfo/py-dev
|
||||||
|
.. _`py-dev 開発者のメーリングリスト`: http://codespeak.net/mailman/listinfo/py-dev
|
||||||
|
.. _`py-svn`:
|
||||||
|
.. _`commit mailing list`: http://codespeak.net/mailman/listinfo/py-svn
|
||||||
|
.. _`コミットメーリングリスト`: http://codespeak.net/mailman/listinfo/py-svn
|
||||||
|
|
|
@ -0,0 +1,34 @@
|
||||||
|
|
||||||
|
.. _toc:
|
||||||
|
|
||||||
|
pytest ドキュメント
|
||||||
|
===================
|
||||||
|
|
||||||
|
..
|
||||||
|
Full pytest documentation
|
||||||
|
===========================
|
||||||
|
|
||||||
|
..
|
||||||
|
`Download latest version as PDF <pytest.pdf>`_
|
||||||
|
|
||||||
|
`PDF で最新バージョンをダウンロードする <pytest.pdf>`_
|
||||||
|
|
||||||
|
.. `Download latest version as EPUB <http://media.readthedocs.org/epub/pytest/latest/pytest.epub>`_
|
||||||
|
.. `PDF で最新バージョンをダウンロードする <http://media.readthedocs.org/epub/pytest/latest/pytest.epub>`_
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
overview
|
||||||
|
example/index
|
||||||
|
apiref
|
||||||
|
plugins
|
||||||
|
talks
|
||||||
|
develop
|
||||||
|
announce/index
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:hidden:
|
||||||
|
|
||||||
|
changelog.txt
|
||||||
|
|
|
@ -0,0 +1,196 @@
|
||||||
|
..
|
||||||
|
Basic test configuration
|
||||||
|
===================================
|
||||||
|
|
||||||
|
基本的なテストの設定
|
||||||
|
====================
|
||||||
|
|
||||||
|
..
|
||||||
|
Command line options and configuration file settings
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
|
||||||
|
コマンドラインオプションと構成ファイルの設定
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
You can get help on command line options and values in INI-style
|
||||||
|
configurations files by using the general help option::
|
||||||
|
|
||||||
|
一般的なヘルプオプションを使って、ini スタイルの構成ファイルのコマンドラインオプションとその値のヘルプを確認できます::
|
||||||
|
|
||||||
|
py.test -h # オプションと構成ファイルの設定を表示
|
||||||
|
|
||||||
|
..
|
||||||
|
This will display command line and configuration file settings
|
||||||
|
which were registered by installed plugins.
|
||||||
|
|
||||||
|
これはインストール済みのプラグインが登録したコマンドライン設定と構成ファイル設定も表示します。
|
||||||
|
|
||||||
|
..
|
||||||
|
How test configuration is read from configuration INI-files
|
||||||
|
-------------------------------------------------------------
|
||||||
|
|
||||||
|
INI 構成ファイルからテスト設定の読み込み方法
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
py.test searches for the first matching ini-style configuration file
|
||||||
|
in the directories of command line argument and the directories above.
|
||||||
|
It looks for file basenames in this order::
|
||||||
|
|
||||||
|
py.test は、コマンドライン引数のディレクトリとその上位ディレクトリの、最初に一致する ini スタイルの構成ファイルを検索します。次の順番でファイル名を見ていきます::
|
||||||
|
|
||||||
|
pytest.ini
|
||||||
|
tox.ini
|
||||||
|
setup.cfg
|
||||||
|
|
||||||
|
..
|
||||||
|
Searching stops when the first ``[pytest]`` section is found.
|
||||||
|
There is no merging of configuration values from multiple files. Example::
|
||||||
|
|
||||||
|
最初の ``[pytest]`` のセクションを見つけたときに検索を中止します。複数の設定ファイルから設定値をマージするようなことはしません。サンプルを紹介します::
|
||||||
|
|
||||||
|
py.test path/to/testdir
|
||||||
|
|
||||||
|
次のように構成ファイルを含むディレクトリがあります::
|
||||||
|
|
||||||
|
path/to/testdir/pytest.ini
|
||||||
|
path/to/testdir/tox.ini
|
||||||
|
path/to/testdir/setup.cfg
|
||||||
|
path/to/pytest.ini
|
||||||
|
path/to/tox.ini
|
||||||
|
path/to/setup.cfg
|
||||||
|
... # ファイルシステムのルートまで上る
|
||||||
|
|
||||||
|
..
|
||||||
|
If argument is provided to a py.test run, the current working directory
|
||||||
|
is used to start the search.
|
||||||
|
|
||||||
|
引数が py.test を実行するために提供されるものなら、カレントディレクトリがその検索の開始位置に使われます。
|
||||||
|
|
||||||
|
.. _`how to change command line options defaults`:
|
||||||
|
.. _`adding default options`:
|
||||||
|
|
||||||
|
コマンドラインオプションのデフォルト値の変更方法
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
How to change command line options defaults
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
It can be tedious to type the same series of command line options
|
||||||
|
every time you use py.test . For example, if you always want to see
|
||||||
|
detailed info on skipped and xfailed tests, as well as have terser "dot"
|
||||||
|
progress output, you can write it into a configuration file::
|
||||||
|
|
||||||
|
py.test を使うときに毎回一連のコマンドラインオプションを入力するのは飽き飽きしてきます。例えば、毎回スキップしたり xfail したテストの詳細情報を見たいなら、進捗状況を簡潔な "ドット" 出力にするのと同様に、構成ファイル内にその設定を記述できます::
|
||||||
|
|
||||||
|
# pytest.ini の内容
|
||||||
|
# (または tox.ini か setup.cfg)
|
||||||
|
[pytest]
|
||||||
|
addopts = -rsxX -q
|
||||||
|
|
||||||
|
..
|
||||||
|
From now on, running ``py.test`` will add the specified options.
|
||||||
|
|
||||||
|
設定後に実行すると ``py.test`` は指定したオプションを追加します。
|
||||||
|
|
||||||
|
..
|
||||||
|
Builtin configuration file options
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
組み込みの構成ファイルオプション
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
.. confval:: minversion
|
||||||
|
|
||||||
|
..
|
||||||
|
Specifies a minimal pytest version required for running tests.
|
||||||
|
minversion = 2.1 # will fail if we run with pytest-2.0
|
||||||
|
|
||||||
|
テストの実行に必要な pytest の最小バージョンを指定します
|
||||||
|
|
||||||
|
minversion = 2.1 # pytest-2.0 で実行すると失敗する
|
||||||
|
|
||||||
|
.. confval:: addopts
|
||||||
|
|
||||||
|
..
|
||||||
|
Add the specified ``OPTS`` to the set of command line arguments as if they
|
||||||
|
had been specified by the user. Example: if you have this ini file content::
|
||||||
|
[pytest]
|
||||||
|
addopts = --maxfail=2 -rf # exit after 2 failures, report fail info
|
||||||
|
issuing ``py.test test_hello.py`` actually means::
|
||||||
|
py.test --maxfail=2 -rf test_hello.py
|
||||||
|
Default is to add no options.
|
||||||
|
|
||||||
|
ユーザーが指定するようにコマンドライン引数をセットするのに特化した ``OPTS`` を追加します。次のような ini ファイルがある場合::
|
||||||
|
|
||||||
|
[pytest]
|
||||||
|
addopts = --maxfail=2 -rf # 2回失敗したら終了して、その内容をレポートする
|
||||||
|
|
||||||
|
``py.test test_hello.py`` は、実際には次の内容と同じです::
|
||||||
|
|
||||||
|
py.test --maxfail=2 -rf test_hello.py
|
||||||
|
|
||||||
|
デフォルトでは何のオプションを追加しません。
|
||||||
|
|
||||||
|
.. confval:: norecursedirs
|
||||||
|
|
||||||
|
..
|
||||||
|
Set the directory basename patterns to avoid when recursing
|
||||||
|
for test discovery. The individual (fnmatch-style) patterns are
|
||||||
|
applied to the basename of a directory to decide if to recurse into it.
|
||||||
|
Pattern matching characters::
|
||||||
|
* matches everything
|
||||||
|
? matches any single character
|
||||||
|
[seq] matches any character in seq
|
||||||
|
[!seq] matches any char not in seq
|
||||||
|
Default patterns are ``.* _* CVS {args}``. Setting a ``norecursedir``
|
||||||
|
replaces the default. Here is an example of how to avoid
|
||||||
|
certain directories::
|
||||||
|
# content of setup.cfg
|
||||||
|
[pytest]
|
||||||
|
norecursedirs = .svn _build tmp*
|
||||||
|
|
||||||
|
再帰的に探索しないテストディレクトリのディレクトリ名のパターンを設定します。それぞれ (fnmatch スタイル) のパターンがそのディレクトリ内を再帰的に調べるかを決めるのにディレクトリ名に適用されます。パターンマッチング文字は次の通りです::
|
||||||
|
|
||||||
|
* 全てに一致する
|
||||||
|
? 任意の1文字に一致する
|
||||||
|
[seq] seq のうち任意の1文字に一致する
|
||||||
|
[!seq] seq のどの文字にも一致しない
|
||||||
|
|
||||||
|
デフォルトパターンは ``.* _* CVS {args}`` となっており、 ``norecursedir`` を設定することで置き換えられます。特定のディレクトリを探索しない方法のサンプルは次の通りです::
|
||||||
|
|
||||||
|
# setup.cfg の内容
|
||||||
|
[pytest]
|
||||||
|
norecursedirs = .svn _build tmp*
|
||||||
|
|
||||||
|
これは典型的な subversion と sphinx の build ディレクトリと ``tmp`` という接頭辞をもつディレクトリを再帰探索しない設定です。
|
||||||
|
|
||||||
|
.. confval:: python_files
|
||||||
|
|
||||||
|
..
|
||||||
|
One or more Glob-style file patterns determining which python files
|
||||||
|
are considered as test modules.
|
||||||
|
|
||||||
|
python ファイルをテストモジュールとみなす、1つかそれ以上の Glob スタイルのファイルパターンです。
|
||||||
|
|
||||||
|
.. confval:: python_classes
|
||||||
|
|
||||||
|
..
|
||||||
|
One or more name prefixes determining which test classes
|
||||||
|
are considered as test modules.
|
||||||
|
|
||||||
|
テストクラスをテストモジュールとみなす、1つかそれ以上の接頭辞です。
|
||||||
|
|
||||||
|
.. confval:: python_functions
|
||||||
|
|
||||||
|
..
|
||||||
|
One or more name prefixes determining which test functions
|
||||||
|
and methods are considered as test modules.
|
||||||
|
See :ref:`change naming conventions` for examples.
|
||||||
|
|
||||||
|
テスト関数やメソッドをテストモジュールとみなす、1つかそれ以上の接頭辞です。
|
||||||
|
|
||||||
|
:ref:`change naming conventions` のサンプルもご覧ください。
|
|
@ -0,0 +1,68 @@
|
||||||
|
..
|
||||||
|
=================================================
|
||||||
|
Feedback and contribute to py.test
|
||||||
|
=================================================
|
||||||
|
|
||||||
|
=================================
|
||||||
|
フィードバックや py.test への貢献
|
||||||
|
=================================
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
contact.txt
|
||||||
|
|
||||||
|
.. _checkout:
|
||||||
|
|
||||||
|
バージョン管理や tarball を使った作業
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
..
|
||||||
|
Working from version control or a tarball
|
||||||
|
=================================================
|
||||||
|
|
||||||
|
..
|
||||||
|
To follow development or start experiments, checkout the
|
||||||
|
complete code and documentation source with mercurial_::
|
||||||
|
|
||||||
|
開発を追いかけたり実験したりするには、 mercurial_ でドキュメントやプログラムのソースをチェックアウトしてください::
|
||||||
|
|
||||||
|
hg clone https://bitbucket.org/hpk42/pytest/
|
||||||
|
|
||||||
|
..
|
||||||
|
You can also go to the python package index and
|
||||||
|
download and unpack a TAR file::
|
||||||
|
|
||||||
|
または Python パッケージインデックスから TAR ファイルをダウンロードして解凍します::
|
||||||
|
|
||||||
|
http://pypi.python.org/pypi/pytest/
|
||||||
|
|
||||||
|
..
|
||||||
|
Activating a checkout with setuptools
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
setuptools でチェックアウトしたものを有効にする
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
With a working Distribute_ or setuptools_ installation you can type::
|
||||||
|
|
||||||
|
distribute_ または setuptools_ を使うと、次のようにしてインストールできます::
|
||||||
|
|
||||||
|
python setup.py develop
|
||||||
|
|
||||||
|
..
|
||||||
|
in order to work inline with the tools and the lib of your checkout.
|
||||||
|
|
||||||
|
チェックアウトしたツールやライブラリを使います。
|
||||||
|
|
||||||
|
..
|
||||||
|
If this command complains that it could not find the required version
|
||||||
|
of "py" then you need to use the development pypi repository::
|
||||||
|
|
||||||
|
このコマンドが "py" の必要なバージョンを発見できなかったとエラーを発生させる場合、開発版の pypi リポジトリを使う必要があります::
|
||||||
|
|
||||||
|
python setup.py develop -i http://pypi.testrun.org
|
||||||
|
|
||||||
|
|
||||||
|
.. include:: links.inc
|
|
@ -0,0 +1,74 @@
|
||||||
|
|
||||||
|
..
|
||||||
|
Doctest integration for modules and test files
|
||||||
|
=========================================================
|
||||||
|
|
||||||
|
モジュールやテストファイルの doctest
|
||||||
|
====================================
|
||||||
|
|
||||||
|
..
|
||||||
|
By default all files matching the ``test*.txt`` pattern will
|
||||||
|
be run through the python standard ``doctest`` module. You
|
||||||
|
can change the pattern by issuing::
|
||||||
|
|
||||||
|
デフォルトで ``test*.txt`` のパターンに一致する全てのファイルは、Python 標準の ``doctest`` モジュールで実行されます。次のようにコマンドラインでこのパターンを変更できます::
|
||||||
|
|
||||||
|
py.test --doctest-glob='*.rst'
|
||||||
|
|
||||||
|
..
|
||||||
|
on the command line. You can also trigger running of doctests
|
||||||
|
from docstrings in all python modules (including regular
|
||||||
|
python test modules)::
|
||||||
|
|
||||||
|
Python モジュール (通常 python テストモジュールを含む) の docstring からも doctest を実行できます::
|
||||||
|
|
||||||
|
py.test --doctest-modules
|
||||||
|
|
||||||
|
..
|
||||||
|
You can make these changes permanent in your project by
|
||||||
|
putting them into a pytest.ini file like this::
|
||||||
|
|
||||||
|
次のように pytest.ini にその設定を追加することで、自分のプロジェクトでそういった変更を永続化できます::
|
||||||
|
|
||||||
|
# pytest.ini の内容
|
||||||
|
[pytest]
|
||||||
|
addopts = --doctest-modules
|
||||||
|
|
||||||
|
..
|
||||||
|
If you then have a text file like this::
|
||||||
|
|
||||||
|
次のようなテキストファイルが存在して::
|
||||||
|
|
||||||
|
# example.rst の内容
|
||||||
|
|
||||||
|
hello this is a doctest
|
||||||
|
>>> x = 3
|
||||||
|
>>> x
|
||||||
|
3
|
||||||
|
|
||||||
|
..
|
||||||
|
and another like this::
|
||||||
|
|
||||||
|
他にも次のようなファイルも存在するとします::
|
||||||
|
|
||||||
|
# mymodule.py の内容
|
||||||
|
def something():
|
||||||
|
""" a doctest in a docstring
|
||||||
|
>>> something()
|
||||||
|
42
|
||||||
|
"""
|
||||||
|
return 42
|
||||||
|
|
||||||
|
..
|
||||||
|
then you can just invoke ``py.test`` without command line options::
|
||||||
|
|
||||||
|
コマンドラインオプションを指定せず ``py.test`` を実行するだけです::
|
||||||
|
|
||||||
|
$ py.test
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 1 items
|
||||||
|
|
||||||
|
mymodule.py .
|
||||||
|
|
||||||
|
========================= 1 passed in 0.02 seconds =========================
|
|
@ -0,0 +1,213 @@
|
||||||
|
from py.test import raises
|
||||||
|
import py
|
||||||
|
|
||||||
|
def otherfunc(a,b):
|
||||||
|
assert a==b
|
||||||
|
|
||||||
|
def somefunc(x,y):
|
||||||
|
otherfunc(x,y)
|
||||||
|
|
||||||
|
def otherfunc_multi(a,b):
|
||||||
|
assert (a ==
|
||||||
|
b)
|
||||||
|
|
||||||
|
def test_generative(param1, param2):
|
||||||
|
assert param1 * 2 < param2
|
||||||
|
|
||||||
|
def pytest_generate_tests(metafunc):
|
||||||
|
if 'param1' in metafunc.funcargnames:
|
||||||
|
metafunc.addcall(funcargs=dict(param1=3, param2=6))
|
||||||
|
|
||||||
|
class TestFailing(object):
|
||||||
|
def test_simple(self):
|
||||||
|
def f():
|
||||||
|
return 42
|
||||||
|
def g():
|
||||||
|
return 43
|
||||||
|
|
||||||
|
assert f() == g()
|
||||||
|
|
||||||
|
def test_simple_multiline(self):
|
||||||
|
otherfunc_multi(
|
||||||
|
42,
|
||||||
|
6*9)
|
||||||
|
|
||||||
|
def test_not(self):
|
||||||
|
def f():
|
||||||
|
return 42
|
||||||
|
assert not f()
|
||||||
|
|
||||||
|
class TestSpecialisedExplanations(object):
|
||||||
|
def test_eq_text(self):
|
||||||
|
assert 'spam' == 'eggs'
|
||||||
|
|
||||||
|
def test_eq_similar_text(self):
|
||||||
|
assert 'foo 1 bar' == 'foo 2 bar'
|
||||||
|
|
||||||
|
def test_eq_multiline_text(self):
|
||||||
|
assert 'foo\nspam\nbar' == 'foo\neggs\nbar'
|
||||||
|
|
||||||
|
def test_eq_long_text(self):
|
||||||
|
a = '1'*100 + 'a' + '2'*100
|
||||||
|
b = '1'*100 + 'b' + '2'*100
|
||||||
|
assert a == b
|
||||||
|
|
||||||
|
def test_eq_long_text_multiline(self):
|
||||||
|
a = '1\n'*100 + 'a' + '2\n'*100
|
||||||
|
b = '1\n'*100 + 'b' + '2\n'*100
|
||||||
|
assert a == b
|
||||||
|
|
||||||
|
def test_eq_list(self):
|
||||||
|
assert [0, 1, 2] == [0, 1, 3]
|
||||||
|
|
||||||
|
def test_eq_list_long(self):
|
||||||
|
a = [0]*100 + [1] + [3]*100
|
||||||
|
b = [0]*100 + [2] + [3]*100
|
||||||
|
assert a == b
|
||||||
|
|
||||||
|
def test_eq_dict(self):
|
||||||
|
assert {'a': 0, 'b': 1} == {'a': 0, 'b': 2}
|
||||||
|
|
||||||
|
def test_eq_set(self):
|
||||||
|
assert set([0, 10, 11, 12]) == set([0, 20, 21])
|
||||||
|
|
||||||
|
def test_eq_longer_list(self):
|
||||||
|
assert [1,2] == [1,2,3]
|
||||||
|
|
||||||
|
def test_in_list(self):
|
||||||
|
assert 1 in [0, 2, 3, 4, 5]
|
||||||
|
|
||||||
|
def test_not_in_text_multiline(self):
|
||||||
|
text = 'some multiline\ntext\nwhich\nincludes foo\nand a\ntail'
|
||||||
|
assert 'foo' not in text
|
||||||
|
|
||||||
|
def test_not_in_text_single(self):
|
||||||
|
text = 'single foo line'
|
||||||
|
assert 'foo' not in text
|
||||||
|
|
||||||
|
def test_not_in_text_single_long(self):
|
||||||
|
text = 'head ' * 50 + 'foo ' + 'tail ' * 20
|
||||||
|
assert 'foo' not in text
|
||||||
|
|
||||||
|
def test_not_in_text_single_long_term(self):
|
||||||
|
text = 'head ' * 50 + 'f'*70 + 'tail ' * 20
|
||||||
|
assert 'f'*70 not in text
|
||||||
|
|
||||||
|
|
||||||
|
def test_attribute():
|
||||||
|
class Foo(object):
|
||||||
|
b = 1
|
||||||
|
i = Foo()
|
||||||
|
assert i.b == 2
|
||||||
|
|
||||||
|
|
||||||
|
def test_attribute_instance():
|
||||||
|
class Foo(object):
|
||||||
|
b = 1
|
||||||
|
assert Foo().b == 2
|
||||||
|
|
||||||
|
|
||||||
|
def test_attribute_failure():
|
||||||
|
class Foo(object):
|
||||||
|
def _get_b(self):
|
||||||
|
raise Exception('Failed to get attrib')
|
||||||
|
b = property(_get_b)
|
||||||
|
i = Foo()
|
||||||
|
assert i.b == 2
|
||||||
|
|
||||||
|
|
||||||
|
def test_attribute_multiple():
|
||||||
|
class Foo(object):
|
||||||
|
b = 1
|
||||||
|
class Bar(object):
|
||||||
|
b = 2
|
||||||
|
assert Foo().b == Bar().b
|
||||||
|
|
||||||
|
|
||||||
|
def globf(x):
|
||||||
|
return x+1
|
||||||
|
|
||||||
|
class TestRaises:
|
||||||
|
def test_raises(self):
|
||||||
|
s = 'qwe'
|
||||||
|
raises(TypeError, "int(s)")
|
||||||
|
|
||||||
|
def test_raises_doesnt(self):
|
||||||
|
raises(IOError, "int('3')")
|
||||||
|
|
||||||
|
def test_raise(self):
|
||||||
|
raise ValueError("demo error")
|
||||||
|
|
||||||
|
def test_tupleerror(self):
|
||||||
|
a,b = [1]
|
||||||
|
|
||||||
|
def test_reinterpret_fails_with_print_for_the_fun_of_it(self):
|
||||||
|
l = [1,2,3]
|
||||||
|
print ("l is %r" % l)
|
||||||
|
a,b = l.pop()
|
||||||
|
|
||||||
|
def test_some_error(self):
|
||||||
|
if namenotexi:
|
||||||
|
pass
|
||||||
|
|
||||||
|
def func1(self):
|
||||||
|
assert 41 == 42
|
||||||
|
|
||||||
|
|
||||||
|
# thanks to Matthew Scott for this test
|
||||||
|
def test_dynamic_compile_shows_nicely():
|
||||||
|
src = 'def foo():\n assert 1 == 0\n'
|
||||||
|
name = 'abc-123'
|
||||||
|
module = py.std.imp.new_module(name)
|
||||||
|
code = py.code.compile(src, name, 'exec')
|
||||||
|
py.builtin.exec_(code, module.__dict__)
|
||||||
|
py.std.sys.modules[name] = module
|
||||||
|
module.foo()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class TestMoreErrors:
|
||||||
|
def test_complex_error(self):
|
||||||
|
def f():
|
||||||
|
return 44
|
||||||
|
def g():
|
||||||
|
return 43
|
||||||
|
somefunc(f(), g())
|
||||||
|
|
||||||
|
def test_z1_unpack_error(self):
|
||||||
|
l = []
|
||||||
|
a,b = l
|
||||||
|
|
||||||
|
def test_z2_type_error(self):
|
||||||
|
l = 3
|
||||||
|
a,b = l
|
||||||
|
|
||||||
|
def test_startswith(self):
|
||||||
|
s = "123"
|
||||||
|
g = "456"
|
||||||
|
assert s.startswith(g)
|
||||||
|
|
||||||
|
def test_startswith_nested(self):
|
||||||
|
def f():
|
||||||
|
return "123"
|
||||||
|
def g():
|
||||||
|
return "456"
|
||||||
|
assert f().startswith(g())
|
||||||
|
|
||||||
|
def test_global_func(self):
|
||||||
|
assert isinstance(globf(42), float)
|
||||||
|
|
||||||
|
def test_instance(self):
|
||||||
|
self.x = 6*7
|
||||||
|
assert self.x != 42
|
||||||
|
|
||||||
|
def test_compare(self):
|
||||||
|
assert globf(10) < 5
|
||||||
|
|
||||||
|
def test_try_finally(self):
|
||||||
|
x = 1
|
||||||
|
try:
|
||||||
|
assert x == 0
|
||||||
|
finally:
|
||||||
|
x = 0
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
import pytest, py
|
||||||
|
mydir = py.path.local(__file__).dirpath()
|
||||||
|
|
||||||
|
def pytest_runtest_setup(item):
|
||||||
|
if isinstance(item, pytest.Function):
|
||||||
|
if not item.fspath.relto(mydir):
|
||||||
|
return
|
||||||
|
mod = item.getparent(pytest.Module).obj
|
||||||
|
if hasattr(mod, 'hello'):
|
||||||
|
print ("mod.hello %r" % (mod.hello,))
|
|
@ -0,0 +1,5 @@
|
||||||
|
|
||||||
|
hello = "world"
|
||||||
|
|
||||||
|
def test_func():
|
||||||
|
pass
|
|
@ -0,0 +1,14 @@
|
||||||
|
|
||||||
|
import py
|
||||||
|
failure_demo = py.path.local(__file__).dirpath('failure_demo.py')
|
||||||
|
pytest_plugins = 'pytester',
|
||||||
|
|
||||||
|
def test_failure_demo_fails_properly(testdir):
|
||||||
|
target = testdir.tmpdir.join(failure_demo.basename)
|
||||||
|
failure_demo.copy(target)
|
||||||
|
failure_demo.copy(testdir.tmpdir.join(failure_demo.basename))
|
||||||
|
result = testdir.runpytest(target)
|
||||||
|
result.stdout.fnmatch_lines([
|
||||||
|
"*39 failed*"
|
||||||
|
])
|
||||||
|
assert result.ret != 0
|
|
@ -0,0 +1,42 @@
|
||||||
|
def setup_module(module):
|
||||||
|
module.TestStateFullThing.classcount = 0
|
||||||
|
|
||||||
|
class TestStateFullThing:
|
||||||
|
def setup_class(cls):
|
||||||
|
cls.classcount += 1
|
||||||
|
|
||||||
|
def teardown_class(cls):
|
||||||
|
cls.classcount -= 1
|
||||||
|
|
||||||
|
def setup_method(self, method):
|
||||||
|
self.id = eval(method.__name__[5:])
|
||||||
|
|
||||||
|
def test_42(self):
|
||||||
|
assert self.classcount == 1
|
||||||
|
assert self.id == 42
|
||||||
|
|
||||||
|
def test_23(self):
|
||||||
|
assert self.classcount == 1
|
||||||
|
assert self.id == 23
|
||||||
|
|
||||||
|
def teardown_module(module):
|
||||||
|
assert module.TestStateFullThing.classcount == 0
|
||||||
|
|
||||||
|
""" For this example the control flow happens as follows::
|
||||||
|
import test_setup_flow_example
|
||||||
|
setup_module(test_setup_flow_example)
|
||||||
|
setup_class(TestStateFullThing)
|
||||||
|
instance = TestStateFullThing()
|
||||||
|
setup_method(instance, instance.test_42)
|
||||||
|
instance.test_42()
|
||||||
|
setup_method(instance, instance.test_23)
|
||||||
|
instance.test_23()
|
||||||
|
teardown_class(TestStateFullThing)
|
||||||
|
teardown_module(test_setup_flow_example)
|
||||||
|
|
||||||
|
Note that ``setup_class(TestStateFullThing)`` is called and not
|
||||||
|
``TestStateFullThing.setup_class()`` which would require you
|
||||||
|
to insert ``setup_class = classmethod(setup_class)`` to make
|
||||||
|
your setup function callable.
|
||||||
|
"""
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
|
||||||
|
.. _`accept example`:
|
||||||
|
|
||||||
|
example: specifying and selecting acceptance tests
|
||||||
|
--------------------------------------------------------------
|
||||||
|
|
||||||
|
.. sourcecode:: python
|
||||||
|
|
||||||
|
# ./conftest.py
|
||||||
|
def pytest_option(parser):
|
||||||
|
group = parser.getgroup("myproject")
|
||||||
|
group.addoption("-A", dest="acceptance", action="store_true",
|
||||||
|
help="run (slow) acceptance tests")
|
||||||
|
|
||||||
|
def pytest_funcarg__accept(request):
|
||||||
|
return AcceptFuncarg(request)
|
||||||
|
|
||||||
|
class AcceptFuncarg:
|
||||||
|
def __init__(self, request):
|
||||||
|
if not request.config.option.acceptance:
|
||||||
|
pytest.skip("specify -A to run acceptance tests")
|
||||||
|
self.tmpdir = request.config.mktemp(request.function.__name__, numbered=True)
|
||||||
|
|
||||||
|
def run(self, cmd):
|
||||||
|
""" called by test code to execute an acceptance test. """
|
||||||
|
self.tmpdir.chdir()
|
||||||
|
return py.process.cmdexec(cmd)
|
||||||
|
|
||||||
|
|
||||||
|
and the actual test function example:
|
||||||
|
|
||||||
|
.. sourcecode:: python
|
||||||
|
|
||||||
|
def test_some_acceptance_aspect(accept):
|
||||||
|
accept.tmpdir.mkdir("somesub")
|
||||||
|
result = accept.run("ls -la")
|
||||||
|
assert "somesub" in result
|
||||||
|
|
||||||
|
If you run this test without specifying a command line option
|
||||||
|
the test will get skipped with an appropriate message. Otherwise
|
||||||
|
you can start to add convenience and test support methods
|
||||||
|
to your AcceptFuncarg and drive running of tools or
|
||||||
|
applications and provide ways to do assertions about
|
||||||
|
the output.
|
||||||
|
|
||||||
|
.. _`decorate a funcarg`:
|
||||||
|
|
||||||
|
example: decorating a funcarg in a test module
|
||||||
|
--------------------------------------------------------------
|
||||||
|
|
||||||
|
For larger scale setups it's sometimes useful to decorate
|
||||||
|
a funcarg just for a particular test module. We can
|
||||||
|
extend the `accept example`_ by putting this in our test module:
|
||||||
|
|
||||||
|
.. sourcecode:: python
|
||||||
|
|
||||||
|
def pytest_funcarg__accept(request):
|
||||||
|
# call the next factory (living in our conftest.py)
|
||||||
|
arg = request.getfuncargvalue("accept")
|
||||||
|
# create a special layout in our tempdir
|
||||||
|
arg.tmpdir.mkdir("special")
|
||||||
|
return arg
|
||||||
|
|
||||||
|
class TestSpecialAcceptance:
|
||||||
|
def test_sometest(self, accept):
|
||||||
|
assert accept.tmpdir.join("special").check()
|
||||||
|
|
||||||
|
Our module level factory will be invoked first and it can
|
||||||
|
ask its request object to call the next factory and then
|
||||||
|
decorate its result. This mechanism allows us to stay
|
||||||
|
ignorant of how/where the function argument is provided -
|
||||||
|
in our example from a `conftest plugin`_.
|
||||||
|
|
||||||
|
sidenote: the temporary directory used here are instances of
|
||||||
|
the `py.path.local`_ class which provides many of the os.path
|
||||||
|
methods in a convenient way.
|
||||||
|
|
||||||
|
.. _`py.path.local`: ../path.html#local
|
||||||
|
.. _`conftest plugin`: customize.html#conftestplugin
|
|
@ -0,0 +1 @@
|
||||||
|
collect_ignore = ["nonpython"]
|
|
@ -0,0 +1,17 @@
|
||||||
|
|
||||||
|
def pytest_funcarg__setup(request):
|
||||||
|
return request.cached_setup(
|
||||||
|
setup=lambda: CostlySetup(),
|
||||||
|
teardown=lambda costlysetup: costlysetup.finalize(),
|
||||||
|
scope="session",
|
||||||
|
)
|
||||||
|
|
||||||
|
class CostlySetup:
|
||||||
|
def __init__(self):
|
||||||
|
import time
|
||||||
|
print ("performing costly setup")
|
||||||
|
time.sleep(5)
|
||||||
|
self.timecostly = 1
|
||||||
|
|
||||||
|
def finalize(self):
|
||||||
|
del self.timecostly
|
|
@ -0,0 +1 @@
|
||||||
|
#
|
|
@ -0,0 +1,3 @@
|
||||||
|
|
||||||
|
def test_quick(setup):
|
||||||
|
pass
|
|
@ -0,0 +1 @@
|
||||||
|
#
|
|
@ -0,0 +1,6 @@
|
||||||
|
def test_something(setup):
|
||||||
|
assert setup.timecostly == 1
|
||||||
|
|
||||||
|
def test_something_more(setup):
|
||||||
|
assert setup.timecostly == 1
|
||||||
|
|
|
@ -0,0 +1,33 @@
|
||||||
|
|
||||||
|
.. _examples:
|
||||||
|
|
||||||
|
使用方法と例
|
||||||
|
============
|
||||||
|
|
||||||
|
..
|
||||||
|
Usages and Examples
|
||||||
|
===========================================
|
||||||
|
|
||||||
|
..
|
||||||
|
Here is a (growing) list of examples. :ref:`Contact <contact>` us if you
|
||||||
|
need more examples or have questions. Also take a look at the :ref:`comprehensive documentation <toc>` which contains many example snippets as well.
|
||||||
|
|
||||||
|
次に pytest の使い方のサンプルリストがあります (さらに増やし続けます) 。もっと良いサンプルや質問があれば :ref:`ご連絡ください <contact>` 。また :ref:`オンラインドキュメント全体 <toc>` を見渡しても多くのサンプルやスニペットがあります。
|
||||||
|
|
||||||
|
..
|
||||||
|
see :doc:`../getting-started` for basic introductory examples
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
基本的な使い方は :doc:`../getting-started` を参照してください
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
reportingdemo.txt
|
||||||
|
simple.txt
|
||||||
|
mysetup.txt
|
||||||
|
parametrize.txt
|
||||||
|
markers.txt
|
||||||
|
pythoncollection.txt
|
||||||
|
nonpython.txt
|
|
@ -0,0 +1,4 @@
|
||||||
|
[pytest]
|
||||||
|
testfilepatterns =
|
||||||
|
${topdir}/tests/unit/test_${basename}
|
||||||
|
${topdir}/tests/functional/*.py
|
|
@ -0,0 +1,404 @@
|
||||||
|
|
||||||
|
.. _`mark examples`:
|
||||||
|
|
||||||
|
カスタムマーカーを使う
|
||||||
|
======================
|
||||||
|
|
||||||
|
..
|
||||||
|
Working with custom markers
|
||||||
|
=================================================
|
||||||
|
|
||||||
|
..
|
||||||
|
Here are some example using the :ref:`mark` mechanism.
|
||||||
|
|
||||||
|
ここでは :ref:`mark` の仕組みを使ったサンプルを紹介します。
|
||||||
|
|
||||||
|
..
|
||||||
|
Marking test functions and selecting them for a run
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
テスト関数をマークして実行時に選択
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
You can "mark" a test function with custom metadata like this::
|
||||||
|
|
||||||
|
次のようにカスタムメタデータでテスト関数を "マーク" できます::
|
||||||
|
|
||||||
|
# test_server.py の内容
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
@pytest.mark.webtest
|
||||||
|
def test_send_http():
|
||||||
|
pass # アプリの webtest テストを実行
|
||||||
|
def test_something_quick():
|
||||||
|
pass
|
||||||
|
|
||||||
|
.. versionadded:: 2.2
|
||||||
|
|
||||||
|
..
|
||||||
|
You can then restrict a test run to only run tests marked with ``webtest``::
|
||||||
|
|
||||||
|
``webtest`` でマークされたテストのみを実行するように制限できます::
|
||||||
|
|
||||||
|
$ py.test -v -m webtest
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4 -- /home/hpk/venv/0/bin/python
|
||||||
|
collecting ... collected 2 items
|
||||||
|
|
||||||
|
test_server.py:3: test_send_http PASSED
|
||||||
|
|
||||||
|
=================== 1 tests deselected by "-m 'webtest'" ===================
|
||||||
|
================== 1 passed, 1 deselected in 0.00 seconds ==================
|
||||||
|
|
||||||
|
..
|
||||||
|
Or the inverse, running all tests except the webtest ones::
|
||||||
|
|
||||||
|
もしくは逆に webtest を除く全てのテストを実行します::
|
||||||
|
|
||||||
|
$ py.test -v -m "not webtest"
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4 -- /home/hpk/venv/0/bin/python
|
||||||
|
collecting ... collected 2 items
|
||||||
|
|
||||||
|
test_server.py:6: test_something_quick PASSED
|
||||||
|
|
||||||
|
================= 1 tests deselected by "-m 'not webtest'" =================
|
||||||
|
================== 1 passed, 1 deselected in 0.00 seconds ==================
|
||||||
|
|
||||||
|
..
|
||||||
|
Registering markers
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
マーカーの登録
|
||||||
|
--------------
|
||||||
|
|
||||||
|
.. versionadded:: 2.2
|
||||||
|
|
||||||
|
..
|
||||||
|
Registering markers for your test suite is simple::
|
||||||
|
|
||||||
|
.. ini-syntax for custom markers:
|
||||||
|
|
||||||
|
テストスイートにマーカーを登録するのは登録です::
|
||||||
|
|
||||||
|
# pytest.ini の内容
|
||||||
|
[pytest]
|
||||||
|
markers =
|
||||||
|
webtest: mark a test as a webtest.
|
||||||
|
|
||||||
|
..
|
||||||
|
You can ask which markers exist for your test suite - the list includes our just defined ``webtest`` markers::
|
||||||
|
|
||||||
|
テストスイートに存在するマーカーが調べます。次の一覧では、先ほど定義した ``webtest`` マーカーがあります::
|
||||||
|
|
||||||
|
$ py.test --markers
|
||||||
|
@pytest.mark.webtest: mark a test as a webtest.
|
||||||
|
|
||||||
|
@pytest.mark.skipif(*conditions): skip the given test function if evaluation of all conditions has a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform.
|
||||||
|
|
||||||
|
@pytest.mark.xfail(*conditions, reason=None, run=True): mark the the test function as an expected failure. Optionally specify a reason and run=False if you don't even want to execute the test function. Any positional condition strings will be evaluated (like with skipif) and if one is False the marker will not be applied.
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in multiple different argument value sets. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.
|
||||||
|
|
||||||
|
@pytest.mark.tryfirst: mark a hook implementation function such that the plugin machinery will try to call it first/as early as possible.
|
||||||
|
|
||||||
|
@pytest.mark.trylast: mark a hook implementation function such that the plugin machinery will try to call it last/as late as possible.
|
||||||
|
|
||||||
|
..
|
||||||
|
For an example on how to add and work with markers from a plugin, see
|
||||||
|
:ref:`adding a custom marker from a plugin`.
|
||||||
|
|
||||||
|
プラグインからマーカーを追加して処理するサンプルについては :ref:`adding a custom marker from a plugin` を参照してください。
|
||||||
|
|
||||||
|
..
|
||||||
|
It is recommended to explicitely register markers so that:
|
||||||
|
|
||||||
|
* there is one place in your test suite defining your markers
|
||||||
|
|
||||||
|
* asking for existing markers via ``py.test --markers`` gives good output
|
||||||
|
|
||||||
|
* typos in function markers are treated as an error if you use
|
||||||
|
the ``--strict`` option. Later versions of py.test are probably
|
||||||
|
going to treat non-registered markers as an error.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
次のように明示的にマーカーを登録することを推奨します:
|
||||||
|
|
||||||
|
* テストスイートの一箇所でマーカーを定義する
|
||||||
|
|
||||||
|
* ``py.test --markers`` で既存のマーカーに関する分かりやすい説明を表示する
|
||||||
|
|
||||||
|
* ``--strict`` オプションを使うと、関数マーカー内の誤字をエラーにします、最近の py.test バージョンでは、未登録マーカーをエラーとして扱うようにしています
|
||||||
|
|
||||||
|
.. _`scoped-marking`:
|
||||||
|
|
||||||
|
クラスまたはモジュール全体をマーキング
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Marking whole classes or modules
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
If you are programming with Python 2.6 or later you may use ``pytest.mark``
|
||||||
|
decorators with classes to apply markers to all of its test methods::
|
||||||
|
|
||||||
|
Python 2.6 か、それ以上のバージョンでコーディングしているなら、クラスのテストメソッド全てにマーカーを適用するために ``pytest.mark`` をクラスデコレーターとして使えます::
|
||||||
|
|
||||||
|
# test_mark_classlevel.py の内容
|
||||||
|
import pytest
|
||||||
|
@pytest.mark.webtest
|
||||||
|
class TestClass:
|
||||||
|
def test_startup(self):
|
||||||
|
pass
|
||||||
|
def test_startup_and_more(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
..
|
||||||
|
This is equivalent to directly applying the decorator to the
|
||||||
|
two test functions.
|
||||||
|
|
||||||
|
これは2つのテスト関数に直接デコレーターを適用するのと同じです。
|
||||||
|
|
||||||
|
..
|
||||||
|
To remain backward-compatible with Python 2.4 you can also set a
|
||||||
|
``pytestmark`` attribute on a TestClass like this::
|
||||||
|
|
||||||
|
Pythn 2.4 との後方互換性を維持するには、次のように TestClass に ``pytestmark`` 属性も設定できます::
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
class TestClass:
|
||||||
|
pytestmark = pytest.mark.webtest
|
||||||
|
|
||||||
|
..
|
||||||
|
or if you need to use multiple markers you can use a list::
|
||||||
|
|
||||||
|
もしくは、複数のマーカーを使う必要がある場合はリストも使えます::
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
class TestClass:
|
||||||
|
pytestmark = [pytest.mark.webtest, pytest.mark.slowtest]
|
||||||
|
|
||||||
|
..
|
||||||
|
You can also set a module level marker::
|
||||||
|
|
||||||
|
モジュールレベルのマーカーも設定できます::
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
pytestmark = pytest.mark.webtest
|
||||||
|
|
||||||
|
..
|
||||||
|
in which case it will be applied to all functions and
|
||||||
|
methods defined in the module.
|
||||||
|
|
||||||
|
この場合、そのモジュール内で定義されている全ての関数とメソッドに適用されます。
|
||||||
|
|
||||||
|
..
|
||||||
|
Using ``-k TEXT`` to select tests
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
``-k TEXT`` を使ったテストの選択
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
You can use the ``-k`` command line option to only run tests with names matching
|
||||||
|
the given argument::
|
||||||
|
|
||||||
|
指定した引数に一致する名前のテストを実行するには ``-k`` コマンドラインオプションを使います::
|
||||||
|
|
||||||
|
$ py.test -k send_http # 前節で定義したサンプルを実行
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 4 items
|
||||||
|
|
||||||
|
test_server.py .
|
||||||
|
|
||||||
|
=================== 3 tests deselected by '-ksend_http' ====================
|
||||||
|
================== 1 passed, 3 deselected in 0.01 seconds ==================
|
||||||
|
|
||||||
|
..
|
||||||
|
And you can also run all tests except the ones that match the keyword::
|
||||||
|
|
||||||
|
また、そのキーワードに一致するものを除く全てのテストを実行することもできます::
|
||||||
|
|
||||||
|
$ py.test -k-send_http
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 4 items
|
||||||
|
|
||||||
|
test_mark_classlevel.py ..
|
||||||
|
test_server.py .
|
||||||
|
|
||||||
|
=================== 1 tests deselected by '-k-send_http' ===================
|
||||||
|
================== 3 passed, 1 deselected in 0.01 seconds ==================
|
||||||
|
|
||||||
|
..
|
||||||
|
Or to only select the class::
|
||||||
|
|
||||||
|
もしくは、クラスのみを選択するには次のようにします::
|
||||||
|
|
||||||
|
$ py.test -kTestClass
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 4 items
|
||||||
|
|
||||||
|
test_mark_classlevel.py ..
|
||||||
|
|
||||||
|
=================== 2 tests deselected by '-kTestClass' ====================
|
||||||
|
================== 2 passed, 2 deselected in 0.01 seconds ==================
|
||||||
|
|
||||||
|
.. _`adding a custom marker from a plugin`:
|
||||||
|
|
||||||
|
カスタムマーカーとコマンドラインオプションによるテストの実行制御
|
||||||
|
----------------------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Custom marker and command line option to control test runs
|
||||||
|
----------------------------------------------------------
|
||||||
|
|
||||||
|
.. regendoc:wipe
|
||||||
|
|
||||||
|
..
|
||||||
|
Plugins can provide custom markers and implement specific behaviour
|
||||||
|
based on it. This is a self-contained example which adds a command
|
||||||
|
line option and a parametrized test function marker to run tests
|
||||||
|
specifies via named environments::
|
||||||
|
|
||||||
|
プラグインは、カスタムマーカーを提供して、そのマーカーに基づく特別な振る舞いを実装します。これは、コマンドラインオプションと、名前付きの環境の値に特化したテストを実行するためのパラメーター化されたテスト関数マーカーを追加する自己完結型のサンプルです::
|
||||||
|
|
||||||
|
# conftest.py の内容
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
def pytest_addoption(parser):
|
||||||
|
parser.addoption("-E", dest="env", action="store", metavar="NAME",
|
||||||
|
help="only run tests matching the environment NAME.")
|
||||||
|
|
||||||
|
def pytest_configure(config):
|
||||||
|
# 追加のマーカーを登録
|
||||||
|
config.addinivalue_line("markers",
|
||||||
|
"env(name): mark test to run only on named environment")
|
||||||
|
|
||||||
|
def pytest_runtest_setup(item):
|
||||||
|
if not isinstance(item, item.Function):
|
||||||
|
return
|
||||||
|
if hasattr(item.obj, 'env'):
|
||||||
|
envmarker = getattr(item.obj, 'env')
|
||||||
|
envname = envmarker.args[0]
|
||||||
|
if envname != item.config.option.env:
|
||||||
|
pytest.skip("test requires env %r" % envname)
|
||||||
|
|
||||||
|
..
|
||||||
|
A test file using this local plugin::
|
||||||
|
|
||||||
|
この local プラグインを使うテストファイルです::
|
||||||
|
|
||||||
|
# test_someenv.py の内容
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
@pytest.mark.env("stage1")
|
||||||
|
def test_basic_db_operation():
|
||||||
|
pass
|
||||||
|
|
||||||
|
..
|
||||||
|
and an example invocations specifying a different environment than what
|
||||||
|
the test needs::
|
||||||
|
|
||||||
|
そのテストが必要とするものではない別の環境を指定して実行する例です::
|
||||||
|
|
||||||
|
$ py.test -E stage2
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 1 items
|
||||||
|
|
||||||
|
test_someenv.py s
|
||||||
|
|
||||||
|
======================== 1 skipped in 0.00 seconds =========================
|
||||||
|
|
||||||
|
..
|
||||||
|
and here is one that specifies exactly the environment needed::
|
||||||
|
|
||||||
|
今度は正しく必要とする環境を指定して実行します::
|
||||||
|
|
||||||
|
$ py.test -E stage1
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 1 items
|
||||||
|
|
||||||
|
test_someenv.py .
|
||||||
|
|
||||||
|
========================= 1 passed in 0.00 seconds =========================
|
||||||
|
|
||||||
|
..
|
||||||
|
The ``--markers`` option always gives you a list of available markers::
|
||||||
|
|
||||||
|
``--markers`` オプションは利用できるマーカーの一覧を表示します::
|
||||||
|
|
||||||
|
$ py.test --markers
|
||||||
|
@pytest.mark.env(name): mark test to run only on named environment
|
||||||
|
|
||||||
|
@pytest.mark.skipif(*conditions): skip the given test function if evaluation of all conditions has a True value. Evaluation happens within the module global context. Example: skipif('sys.platform == "win32"') skips the test if we are on the win32 platform.
|
||||||
|
|
||||||
|
@pytest.mark.xfail(*conditions, reason=None, run=True): mark the the test function as an expected failure. Optionally specify a reason and run=False if you don't even want to execute the test function. Any positional condition strings will be evaluated (like with skipif) and if one is False the marker will not be applied.
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(argnames, argvalues): call a test function multiple times passing in multiple different argument value sets. Example: @parametrize('arg1', [1,2]) would lead to two calls of the decorated test function, one with arg1=1 and another with arg1=2.
|
||||||
|
|
||||||
|
@pytest.mark.tryfirst: mark a hook implementation function such that the plugin machinery will try to call it first/as early as possible.
|
||||||
|
|
||||||
|
@pytest.mark.trylast: mark a hook implementation function such that the plugin machinery will try to call it last/as late as possible.
|
||||||
|
|
||||||
|
|
||||||
|
..
|
||||||
|
Reading markers which were set from multiple places
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
複数の場所から設定されたマーカーを読み込む
|
||||||
|
------------------------------------------
|
||||||
|
|
||||||
|
.. versionadded: 2.2.2
|
||||||
|
|
||||||
|
..
|
||||||
|
If you are heavily using markers in your test suite you may encounter the case where a marker is applied several times to a test function. From plugin
|
||||||
|
code you can read over all such settings. Example::
|
||||||
|
|
||||||
|
テストスイート内でマーカーをたくさん使うと、テスト関数に対して数回マーカーが適用される場合があります。プラグインコードから、そういった全ての設定を読み込めます。サンプルを紹介します::
|
||||||
|
|
||||||
|
# test_mark_three_times.py の内容
|
||||||
|
import pytest
|
||||||
|
pytestmark = pytest.mark.glob("module", x=1)
|
||||||
|
|
||||||
|
@pytest.mark.glob("class", x=2)
|
||||||
|
class TestClass:
|
||||||
|
@pytest.mark.glob("function", x=3)
|
||||||
|
def test_something(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
..
|
||||||
|
Here we have the marker "glob" applied three times to the same
|
||||||
|
test function. From a conftest file we can read it like this::
|
||||||
|
|
||||||
|
ここでは、同じテスト関数に対して3回適用される "glob" マーカーがあります。conftest ファイルから次のようにしてそれを調べます::
|
||||||
|
|
||||||
|
# conftest.py の内容
|
||||||
|
|
||||||
|
def pytest_runtest_setup(item):
|
||||||
|
g = getattr(item.obj, 'glob', None)
|
||||||
|
if g is not None:
|
||||||
|
for info in g:
|
||||||
|
print ("glob args=%s kwargs=%s" %(info.args, info.kwargs))
|
||||||
|
|
||||||
|
..
|
||||||
|
Let's run this without capturing output and see what we get::
|
||||||
|
|
||||||
|
標準出力を取得せずにこのテストを実行して、何が表示されるかを見てみましょう::
|
||||||
|
|
||||||
|
$ py.test -q -s
|
||||||
|
collecting ... collected 2 items
|
||||||
|
..
|
||||||
|
2 passed in 0.01 seconds
|
||||||
|
glob args=('function',) kwargs={'x': 3}
|
||||||
|
glob args=('class',) kwargs={'x': 2}
|
||||||
|
glob args=('module',) kwargs={'x': 1}
|
|
@ -0,0 +1,60 @@
|
||||||
|
"""
|
||||||
|
module containing a parametrized tests testing cross-python
|
||||||
|
serialization via the pickle module.
|
||||||
|
"""
|
||||||
|
import py, pytest
|
||||||
|
|
||||||
|
pythonlist = ['python2.4', 'python2.5', 'python2.6', 'python2.7', 'python2.8']
|
||||||
|
|
||||||
|
def pytest_generate_tests(metafunc):
|
||||||
|
# we parametrize all "python1" and "python2" arguments to iterate
|
||||||
|
# over the python interpreters of our list above - the actual
|
||||||
|
# setup and lookup of interpreters in the python1/python2 factories
|
||||||
|
# respectively.
|
||||||
|
for arg in metafunc.funcargnames:
|
||||||
|
if arg in ("python1", "python2"):
|
||||||
|
metafunc.parametrize(arg, pythonlist, indirect=True)
|
||||||
|
|
||||||
|
@pytest.mark.parametrize("obj", [42, {}, {1:3},])
|
||||||
|
def test_basic_objects(python1, python2, obj):
|
||||||
|
python1.dumps(obj)
|
||||||
|
python2.load_and_is_true("obj == %s" % obj)
|
||||||
|
|
||||||
|
def pytest_funcarg__python1(request):
|
||||||
|
tmpdir = request.getfuncargvalue("tmpdir")
|
||||||
|
picklefile = tmpdir.join("data.pickle")
|
||||||
|
return Python(request.param, picklefile)
|
||||||
|
|
||||||
|
def pytest_funcarg__python2(request):
|
||||||
|
python1 = request.getfuncargvalue("python1")
|
||||||
|
return Python(request.param, python1.picklefile)
|
||||||
|
|
||||||
|
class Python:
|
||||||
|
def __init__(self, version, picklefile):
|
||||||
|
self.pythonpath = py.path.local.sysfind(version)
|
||||||
|
if not self.pythonpath:
|
||||||
|
py.test.skip("%r not found" %(version,))
|
||||||
|
self.picklefile = picklefile
|
||||||
|
def dumps(self, obj):
|
||||||
|
dumpfile = self.picklefile.dirpath("dump.py")
|
||||||
|
dumpfile.write(py.code.Source("""
|
||||||
|
import pickle
|
||||||
|
f = open(%r, 'wb')
|
||||||
|
s = pickle.dump(%r, f)
|
||||||
|
f.close()
|
||||||
|
""" % (str(self.picklefile), obj)))
|
||||||
|
py.process.cmdexec("%s %s" %(self.pythonpath, dumpfile))
|
||||||
|
|
||||||
|
def load_and_is_true(self, expression):
|
||||||
|
loadfile = self.picklefile.dirpath("load.py")
|
||||||
|
loadfile.write(py.code.Source("""
|
||||||
|
import pickle
|
||||||
|
f = open(%r, 'rb')
|
||||||
|
obj = pickle.load(f)
|
||||||
|
f.close()
|
||||||
|
res = eval(%r)
|
||||||
|
if not res:
|
||||||
|
raise SystemExit(1)
|
||||||
|
""" % (str(self.picklefile), expression)))
|
||||||
|
print (loadfile)
|
||||||
|
py.process.cmdexec("%s %s" %(self.pythonpath, loadfile))
|
|
@ -0,0 +1,185 @@
|
||||||
|
|
||||||
|
.. highlightlang:: python
|
||||||
|
|
||||||
|
.. _mysetup:
|
||||||
|
|
||||||
|
Mysetup パターン: アプリケーションに特化したテストフィクスチャ
|
||||||
|
==============================================================
|
||||||
|
|
||||||
|
..
|
||||||
|
Mysetup pattern: application specific test fixtures
|
||||||
|
==========================================================
|
||||||
|
|
||||||
|
..
|
||||||
|
Here is a basic useful step-by-step example for managing and interacting
|
||||||
|
with application 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 test modules and test
|
||||||
|
functions to stay ignorant of involved details.
|
||||||
|
|
||||||
|
アプリケーションに特化したテストのセットアップを管理したり、相互にやり取りする、基本的且つ便利なサンプルを順を追って紹介します。その目的としては、アプリケーションオブジェクトの一連の開始処理や設定のグルーコードやテストコードを1つの場所に集め、実行時にテストモジュールとテスト関数からそういった処理の詳細を見えなくすることです。
|
||||||
|
|
||||||
|
..
|
||||||
|
Step 1: Implementing the test/app-specific ``mysetup`` pattern
|
||||||
|
--------------------------------------------------------------
|
||||||
|
|
||||||
|
ステップ 1: アプリケーションに特化した ``mysetup`` パターンの実装
|
||||||
|
-----------------------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Let's write a simple test function using a ``mysetup`` funcarg::
|
||||||
|
|
||||||
|
``mysetup`` という関数の引数を使って、簡単なテスト関数を書いてみましょう::
|
||||||
|
|
||||||
|
# test_sample.py の内容
|
||||||
|
def test_answer(mysetup):
|
||||||
|
app = mysetup.myapp()
|
||||||
|
answer = app.question()
|
||||||
|
assert answer == 42
|
||||||
|
|
||||||
|
..
|
||||||
|
To run this test py.test needs to find and call a factory to
|
||||||
|
obtain the required ``mysetup`` function argument. To make
|
||||||
|
an according factory findable we write down a specifically named factory
|
||||||
|
method in a :ref:`local plugin <localplugin>` ::
|
||||||
|
|
||||||
|
このテストを実行するために py.test は、関数の引数に与えられた ``mysetup`` を扱うファクトリー関数を探して呼び出す必要があります。このファクトリー関数を探し出せるように :ref:`local プラグイン <localplugin>` に特別な名前をもつファクトリーメソッドを書きます::
|
||||||
|
|
||||||
|
# conftest.py の内容
|
||||||
|
from myapp import MyApp
|
||||||
|
|
||||||
|
def pytest_funcarg__mysetup(request): # "mysetup" ファクトリー関数
|
||||||
|
return MySetup()
|
||||||
|
|
||||||
|
class MySetup: # このインスタンスはテスト関数から見える
|
||||||
|
def myapp(self):
|
||||||
|
return MyApp()
|
||||||
|
|
||||||
|
..
|
||||||
|
To run the example we stub out a simple ``MyApp`` application object::
|
||||||
|
|
||||||
|
このサンプルを実行するために ``MyApp`` アプリケーションオブジェクトの簡単なスタブを作ります::
|
||||||
|
|
||||||
|
# myapp.py の内容
|
||||||
|
class MyApp:
|
||||||
|
def question(self):
|
||||||
|
return 6 * 9
|
||||||
|
|
||||||
|
..
|
||||||
|
You can now run the test::
|
||||||
|
|
||||||
|
テストを実行します::
|
||||||
|
|
||||||
|
$ py.test test_sample.py
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 1 items
|
||||||
|
|
||||||
|
test_sample.py F
|
||||||
|
|
||||||
|
================================= FAILURES =================================
|
||||||
|
_______________________________ test_answer ________________________________
|
||||||
|
|
||||||
|
mysetup = <conftest.MySetup instance at 0x17f21b8>
|
||||||
|
|
||||||
|
def test_answer(mysetup):
|
||||||
|
app = mysetup.myapp()
|
||||||
|
answer = app.question()
|
||||||
|
> assert answer == 42
|
||||||
|
E assert 54 == 42
|
||||||
|
|
||||||
|
test_sample.py:4: AssertionError
|
||||||
|
========================= 1 failed in 0.01 seconds =========================
|
||||||
|
|
||||||
|
..
|
||||||
|
This means that our ``mysetup`` object was successfully instantiated
|
||||||
|
and ``mysetup.app()`` returned an initialized ``MyApp`` instance.
|
||||||
|
We can ask it about the question and if you are confused as to what
|
||||||
|
the concrete question or answers actually mean, please see here_.
|
||||||
|
|
||||||
|
``mysetup`` オブジェクトが正常にインスタンス化されて、 ``mysetup.app()`` が初期化された ``MyApp`` インスタンスを返しました。あなたが具体的に何を聞けば良いのか、もしくは実際に何が起こったかに混乱しているなら、その質問に関して尋ねられます。 `ここ`_ をご覧ください。
|
||||||
|
|
||||||
|
.. _here: http://uncyclopedia.wikia.com/wiki/The_Hitchhiker's_Guide_to_the_Galaxy
|
||||||
|
.. _ここ: http://uncyclopedia.wikia.com/wiki/The_Hitchhiker's_Guide_to_the_Galaxy
|
||||||
|
.. _`tut-cmdlineoption`:
|
||||||
|
|
||||||
|
ステップ 2: コマンドラインオプションとテストのスキップを確認
|
||||||
|
------------------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Step 2: Checking a command line option and skipping tests
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
To add a command line option we update the ``conftest.py`` of
|
||||||
|
the previous example to add a command line option
|
||||||
|
and to offer a new mysetup method::
|
||||||
|
|
||||||
|
コマンドラインオプションを追加するには、前述したサンプルの ``conftest.py`` に、コマンドラインオプションを追加して新たな mysetup メソッドを提供するように変更します::
|
||||||
|
|
||||||
|
# ./conftest.py の内容
|
||||||
|
import pytest
|
||||||
|
from myapp import MyApp
|
||||||
|
|
||||||
|
def pytest_funcarg__mysetup(request): # "mysetup" ファクトリー関数
|
||||||
|
return MySetup(request)
|
||||||
|
|
||||||
|
def pytest_addoption(parser):
|
||||||
|
parser.addoption("--ssh", action="store", default=None,
|
||||||
|
help="specify ssh host to run tests with")
|
||||||
|
|
||||||
|
|
||||||
|
class MySetup:
|
||||||
|
def __init__(self, request):
|
||||||
|
self.config = request.config
|
||||||
|
|
||||||
|
def myapp(self):
|
||||||
|
return MyApp()
|
||||||
|
|
||||||
|
def getsshconnection(self):
|
||||||
|
host = self.config.option.ssh
|
||||||
|
if host is None:
|
||||||
|
pytest.skip("specify ssh host with --ssh")
|
||||||
|
return execnet.SshGateway(host)
|
||||||
|
|
||||||
|
|
||||||
|
..
|
||||||
|
Now any test function can use the ``mysetup.getsshconnection()`` method
|
||||||
|
like this::
|
||||||
|
|
||||||
|
次のようにテスト関数から ``mysetup.getsshconnection()`` メソッドを使えます::
|
||||||
|
|
||||||
|
# test_ssh.py の内容
|
||||||
|
class TestClass:
|
||||||
|
def test_function(self, mysetup):
|
||||||
|
conn = mysetup.getsshconnection()
|
||||||
|
# conn を使ってテストする
|
||||||
|
|
||||||
|
..
|
||||||
|
Running it yields::
|
||||||
|
|
||||||
|
実行すると次のようなレポートが表示されます::
|
||||||
|
|
||||||
|
$ py.test test_ssh.py -rs
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 1 items
|
||||||
|
|
||||||
|
test_ssh.py s
|
||||||
|
========================= short test summary info ==========================
|
||||||
|
SKIP [1] /tmp/doc-exec-220/conftest.py:22: specify ssh host with --ssh
|
||||||
|
|
||||||
|
======================== 1 skipped in 0.01 seconds =========================
|
||||||
|
|
||||||
|
..
|
||||||
|
If you specify a command line option like ``py.test --ssh=python.org`` the test will execute as expected.
|
||||||
|
|
||||||
|
``py.test --ssh=python.org`` のようにコマンドラインオプションを指定すると、期待した通りにテストが実行されます。
|
||||||
|
|
||||||
|
..
|
||||||
|
Note that neither the ``TestClass`` nor the ``test_function`` need to
|
||||||
|
know anything about how to setup the test state. It is handled separately
|
||||||
|
in your "test setup glue" code in the ``conftest.py`` file. It is easy
|
||||||
|
to extend the ``mysetup`` object for further needs in the test code - and for use by any other test functions in the files and directories below the ``conftest.py`` file.
|
||||||
|
|
||||||
|
``TestClass`` も ``test_function`` のどちらとも、テストの状態をセットアップする方法について何も知る必要がないことに注目してください。 ``conftest.py`` ファイルの "テストをセットアップするグルー" コードは別々に処理されます。テストコード内で必要に応じて ``mysetup`` オブジェクトを拡張するのは簡単です。 ``conftest.py`` ファイルの配下にあるファイルやディレクトリの、任意のテスト関数によって使われます。
|
|
@ -0,0 +1,112 @@
|
||||||
|
|
||||||
|
.. _`non-python tests`:
|
||||||
|
|
||||||
|
Python 以外のテストを扱う
|
||||||
|
=========================
|
||||||
|
|
||||||
|
..
|
||||||
|
Working with non-python tests
|
||||||
|
====================================================
|
||||||
|
|
||||||
|
.. _`yaml plugin`:
|
||||||
|
|
||||||
|
Yaml ファイルでテストを指定する基本的なサンプル
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
A basic example for specifying tests in Yaml files
|
||||||
|
--------------------------------------------------------------
|
||||||
|
|
||||||
|
.. _`pytest-yamlwsgi`: http://bitbucket.org/aafshar/pytest-yamlwsgi/src/tip/pytest_yamlwsgi.py
|
||||||
|
.. _`PyYAML`: http://pypi.python.org/pypi/PyYAML/
|
||||||
|
|
||||||
|
..
|
||||||
|
Here is an example ``conftest.py`` (extracted from Ali Afshnars special purpose `pytest-yamlwsgi`_ plugin). This ``conftest.py`` will collect ``test*.yml`` files and will execute the yaml-formatted content as custom tests:
|
||||||
|
|
||||||
|
``conftest.py`` (Ali Afshnars の特殊用途の `pytest-yamlwsgi`_ プラグインから引用) のサンプルを紹介します。この ``conftest.py`` は ``test*.yml`` ファイルを探してきて、yaml フォーマットのコンテンツをカスタムテストとして実行します:
|
||||||
|
|
||||||
|
.. include:: nonpython/conftest.py
|
||||||
|
:literal:
|
||||||
|
|
||||||
|
..
|
||||||
|
You can create a simple example file:
|
||||||
|
|
||||||
|
簡単なサンプルファイルを作成します:
|
||||||
|
|
||||||
|
.. include:: nonpython/test_simple.yml
|
||||||
|
:literal:
|
||||||
|
|
||||||
|
..
|
||||||
|
and if you installed `PyYAML`_ or a compatible YAML-parser you can
|
||||||
|
now execute the test specification::
|
||||||
|
|
||||||
|
`PyYAML`_ か、互換性のある YAML パーサーをインストール済みなら、そのテスト仕様を実行できます::
|
||||||
|
|
||||||
|
nonpython $ py.test test_simple.yml
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 2 items
|
||||||
|
|
||||||
|
test_simple.yml .F
|
||||||
|
|
||||||
|
================================= FAILURES =================================
|
||||||
|
______________________________ usecase: hello ______________________________
|
||||||
|
usecase execution failed
|
||||||
|
spec failed: 'some': 'other'
|
||||||
|
no further details known at this point.
|
||||||
|
==================== 1 failed, 1 passed in 0.06 seconds ====================
|
||||||
|
|
||||||
|
..
|
||||||
|
You get one dot for the passing ``sub1: sub1`` check and one failure.
|
||||||
|
Obviously in the above ``conftest.py`` you'll want to implement a more
|
||||||
|
interesting interpretation of the yaml-values. You can easily write
|
||||||
|
your own domain specific testing language this way.
|
||||||
|
|
||||||
|
``sub1: sub1`` は成功してドットを1つ表示し、もう1つは失敗します。上述した ``conftest.py`` は言うまでもなく単純なので、もっとおもしろい yaml 値を解釈するサンプルを実装したくなるでしょう。このように独自のドメイン固有テスト言語を簡単に記述できます。
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
..
|
||||||
|
``repr_failure(excinfo)`` is called for representing test failures.
|
||||||
|
If you create custom collection nodes you can return an error
|
||||||
|
representation string of your choice. It
|
||||||
|
will be reported as a (red) string.
|
||||||
|
|
||||||
|
``repr_failure(excinfo)`` はテストの失敗を表現するために呼ばれます。カスタムコレクションのノードを作成する場合、好きなエラーを表現する文字列を返せます。それは (赤い) 文字列で表示されます。
|
||||||
|
|
||||||
|
..
|
||||||
|
``reportinfo()`` is used for representing the test location and is also
|
||||||
|
consulted when reporting in ``verbose`` mode::
|
||||||
|
|
||||||
|
``reportinfo()`` はテストの位置を表現したり、 ``verbose`` モードではレポート時にも使われます::
|
||||||
|
|
||||||
|
nonpython $ py.test -v
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4 -- /home/hpk/venv/0/bin/python
|
||||||
|
collecting ... collected 2 items
|
||||||
|
|
||||||
|
test_simple.yml:1: usecase: ok PASSED
|
||||||
|
test_simple.yml:1: usecase: hello FAILED
|
||||||
|
|
||||||
|
================================= FAILURES =================================
|
||||||
|
______________________________ usecase: hello ______________________________
|
||||||
|
usecase execution failed
|
||||||
|
spec failed: 'some': 'other'
|
||||||
|
no further details known at this point.
|
||||||
|
==================== 1 failed, 1 passed in 0.06 seconds ====================
|
||||||
|
|
||||||
|
..
|
||||||
|
While developing your custom test collection and execution it's also
|
||||||
|
interesting to just look at the collection tree::
|
||||||
|
|
||||||
|
カスタムテストコレクションや実行処理の開発中、そのコレクションツリーをちょっと見るのもおもしろいです::
|
||||||
|
|
||||||
|
nonpython $ py.test --collectonly
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 2 items
|
||||||
|
<YamlFile 'test_simple.yml'>
|
||||||
|
<YamlItem 'ok'>
|
||||||
|
<YamlItem 'hello'>
|
||||||
|
|
||||||
|
============================= in 0.07 seconds =============================
|
|
@ -0,0 +1,40 @@
|
||||||
|
# content of conftest.py
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
def pytest_collect_file(path, parent):
|
||||||
|
if path.ext == ".yml" and path.basename.startswith("test"):
|
||||||
|
return YamlFile(path, parent)
|
||||||
|
|
||||||
|
class YamlFile(pytest.File):
|
||||||
|
def collect(self):
|
||||||
|
import yaml # we need a yaml parser, e.g. PyYAML
|
||||||
|
raw = yaml.load(self.fspath.open())
|
||||||
|
for name, spec in raw.items():
|
||||||
|
yield YamlItem(name, self, spec)
|
||||||
|
|
||||||
|
class YamlItem(pytest.Item):
|
||||||
|
def __init__(self, name, parent, spec):
|
||||||
|
super(YamlItem, self).__init__(name, parent)
|
||||||
|
self.spec = spec
|
||||||
|
|
||||||
|
def runtest(self):
|
||||||
|
for name, value in self.spec.items():
|
||||||
|
# some custom test execution (dumb example follows)
|
||||||
|
if name != value:
|
||||||
|
raise YamlException(self, name, value)
|
||||||
|
|
||||||
|
def repr_failure(self, excinfo):
|
||||||
|
""" called when self.runtest() raises an exception. """
|
||||||
|
if isinstance(excinfo.value, YamlException):
|
||||||
|
return "\n".join([
|
||||||
|
"usecase execution failed",
|
||||||
|
" spec failed: %r: %r" % excinfo.value.args[1:3],
|
||||||
|
" no further details known at this point."
|
||||||
|
])
|
||||||
|
|
||||||
|
def reportinfo(self):
|
||||||
|
return self.fspath, 0, "usecase: %s" % self.name
|
||||||
|
|
||||||
|
class YamlException(Exception):
|
||||||
|
""" custom exception for error reporting. """
|
|
@ -0,0 +1,7 @@
|
||||||
|
# test_simple.yml
|
||||||
|
ok:
|
||||||
|
sub1: sub1
|
||||||
|
|
||||||
|
hello:
|
||||||
|
world: world
|
||||||
|
some: other
|
|
@ -0,0 +1,425 @@
|
||||||
|
|
||||||
|
.. _paramexamples:
|
||||||
|
|
||||||
|
パラメーターテスト
|
||||||
|
==================
|
||||||
|
|
||||||
|
..
|
||||||
|
Parametrizing tests
|
||||||
|
=================================================
|
||||||
|
|
||||||
|
.. currentmodule:: _pytest.python
|
||||||
|
|
||||||
|
py.test は、簡単にパラメーターをテスト関数へ渡せます。パラメーターテストを行うための組み込みの仕組みを使ったサンプルを紹介します。
|
||||||
|
|
||||||
|
..
|
||||||
|
py.test allows to easily parametrize test functions.
|
||||||
|
In the following we provide some examples using
|
||||||
|
the builtin mechanisms.
|
||||||
|
|
||||||
|
.. _parametrizemark:
|
||||||
|
|
||||||
|
シンプルな "デコレーター" によるパラメーターテスト
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Simple "decorator" parametrization of a test function
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
.. versionadded:: 2.2
|
||||||
|
|
||||||
|
..
|
||||||
|
The builtin ``pytest.mark.parametrize`` decorator directly enables
|
||||||
|
parametrization of arguments for a test function. Here is an example
|
||||||
|
of a test function that wants to compare that processing some input
|
||||||
|
results in expected output::
|
||||||
|
|
||||||
|
組み込みの ``pytest.mark.parametrize`` デコレーターは、直接、テスト関数の引数へパラメーターを渡せます。入力値を処理して、その結果として期待される出力値を比較したいテスト関数のサンプルを紹介します::
|
||||||
|
|
||||||
|
# test_expectation.py の内容
|
||||||
|
import pytest
|
||||||
|
@pytest.mark.parametrize(("input", "expected"), [
|
||||||
|
("3+5", 8),
|
||||||
|
("2+4", 6),
|
||||||
|
("6*9", 42),
|
||||||
|
])
|
||||||
|
def test_eval(input, expected):
|
||||||
|
assert eval(input) == expected
|
||||||
|
|
||||||
|
..
|
||||||
|
we parametrize two arguments of the test function so that the test
|
||||||
|
function is called three times. Let's run it::
|
||||||
|
|
||||||
|
テスト関数が3回呼び出され、そのテスト関数へ2つの引数をパラメーターとして渡します。実行してみましょう::
|
||||||
|
|
||||||
|
$ py.test -q
|
||||||
|
collecting ... collected 3 items
|
||||||
|
..F
|
||||||
|
================================= FAILURES =================================
|
||||||
|
____________________________ test_eval[6*9-42] _____________________________
|
||||||
|
|
||||||
|
input = '6*9', expected = 42
|
||||||
|
|
||||||
|
@pytest.mark.parametrize(("input", "expected"), [
|
||||||
|
("3+5", 8),
|
||||||
|
("2+4", 6),
|
||||||
|
("6*9", 42),
|
||||||
|
])
|
||||||
|
def test_eval(input, expected):
|
||||||
|
> assert eval(input) == expected
|
||||||
|
E assert 54 == 42
|
||||||
|
E + where 54 = eval('6*9')
|
||||||
|
|
||||||
|
test_expectation.py:8: AssertionError
|
||||||
|
1 failed, 2 passed in 0.01 seconds
|
||||||
|
|
||||||
|
..
|
||||||
|
As expected only one pair of input/output values fails the simple test function.
|
||||||
|
|
||||||
|
期待した通り、入力値/出力値の組み合わせの1つだけがこの単純なテスト関数を失敗させます。
|
||||||
|
|
||||||
|
..
|
||||||
|
Note that there are various ways how you can mark groups of functions,
|
||||||
|
see :ref:`mark`.
|
||||||
|
|
||||||
|
関数のグループをマークする方法は様々なやり方があるのに注意してください。詳細は :ref:`mark` を参照してください。
|
||||||
|
|
||||||
|
..
|
||||||
|
Generating parameters combinations, depending on command line
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
コマンドラインからパラメーターの組み合わせを作成
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
.. regendoc:wipe
|
||||||
|
|
||||||
|
..
|
||||||
|
Let's say we want to execute a test with different computation
|
||||||
|
parameters and the parameter range shall be determined by a command
|
||||||
|
line argument. Let's first write a simple (do-nothing) computation test::
|
||||||
|
|
||||||
|
別のパラメーターでテストを実行したいときに、そのパラメーターの範囲はコマンドライン引数によって決まるものとしましょう。最初の簡単な (何もしない) テストを書いてみます::
|
||||||
|
|
||||||
|
# test_compute.py の内容
|
||||||
|
|
||||||
|
def test_compute(param1):
|
||||||
|
assert param1 < 4
|
||||||
|
|
||||||
|
..
|
||||||
|
Now we add a test configuration like this::
|
||||||
|
|
||||||
|
次のようなテスト設定を追加します::
|
||||||
|
|
||||||
|
# conftest.py の内容
|
||||||
|
|
||||||
|
def pytest_addoption(parser):
|
||||||
|
parser.addoption("--all", action="store_true",
|
||||||
|
help="run all combinations")
|
||||||
|
|
||||||
|
def pytest_generate_tests(metafunc):
|
||||||
|
if 'param1' in metafunc.funcargnames:
|
||||||
|
if metafunc.config.option.all:
|
||||||
|
end = 5
|
||||||
|
else:
|
||||||
|
end = 2
|
||||||
|
metafunc.parametrize("param1", range(end))
|
||||||
|
|
||||||
|
..
|
||||||
|
This means that we only run 2 tests if we do not pass ``--all``::
|
||||||
|
|
||||||
|
これは ``--all`` を指定しない場合、2回だけテストを実行します::
|
||||||
|
|
||||||
|
$ py.test -q test_compute.py
|
||||||
|
collecting ... collected 2 items
|
||||||
|
..
|
||||||
|
2 passed in 0.01 seconds
|
||||||
|
|
||||||
|
..
|
||||||
|
We run only two computations, so we see two dots.
|
||||||
|
let's run the full monty::
|
||||||
|
|
||||||
|
2回だけテストを実行するので、ドットが2つ表示されます。では、全テストを実行してみましょう::
|
||||||
|
|
||||||
|
$ py.test -q --all
|
||||||
|
collecting ... collected 5 items
|
||||||
|
....F
|
||||||
|
================================= FAILURES =================================
|
||||||
|
_____________________________ test_compute[4] ______________________________
|
||||||
|
|
||||||
|
param1 = 4
|
||||||
|
|
||||||
|
def test_compute(param1):
|
||||||
|
> assert param1 < 4
|
||||||
|
E assert 4 < 4
|
||||||
|
|
||||||
|
test_compute.py:3: AssertionError
|
||||||
|
1 failed, 4 passed in 0.02 seconds
|
||||||
|
|
||||||
|
..
|
||||||
|
As expected when running the full range of ``param1`` values
|
||||||
|
we'll get an error on the last one.
|
||||||
|
|
||||||
|
期待した通り ``param1`` の全ての範囲値を実行すると、最後の1つがエラーになります。
|
||||||
|
|
||||||
|
..
|
||||||
|
A quick port of "testscenarios"
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
"testscenarios" の手早い移行
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
.. _`test scenarios`: http://bazaar.launchpad.net/~lifeless/testscenarios/trunk/annotate/head%3A/doc/example.py
|
||||||
|
|
||||||
|
..
|
||||||
|
Here is a quick port to run tests configured with `test scenarios`_,
|
||||||
|
an add-on from Robert Collins for the standard unittest framework. We
|
||||||
|
only have to work a bit to construct the correct arguments for pytest's
|
||||||
|
:py:func:`Metafunc.parametrize`::
|
||||||
|
|
||||||
|
Robert Collins による標準ライブラリの unittest フレームワークのアドオンである `test scenarios`_ で設定されたテストを実行するために手早い移行方法を紹介します。pytest の :py:func:`Metafunc.parametrize` へ渡す正しい引数を作成するために少しだけコーディングが必要です::
|
||||||
|
|
||||||
|
# test_scenarios.py の内容
|
||||||
|
|
||||||
|
def pytest_generate_tests(metafunc):
|
||||||
|
idlist = []
|
||||||
|
argvalues = []
|
||||||
|
for scenario in metafunc.cls.scenarios:
|
||||||
|
idlist.append(scenario[0])
|
||||||
|
items = scenario[1].items()
|
||||||
|
argnames = [x[0] for x in items]
|
||||||
|
argvalues.append(([x[1] for x in items]))
|
||||||
|
metafunc.parametrize(argnames, argvalues, ids=idlist)
|
||||||
|
|
||||||
|
scenario1 = ('basic', {'attribute': 'value'})
|
||||||
|
scenario2 = ('advanced', {'attribute': 'value2'})
|
||||||
|
|
||||||
|
class TestSampleWithScenarios:
|
||||||
|
scenarios = [scenario1, scenario2]
|
||||||
|
|
||||||
|
def test_demo(self, attribute):
|
||||||
|
assert isinstance(attribute, str)
|
||||||
|
|
||||||
|
..
|
||||||
|
this is a fully self-contained example which you can run with::
|
||||||
|
|
||||||
|
これはすぐ実行できる完全な自己完結型サンプルです::
|
||||||
|
|
||||||
|
$ py.test test_scenarios.py
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 2 items
|
||||||
|
|
||||||
|
test_scenarios.py ..
|
||||||
|
|
||||||
|
========================= 2 passed in 0.01 seconds =========================
|
||||||
|
|
||||||
|
..
|
||||||
|
If you just collect tests you'll also nicely see 'advanced' and 'basic' as variants for the test function::
|
||||||
|
|
||||||
|
ただテストを (実行せずに) 集めるだけなら、テスト関数の変数として 'advanced' と 'basic' もうまく表示されます::
|
||||||
|
|
||||||
|
$ py.test --collectonly test_scenarios.py
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 2 items
|
||||||
|
<Module 'test_scenarios.py'>
|
||||||
|
<Class 'TestSampleWithScenarios'>
|
||||||
|
<Instance '()'>
|
||||||
|
<Function 'test_demo[basic]'>
|
||||||
|
<Function 'test_demo[advanced]'>
|
||||||
|
|
||||||
|
============================= in 0.00 seconds =============================
|
||||||
|
|
||||||
|
..
|
||||||
|
Deferring the setup of parametrized resources
|
||||||
|
---------------------------------------------------
|
||||||
|
|
||||||
|
パラメーター化されたリソースの遅延セットアップ
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
.. regendoc:wipe
|
||||||
|
|
||||||
|
..
|
||||||
|
The parametrization of test functions happens at collection
|
||||||
|
time. It is a good idea to setup expensive resources like DB
|
||||||
|
connections or subprocess only when the actual test is run.
|
||||||
|
Here is a simple example how you can achieve that, first
|
||||||
|
the actual test requiring a ``db`` object::
|
||||||
|
|
||||||
|
テスト関数へのパラメーター渡しはコレクション時に発生します。実際にテストを実行するときのみ、DB コネクションやサブプロセスといった高価なリソースをセットアップするのは良い考えです。そういったテストを行う簡単なサンプルが次になります。最初のテストは ``db`` オブジェクトを要求します::
|
||||||
|
|
||||||
|
# test_backends.py の内容
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
def test_db_initialized(db):
|
||||||
|
# ダミーテスト
|
||||||
|
if db.__class__.__name__ == "DB2":
|
||||||
|
pytest.fail("deliberately failing for demo purposes")
|
||||||
|
|
||||||
|
..
|
||||||
|
We can now add a test configuration that generates two invocations of
|
||||||
|
the ``test_db_initialized`` function and also implements a factory that
|
||||||
|
creates a database object for the actual test invocations::
|
||||||
|
|
||||||
|
``test_db_initialized`` 関数の2回実行するようにテスト設定を追加します。さらに実際のテスト実行時にデータベースオブジェクトを作成するファクトリー関数も実装します::
|
||||||
|
|
||||||
|
# conftest.py の内容
|
||||||
|
|
||||||
|
def pytest_generate_tests(metafunc):
|
||||||
|
if 'db' in metafunc.funcargnames:
|
||||||
|
metafunc.parametrize("db", ['d1', 'd2'], indirect=True)
|
||||||
|
|
||||||
|
class DB1:
|
||||||
|
"one database object"
|
||||||
|
class DB2:
|
||||||
|
"alternative database object"
|
||||||
|
|
||||||
|
def pytest_funcarg__db(request):
|
||||||
|
if request.param == "d1":
|
||||||
|
return DB1()
|
||||||
|
elif request.param == "d2":
|
||||||
|
return DB2()
|
||||||
|
else:
|
||||||
|
raise ValueError("invalid internal test config")
|
||||||
|
|
||||||
|
..
|
||||||
|
Let's first see how it looks like at collection time::
|
||||||
|
|
||||||
|
コレクション時に先ほどの設定がどうなるかを最初に見てみましょう::
|
||||||
|
|
||||||
|
$ py.test test_backends.py --collectonly
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 2 items
|
||||||
|
<Module 'test_backends.py'>
|
||||||
|
<Function 'test_db_initialized[d1]'>
|
||||||
|
<Function 'test_db_initialized[d2]'>
|
||||||
|
|
||||||
|
============================= in 0.00 seconds =============================
|
||||||
|
|
||||||
|
..
|
||||||
|
And then when we run the test::
|
||||||
|
|
||||||
|
それからテストを実行します::
|
||||||
|
|
||||||
|
$ py.test -q test_backends.py
|
||||||
|
collecting ... collected 2 items
|
||||||
|
.F
|
||||||
|
================================= FAILURES =================================
|
||||||
|
_________________________ test_db_initialized[d2] __________________________
|
||||||
|
|
||||||
|
db = <conftest.DB2 instance at 0x1d4eb00>
|
||||||
|
|
||||||
|
def test_db_initialized(db):
|
||||||
|
# ダミーテスト
|
||||||
|
if db.__class__.__name__ == "DB2":
|
||||||
|
> pytest.fail("deliberately failing for demo purposes")
|
||||||
|
E Failed: deliberately failing for demo purposes
|
||||||
|
|
||||||
|
test_backends.py:6: Failed
|
||||||
|
1 failed, 1 passed in 0.01 seconds
|
||||||
|
|
||||||
|
..
|
||||||
|
The first invocation with ``db == "DB1"`` passed while the second with ``db == "DB2"`` failed. Our ``pytest_funcarg__db`` factory has instantiated each of the DB values during the setup phase while the ``pytest_generate_tests`` generated two according calls to the ``test_db_initialized`` during the collection phase.
|
||||||
|
|
||||||
|
最初の ``db == "DB1"`` による実行が成功したのに対して、2番目の ``db == "DB2"`` は失敗しました。 ``pytest_funcarg__db`` ファクトリーは、セットアップフェーズのときにそれぞれの DB 値をインスタンス化しました。一方 ``pytest_generate_tests`` は、コレクションフェーズのときに2回の ``test_db_initialized`` 呼び出しを生成しました。
|
||||||
|
|
||||||
|
.. regendoc:wipe
|
||||||
|
|
||||||
|
..
|
||||||
|
Parametrizing test methods through per-class configuration
|
||||||
|
--------------------------------------------------------------
|
||||||
|
|
||||||
|
クラス設定毎のテストメソッドのパラメーター渡し
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
.. _`unittest parameterizer`: http://code.google.com/p/unittest-ext/source/browse/trunk/params.py
|
||||||
|
|
||||||
|
..
|
||||||
|
Here is an example ``pytest_generate_function`` function implementing a
|
||||||
|
parametrization scheme similar to Michael Foord's `unittest
|
||||||
|
parameterizer`_ but in a lot less code::
|
||||||
|
|
||||||
|
Michael Foord の `unittest parameterizer`_ とよく似ていますが、それよりもずっと少ないコードでパラメーターを渡す仕組みを実装する ``pytest_generate_function`` 関数のサンプルがあります::
|
||||||
|
|
||||||
|
# ./test_parametrize.py の内容
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
def pytest_generate_tests(metafunc):
|
||||||
|
# それぞれのテスト関数毎に1回呼び出される
|
||||||
|
funcarglist = metafunc.cls.params[metafunc.function.__name__]
|
||||||
|
argnames = list(funcarglist[0])
|
||||||
|
metafunc.parametrize(argnames, [[funcargs[name] for name in argnames]
|
||||||
|
for funcargs in funcarglist])
|
||||||
|
|
||||||
|
class TestClass:
|
||||||
|
# テストメソッドのために複数の引数セットを指定するディクショナリ
|
||||||
|
params = {
|
||||||
|
'test_equals': [dict(a=1, b=2), dict(a=3, b=3), ],
|
||||||
|
'test_zerodivision': [dict(a=1, b=0), ],
|
||||||
|
}
|
||||||
|
|
||||||
|
def test_equals(self, a, b):
|
||||||
|
assert a == b
|
||||||
|
|
||||||
|
def test_zerodivision(self, a, b):
|
||||||
|
pytest.raises(ZeroDivisionError, "a/b")
|
||||||
|
|
||||||
|
..
|
||||||
|
Our test generator looks up a class-level definition which specifies which
|
||||||
|
argument sets to use for each test function. Let's run it::
|
||||||
|
|
||||||
|
テストジェネレーターは、それぞれのテストメソッドへどの引数セットを渡すかを特定するクラスレベルの定義を調べます。実行してみましょう::
|
||||||
|
|
||||||
|
$ py.test -q
|
||||||
|
collecting ... collected 3 items
|
||||||
|
F..
|
||||||
|
================================= FAILURES =================================
|
||||||
|
________________________ TestClass.test_equals[1-2] ________________________
|
||||||
|
|
||||||
|
self = <test_parametrize.TestClass instance at 0x10d2e18>, a = 1, b = 2
|
||||||
|
|
||||||
|
def test_equals(self, a, b):
|
||||||
|
> assert a == b
|
||||||
|
E assert 1 == 2
|
||||||
|
|
||||||
|
test_parametrize.py:18: AssertionError
|
||||||
|
1 failed, 2 passed in 0.01 seconds
|
||||||
|
|
||||||
|
..
|
||||||
|
Indirect parametrization with multiple resources
|
||||||
|
--------------------------------------------------------------
|
||||||
|
|
||||||
|
複数リソースでの間接的なパラメーター渡し
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Here is a stripped down real-life example of using parametrized
|
||||||
|
testing for testing serialization, invoking different python interpreters.
|
||||||
|
We define a ``test_basic_objects`` function which is to be run
|
||||||
|
with different sets of arguments for its three arguments:
|
||||||
|
|
||||||
|
別々の Python インタープリターで実行し、シリアライズ化を検証するのにパラメーターテストを使う、実際の世界でのサンプルを解説します。次の3つの引数を全組み合わせで実行する ``test_basic_objects`` 関数を定義します。
|
||||||
|
|
||||||
|
..
|
||||||
|
* ``python1``: first python interpreter, run to pickle-dump an object to a file
|
||||||
|
* ``python2``: second interpreter, run to pickle-load an object from a file
|
||||||
|
* ``obj``: object to be dumped/loaded
|
||||||
|
|
||||||
|
* ``python1`` : 1番目の Python インタープリター、オブジェクトをファイルへ pickle-dump するために実行
|
||||||
|
* ``python2`` : 2番目の Python インタープリター、ファイルからオブジェクトを pickle-load するために実行
|
||||||
|
* ``obj`` : ダンプしたり読み込むためのオブジェクト
|
||||||
|
|
||||||
|
.. literalinclude:: multipython.py
|
||||||
|
|
||||||
|
..
|
||||||
|
Running it results in some skips if we don't have all the python interpreters installed and otherwise runs all combinations (5 interpreters times 5 interpreters times 3 objects to serialize/deserialize)::
|
||||||
|
|
||||||
|
もし全ての Python インタープリターがインストールされていない場合、実行してもスキップされます。インストール済みの場合、全ての組み合わせが実行されます (5つのインタープリター * 5つのインタープリター * 3つのシリアライズ/デシリアライズするオブジェクト)::
|
||||||
|
|
||||||
|
. $ py.test -rs -q multipython.py
|
||||||
|
collecting ... collected 75 items
|
||||||
|
............sss............sss............sss............ssssssssssssssssss
|
||||||
|
========================= short test summary info ==========================
|
||||||
|
SKIP [27] /home/hpk/p/pytest/doc/example/multipython.py:36: 'python2.8' not found
|
||||||
|
48 passed, 27 skipped in 1.71 seconds
|
|
@ -0,0 +1,16 @@
|
||||||
|
import sys
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
py3 = sys.version_info[0] >= 3
|
||||||
|
|
||||||
|
class DummyCollector(pytest.collect.File):
|
||||||
|
def collect(self):
|
||||||
|
return []
|
||||||
|
|
||||||
|
def pytest_pycollect_makemodule(path, parent):
|
||||||
|
bn = path.basename
|
||||||
|
if "py3" in bn and not py3 or ("py2" in bn and py3):
|
||||||
|
return DummyCollector(path, parent=parent)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
def test_exception_syntax():
|
||||||
|
try:
|
||||||
|
0/0
|
||||||
|
except ZeroDivisionError, e:
|
||||||
|
assert 0, e
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
|
||||||
|
def test_exception_syntax():
|
||||||
|
try:
|
||||||
|
0/0
|
||||||
|
except ZeroDivisionError as e:
|
||||||
|
assert 0, e
|
||||||
|
|
|
@ -0,0 +1,11 @@
|
||||||
|
|
||||||
|
# run this with $ py.test --collectonly test_collectonly.py
|
||||||
|
#
|
||||||
|
def test_function():
|
||||||
|
pass
|
||||||
|
|
||||||
|
class TestClass:
|
||||||
|
def test_method(self):
|
||||||
|
pass
|
||||||
|
def test_anothermethod(self):
|
||||||
|
pass
|
|
@ -0,0 +1,141 @@
|
||||||
|
標準的な (Python) テスト探索の変更
|
||||||
|
==================================
|
||||||
|
|
||||||
|
..
|
||||||
|
Changing standard (Python) test discovery
|
||||||
|
===============================================
|
||||||
|
|
||||||
|
..
|
||||||
|
Changing directory recursion
|
||||||
|
-----------------------------------------------------
|
||||||
|
|
||||||
|
ディレクトリの再帰探索の変更
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
You can set the :confval:`norecursedirs` option in an ini-file, for example your ``setup.cfg`` in the project root directory::
|
||||||
|
|
||||||
|
ini ファイルで :confval:`norecursedirs` オプションを設定できます。例えば、プロジェクトのルートディレクトリにある ``setup.cfg`` に設定します::
|
||||||
|
|
||||||
|
# setup.cfg の内容
|
||||||
|
[pytest]
|
||||||
|
norecursedirs = .svn _build tmp*
|
||||||
|
|
||||||
|
..
|
||||||
|
This would tell py.test to not recurse into typical subversion or sphinx-build directories or into any ``tmp`` prefixed directory.
|
||||||
|
|
||||||
|
これは典型的な subversion と sphinx の build ディレクトリと ``tmp`` という接頭辞をもつディレクトリを再帰探索しない設定です。
|
||||||
|
|
||||||
|
.. _`change naming conventions`:
|
||||||
|
|
||||||
|
命名規則の変更
|
||||||
|
--------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Changing naming conventions
|
||||||
|
-----------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
You can configure different naming conventions by setting
|
||||||
|
the :confval:`python_files`, :confval:`python_classes` and
|
||||||
|
:confval:`python_functions` configuration options. Example::
|
||||||
|
|
||||||
|
:confval:`python_files`, :confval:`python_classes`, :confval:`python_functions` オプションを設定することで別の命名規則を使うこともできます。サンプルを紹介します::
|
||||||
|
|
||||||
|
# setup.cfg の内容
|
||||||
|
# tox.ini または pytest.init ファイルでも定義できる
|
||||||
|
[pytest]
|
||||||
|
python_files=check_*.py
|
||||||
|
python_classes=Check
|
||||||
|
python_functions=check
|
||||||
|
|
||||||
|
..
|
||||||
|
This would make py.test look for ``check_`` prefixes in
|
||||||
|
Python filenames, ``Check`` prefixes in classes and ``check`` prefixes
|
||||||
|
in functions and classes. For example, if we have::
|
||||||
|
|
||||||
|
この設定は Python ファイル名に ``check_`` 、 クラス名に ``Check`` 、関数名に ``check`` という接頭辞を py.test が探すようにします。例えば、次のようなファイルです::
|
||||||
|
|
||||||
|
# check_myapp.py の内容
|
||||||
|
class CheckMyApp:
|
||||||
|
def check_simple(self):
|
||||||
|
pass
|
||||||
|
def check_complex(self):
|
||||||
|
pass
|
||||||
|
|
||||||
|
..
|
||||||
|
then the test collection looks like this::
|
||||||
|
|
||||||
|
テストコレクションは次のようになります::
|
||||||
|
|
||||||
|
$ py.test --collectonly
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 2 items
|
||||||
|
<Module 'check_myapp.py'>
|
||||||
|
<Class 'CheckMyApp'>
|
||||||
|
<Instance '()'>
|
||||||
|
<Function 'check_simple'>
|
||||||
|
<Function 'check_complex'>
|
||||||
|
|
||||||
|
============================= in 0.00 seconds =============================
|
||||||
|
|
||||||
|
..
|
||||||
|
Interpreting cmdline arguments as Python packages
|
||||||
|
-----------------------------------------------------
|
||||||
|
|
||||||
|
Python パッケージとしてコマンドライン引数を解釈
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
You can use the ``--pyargs`` option to make py.test try
|
||||||
|
interpreting arguments as python package names, deriving
|
||||||
|
their file system path and then running the test. For
|
||||||
|
example if you have unittest2 installed you can type::
|
||||||
|
|
||||||
|
py.test がファイルシステムのパスから Python パッケージ名として引数を解釈するように ``--pyargs`` オプションを使えます。例えば、unittest2 をインストール済みなら、次のように指定できます::
|
||||||
|
|
||||||
|
py.test --pyargs unittest2.test.test_skipping -q
|
||||||
|
|
||||||
|
..
|
||||||
|
which would run the respective test module. Like with
|
||||||
|
other options, through an ini-file and the :confval:`addopts` option you
|
||||||
|
can make this change more permanently::
|
||||||
|
|
||||||
|
それぞれのテストモジュールを実行します。その他のオプションと同様に ini ファイルと :confval:`addopts` オプションにより、この変更を永続化できます::
|
||||||
|
|
||||||
|
# pytest.ini の内容
|
||||||
|
[pytest]
|
||||||
|
addopts = --pyargs
|
||||||
|
|
||||||
|
..
|
||||||
|
Now a simple invocation of ``py.test NAME`` will check
|
||||||
|
if NAME exists as an importable package/module and otherwise
|
||||||
|
treat it as a filesystem path.
|
||||||
|
|
||||||
|
単純に ``py.test NAME`` を実行すると、NAME がインポート可能なパッケージ/モジュールとして存在しているかどうかをチェックします。存在しない場合、ファイルシステム上のパスとして NAME を扱います。
|
||||||
|
|
||||||
|
..
|
||||||
|
Finding out what is collected
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
コレクションの探索
|
||||||
|
------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
You can always peek at the collection tree without running tests like this::
|
||||||
|
|
||||||
|
次のようにテストを実行せずにコレクションツリーをピークできます::
|
||||||
|
|
||||||
|
. $ py.test --collectonly pythoncollection.py
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 3 items
|
||||||
|
<Module 'pythoncollection.py'>
|
||||||
|
<Function 'test_function'>
|
||||||
|
<Class 'TestClass'>
|
||||||
|
<Instance '()'>
|
||||||
|
<Function 'test_method'>
|
||||||
|
<Function 'test_anothermethod'>
|
||||||
|
|
||||||
|
============================= in 0.00 seconds =============================
|
|
@ -0,0 +1,550 @@
|
||||||
|
|
||||||
|
.. _`tbreportdemo`:
|
||||||
|
|
||||||
|
py.test によるテスト失敗時のレポートのデモ
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
..
|
||||||
|
Demo of Python failure reports with py.test
|
||||||
|
==================================================
|
||||||
|
|
||||||
|
..
|
||||||
|
Here is a nice run of several tens of failures
|
||||||
|
and how py.test presents things (unfortunately
|
||||||
|
not showing the nice colors here in the HTML that you
|
||||||
|
get on the terminal - we are working on that):
|
||||||
|
|
||||||
|
次に py.test がテスト失敗時のレポートをどう表現するかについての、数十個の実行結果があります (残念ながら、ここでは、ターミナルで実行したときのような見やすいカラー表示ではありません):
|
||||||
|
|
||||||
|
.. code-block:: python
|
||||||
|
|
||||||
|
assertion $ py.test failure_demo.py
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 39 items
|
||||||
|
|
||||||
|
failure_demo.py FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF
|
||||||
|
|
||||||
|
================================= FAILURES =================================
|
||||||
|
____________________________ test_generative[0] ____________________________
|
||||||
|
|
||||||
|
param1 = 3, param2 = 6
|
||||||
|
|
||||||
|
def test_generative(param1, param2):
|
||||||
|
> assert param1 * 2 < param2
|
||||||
|
E assert (3 * 2) < 6
|
||||||
|
|
||||||
|
failure_demo.py:15: AssertionError
|
||||||
|
_________________________ TestFailing.test_simple __________________________
|
||||||
|
|
||||||
|
self = <failure_demo.TestFailing object at 0x2e4dd50>
|
||||||
|
|
||||||
|
def test_simple(self):
|
||||||
|
def f():
|
||||||
|
return 42
|
||||||
|
def g():
|
||||||
|
return 43
|
||||||
|
|
||||||
|
> assert f() == g()
|
||||||
|
E assert 42 == 43
|
||||||
|
E + where 42 = <function f at 0x2e73c80>()
|
||||||
|
E + and 43 = <function g at 0x2e73cf8>()
|
||||||
|
|
||||||
|
failure_demo.py:28: AssertionError
|
||||||
|
____________________ TestFailing.test_simple_multiline _____________________
|
||||||
|
|
||||||
|
self = <failure_demo.TestFailing object at 0x2e4d7d0>
|
||||||
|
|
||||||
|
def test_simple_multiline(self):
|
||||||
|
otherfunc_multi(
|
||||||
|
42,
|
||||||
|
> 6*9)
|
||||||
|
|
||||||
|
failure_demo.py:33:
|
||||||
|
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||||
|
|
||||||
|
a = 42, b = 54
|
||||||
|
|
||||||
|
def otherfunc_multi(a,b):
|
||||||
|
> assert (a ==
|
||||||
|
b)
|
||||||
|
E assert 42 == 54
|
||||||
|
|
||||||
|
failure_demo.py:11: AssertionError
|
||||||
|
___________________________ TestFailing.test_not ___________________________
|
||||||
|
|
||||||
|
self = <failure_demo.TestFailing object at 0x2e4d390>
|
||||||
|
|
||||||
|
def test_not(self):
|
||||||
|
def f():
|
||||||
|
return 42
|
||||||
|
> assert not f()
|
||||||
|
E assert not 42
|
||||||
|
E + where 42 = <function f at 0x2d36cf8>()
|
||||||
|
|
||||||
|
failure_demo.py:38: AssertionError
|
||||||
|
_________________ TestSpecialisedExplanations.test_eq_text _________________
|
||||||
|
|
||||||
|
self = <failure_demo.TestSpecialisedExplanations object at 0x2e4db10>
|
||||||
|
|
||||||
|
def test_eq_text(self):
|
||||||
|
> assert 'spam' == 'eggs'
|
||||||
|
E assert 'spam' == 'eggs'
|
||||||
|
E - spam
|
||||||
|
E + eggs
|
||||||
|
|
||||||
|
failure_demo.py:42: AssertionError
|
||||||
|
_____________ TestSpecialisedExplanations.test_eq_similar_text _____________
|
||||||
|
|
||||||
|
self = <failure_demo.TestSpecialisedExplanations object at 0x2e6cbd0>
|
||||||
|
|
||||||
|
def test_eq_similar_text(self):
|
||||||
|
> assert 'foo 1 bar' == 'foo 2 bar'
|
||||||
|
E assert 'foo 1 bar' == 'foo 2 bar'
|
||||||
|
E - foo 1 bar
|
||||||
|
E ? ^
|
||||||
|
E + foo 2 bar
|
||||||
|
E ? ^
|
||||||
|
|
||||||
|
failure_demo.py:45: AssertionError
|
||||||
|
____________ TestSpecialisedExplanations.test_eq_multiline_text ____________
|
||||||
|
|
||||||
|
self = <failure_demo.TestSpecialisedExplanations object at 0x2e6cdd0>
|
||||||
|
|
||||||
|
def test_eq_multiline_text(self):
|
||||||
|
> assert 'foo\nspam\nbar' == 'foo\neggs\nbar'
|
||||||
|
E assert 'foo\nspam\nbar' == 'foo\neggs\nbar'
|
||||||
|
E foo
|
||||||
|
E - spam
|
||||||
|
E + eggs
|
||||||
|
E bar
|
||||||
|
|
||||||
|
failure_demo.py:48: AssertionError
|
||||||
|
______________ TestSpecialisedExplanations.test_eq_long_text _______________
|
||||||
|
|
||||||
|
self = <failure_demo.TestSpecialisedExplanations object at 0x2e6cad0>
|
||||||
|
|
||||||
|
def test_eq_long_text(self):
|
||||||
|
a = '1'*100 + 'a' + '2'*100
|
||||||
|
b = '1'*100 + 'b' + '2'*100
|
||||||
|
> assert a == b
|
||||||
|
E assert '111111111111...2222222222222' == '1111111111111...2222222222222'
|
||||||
|
E Skipping 90 identical leading characters in diff
|
||||||
|
E Skipping 91 identical trailing characters in diff
|
||||||
|
E - 1111111111a222222222
|
||||||
|
E ? ^
|
||||||
|
E + 1111111111b222222222
|
||||||
|
E ? ^
|
||||||
|
|
||||||
|
failure_demo.py:53: AssertionError
|
||||||
|
_________ TestSpecialisedExplanations.test_eq_long_text_multiline __________
|
||||||
|
|
||||||
|
self = <failure_demo.TestSpecialisedExplanations object at 0x2e6cb50>
|
||||||
|
|
||||||
|
def test_eq_long_text_multiline(self):
|
||||||
|
a = '1\n'*100 + 'a' + '2\n'*100
|
||||||
|
b = '1\n'*100 + 'b' + '2\n'*100
|
||||||
|
> assert a == b
|
||||||
|
E assert '1\n1\n1\n1\n...n2\n2\n2\n2\n' == '1\n1\n1\n1\n1...n2\n2\n2\n2\n'
|
||||||
|
E Skipping 190 identical leading characters in diff
|
||||||
|
E Skipping 191 identical trailing characters in diff
|
||||||
|
E 1
|
||||||
|
E 1
|
||||||
|
E 1
|
||||||
|
E 1
|
||||||
|
E 1
|
||||||
|
E - a2
|
||||||
|
E + b2
|
||||||
|
E 2
|
||||||
|
E 2
|
||||||
|
E 2
|
||||||
|
E 2
|
||||||
|
|
||||||
|
failure_demo.py:58: AssertionError
|
||||||
|
_________________ TestSpecialisedExplanations.test_eq_list _________________
|
||||||
|
|
||||||
|
self = <failure_demo.TestSpecialisedExplanations object at 0x2dca1d0>
|
||||||
|
|
||||||
|
def test_eq_list(self):
|
||||||
|
> assert [0, 1, 2] == [0, 1, 3]
|
||||||
|
E assert [0, 1, 2] == [0, 1, 3]
|
||||||
|
E At index 2 diff: 2 != 3
|
||||||
|
|
||||||
|
failure_demo.py:61: AssertionError
|
||||||
|
______________ TestSpecialisedExplanations.test_eq_list_long _______________
|
||||||
|
|
||||||
|
self = <failure_demo.TestSpecialisedExplanations object at 0x2dcad10>
|
||||||
|
|
||||||
|
def test_eq_list_long(self):
|
||||||
|
a = [0]*100 + [1] + [3]*100
|
||||||
|
b = [0]*100 + [2] + [3]*100
|
||||||
|
> assert a == b
|
||||||
|
E assert [0, 0, 0, 0, 0, 0, ...] == [0, 0, 0, 0, 0, 0, ...]
|
||||||
|
E At index 100 diff: 1 != 2
|
||||||
|
|
||||||
|
failure_demo.py:66: AssertionError
|
||||||
|
_________________ TestSpecialisedExplanations.test_eq_dict _________________
|
||||||
|
|
||||||
|
self = <failure_demo.TestSpecialisedExplanations object at 0x2dca3d0>
|
||||||
|
|
||||||
|
def test_eq_dict(self):
|
||||||
|
> assert {'a': 0, 'b': 1} == {'a': 0, 'b': 2}
|
||||||
|
E assert {'a': 0, 'b': 1} == {'a': 0, 'b': 2}
|
||||||
|
E - {'a': 0, 'b': 1}
|
||||||
|
E ? ^
|
||||||
|
E + {'a': 0, 'b': 2}
|
||||||
|
E ? ^
|
||||||
|
|
||||||
|
failure_demo.py:69: AssertionError
|
||||||
|
_________________ TestSpecialisedExplanations.test_eq_set __________________
|
||||||
|
|
||||||
|
self = <failure_demo.TestSpecialisedExplanations object at 0x2dca710>
|
||||||
|
|
||||||
|
def test_eq_set(self):
|
||||||
|
> assert set([0, 10, 11, 12]) == set([0, 20, 21])
|
||||||
|
E assert set([0, 10, 11, 12]) == set([0, 20, 21])
|
||||||
|
E Extra items in the left set:
|
||||||
|
E 10
|
||||||
|
E 11
|
||||||
|
E 12
|
||||||
|
E Extra items in the right set:
|
||||||
|
E 20
|
||||||
|
E 21
|
||||||
|
|
||||||
|
failure_demo.py:72: AssertionError
|
||||||
|
_____________ TestSpecialisedExplanations.test_eq_longer_list ______________
|
||||||
|
|
||||||
|
self = <failure_demo.TestSpecialisedExplanations object at 0x2dca490>
|
||||||
|
|
||||||
|
def test_eq_longer_list(self):
|
||||||
|
> assert [1,2] == [1,2,3]
|
||||||
|
E assert [1, 2] == [1, 2, 3]
|
||||||
|
E Right contains more items, first extra item: 3
|
||||||
|
|
||||||
|
failure_demo.py:75: AssertionError
|
||||||
|
_________________ TestSpecialisedExplanations.test_in_list _________________
|
||||||
|
|
||||||
|
self = <failure_demo.TestSpecialisedExplanations object at 0x2dca510>
|
||||||
|
|
||||||
|
def test_in_list(self):
|
||||||
|
> assert 1 in [0, 2, 3, 4, 5]
|
||||||
|
E assert 1 in [0, 2, 3, 4, 5]
|
||||||
|
|
||||||
|
failure_demo.py:78: AssertionError
|
||||||
|
__________ TestSpecialisedExplanations.test_not_in_text_multiline __________
|
||||||
|
|
||||||
|
self = <failure_demo.TestSpecialisedExplanations object at 0x2db86d0>
|
||||||
|
|
||||||
|
def test_not_in_text_multiline(self):
|
||||||
|
text = 'some multiline\ntext\nwhich\nincludes foo\nand a\ntail'
|
||||||
|
> assert 'foo' not in text
|
||||||
|
E assert 'foo' not in 'some multiline\ntext\nw...ncludes foo\nand a\ntail'
|
||||||
|
E 'foo' is contained here:
|
||||||
|
E some multiline
|
||||||
|
E text
|
||||||
|
E which
|
||||||
|
E includes foo
|
||||||
|
E ? +++
|
||||||
|
E and a
|
||||||
|
E tail
|
||||||
|
|
||||||
|
failure_demo.py:82: AssertionError
|
||||||
|
___________ TestSpecialisedExplanations.test_not_in_text_single ____________
|
||||||
|
|
||||||
|
self = <failure_demo.TestSpecialisedExplanations object at 0x2db8450>
|
||||||
|
|
||||||
|
def test_not_in_text_single(self):
|
||||||
|
text = 'single foo line'
|
||||||
|
> assert 'foo' not in text
|
||||||
|
E assert 'foo' not in 'single foo line'
|
||||||
|
E 'foo' is contained here:
|
||||||
|
E single foo line
|
||||||
|
E ? +++
|
||||||
|
|
||||||
|
failure_demo.py:86: AssertionError
|
||||||
|
_________ TestSpecialisedExplanations.test_not_in_text_single_long _________
|
||||||
|
|
||||||
|
self = <failure_demo.TestSpecialisedExplanations object at 0x2db8910>
|
||||||
|
|
||||||
|
def test_not_in_text_single_long(self):
|
||||||
|
text = 'head ' * 50 + 'foo ' + 'tail ' * 20
|
||||||
|
> assert 'foo' not in text
|
||||||
|
E assert 'foo' not in 'head head head head hea...ail tail tail tail tail '
|
||||||
|
E 'foo' is contained here:
|
||||||
|
E head head foo tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail
|
||||||
|
E ? +++
|
||||||
|
|
||||||
|
failure_demo.py:90: AssertionError
|
||||||
|
______ TestSpecialisedExplanations.test_not_in_text_single_long_term _______
|
||||||
|
|
||||||
|
self = <failure_demo.TestSpecialisedExplanations object at 0x2db88d0>
|
||||||
|
|
||||||
|
def test_not_in_text_single_long_term(self):
|
||||||
|
text = 'head ' * 50 + 'f'*70 + 'tail ' * 20
|
||||||
|
> assert 'f'*70 not in text
|
||||||
|
E assert 'fffffffffff...ffffffffffff' not in 'head head he...l tail tail '
|
||||||
|
E 'ffffffffffffffffff...fffffffffffffffffff' is contained here:
|
||||||
|
E head head fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffftail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail tail
|
||||||
|
E ? ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
failure_demo.py:94: AssertionError
|
||||||
|
______________________________ test_attribute ______________________________
|
||||||
|
|
||||||
|
def test_attribute():
|
||||||
|
class Foo(object):
|
||||||
|
b = 1
|
||||||
|
i = Foo()
|
||||||
|
> assert i.b == 2
|
||||||
|
E assert 1 == 2
|
||||||
|
E + where 1 = <failure_demo.Foo object at 0x2db8d90>.b
|
||||||
|
|
||||||
|
failure_demo.py:101: AssertionError
|
||||||
|
_________________________ test_attribute_instance __________________________
|
||||||
|
|
||||||
|
def test_attribute_instance():
|
||||||
|
class Foo(object):
|
||||||
|
b = 1
|
||||||
|
> assert Foo().b == 2
|
||||||
|
E assert 1 == 2
|
||||||
|
E + where 1 = <failure_demo.Foo object at 0x2db8f50>.b
|
||||||
|
E + where <failure_demo.Foo object at 0x2db8f50> = <class 'failure_demo.Foo'>()
|
||||||
|
|
||||||
|
failure_demo.py:107: AssertionError
|
||||||
|
__________________________ test_attribute_failure __________________________
|
||||||
|
|
||||||
|
def test_attribute_failure():
|
||||||
|
class Foo(object):
|
||||||
|
def _get_b(self):
|
||||||
|
raise Exception('Failed to get attrib')
|
||||||
|
b = property(_get_b)
|
||||||
|
i = Foo()
|
||||||
|
> assert i.b == 2
|
||||||
|
|
||||||
|
failure_demo.py:116:
|
||||||
|
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||||
|
|
||||||
|
self = <failure_demo.Foo object at 0x2db8dd0>
|
||||||
|
|
||||||
|
def _get_b(self):
|
||||||
|
> raise Exception('Failed to get attrib')
|
||||||
|
E Exception: Failed to get attrib
|
||||||
|
|
||||||
|
failure_demo.py:113: Exception
|
||||||
|
_________________________ test_attribute_multiple __________________________
|
||||||
|
|
||||||
|
def test_attribute_multiple():
|
||||||
|
class Foo(object):
|
||||||
|
b = 1
|
||||||
|
class Bar(object):
|
||||||
|
b = 2
|
||||||
|
> assert Foo().b == Bar().b
|
||||||
|
E assert 1 == 2
|
||||||
|
E + where 1 = <failure_demo.Foo object at 0x2db8c10>.b
|
||||||
|
E + where <failure_demo.Foo object at 0x2db8c10> = <class 'failure_demo.Foo'>()
|
||||||
|
E + and 2 = <failure_demo.Bar object at 0x2db8b90>.b
|
||||||
|
E + where <failure_demo.Bar object at 0x2db8b90> = <class 'failure_demo.Bar'>()
|
||||||
|
|
||||||
|
failure_demo.py:124: AssertionError
|
||||||
|
__________________________ TestRaises.test_raises __________________________
|
||||||
|
|
||||||
|
self = <failure_demo.TestRaises instance at 0x2d93cf8>
|
||||||
|
|
||||||
|
def test_raises(self):
|
||||||
|
s = 'qwe'
|
||||||
|
> raises(TypeError, "int(s)")
|
||||||
|
|
||||||
|
failure_demo.py:133:
|
||||||
|
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||||
|
|
||||||
|
> int(s)
|
||||||
|
E ValueError: invalid literal for int() with base 10: 'qwe'
|
||||||
|
|
||||||
|
<0-codegen /home/hpk/p/pytest/_pytest/python.py:978>:1: ValueError
|
||||||
|
______________________ TestRaises.test_raises_doesnt _______________________
|
||||||
|
|
||||||
|
self = <failure_demo.TestRaises instance at 0x2e69c20>
|
||||||
|
|
||||||
|
def test_raises_doesnt(self):
|
||||||
|
> raises(IOError, "int('3')")
|
||||||
|
E Failed: DID NOT RAISE
|
||||||
|
|
||||||
|
failure_demo.py:136: Failed
|
||||||
|
__________________________ TestRaises.test_raise ___________________________
|
||||||
|
|
||||||
|
self = <failure_demo.TestRaises instance at 0x2d96098>
|
||||||
|
|
||||||
|
def test_raise(self):
|
||||||
|
> raise ValueError("demo error")
|
||||||
|
E ValueError: demo error
|
||||||
|
|
||||||
|
failure_demo.py:139: ValueError
|
||||||
|
________________________ TestRaises.test_tupleerror ________________________
|
||||||
|
|
||||||
|
self = <failure_demo.TestRaises instance at 0x2d96e60>
|
||||||
|
|
||||||
|
def test_tupleerror(self):
|
||||||
|
> a,b = [1]
|
||||||
|
E ValueError: need more than 1 value to unpack
|
||||||
|
|
||||||
|
failure_demo.py:142: ValueError
|
||||||
|
______ TestRaises.test_reinterpret_fails_with_print_for_the_fun_of_it ______
|
||||||
|
|
||||||
|
self = <failure_demo.TestRaises instance at 0x2d99b90>
|
||||||
|
|
||||||
|
def test_reinterpret_fails_with_print_for_the_fun_of_it(self):
|
||||||
|
l = [1,2,3]
|
||||||
|
print ("l is %r" % l)
|
||||||
|
> a,b = l.pop()
|
||||||
|
E TypeError: 'int' object is not iterable
|
||||||
|
|
||||||
|
failure_demo.py:147: TypeError
|
||||||
|
----------------------------- Captured stdout ------------------------------
|
||||||
|
l is [1, 2, 3]
|
||||||
|
________________________ TestRaises.test_some_error ________________________
|
||||||
|
|
||||||
|
self = <failure_demo.TestRaises instance at 0x2d9b998>
|
||||||
|
|
||||||
|
def test_some_error(self):
|
||||||
|
> if namenotexi:
|
||||||
|
E NameError: global name 'namenotexi' is not defined
|
||||||
|
|
||||||
|
failure_demo.py:150: NameError
|
||||||
|
____________________ test_dynamic_compile_shows_nicely _____________________
|
||||||
|
|
||||||
|
def test_dynamic_compile_shows_nicely():
|
||||||
|
src = 'def foo():\n assert 1 == 0\n'
|
||||||
|
name = 'abc-123'
|
||||||
|
module = py.std.imp.new_module(name)
|
||||||
|
code = py.code.compile(src, name, 'exec')
|
||||||
|
py.builtin.exec_(code, module.__dict__)
|
||||||
|
py.std.sys.modules[name] = module
|
||||||
|
> module.foo()
|
||||||
|
|
||||||
|
failure_demo.py:165:
|
||||||
|
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||||
|
|
||||||
|
def foo():
|
||||||
|
> assert 1 == 0
|
||||||
|
E assert 1 == 0
|
||||||
|
|
||||||
|
<2-codegen 'abc-123' /home/hpk/p/pytest/doc/example/assertion/failure_demo.py:162>:2: AssertionError
|
||||||
|
____________________ TestMoreErrors.test_complex_error _____________________
|
||||||
|
|
||||||
|
self = <failure_demo.TestMoreErrors instance at 0x2e5b6c8>
|
||||||
|
|
||||||
|
def test_complex_error(self):
|
||||||
|
def f():
|
||||||
|
return 44
|
||||||
|
def g():
|
||||||
|
return 43
|
||||||
|
> somefunc(f(), g())
|
||||||
|
|
||||||
|
failure_demo.py:175:
|
||||||
|
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||||
|
|
||||||
|
x = 44, y = 43
|
||||||
|
|
||||||
|
def somefunc(x,y):
|
||||||
|
> otherfunc(x,y)
|
||||||
|
|
||||||
|
failure_demo.py:8:
|
||||||
|
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
|
||||||
|
|
||||||
|
a = 44, b = 43
|
||||||
|
|
||||||
|
def otherfunc(a,b):
|
||||||
|
> assert a==b
|
||||||
|
E assert 44 == 43
|
||||||
|
|
||||||
|
failure_demo.py:5: AssertionError
|
||||||
|
___________________ TestMoreErrors.test_z1_unpack_error ____________________
|
||||||
|
|
||||||
|
self = <failure_demo.TestMoreErrors instance at 0x2d9a998>
|
||||||
|
|
||||||
|
def test_z1_unpack_error(self):
|
||||||
|
l = []
|
||||||
|
> a,b = l
|
||||||
|
E ValueError: need more than 0 values to unpack
|
||||||
|
|
||||||
|
failure_demo.py:179: ValueError
|
||||||
|
____________________ TestMoreErrors.test_z2_type_error _____________________
|
||||||
|
|
||||||
|
self = <failure_demo.TestMoreErrors instance at 0x2dc87a0>
|
||||||
|
|
||||||
|
def test_z2_type_error(self):
|
||||||
|
l = 3
|
||||||
|
> a,b = l
|
||||||
|
E TypeError: 'int' object is not iterable
|
||||||
|
|
||||||
|
failure_demo.py:183: TypeError
|
||||||
|
______________________ TestMoreErrors.test_startswith ______________________
|
||||||
|
|
||||||
|
self = <failure_demo.TestMoreErrors instance at 0x2dc55a8>
|
||||||
|
|
||||||
|
def test_startswith(self):
|
||||||
|
s = "123"
|
||||||
|
g = "456"
|
||||||
|
> assert s.startswith(g)
|
||||||
|
E assert <built-in method startswith of str object at 0x2daf3f0>('456')
|
||||||
|
E + where <built-in method startswith of str object at 0x2daf3f0> = '123'.startswith
|
||||||
|
|
||||||
|
failure_demo.py:188: AssertionError
|
||||||
|
__________________ TestMoreErrors.test_startswith_nested ___________________
|
||||||
|
|
||||||
|
self = <failure_demo.TestMoreErrors instance at 0x2dc8518>
|
||||||
|
|
||||||
|
def test_startswith_nested(self):
|
||||||
|
def f():
|
||||||
|
return "123"
|
||||||
|
def g():
|
||||||
|
return "456"
|
||||||
|
> assert f().startswith(g())
|
||||||
|
E assert <built-in method startswith of str object at 0x2daf3f0>('456')
|
||||||
|
E + where <built-in method startswith of str object at 0x2daf3f0> = '123'.startswith
|
||||||
|
E + where '123' = <function f at 0x2e50aa0>()
|
||||||
|
E + and '456' = <function g at 0x2e52cf8>()
|
||||||
|
|
||||||
|
failure_demo.py:195: AssertionError
|
||||||
|
_____________________ TestMoreErrors.test_global_func ______________________
|
||||||
|
|
||||||
|
self = <failure_demo.TestMoreErrors instance at 0x2e69098>
|
||||||
|
|
||||||
|
def test_global_func(self):
|
||||||
|
> assert isinstance(globf(42), float)
|
||||||
|
E assert isinstance(43, float)
|
||||||
|
E + where 43 = globf(42)
|
||||||
|
|
||||||
|
failure_demo.py:198: AssertionError
|
||||||
|
_______________________ TestMoreErrors.test_instance _______________________
|
||||||
|
|
||||||
|
self = <failure_demo.TestMoreErrors instance at 0x2d96fc8>
|
||||||
|
|
||||||
|
def test_instance(self):
|
||||||
|
self.x = 6*7
|
||||||
|
> assert self.x != 42
|
||||||
|
E assert 42 != 42
|
||||||
|
E + where 42 = <failure_demo.TestMoreErrors instance at 0x2d96fc8>.x
|
||||||
|
|
||||||
|
failure_demo.py:202: AssertionError
|
||||||
|
_______________________ TestMoreErrors.test_compare ________________________
|
||||||
|
|
||||||
|
self = <failure_demo.TestMoreErrors instance at 0x2d9e170>
|
||||||
|
|
||||||
|
def test_compare(self):
|
||||||
|
> assert globf(10) < 5
|
||||||
|
E assert 11 < 5
|
||||||
|
E + where 11 = globf(10)
|
||||||
|
|
||||||
|
failure_demo.py:205: AssertionError
|
||||||
|
_____________________ TestMoreErrors.test_try_finally ______________________
|
||||||
|
|
||||||
|
self = <failure_demo.TestMoreErrors instance at 0x2d9ef80>
|
||||||
|
|
||||||
|
def test_try_finally(self):
|
||||||
|
x = 1
|
||||||
|
try:
|
||||||
|
> assert x == 0
|
||||||
|
E assert 1 == 0
|
||||||
|
|
||||||
|
failure_demo.py:210: AssertionError
|
||||||
|
======================== 39 failed in 0.17 seconds =========================
|
|
@ -0,0 +1,439 @@
|
||||||
|
|
||||||
|
.. highlightlang:: python
|
||||||
|
|
||||||
|
基本的なパターンと例
|
||||||
|
====================
|
||||||
|
|
||||||
|
..
|
||||||
|
Basic patterns and examples
|
||||||
|
==========================================================
|
||||||
|
|
||||||
|
..
|
||||||
|
Pass different values to a test function, depending on command line options
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
コマンドラインオプションでテスト関数に違う値を渡す
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
.. regendoc:wipe
|
||||||
|
|
||||||
|
..
|
||||||
|
Suppose we want to write a test that depends on a command line option.
|
||||||
|
Here is a basic pattern how to achieve this::
|
||||||
|
|
||||||
|
コマンドラインオプションで制御するテストを書きたいと仮定します。これを実現する基本的な方法は次の通りです::
|
||||||
|
|
||||||
|
# test_sample.py の内容
|
||||||
|
def test_answer(cmdopt):
|
||||||
|
if cmdopt == "type1":
|
||||||
|
print ("first")
|
||||||
|
elif cmdopt == "type2":
|
||||||
|
print ("second")
|
||||||
|
assert 0 # 何が表示されるかを見るため
|
||||||
|
|
||||||
|
|
||||||
|
..
|
||||||
|
For this to work we need to add a command line option and
|
||||||
|
provide the ``cmdopt`` through a :ref:`function argument <funcarg>` factory::
|
||||||
|
|
||||||
|
このためにはコマンドラインオプションを追加する必要があります。 :ref:`関数の引数 <funcarg>` ファクトリーを使って ``cmdopt`` を提供します::
|
||||||
|
|
||||||
|
# conftest.py の内容
|
||||||
|
def pytest_addoption(parser):
|
||||||
|
parser.addoption("--cmdopt", action="store", default="type1",
|
||||||
|
help="my option: type1 or type2")
|
||||||
|
|
||||||
|
def pytest_funcarg__cmdopt(request):
|
||||||
|
return request.config.option.cmdopt
|
||||||
|
|
||||||
|
..
|
||||||
|
Let's run this without supplying our new command line option::
|
||||||
|
|
||||||
|
先ほど作成したコマンドラインオプションを指定せずに実行してみましょう::
|
||||||
|
|
||||||
|
$ py.test -q test_sample.py
|
||||||
|
collecting ... collected 1 items
|
||||||
|
F
|
||||||
|
================================= FAILURES =================================
|
||||||
|
_______________________________ test_answer ________________________________
|
||||||
|
|
||||||
|
cmdopt = 'type1'
|
||||||
|
|
||||||
|
def test_answer(cmdopt):
|
||||||
|
if cmdopt == "type1":
|
||||||
|
print ("first")
|
||||||
|
elif cmdopt == "type2":
|
||||||
|
print ("second")
|
||||||
|
> assert 0 # 何が表示されるかを見るため
|
||||||
|
E assert 0
|
||||||
|
|
||||||
|
test_sample.py:6: AssertionError
|
||||||
|
----------------------------- Captured stdout ------------------------------
|
||||||
|
first
|
||||||
|
1 failed in 0.01 seconds
|
||||||
|
|
||||||
|
..
|
||||||
|
And now with supplying a command line option::
|
||||||
|
|
||||||
|
次はコマンドラインオプションを指定して実行します::
|
||||||
|
|
||||||
|
$ py.test -q --cmdopt=type2
|
||||||
|
collecting ... collected 1 items
|
||||||
|
F
|
||||||
|
================================= FAILURES =================================
|
||||||
|
_______________________________ test_answer ________________________________
|
||||||
|
|
||||||
|
cmdopt = 'type2'
|
||||||
|
|
||||||
|
def test_answer(cmdopt):
|
||||||
|
if cmdopt == "type1":
|
||||||
|
print ("first")
|
||||||
|
elif cmdopt == "type2":
|
||||||
|
print ("second")
|
||||||
|
> assert 0 # 何が表示されるかを見るため
|
||||||
|
E assert 0
|
||||||
|
|
||||||
|
test_sample.py:6: AssertionError
|
||||||
|
----------------------------- Captured stdout ------------------------------
|
||||||
|
second
|
||||||
|
1 failed in 0.01 seconds
|
||||||
|
|
||||||
|
..
|
||||||
|
Ok, this completes the basic pattern. However, one often rather
|
||||||
|
wants to process command line options outside of the test and
|
||||||
|
rather pass in different or more complex objects. See the
|
||||||
|
next example or refer to :ref:`mysetup` for more information
|
||||||
|
on real-life examples.
|
||||||
|
|
||||||
|
はい。基本的な使い方が分かりました。これ以外にも、テストの外部でコマンドラインオプションを処理して、別オブジェクトや複雑なオブジェクトを渡したいこともよくあります。次の例、もしくは現実の世界での例は :ref:`mysetup` を参照してください。
|
||||||
|
|
||||||
|
..
|
||||||
|
Dynamically adding command line options
|
||||||
|
--------------------------------------------------------------
|
||||||
|
|
||||||
|
コマンドラインオプションを動的に追加
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
.. regendoc:wipe
|
||||||
|
|
||||||
|
..
|
||||||
|
Through :confval:`addopts` you can statically add command line
|
||||||
|
options for your project. You can also dynamically modify
|
||||||
|
the command line arguments before they get processed::
|
||||||
|
|
||||||
|
:confval:`addopts` を使って、プロジェクトにコマンドラインオプションを静的に追加できます。静的に追加したコマンドラインオプションが処理される前に、そのコマンドラインオプションを動的に変更することもできます::
|
||||||
|
|
||||||
|
# conftest.py の内容
|
||||||
|
import sys
|
||||||
|
def pytest_cmdline_preparse(args):
|
||||||
|
if 'xdist' in sys.modules: # pytest-xdist プラグイン
|
||||||
|
import multiprocessing
|
||||||
|
num = max(multiprocessing.cpu_count() / 2, 1)
|
||||||
|
args[:] = ["-n", str(num)] + args
|
||||||
|
|
||||||
|
..
|
||||||
|
If you have the :ref:`xdist plugin <xdist>` installed
|
||||||
|
you will now always perform test runs using a number
|
||||||
|
of subprocesses close to your CPU. Running in an empty
|
||||||
|
directory with the above conftest.py::
|
||||||
|
|
||||||
|
:ref:`xdist プラグイン <xdist>` をインストール済みなら、毎回 CPU 数に近いサブプロセスを使ってテストを実行できます。空のディレクトリで上記の conftest.py を実行します::
|
||||||
|
|
||||||
|
$ py.test
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
gw0 I / gw1 I / gw2 I / gw3 I
|
||||||
|
gw0 [0] / gw1 [0] / gw2 [0] / gw3 [0]
|
||||||
|
|
||||||
|
scheduling tests via LoadScheduling
|
||||||
|
|
||||||
|
============================= in 0.52 seconds =============================
|
||||||
|
|
||||||
|
.. _`excontrolskip`:
|
||||||
|
|
||||||
|
コマンドラインオプションでテストのスキップを制御
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Control skipping of tests according to command line option
|
||||||
|
--------------------------------------------------------------
|
||||||
|
|
||||||
|
.. regendoc:wipe
|
||||||
|
|
||||||
|
..
|
||||||
|
Here is a ``conftest.py`` file adding a ``--runslow`` command
|
||||||
|
line option to control skipping of ``slow`` marked tests::
|
||||||
|
|
||||||
|
``slow`` とマークされたテストのスキップを制御するコマンドラインオプション ``--runslow`` を追加する ``conftest.py`` があります::
|
||||||
|
|
||||||
|
# conftest.py の内容
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
def pytest_addoption(parser):
|
||||||
|
parser.addoption("--runslow", action="store_true",
|
||||||
|
help="run slow tests")
|
||||||
|
|
||||||
|
def pytest_runtest_setup(item):
|
||||||
|
if 'slow' in item.keywords and not item.config.getvalue("runslow"):
|
||||||
|
pytest.skip("need --runslow option to run")
|
||||||
|
|
||||||
|
..
|
||||||
|
We can now write a test module like this::
|
||||||
|
|
||||||
|
テストモジュールは次のように書きます::
|
||||||
|
|
||||||
|
# test_module.py の内容
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
slow = pytest.mark.slow
|
||||||
|
|
||||||
|
def test_func_fast():
|
||||||
|
pass
|
||||||
|
|
||||||
|
@slow
|
||||||
|
def test_func_slow():
|
||||||
|
pass
|
||||||
|
|
||||||
|
..
|
||||||
|
and when running it will see a skipped "slow" test::
|
||||||
|
|
||||||
|
実行すると、"slow" テストがスキップされます::
|
||||||
|
|
||||||
|
$ py.test -rs # "-rs" は 's' の詳細をレポートします
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 2 items
|
||||||
|
|
||||||
|
test_module.py .s
|
||||||
|
========================= short test summary info ==========================
|
||||||
|
SKIP [1] /tmp/doc-exec-225/conftest.py:9: need --runslow option to run
|
||||||
|
|
||||||
|
=================== 1 passed, 1 skipped in 0.01 seconds ====================
|
||||||
|
|
||||||
|
..
|
||||||
|
Or run it including the ``slow`` marked test::
|
||||||
|
|
||||||
|
もしくは ``slow`` とマークされたテストを実行します::
|
||||||
|
|
||||||
|
$ py.test --runslow
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 2 items
|
||||||
|
|
||||||
|
test_module.py ..
|
||||||
|
|
||||||
|
========================= 2 passed in 0.01 seconds =========================
|
||||||
|
|
||||||
|
..
|
||||||
|
Writing well integrated assertion helpers
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
統合的なアサーションヘルパーの作成
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
.. regendoc:wipe
|
||||||
|
|
||||||
|
..
|
||||||
|
If you have a test helper function called from a test you can
|
||||||
|
use the ``pytest.fail`` marker to fail a test with a certain message.
|
||||||
|
The test support function will not show up in the traceback if you
|
||||||
|
set the ``__tracebackhide__`` option somewhere in the helper function.
|
||||||
|
Example::
|
||||||
|
|
||||||
|
テストから呼ばれるテストヘルパー関数があるなら、特定メッセージ付きでテストを失敗させる ``pytest.fail`` マーカーを使えます。 ``__tracebackhide__`` オプションをヘルパー関数内にセットすると、そのテストヘルパー関数はトレースバックを表示しなくなります。サンプルを紹介します::
|
||||||
|
|
||||||
|
# test_checkconfig.py の内容
|
||||||
|
import pytest
|
||||||
|
def checkconfig(x):
|
||||||
|
__tracebackhide__ = True
|
||||||
|
if not hasattr(x, "config"):
|
||||||
|
pytest.fail("not configured: %s" %(x,))
|
||||||
|
|
||||||
|
def test_something():
|
||||||
|
checkconfig(42)
|
||||||
|
|
||||||
|
..
|
||||||
|
The ``__tracebackhide__`` setting influences py.test showing
|
||||||
|
of tracebacks: the ``checkconfig`` function will not be shown
|
||||||
|
unless the ``--fulltrace`` command line option is specified.
|
||||||
|
Let's run our little function::
|
||||||
|
|
||||||
|
``__tracebackhide__`` 設定は、py.test のトレースバック表示に影響を与えます。 ``checkconfig`` 関数は、 ``--fulltrace`` コマンドラインオプションを指定しない限り、トレースバックを表示しません。この小さな関数を実行してみましょう::
|
||||||
|
|
||||||
|
$ py.test -q test_checkconfig.py
|
||||||
|
collecting ... collected 1 items
|
||||||
|
F
|
||||||
|
================================= FAILURES =================================
|
||||||
|
______________________________ test_something ______________________________
|
||||||
|
|
||||||
|
def test_something():
|
||||||
|
> checkconfig(42)
|
||||||
|
E Failed: not configured: 42
|
||||||
|
|
||||||
|
test_checkconfig.py:8: Failed
|
||||||
|
1 failed in 0.01 seconds
|
||||||
|
|
||||||
|
..
|
||||||
|
Detect if running from within a py.test run
|
||||||
|
--------------------------------------------------------------
|
||||||
|
|
||||||
|
py.test で実行していることを検出
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
.. regendoc:wipe
|
||||||
|
|
||||||
|
..
|
||||||
|
Usually it is a bad idea to make application code
|
||||||
|
behave differently if called from a test. But if you
|
||||||
|
absolutely must find out if your application code is
|
||||||
|
running from a test you can do something like this::
|
||||||
|
|
||||||
|
通常は、テストから呼ばれる場合にアプリケーションコードの振る舞いを分けるのは悪い考えです。しかし、アプリケーションコードがテストから実行されている場合に、確実に解明しなければならないことがあるなら、次のようなことができます::
|
||||||
|
|
||||||
|
# conftest.py の内容
|
||||||
|
|
||||||
|
def pytest_configure(config):
|
||||||
|
import sys
|
||||||
|
sys._called_from_test = True
|
||||||
|
|
||||||
|
def pytest_unconfigure(config):
|
||||||
|
del sys._called_from_test
|
||||||
|
|
||||||
|
..
|
||||||
|
and then check for the ``sys._called_from_test`` flag::
|
||||||
|
|
||||||
|
アプリケーション内で ``sys._called_from_test`` というフラグをチェックします::
|
||||||
|
|
||||||
|
if hasattr(sys, '_called_from_test'):
|
||||||
|
# テスト内から実行時に呼ばれる
|
||||||
|
else:
|
||||||
|
# "普通" のときに呼ばれる
|
||||||
|
|
||||||
|
..
|
||||||
|
accordingly in your application. It's also a good idea
|
||||||
|
to use your own application module rather than ``sys``
|
||||||
|
for handling flag.
|
||||||
|
|
||||||
|
フラグを処理するために ``sys`` よりも独自のアプリケーションモジュールを使うのも良い考えです。
|
||||||
|
|
||||||
|
..
|
||||||
|
Adding info to test report header
|
||||||
|
--------------------------------------------------------------
|
||||||
|
|
||||||
|
テストレポートヘッダーに情報を追加
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
.. regendoc:wipe
|
||||||
|
|
||||||
|
..
|
||||||
|
It's easy to present extra information in a py.test run::
|
||||||
|
|
||||||
|
py.test の実行時に追加の情報を表示するのは簡単です::
|
||||||
|
|
||||||
|
# conftest.py の内容
|
||||||
|
|
||||||
|
def pytest_report_header(config):
|
||||||
|
return "project deps: mylib-1.1"
|
||||||
|
|
||||||
|
..
|
||||||
|
which will add the string to the test header accordingly::
|
||||||
|
|
||||||
|
この関数はテストヘッダーに文字列を追加します::
|
||||||
|
|
||||||
|
$ py.test
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
project deps: mylib-1.1
|
||||||
|
collecting ... collected 0 items
|
||||||
|
|
||||||
|
============================= in 0.00 seconds =============================
|
||||||
|
|
||||||
|
.. regendoc:wipe
|
||||||
|
|
||||||
|
..
|
||||||
|
You can also return a list of strings which will be considered as several
|
||||||
|
lines of information. You can of course also make the amount of reporting
|
||||||
|
information on e.g. the value of ``config.option.verbose`` so that
|
||||||
|
you present more information appropriately::
|
||||||
|
|
||||||
|
複数行に渡る情報を扱うなら文字列のリストも返せます。当然レポートの情報量も制御できます。例えば、必要なときに情報を表示するために ``config.option.verbose`` の値で切り分けます::
|
||||||
|
|
||||||
|
# conftest.py の内容
|
||||||
|
|
||||||
|
def pytest_report_header(config):
|
||||||
|
if config.option.verbose > 0:
|
||||||
|
return ["info1: did you know that ...", "did you?"]
|
||||||
|
|
||||||
|
..
|
||||||
|
which will add info only when run with "--v"::
|
||||||
|
|
||||||
|
"--v" を指定して実行したときのみ追加の情報が表示されます::
|
||||||
|
|
||||||
|
$ py.test -v
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4 -- /home/hpk/venv/0/bin/python
|
||||||
|
info1: did you know that ...
|
||||||
|
did you?
|
||||||
|
collecting ... collected 0 items
|
||||||
|
|
||||||
|
============================= in 0.00 seconds =============================
|
||||||
|
|
||||||
|
..
|
||||||
|
and nothing when run plainly::
|
||||||
|
|
||||||
|
何も指定せずに実行すると何も表示しません::
|
||||||
|
|
||||||
|
$ py.test
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 0 items
|
||||||
|
|
||||||
|
============================= in 0.00 seconds =============================
|
||||||
|
|
||||||
|
..
|
||||||
|
profiling test duration
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
テスト実行のプロファイリング
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
.. regendoc:wipe
|
||||||
|
|
||||||
|
.. versionadded: 2.2
|
||||||
|
|
||||||
|
..
|
||||||
|
If you have a slow running large test suite you might want to find
|
||||||
|
out which tests are the slowest. Let's make an artifical test suite::
|
||||||
|
|
||||||
|
巨大なテストスイートの実行に時間がかかる場合、どのテストが最も遅いかを調べたいときがあります。擬似テストスイートで試してみましょう::
|
||||||
|
|
||||||
|
# test_some_are_slow.py の内容
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
def test_funcfast():
|
||||||
|
pass
|
||||||
|
|
||||||
|
def test_funcslow1():
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
def test_funcslow2():
|
||||||
|
time.sleep(0.2)
|
||||||
|
|
||||||
|
..
|
||||||
|
Now we can profile which test functions execute the slowest::
|
||||||
|
|
||||||
|
次にようにして、どのテスト関数が最も遅いかをプロファイルできます::
|
||||||
|
|
||||||
|
$ py.test --durations=3
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 3 items
|
||||||
|
|
||||||
|
test_some_are_slow.py ...
|
||||||
|
|
||||||
|
========================= slowest 3 test durations =========================
|
||||||
|
0.20s call test_some_are_slow.py::test_funcslow2
|
||||||
|
0.10s call test_some_are_slow.py::test_funcslow1
|
||||||
|
0.00s setup test_some_are_slow.py::test_funcslow2
|
||||||
|
========================= 3 passed in 0.31 seconds =========================
|
|
@ -0,0 +1,25 @@
|
||||||
|
import pytest
|
||||||
|
xfail = pytest.mark.xfail
|
||||||
|
|
||||||
|
@xfail
|
||||||
|
def test_hello():
|
||||||
|
assert 0
|
||||||
|
|
||||||
|
@xfail(run=False)
|
||||||
|
def test_hello2():
|
||||||
|
assert 0
|
||||||
|
|
||||||
|
@xfail("hasattr(os, 'sep')")
|
||||||
|
def test_hello3():
|
||||||
|
assert 0
|
||||||
|
|
||||||
|
@xfail(reason="bug 110")
|
||||||
|
def test_hello4():
|
||||||
|
assert 0
|
||||||
|
|
||||||
|
@xfail('pytest.__version__[0] != "17"')
|
||||||
|
def test_hello5():
|
||||||
|
assert 0
|
||||||
|
|
||||||
|
def test_hello6():
|
||||||
|
pytest.xfail("reason")
|
|
@ -0,0 +1,230 @@
|
||||||
|
課題と質問
|
||||||
|
==========
|
||||||
|
|
||||||
|
..
|
||||||
|
Some Issues and Questions
|
||||||
|
==================================
|
||||||
|
|
||||||
|
..
|
||||||
|
If you don't find an answer here, checkout the :ref:`contact channels`
|
||||||
|
to get help.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
ここで答えが見つからない場合は :ref:`contact channels` から助けを求めてください。
|
||||||
|
|
||||||
|
..
|
||||||
|
On naming, nosetests, licensing and magic
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
名前付け、nosetests、ライセンスと魔法
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Why a ``py.test`` instead of a ``pytest`` command?
|
||||||
|
++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
どうしてコマンド名は ``pytest`` ではなく ``py.test`` なの?
|
||||||
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
..
|
||||||
|
Some of the reasons are historic, others are practical. ``py.test``
|
||||||
|
used to be part of the ``py`` package which provided several developer
|
||||||
|
utilities, all starting with ``py.<TAB>``, thus providing nice
|
||||||
|
TAB-completion. If
|
||||||
|
you install ``pip install pycmd`` you get these tools from a separate
|
||||||
|
package. These days the command line tool could be called ``pytest``
|
||||||
|
but since many people have gotten used to the old name and there
|
||||||
|
is another tool named "pytest" we just decided to stick with
|
||||||
|
``py.test``.
|
||||||
|
|
||||||
|
理由の一部は歴史的なもので、それ以外は実用上のものです。 ``py.test`` は、複数の開発者向けユーティリティを提供する ``py`` パッケージの一部として使われていました。それは全て ``py.<TAB>`` で始まり、このように <TAB> を補完する優れた機能を提供しています。 ``pip install pycmd`` でインストールしたら、別々のパッケージからそういったツールを確認できます。最近になって、コマンドラインツールは ``pytest`` と呼んでいますが、昔からの多くの人たちが古い名前になじんでいて "pytest" という名前は別ツールに思えます。そのため、我々は ``py.test`` という名前を使い続けることに決めました。
|
||||||
|
|
||||||
|
..
|
||||||
|
How does py.test relate to nose and unittest?
|
||||||
|
+++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
py.test は nose や unittest とどんな関係があるの?
|
||||||
|
++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
..
|
||||||
|
py.test and nose_ share basic philosophy when it comes
|
||||||
|
to running and writing Python tests. In fact, you can run many tests
|
||||||
|
written for nose with py.test. nose_ was originally created
|
||||||
|
as a clone of ``py.test`` when py.test was in the ``0.8`` release
|
||||||
|
cycle. Note that starting with pytest-2.0 support for running unittest
|
||||||
|
test suites is majorly improved and you should be able to run
|
||||||
|
many Django and Twisted test suites without modification.
|
||||||
|
|
||||||
|
py.test と nose_ は、Python テストを書いて実行するのに同じ基本理念をもっています。 nose_ は、もともと ``py.test`` が ``0.8`` リリースのときに py.test のクローンとして作成されました。pytest 2.0 は unittest のテストスイートを実行できるようになったのが主な改善点であることに注目してください。そして、多くの Django や Twisted のテストスイートを変更せずに実行できます。
|
||||||
|
|
||||||
|
.. _features: test/features.html
|
||||||
|
|
||||||
|
py.test の "魔法" は一体何なの?
|
||||||
|
++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
..
|
||||||
|
What's this "magic" with py.test?
|
||||||
|
++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
..
|
||||||
|
Around 2007 (version ``0.8``) some people claimed that py.test
|
||||||
|
was using too much "magic". Partly this has been fixed by removing
|
||||||
|
unused, deprecated or complicated code. It is today probably one
|
||||||
|
of the smallest, most universally runnable and most
|
||||||
|
customizable testing frameworks for Python. However,
|
||||||
|
``py.test`` still uses many metaprogramming techniques and
|
||||||
|
reading its source is thus likely not something for Python beginners.
|
||||||
|
|
||||||
|
2007年頃 (バージョン ``0.8``)、py.test はあまりにも多くの "魔法" を使っていると主張する人たちがいました。未使用なコード、非推奨、複雑なコードを削除することで部分的には解消されました。今日では、py.test は確かに Python 向けの最も小さく普遍的でカスタマイズ可能なテストフレームワークの1つです。但し ``py.test`` は、まだ多くのメタプログラミングテクニックを使っていて、Python 初心者がそのソースを読めるものではありません。
|
||||||
|
|
||||||
|
..
|
||||||
|
A second "magic" issue is arguably the assert statement debugging feature. When
|
||||||
|
loading test modules py.test rewrites the source code of assert statements. When
|
||||||
|
a rewritten assert statement fails, its error message has more information than
|
||||||
|
the original. py.test also has a second assert debugging technique. When an
|
||||||
|
``assert`` statement that was missed by the rewriter fails, py.test
|
||||||
|
re-interprets the expression to show intermediate values if a test fails. This
|
||||||
|
second technique suffers from a caveat that the rewriting does not: If your
|
||||||
|
expression has side effects (better to avoid them anyway!) the intermediate
|
||||||
|
values may not be the same, confusing the reinterpreter and obfuscating the
|
||||||
|
initial error (this is also explained at the command line if it happens).
|
||||||
|
You can turn off all assertion debugging with ``py.test --assertmode=off``.
|
||||||
|
|
||||||
|
2番目の "魔法" の課題は、間違いなく assert 文のデバッグ機能です。テストモジュールが読み込まれると、py.test は assert 文のソースコードを書き換えます。書き換えられた assert 文が失敗したとき、そのエラーメッセージは、オリジナルの assert 文より分かりやすいものです。py.test にも別のデバッグ手法があります。書き換えが失敗することにより ``assert`` 文が失敗したとき、py.test はテストが失敗したときに中間値を表示するためにその式を再解釈します。この別のデバッグ手法は書き換えが行われなかったという警告で悩まされます。その式が副作用 (とにかく触らないのが良い!) をもつなら、中間値は同じにならない可能性があります。それは再解釈するインタープリターを混乱させ、初期のエラーを分かり難くします (これも発生したらコマンドラインで表示される) 。 ``py.test --assertmode=off`` により、全てのアサーションデバッグを無効にできます。
|
||||||
|
|
||||||
|
.. _`py namespaces`: index.html
|
||||||
|
.. _`py/__init__.py`: http://bitbucket.org/hpk42/py-trunk/src/trunk/py/__init__.py
|
||||||
|
|
||||||
|
関数の引数、パラメーターテストとセットアップ
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Function arguments, parametrized tests and setup
|
||||||
|
-------------------------------------------------------
|
||||||
|
|
||||||
|
.. _funcargs: test/funcargs.html
|
||||||
|
|
||||||
|
funcarg- 対 xUnit セットアップスタイルの疑問
|
||||||
|
++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
..
|
||||||
|
Is using funcarg- versus xUnit setup a style question?
|
||||||
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
..
|
||||||
|
For simple applications and for people experienced with nose_ or
|
||||||
|
unittest-style test setup using `xUnit style setup`_ probably
|
||||||
|
feels natural. For larger test suites, parametrized testing
|
||||||
|
or setup of complex test resources using funcargs_ may feel more natural.
|
||||||
|
Moreover, funcargs are ideal for writing advanced test support
|
||||||
|
code (like e.g. the monkeypatch_, the tmpdir_ or capture_ funcargs)
|
||||||
|
because the support code can register setup/teardown functions
|
||||||
|
in a managed class/module/function scope.
|
||||||
|
|
||||||
|
シンプルなアプリケーション向けや、nose_ か unittest スタイルの経験がある人たちにとっては、おそらく :ref:`xunitsetup` を使う方が自然に感じるはずです。しかし、巨大なテストスイート向けでは、パラメーターテストや funcargs_ を使った複雑なテストリソースのセットアップの方がもっと自然に感じるかもしれません。さらに言うと、funcargs は高度なテストサポートコード (例えば monkeypatch_, tmpdir_, capture_, funcargs) を書くのに最適です。というのは、そのサポートコードは class/module/function スコープを管理する setup/teardown 関数を登録できるからです。
|
||||||
|
|
||||||
|
.. _monkeypatch: test/plugin/monkeypatch.html
|
||||||
|
.. _tmpdir: test/plugin/tmpdir.html
|
||||||
|
.. _capture: test/plugin/capture.html
|
||||||
|
|
||||||
|
.. _`why pytest_pyfuncarg__ methods?`:
|
||||||
|
|
||||||
|
どうして funcarg ファクトリーの名前は ``pytest_funcarg__*`` なの?
|
||||||
|
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
..
|
||||||
|
Why the ``pytest_funcarg__*`` name for funcarg factories?
|
||||||
|
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
..
|
||||||
|
We like `Convention over Configuration`_ and didn't see much point
|
||||||
|
in allowing a more flexible or abstract mechanism. Moreover,
|
||||||
|
it is nice to be able to search for ``pytest_funcarg__MYARG`` in
|
||||||
|
source code and safely find all factory functions for
|
||||||
|
the ``MYARG`` function argument.
|
||||||
|
|
||||||
|
我々は `設定より規約`_ を好み、より柔軟に抽象的な仕組みを許容するのに意味があるとは思いませんでした。さらに、ソースコード内で ``pytest_funcarg__MYARG`` を検索できるのは便利で、 ``MYARG`` という関数の引数に対する全てのファクトリー関数を戸惑いなく探せます。
|
||||||
|
|
||||||
|
.. _`Convention over Configuration`: http://en.wikipedia.org/wiki/Convention_over_Configuration
|
||||||
|
.. _`設定より規約`: http://en.wikipedia.org/wiki/Convention_over_Configuration
|
||||||
|
|
||||||
|
funcarg ファクトリー関数から複数の値を yield できますか?
|
||||||
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
..
|
||||||
|
Can I yield multiple values from a funcarg factory function?
|
||||||
|
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
..
|
||||||
|
There are two conceptual reasons why yielding from a factory function
|
||||||
|
is not possible:
|
||||||
|
|
||||||
|
ファクトリー関数が yield できない概念上の理由が2つあります:
|
||||||
|
|
||||||
|
..
|
||||||
|
* Calling factories for obtaining test function arguments
|
||||||
|
is part of setting up and running a test. At that
|
||||||
|
point it is not possible to add new test calls to
|
||||||
|
the test collection anymore.
|
||||||
|
|
||||||
|
* テスト関数の引数を取得するためにファクトリー関数を呼び出すのは、テストの設定と実行の部分です。その時点では、テストコレクションのために新たなテスト呼び出しを追加できません。
|
||||||
|
|
||||||
|
..
|
||||||
|
* If multiple factories yielded values there would
|
||||||
|
be no natural place to determine the combination
|
||||||
|
policy - in real-world examples some combinations
|
||||||
|
often should not run.
|
||||||
|
|
||||||
|
* 複数のファクトリー関数が値を yield した場合、組み合わせ方法を決定するのに適当な場所がありません。現実の世界の例は、そういった組み合わせが多くの場合に実行されません。
|
||||||
|
|
||||||
|
..
|
||||||
|
Use the `pytest_generate_tests`_ hook to solve both issues
|
||||||
|
and implement the `parametrization scheme of your choice`_.
|
||||||
|
|
||||||
|
両方の課題を解決するために `pytest_generate_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/
|
||||||
|
.. _`パラメーター化の仕組みにあったものを選択して`: http://tetamap.wordpress.com/2009/05/13/parametrizing-python-tests-generalized/
|
||||||
|
|
||||||
|
その他のパッケージと py.test の相互連携
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
py.test interaction with other packages
|
||||||
|
---------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Issues with py.test, multiprocess and setuptools?
|
||||||
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
py.test, multiprocess, setuptools と関連する問題?
|
||||||
|
++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
..
|
||||||
|
On windows the multiprocess package will instantiate sub processes
|
||||||
|
by pickling and thus implicitly re-import a lot of local modules.
|
||||||
|
Unfortunately, setuptools-0.6.11 does not ``if __name__=='__main__'``
|
||||||
|
protect its generated command line script. This leads to infinite
|
||||||
|
recursion when running a test that instantiates Processes.
|
||||||
|
|
||||||
|
Windows 上の multiprocess パッケージは、pickle 化することでサブプロセスをインスタンス化し、暗黙的にたくさんのローカルモジュールを再インポートします。残念ながら、setuptools 0.6.11 が作成したコマンドラインスクリプトは ``if __name__=='__main__'`` による保護がありません。これにより、実行中のテストがプロセスをインスタンス化するときに無限再帰を引き起こします。
|
||||||
|
|
||||||
|
..
|
||||||
|
A good solution is to `install Distribute`_ as a drop-in replacement
|
||||||
|
for setuptools and then re-install ``pytest``. Otherwise you could
|
||||||
|
fix the script that is created by setuptools by inserting an
|
||||||
|
``if __name__ == '__main__'``. Or you can create a "pytest.py"
|
||||||
|
script with this content and invoke that with the python version::
|
||||||
|
|
||||||
|
良い解決策は、setuptools の置き換えとして `distribute をインストールする`_ ことです。その後に ``pytest`` を再インストールします。別の方法では、setuptools が作成したスクリプトに ``if __name__ == '__main__'`` を追加して修正します。もしくは、この内容を含む "pytest.py" スクリプトを作成して、そのスクリプトを実行します::
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
if __name__ == '__main__':
|
||||||
|
pytest.main()
|
||||||
|
|
||||||
|
.. _`install distribute`: http://pypi.python.org/pypi/distribute#installation-instructions
|
||||||
|
.. _`distribute をインストールする`: http://pypi.python.org/pypi/distribute#installation-instructions
|
||||||
|
|
||||||
|
.. include:: links.inc
|
|
@ -0,0 +1,8 @@
|
||||||
|
|
||||||
|
What users say:
|
||||||
|
|
||||||
|
`py.test is pretty much the best thing ever`_ (Alex Gaynor)
|
||||||
|
|
||||||
|
|
||||||
|
.. _`py.test is pretty much the best thing ever`_ (Alex Gaynor)
|
||||||
|
http://twitter.com/#!/alex_gaynor/status/22389410366
|
|
@ -0,0 +1,357 @@
|
||||||
|
..
|
||||||
|
==============================================================
|
||||||
|
Injecting objects into test functions (funcargs)
|
||||||
|
==============================================================
|
||||||
|
|
||||||
|
==========================================
|
||||||
|
テスト関数 (funcargs) にオブジェクトを注入
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
.. currentmodule:: _pytest.python
|
||||||
|
|
||||||
|
|
||||||
|
.. _`funcargs`:
|
||||||
|
.. _`funcarg mechanism`:
|
||||||
|
|
||||||
|
関数の引数を使った依存性の注入
|
||||||
|
==============================
|
||||||
|
|
||||||
|
..
|
||||||
|
Dependency injection through function arguments
|
||||||
|
=================================================
|
||||||
|
|
||||||
|
..
|
||||||
|
py.test lets you inject objects into test functions and precisely
|
||||||
|
control their life cycle in relation to the test execution. It is
|
||||||
|
also possible to run a test function multiple times with different objects.
|
||||||
|
|
||||||
|
py.test は、テスト関数にオブジェクトを注入し、テストの実行に関連付けてそのライフサイクルを細かく制御できます。さらに別のオブジェクトでテスト関数を複数回実行することもできます。
|
||||||
|
|
||||||
|
..
|
||||||
|
The basic mechanism for injecting objects is also called the
|
||||||
|
*funcarg mechanism* because objects are ultimately injected
|
||||||
|
by calling a test function with it as an argument. Unlike the
|
||||||
|
classical xUnit approach *funcargs* relate more to `Dependency Injection`_
|
||||||
|
because they help to de-couple test code from objects required for
|
||||||
|
them to execute.
|
||||||
|
|
||||||
|
オブジェクトを注入するための基本的な仕組みは *funcarg 機構* とも呼ばれます。ある引数に対して、その引数を受け取るテスト関数が呼ばれることで最終的にオブジェクトが注入されるからです。古典的な xUnit のやり方とは異なり *funcargs* は `依存性の注入`_ に密接に関連したものです。その根拠は、テストコードを実行するために必要なオブジェクトからテストコードを分離するのに役立つからです。
|
||||||
|
|
||||||
|
.. _`Dependency injection`: http://en.wikipedia.org/wiki/Dependency_injection
|
||||||
|
.. _`依存性の注入`: http://en.wikipedia.org/wiki/Dependency_injection
|
||||||
|
|
||||||
|
..
|
||||||
|
To create a value with which to call a test function a factory function
|
||||||
|
is called which gets full access to the test function context and can
|
||||||
|
register finalizers or invoke lifecycle-caching helpers. The factory
|
||||||
|
can be implemented in same test class or test module, or in a
|
||||||
|
per-directory ``conftest.py`` file or even in an external plugin. This
|
||||||
|
allows full de-coupling of test code and objects needed for test
|
||||||
|
execution.
|
||||||
|
|
||||||
|
テスト関数へ渡される値を作成するために、テスト関数のコンテキストに対してフルアクセスをもったファクトリー関数が呼ばれます。そして、ファイナライザーを登録したり、ライフサイクルキャッシュヘルパーを実行します。ファクトリー関数は、同じテストクラスかテストモジュール、ディレクトリ毎の ``conftest.py`` ファイル、外部プラグインであろうと、そのいずれでも実装できます。これにより、テストの実行に必要なテストコードとオブジェクトを完全に分離できます。
|
||||||
|
|
||||||
|
..
|
||||||
|
A test function may be invoked multiple times in which case we
|
||||||
|
speak of :ref:`parametrized testing <parametrizing-tests>`. This can be
|
||||||
|
very useful if you want to test e.g. against different database backends
|
||||||
|
or with multiple numerical arguments sets and want to reuse the same set
|
||||||
|
of test functions.
|
||||||
|
|
||||||
|
テスト関数は、 :ref:`パラメーターテスト <parametrizing-tests>` で説明したようなケースなら複数回呼び出すこともあります。これは、例えば、別々のデータベースのバックエンド、または複数の数値の引数セットをテストしたいときや、テスト関数の同じセットを再利用したいといったときにとても便利です。
|
||||||
|
|
||||||
|
..
|
||||||
|
py.test comes with :ref:`builtinfuncargs` and there are some refined usages in the examples section.
|
||||||
|
|
||||||
|
py.test には :ref:`builtinfuncargs` が付属していて、そのサンプルを紹介する節に洗練された利用方法があります。
|
||||||
|
|
||||||
|
.. _funcarg:
|
||||||
|
|
||||||
|
基本的な注入の例
|
||||||
|
----------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Basic injection example
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Let's look at a simple self-contained test module::
|
||||||
|
|
||||||
|
簡単な自己完結型のテストモジュールを見てみましょう::
|
||||||
|
|
||||||
|
# ./test_simplefactory.py の内容
|
||||||
|
def pytest_funcarg__myfuncarg(request):
|
||||||
|
return 42
|
||||||
|
|
||||||
|
def test_function(myfuncarg):
|
||||||
|
assert myfuncarg == 17
|
||||||
|
|
||||||
|
..
|
||||||
|
This test function needs an injected object named ``myfuncarg``.
|
||||||
|
py.test will discover and call the factory named
|
||||||
|
``pytest_funcarg__myfuncarg`` within the same module in this case.
|
||||||
|
|
||||||
|
このテスト関数は ``myfuncarg`` という名前のオブジェクトへの注入を必要とします。この場合 py.test は、同じモジュール内の ``pytest_funcarg__myfuncarg`` というファクトリー関数を見つけて呼び出します。
|
||||||
|
|
||||||
|
..
|
||||||
|
Running the test looks like this::
|
||||||
|
|
||||||
|
次のようにテストが実行されます::
|
||||||
|
|
||||||
|
$ py.test test_simplefactory.py
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 1 items
|
||||||
|
|
||||||
|
test_simplefactory.py F
|
||||||
|
|
||||||
|
================================= FAILURES =================================
|
||||||
|
______________________________ test_function _______________________________
|
||||||
|
|
||||||
|
myfuncarg = 42
|
||||||
|
|
||||||
|
def test_function(myfuncarg):
|
||||||
|
> assert myfuncarg == 17
|
||||||
|
E assert 42 == 17
|
||||||
|
|
||||||
|
test_simplefactory.py:5: AssertionError
|
||||||
|
========================= 1 failed in 0.01 seconds =========================
|
||||||
|
|
||||||
|
..
|
||||||
|
This means that indeed the test function was called with a ``myfuncarg``
|
||||||
|
argument value of ``42`` and the assert fails. Here is how py.test
|
||||||
|
comes to call the test function this way:
|
||||||
|
|
||||||
|
これは実際にテスト関数が ``myfuncarg`` 引数の値が ``42`` で呼び出されて、そのアサートに失敗します。py.test がどういった手順でテスト関数を呼び出すかを説明します:
|
||||||
|
|
||||||
|
..
|
||||||
|
1. py.test :ref:`finds <test discovery>` the ``test_function`` because
|
||||||
|
of the ``test_`` prefix. The test function needs a function argument
|
||||||
|
named ``myfuncarg``. A matching factory function is discovered by
|
||||||
|
looking for the name ``pytest_funcarg__myfuncarg``.
|
||||||
|
|
||||||
|
1. py.test は ``test_`` という接頭辞をもつ ``test_function`` を :ref:`探索します <test discovery>` 。テスト関数は ``myfuncarg`` という関数の引数を必要とします。 ``pytest_funcarg__myfuncarg`` という名前を調べて一致するファクトリー関数が検出されます。
|
||||||
|
|
||||||
|
..
|
||||||
|
2. ``pytest_funcarg__myfuncarg(request)`` is called and
|
||||||
|
returns the value for ``myfuncarg``.
|
||||||
|
|
||||||
|
2. ``pytest_funcarg__myfuncarg(request)`` が呼び出されて ``myfuncarg`` の値を返します。
|
||||||
|
|
||||||
|
..
|
||||||
|
3. the test function can now be called: ``test_function(42)``.
|
||||||
|
This results in the above exception because of the assertion
|
||||||
|
mismatch.
|
||||||
|
|
||||||
|
3. そのテスト関数は ``test_function(42)`` として呼び出されます。この実行結果は、アサーションが不一致なので上述した例外を発生させます。
|
||||||
|
|
||||||
|
..
|
||||||
|
Note that if you misspell a function argument or want
|
||||||
|
to use one that isn't available, you'll see an error
|
||||||
|
with a list of available function arguments.
|
||||||
|
|
||||||
|
関数の引数に誤字があったり、利用できないものを使おうとしたら、利用できる関数の引数の一覧と共にエラーが表示されるので注意してください。
|
||||||
|
|
||||||
|
..
|
||||||
|
You can always issue::
|
||||||
|
|
||||||
|
いつでも次のようにして::
|
||||||
|
|
||||||
|
py.test --funcargs test_simplefactory.py
|
||||||
|
|
||||||
|
..
|
||||||
|
to see available function arguments (which you can also
|
||||||
|
think of as "resources").
|
||||||
|
|
||||||
|
利用できる関数の引数 ("リソース" とも見なせる) を調べられます。
|
||||||
|
|
||||||
|
.. _`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/
|
||||||
|
.. _`xUnit style`: xunit_setup.html
|
||||||
|
|
||||||
|
|
||||||
|
.. _`funcarg factory`:
|
||||||
|
.. _factory:
|
||||||
|
|
||||||
|
funcarg **request** オブジェクト
|
||||||
|
================================
|
||||||
|
|
||||||
|
..
|
||||||
|
The funcarg **request** object
|
||||||
|
=============================================
|
||||||
|
|
||||||
|
..
|
||||||
|
Each funcarg factory receives a **request** object tied to a specific test
|
||||||
|
function call. A request object is passed to a funcarg factory and provides
|
||||||
|
access to test configuration and context:
|
||||||
|
|
||||||
|
funcarg ファクトリー関数は、特別なテスト関数呼び出しに関連付けられた **request** オブジェクトを受け取ります。request オブジェクトは funcarg ファクトリーへ渡されて、テスト設定とコンテキストへのアクセスを提供します:
|
||||||
|
|
||||||
|
.. autoclass:: _pytest.python.FuncargRequest()
|
||||||
|
:members: function,cls,module,keywords,config
|
||||||
|
|
||||||
|
.. _`useful caching and finalization helpers`:
|
||||||
|
|
||||||
|
.. automethod:: FuncargRequest.addfinalizer
|
||||||
|
|
||||||
|
.. automethod:: FuncargRequest.cached_setup
|
||||||
|
|
||||||
|
.. automethod:: FuncargRequest.applymarker
|
||||||
|
|
||||||
|
.. automethod:: FuncargRequest.getfuncargvalue
|
||||||
|
|
||||||
|
|
||||||
|
.. _`test generators`:
|
||||||
|
.. _`parametrizing-tests`:
|
||||||
|
.. _`parametrized test functions`:
|
||||||
|
|
||||||
|
パラメーター化したテスト関数の複数呼び出し
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
..
|
||||||
|
Parametrizing multiple calls to a test function
|
||||||
|
===========================================================
|
||||||
|
|
||||||
|
..
|
||||||
|
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:
|
||||||
|
|
||||||
|
別の関数の引数の値を取って呼び出す新たなテスト関数を追加することで、同じテスト関数に対して複数回の実行をパラメーター化して実行できます。簡単な自己完結型のサンプルコードを見てみましょう:
|
||||||
|
|
||||||
|
..
|
||||||
|
Basic generated test example
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
テストを生成する基本的な例
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Let's consider a test module which uses the ``pytest_generate_tests``
|
||||||
|
hook to generate several calls to the same test function::
|
||||||
|
|
||||||
|
同じテスト関数に対する複数回呼び出しに生成する ``pytest_generate_tests`` フックを使うテストモジュールを見てみましょう::
|
||||||
|
|
||||||
|
# test_example.py の内容
|
||||||
|
def pytest_generate_tests(metafunc):
|
||||||
|
if "numiter" in metafunc.funcargnames:
|
||||||
|
metafunc.parametrize("numiter", range(10))
|
||||||
|
|
||||||
|
def test_func(numiter):
|
||||||
|
assert numiter < 9
|
||||||
|
|
||||||
|
..
|
||||||
|
Running this will generate ten invocations of ``test_func`` passing in each of the items in the list of ``range(10)``::
|
||||||
|
|
||||||
|
このサンプルコードを実行すると ``range(10)`` のリストの要素を1つずつ引数に渡す ``test_func`` を10回実行します::
|
||||||
|
|
||||||
|
$ py.test test_example.py
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 10 items
|
||||||
|
|
||||||
|
test_example.py .........F
|
||||||
|
|
||||||
|
================================= FAILURES =================================
|
||||||
|
_______________________________ test_func[9] _______________________________
|
||||||
|
|
||||||
|
numiter = 9
|
||||||
|
|
||||||
|
def test_func(numiter):
|
||||||
|
> assert numiter < 9
|
||||||
|
E assert 9 < 9
|
||||||
|
|
||||||
|
test_example.py:6: AssertionError
|
||||||
|
==================== 1 failed, 9 passed in 0.02 seconds ====================
|
||||||
|
|
||||||
|
..
|
||||||
|
Obviously, only when ``numiter`` has the value of ``9`` does the test fail. Note that the ``pytest_generate_tests(metafunc)`` hook is called during
|
||||||
|
the test collection phase which is separate from the actual test running.
|
||||||
|
Let's just look at what is collected::
|
||||||
|
|
||||||
|
分かりやすいように ``numiter`` の値が ``9`` のときのみテストが失敗します。 ``pytest_generate_tests(metafunc)`` フックは、実際にテストを実行するときとは違うフェーズの、テストコレクションで呼ばれることに注意してください。では、テストコレクションがどうなるかをちょっと見てみましょう::
|
||||||
|
|
||||||
|
$ py.test --collectonly test_example.py
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 10 items
|
||||||
|
<Module 'test_example.py'>
|
||||||
|
<Function 'test_func[0]'>
|
||||||
|
<Function 'test_func[1]'>
|
||||||
|
<Function 'test_func[2]'>
|
||||||
|
<Function 'test_func[3]'>
|
||||||
|
<Function 'test_func[4]'>
|
||||||
|
<Function 'test_func[5]'>
|
||||||
|
<Function 'test_func[6]'>
|
||||||
|
<Function 'test_func[7]'>
|
||||||
|
<Function 'test_func[8]'>
|
||||||
|
<Function 'test_func[9]'>
|
||||||
|
|
||||||
|
============================= in 0.00 seconds =============================
|
||||||
|
|
||||||
|
..
|
||||||
|
If you want to select only the run with the value ``7`` you could do::
|
||||||
|
|
||||||
|
テスト実行時に ``7`` の値が渡されるときだけ実行したい場合は次のようにして行います::
|
||||||
|
|
||||||
|
$ py.test -v -k 7 test_example.py # または -k test_func[7]
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4 -- /home/hpk/venv/0/bin/python
|
||||||
|
collecting ... collected 10 items
|
||||||
|
|
||||||
|
test_example.py:5: test_func[7] PASSED
|
||||||
|
|
||||||
|
======================= 9 tests deselected by '-k7' ========================
|
||||||
|
================== 1 passed, 9 deselected in 0.01 seconds ==================
|
||||||
|
|
||||||
|
..
|
||||||
|
You might want to look at :ref:`more parametrization examples <paramexamples>`.
|
||||||
|
|
||||||
|
:ref:`さらにパラメーターテストのサンプル <paramexamples>` を見たくなりますね。
|
||||||
|
|
||||||
|
.. _`metafunc object`:
|
||||||
|
|
||||||
|
**metafunc** オブジェクト
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
The **metafunc** object
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
metafunc objects are passed to the ``pytest_generate_tests`` hook.
|
||||||
|
They help to inspect a testfunction and to generate tests
|
||||||
|
according to test configuration or values specified
|
||||||
|
in the class or module where a test function is defined:
|
||||||
|
|
||||||
|
metafunc オブジェクトは ``pytest_generate_tests`` フックへ渡されます。これはテスト関数を検査したり、テスト設定またはテスト関数が定義されているクラスやモジュールで指定された値を取るテストを生成するのに役立ちます:
|
||||||
|
|
||||||
|
..
|
||||||
|
``metafunc.funcargnames``: set of required function arguments for given function
|
||||||
|
|
||||||
|
``metafunc.funcargnames``: テスト関数へ渡される引数セット
|
||||||
|
|
||||||
|
..
|
||||||
|
``metafunc.function``: underlying python test function
|
||||||
|
|
||||||
|
``metafunc.function``: 対象となる Python のテスト関数
|
||||||
|
|
||||||
|
..
|
||||||
|
``metafunc.cls``: class object where the test function is defined in or None.
|
||||||
|
|
||||||
|
``metafunc.cls``: テスト関数が定義されているところのクラスオブジェクト、または None
|
||||||
|
|
||||||
|
..
|
||||||
|
``metafunc.module``: the module object where the test function is defined in.
|
||||||
|
|
||||||
|
``metafunc.module``: テスト関数が定義されているところのモジュールオブジェクト
|
||||||
|
|
||||||
|
..
|
||||||
|
``metafunc.config``: access to command line opts and general config
|
||||||
|
|
||||||
|
``metafunc.config``: コマンドラインオプションと汎用的な設定オブジェクト
|
||||||
|
|
||||||
|
.. automethod:: Metafunc.parametrize
|
||||||
|
.. automethod:: Metafunc.addcall(funcargs=None,id=_notexists,param=_notexists)
|
|
@ -0,0 +1,364 @@
|
||||||
|
..
|
||||||
|
Installation and Getting Started
|
||||||
|
===================================
|
||||||
|
|
||||||
|
インストールして始めよう
|
||||||
|
========================
|
||||||
|
|
||||||
|
|
||||||
|
**Pythons**: Python 2.4-3.2, Jython, PyPy
|
||||||
|
|
||||||
|
..
|
||||||
|
**Platforms**: Unix/Posix and Windows
|
||||||
|
|
||||||
|
**Platforms** : Unix/Posix と Windows
|
||||||
|
|
||||||
|
..
|
||||||
|
**PyPI package name**: `pytest <http://pypi.python.org/pypi/pytest>`_
|
||||||
|
|
||||||
|
**PyPI パッケージ名** : `pytest <http://pypi.python.org/pypi/pytest>`_
|
||||||
|
|
||||||
|
..
|
||||||
|
**documentation as PDF**: `download latest <http://pytest.org/latest/pytest.pdf>`_
|
||||||
|
|
||||||
|
**PDF ドキュメント** : `最新をダウンロード <http://pytest.org/latest/pytest.pdf>`_
|
||||||
|
|
||||||
|
|
||||||
|
.. _`getstarted`:
|
||||||
|
|
||||||
|
インストール
|
||||||
|
------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Installation
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Installation options::
|
||||||
|
|
||||||
|
インストールオプション::
|
||||||
|
|
||||||
|
pip install -U pytest # or
|
||||||
|
easy_install -U pytest
|
||||||
|
|
||||||
|
..
|
||||||
|
To check your installation has installed the correct version::
|
||||||
|
|
||||||
|
インストール後に適切なバージョンかを確認するには、次のように実行します::
|
||||||
|
|
||||||
|
$ py.test --version
|
||||||
|
This is py.test version 2.2.4, imported from /home/hpk/p/pytest/pytest.py
|
||||||
|
setuptools registered plugins:
|
||||||
|
pytest-xdist-1.8 at /home/hpk/p/pytest-xdist/xdist/plugin.pyc
|
||||||
|
|
||||||
|
..
|
||||||
|
If you get an error checkout :ref:`installation issues`.
|
||||||
|
|
||||||
|
エラーが発生したら :ref:`installation issues` を確認してください。
|
||||||
|
|
||||||
|
|
||||||
|
.. _`simpletest`:
|
||||||
|
|
||||||
|
初めてのテスト実行
|
||||||
|
------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Our first test run
|
||||||
|
----------------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Let's create a first test file with a simple test function::
|
||||||
|
|
||||||
|
簡単なテスト関数を含む最初のテストファイルを作りましょう::
|
||||||
|
|
||||||
|
# test_sample.py の内容
|
||||||
|
def func(x):
|
||||||
|
return x + 1
|
||||||
|
|
||||||
|
def test_answer():
|
||||||
|
assert func(3) == 5
|
||||||
|
|
||||||
|
..
|
||||||
|
That's it. You can execute the test function now::
|
||||||
|
|
||||||
|
こんな感じです。さあ、テスト関数を実行しましょう::
|
||||||
|
|
||||||
|
$ py.test
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 1 items
|
||||||
|
|
||||||
|
test_sample.py F
|
||||||
|
|
||||||
|
================================= FAILURES =================================
|
||||||
|
_______________________________ test_answer ________________________________
|
||||||
|
|
||||||
|
def test_answer():
|
||||||
|
> assert func(3) == 5
|
||||||
|
E assert 4 == 5
|
||||||
|
E + where 4 = func(3)
|
||||||
|
|
||||||
|
test_sample.py:5: AssertionError
|
||||||
|
========================= 1 failed in 0.01 seconds =========================
|
||||||
|
|
||||||
|
..
|
||||||
|
py.test found the ``test_answer`` function by following :ref:`standard test discovery rules <test discovery>`, basically detecting the ``test_`` prefixes. We got a failure report because our little ``func(3)`` call did not return ``5``.
|
||||||
|
|
||||||
|
py.test は :ref:`標準的なテスト探索ルール <test discovery>` に従い ``test_answer`` 関数を検出します。基本的には ``test_`` の接頭辞をもつファイルや関数です。先ほど作成した ``func(3)`` 呼び出しが ``5`` を返さなかったという失敗レポートを受け取りました。
|
||||||
|
|
||||||
|
..
|
||||||
|
You can simply use the ``assert`` statement for asserting test
|
||||||
|
expectations. pytest's :ref:`assert introspection` will intelligently
|
||||||
|
report intermediate values of the assert expression freeing
|
||||||
|
you from the need to learn the many names of `JUnit legacy methods`_.
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
テストの期待値をアサートするには単純に ``assert`` 文を使います。pytest の :ref:`assert introspection` は assert 評価時の中間値を賢くレポートします。これにより、多くの `JUnit レガシーメソッド`_ の名前を覚える必要がなくなります。
|
||||||
|
|
||||||
|
.. _`JUnit legacy methods`: http://docs.python.org/library/unittest.html#test-cases
|
||||||
|
.. _`JUnit レガシーメソッド`: http://docs.python.org/library/unittest.html#test-cases
|
||||||
|
|
||||||
|
.. _`assert statement`: http://docs.python.org/reference/simple_stmts.html#the-assert-statement
|
||||||
|
|
||||||
|
特定の例外が発生したことをアサートする
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Asserting that a certain exception is raised
|
||||||
|
--------------------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
If you want to assert that some code raises an exception you can
|
||||||
|
use the ``raises`` helper::
|
||||||
|
|
||||||
|
例外を発生させるコードをテストしたいなら ``raises`` ヘルパー関数を使います::
|
||||||
|
|
||||||
|
# test_sysexit.py の内容
|
||||||
|
import pytest
|
||||||
|
def f():
|
||||||
|
raise SystemExit(1)
|
||||||
|
|
||||||
|
def test_mytest():
|
||||||
|
with pytest.raises(SystemExit):
|
||||||
|
f()
|
||||||
|
|
||||||
|
..
|
||||||
|
Running it with, this time in "quiet" reporting mode::
|
||||||
|
|
||||||
|
このコードを "quiet" モードで実行します::
|
||||||
|
|
||||||
|
$ py.test -q test_sysexit.py
|
||||||
|
collecting ... collected 1 items
|
||||||
|
.
|
||||||
|
1 passed in 0.00 seconds
|
||||||
|
|
||||||
|
.. todo:: For further ways to assert exceptions see the `raises`
|
||||||
|
|
||||||
|
..
|
||||||
|
Grouping multiple tests in a class
|
||||||
|
--------------------------------------------------------------
|
||||||
|
|
||||||
|
1つのクラスで複数のテストをグループ化する
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Once you start to have more than a few tests it often makes sense
|
||||||
|
to group tests logically, in classes and modules. Let's write a class
|
||||||
|
containing two tests::
|
||||||
|
|
||||||
|
テストを書き始めて何個か作成したら、クラスやモジュール内にそういったテストをグループ化すると分かりやすくなります。2つのテストを含むクラスを作成しましょう::
|
||||||
|
|
||||||
|
# test_class.py の内容
|
||||||
|
class TestClass:
|
||||||
|
def test_one(self):
|
||||||
|
x = "this"
|
||||||
|
assert 'h' in x
|
||||||
|
|
||||||
|
def test_two(self):
|
||||||
|
x = "hello"
|
||||||
|
assert hasattr(x, 'check')
|
||||||
|
|
||||||
|
..
|
||||||
|
The two tests are found because of the standard :ref:`test discovery`.
|
||||||
|
There is no need to subclass anything. We can simply
|
||||||
|
run the module by passing its filename::
|
||||||
|
|
||||||
|
:ref:`標準的なテスト探索ルール <test discovery>` により、2つのテストが検出されました。サブクラス化する必要はありません。単純にそのファイル名を与えることで、対象のモジュールを実行できます::
|
||||||
|
|
||||||
|
$ py.test -q test_class.py
|
||||||
|
collecting ... collected 2 items
|
||||||
|
.F
|
||||||
|
================================= FAILURES =================================
|
||||||
|
____________________________ TestClass.test_two ____________________________
|
||||||
|
|
||||||
|
self = <test_class.TestClass instance at 0x1a956c8>
|
||||||
|
|
||||||
|
def test_two(self):
|
||||||
|
x = "hello"
|
||||||
|
> assert hasattr(x, 'check')
|
||||||
|
E assert hasattr('hello', 'check')
|
||||||
|
|
||||||
|
test_class.py:8: AssertionError
|
||||||
|
1 failed, 1 passed in 0.01 seconds
|
||||||
|
|
||||||
|
..
|
||||||
|
The first test passed, the second failed. Again we can easily see
|
||||||
|
the intermediate values used in the assertion, helping us to
|
||||||
|
understand the reason for the failure.
|
||||||
|
|
||||||
|
最初のテストは成功し、2番目のテストは失敗しました。また、失敗した原因を理解しやすいよう、このアサーションの中間値がぱっと見て分かります。
|
||||||
|
|
||||||
|
..
|
||||||
|
Going functional: requesting a unique temporary directory
|
||||||
|
--------------------------------------------------------------
|
||||||
|
|
||||||
|
機能テスト: 一時ディレクトリの要求
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
For functional tests one often needs to create some files
|
||||||
|
and pass them to application objects. py.test provides
|
||||||
|
the versatile :ref:`funcarg mechanism` which allows to request
|
||||||
|
arbitrary resources, for example a unique temporary directory::
|
||||||
|
|
||||||
|
機能テストでは、ファイルを作成して、アプリケーションのオブジェクトをそのファイルに書き込むようなことがよくあります。py.test は、1つだけ存在する一時ディレクトリといった、任意のリソース要求を扱う万能の :ref:`funcarg mechanism` を提供します::
|
||||||
|
|
||||||
|
# test_tmpdir.py の内容
|
||||||
|
def test_needsfiles(tmpdir):
|
||||||
|
print tmpdir
|
||||||
|
assert 0
|
||||||
|
|
||||||
|
..
|
||||||
|
We list the name ``tmpdir`` in the test function signature and
|
||||||
|
py.test will lookup and call a factory to create the resource
|
||||||
|
before performing the test function call. Let's just run it::
|
||||||
|
|
||||||
|
テスト関数のシグネチャに ``tmpdir`` という名前を含めます。py.test はその名前を見つけ、テスト関数が呼び出される前にリソースを作成するファクトリー関数を呼び出します。では、実行してみましょう::
|
||||||
|
|
||||||
|
$ py.test -q test_tmpdir.py
|
||||||
|
collecting ... collected 1 items
|
||||||
|
F
|
||||||
|
================================= FAILURES =================================
|
||||||
|
_____________________________ test_needsfiles ______________________________
|
||||||
|
|
||||||
|
tmpdir = local('/tmp/pytest-22/test_needsfiles0')
|
||||||
|
|
||||||
|
def test_needsfiles(tmpdir):
|
||||||
|
print tmpdir
|
||||||
|
> assert 0
|
||||||
|
E assert 0
|
||||||
|
|
||||||
|
test_tmpdir.py:3: AssertionError
|
||||||
|
----------------------------- Captured stdout ------------------------------
|
||||||
|
/tmp/pytest-22/test_needsfiles0
|
||||||
|
1 failed in 0.01 seconds
|
||||||
|
|
||||||
|
..
|
||||||
|
Before the test runs, a unique-per-test-invocation temporary directory
|
||||||
|
was created. More info at :ref:`tmpdir handling`.
|
||||||
|
|
||||||
|
テストを実行する毎に、そのテスト関数の実行前に一時ディレクトリが作成されました。さらに詳細は :ref:`tmpdir handling` を参照してください。
|
||||||
|
|
||||||
|
..
|
||||||
|
You can find out what kind of builtin :ref:`funcargs` exist by typing::
|
||||||
|
|
||||||
|
組み込みの :ref:`funcargs` を把握するには、次のコマンドを実行します::
|
||||||
|
|
||||||
|
py.test --funcargs # 組み込み/カスタムの関数の引数を表示する
|
||||||
|
|
||||||
|
..
|
||||||
|
Where to go next
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
次に学ぶこと
|
||||||
|
------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Here are a few suggestions where to go next:
|
||||||
|
|
||||||
|
次のドキュメントを見てましょう:
|
||||||
|
|
||||||
|
..
|
||||||
|
* :ref:`cmdline` for command line invocation examples
|
||||||
|
* :ref:`good practises <goodpractises>` for virtualenv, test layout, genscript support
|
||||||
|
* :ref:`apiref` for documentation and examples on using py.test
|
||||||
|
* :ref:`plugins` managing and writing plugins
|
||||||
|
|
||||||
|
* :ref:`cmdline`: コマンドラインの実行方法のサンプル
|
||||||
|
* :ref:`優れたプラクティス <goodpractises>`: virtualenv、テストレイアウト、genscript の対応
|
||||||
|
* :ref:`apiref`: ドキュメントと py.test を使う上でのサンプル
|
||||||
|
* :ref:`plugins`: プラグインの管理と作成
|
||||||
|
|
||||||
|
.. _`installation issues`:
|
||||||
|
|
||||||
|
インストールに関する既知の問題
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Known Installation issues
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
easy_install or pip not found?
|
||||||
|
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
easy_install や pip が見つかりません
|
||||||
|
++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
.. _`install pip`: http://www.pip-installer.org/en/latest/index.html
|
||||||
|
.. _`pip をインストール`: http://www.pip-installer.org/en/latest/index.html
|
||||||
|
|
||||||
|
..
|
||||||
|
`Install pip`_ for a state of the art python package installer.
|
||||||
|
|
||||||
|
最先端の Python パッケージインストーラーである `pip をインストール`_ してください。
|
||||||
|
|
||||||
|
..
|
||||||
|
Or consult `distribute docs`_ to install the ``easy_install``
|
||||||
|
tool on your machine.
|
||||||
|
|
||||||
|
もしくは ``easy_install`` ツールをインストールするために `distribute docs`_ を読んでください。
|
||||||
|
|
||||||
|
..
|
||||||
|
You may also use the older `setuptools`_ project but it lacks bug fixes
|
||||||
|
and does not work on Python3.
|
||||||
|
|
||||||
|
旧来の `setuptools`_ プロジェクトも使えますが、それはバグ修正が行われてなく Python 3 でも動作しません。
|
||||||
|
|
||||||
|
..
|
||||||
|
py.test not found on Windows despite installation?
|
||||||
|
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
インストールしたのに Windows 上で py.test が見つかりません
|
||||||
|
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
.. _`Python for Windows`: http://www.imladris.com/Scripts/PythonForWindows.html
|
||||||
|
|
||||||
|
..
|
||||||
|
- **Windows**: If "easy_install" or "py.test" are not found
|
||||||
|
you need to add the Python script path to your ``PATH``, see here:
|
||||||
|
`Python for Windows`_. You may alternatively use an `ActivePython install`_
|
||||||
|
which does this for you automatically.
|
||||||
|
|
||||||
|
- **Windows**: "easy_install" または "py.test" が見つからないなら、 ``PATH`` にそれらの Python スクリプトを追加する必要があります。 `Python for Windows`_ を参照してください。別の方法として、自動的にパス設定を行ってくれる `ActivePython install`_ を使うこともできます。
|
||||||
|
|
||||||
|
.. _`ActivePython install`: http://www.activestate.com/activepython/downloads
|
||||||
|
|
||||||
|
.. _`Jython does not create command line launchers`: http://bugs.jython.org/issue1491
|
||||||
|
.. _`Jython はコマンドラインランチャーを作らない`: http://bugs.jython.org/issue1491
|
||||||
|
|
||||||
|
..
|
||||||
|
- **Jython2.5.1 on Windows XP**: `Jython does not create command line launchers`_
|
||||||
|
so ``py.test`` will not work correctly. You may install py.test on
|
||||||
|
CPython and type ``py.test --genscript=mytest`` and then use
|
||||||
|
|
||||||
|
:ref:`examples` for more complex examples
|
||||||
|
|
||||||
|
``jython mytest`` to run py.test for your tests to run with Jython.
|
||||||
|
|
||||||
|
- **Windows XP 上の Jython2.5.1**: `Jython はコマンドラインランチャーを作らない`_ ので ``py.test`` は正常に動作しません。CPython 上に py.test をインストールして ``py.test --genscript=mytest`` を実行すると、Jython で行うテストを py.test で実行する ``jython mytest`` が使えます。
|
||||||
|
|
||||||
|
複雑な例は :ref:`examples` を参照してください。
|
||||||
|
|
||||||
|
.. include:: links.inc
|
|
@ -0,0 +1,315 @@
|
||||||
|
|
||||||
|
.. highlightlang:: python
|
||||||
|
.. _`goodpractises`:
|
||||||
|
|
||||||
|
優れたインテグレーションプラクティス
|
||||||
|
====================================
|
||||||
|
|
||||||
|
..
|
||||||
|
Good Integration Practises
|
||||||
|
=================================================
|
||||||
|
|
||||||
|
..
|
||||||
|
Work with virtual environments
|
||||||
|
-----------------------------------------------------------
|
||||||
|
|
||||||
|
仮想環境での作業
|
||||||
|
----------------
|
||||||
|
|
||||||
|
..
|
||||||
|
We recommend to use virtualenv_ environments and use easy_install_
|
||||||
|
(or pip_) for installing your application dependencies as well as
|
||||||
|
the ``pytest`` package itself. This way you will get a much more reproducible
|
||||||
|
environment. A good tool to help you automate test runs against multiple
|
||||||
|
dependency configurations or Python interpreters is `tox`_.
|
||||||
|
|
||||||
|
virtualenv_ 環境を構築して、 ``pytest`` パッケージとその他に依存するアプリケーションをインストールするのに easy_install_ (または pip_) を使うことをお奨めします。 `tox`_ という、複数の依存設定や Python インタープリターに対して自動的にテストを実行する便利なツールがあります。
|
||||||
|
|
||||||
|
.. _`virtualenv`: http://pypi.python.org/pypi/virtualenv
|
||||||
|
.. _`buildout`: http://www.buildout.org/
|
||||||
|
.. _pip: http://pypi.python.org/pypi/pip
|
||||||
|
|
||||||
|
..
|
||||||
|
Use tox and Continuous Integration servers
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
tox と継続的インテグレーションサーバーの利用
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
If you frequently release code to the public you
|
||||||
|
may want to look into `tox`_, the virtualenv test automation
|
||||||
|
tool and its `pytest support <http://codespeak.net/tox/example/pytest.html>`_.
|
||||||
|
The basic idea is to generate a JUnitXML file through the ``--junitxml=PATH`` option and have a continuous integration server like Jenkins_ pick it up
|
||||||
|
and generate reports.
|
||||||
|
|
||||||
|
もし頻繁にコードを一般向けにリリースするなら、virtualenv のテスト自動化とその `pytest サポート <http://codespeak.net/tox/example/pytest.html>`_ を行う `tox`_ を調べてみたくなるでしょう。基本的な考え方は、 ``--junitxml=PATH`` オプションにより JUnitXML ファイルを生成します。そして Jenkins_ のような継続的インテグレーションサーバーがそのファイルを取得してレポートを生成します。
|
||||||
|
|
||||||
|
.. _standalone:
|
||||||
|
.. _`genscript method`:
|
||||||
|
|
||||||
|
単独実行できる py.test スクリプトの作成
|
||||||
|
---------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Create a py.test standalone script
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
If you are a maintainer or application developer and want others
|
||||||
|
to easily run tests you can generate a completely standalone "py.test"
|
||||||
|
script::
|
||||||
|
|
||||||
|
あなたがメンテナーまたはアプリケーション開発者で、他の人にも簡単にテストを実行させたいなら、単独で実行できる "py.test" スクリプトを作成できます::
|
||||||
|
|
||||||
|
py.test --genscript=runtests.py
|
||||||
|
|
||||||
|
..
|
||||||
|
generates a ``runtests.py`` script which is a fully functional basic
|
||||||
|
``py.test`` script, running unchanged under Python2 and Python3.
|
||||||
|
You can tell people to download the script and then e.g. run it like this::
|
||||||
|
|
||||||
|
基本的に ``py.test`` スクリプトと完全に同機能をもつ ``runtests.py`` スクリプトを生成します。このスクリプトは Python2 と Python3 においても修正せず実行できます。このスクリプトをダウンロードして、例えば、次のように実行してくださいと伝えれば良いです::
|
||||||
|
|
||||||
|
python runtests.py
|
||||||
|
|
||||||
|
.. _`Distribute for installation`: http://pypi.python.org/pypi/distribute#installation-instructions
|
||||||
|
.. _`distribute installation`: http://pypi.python.org/pypi/distribute
|
||||||
|
|
||||||
|
``python setup.py test`` による distutils との連携
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Integrating with distutils / ``python setup.py test``
|
||||||
|
--------------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
You can integrate test runs into your distutils or
|
||||||
|
setuptools based project. Use the `genscript method`_
|
||||||
|
to generate a standalone py.test script::
|
||||||
|
|
||||||
|
プロジェクトベースの distutils または setuptools でテスト実行を連携できます。単独で実行できる py.test スクリプトを生成するには :ref:`genscript メソッド <genscript method>` を使ってください::
|
||||||
|
|
||||||
|
py.test --genscript=runtests.py
|
||||||
|
|
||||||
|
..
|
||||||
|
and make this script part of your distribution and then add
|
||||||
|
this to your ``setup.py`` file::
|
||||||
|
|
||||||
|
このスクリプトを配布物の一部にして ``setup.py`` ファイルに次のコードを追加します::
|
||||||
|
|
||||||
|
from distutils.core import setup, Command
|
||||||
|
# setuptools からもインポートできます
|
||||||
|
|
||||||
|
class PyTest(Command):
|
||||||
|
user_options = []
|
||||||
|
def initialize_options(self):
|
||||||
|
pass
|
||||||
|
def finalize_options(self):
|
||||||
|
pass
|
||||||
|
def run(self):
|
||||||
|
import sys,subprocess
|
||||||
|
errno = subprocess.call([sys.executable, 'runtest.py'])
|
||||||
|
raise SystemExit(errno)
|
||||||
|
setup(
|
||||||
|
#...,
|
||||||
|
cmdclass = {'test': PyTest},
|
||||||
|
#...,
|
||||||
|
)
|
||||||
|
|
||||||
|
..
|
||||||
|
If you now type::
|
||||||
|
|
||||||
|
ここで次のように実行します::
|
||||||
|
|
||||||
|
python setup.py test
|
||||||
|
|
||||||
|
..
|
||||||
|
this will execute your tests using ``runtest.py``. As this is a
|
||||||
|
standalone version of ``py.test`` no prior installation whatsoever is
|
||||||
|
required for calling the test command. You can also pass additional
|
||||||
|
arguments to the subprocess-calls such as your test directory or other
|
||||||
|
options.
|
||||||
|
|
||||||
|
これは ``runtest.py`` を使ってテストを実行します。このように、単独で実行できる ``py.test`` スクリプトは、そのテストコマンドを呼び出すために依存パッケージをインストールする必要がありません。さらにテストディレクトリやその他のオプションなど、subprocess.call に追加の引数として渡せます。
|
||||||
|
|
||||||
|
.. _`test discovery`:
|
||||||
|
.. _`Python test discovery`:
|
||||||
|
|
||||||
|
setuptools/distribute のテストコマンドとの組み合わせ
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Integration with setuptools/distribute test commands
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Distribute/Setuptools support test requirements,
|
||||||
|
which means its really easy to extend its test command
|
||||||
|
to support running a pytest from test requirements::
|
||||||
|
|
||||||
|
setuptools/distribute は、テストに必要なパッケージ要件から pytest を実行するテストコマンドをとても簡単に拡張できる tests_require に対応しています::
|
||||||
|
|
||||||
|
from setuptools.command.test import test as TestCommand
|
||||||
|
|
||||||
|
class PyTest(TestCommand):
|
||||||
|
def finalize_options(self):
|
||||||
|
TestCommand.finalize_options(self)
|
||||||
|
self.test_args = []
|
||||||
|
self.test_suite = True
|
||||||
|
def run_tests(self):
|
||||||
|
# 外部で egg を読み込ませたくないならここでインポートしてください
|
||||||
|
import pytest
|
||||||
|
pytest.main(self.test_args)
|
||||||
|
|
||||||
|
setup(
|
||||||
|
#...,
|
||||||
|
tests_require=['pytest'],
|
||||||
|
cmdclass = {'test': pytest},
|
||||||
|
)
|
||||||
|
|
||||||
|
..
|
||||||
|
Now if you run::
|
||||||
|
|
||||||
|
ここで次のように実行します::
|
||||||
|
|
||||||
|
python setup.py test
|
||||||
|
|
||||||
|
..
|
||||||
|
this will download py.test if needed and then run py.test
|
||||||
|
as you would expect it to.
|
||||||
|
|
||||||
|
必要に応じて py.test をダウンロードしてから、期待した通りに py.test を実行します。
|
||||||
|
|
||||||
|
..
|
||||||
|
Conventions for Python test discovery
|
||||||
|
-------------------------------------------------
|
||||||
|
|
||||||
|
Python テスト探索の規約
|
||||||
|
-----------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
``py.test`` implements the following standard test discovery:
|
||||||
|
|
||||||
|
``py.test`` は次のテスト探索標準を実装します:
|
||||||
|
|
||||||
|
..
|
||||||
|
* collection starts from the initial command line arguments
|
||||||
|
which may be directories, filenames or test ids.
|
||||||
|
* recurse into directories, unless they match :confval:`norecursedirs`
|
||||||
|
* ``test_*.py`` or ``*_test.py`` files, imported by their `package name`_.
|
||||||
|
* ``Test`` prefixed test classes (without an ``__init__`` method)
|
||||||
|
* ``test_`` prefixed test functions or methods are test items
|
||||||
|
|
||||||
|
* コレクションは、ディレクトリ、ファイル名、テスト ID といった最初に与えたコマンドライン引数から開始する
|
||||||
|
* :confval:`norecursedirs` に一致しない限り、ディレクトリを再帰的に探索する
|
||||||
|
* `package name`_ でインポートされる ``test_*.py`` または ``*_test.py`` ファイル
|
||||||
|
* ``Test`` という接頭辞をもつテストクラス (``__init__`` メソッドをもたない)
|
||||||
|
* ``test_`` という接頭辞をもつテスト関数やメソッドがテスト項目になる
|
||||||
|
|
||||||
|
..
|
||||||
|
For examples of how to customize your test discovery :doc:`example/pythoncollection`.
|
||||||
|
|
||||||
|
テスト探索をカスタマイズする方法の例は :doc:`example/pythoncollection` を参照してください。
|
||||||
|
|
||||||
|
..
|
||||||
|
Within Python modules, py.test also discovers tests using the standard
|
||||||
|
:ref:`unittest.TestCase <unittest.TestCase>` subclassing technique.
|
||||||
|
|
||||||
|
Python モジュール内では、py.test も標準ライブラリの :ref:`unittest.TestCase <unittest.TestCase>` のサブクラス化を使ってテストを探索します。
|
||||||
|
|
||||||
|
..
|
||||||
|
Choosing a test layout / import rules
|
||||||
|
------------------------------------------
|
||||||
|
|
||||||
|
テストレイアウト選択とインポートルール
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
py.test supports common test layouts:
|
||||||
|
|
||||||
|
py.test は一般的なテストレイアウトに対応しています:
|
||||||
|
|
||||||
|
..
|
||||||
|
* inlining test directories into your application package, useful if you want to
|
||||||
|
keep (unit) tests and actually tested code close together::
|
||||||
|
|
||||||
|
* アプリケーション内に test ディレクトリを配置しています。(ユニット) テストを保持して実際にテストされたコードを一緒にしておくのに役立ちます::
|
||||||
|
|
||||||
|
mypkg/
|
||||||
|
__init__.py
|
||||||
|
appmodule.py
|
||||||
|
...
|
||||||
|
test/
|
||||||
|
test_app.py
|
||||||
|
...
|
||||||
|
|
||||||
|
..
|
||||||
|
* putting tests into an extra directory outside your actual application
|
||||||
|
code, useful if you have many functional tests or want to keep
|
||||||
|
tests separate from actual application code::
|
||||||
|
|
||||||
|
* テストをアプリケーションコードの外部に配置しています。多くの機能テストがある、または実際のアプリケーションコードからテストを分離して保持したいときに役立ちます::
|
||||||
|
|
||||||
|
mypkg/
|
||||||
|
__init__.py
|
||||||
|
appmodule.py
|
||||||
|
tests/
|
||||||
|
test_app.py
|
||||||
|
...
|
||||||
|
|
||||||
|
..
|
||||||
|
In both cases you usually need to make sure that ``mypkg`` is importable,
|
||||||
|
for example by using the setuptools ``python setup.py develop`` method.
|
||||||
|
|
||||||
|
どちらの場合も、普通に ``mypkg`` がインポートできることを保証する必要があります。例えば、setuptools の ``python setup.py develop`` メソッドを使います。
|
||||||
|
|
||||||
|
..
|
||||||
|
You can run your tests by pointing to it::
|
||||||
|
|
||||||
|
次のようにテストを実行できます::
|
||||||
|
|
||||||
|
py.test tests/test_app.py # 外部のテストディレクトリ
|
||||||
|
py.test mypkg/test/test_app.py # 内部のテストディレクトリ
|
||||||
|
py.test mypkg # テストディレクトリ配下にある全てのテストを実行
|
||||||
|
py.test # カレントディテクリ配下にある全てのテストを実行
|
||||||
|
...
|
||||||
|
|
||||||
|
.. _`package name`:
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
py.test がファイルシステムを再帰的に辿って "a/b/test_module.py" テストファイルを検出する場合、インポート名を次のようにして決定します。
|
||||||
|
|
||||||
|
* ``basedir`` を検出する -- これは ``__init__.py`` を含まない最初の "upward" (ルートに向かう) ディレクトリです。 ``a`` と ``b`` のディレクトリ両方に ``__init__.py`` を含む場合、basedir は ``a`` の親ディレクトリになります
|
||||||
|
|
||||||
|
* テストモジュールを完全修飾インポート名でインポートできるようにするために ``sys.path.insert(0, basedir)`` を実行します
|
||||||
|
|
||||||
|
* パス区切り文字 ``/`` を "." に変換することで決まる ``import a.b.test_module`` を行う、つまりインポート名に直接ディレクトリやファイル名を対応付ける規約に従わないといけません
|
||||||
|
|
||||||
|
この少し進化したインポートテクニックを使う理由は、巨大なプロジェクトでは複数のテストモジュールがお互いにインポートする可能性があるからです。そして、このように導出されたインポート名の標準化は、テストモジュールを2回インポートしてしまって驚かないようにするのに役立ちます。
|
||||||
|
|
||||||
|
..
|
||||||
|
If py.test finds a "a/b/test_module.py" test file while
|
||||||
|
recursing into the filesystem it determines the import name
|
||||||
|
as follows:
|
||||||
|
|
||||||
|
* find ``basedir`` -- this is the first "upward" (towards the root)
|
||||||
|
directory not containing an ``__init__.py``. If both the ``a``
|
||||||
|
and ``b`` directories contain an ``__init__.py`` the basedir will
|
||||||
|
be the parent dir of ``a``.
|
||||||
|
|
||||||
|
* perform ``sys.path.insert(0, basedir)`` to make the test module
|
||||||
|
importable under the fully qualified import name.
|
||||||
|
|
||||||
|
* ``import a.b.test_module`` where the path is determined
|
||||||
|
by converting path separators ``/`` into "." characters. This means
|
||||||
|
you must follow the convention of having directory and file
|
||||||
|
names map directly to the import names.
|
||||||
|
|
||||||
|
The reason for this somewhat evolved importing technique is
|
||||||
|
that in larger projects multiple test modules might import
|
||||||
|
from each other and thus deriving a canonical import name helps
|
||||||
|
to avoid surprises such as a test modules getting imported twice.
|
||||||
|
|
||||||
|
.. include:: links.inc
|
Binary file not shown.
After Width: | Height: | Size: 8.1 KiB |
|
@ -0,0 +1,104 @@
|
||||||
|
|
||||||
|
..
|
||||||
|
Welcome to pytest!
|
||||||
|
=============================================
|
||||||
|
|
||||||
|
Pytest へようこそ!
|
||||||
|
===================
|
||||||
|
|
||||||
|
..
|
||||||
|
- **a mature full-featured testing tool**
|
||||||
|
- runs on Posix/Windows, Python 2.4-3.2, PyPy and Jython-2.5.1
|
||||||
|
- :ref:`comprehensive online <toc>` and `PDF documentation <pytest.pdf>`_
|
||||||
|
- continuously `tested on many Python interpreters <http://hudson.testrun.org/view/pytest/job/pytest/>`_
|
||||||
|
- used in :ref:`many projects and organisations <projects>`, in test
|
||||||
|
suites ranging from 10 to 10s of thousands of tests
|
||||||
|
- comes with many :ref:`tested examples <examples>`
|
||||||
|
- supports :ref:`good integration practises <goodpractises>`
|
||||||
|
|
||||||
|
- **長い間開発され、全ての機能を備えたテストツール**
|
||||||
|
|
||||||
|
- Posix/Windows, Python 2.4-3.2, PyPy, Jython 2.5.1 に対応
|
||||||
|
- :ref:`包括的なオンラインドキュメント <toc>` と `PDF ドキュメント <pytest.pdf>`_
|
||||||
|
- 継続的に `多くの Python インタープリターでテスト <http://hudson.testrun.org/view/pytest/job/pytest/>`_
|
||||||
|
- :ref:`様々なプロジェクトと組織 <projects>` の、数万もの幅広いテストスイートで利用
|
||||||
|
- 多くの :ref:`テストサンプル <examples>` が付属
|
||||||
|
- :ref:`優れたインテグレーションプラクティス <goodpractises>` に対応
|
||||||
|
|
||||||
|
..
|
||||||
|
- **provides no-boilerplate testing**
|
||||||
|
- makes it :ref:`easy to get started <getstarted>`,
|
||||||
|
- refined :ref:`usage options <usage>`
|
||||||
|
- :ref:`assert with the assert statement`
|
||||||
|
- helpful :ref:`traceback and failing assertion reporting <tbreportdemo>`
|
||||||
|
- allows :ref:`print debugging <printdebugging>` and :ref:`the
|
||||||
|
capturing of standard output during test execution <captures>`
|
||||||
|
- supports :pep:`8` compliant coding styles in tests
|
||||||
|
|
||||||
|
- **ボイラープレート (ひな形) のいらないテストを提供**
|
||||||
|
|
||||||
|
- :ref:`簡単に始められる <getstarted>`
|
||||||
|
- 洗練された :ref:`オプションの使い方 <usage>`
|
||||||
|
- :ref:`assert with the assert statement`
|
||||||
|
- 分かりやすい :ref:`トレースバックと失敗時のレポート <tbreportdemo>`
|
||||||
|
- :ref:`print デバッグ <printdebugging>` と :ref:`テスト実行時の標準出力のキャプチャ <captures>`
|
||||||
|
- テストのコーディングスタイルを :pep:`8` 準拠に対応
|
||||||
|
|
||||||
|
..
|
||||||
|
- **supports functional testing and complex test setups**
|
||||||
|
- (new in 2.2) :ref:`durations`
|
||||||
|
- (much improved in 2.2) :ref:`marking and test selection <mark>`
|
||||||
|
- (improved in 2.2) :ref:`parametrized test functions <parametrized test functions>`
|
||||||
|
- advanced :ref:`skip and xfail`
|
||||||
|
- unique :ref:`dependency injection through funcargs <funcargs>`
|
||||||
|
- can :ref:`distribute tests to multiple CPUs <xdistcpu>` through :ref:`xdist plugin <xdist>`
|
||||||
|
- can :ref:`continuously re-run failing tests <looponfailing>`
|
||||||
|
- many :ref:`builtin helpers <pytest helpers>`
|
||||||
|
- flexible :ref:`Python test discovery`
|
||||||
|
|
||||||
|
- **機能テストと複雑なテストのセットアップ**
|
||||||
|
|
||||||
|
- (2.2 の新機能) :ref:`durations`
|
||||||
|
- (2.2 でかなり改善) :ref:`マーキングとテスト選択 <mark>`
|
||||||
|
- (2.2 で改善) :ref:`パラメーターテスト機能 <parametrized test functions>`
|
||||||
|
- :ref:`skip and xfail`
|
||||||
|
- ユニークな :ref:`funcargs を用いた依存性の注入 <funcargs>`
|
||||||
|
- :ref:`xdist プラグイン <xdist>` を用いた :ref:`複数 CPU に対する分散テスト <xdistcpu>`
|
||||||
|
- :ref:`失敗するテストのみを継続的に再実行 <looponfailing>`
|
||||||
|
- 多くの :ref:`組み込みヘルパー機能 <pytest helpers>`
|
||||||
|
- 柔軟な :ref:`Python test discovery`
|
||||||
|
|
||||||
|
..
|
||||||
|
- **integrates many common testing methods**
|
||||||
|
- can integrate ``nose``, ``unittest.py`` and ``doctest.py`` style
|
||||||
|
tests, including running testcases made for Django and trial
|
||||||
|
- supports extended :ref:`xUnit style setup <xunitsetup>`
|
||||||
|
- supports domain-specific :ref:`non-python tests`
|
||||||
|
- supports the generation of testing coverage reports
|
||||||
|
- `Javascript unit- and functional testing`_
|
||||||
|
|
||||||
|
- **多くの共通テストメソッドを統合**
|
||||||
|
|
||||||
|
- ``nose``, ``unittest.py``, ``doctest.py`` スタイルのテスト、Django のテストランナー (試作段階)
|
||||||
|
- :ref:`xUnit スタイルの setup <xunitsetup>` の拡張
|
||||||
|
- ドメイン固有の :ref:`non-python tests`
|
||||||
|
- テストカバレッジレポートの生成
|
||||||
|
- `Javascript のユニット/機能テスト <Javascript unit- and functional testing>`_
|
||||||
|
|
||||||
|
..
|
||||||
|
- **extensive plugin and customization system**
|
||||||
|
- all collection, reporting, running aspects are delegated to hook functions
|
||||||
|
- customizations can be per-directory, per-project or per PyPI released plugins
|
||||||
|
- it is easy to add command line options or do other kind of add-ons and customizations.
|
||||||
|
|
||||||
|
- **豊富なプラグインとカスタマイズの仕組み**
|
||||||
|
|
||||||
|
- 全てのコレクション、レポート、実行状態をフック関数に委譲
|
||||||
|
- ディレクトリ単位、プロジェクト単位、PyPI でリリースされたプラグイン単位でのカスタマイズ
|
||||||
|
- コマンドラインオプションを追加したり、その他のアドオンやカスタマイズが簡単
|
||||||
|
|
||||||
|
.. _`Javascript unit- and functional testing`: http://pypi.python.org/pypi/oejskit
|
||||||
|
|
||||||
|
.. _`easy`: http://bruynooghe.blogspot.com/2009/12/skipping-slow-test-by-default-in-pytest.html
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
.. _`skipping plugin`: plugin/skipping.html
|
||||||
|
.. _`funcargs mechanism`: funcargs.html
|
||||||
|
.. _`doctest.py`: http://docs.python.org/library/doctest.html
|
||||||
|
.. _`xUnit style setup`: xunit_setup.html
|
||||||
|
.. _`pytest_nose`: plugin/nose.html
|
||||||
|
.. _`reStructured Text`: http://docutils.sourceforge.net
|
||||||
|
.. _`Python debugger`: http://docs.python.org/lib/module-pdb.html
|
||||||
|
.. _nose: http://somethingaboutorange.com/mrl/projects/nose/
|
||||||
|
.. _pytest: http://pypi.python.org/pypi/pytest
|
||||||
|
.. _mercurial: http://mercurial.selenic.com/wiki/
|
||||||
|
.. _`setuptools`: http://pypi.python.org/pypi/setuptools
|
||||||
|
.. _`easy_install`:
|
||||||
|
.. _`distribute docs`:
|
||||||
|
.. _`distribute`: http://pypi.python.org/pypi/distribute
|
||||||
|
.. _`pip`: http://pypi.python.org/pypi/pip
|
||||||
|
.. _`virtualenv`: http://pypi.python.org/pypi/virtualenv
|
||||||
|
.. _hudson: http://hudson-ci.org/
|
||||||
|
.. _jenkins: http://jenkins-ci.org/
|
||||||
|
.. _tox: http://codespeak.net/tox
|
|
@ -0,0 +1,53 @@
|
||||||
|
|
||||||
|
.. _mark:
|
||||||
|
|
||||||
|
属性をもつテスト関数のマーク
|
||||||
|
============================
|
||||||
|
|
||||||
|
..
|
||||||
|
Marking test functions with attributes
|
||||||
|
=================================================================
|
||||||
|
|
||||||
|
.. currentmodule:: _pytest.mark
|
||||||
|
|
||||||
|
..
|
||||||
|
By using the ``pytest.mark`` helper you can easily set
|
||||||
|
metadata on your test functions. There are
|
||||||
|
some builtin markers, for example:
|
||||||
|
|
||||||
|
``pytest.mark`` ヘルパーを使って、テスト関数にメタデータを簡単に設定できます。組み込みのマーカーを紹介します:
|
||||||
|
|
||||||
|
..
|
||||||
|
* :ref:`skipif <skipif>` - skip a test function if a certain condition is met
|
||||||
|
* :ref:`xfail <xfail>` - produce an "expected failure" outcome if a certain
|
||||||
|
condition is met
|
||||||
|
* :ref:`parametrize <parametrizemark>` to perform multiple calls
|
||||||
|
to the same test function.
|
||||||
|
|
||||||
|
* :ref:`skipif <skipif>`: 特定の条件を満たした場合にテスト関数をスキップ
|
||||||
|
* :ref:`xfail <xfail>`: 特定の条件を満たした場合に "失敗を期待"
|
||||||
|
* :ref:`parametrize <parametrizemark>`: 同じテスト関数に対して複数回の呼び出しを実行
|
||||||
|
|
||||||
|
..
|
||||||
|
It's easy to create custom markers or to apply markers
|
||||||
|
to whole test classes or modules. See :ref:`mark examples` for examples
|
||||||
|
which also serve as documentation.
|
||||||
|
|
||||||
|
カスタムマーカーを作成する、または全体のテストクラスやモジュールにマーカーを適用するのは簡単です。ドキュメントでもある :ref:`mark examples` のサンプルを参照してください。
|
||||||
|
|
||||||
|
..
|
||||||
|
API reference for mark related objects
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
マーカー関連オブジェクトの API リファレンス
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
.. autoclass:: MarkGenerator
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: MarkDecorator
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: MarkInfo
|
||||||
|
:members:
|
||||||
|
|
|
@ -0,0 +1,74 @@
|
||||||
|
|
||||||
|
..
|
||||||
|
Monkeypatching/mocking modules and environments
|
||||||
|
================================================================
|
||||||
|
|
||||||
|
モンキーパッチ/モックのモジュールと環境
|
||||||
|
========================================
|
||||||
|
|
||||||
|
.. currentmodule:: _pytest.monkeypatch
|
||||||
|
|
||||||
|
..
|
||||||
|
Sometimes tests need to invoke functionality which depends
|
||||||
|
on global settings or which invokes code which cannot be easily
|
||||||
|
tested such as network access. The ``monkeypatch`` function argument
|
||||||
|
helps you to safely set/delete an attribute, dictionary item or
|
||||||
|
environment variable or to modify ``sys.path`` for importing.
|
||||||
|
See the `monkeypatch blog post`_ for some introduction material
|
||||||
|
and a discussion of its motivation.
|
||||||
|
|
||||||
|
時々、グローバル設定に依存する機能のテストを実行する、またはネットワークアクセスを伴うような簡単にテストできないコードを実行する必要があります。 ``monkeypatch`` という関数の引数を使うことで、属性、ディクショナリの項目、環境変数、インポートのための ``sys.path`` の変更を安全に追加/削除するのを支援します。入門記事とその動機付けの議論は `monkeypatch のブログ記事`_ を参照してください。
|
||||||
|
|
||||||
|
.. _`monkeypatch blog post`: http://tetamap.wordpress.com/2009/03/03/monkeypatching-in-unit-tests-done-right/
|
||||||
|
.. _`monkeypatch のブログ記事`: http://tetamap.wordpress.com/2009/03/03/monkeypatching-in-unit-tests-done-right/
|
||||||
|
|
||||||
|
..
|
||||||
|
Simple example: monkeypatching functions
|
||||||
|
---------------------------------------------------
|
||||||
|
|
||||||
|
簡単な例: モンキーパッチ機能
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
If you want to pretend that ``os.expanduser`` returns a certain
|
||||||
|
directory, you can use the :py:meth:`monkeypatch.setattr` method to
|
||||||
|
patch this function before calling into a function which uses it::
|
||||||
|
|
||||||
|
``os.expanduser`` が特定のディレクトリを返すようにさせたい場合、関数内で ``os.expanduser`` が呼ばれる前にこの関数へパッチを当てるために :py:meth:`monkeypatch.setattr` メソッドが使えます::
|
||||||
|
|
||||||
|
# test_module.py の内容
|
||||||
|
import os.path
|
||||||
|
def getssh(): # 疑似アプリケーションコード
|
||||||
|
return os.path.join(os.path.expanduser("~admin"), '.ssh')
|
||||||
|
|
||||||
|
def test_mytest(monkeypatch):
|
||||||
|
def mockreturn(path):
|
||||||
|
return '/abc'
|
||||||
|
monkeypatch.setattr(os.path, 'expanduser', mockreturn)
|
||||||
|
x = getssh()
|
||||||
|
assert x == '/abc/.ssh'
|
||||||
|
|
||||||
|
..
|
||||||
|
Here our test function monkeypatches ``os.path.expanduser`` and
|
||||||
|
then calls into an function that calls it. After the test function
|
||||||
|
finishes the ``os.path.expanduser`` modification will be undone.
|
||||||
|
|
||||||
|
このテスト関数は ``os.path.expanduser`` にモンキーパッチを当てた後で、ある関数内からその関数が呼ばれます。このテスト関数が終了した後で ``os.path.expanduser`` に対する変更は元に戻ります。
|
||||||
|
|
||||||
|
..
|
||||||
|
Method reference of the monkeypatch function argument
|
||||||
|
-----------------------------------------------------
|
||||||
|
|
||||||
|
関数の引数 monkeypatch のメソッドリファレンス
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
.. autoclass:: monkeypatch
|
||||||
|
:members: setattr, delattr, setitem, delitem, setenv, delenv, syspath_prepend, chdir, undo
|
||||||
|
|
||||||
|
..
|
||||||
|
``monkeypatch.setattr/delattr/delitem/delenv()`` all
|
||||||
|
by default raise an Exception if the target does not exist.
|
||||||
|
Pass ``raising=False`` if you want to skip this check.
|
||||||
|
|
||||||
|
``monkeypatch.setattr/delattr/delitem/delenv()`` の全ての関数において、変更対象が存在しない場合にデフォルトで例外を発生させます。このチェック処理をスキップしたいなら ``raising=False`` を渡してください。
|
||||||
|
|
|
@ -0,0 +1,20 @@
|
||||||
|
|
||||||
|
.. _naming20:
|
||||||
|
|
||||||
|
New pytest names in 2.0 (flat is better than nested)
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
If you used older version of the ``py`` distribution (which
|
||||||
|
included the py.test command line tool and Python name space)
|
||||||
|
you accessed helpers and possibly collection classes through
|
||||||
|
the ``py.test`` Python namespaces. The new ``pytest``
|
||||||
|
Python module flaty provides the same objects, following
|
||||||
|
these renaming rules::
|
||||||
|
|
||||||
|
py.test.XYZ -> pytest.XYZ
|
||||||
|
py.test.collect.XYZ -> pytest.XYZ
|
||||||
|
py.test.cmdline.main -> pytest.main
|
||||||
|
|
||||||
|
The old ``py.test.*`` ways to access functionality remain
|
||||||
|
valid but you are encouraged to do global renaming according
|
||||||
|
to the above rules in your test code.
|
|
@ -0,0 +1,72 @@
|
||||||
|
..
|
||||||
|
Running tests written for nose
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
nose 向けに書かれたテストの実行
|
||||||
|
===============================
|
||||||
|
|
||||||
|
.. include:: links.inc
|
||||||
|
|
||||||
|
..
|
||||||
|
py.test has basic support for running tests written for nose_.
|
||||||
|
|
||||||
|
py.test は、基本的には nose_ 向けに書かれたテストの実行に対応しています。
|
||||||
|
|
||||||
|
..
|
||||||
|
Usage
|
||||||
|
-------------
|
||||||
|
|
||||||
|
使用方法
|
||||||
|
--------
|
||||||
|
|
||||||
|
..
|
||||||
|
type::
|
||||||
|
|
||||||
|
単純に::
|
||||||
|
|
||||||
|
py.test # 'nosetests' の代わりに実行
|
||||||
|
|
||||||
|
..
|
||||||
|
and you should be able to run your nose style tests and
|
||||||
|
make use of py.test's capabilities.
|
||||||
|
|
||||||
|
を実行します。pytest の機能を使って nose スタイルのテストを実行できます。
|
||||||
|
|
||||||
|
..
|
||||||
|
Supported nose Idioms
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
対応している nose イディオム
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
* setup and teardown at module/class/method level
|
||||||
|
* SkipTest exceptions and markers
|
||||||
|
* setup/teardown decorators
|
||||||
|
* yield-based tests and their setup
|
||||||
|
* general usage of nose utilities
|
||||||
|
|
||||||
|
* モジュール/クラス/メソッドレベルの setup と teardown
|
||||||
|
* SkipTest 例外とマーカー
|
||||||
|
* setup/teardown デコレーター
|
||||||
|
* yield ベースのテストとそのセットアップ
|
||||||
|
* nose ユーティリティの一般的な使用方法
|
||||||
|
|
||||||
|
..
|
||||||
|
Unsupported idioms / known issues
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
対応していないイディオムと既知の課題
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
- nose-style doctests are not collected and executed correctly,
|
||||||
|
also doctest fixtures don't work.
|
||||||
|
|
||||||
|
- nose スタイルの doctest は探索されず、正常に実行されません、また doctest フィクスチャも動作しません
|
||||||
|
|
||||||
|
..
|
||||||
|
- no nose-configuration is recognized
|
||||||
|
|
||||||
|
- nose 設定は認識されません
|
||||||
|
|
|
@ -0,0 +1,19 @@
|
||||||
|
..
|
||||||
|
==================================================
|
||||||
|
Getting started basics
|
||||||
|
==================================================
|
||||||
|
|
||||||
|
================
|
||||||
|
基本から始めよう
|
||||||
|
================
|
||||||
|
|
||||||
|
.. toctree::
|
||||||
|
:maxdepth: 2
|
||||||
|
|
||||||
|
index.txt
|
||||||
|
getting-started.txt
|
||||||
|
usage.txt
|
||||||
|
goodpractises.txt
|
||||||
|
projects.txt
|
||||||
|
faq.txt
|
||||||
|
|
|
@ -0,0 +1,564 @@
|
||||||
|
.. _plugins:
|
||||||
|
|
||||||
|
プラグインと conftest ファイルの連携
|
||||||
|
====================================
|
||||||
|
|
||||||
|
..
|
||||||
|
Working with plugins and conftest files
|
||||||
|
=============================================
|
||||||
|
|
||||||
|
..
|
||||||
|
py.test implements all aspects of configuration, collection, running and reporting by calling `well specified hooks`_. Virtually any Python module can be registered as a plugin. It can implement any number of hook functions (usually two or three) which all have a ``pytest_`` prefix, making hook functions easy to distinguish and find. There are three basic locations types:
|
||||||
|
|
||||||
|
py.test は :ref:`よく練られたフック <well specified hooks>` を呼び出すことにより、設定、コレクション、実行、レポートの全箇所で処理を実装します。事実上、任意の Python モジュールをプラグインとして登録できます。このプラグインは、フック関数の区別や検出を容易にして ``pytest_`` という接頭辞をもつ全フック関数から任意のフック関数 (通常は2つか3つ) を実装します。3つの基本的な配置場所があります:
|
||||||
|
|
||||||
|
..
|
||||||
|
* `builtin plugins`_: loaded from py.test's own ``pytest/plugin`` directory.
|
||||||
|
* `external plugins`_: modules discovered through `setuptools entry points`_
|
||||||
|
* `conftest.py plugins`_: modules auto-discovered in test directories
|
||||||
|
|
||||||
|
* :ref:`組み込みプラグイン <builtin plugins>`: py.test がもつ ``pytest/plugin`` ディレクトリから読み込む
|
||||||
|
* :ref:`外部プラグイン <external plugins>`: :ref:`setuptools のエントリーポイント <setuptools entry points>` からモジュールを検出
|
||||||
|
* :ref:`conftest.py プラグイン <conftest.py plugins>`: テストディレクトリから自動的にモジュールを検出
|
||||||
|
|
||||||
|
.. _`pytest/plugin`: http://bitbucket.org/hpk42/pytest/src/tip/pytest/plugin/
|
||||||
|
.. _`conftest.py plugins`:
|
||||||
|
.. _`conftest.py`:
|
||||||
|
.. _`localplugin`:
|
||||||
|
.. _`conftest`:
|
||||||
|
|
||||||
|
conftest.py: ディレクトリ毎のローカルプラグイン
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
conftest.py: local per-directory plugins
|
||||||
|
--------------------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
local ``conftest.py`` plugins contain directory-specific hook
|
||||||
|
implementations. Session and test running activities will
|
||||||
|
invoke all hooks defined in ``conftest.py`` files closer to the
|
||||||
|
root of the filesystem. Example: Assume the following layout
|
||||||
|
and content of files::
|
||||||
|
|
||||||
|
ローカルの ``conftest.py`` プラグインは、ディレクトリ固有のフック実装を含みます。セッションとテストの実行処理は、ファイルシステムのルートディレクトリに近い ``conftest.py`` ファイルで定義された全てのフックを実行します。ファイルを次の場所に置くと仮定してください::
|
||||||
|
|
||||||
|
a/conftest.py:
|
||||||
|
def pytest_runtest_setup(item):
|
||||||
|
# 'a' ディレクトリにある各テストの実行向けに呼ばれる
|
||||||
|
print ("setting up", item)
|
||||||
|
|
||||||
|
a/test_in_subdir.py:
|
||||||
|
def test_sub():
|
||||||
|
pass
|
||||||
|
|
||||||
|
test_flat.py:
|
||||||
|
def test_flat():
|
||||||
|
pass
|
||||||
|
|
||||||
|
..
|
||||||
|
Here is how you might run it::
|
||||||
|
|
||||||
|
このコードの実行方法です::
|
||||||
|
|
||||||
|
py.test test_flat.py # "setting up" を表示しない
|
||||||
|
py.test a/test_sub.py # "setting up" を表示
|
||||||
|
|
||||||
|
.. Note::
|
||||||
|
|
||||||
|
..
|
||||||
|
If you have ``conftest.py`` files which do not reside in a
|
||||||
|
python package directory (i.e. one containing an ``__init__.py``) then
|
||||||
|
"import conftest" can be ambiguous because there might be other
|
||||||
|
``conftest.py`` files as well on your PYTHONPATH or ``sys.path``.
|
||||||
|
It is thus good practise for projects to either put ``conftest.py``
|
||||||
|
under a package scope or to never import anything from a
|
||||||
|
conftest.py file.
|
||||||
|
|
||||||
|
Python パッケージディレクトリ (例えば ``__Init__.py`` を含むディレクトリ) に置かれてない ``conftest.py`` ファイルがある場合、PYTHONPATH または ``sys.path`` に同じ名前をもつ別の ``conftest.py`` ファイルを置く可能性があり、"import conftest" が曖昧になるときがあります。こういったプロジェクトでは、パッケージスコープの中で ``conftest.py`` を置くか ``conftest.py`` ファイルから決してインポートしないかのどちらか一方を選択するのが良いプラクティスです。
|
||||||
|
|
||||||
|
.. _`external plugins`:
|
||||||
|
.. _`extplugins`:
|
||||||
|
|
||||||
|
外部プラグインのインストールと探索
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Installing External Plugins / Searching
|
||||||
|
------------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Installing a plugin happens through any usual Python installation
|
||||||
|
tool, for example::
|
||||||
|
|
||||||
|
プラグインのインストールは、普通の Python インストールツールを使って行います。例えば::
|
||||||
|
|
||||||
|
pip install pytest-NAME
|
||||||
|
pip uninstall pytest-NAME
|
||||||
|
|
||||||
|
..
|
||||||
|
If a plugin is installed, py.test automatically finds and integrates it,
|
||||||
|
there is no need to activate it. Here is a list of known plugins:
|
||||||
|
|
||||||
|
プラグインがインストール済みなら、py.test が自動的に検出してそのプラグインを組み込みます。プラグインを有効化する必要はありません。既知のプラグイン一覧を紹介します:
|
||||||
|
|
||||||
|
..
|
||||||
|
* `pytest-capturelog <http://pypi.python.org/pypi/pytest-capturelog>`_:
|
||||||
|
to capture and assert about messages from the logging module
|
||||||
|
|
||||||
|
* `pytest-capturelog <http://pypi.python.org/pypi/pytest-capturelog>`_: logging モジュールからのメッセージに関するアサートやキャプチャ
|
||||||
|
|
||||||
|
..
|
||||||
|
* `pytest-xdist <http://pypi.python.org/pypi/pytest-xdist>`_:
|
||||||
|
to distribute tests to CPUs and remote hosts, looponfailing mode,
|
||||||
|
see also :ref:`xdist`
|
||||||
|
|
||||||
|
* `pytest-xdist <http://pypi.python.org/pypi/pytest-xdist>`_: CPU やリモートホストを使った分散テスト、 :ref:`xdist` を参照
|
||||||
|
|
||||||
|
..
|
||||||
|
* `pytest-cov <http://pypi.python.org/pypi/pytest-cov>`_:
|
||||||
|
coverage reporting, compatible with distributed testing
|
||||||
|
|
||||||
|
* `pytest-cov <http://pypi.python.org/pypi/pytest-cov>`_: 分散テストでの互換性やカバレッジレポート
|
||||||
|
|
||||||
|
..
|
||||||
|
* `pytest-pep8 <http://pypi.python.org/pypi/pytest-pep8>`_:
|
||||||
|
a ``--pep8`` option to enable PEP8 compliance checking.
|
||||||
|
|
||||||
|
* `pytest-pep8 <http://pypi.python.org/pypi/pytest-pep8>`_: ``--pep8`` オプションを使った PEP8 規約チェック
|
||||||
|
|
||||||
|
..
|
||||||
|
* `oejskit <http://pypi.python.org/pypi/oejskit>`_:
|
||||||
|
a plugin to run javascript unittests in life browsers
|
||||||
|
(**version 0.8.9 not compatible with pytest-2.0**)
|
||||||
|
|
||||||
|
* `oejskit <http://pypi.python.org/pypi/oejskit>`_: 実際のブラウザーで javascript の unittests を実行するプラグイン (**バージョン 0.8.9 は pytest-2.0 では互換性がありません** )
|
||||||
|
|
||||||
|
..
|
||||||
|
You may discover more plugins through a `pytest- pypi.python.org search`_.
|
||||||
|
|
||||||
|
`"pytest-" で pypi.python.org を検索`_ すると、もっとプラグインが見つかるでしょう。
|
||||||
|
|
||||||
|
.. _`available installable plugins`:
|
||||||
|
.. _`pytest- pypi.python.org search`: http://pypi.python.org/pypi?%3Aaction=search&term=pytest-&submit=search
|
||||||
|
.. _`"pytest-" で pypi.python.org を検索`: http://pypi.python.org/pypi?%3Aaction=search&term=pytest-&submit=search
|
||||||
|
|
||||||
|
サンプルによるプラグインの記述
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Writing a plugin by looking at examples
|
||||||
|
------------------------------------------------------
|
||||||
|
|
||||||
|
.. _`Distribute`: http://pypi.python.org/pypi/distribute
|
||||||
|
.. _`setuptools`: http://pypi.python.org/pypi/setuptools
|
||||||
|
|
||||||
|
..
|
||||||
|
If you want to write a plugin, there are many real-life examples
|
||||||
|
you can copy from:
|
||||||
|
|
||||||
|
自分でプラグインを作成したいなら、たくさんある実際のプラグインをコピーしてから始めると良いです:
|
||||||
|
|
||||||
|
..
|
||||||
|
* a custom collection example plugin: :ref:`yaml plugin`
|
||||||
|
* around 20 `builtin plugins`_ which comprise py.test's own functionality
|
||||||
|
* around 10 `external plugins`_ providing additional features
|
||||||
|
|
||||||
|
* カスタムコレクションのサンプルプラグイン: :ref:`yaml プラグイン <yaml plugin>`
|
||||||
|
* py.test の独自機能を構成する約20個の :ref:`組み込みプラグイン <builtin plugins>`
|
||||||
|
* 追加機能を提供する約10個の :ref:`外部プラグイン <external plugins>`
|
||||||
|
|
||||||
|
..
|
||||||
|
All of these plugins implement the documented `well specified hooks`_
|
||||||
|
to extend and add functionality.
|
||||||
|
|
||||||
|
これらの全プラグインは、機能を追加/拡張するためにドキュメント付きの :ref:`よく練られたフック <well specified hooks>` を実装します。
|
||||||
|
|
||||||
|
.. _`setuptools entry points`:
|
||||||
|
|
||||||
|
独自プラグインを他からインストール可能にする
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Making your plugin installable by others
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
If you want to make your plugin externally available, you
|
||||||
|
may define a so-called entry point for your distribution so
|
||||||
|
that ``py.test`` finds your plugin module. Entry points are
|
||||||
|
a feature that is provided by `setuptools`_ or `Distribute`_.
|
||||||
|
py.test looks up the ``pytest11`` entrypoint to discover its
|
||||||
|
plugins and you can thus make your plugin available by definig
|
||||||
|
it in your setuptools/distribute-based setup-invocation:
|
||||||
|
|
||||||
|
自分で作成したプラグインを外部から利用できるようにしたいなら、 ``py.test`` がプラグインモジュールを見つけられるように、ディストリビューションのいわゆるエントリーポイントを定義します。エントリーポイントは `setuptools`_ または `distribute`_ が提供する機能です。py.test は、プラグインを検出するために ``pytest11`` というエントリーポイントを調べます。このように setuptools/distribute の setup 処理でエントリーポイントを定義することにより、自分のプラグインを利用できます。
|
||||||
|
|
||||||
|
.. sourcecode:: python
|
||||||
|
|
||||||
|
# サンプルの ./setup.py ファイル
|
||||||
|
from setuptools import setup
|
||||||
|
|
||||||
|
setup(
|
||||||
|
name="myproject",
|
||||||
|
packages = ['myproject']
|
||||||
|
|
||||||
|
# 次のように記述して py.test からプラグインを利用可能にする
|
||||||
|
entry_points = {
|
||||||
|
'pytest11': [
|
||||||
|
'name_of_plugin = myproject.pluginmodule',
|
||||||
|
]
|
||||||
|
},
|
||||||
|
)
|
||||||
|
|
||||||
|
..
|
||||||
|
If a package is installed this way, py.test will load
|
||||||
|
``myproject.pluginmodule`` as a plugin which can define
|
||||||
|
`well specified hooks`_.
|
||||||
|
|
||||||
|
パッケージがこの方法でインストールされる場合、py.test は :ref:`よく練られたフック <well specified hooks>` を定義するプラグインとして ``myproject.pluginmodule`` を読み込みます。
|
||||||
|
|
||||||
|
..
|
||||||
|
Plugin discovery order at tool startup
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
ツール起動時のプラグイン検出順序
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
py.test loads plugin modules at tool startup in the following way:
|
||||||
|
|
||||||
|
py.test は、次の方法でツール起動時にプラグインモジュールを読み込みます。
|
||||||
|
|
||||||
|
..
|
||||||
|
* by loading all builtin plugins
|
||||||
|
|
||||||
|
* 全ての組み込みプラグインを読み込む。
|
||||||
|
|
||||||
|
..
|
||||||
|
* by loading all plugins registered through `setuptools entry points`_.
|
||||||
|
|
||||||
|
* :ref:`setuptools のエントリーポイント <setuptools entry points>` から登録された全てのプラグインを読み込む。
|
||||||
|
|
||||||
|
..
|
||||||
|
* by pre-scanning the command line for the ``-p name`` option
|
||||||
|
and loading the specified plugin before actual command line parsing.
|
||||||
|
|
||||||
|
* コマンドラインの ``-p name`` オプションを事前に調べ、実際にコマンドラインの引数解析を行う前に指定したプラグインを読み込む。
|
||||||
|
|
||||||
|
..
|
||||||
|
* by loading all :file:`conftest.py` files as inferred by the command line
|
||||||
|
invocation (test files and all of its *parent* directories).
|
||||||
|
Note that ``conftest.py`` files from *sub* directories are by default
|
||||||
|
not loaded at tool startup.
|
||||||
|
|
||||||
|
* コマンドラインの実行で推定される全ての :file:`conftest.py` ファイルを読み込む (テストファイルと全ての *親* ディレクトリ) 。 *サブ* ディレクトリからの ``conftest.py`` ファイルは、デフォルトでは、ツールの起動時に読み込まれないことに注意してください。
|
||||||
|
|
||||||
|
..
|
||||||
|
* by recursively loading all plugins specified by the
|
||||||
|
``pytest_plugins`` variable in ``conftest.py`` files
|
||||||
|
|
||||||
|
* ``conftest.py`` ファイルの ``pytest_plugins`` 変数で指定された全てのプラグインを再帰的に読み込む
|
||||||
|
|
||||||
|
テストモジュールまたは conftest ファイルのプラグインの要求と読み込み
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Requiring/Loading plugins in a test module or conftest file
|
||||||
|
-------------------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
You can require plugins in a test module or a conftest file like this::
|
||||||
|
|
||||||
|
テストモジュール、または conftest ファイル内でプラグインを要求できます::
|
||||||
|
|
||||||
|
pytest_plugins = "name1", "name2",
|
||||||
|
|
||||||
|
..
|
||||||
|
When the test module or conftest plugin is loaded the specified plugins
|
||||||
|
will be loaded as well. You can also use dotted path like this::
|
||||||
|
|
||||||
|
テストモジュール、または conftest プラグインが読み込まれるとき、指定したプラグインも同様に読み込まれます。さらに次のようにドット区切りのパスも使えます::
|
||||||
|
|
||||||
|
pytest_plugins = "myapp.testsupport.myplugin"
|
||||||
|
|
||||||
|
..
|
||||||
|
which will import the specified module as a py.test plugin.
|
||||||
|
|
||||||
|
これは py.test プラグインとして指定したモジュールをインポートします。
|
||||||
|
|
||||||
|
..
|
||||||
|
Accessing another plugin by name
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
プラグイン名で別のプラグインへアクセス
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
If a plugin wants to collaborate with code from
|
||||||
|
another plugin it can obtain a reference through
|
||||||
|
the plugin manager like this:
|
||||||
|
|
||||||
|
あるプラグインと別のプラグインのコードを協調させたいなら、次のようにプラグインマネージャーを使ってリファレンスを取得できます:
|
||||||
|
|
||||||
|
.. sourcecode:: python
|
||||||
|
|
||||||
|
plugin = config.pluginmanager.getplugin("name_of_plugin")
|
||||||
|
|
||||||
|
..
|
||||||
|
If you want to look at the names of existing plugins, use
|
||||||
|
the ``--traceconfig`` option.
|
||||||
|
|
||||||
|
既存のプラグイン名を調べたい場合は ``--traceconfig`` オプションを使ってください。
|
||||||
|
|
||||||
|
.. _`findpluginname`:
|
||||||
|
|
||||||
|
有効なプラグインの検出
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Finding out which plugins are active
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
If you want to find out which plugins are active in your
|
||||||
|
environment you can type::
|
||||||
|
|
||||||
|
自分の環境で有効なプラグインを調べたいなら、次のように実行してください::
|
||||||
|
|
||||||
|
py.test --traceconfig
|
||||||
|
|
||||||
|
..
|
||||||
|
and will get an extended test header which shows activated plugins
|
||||||
|
and their names. It will also print local plugins aka
|
||||||
|
:ref:`conftest.py <conftest>` files when they are loaded.
|
||||||
|
|
||||||
|
有効なプラグインとその名前を表示する拡張テストヘッダーを取得します。 :ref:`conftest.py <conftest>` が読み込まれるときにそのローカルプラグインも表示します。
|
||||||
|
|
||||||
|
.. _`cmdunregister`:
|
||||||
|
|
||||||
|
名前からプラグインの無効化や登録解除
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Deactivating / unregistering a plugin by name
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
You can prevent plugins from loading or unregister them::
|
||||||
|
|
||||||
|
プラグインを読み込ませない、または登録を解除できます::
|
||||||
|
|
||||||
|
py.test -p no:NAME
|
||||||
|
|
||||||
|
..
|
||||||
|
This means that any subsequent try to activate/load the named
|
||||||
|
plugin will it already existing. See :ref:`findpluginname` for
|
||||||
|
how to obtain the name of a plugin.
|
||||||
|
|
||||||
|
このオプションは、有効化/読み込もうとするプラグインが既に存在するものとして扱います。プラグイン名を取得する方法は :ref:`findpluginname` を参照してください。
|
||||||
|
|
||||||
|
.. _`builtin plugins`:
|
||||||
|
|
||||||
|
py.test のデフォルトのプラグインリファレンス
|
||||||
|
============================================
|
||||||
|
|
||||||
|
..
|
||||||
|
py.test default plugin reference
|
||||||
|
====================================
|
||||||
|
|
||||||
|
..
|
||||||
|
You can find the source code for the following plugins
|
||||||
|
in the `pytest repository <http://bitbucket.org/hpk42/pytest/>`_.
|
||||||
|
|
||||||
|
次のプラグインのソースコードが `pytest リポジトリ <http://bitbucket.org/hpk42/pytest/>`_ に含まれています。
|
||||||
|
|
||||||
|
.. autosummary::
|
||||||
|
|
||||||
|
_pytest.assertion
|
||||||
|
_pytest.capture
|
||||||
|
_pytest.config
|
||||||
|
_pytest.doctest
|
||||||
|
_pytest.genscript
|
||||||
|
_pytest.helpconfig
|
||||||
|
_pytest.junitxml
|
||||||
|
_pytest.mark
|
||||||
|
_pytest.monkeypatch
|
||||||
|
_pytest.nose
|
||||||
|
_pytest.pastebin
|
||||||
|
_pytest.pdb
|
||||||
|
_pytest.pytester
|
||||||
|
_pytest.python
|
||||||
|
_pytest.recwarn
|
||||||
|
_pytest.resultlog
|
||||||
|
_pytest.runner
|
||||||
|
_pytest.main
|
||||||
|
_pytest.skipping
|
||||||
|
_pytest.terminal
|
||||||
|
_pytest.tmpdir
|
||||||
|
_pytest.unittest
|
||||||
|
|
||||||
|
.. _`well specified hooks`:
|
||||||
|
|
||||||
|
py.test のフックリファレンス
|
||||||
|
============================
|
||||||
|
|
||||||
|
..
|
||||||
|
py.test hook reference
|
||||||
|
====================================
|
||||||
|
|
||||||
|
..
|
||||||
|
Hook specification and validation
|
||||||
|
-----------------------------------------
|
||||||
|
|
||||||
|
フックの仕様と検証
|
||||||
|
------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
py.test calls hook functions to implement initialization, running,
|
||||||
|
test execution and reporting. When py.test loads a plugin it validates
|
||||||
|
that each hook function conforms to its respective hook specification.
|
||||||
|
Each hook function name and its argument names need to match a hook
|
||||||
|
specification. However, a hook function may accept *fewer* parameters
|
||||||
|
by simply not specifying them. If you mistype argument names or the
|
||||||
|
hook name itself you get an error showing the available arguments.
|
||||||
|
|
||||||
|
py.test は、初期化、テスト実行、レポートを実装するフック関数を呼び出します。py.test がプラグインを読み込むとき、各フック関数名はその対応するフック仕様を確認します。各フック関数名とその引数の名前は、フック仕様に一致する必要があります。但し、フック関数を単に指定しないことにより *少ない* パラメーターは許容します。引数の名前やフック名そのものを誤入力した場合、利用できる引数を表示するエラーが表示されます。
|
||||||
|
|
||||||
|
..
|
||||||
|
Initialization, command line and configuration hooks
|
||||||
|
--------------------------------------------------------------------
|
||||||
|
|
||||||
|
初期化、コマンドライン、設定のフック
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
.. currentmodule:: _pytest.hookspec
|
||||||
|
|
||||||
|
.. autofunction:: pytest_cmdline_preparse
|
||||||
|
.. autofunction:: pytest_cmdline_parse
|
||||||
|
.. autofunction:: pytest_namespace
|
||||||
|
.. autofunction:: pytest_addoption
|
||||||
|
.. autofunction:: pytest_cmdline_main
|
||||||
|
.. autofunction:: pytest_configure
|
||||||
|
.. autofunction:: pytest_unconfigure
|
||||||
|
|
||||||
|
..
|
||||||
|
Generic "runtest" hooks
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
汎用的な "runtest" フック
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
All all runtest related hooks receive a :py:class:`pytest.Item` object.
|
||||||
|
|
||||||
|
フックに関連する全ての runtest は :py:class:`pytest.Item` オブジェクトを受け取ります。
|
||||||
|
|
||||||
|
.. autofunction:: pytest_runtest_protocol
|
||||||
|
.. autofunction:: pytest_runtest_setup
|
||||||
|
.. autofunction:: pytest_runtest_call
|
||||||
|
.. autofunction:: pytest_runtest_teardown
|
||||||
|
.. autofunction:: pytest_runtest_makereport
|
||||||
|
|
||||||
|
..
|
||||||
|
For deeper understanding you may look at the default implementation of
|
||||||
|
these hooks in :py:mod:`_pytest.runner` and maybe also
|
||||||
|
in :py:mod:`_pytest.pdb` which interacts with :py:mod:`_pytest.capture`
|
||||||
|
and its input/output capturing in order to immediately drop
|
||||||
|
into interactive debugging when a test failure occurs.
|
||||||
|
|
||||||
|
より深く理解するには :py:mod:`_pytest.runner` の実際のフックのデフォルト実装を調べることになるかもしれません。さらに、テストが失敗したときにそのまま対話式のデバッガーに入る、その入出力のキャプチャや :py:mod:`_pytest.capture` と相互にやり取りする :py:mod:`_pytest.pdb` もきっと見たくなるでしょう。
|
||||||
|
|
||||||
|
..
|
||||||
|
The :py:mod:`_pytest.terminal` reported specifically uses
|
||||||
|
the reporting hook to print information about a test run.
|
||||||
|
|
||||||
|
実際にレポートを行う :py:mod:`_pytest.terminal` は、テスト実行に関する情報を表示するためにレポートフックを使います。
|
||||||
|
|
||||||
|
..
|
||||||
|
Collection hooks
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
コレクションのフック
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
py.test calls the following hooks for collecting files and directories:
|
||||||
|
|
||||||
|
py.test はファイルとディレクトリを探索するために次のフックを呼び出します:
|
||||||
|
|
||||||
|
.. autofunction:: pytest_ignore_collect
|
||||||
|
.. autofunction:: pytest_collect_directory
|
||||||
|
.. autofunction:: pytest_collect_file
|
||||||
|
|
||||||
|
..
|
||||||
|
For influencing the collection of objects in Python modules
|
||||||
|
you can use the following hook:
|
||||||
|
|
||||||
|
Python モジュール内のオブジェクトのコレクションに影響を与えるには、次のフックが使えます:
|
||||||
|
|
||||||
|
.. autofunction:: pytest_pycollect_makeitem
|
||||||
|
|
||||||
|
..
|
||||||
|
Reporting hooks
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
レポートフック
|
||||||
|
--------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Session related reporting hooks:
|
||||||
|
|
||||||
|
レポートフックに関連するセッション:
|
||||||
|
|
||||||
|
.. autofunction:: pytest_collectstart
|
||||||
|
.. autofunction:: pytest_itemcollected
|
||||||
|
.. autofunction:: pytest_collectreport
|
||||||
|
.. autofunction:: pytest_deselected
|
||||||
|
|
||||||
|
..
|
||||||
|
And here is the central hook for reporting about
|
||||||
|
test execution:
|
||||||
|
|
||||||
|
そして、テストの実行に関する中央のフックです:
|
||||||
|
|
||||||
|
.. autofunction:: pytest_runtest_logreport
|
||||||
|
|
||||||
|
..
|
||||||
|
Reference of important objects involved in hooks
|
||||||
|
===========================================================
|
||||||
|
|
||||||
|
フックで実行される重要なオブジェクトのリファレンス
|
||||||
|
==================================================
|
||||||
|
|
||||||
|
.. autoclass:: _pytest.config.Config
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: _pytest.config.Parser
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: _pytest.main.Node(name, parent)
|
||||||
|
:members:
|
||||||
|
|
||||||
|
..
|
||||||
|
.. autoclass:: _pytest.main.File(fspath, parent)
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: _pytest.main.Item(name, parent)
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: _pytest.python.Module(name, parent)
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: _pytest.python.Class(name, parent)
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: _pytest.python.Function(name, parent)
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: _pytest.runner.CallInfo
|
||||||
|
:members:
|
||||||
|
|
||||||
|
.. autoclass:: _pytest.runner.TestReport
|
||||||
|
:members:
|
||||||
|
|
|
@ -0,0 +1,112 @@
|
||||||
|
.. _projects:
|
||||||
|
|
||||||
|
プロジェクトの例
|
||||||
|
================
|
||||||
|
|
||||||
|
..
|
||||||
|
Project examples
|
||||||
|
==========================
|
||||||
|
|
||||||
|
..
|
||||||
|
Here are some examples of projects using py.test (please send notes via :ref:`contact`):
|
||||||
|
|
||||||
|
py.test を使っているプロジェクトを紹介します (:ref:`contact` を通してメモを送ってください):
|
||||||
|
|
||||||
|
..
|
||||||
|
* `PyPy <http://pypy.org>`_, Python with a JIT compiler, running over
|
||||||
|
`16000 tests <http://buildbot.pypy.org/summary?branch=%3Ctrunk%3E>`_
|
||||||
|
* the `MoinMoin <http://moinmo.in>`_ Wiki Engine
|
||||||
|
* `tox <http://codespeak.net/tox>`_, virtualenv/Hudson integration tool
|
||||||
|
* `PIDA <http://pida.co.uk>`_ framework for integrated development
|
||||||
|
* `PyPM <http://code.activestate.com/pypm/>`_ ActiveState's package manager
|
||||||
|
* `Fom <http://packages.python.org/Fom/>`_ a fluid object mapper for FluidDB
|
||||||
|
* `applib <https://github.com/ActiveState/applib>`_ cross-platform utilities
|
||||||
|
* `six <http://pypi.python.org/pypi/six/>`_ Python 2 and 3 compatibility utilities
|
||||||
|
* `pediapress <http://code.pediapress.com/wiki/wiki>`_ MediaWiki articles
|
||||||
|
* `mwlib <http://pypi.python.org/pypi/mwlib>`_ mediawiki parser and utility library
|
||||||
|
* `The Translate Toolkit <http://translate.sourceforge.net/wiki/toolkit/index>`_ for localization and conversion
|
||||||
|
* `execnet <http://codespeak.net/execnet>`_ rapid multi-Python deployment
|
||||||
|
* `pylib <http://pylib.org>`_ cross-platform path, IO, dynamic code library
|
||||||
|
* `Pacha <http://pacha.cafepais.com/>`_ configuration management in five minutes
|
||||||
|
* `bbfreeze <http://pypi.python.org/pypi/bbfreeze>`_ create standalone executables from Python scripts
|
||||||
|
* `pdb++ <http://bitbucket.org/antocuni/pdb>`_ a fancier version of PDB
|
||||||
|
* `py-s3fuse <http://code.google.com/p/py-s3fuse/>`_ Amazon S3 FUSE based filesystem
|
||||||
|
* `waskr <http://pacha.cafepais.com/>`_ WSGI Stats Middleware
|
||||||
|
* `guachi <http://code.google.com/p/guachi/>`_ global persistent configs for Python modules
|
||||||
|
* `Circuits <http://pypi.python.org/pypi/circuits>`_ lightweight Event Driven Framework
|
||||||
|
* `pygtk-helpers <http://bitbucket.org/aafshar/pygtkhelpers-main/>`_ easy interaction with PyGTK
|
||||||
|
* `QuantumCore <http://quantumcore.org/>`_ statusmessage and repoze openid plugin
|
||||||
|
* `pydataportability <http://pydataportability.net/>`_ libraries for managing the open web
|
||||||
|
* `XIST <http://www.livinglogic.de/Python/xist/>`_ extensible HTML/XML generator
|
||||||
|
* `tiddlyweb <http://pypi.python.org/pypi/tiddlyweb>`_ optionally headless, extensible RESTful datastore
|
||||||
|
* `fancycompleter <http://bitbucket.org/antocuni/fancycompleter/src>`_ for colorful tab-completion
|
||||||
|
* `Paludis <http://paludis-tools.lunaryorn.de/>`_ tools for Gentoo Paludis package manager
|
||||||
|
* `Gerald <http://halfcooked.com/code/gerald/>`_ schema comparison tool
|
||||||
|
* `abjad <http://code.google.com/p/abjad/>`_ Python API for Formalized Score control
|
||||||
|
* `bu <http://packages.python.org/bu/>`_ a microscopic build system
|
||||||
|
* `katcp <https://bitbucket.org/hodgestar/katcp>`_ Telescope communication protocol over Twisted
|
||||||
|
* `kss plugin timer <http://pypi.python.org/pypi/kss.plugin.timer>`_
|
||||||
|
|
||||||
|
* `PyPy <http://pypy.org>`_: JIT コンパイラーを備えた Python、 `16000 テスト <http://buildbot.pypy.org/summary?branch=%3Ctrunk%3E>`_ 以上を実行
|
||||||
|
* `MoinMoin <http://moinmo.in>`_: Wiki エンジン
|
||||||
|
* `tox <http://codespeak.net/tox>`_: virtualenv/Jenkins インテグレーションツール
|
||||||
|
* `PIDA <http://pida.co.uk>`_: 統合開発フレームワーク
|
||||||
|
* `PyPM <http://code.activestate.com/pypm/>`_: Activestate 社のパッケージマネージャー
|
||||||
|
* `Fom <http://packages.python.org/Fom/>`_: FluidDB の fluid オブジェクトマッパー
|
||||||
|
* `applib <https://github.com/ActiveState/applib>`_: クロスプラットフォームユーティリティ
|
||||||
|
* `six <http://pypi.python.org/pypi/six/>`_: Python 2 と 3 の互換ユーティリティ
|
||||||
|
* `pediapress <http://code.pediapress.com/wiki/wiki>`_: MediaWiki の記事
|
||||||
|
* `mwlib <http://pypi.python.org/pypi/mwlib>`_: mediawiki のパーサーとユーティリティライブラリ
|
||||||
|
* `The Translate Toolkit <http://translate.sourceforge.net/wiki/toolkit/index>`_: ローカライズと変換
|
||||||
|
* `execnet <http://codespeak.net/execnet>`_: 高速な multi-Python デプロイ
|
||||||
|
* `pylib <http://pylib.org>`_: クロスプラットフォームのパス、IO、動的コードライブラリ
|
||||||
|
* `Pacha <http://pacha.cafepais.com/>`_: 5分でできる構成管理
|
||||||
|
* `bbfreeze <http://pypi.python.org/pypi/bbfreeze>`_: Python スクリプトから単独で実行できる実行可能ファイルの作成
|
||||||
|
* `pdb++ <http://bitbucket.org/antocuni/pdb>`_: PDB の手の込んだバージョン
|
||||||
|
* `py-s3fuse <http://code.google.com/p/py-s3fuse/>`_: Amazon S3 FUSE ベースのファイルシステム
|
||||||
|
* `waskr <http://pacha.cafepais.com/>`_: WSGI 統計ミドルウェア
|
||||||
|
* `guachi <http://code.google.com/p/guachi/>`_: Python モジュールのグローバルな永続的設定
|
||||||
|
* `Circuits <http://pypi.python.org/pypi/circuits>`_: 軽量のイベント駆動型フレームワーク
|
||||||
|
* `pygtk-helpers <http://bitbucket.org/aafshar/pygtkhelpers-main/>`_: PyGTK による簡単操作
|
||||||
|
* `QuantumCore <http://quantumcore.org/>`_: statusmessage と repoze の openid プラグイン
|
||||||
|
* `pydataportability <http://pydataportability.net/>`_: open web を管理するためのライブラリ
|
||||||
|
* `XIST <http://www.livinglogic.de/Python/xist/>`_: 拡張可能な HTML/XML ジェネレーター
|
||||||
|
* `tiddlyweb <http://pypi.python.org/pypi/tiddlyweb>`_: ヘッドレスを選択できる拡張可能な RESTful データストア
|
||||||
|
* `fancycompleter <http://bitbucket.org/antocuni/fancycompleter/src>`_: カラフルなタブ補完
|
||||||
|
* `Paludis <http://paludis-tools.lunaryorn.de/>`_: Gentoo Paludis パッケージマネージャーツール
|
||||||
|
* `Gerald <http://halfcooked.com/code/gerald/>`_: スキーマ比較ツール
|
||||||
|
* `abjad <http://code.google.com/p/abjad/>`_: Formalized Score 制御のための Python API
|
||||||
|
* `bu <http://packages.python.org/bu/>`_: 微小ビルドシステム
|
||||||
|
* `katcp <https://bitbucket.org/hodgestar/katcp>`_: Twisted 上の Telescope 通信プロトコル
|
||||||
|
* `kss plugin timer <http://pypi.python.org/pypi/kss.plugin.timer>`_
|
||||||
|
|
||||||
|
..
|
||||||
|
Some organisations using py.test
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
py.test を使っている組織
|
||||||
|
------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
* `Square Kilometre Array, Cape Town <http://ska.ac.za/>`_
|
||||||
|
* `Some Mozilla QA people <http://www.theautomatedtester.co.uk/blog/2011/pytest_and_xdist_plugin.html>`_ use pytest to distribute their Selenium tests
|
||||||
|
* `Tandberg <http://www.tandberg.com/>`_
|
||||||
|
* `Shootq <http://web.shootq.com/>`_
|
||||||
|
* `Stups department of Heinrich Heine University Duesseldorf <http://www.stups.uni-duesseldorf.de/projects.php>`_
|
||||||
|
* `cellzome <http://www.cellzome.com/>`_
|
||||||
|
* `Open End, Gothenborg <http://www.openend.se>`_
|
||||||
|
* `Laboraratory of Bioinformatics, Warsaw <http://genesilico.pl/>`_
|
||||||
|
* `merlinux, Germany <http://merlinux.eu>`_
|
||||||
|
* many more ... (please be so kind to send a note via :ref:`contact`)
|
||||||
|
|
||||||
|
* `Square Kilometre Array, Cape Town <http://ska.ac.za/>`_
|
||||||
|
* `Some Mozilla QA people <http://www.theautomatedtester.co.uk/blog/2011/pytest_and_xdist_plugin.html>`_: Selenium テストを配布するために pytest を使用
|
||||||
|
* `Tandberg <http://www.tandberg.com/>`_
|
||||||
|
* `Shootq <http://web.shootq.com/>`_
|
||||||
|
* `Stups department of Heinrich Heine University Duesseldorf <http://www.stups.uni-duesseldorf.de/projects.php>`_
|
||||||
|
* `cellzome <http://www.cellzome.com/>`_
|
||||||
|
* `Open End, Gothenborg <http://www.openend.se>`_
|
||||||
|
* `Laboraratory of Bioinformatics, Warsaw <http://genesilico.pl/>`_
|
||||||
|
* `merlinux, Germany <http://merlinux.eu>`_
|
||||||
|
* さらにたくさん ... (:ref:`contact` を通してメモを送ってください)
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
[pytest]
|
||||||
|
# just defined to prevent the root level tox.ini from kicking in
|
|
@ -0,0 +1,62 @@
|
||||||
|
|
||||||
|
..
|
||||||
|
Asserting deprecation and other warnings
|
||||||
|
=====================================================
|
||||||
|
|
||||||
|
非推奨の警告やその他の警告のアサート
|
||||||
|
====================================
|
||||||
|
|
||||||
|
..
|
||||||
|
The recwarn function argument
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
関数の引数 recwarn
|
||||||
|
------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
You can use the ``recwarn`` funcarg to assert that code triggers
|
||||||
|
warnings through the Python warnings system. Here is a simple
|
||||||
|
self-contained test::
|
||||||
|
|
||||||
|
Python のワーニングシステムからの警告を受け取るコードをアサートするために ``recwarn`` という関数の引数が使えます。簡単な自己完結型のテストを紹介します::
|
||||||
|
|
||||||
|
# test_recwarn.py の内容
|
||||||
|
def test_hello(recwarn):
|
||||||
|
from warnings import warn
|
||||||
|
warn("hello", DeprecationWarning)
|
||||||
|
w = recwarn.pop(DeprecationWarning)
|
||||||
|
assert issubclass(w.category, DeprecationWarning)
|
||||||
|
assert 'hello' in str(w.message)
|
||||||
|
assert w.filename
|
||||||
|
assert w.lineno
|
||||||
|
|
||||||
|
..
|
||||||
|
The ``recwarn`` function argument provides these methods:
|
||||||
|
|
||||||
|
関数の引数 ``recwarn`` は次のメソッドを提供します:
|
||||||
|
|
||||||
|
..
|
||||||
|
* ``pop(category=None)``: return last warning matching the category.
|
||||||
|
* ``clear()``: clear list of warnings
|
||||||
|
|
||||||
|
* ``pop(category=None)``: カテゴリに一致する最後の警告を返す
|
||||||
|
* ``clear()``: 警告の一覧をクリアする
|
||||||
|
|
||||||
|
..
|
||||||
|
Ensuring a function triggers a deprecation warning
|
||||||
|
-------------------------------------------------------
|
||||||
|
|
||||||
|
非推奨の警告を発生させる関数の確認
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
You can also call a global helper for checking
|
||||||
|
that a certain function call triggers a Deprecation
|
||||||
|
warning::
|
||||||
|
|
||||||
|
非推奨の警告を発生させる特定の関数呼び出しを確認するためのグローバルなヘルパー関数も呼び出せます::
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
|
||||||
|
def test_global():
|
||||||
|
pytest.deprecated_call(myfunction, 17)
|
|
@ -0,0 +1,327 @@
|
||||||
|
.. _`skip and xfail`:
|
||||||
|
|
||||||
|
skip と xfail: 成功しないテストを扱う
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
..
|
||||||
|
Skip and xfail: dealing with tests that can not succeed
|
||||||
|
=====================================================================
|
||||||
|
|
||||||
|
..
|
||||||
|
If you have test functions that cannot be run on certain platforms
|
||||||
|
or that you expect to fail you can mark them accordingly or you
|
||||||
|
may call helper functions during execution of setup or test functions.
|
||||||
|
|
||||||
|
テスト関数が、特定のプラットフォームで実行できない、またはマークしたものが失敗することを期待する、またはテスト関数や setup 関数の実行中にヘルパー関数を呼び出すといった場合があります。
|
||||||
|
|
||||||
|
..
|
||||||
|
A *skip* means that you expect your test to pass unless a certain
|
||||||
|
configuration or condition (e.g. wrong Python interpreter, missing
|
||||||
|
dependency) prevents it to run. And *xfail* means that your test
|
||||||
|
can run but you expect it to fail because there is an implementation problem.
|
||||||
|
|
||||||
|
*skip* は、特定の設定や条件 (誤った Python インタープリターや依存関係の欠落など) がテスト関数を実行させない場合を除けば、テストが成功するのを期待します。 *xfail* は、テストそのものは実行しますが、実装上の問題からそのテストが失敗することを期待します。
|
||||||
|
|
||||||
|
..
|
||||||
|
py.test counts and lists *skip* and *xfail* tests separately. However,
|
||||||
|
detailed information about skipped/xfailed tests is not shown by default
|
||||||
|
to avoid cluttering the output. You can use the ``-r`` option to see
|
||||||
|
details corresponding to the "short" letters shown in the test
|
||||||
|
progress::
|
||||||
|
|
||||||
|
py.test は *skip* と *xfail* テストを別々に数えて一覧表示します。しかし、スキップした/失敗したテストテストについての詳細な情報は、出力内容がごちゃごちゃにならないようにデフォルトでは表示されません。テストの進捗状況を表示する "短い" 文字に対応する詳細を見るために ``-r`` オプションが使えます::
|
||||||
|
|
||||||
|
py.test -rxs # skips と xfails の補足情報を表示
|
||||||
|
|
||||||
|
..
|
||||||
|
(See :ref:`how to change command line options defaults`)
|
||||||
|
|
||||||
|
(:ref:`how to change command line options defaults` を参照)
|
||||||
|
|
||||||
|
.. _skipif:
|
||||||
|
|
||||||
|
スキップするテスト関数のマーク
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Marking a test function to be skipped
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Here is an example of marking a test function to be skipped
|
||||||
|
when run on a Python3 interpreter::
|
||||||
|
|
||||||
|
Python 3 インタープリターで実行するときにスキップするテスト関数をマークする例を紹介します::
|
||||||
|
|
||||||
|
import sys
|
||||||
|
@pytest.mark.skipif("sys.version_info >= (3,0)")
|
||||||
|
def test_function():
|
||||||
|
...
|
||||||
|
|
||||||
|
..
|
||||||
|
During test function setup the skipif condition is
|
||||||
|
evaluated by calling ``eval('sys.version_info >= (3,0)', namespace)``.
|
||||||
|
(*New in version 2.0.2*) The namespace contains all the module globals of the test function so that
|
||||||
|
you can for example check for versions of a module you are using::
|
||||||
|
|
||||||
|
テスト関数の setup 処理中に skipif の条件が ``eval('sys.version_info >= (3,0)', namespace)`` を呼び出すことにより評価されます (*バージョン 2.0.2 で追加*) 。その名前空間は、例えば使っているモジュールのバージョンをチェックできるように、テスト関数の全モジュールの globals を含みます::
|
||||||
|
|
||||||
|
import mymodule
|
||||||
|
|
||||||
|
@pytest.mark.skipif("mymodule.__version__ < '1.2'")
|
||||||
|
def test_function():
|
||||||
|
...
|
||||||
|
|
||||||
|
..
|
||||||
|
The test function will not be run ("skipped") if
|
||||||
|
``mymodule`` is below the specified version. The reason
|
||||||
|
for specifying the condition as a string is mainly that
|
||||||
|
py.test can report a summary of skip conditions.
|
||||||
|
For information on the construction of the ``namespace``
|
||||||
|
see `evaluation of skipif/xfail conditions`_.
|
||||||
|
|
||||||
|
このテスト関数は、 ``mymodule`` が指定したバージョンより低いときには実行されません ("スキップされる") 。こういった条件を文字列で指定する主な理由は、py.test が skip 条件の概要をレポートできるからです。 ``namespace`` の構築に関する詳細は :ref:`evaluation of skipif/xfail conditions` を参照してください。
|
||||||
|
|
||||||
|
..
|
||||||
|
You can of course create a shortcut for your conditional skip
|
||||||
|
decorator at module level like this::
|
||||||
|
|
||||||
|
次のようにモジュールレベルで条件付きの skipif デコレーターのショートカットも作成できます::
|
||||||
|
|
||||||
|
win32only = pytest.mark.skipif("sys.platform != 'win32'")
|
||||||
|
|
||||||
|
@win32only
|
||||||
|
def test_function():
|
||||||
|
...
|
||||||
|
|
||||||
|
..
|
||||||
|
Skip all test functions of a class
|
||||||
|
--------------------------------------
|
||||||
|
|
||||||
|
クラスの全テスト関数のスキップ
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
As with all function :ref:`marking <mark>` you can skip test functions at the
|
||||||
|
`whole class- or module level`_. Here is an example
|
||||||
|
for skipping all methods of a test class based on the platform::
|
||||||
|
|
||||||
|
全ての関数を :ref:`マークする <mark>` のと同様に `クラス全体またはモジュールレベル`_ でテスト関数をスキップできます。プラットフォームによりテストクラスの全メソッドをスキップするサンプルを紹介します::
|
||||||
|
|
||||||
|
class TestPosixCalls:
|
||||||
|
pytestmark = pytest.mark.skipif("sys.platform == 'win32'")
|
||||||
|
|
||||||
|
def test_function(self):
|
||||||
|
"will not be setup or run under 'win32' platform"
|
||||||
|
|
||||||
|
..
|
||||||
|
The ``pytestmark`` special name tells py.test to apply it to each test
|
||||||
|
function in the class. If your code targets python2.6 or above you can
|
||||||
|
more naturally use the skipif decorator (and any other marker) on
|
||||||
|
classes::
|
||||||
|
|
||||||
|
``pytestmark`` という特別な名前を使って、クラス内の各テスト関数へセットした関数を pytest に適用させます。テストコードが Python 2.6 以上を想定しているなら、もっと自然に skipif デコレーター (その他の任意のマーカー) をクラスに対して適用できます::
|
||||||
|
|
||||||
|
@pytest.mark.skipif("sys.platform == 'win32'")
|
||||||
|
class TestPosixCalls:
|
||||||
|
|
||||||
|
def test_function(self):
|
||||||
|
"will not be setup or run under 'win32' platform"
|
||||||
|
|
||||||
|
..
|
||||||
|
Using multiple "skipif" decorators on a single function is generally fine - it means that if any of the conditions apply the function execution will be skipped.
|
||||||
|
|
||||||
|
1つの関数に複数の "skipif" デコレーターを使うことは一般的に良いことです。いずれかの条件が適用された場合にそのテスト関数の実行はスキップされることになります。
|
||||||
|
|
||||||
|
.. _`whole class- or module level`: mark.html#scoped-marking
|
||||||
|
.. _`クラス全体またはモジュールレベル`: mark.html#scoped-marking
|
||||||
|
|
||||||
|
.. _xfail:
|
||||||
|
|
||||||
|
失敗を期待するテスト関数のマーク
|
||||||
|
--------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Mark a test function as expected to fail
|
||||||
|
-------------------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
You can use the ``xfail`` marker to indicate that you
|
||||||
|
expect the test to fail::
|
||||||
|
|
||||||
|
テストの失敗を期待していることを表すのに ``xfail`` マーカーを使います::
|
||||||
|
|
||||||
|
@pytest.mark.xfail
|
||||||
|
def test_function():
|
||||||
|
...
|
||||||
|
|
||||||
|
..
|
||||||
|
This test will be run but no traceback will be reported
|
||||||
|
when it fails. Instead terminal reporting will list it in the
|
||||||
|
"expected to fail" or "unexpectedly passing" sections.
|
||||||
|
|
||||||
|
このテストは実行されますが、失敗するときにトレースバックを表示しません。その代わり、ターミナル上に "expected to fail" か "unexpectedly passing" セクションにその一覧が表示されます。
|
||||||
|
|
||||||
|
..
|
||||||
|
By specifying on the commandline::
|
||||||
|
|
||||||
|
コマンドラインで次のように指定すると::
|
||||||
|
|
||||||
|
pytest --runxfail
|
||||||
|
|
||||||
|
..
|
||||||
|
you can force the running and reporting of an ``xfail`` marked test
|
||||||
|
as if it weren't marked at all.
|
||||||
|
|
||||||
|
``xfail`` でマークされていないかのように ``xfail`` でマークされたテスト関数を実行してレポートの表示を強制できます。
|
||||||
|
|
||||||
|
..
|
||||||
|
As with skipif_ you can also mark your expectation of a failure
|
||||||
|
on a particular platform::
|
||||||
|
|
||||||
|
skipif_ と同様に、特定のプラットフォームでの失敗を期待するようにもマークできます::
|
||||||
|
|
||||||
|
@pytest.mark.xfail("sys.version_info >= (3,0)")
|
||||||
|
def test_function():
|
||||||
|
...
|
||||||
|
|
||||||
|
..
|
||||||
|
You can furthermore prevent the running of an "xfail" test or
|
||||||
|
specify a reason such as a bug ID or similar. Here is
|
||||||
|
a simple test file with the several usages:
|
||||||
|
|
||||||
|
さらに、バグ ID といった reason を指定して "xfail" テストを実行しないようにもできます。他にも使用例と簡単なテストを紹介します:
|
||||||
|
|
||||||
|
.. literalinclude:: example/xfail_demo.py
|
||||||
|
|
||||||
|
..
|
||||||
|
Running it with the report-on-xfail option gives this output::
|
||||||
|
|
||||||
|
次のように xfail のレポートを表示するオプションを指定して実行します::
|
||||||
|
|
||||||
|
example $ py.test -rx xfail_demo.py
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 6 items
|
||||||
|
|
||||||
|
xfail_demo.py xxxxxx
|
||||||
|
========================= short test summary info ==========================
|
||||||
|
XFAIL xfail_demo.py::test_hello
|
||||||
|
XFAIL xfail_demo.py::test_hello2
|
||||||
|
reason: [NOTRUN]
|
||||||
|
XFAIL xfail_demo.py::test_hello3
|
||||||
|
condition: hasattr(os, 'sep')
|
||||||
|
XFAIL xfail_demo.py::test_hello4
|
||||||
|
bug 110
|
||||||
|
XFAIL xfail_demo.py::test_hello5
|
||||||
|
condition: pytest.__version__[0] != "17"
|
||||||
|
XFAIL xfail_demo.py::test_hello6
|
||||||
|
reason: reason
|
||||||
|
|
||||||
|
======================== 6 xfailed in 0.03 seconds =========================
|
||||||
|
|
||||||
|
.. _`evaluation of skipif/xfail conditions`:
|
||||||
|
|
||||||
|
skipif/xfail 式の評価
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Evaluation of skipif/xfail expressions
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
.. versionadded:: 2.0.2
|
||||||
|
|
||||||
|
..
|
||||||
|
The evaluation of a condition string in ``pytest.mark.skipif(conditionstring)``
|
||||||
|
or ``pytest.mark.xfail(conditionstring)`` takes place in a namespace
|
||||||
|
dictionary which is constructed as follows:
|
||||||
|
|
||||||
|
``pytest.mark.skipif(conditionstring)`` または ``pytest.mark.xfail(conditionstring)`` の条件文字列の評価は、次のように構築された名前空間ディクショナリの中で行われます:
|
||||||
|
|
||||||
|
..
|
||||||
|
* the namespace is initialized by putting the ``sys`` and ``os`` modules
|
||||||
|
and the pytest ``config`` object into it.
|
||||||
|
|
||||||
|
* ``sys`` と ``os`` モジュールと pytest の ``config`` オブジェクトを加えて名前空間が初期化される
|
||||||
|
|
||||||
|
..
|
||||||
|
* updated with the module globals of the test function for which the
|
||||||
|
expression is applied.
|
||||||
|
|
||||||
|
* その式の評価を適用するテスト関数のモジュールの globals が更新される
|
||||||
|
|
||||||
|
..
|
||||||
|
The pytest ``config`` object allows you to skip based on a test configuration value
|
||||||
|
which you might have added::
|
||||||
|
|
||||||
|
pytest の ``config`` オブジェクトを使って、追加したテスト設定値によりスキップさせます::
|
||||||
|
|
||||||
|
@pytest.mark.skipif("not config.getvalue('db')")
|
||||||
|
def test_function(...):
|
||||||
|
...
|
||||||
|
|
||||||
|
..
|
||||||
|
Imperative xfail from within a test or setup function
|
||||||
|
------------------------------------------------------
|
||||||
|
|
||||||
|
テスト関数または setup 関数内から命令型 xfail
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
If you cannot declare xfail-conditions at import time
|
||||||
|
you can also imperatively produce an XFail-outcome from
|
||||||
|
within test or setup code. Example::
|
||||||
|
|
||||||
|
インポート時に xfail の条件を宣言できない場合、テスト関数または setup コード内から xfail するように命令的に記述できます。サンプルを紹介します::
|
||||||
|
|
||||||
|
def test_function():
|
||||||
|
if not valid_config():
|
||||||
|
pytest.xfail("unsupported configuration")
|
||||||
|
|
||||||
|
..
|
||||||
|
Skipping on a missing import dependency
|
||||||
|
--------------------------------------------------
|
||||||
|
|
||||||
|
インポートの依存関係の欠落をスキップ
|
||||||
|
------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
You can use the following import helper at module level
|
||||||
|
or within a test or test setup function::
|
||||||
|
|
||||||
|
モジュールレベル、またはテスト関数や setup 関数内から次のインポートヘルパーが使えます::
|
||||||
|
|
||||||
|
docutils = pytest.importorskip("docutils")
|
||||||
|
|
||||||
|
..
|
||||||
|
If ``docutils`` cannot be imported here, this will lead to a
|
||||||
|
skip outcome of the test. You can also skip based on the
|
||||||
|
version number of a library::
|
||||||
|
|
||||||
|
もし ``docutils`` がこの場所でインポートできないなら、このテストはスキップされます。ライブラリのバージョンによりスキップさせることもできます::
|
||||||
|
|
||||||
|
docutils = pytest.importorskip("docutils", minversion="0.3")
|
||||||
|
|
||||||
|
..
|
||||||
|
The version will be read from the specified module's ``__version__`` attribute.
|
||||||
|
|
||||||
|
このバージョンは指定したモジュールの ``__ version__`` 属性から読み込まれます。
|
||||||
|
|
||||||
|
..
|
||||||
|
Imperative skip from within a test or setup function
|
||||||
|
------------------------------------------------------
|
||||||
|
|
||||||
|
テスト関数または setup 関数内から命令型スキップ
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
If for some reason you cannot declare skip-conditions
|
||||||
|
you can also imperatively produce a skip-outcome from
|
||||||
|
within test or setup code. Example::
|
||||||
|
|
||||||
|
何らかの理由でスキップ条件を宣言できない場合も、テスト関数または setup コード内からスキップするように命令的に記述できます。サンプルを紹介します::
|
||||||
|
|
||||||
|
def test_function():
|
||||||
|
if not valid_config():
|
||||||
|
pytest.skip("unsupported configuration")
|
||||||
|
|
|
@ -0,0 +1,143 @@
|
||||||
|
|
||||||
|
..
|
||||||
|
Talks and Tutorials
|
||||||
|
==========================
|
||||||
|
|
||||||
|
講演とチュートリアル
|
||||||
|
====================
|
||||||
|
|
||||||
|
.. _`funcargs`: funcargs.html
|
||||||
|
|
||||||
|
チュートリアルやブログ記事
|
||||||
|
--------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Tutorial examples and blog postings
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
.. _`tutorial1 repository`: http://bitbucket.org/hpk42/pytest-tutorial1/
|
||||||
|
.. _`pycon 2010 tutorial PDF`: http://bitbucket.org/hpk42/pytest-tutorial1/raw/tip/pytest-basic.pdf
|
||||||
|
|
||||||
|
..
|
||||||
|
Basic usage and funcargs:
|
||||||
|
|
||||||
|
基本的な使用方法と関数の引数 (funcarg):
|
||||||
|
|
||||||
|
..
|
||||||
|
- `pycon 2010 tutorial PDF`_ and `tutorial1 repository`_
|
||||||
|
|
||||||
|
- `pycon 2010 tutorial PDF`_ と `tutorial1 repository`_
|
||||||
|
|
||||||
|
..
|
||||||
|
Function arguments:
|
||||||
|
|
||||||
|
関数の引数:
|
||||||
|
|
||||||
|
- :ref:`mysetup`
|
||||||
|
- `application setup in test functions with funcargs`_
|
||||||
|
|
||||||
|
..
|
||||||
|
- `monkey patching done right`_ (blog post, consult `monkeypatch
|
||||||
|
plugin`_ for actual 1.0 API)
|
||||||
|
|
||||||
|
- `monkey patching done right`_ (ブログ記事、実際の 1.0 API は `monkeypatch plugin`_ を参照)
|
||||||
|
|
||||||
|
..
|
||||||
|
Test parametrization:
|
||||||
|
|
||||||
|
パラメーターテスト:
|
||||||
|
|
||||||
|
..
|
||||||
|
- `generating parametrized tests with funcargs`_ (uses deprecated ``addcall()`` API.
|
||||||
|
- `test generators and cached setup`_
|
||||||
|
- `parametrizing tests, generalized`_ (blog post)
|
||||||
|
- `putting test-hooks into local or global plugins`_ (blog post)
|
||||||
|
|
||||||
|
- `generating parametrized tests with funcargs`_ (非推奨 ``addcall()`` API を使用)
|
||||||
|
- `test generators and cached setup`_
|
||||||
|
- `parametrizing tests, generalized`_ (ブログ記事)
|
||||||
|
- `putting test-hooks into local or global plugins`_ (ブログ記事)
|
||||||
|
|
||||||
|
..
|
||||||
|
Assertion introspection:
|
||||||
|
|
||||||
|
アサートイントロスペクション:
|
||||||
|
|
||||||
|
- `(07/2011) Behind the scenes of py.test's new assertion rewriting
|
||||||
|
<http://pybites.blogspot.com/2011/07/behind-scenes-of-pytests-new-assertion.html>`_
|
||||||
|
|
||||||
|
..
|
||||||
|
Distributed testing:
|
||||||
|
|
||||||
|
分散テスト:
|
||||||
|
|
||||||
|
..
|
||||||
|
- `simultaneously test your code on all platforms`_ (blog entry)
|
||||||
|
|
||||||
|
- `simultaneously test your code on all platforms`_ (ブログ記事)
|
||||||
|
|
||||||
|
..
|
||||||
|
Plugin specific examples:
|
||||||
|
|
||||||
|
プラグインに特化した例:
|
||||||
|
|
||||||
|
..
|
||||||
|
- `skipping slow tests by default in py.test`_ (blog entry)
|
||||||
|
|
||||||
|
- `skipping slow tests by default in py.test`_ (ブログ記事)
|
||||||
|
|
||||||
|
- `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
|
||||||
|
.. _`many examples in the docs for plugins`: plugin/index.html
|
||||||
|
.. _`monkeypatch plugin`: plugin/monkeypatch.html
|
||||||
|
.. _`application setup in test functions with funcargs`: funcargs.html#appsetup
|
||||||
|
.. _`simultaneously test your code on all platforms`: http://tetamap.wordpress.com/2009/03/23/new-simultanously-test-your-code-on-all-platforms/
|
||||||
|
.. _`monkey patching done right`: http://tetamap.wordpress.com/2009/03/03/monkeypatching-in-unit-tests-done-right/
|
||||||
|
.. _`putting test-hooks into local or global plugins`: http://tetamap.wordpress.com/2009/05/14/putting-test-hooks-into-local-and-global-plugins/
|
||||||
|
.. _`parametrizing tests, generalized`: http://tetamap.wordpress.com/2009/05/13/parametrizing-python-tests-generalized/
|
||||||
|
.. _`generating parametrized tests with funcargs`: funcargs.html#test-generators
|
||||||
|
.. _`test generators and cached setup`: http://bruynooghe.blogspot.com/2010/06/pytest-test-generators-and-cached-setup.html
|
||||||
|
|
||||||
|
..
|
||||||
|
Conference talks and tutorials
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
カンファレンス講演とチュートリアル
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
- `ep2009-rapidtesting.pdf`_ tutorial slides (July 2009):
|
||||||
|
- testing terminology
|
||||||
|
- basic py.test usage, file system layout
|
||||||
|
- test function arguments (funcargs_) and test fixtures
|
||||||
|
- existing plugins
|
||||||
|
- distributed testing
|
||||||
|
|
||||||
|
- `ep2009-rapidtesting.pdf`_ チュートリアルのスライド (2009年7月):
|
||||||
|
|
||||||
|
- テストの専門用語
|
||||||
|
- 基本的な py.test 使用方法、ファイルシステムの配置
|
||||||
|
- テスト関数の引数 (funcargs_) とテストフィクスチャ
|
||||||
|
- 既存のプラグイン
|
||||||
|
- 分散テスト
|
||||||
|
|
||||||
|
..
|
||||||
|
- `ep2009-pytest.pdf`_ 60 minute py.test talk, highlighting unique features and a roadmap (July 2009)
|
||||||
|
|
||||||
|
- `ep2009-pytest.pdf`_: 60分の py.test 講演、独特の機能やロードマップを強調して説明 (2009年7月)
|
||||||
|
|
||||||
|
..
|
||||||
|
- `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`_: スライドとファイル、py.test 入門の拡張バージョン、より多くのオプションの議論、古いスタイル xUnit setup の導入、looponfailing とその他の機能
|
||||||
|
|
||||||
|
..
|
||||||
|
- `pycon2009-pytest-advanced.pdf`_ contain a slightly older version of funcargs and distributed testing, compared to the EuroPython 2009 slides.
|
||||||
|
|
||||||
|
- `pycon2009-pytest-advanced.pdf`_: EuroPython 2009 のスライドと比較して、ちょっと古いバージョンの funcargs や分散テストを含む
|
||||||
|
|
||||||
|
.. _`ep2009-rapidtesting.pdf`: http://codespeak.net/download/py/ep2009-rapidtesting.pdf
|
||||||
|
.. _`ep2009-pytest.pdf`: http://codespeak.net/download/py/ep2009-pytest.pdf
|
||||||
|
.. _`pycon2009-pytest-introduction.zip`: http://codespeak.net/download/py/pycon2009-pytest-introduction.zip
|
||||||
|
.. _`pycon2009-pytest-advanced.pdf`: http://codespeak.net/download/py/pycon2009-pytest-advanced.pdf
|
|
@ -0,0 +1,117 @@
|
||||||
|
===============================================
|
||||||
|
ATTIC documentation
|
||||||
|
===============================================
|
||||||
|
|
||||||
|
XXX REVIEW and remove the below XXX
|
||||||
|
|
||||||
|
Customizing the testing process
|
||||||
|
===============================
|
||||||
|
|
||||||
|
writing conftest.py files
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
You may put conftest.py files containing project-specific
|
||||||
|
configuration in your project's root directory, it's usually
|
||||||
|
best to put it just into the same directory level as your
|
||||||
|
topmost ``__init__.py``. In fact, ``py.test`` performs
|
||||||
|
an "upwards" search starting from the directory that you specify
|
||||||
|
to be tested and will lookup configuration values right-to-left.
|
||||||
|
You may have options that reside e.g. in your home directory
|
||||||
|
but note that project specific settings will be considered
|
||||||
|
first. There is a flag that helps you debugging your
|
||||||
|
conftest.py configurations::
|
||||||
|
|
||||||
|
py.test --traceconfig
|
||||||
|
|
||||||
|
|
||||||
|
customizing the collecting and running process
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
To introduce different test items you can create
|
||||||
|
one or more ``conftest.py`` files in your project.
|
||||||
|
When the collection process traverses directories
|
||||||
|
and modules the default collectors will produce
|
||||||
|
custom Collectors and Items if they are found
|
||||||
|
in a local ``conftest.py`` file.
|
||||||
|
|
||||||
|
|
||||||
|
Customizing the collection process in a module
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
If you have a module where you want to take responsibility for
|
||||||
|
collecting your own test Items and possibly even for executing
|
||||||
|
a test then you can provide `generative tests`_ that yield
|
||||||
|
callables and possibly arguments as a tuple. This is especially
|
||||||
|
useful for calling application test machinery with different
|
||||||
|
parameter sets but counting each of the calls as a separate
|
||||||
|
tests.
|
||||||
|
|
||||||
|
.. _`generative tests`: features.html#generative-tests
|
||||||
|
|
||||||
|
The other extension possibility is about
|
||||||
|
specifying a custom test ``Item`` class which
|
||||||
|
is responsible for setting up and executing an underlying
|
||||||
|
test. Or you can extend the collection process for a whole
|
||||||
|
directory tree by putting Items in a ``conftest.py`` configuration file.
|
||||||
|
The collection process dynamically consults the *chain of conftest.py*
|
||||||
|
modules to determine collectors and items at ``Directory``, ``Module``,
|
||||||
|
``Class``, ``Function`` or ``Generator`` level respectively.
|
||||||
|
|
||||||
|
Customizing execution of Items and Functions
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
- ``pytest.Function`` test items control execution
|
||||||
|
of a test function through its ``function.runtest()`` method.
|
||||||
|
This method is responsible for performing setup and teardown
|
||||||
|
("Test Fixtures") for a test Function.
|
||||||
|
|
||||||
|
- ``Function.execute(target, *args)`` methods are invoked by
|
||||||
|
the default ``Function.run()`` to actually execute a python
|
||||||
|
function with the given (usually empty set of) arguments.
|
||||||
|
|
||||||
|
.. _`py-dev mailing list`: http://codespeak.net/mailman/listinfo/py-dev
|
||||||
|
|
||||||
|
|
||||||
|
.. _`test generators`: funcargs.html#test-generators
|
||||||
|
|
||||||
|
.. _`generative tests`:
|
||||||
|
|
||||||
|
generative tests: yielding parametrized tests
|
||||||
|
====================================================
|
||||||
|
|
||||||
|
Deprecated since 1.0 in favour of `test generators`_.
|
||||||
|
|
||||||
|
*Generative tests* are test methods that are *generator functions* which
|
||||||
|
``yield`` callables and their arguments. This is useful for running a
|
||||||
|
test function multiple times against different parameters. Example::
|
||||||
|
|
||||||
|
def test_generative():
|
||||||
|
for x in (42,17,49):
|
||||||
|
yield check, x
|
||||||
|
|
||||||
|
def check(arg):
|
||||||
|
assert arg % 7 == 0 # second generated tests fails!
|
||||||
|
|
||||||
|
Note that ``test_generative()`` will cause three tests
|
||||||
|
to get run, notably ``check(42)``, ``check(17)`` and ``check(49)``
|
||||||
|
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::
|
||||||
|
|
||||||
|
def test_generative():
|
||||||
|
for x in (42,17,49):
|
||||||
|
yield "case %d" % x, check, x
|
||||||
|
|
||||||
|
|
||||||
|
disabling a test class
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
If you want to disable a complete test class you
|
||||||
|
can set the class-level attribute ``disabled``.
|
||||||
|
For example, in order to avoid running some tests on Win32::
|
||||||
|
|
||||||
|
class TestPosixOnly:
|
||||||
|
disabled = sys.platform == 'win32'
|
||||||
|
|
||||||
|
def test_xxx(self):
|
||||||
|
...
|
|
@ -0,0 +1,35 @@
|
||||||
|
=======================================
|
||||||
|
py.test documentation index
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
|
||||||
|
features_: overview and discussion of features.
|
||||||
|
|
||||||
|
quickstart_: getting started with writing a simple test.
|
||||||
|
|
||||||
|
`talks, tutorials, examples`_: tutorial examples, slides
|
||||||
|
|
||||||
|
funcargs_: powerful parametrized test function setup
|
||||||
|
|
||||||
|
`plugins`_: list of available plugins with usage examples and feature details.
|
||||||
|
|
||||||
|
customize_: configuration, customization, extensions
|
||||||
|
|
||||||
|
changelog_: history of changes covering last releases
|
||||||
|
|
||||||
|
**Continuous Integration of py.test's own tests and plugins with Hudson**:
|
||||||
|
|
||||||
|
`http://hudson.testrun.org/view/pytest`_
|
||||||
|
|
||||||
|
.. _`http://hudson.testrun.org/view/pytest`: http://hudson.testrun.org/view/pytest/
|
||||||
|
|
||||||
|
|
||||||
|
.. _changelog: ../changelog.html
|
||||||
|
.. _`plugins`: plugin/index.html
|
||||||
|
.. _`talks, tutorials, examples`: talks.html
|
||||||
|
.. _quickstart: quickstart.html
|
||||||
|
.. _features: features.html
|
||||||
|
.. _funcargs: funcargs.html
|
||||||
|
.. _customize: customize.html
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
|
||||||
|
Mission
|
||||||
|
====================================
|
||||||
|
|
||||||
|
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
|
||||||
|
are also usable independently. The project independent ``py.test`` command line tool helps you to:
|
||||||
|
|
||||||
|
* rapidly collect and run tests
|
||||||
|
* run unit- or doctests, functional or integration tests
|
||||||
|
* distribute tests to multiple environments
|
||||||
|
* use local or global plugins for custom test types and setup
|
|
@ -0,0 +1,230 @@
|
||||||
|
|
||||||
|
produce code coverage reports using the 'coverage' package, including support for distributed testing.
|
||||||
|
======================================================================================================
|
||||||
|
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
:local:
|
||||||
|
|
||||||
|
This plugin produces coverage reports. It supports centralised testing and distributed testing in
|
||||||
|
both load and each modes. It also supports coverage of subprocesses.
|
||||||
|
|
||||||
|
All features offered by the coverage package should be available, either through pytest-cov or
|
||||||
|
through coverage's config file.
|
||||||
|
|
||||||
|
|
||||||
|
Installation
|
||||||
|
------------
|
||||||
|
|
||||||
|
The `pytest-cov`_ package may be installed with pip or easy_install::
|
||||||
|
|
||||||
|
pip install pytest-cov
|
||||||
|
easy_install pytest-cov
|
||||||
|
|
||||||
|
.. _`pytest-cov`: http://pypi.python.org/pypi/pytest-cov/
|
||||||
|
|
||||||
|
|
||||||
|
Uninstallation
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Uninstalling packages is supported by pip::
|
||||||
|
|
||||||
|
pip uninstall pytest-cov
|
||||||
|
|
||||||
|
However easy_install does not provide an uninstall facility.
|
||||||
|
|
||||||
|
.. IMPORTANT::
|
||||||
|
|
||||||
|
Ensure that you manually delete the init_covmain.pth file in your
|
||||||
|
site-packages directory.
|
||||||
|
|
||||||
|
This file starts coverage collection of subprocesses if appropriate during
|
||||||
|
site initialization at python startup.
|
||||||
|
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-----
|
||||||
|
|
||||||
|
Centralised Testing
|
||||||
|
~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Centralised testing will report on the combined coverage of the main process and all of it's
|
||||||
|
subprocesses.
|
||||||
|
|
||||||
|
Running centralised testing::
|
||||||
|
|
||||||
|
py.test --cov myproj tests/
|
||||||
|
|
||||||
|
Shows a terminal report::
|
||||||
|
|
||||||
|
-------------------- coverage: platform linux2, python 2.6.4-final-0 ---------------------
|
||||||
|
Name Stmts Miss Cover
|
||||||
|
----------------------------------------
|
||||||
|
myproj/__init__ 2 0 100%
|
||||||
|
myproj/myproj 257 13 94%
|
||||||
|
myproj/feature4286 94 7 92%
|
||||||
|
----------------------------------------
|
||||||
|
TOTAL 353 20 94%
|
||||||
|
|
||||||
|
|
||||||
|
Distributed Testing: Load
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Distributed testing with dist mode set to load will report on the combined coverage of all slaves.
|
||||||
|
The slaves may be spread out over any number of hosts and each slave may be located anywhere on the
|
||||||
|
file system. Each slave will have it's subprocesses measured.
|
||||||
|
|
||||||
|
Running distributed testing with dist mode set to load::
|
||||||
|
|
||||||
|
py.test --cov myproj -n 2 tests/
|
||||||
|
|
||||||
|
Shows a terminal report::
|
||||||
|
|
||||||
|
-------------------- coverage: platform linux2, python 2.6.4-final-0 ---------------------
|
||||||
|
Name Stmts Miss Cover
|
||||||
|
----------------------------------------
|
||||||
|
myproj/__init__ 2 0 100%
|
||||||
|
myproj/myproj 257 13 94%
|
||||||
|
myproj/feature4286 94 7 92%
|
||||||
|
----------------------------------------
|
||||||
|
TOTAL 353 20 94%
|
||||||
|
|
||||||
|
|
||||||
|
Again but spread over different hosts and different directories::
|
||||||
|
|
||||||
|
py.test --cov myproj --dist load
|
||||||
|
--tx ssh=memedough@host1//chdir=testenv1
|
||||||
|
--tx ssh=memedough@host2//chdir=/tmp/testenv2//python=/tmp/env1/bin/python
|
||||||
|
--rsyncdir myproj --rsyncdir tests --rsync examples
|
||||||
|
tests/
|
||||||
|
|
||||||
|
Shows a terminal report::
|
||||||
|
|
||||||
|
-------------------- coverage: platform linux2, python 2.6.4-final-0 ---------------------
|
||||||
|
Name Stmts Miss Cover
|
||||||
|
----------------------------------------
|
||||||
|
myproj/__init__ 2 0 100%
|
||||||
|
myproj/myproj 257 13 94%
|
||||||
|
myproj/feature4286 94 7 92%
|
||||||
|
----------------------------------------
|
||||||
|
TOTAL 353 20 94%
|
||||||
|
|
||||||
|
|
||||||
|
Distributed Testing: Each
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
Distributed testing with dist mode set to each will report on the combined coverage of all slaves.
|
||||||
|
Since each slave is running all tests this allows generating a combined coverage report for multiple
|
||||||
|
environments.
|
||||||
|
|
||||||
|
Running distributed testing with dist mode set to each::
|
||||||
|
|
||||||
|
py.test --cov myproj --dist each
|
||||||
|
--tx popen//chdir=/tmp/testenv3//python=/usr/local/python27/bin/python
|
||||||
|
--tx ssh=memedough@host2//chdir=/tmp/testenv4//python=/tmp/env2/bin/python
|
||||||
|
--rsyncdir myproj --rsyncdir tests --rsync examples
|
||||||
|
tests/
|
||||||
|
|
||||||
|
Shows a terminal report::
|
||||||
|
|
||||||
|
---------------------------------------- coverage ----------------------------------------
|
||||||
|
platform linux2, python 2.6.5-final-0
|
||||||
|
platform linux2, python 2.7.0-final-0
|
||||||
|
Name Stmts Miss Cover
|
||||||
|
----------------------------------------
|
||||||
|
myproj/__init__ 2 0 100%
|
||||||
|
myproj/myproj 257 13 94%
|
||||||
|
myproj/feature4286 94 7 92%
|
||||||
|
----------------------------------------
|
||||||
|
TOTAL 353 20 94%
|
||||||
|
|
||||||
|
|
||||||
|
Reporting
|
||||||
|
---------
|
||||||
|
|
||||||
|
It is possible to generate any combination of the reports for a single test run.
|
||||||
|
|
||||||
|
The available reports are terminal (with or without missing line numbers shown), HTML, XML and
|
||||||
|
annotated source code.
|
||||||
|
|
||||||
|
The terminal report without line numbers (default)::
|
||||||
|
|
||||||
|
py.test --cov-report term --cov myproj tests/
|
||||||
|
|
||||||
|
-------------------- coverage: platform linux2, python 2.6.4-final-0 ---------------------
|
||||||
|
Name Stmts Miss Cover
|
||||||
|
----------------------------------------
|
||||||
|
myproj/__init__ 2 0 100%
|
||||||
|
myproj/myproj 257 13 94%
|
||||||
|
myproj/feature4286 94 7 92%
|
||||||
|
----------------------------------------
|
||||||
|
TOTAL 353 20 94%
|
||||||
|
|
||||||
|
|
||||||
|
The terminal report with line numbers::
|
||||||
|
|
||||||
|
py.test --cov-report term-missing --cov myproj tests/
|
||||||
|
|
||||||
|
-------------------- coverage: platform linux2, python 2.6.4-final-0 ---------------------
|
||||||
|
Name Stmts Miss Cover Missing
|
||||||
|
--------------------------------------------------
|
||||||
|
myproj/__init__ 2 0 100%
|
||||||
|
myproj/myproj 257 13 94% 24-26, 99, 149, 233-236, 297-298, 369-370
|
||||||
|
myproj/feature4286 94 7 92% 183-188, 197
|
||||||
|
--------------------------------------------------
|
||||||
|
TOTAL 353 20 94%
|
||||||
|
|
||||||
|
|
||||||
|
The remaining three reports output to files without showing anything on the terminal (useful for
|
||||||
|
when the output is going to a continuous integration server)::
|
||||||
|
|
||||||
|
py.test --cov-report html --cov-report xml --cov-report annotate --cov myproj tests/
|
||||||
|
|
||||||
|
|
||||||
|
Coverage Data File
|
||||||
|
------------------
|
||||||
|
|
||||||
|
The data file is erased at the beginning of testing to ensure clean data for each test run.
|
||||||
|
|
||||||
|
The data file is left at the end of testing so that it is possible to use normal coverage tools to
|
||||||
|
examine it.
|
||||||
|
|
||||||
|
|
||||||
|
Limitations
|
||||||
|
-----------
|
||||||
|
|
||||||
|
For distributed testing the slaves must have the pytest-cov package installed. This is needed since
|
||||||
|
the plugin must be registered through setuptools / distribute for pytest to start the plugin on the
|
||||||
|
slave.
|
||||||
|
|
||||||
|
For subprocess measurement environment variables must make it from the main process to the
|
||||||
|
subprocess. The python used by the subprocess must have pytest-cov installed. The subprocess must
|
||||||
|
do normal site initialization so that the environment variables can be detected and coverage
|
||||||
|
started.
|
||||||
|
|
||||||
|
|
||||||
|
Acknowledgments
|
||||||
|
----------------
|
||||||
|
|
||||||
|
Holger Krekel for pytest with its distributed testing support.
|
||||||
|
|
||||||
|
Ned Batchelder for coverage and its ability to combine the coverage results of parallel runs.
|
||||||
|
|
||||||
|
Whilst this plugin has been built fresh from the ground up to support distributed testing it has
|
||||||
|
been influenced by the work done on pytest-coverage (Ross Lawley, James Mills, Holger Krekel) and
|
||||||
|
nose-cover (Jason Pellerin) which are other coverage plugins for pytest and nose respectively.
|
||||||
|
|
||||||
|
No doubt others have contributed to these tools as well.
|
||||||
|
|
||||||
|
command line options
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
|
||||||
|
``--cov=path``
|
||||||
|
measure coverage for filesystem path (multi-allowed)
|
||||||
|
``--cov-report=type``
|
||||||
|
type of report to generate: term, term-missing, annotate, html, xml (multi-allowed)
|
||||||
|
``--cov-config=path``
|
||||||
|
config file for coverage, default: .coveragerc
|
||||||
|
|
||||||
|
.. include:: links.txt
|
|
@ -0,0 +1,51 @@
|
||||||
|
|
||||||
|
Write and report coverage data with the 'coverage' package.
|
||||||
|
===========================================================
|
||||||
|
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
:local:
|
||||||
|
|
||||||
|
Note: Original code by Ross Lawley.
|
||||||
|
|
||||||
|
Install
|
||||||
|
--------------
|
||||||
|
|
||||||
|
Use pip to (un)install::
|
||||||
|
|
||||||
|
pip install pytest-coverage
|
||||||
|
pip uninstall pytest-coverage
|
||||||
|
|
||||||
|
or alternatively use easy_install to install::
|
||||||
|
|
||||||
|
easy_install pytest-coverage
|
||||||
|
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-------------
|
||||||
|
|
||||||
|
To get full test coverage reports for a particular package type::
|
||||||
|
|
||||||
|
py.test --cover-report=report
|
||||||
|
|
||||||
|
command line options
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
|
||||||
|
``--cover=COVERPACKAGES``
|
||||||
|
(multi allowed) only include info from specified package.
|
||||||
|
``--cover-report=REPORT_TYPE``
|
||||||
|
html: Directory for html output.
|
||||||
|
report: Output a text report.
|
||||||
|
annotate: Annotate your source code for which lines were executed and which were not.
|
||||||
|
xml: Output an xml report compatible with the cobertura plugin for hudson.
|
||||||
|
``--cover-directory=DIRECTORY``
|
||||||
|
Directory for the reports (html / annotate results) defaults to ./coverage
|
||||||
|
``--cover-xml-file=XML_FILE``
|
||||||
|
File for the xml report defaults to ./coverage.xml
|
||||||
|
``--cover-show-missing``
|
||||||
|
Show missing files
|
||||||
|
``--cover-ignore-errors=IGNORE_ERRORS``
|
||||||
|
Ignore errors of finding source files for code.
|
||||||
|
|
||||||
|
.. include:: links.txt
|
|
@ -0,0 +1,7 @@
|
||||||
|
pytest_django plugin (EXTERNAL)
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
pytest_django is a plugin for py.test that provides a set of useful tools for testing Django applications, checkout Ben Firshman's `pytest_django github page`_.
|
||||||
|
|
||||||
|
.. _`pytest_django github page`: http://github.com/bfirsh/pytest_django/tree/master
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
|
||||||
|
report test coverage using the 'figleaf' package.
|
||||||
|
=================================================
|
||||||
|
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
:local:
|
||||||
|
|
||||||
|
Install
|
||||||
|
---------------
|
||||||
|
|
||||||
|
To install the plugin issue::
|
||||||
|
|
||||||
|
easy_install pytest-figleaf # or
|
||||||
|
pip install pytest-figleaf
|
||||||
|
|
||||||
|
and if you are using pip you can also uninstall::
|
||||||
|
|
||||||
|
pip uninstall pytest-figleaf
|
||||||
|
|
||||||
|
|
||||||
|
Usage
|
||||||
|
---------------
|
||||||
|
|
||||||
|
After installation you can simply type::
|
||||||
|
|
||||||
|
py.test --figleaf [...]
|
||||||
|
|
||||||
|
to enable figleaf coverage in your test run. A default ".figleaf" data file
|
||||||
|
and "html" directory will be created. You can use command line options
|
||||||
|
to control where data and html files are created.
|
||||||
|
|
||||||
|
command line options
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
|
||||||
|
``--figleaf``
|
||||||
|
trace python coverage with figleaf and write HTML for files below the current working dir
|
||||||
|
``--fig-data=dir``
|
||||||
|
set tracing file, default: ".figleaf".
|
||||||
|
``--fig-html=dir``
|
||||||
|
set html reporting dir, default "html".
|
||||||
|
|
||||||
|
.. include:: links.txt
|
|
@ -0,0 +1,28 @@
|
||||||
|
|
||||||
|
generate standalone test script to be distributed along with an application.
|
||||||
|
============================================================================
|
||||||
|
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
:local:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
command line options
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
|
||||||
|
``--genscript=path``
|
||||||
|
create standalone py.test script at given target path.
|
||||||
|
|
||||||
|
Start improving this plugin in 30 seconds
|
||||||
|
=========================================
|
||||||
|
|
||||||
|
|
||||||
|
1. Download `pytest_genscript.py`_ plugin source code
|
||||||
|
2. put it somewhere as ``pytest_genscript.py`` into your import path
|
||||||
|
3. a subsequent ``py.test`` run will use your local version
|
||||||
|
|
||||||
|
Checkout customize_, other plugins_ or `get in contact`_.
|
||||||
|
|
||||||
|
.. include:: links.txt
|
|
@ -0,0 +1,38 @@
|
||||||
|
|
||||||
|
provide version info, conftest/environment config names.
|
||||||
|
========================================================
|
||||||
|
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
:local:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
command line options
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
|
||||||
|
``--version``
|
||||||
|
display py lib version and import information.
|
||||||
|
``-p name``
|
||||||
|
early-load given plugin (multi-allowed).
|
||||||
|
``--traceconfig``
|
||||||
|
trace considerations of conftest.py files.
|
||||||
|
``--nomagic``
|
||||||
|
don't reinterpret asserts, no traceback cutting.
|
||||||
|
``--debug``
|
||||||
|
generate and show internal debugging information.
|
||||||
|
``--help-config``
|
||||||
|
show available conftest.py and ENV-variable names.
|
||||||
|
|
||||||
|
Start improving this plugin in 30 seconds
|
||||||
|
=========================================
|
||||||
|
|
||||||
|
|
||||||
|
1. Download `pytest_helpconfig.py`_ plugin source code
|
||||||
|
2. put it somewhere as ``pytest_helpconfig.py`` into your import path
|
||||||
|
3. a subsequent ``py.test`` run will use your local version
|
||||||
|
|
||||||
|
Checkout customize_, other plugins_ or `get in contact`_.
|
||||||
|
|
||||||
|
.. include:: links.txt
|
|
@ -0,0 +1,68 @@
|
||||||
|
|
||||||
|
advanced python testing
|
||||||
|
=======================
|
||||||
|
|
||||||
|
skipping_ advanced skipping for python test functions, classes or modules.
|
||||||
|
|
||||||
|
mark_ generic mechanism for marking python functions.
|
||||||
|
|
||||||
|
pdb_ interactive debugging with the Python Debugger.
|
||||||
|
|
||||||
|
figleaf_ (external) report test coverage using the 'figleaf' package.
|
||||||
|
|
||||||
|
monkeypatch_ safely patch object attributes, dicts and environment variables.
|
||||||
|
|
||||||
|
coverage_ (external) Write and report coverage data with the 'coverage' package.
|
||||||
|
|
||||||
|
cov_ (external) produce code coverage reports using the 'coverage' package, including support for distributed testing.
|
||||||
|
|
||||||
|
capture_ configurable per-test stdout/stderr capturing mechanisms.
|
||||||
|
|
||||||
|
capturelog_ (external) capture output of logging module.
|
||||||
|
|
||||||
|
recwarn_ helpers for asserting deprecation and other warnings.
|
||||||
|
|
||||||
|
tmpdir_ provide temporary directories to test functions.
|
||||||
|
|
||||||
|
|
||||||
|
distributed testing, CI and deployment
|
||||||
|
======================================
|
||||||
|
|
||||||
|
xdist_ (external) loop on failing tests, distribute test runs to CPUs and hosts.
|
||||||
|
|
||||||
|
pastebin_ submit failure or test session information to a pastebin service.
|
||||||
|
|
||||||
|
junitxml_ logging of test results in JUnit-XML format, for use with Hudson
|
||||||
|
|
||||||
|
resultlog_ non-xml machine-readable logging of test results.
|
||||||
|
|
||||||
|
genscript_ generate standalone test script to be distributed along with an application.
|
||||||
|
|
||||||
|
|
||||||
|
testing domains and conventions codecheckers
|
||||||
|
============================================
|
||||||
|
|
||||||
|
oejskit_ (external) run javascript tests in real life browsers
|
||||||
|
|
||||||
|
django_ (external) for testing django applications
|
||||||
|
|
||||||
|
unittest_ automatically discover and run traditional "unittest.py" style tests.
|
||||||
|
|
||||||
|
nose_ nose-compatibility plugin: allow to run nose test suites natively.
|
||||||
|
|
||||||
|
doctest_ collect and execute doctests from modules and test files.
|
||||||
|
|
||||||
|
restdoc_ perform ReST syntax, local and remote reference tests on .rst/.txt files.
|
||||||
|
|
||||||
|
|
||||||
|
internal, debugging, help functionality
|
||||||
|
=======================================
|
||||||
|
|
||||||
|
helpconfig_ provide version info, conftest/environment config names.
|
||||||
|
|
||||||
|
terminal_ Implements terminal reporting of the full testing process.
|
||||||
|
|
||||||
|
hooklog_ log invocations of extension hooks to a file.
|
||||||
|
|
||||||
|
|
||||||
|
.. include:: links.txt
|
|
@ -0,0 +1,47 @@
|
||||||
|
.. _`helpconfig`: helpconfig.html
|
||||||
|
.. _`pytest_recwarn.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_recwarn.py
|
||||||
|
.. _`unittest`: unittest.html
|
||||||
|
.. _`pytest_monkeypatch.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_monkeypatch.py
|
||||||
|
.. _`pytest_genscript.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_genscript.py
|
||||||
|
.. _`pastebin`: pastebin.html
|
||||||
|
.. _`skipping`: skipping.html
|
||||||
|
.. _`genscript`: genscript.html
|
||||||
|
.. _`plugins`: index.html
|
||||||
|
.. _`mark`: mark.html
|
||||||
|
.. _`tmpdir`: tmpdir.html
|
||||||
|
.. _`pytest_doctest.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_doctest.py
|
||||||
|
.. _`capture`: capture.html
|
||||||
|
.. _`pytest_nose.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_nose.py
|
||||||
|
.. _`pytest_restdoc.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_restdoc.py
|
||||||
|
.. _`restdoc`: restdoc.html
|
||||||
|
.. _`xdist`: xdist.html
|
||||||
|
.. _`pytest_pastebin.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_pastebin.py
|
||||||
|
.. _`pytest_tmpdir.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_tmpdir.py
|
||||||
|
.. _`terminal`: terminal.html
|
||||||
|
.. _`pytest_hooklog.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_hooklog.py
|
||||||
|
.. _`capturelog`: capturelog.html
|
||||||
|
.. _`junitxml`: junitxml.html
|
||||||
|
.. _`pytest_skipping.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_skipping.py
|
||||||
|
.. _`checkout the py.test development version`: ../../install.html#checkout
|
||||||
|
.. _`pytest_helpconfig.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_helpconfig.py
|
||||||
|
.. _`oejskit`: oejskit.html
|
||||||
|
.. _`doctest`: doctest.html
|
||||||
|
.. _`pytest_mark.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_mark.py
|
||||||
|
.. _`get in contact`: ../../contact.html
|
||||||
|
.. _`pytest_capture.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_capture.py
|
||||||
|
.. _`figleaf`: figleaf.html
|
||||||
|
.. _`customize`: ../customize.html
|
||||||
|
.. _`hooklog`: hooklog.html
|
||||||
|
.. _`pytest_terminal.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_terminal.py
|
||||||
|
.. _`recwarn`: recwarn.html
|
||||||
|
.. _`pytest_pdb.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_pdb.py
|
||||||
|
.. _`monkeypatch`: monkeypatch.html
|
||||||
|
.. _`coverage`: coverage.html
|
||||||
|
.. _`resultlog`: resultlog.html
|
||||||
|
.. _`cov`: cov.html
|
||||||
|
.. _`pytest_junitxml.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_junitxml.py
|
||||||
|
.. _`django`: django.html
|
||||||
|
.. _`pytest_unittest.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_unittest.py
|
||||||
|
.. _`nose`: nose.html
|
||||||
|
.. _`pytest_resultlog.py`: http://bitbucket.org/hpk42/py-trunk/raw/1.3.4/py/_plugin/pytest_resultlog.py
|
||||||
|
.. _`pdb`: pdb.html
|
|
@ -0,0 +1,56 @@
|
||||||
|
|
||||||
|
nose-compatibility plugin: allow to run nose test suites natively.
|
||||||
|
==================================================================
|
||||||
|
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
:local:
|
||||||
|
|
||||||
|
This is an experimental plugin for allowing to run tests written
|
||||||
|
in 'nosetests style with py.test.
|
||||||
|
|
||||||
|
Usage
|
||||||
|
-------------
|
||||||
|
|
||||||
|
type::
|
||||||
|
|
||||||
|
py.test # instead of 'nosetests'
|
||||||
|
|
||||||
|
and you should be able to run nose style tests and at the same
|
||||||
|
time can make full use of py.test's capabilities.
|
||||||
|
|
||||||
|
Supported nose Idioms
|
||||||
|
----------------------
|
||||||
|
|
||||||
|
* setup and teardown at module/class/method level
|
||||||
|
* SkipTest exceptions and markers
|
||||||
|
* setup/teardown decorators
|
||||||
|
* yield-based tests and their setup
|
||||||
|
* general usage of nose utilities
|
||||||
|
|
||||||
|
Unsupported idioms / issues
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
- nose-style doctests are not collected and executed correctly,
|
||||||
|
also fixtures don't work.
|
||||||
|
|
||||||
|
- no nose-configuration is recognized
|
||||||
|
|
||||||
|
If you find other issues or have suggestions please run::
|
||||||
|
|
||||||
|
py.test --pastebin=all
|
||||||
|
|
||||||
|
and send the resulting URL to a py.test contact channel,
|
||||||
|
at best to the mailing list.
|
||||||
|
|
||||||
|
Start improving this plugin in 30 seconds
|
||||||
|
=========================================
|
||||||
|
|
||||||
|
|
||||||
|
1. Download `pytest_nose.py`_ plugin source code
|
||||||
|
2. put it somewhere as ``pytest_nose.py`` into your import path
|
||||||
|
3. a subsequent ``py.test`` run will use your local version
|
||||||
|
|
||||||
|
Checkout customize_, other plugins_ or `get in contact`_.
|
||||||
|
|
||||||
|
.. include:: links.txt
|
|
@ -0,0 +1,12 @@
|
||||||
|
pytest_oejskit plugin (EXTERNAL)
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
The `oejskit`_ offers a py.test plugin for running Javascript tests in life browsers. 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.
|
||||||
|
|
||||||
|
For more info and download please visit the `oejskit PyPI`_ page.
|
||||||
|
|
||||||
|
.. _`oejskit`:
|
||||||
|
.. _`oejskit PyPI`: http://pypi.python.org/pypi/oejskit
|
||||||
|
|
||||||
|
.. source link 'http://bitbucket.org/pedronis/js-infrastructure/src/tip/pytest_jstests.py',
|
|
@ -0,0 +1,40 @@
|
||||||
|
|
||||||
|
Implements terminal reporting of the full testing process.
|
||||||
|
==========================================================
|
||||||
|
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
:local:
|
||||||
|
|
||||||
|
This is a good source for looking at the various reporting hooks.
|
||||||
|
|
||||||
|
command line options
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
|
||||||
|
``-v, --verbose``
|
||||||
|
increase verbosity.
|
||||||
|
``-r chars``
|
||||||
|
show extra test summary info as specified by chars (f)ailed, (s)skipped, (x)failed, (X)passed.
|
||||||
|
``-l, --showlocals``
|
||||||
|
show locals in tracebacks (disabled by default).
|
||||||
|
``--report=opts``
|
||||||
|
(deprecated, use -r)
|
||||||
|
``--tb=style``
|
||||||
|
traceback print mode (long/short/line/no).
|
||||||
|
``--fulltrace``
|
||||||
|
don't cut any tracebacks (default is to cut).
|
||||||
|
``--funcargs``
|
||||||
|
show available function arguments, sorted by plugin
|
||||||
|
|
||||||
|
Start improving this plugin in 30 seconds
|
||||||
|
=========================================
|
||||||
|
|
||||||
|
|
||||||
|
1. Download `pytest_terminal.py`_ plugin source code
|
||||||
|
2. put it somewhere as ``pytest_terminal.py`` into your import path
|
||||||
|
3. a subsequent ``py.test`` run will use your local version
|
||||||
|
|
||||||
|
Checkout customize_, other plugins_ or `get in contact`_.
|
||||||
|
|
||||||
|
.. include:: links.txt
|
|
@ -0,0 +1,172 @@
|
||||||
|
|
||||||
|
loop on failing tests, distribute test runs to CPUs and hosts.
|
||||||
|
==============================================================
|
||||||
|
|
||||||
|
|
||||||
|
.. contents::
|
||||||
|
:local:
|
||||||
|
|
||||||
|
The `pytest-xdist`_ plugin extends py.test with some unique
|
||||||
|
test execution modes:
|
||||||
|
|
||||||
|
* 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
|
||||||
|
failing tests. This is repeated until all tests pass after which again
|
||||||
|
a full run is performed.
|
||||||
|
|
||||||
|
* Load-balancing: if you have multiple CPUs or hosts you can use
|
||||||
|
those for a combined test run. This allows to speed up
|
||||||
|
development or to use special resources of remote machines.
|
||||||
|
|
||||||
|
* Multi-Platform coverage: you can specify different Python interpreters
|
||||||
|
or different platforms and run tests in parallel on all of them.
|
||||||
|
|
||||||
|
Before running tests remotely, ``py.test`` efficiently synchronizes your
|
||||||
|
program source code to the remote place. All test results
|
||||||
|
are reported back and displayed to your local test session.
|
||||||
|
You may specify different Python versions and interpreters.
|
||||||
|
|
||||||
|
.. _`pytest-xdist`: http://pypi.python.org/pypi/pytest-xdist
|
||||||
|
|
||||||
|
Usage examples
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
Speed up test runs by sending tests to multiple CPUs
|
||||||
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
To send tests to multiple CPUs, type::
|
||||||
|
|
||||||
|
py.test -n NUM
|
||||||
|
|
||||||
|
Especially for longer running tests or tests requiring
|
||||||
|
a lot of IO this can lead to considerable speed ups.
|
||||||
|
|
||||||
|
|
||||||
|
Running tests in a Python subprocess
|
||||||
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
To instantiate a python2.4 sub process and send tests to it, you may type::
|
||||||
|
|
||||||
|
py.test -d --tx popen//python=python2.4
|
||||||
|
|
||||||
|
This will start a subprocess which is run with the "python2.4"
|
||||||
|
Python interpreter, found in your system binary lookup path.
|
||||||
|
|
||||||
|
If you prefix the --tx option value like this::
|
||||||
|
|
||||||
|
--tx 3*popen//python=python2.4
|
||||||
|
|
||||||
|
then three subprocesses would be created and tests
|
||||||
|
will be load-balanced across these three processes.
|
||||||
|
|
||||||
|
|
||||||
|
Sending tests to remote SSH accounts
|
||||||
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
Suppose you have a package ``mypkg`` which contains some
|
||||||
|
tests that you can successfully run locally. And you
|
||||||
|
have a ssh-reachable machine ``myhost``. Then
|
||||||
|
you can ad-hoc distribute your tests by typing::
|
||||||
|
|
||||||
|
py.test -d --tx ssh=myhostpopen --rsyncdir mypkg mypkg
|
||||||
|
|
||||||
|
This will synchronize your ``mypkg`` package directory
|
||||||
|
to an remote ssh account and then locally collect tests
|
||||||
|
and send them to remote places for execution.
|
||||||
|
|
||||||
|
You can specify multiple ``--rsyncdir`` directories
|
||||||
|
to be sent to the remote side.
|
||||||
|
|
||||||
|
**NOTE:** For py.test to collect and send tests correctly
|
||||||
|
you not only need to make sure all code and tests
|
||||||
|
directories are rsynced, but that any test (sub) directory
|
||||||
|
also has an ``__init__.py`` file because internally
|
||||||
|
py.test references tests as a fully qualified python
|
||||||
|
module path. **You will otherwise get strange errors**
|
||||||
|
during setup of the remote side.
|
||||||
|
|
||||||
|
Sending tests to remote Socket Servers
|
||||||
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
Download the single-module `socketserver.py`_ Python program
|
||||||
|
and run it like this::
|
||||||
|
|
||||||
|
python socketserver.py
|
||||||
|
|
||||||
|
It will tell you that it starts listening on the default
|
||||||
|
port. You can now on your home machine specify this
|
||||||
|
new socket host with something like this::
|
||||||
|
|
||||||
|
py.test -d --tx socket=192.168.1.102:8888 --rsyncdir mypkg mypkg
|
||||||
|
|
||||||
|
|
||||||
|
.. _`atonce`:
|
||||||
|
|
||||||
|
Running tests on many platforms at once
|
||||||
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
The basic command to run tests on multiple platforms is::
|
||||||
|
|
||||||
|
py.test --dist=each --tx=spec1 --tx=spec2
|
||||||
|
|
||||||
|
If you specify a windows host, an OSX host and a Linux
|
||||||
|
environment this command will send each tests to all
|
||||||
|
platforms - and report back failures from all platforms
|
||||||
|
at once. The specifications strings use the `xspec syntax`_.
|
||||||
|
|
||||||
|
.. _`xspec syntax`: http://codespeak.net/execnet/trunk/basics.html#xspec
|
||||||
|
|
||||||
|
.. _`socketserver.py`: http://codespeak.net/svn/py/dist/py/execnet/script/socketserver.py
|
||||||
|
|
||||||
|
.. _`execnet`: http://codespeak.net/execnet
|
||||||
|
|
||||||
|
Specifying test exec environments in a conftest.py
|
||||||
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
Instead of specifying command line options, you can
|
||||||
|
put options values in a ``conftest.py`` file like this::
|
||||||
|
|
||||||
|
option_tx = ['ssh=myhost//python=python2.5', 'popen//python=python2.5']
|
||||||
|
option_dist = True
|
||||||
|
|
||||||
|
Any commandline ``--tx`` specifications will add to the list of
|
||||||
|
available execution environments.
|
||||||
|
|
||||||
|
Specifying "rsync" dirs in a conftest.py
|
||||||
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
In your ``mypkg/conftest.py`` you may specify directories to synchronise
|
||||||
|
or to exclude::
|
||||||
|
|
||||||
|
rsyncdirs = ['.', '../plugins']
|
||||||
|
rsyncignore = ['_cache']
|
||||||
|
|
||||||
|
These directory specifications are relative to the directory
|
||||||
|
where the ``conftest.py`` is found.
|
||||||
|
|
||||||
|
command line options
|
||||||
|
--------------------
|
||||||
|
|
||||||
|
|
||||||
|
``-f, --looponfail``
|
||||||
|
run tests in subprocess, wait for modified files and re-run failing test set until all pass.
|
||||||
|
``-n numprocesses``
|
||||||
|
shortcut for '--dist=load --tx=NUM*popen'
|
||||||
|
``--boxed``
|
||||||
|
box each test run in a separate process (unix)
|
||||||
|
``--dist=distmode``
|
||||||
|
set mode for distributing tests to exec environments.
|
||||||
|
|
||||||
|
each: send each test to each available environment.
|
||||||
|
|
||||||
|
load: send each test to available environment.
|
||||||
|
|
||||||
|
(default) no: run tests inprocess, don't distribute.
|
||||||
|
``--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
|
||||||
|
``-d``
|
||||||
|
load-balance tests. shortcut for '--dist=load'
|
||||||
|
``--rsyncdir=dir1``
|
||||||
|
add directory for rsyncing to remote tx nodes.
|
||||||
|
|
||||||
|
.. include:: links.txt
|
|
@ -0,0 +1,102 @@
|
||||||
|
|
||||||
|
.. _`tmpdir handling`:
|
||||||
|
|
||||||
|
一時ディレクトリとファイル
|
||||||
|
==========================
|
||||||
|
|
||||||
|
..
|
||||||
|
Temporary directories and files
|
||||||
|
================================================
|
||||||
|
|
||||||
|
..
|
||||||
|
The 'tmpdir' test function argument
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
テスト関数の引数 'tmpdir'
|
||||||
|
-------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
You can use the ``tmpdir`` function argument which will
|
||||||
|
provide a temporary directory unique to the test invocation,
|
||||||
|
created in the `base temporary directory`_.
|
||||||
|
|
||||||
|
``tmpdir`` という関数の引数を一意な一時ディレクトリを提供するのに使えます。それは :ref:`base temporary directory` に作成されます。
|
||||||
|
|
||||||
|
..
|
||||||
|
``tmpdir`` is a `py.path.local`_ object which offers ``os.path`` methods
|
||||||
|
and more. Here is an example test usage::
|
||||||
|
|
||||||
|
``tmpdir`` は ``os.path`` メソッドやさらに他のメソッドを提供する `py.path.local`_ オブジェクトです。次にテストでの使用例を紹介します::
|
||||||
|
|
||||||
|
# test_tmpdir.py の内容
|
||||||
|
import os
|
||||||
|
def test_create_file(tmpdir):
|
||||||
|
p = tmpdir.mkdir("sub").join("hello.txt")
|
||||||
|
p.write("content")
|
||||||
|
assert p.read() == "content"
|
||||||
|
assert len(tmpdir.listdir()) == 1
|
||||||
|
assert 0
|
||||||
|
|
||||||
|
..
|
||||||
|
Running this would result in a passed test except for the last
|
||||||
|
``assert 0`` line which we use to look at values::
|
||||||
|
|
||||||
|
このテストを実行すると、最終行の ``assert 0`` が失敗して ``tmpdir`` の値が見えます::
|
||||||
|
|
||||||
|
$ py.test test_tmpdir.py
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 1 items
|
||||||
|
|
||||||
|
test_tmpdir.py F
|
||||||
|
|
||||||
|
================================= FAILURES =================================
|
||||||
|
_____________________________ test_create_file _____________________________
|
||||||
|
|
||||||
|
tmpdir = local('/tmp/pytest-23/test_create_file0')
|
||||||
|
|
||||||
|
def test_create_file(tmpdir):
|
||||||
|
p = tmpdir.mkdir("sub").join("hello.txt")
|
||||||
|
p.write("content")
|
||||||
|
assert p.read() == "content"
|
||||||
|
assert len(tmpdir.listdir()) == 1
|
||||||
|
> assert 0
|
||||||
|
E assert 0
|
||||||
|
|
||||||
|
test_tmpdir.py:7: AssertionError
|
||||||
|
========================= 1 failed in 0.02 seconds =========================
|
||||||
|
|
||||||
|
.. _`base temporary directory`:
|
||||||
|
|
||||||
|
デフォルトの一時ディレクトリ
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
The default base temporary directory
|
||||||
|
-----------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Temporary directories are by default created as sub-directories of
|
||||||
|
the system temporary directory. The base name will be ``pytest-NUM`` where
|
||||||
|
``NUM`` will be incremented with each test run. Moreover, entries older
|
||||||
|
than 3 temporary directories will be removed.
|
||||||
|
|
||||||
|
デフォルトでは、テスト向けの一時ディレクトリは、システムの一時ディレクトリのサブディレクトリとして作成されます。基本となる名前は ``pytest-NUM`` となり ``NUM`` はテストが実行される度に数字が増えます。また、3世代より古い一時ディレクトリは削除されます。
|
||||||
|
|
||||||
|
..
|
||||||
|
You can override the default temporary directory setting like this::
|
||||||
|
|
||||||
|
デフォルトの一時ディレクトリの設定は次のように書き換えられます::
|
||||||
|
|
||||||
|
py.test --basetemp=mydir
|
||||||
|
|
||||||
|
..
|
||||||
|
When distributing tests on the local machine, ``py.test`` takes care to
|
||||||
|
configure a basetemp directory for the sub processes such that all temporary
|
||||||
|
data lands below a single per-test run basetemp directory.
|
||||||
|
|
||||||
|
``py.test`` は、ローカルマシン上で分散テストを行うとき、全ての一時データが basetemp ディレクトリの配下で実行されてテスト毎に一意になるよう、サブプロセスに対しても basetemp ディレクトリをちゃんと設定します。
|
||||||
|
|
||||||
|
.. _`py.path.local`: http://pylib.org/path.html
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,59 @@
|
||||||
|
|
||||||
|
.. _`unittest.TestCase`:
|
||||||
|
|
||||||
|
unittest.TestCase の対応
|
||||||
|
========================
|
||||||
|
|
||||||
|
..
|
||||||
|
Support for unittest.TestCase
|
||||||
|
=====================================================================
|
||||||
|
|
||||||
|
..
|
||||||
|
py.test has limited support for running Python `unittest.py style`_ tests.
|
||||||
|
It will automatically collect ``unittest.TestCase`` subclasses
|
||||||
|
and their ``test`` methods in test files. It will invoke
|
||||||
|
``setUp/tearDown`` methods but also perform py.test's standard ways
|
||||||
|
of treating tests such as IO capturing::
|
||||||
|
|
||||||
|
py.test は、Python の `unittest スタイル`_ のテストに制限付きで対応しています。テストファイル内の ``unittest.TestCase`` のサブクラスとその ``test`` メソッドを自動的に探します。 ``setUp/tearDown`` メソッドを実行しますが、IO キャプチャのようなテストの扱いは pytest の標準的な方法で行います::
|
||||||
|
|
||||||
|
# test_unittest.py の内容
|
||||||
|
|
||||||
|
import unittest
|
||||||
|
class MyTest(unittest.TestCase):
|
||||||
|
def setUp(self):
|
||||||
|
print ("hello") # 出力内容をキャプチャ
|
||||||
|
def test_method(self):
|
||||||
|
x = 1
|
||||||
|
self.assertEquals(x, 3)
|
||||||
|
|
||||||
|
..
|
||||||
|
Running it yields::
|
||||||
|
|
||||||
|
このコードを実行すると次のようになります::
|
||||||
|
|
||||||
|
$ py.test test_unittest.py
|
||||||
|
=========================== test session starts ============================
|
||||||
|
platform linux2 -- Python 2.7.1 -- pytest-2.2.4
|
||||||
|
collecting ... collected 1 items
|
||||||
|
|
||||||
|
test_unittest.py F
|
||||||
|
|
||||||
|
================================= FAILURES =================================
|
||||||
|
____________________________ MyTest.test_method ____________________________
|
||||||
|
|
||||||
|
self = <test_unittest.MyTest testMethod=test_method>
|
||||||
|
|
||||||
|
def test_method(self):
|
||||||
|
x = 1
|
||||||
|
> self.assertEquals(x, 3)
|
||||||
|
E AssertionError: 1 != 3
|
||||||
|
|
||||||
|
test_unittest.py:8: AssertionError
|
||||||
|
----------------------------- Captured stdout ------------------------------
|
||||||
|
hello
|
||||||
|
========================= 1 failed in 0.01 seconds =========================
|
||||||
|
|
||||||
|
.. _`unittest.py style`: http://docs.python.org/library/unittest.html
|
||||||
|
.. _`unittest スタイル`: http://docs.python.org/library/unittest.html
|
||||||
|
|
|
@ -0,0 +1,313 @@
|
||||||
|
|
||||||
|
.. _usage:
|
||||||
|
|
||||||
|
使用方法とテスト実行
|
||||||
|
====================
|
||||||
|
|
||||||
|
..
|
||||||
|
Usage and Invocations
|
||||||
|
==========================================
|
||||||
|
|
||||||
|
.. _cmdline:
|
||||||
|
|
||||||
|
``python -m pytest`` による pytest 呼び出し
|
||||||
|
-------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Calling pytest through ``python -m pytest``
|
||||||
|
-----------------------------------------------------
|
||||||
|
|
||||||
|
.. versionadded:: 2.0
|
||||||
|
|
||||||
|
..
|
||||||
|
If you use Python-2.5 or later you can invoke testing through the
|
||||||
|
Python interpreter from the command line::
|
||||||
|
|
||||||
|
Python 2.5 か、それ以上のバージョンを使っているなら、コマンドラインから Python インタープリターでテストを実行できます::
|
||||||
|
|
||||||
|
python -m pytest [...]
|
||||||
|
|
||||||
|
..
|
||||||
|
This is equivalent to invoking the command line script ``py.test [...]``
|
||||||
|
directly.
|
||||||
|
|
||||||
|
これは直接的にコマンドラインスクリプト ``py.test [...]`` を実行するのと同じです。
|
||||||
|
|
||||||
|
..
|
||||||
|
Getting help on version, option names, environment variables
|
||||||
|
--------------------------------------------------------------
|
||||||
|
|
||||||
|
バージョン、オプション名、環境変数のヘルプを表示
|
||||||
|
------------------------------------------------
|
||||||
|
|
||||||
|
::
|
||||||
|
|
||||||
|
py.test --version # pytest がインポートされた場所を表示
|
||||||
|
py.test --funcargs # 利用できる組み込みの関数引数を表示
|
||||||
|
py.test -h | --help # コマンドラインと設定ファイルオプションのヘルプを表示
|
||||||
|
|
||||||
|
..
|
||||||
|
Stopping after the first (or N) failures
|
||||||
|
---------------------------------------------------
|
||||||
|
|
||||||
|
最初 (または N 回) 失敗したときにテストを中止
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
To stop the testing process after the first (N) failures::
|
||||||
|
|
||||||
|
py.test -x # stop after first failure
|
||||||
|
py.test --maxfail=2 # stop after two failures
|
||||||
|
|
||||||
|
最初 (N 回) 失敗したときにテストプロセスを中止するには、次のようにします::
|
||||||
|
|
||||||
|
py.test -x # 最初に失敗したときに中止
|
||||||
|
py.test --maxfail=2 # 2 回失敗したときに中止
|
||||||
|
|
||||||
|
..
|
||||||
|
Specifying tests / selecting tests
|
||||||
|
---------------------------------------------------
|
||||||
|
|
||||||
|
テストの指定と選択
|
||||||
|
------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Several test run options::
|
||||||
|
|
||||||
|
次のようなテスト実行のオプションがあります::
|
||||||
|
|
||||||
|
py.test test_mod.py # モジュール内のテストを実行
|
||||||
|
py.test somepath # 指定したパスの全てのテストを実行
|
||||||
|
py.test -k string # string を含む名前をもつテストのみを実行
|
||||||
|
|
||||||
|
..
|
||||||
|
Import 'pkg' and use its filesystem location to find and run tests::
|
||||||
|
|
||||||
|
'pkg' をインポートして、そのファイルシステム上の位置からテストを探して実行します::
|
||||||
|
|
||||||
|
py.test --pyargs pkg # pkg のディレクトリ配下にある全てのテストを実行
|
||||||
|
|
||||||
|
..
|
||||||
|
Modifying Python traceback printing
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
Python のトレースバック表示を変更
|
||||||
|
---------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Examples for modifying traceback printing::
|
||||||
|
|
||||||
|
トレースバック表示を変更する例です::
|
||||||
|
|
||||||
|
py.test --showlocals # トレースバックのローカル変数を表示
|
||||||
|
py.test -l # トレースバックのローカル変数を表示 (短いオプション)
|
||||||
|
|
||||||
|
py.test --tb=long # デフォルトの詳細なトレースバック形式
|
||||||
|
py.test --tb=native # Python 標準ライブラリの形式
|
||||||
|
py.test --tb=short # 短いトレースバック形式
|
||||||
|
py.test --tb=line # 失敗したテストを1行表示
|
||||||
|
|
||||||
|
..
|
||||||
|
Dropping to PDB (Python Debugger) on failures
|
||||||
|
----------------------------------------------
|
||||||
|
|
||||||
|
失敗したときに PDB (Python デバッガー) を起動
|
||||||
|
---------------------------------------------
|
||||||
|
|
||||||
|
.. _PDB: http://docs.python.org/library/pdb.html
|
||||||
|
|
||||||
|
..
|
||||||
|
Python comes with a builtin Python debugger called PDB_. ``py.test``
|
||||||
|
allows one to drop into the PDB prompt via a command line option::
|
||||||
|
|
||||||
|
Python には PDB_ という組み込みの Python デバッガーが付属しています。 ``py.test`` は、コマンドラインオプションで PDB プロンプトを起動できます::
|
||||||
|
|
||||||
|
py.test --pdb
|
||||||
|
|
||||||
|
..
|
||||||
|
This will invoke the Python debugger on every failure. Often you might
|
||||||
|
only want to do this for the first failing test to understand a certain
|
||||||
|
failure situation::
|
||||||
|
|
||||||
|
このオプションは、テストが失敗したときに Python デバッガーを起動します。多くの場合、特定のエラー状況を把握するのに最初に失敗したときのみデバッガーを起動したいはずです::
|
||||||
|
|
||||||
|
py.test -x --pdb # 最初にテストが失敗したときに PDB を起動してテストセッションを終了
|
||||||
|
py.test --pdb --maxfail=3 # 最初の 3 回の失敗に対して PDB を起動
|
||||||
|
|
||||||
|
..
|
||||||
|
Setting a breakpoint / aka ``set_trace()``
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
``set_trace()`` というブレークポイントの設定
|
||||||
|
--------------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
If you want to set a breakpoint and enter the ``pdb.set_trace()`` you
|
||||||
|
can use a helper::
|
||||||
|
|
||||||
|
ブレークポイントを設定して ``pdb.set_trace()`` を行いたいなら、ヘルパー関数を使えます::
|
||||||
|
|
||||||
|
import pytest
|
||||||
|
def test_function():
|
||||||
|
...
|
||||||
|
pytest.set_trace() # PDB デバッガーを起動してトレースする
|
||||||
|
|
||||||
|
.. versionadded: 2.0.0
|
||||||
|
|
||||||
|
..
|
||||||
|
In previous versions you could only enter PDB tracing if
|
||||||
|
you disabled capturing on the command line via ``py.test -s``.
|
||||||
|
|
||||||
|
以前のバージョンでは、コマンドラインから ``py.test -s`` で標準出力の取得を無効にした場合のみ、PDB トレースが可能でした。
|
||||||
|
|
||||||
|
.. _durations:
|
||||||
|
|
||||||
|
テストの実行時間をプロファイリング
|
||||||
|
----------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Profiling test execution duration
|
||||||
|
-------------------------------------
|
||||||
|
|
||||||
|
.. versionadded: 2.2
|
||||||
|
|
||||||
|
..
|
||||||
|
To get a list of the slowest 10 test durations::
|
||||||
|
|
||||||
|
最も遅い 10 個のテスト一覧を取得するには、次のようにします::
|
||||||
|
|
||||||
|
py.test --durations=10
|
||||||
|
|
||||||
|
..
|
||||||
|
Creating JUnitXML format files
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
JUnitXML 形式のファイル作成
|
||||||
|
---------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
To create result files which can be read by Hudson_ or other Continuous
|
||||||
|
integration servers, use this invocation::
|
||||||
|
|
||||||
|
Hudson_ やその他の継続的インテグレーションサーバーで読み込める結果ファイルを作成するには、次のように実行します::
|
||||||
|
|
||||||
|
py.test --junitxml=path
|
||||||
|
|
||||||
|
..
|
||||||
|
to create an XML file at ``path``.
|
||||||
|
|
||||||
|
``path`` に XML ファイルが作成されます。
|
||||||
|
|
||||||
|
..
|
||||||
|
Creating resultlog format files
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
resultlog 形式のファイル作成
|
||||||
|
----------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
To create plain-text machine-readable result files you can issue::
|
||||||
|
|
||||||
|
コンピューターが読める平文の結果ファイルを作成するには、次のようにします::
|
||||||
|
|
||||||
|
py.test --resultlog=path
|
||||||
|
|
||||||
|
..
|
||||||
|
and look at the content at the ``path`` location. Such files are used e.g.
|
||||||
|
by the `PyPy-test`_ web page to show test results over several revisions.
|
||||||
|
|
||||||
|
``path`` に作成されたファイルがあります。そういったファイルは、例えば `PyPy-test`_ で複数バージョンでのテスト結果を表示するのに使われます。
|
||||||
|
|
||||||
|
.. _`PyPy-test`: http://codespeak.net:8099/summary
|
||||||
|
|
||||||
|
..
|
||||||
|
Sending test report to pocoo pastebin service
|
||||||
|
-----------------------------------------------------
|
||||||
|
|
||||||
|
pocoo pastbin サービスにテスト結果を投稿
|
||||||
|
----------------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
**Creating a URL for each test failure**::
|
||||||
|
|
||||||
|
**テストが失敗する毎に URL を作成します**::
|
||||||
|
|
||||||
|
py.test --pastebin=failed
|
||||||
|
|
||||||
|
..
|
||||||
|
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
|
||||||
|
for example ``-x`` if you only want to send one particular failure.
|
||||||
|
|
||||||
|
これはリモートの Paste サービスへテストの実行情報を投稿して、失敗したテスト毎に URL を提供します。特定のエラーのみを投稿したい場合、普通にテストを選択するか、例えば ``-x`` を追加します。
|
||||||
|
|
||||||
|
..
|
||||||
|
**Creating a URL for a whole test session log**::
|
||||||
|
|
||||||
|
**全てのテストセッションログに対して1つの URL を作成します**::
|
||||||
|
|
||||||
|
py.test --pastebin=all
|
||||||
|
|
||||||
|
..
|
||||||
|
Currently only pasting to the http://paste.pocoo.org service is implemented.
|
||||||
|
|
||||||
|
いまのところは、http://paste.pocoo.org サービスへのペーストのみが実装されています。
|
||||||
|
|
||||||
|
..
|
||||||
|
Calling pytest from Python code
|
||||||
|
----------------------------------------------------
|
||||||
|
|
||||||
|
Python コードからの pytest 呼び出し
|
||||||
|
-----------------------------------
|
||||||
|
|
||||||
|
.. versionadded:: 2.0
|
||||||
|
|
||||||
|
..
|
||||||
|
You can invoke ``py.test`` from Python code directly::
|
||||||
|
|
||||||
|
Python コードから直接 ``py.test`` を呼び出せます::
|
||||||
|
|
||||||
|
pytest.main()
|
||||||
|
|
||||||
|
..
|
||||||
|
this acts as if you would call "py.test" from the command line.
|
||||||
|
It will not raise ``SystemExit`` but return the exitcode instead.
|
||||||
|
You can pass in options and arguments::
|
||||||
|
|
||||||
|
これはコマンドラインから "py.test" を呼び出すように動作します。 ``SystemExit`` を発生させない代わりに終了コードを返します。次のようにオプションと引数を渡します::
|
||||||
|
|
||||||
|
pytest.main(['x', 'mytestdir'])
|
||||||
|
|
||||||
|
..
|
||||||
|
or pass in a string::
|
||||||
|
|
||||||
|
または、文字列で渡します::
|
||||||
|
|
||||||
|
pytest.main("-x mytestdir")
|
||||||
|
|
||||||
|
..
|
||||||
|
You can specify additional plugins to ``pytest.main``::
|
||||||
|
|
||||||
|
``pytest.main`` に追加のプラグインを指定できます::
|
||||||
|
|
||||||
|
# myinvoke.py の内容
|
||||||
|
import pytest
|
||||||
|
class MyPlugin:
|
||||||
|
def pytest_sessionfinish(self):
|
||||||
|
print("*** test run reporting finishing")
|
||||||
|
|
||||||
|
pytest.main("-qq", plugins=[MyPlugin()])
|
||||||
|
|
||||||
|
..
|
||||||
|
Running it will show that ``MyPlugin`` was added and its
|
||||||
|
hook was invoked::
|
||||||
|
|
||||||
|
このコードを実行すると ``MyPlugin`` が追加され、そのフックが実行されたことを表示します::
|
||||||
|
|
||||||
|
$ python myinvoke.py
|
||||||
|
collecting ... collected 0 items
|
||||||
|
|
||||||
|
in 0.00 seconds
|
||||||
|
*** test run reporting finishing
|
||||||
|
|
||||||
|
.. include:: links.inc
|
|
@ -0,0 +1,325 @@
|
||||||
|
|
||||||
|
.. _`xdist`:
|
||||||
|
|
||||||
|
xdist: pytest の分散テストプラグイン
|
||||||
|
====================================
|
||||||
|
|
||||||
|
..
|
||||||
|
xdist: pytest distributed testing plugin
|
||||||
|
===============================================================
|
||||||
|
|
||||||
|
..
|
||||||
|
The `pytest-xdist`_ plugin extends py.test with some unique
|
||||||
|
test execution modes:
|
||||||
|
|
||||||
|
`pytest-xdist`_ プラグインは、独自のテストモードで 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 failing tests. This is repeated until all
|
||||||
|
tests pass. At this point a full run is again performed.
|
||||||
|
|
||||||
|
* Looponfail: サブプロセスでテストを繰り返し実行します。各テストを実行してから py.test はプロジェクト内のファイルが変更されるまで待ち、事前に失敗したテストのみを再実行します。この動作は全てのテストが成功するまで繰り返されます。この段階になって再度、全てのテストを実行します。
|
||||||
|
|
||||||
|
..
|
||||||
|
* multiprocess Load-balancing: if you have multiple CPUs or hosts you can use
|
||||||
|
them for a combined test run. This allows to speed up
|
||||||
|
development or to use special resources of remote machines.
|
||||||
|
|
||||||
|
* マルチプロセス負荷分散: 複数 CPU または複数ホストがある場合、それらを結合テストの実行に使います。これにより開発を高速化したり、リモートマシンの特別なリソースを使ったりします。
|
||||||
|
|
||||||
|
..
|
||||||
|
* Multi-Platform coverage: you can specify different Python interpreters
|
||||||
|
or different platforms and run tests in parallel on all of them.
|
||||||
|
|
||||||
|
* マルチプラットフォームのカバレッジ: 異なる Python インタープリター、または異なるプラットフォームを指定して、全ての環境で並行してテストを実行します。
|
||||||
|
|
||||||
|
..
|
||||||
|
Before running tests remotely, ``py.test`` efficiently "rsyncs" your
|
||||||
|
program source code to the remote place. All test results
|
||||||
|
are reported back and displayed to your local terminal.
|
||||||
|
You may specify different Python versions and interpreters.
|
||||||
|
|
||||||
|
リモート環境でテストを実行する前に、 ``py.test`` はプログラムのソースコードをリモートマシンへ効率的に "rsync" します。全てのテスト結果は、ローカルマシンのターミナル上で表示されます。異なる Python バージョンやインタープリターも指定できます。
|
||||||
|
|
||||||
|
..
|
||||||
|
Installation of xdist plugin
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
xdist プラグインのインストール
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
..
|
||||||
|
Install the plugin with::
|
||||||
|
|
||||||
|
プラグインをインストールします::
|
||||||
|
|
||||||
|
easy_install pytest-xdist
|
||||||
|
|
||||||
|
# または
|
||||||
|
|
||||||
|
pip install pytest-xdist
|
||||||
|
|
||||||
|
..
|
||||||
|
or use the package in develop/in-place mode with
|
||||||
|
a checkout of the `pytest-xdist repository`_ ::
|
||||||
|
|
||||||
|
もしくは `pytest-xdist リポジトリ`_ からチェックアウトして develop コマンドでパッケージを使います::
|
||||||
|
|
||||||
|
python setup.py develop
|
||||||
|
|
||||||
|
..
|
||||||
|
Usage examples
|
||||||
|
---------------------
|
||||||
|
|
||||||
|
使用例
|
||||||
|
------
|
||||||
|
|
||||||
|
.. _`xdistcpu`:
|
||||||
|
|
||||||
|
複数の CPU を使ったテスト実行の高速化
|
||||||
|
+++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
..
|
||||||
|
Speed up test runs by sending tests to multiple CPUs
|
||||||
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
..
|
||||||
|
To send tests to multiple CPUs, type::
|
||||||
|
|
||||||
|
複数の CPU でテストを行うには、次のように実行します::
|
||||||
|
|
||||||
|
py.test -n NUM
|
||||||
|
|
||||||
|
..
|
||||||
|
Especially for longer running tests or tests requiring
|
||||||
|
a lot of I/O this can lead to considerable speed ups.
|
||||||
|
|
||||||
|
特に長時間実行されるテスト、またはたくさんの I/O を必要とするテストの速度向上が見込めます。
|
||||||
|
|
||||||
|
..
|
||||||
|
Running tests in a Python subprocess
|
||||||
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
Python のサブプロセスでテスト実行
|
||||||
|
+++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
..
|
||||||
|
To instantiate a Python-2.4 subprocess and send tests to it, you may type::
|
||||||
|
|
||||||
|
Python 2.4 の subprocess をインスタンス化するには、そこにテストを送り、次のように実行します::
|
||||||
|
|
||||||
|
py.test -d --tx popen//python=python2.4
|
||||||
|
|
||||||
|
..
|
||||||
|
This will start a subprocess which is run with the "python2.4"
|
||||||
|
Python interpreter, found in your system binary lookup path.
|
||||||
|
|
||||||
|
システムのバイナリ検索パスで見つけた "Python 2.4" インタープリターで実行するサブプロセスを開始します。
|
||||||
|
|
||||||
|
..
|
||||||
|
If you prefix the --tx option value like this::
|
||||||
|
|
||||||
|
次のように --tx オプションに値を指定する場合::
|
||||||
|
|
||||||
|
py.test -d --tx 3*popen//python=python2.4
|
||||||
|
|
||||||
|
..
|
||||||
|
then three subprocesses would be created and the tests
|
||||||
|
will be distributed to three subprocesses and run simultanously.
|
||||||
|
|
||||||
|
3つのサブプロセスが作成され、その3つのサブプロセスにテストが分散されて並行で実行されます。
|
||||||
|
|
||||||
|
.. _looponfailing:
|
||||||
|
|
||||||
|
looponfailing モードでのテスト実行
|
||||||
|
++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
..
|
||||||
|
Running tests in looponfailing mode
|
||||||
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
..
|
||||||
|
For refactoring a project with a medium or large test suite
|
||||||
|
you can use the looponfailing mode. Simply add the ``--f`` option::
|
||||||
|
|
||||||
|
中規模または大規模のテストスイートをもつプロジェクトをリファクタリングするために、looponfailing モードが便利です。単純に ``--f`` オプションを追加します::
|
||||||
|
|
||||||
|
py.test -f
|
||||||
|
|
||||||
|
..
|
||||||
|
and py.test will run your tests. Assuming you have failures it will then
|
||||||
|
wait for file changes and re-run the failing test set. File changes are detected by looking at ``looponfailingroots`` root directories and all of their contents (recursively). If the default for this value does not work for you you
|
||||||
|
can change it in your project by setting a configuration option::
|
||||||
|
|
||||||
|
py.test はテストを実行します。ここで実行したテストに失敗すると仮定して、ファイルの更新を待ってからその失敗したテストを再実行します。ファイルの更新は ``looponfailingroots`` というルートディレクトリとその全てのコンテンツを (再帰的に) 調べることで検出されます。このデフォルト値が意図したように作用しないなら、設定オプションを追加することで自分のプロジェクト向けの値を変更できます::
|
||||||
|
|
||||||
|
# pytest.ini, setup.cfg または tox.ini ファイルの内容
|
||||||
|
[pytest]
|
||||||
|
looponfailroots = mypkg testdir
|
||||||
|
|
||||||
|
..
|
||||||
|
This would lead to only looking for file changes in the respective directories, specified relatively to the ini-file's directory.
|
||||||
|
|
||||||
|
この設定は ini ファイルがあるディレクトリからみて、相対パスで指定したディレクトリのファイルの更新のみを調べるようにします。
|
||||||
|
|
||||||
|
..
|
||||||
|
Sending tests to remote SSH accounts
|
||||||
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
リモートの SSH アカウントへテストを送信
|
||||||
|
+++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
..
|
||||||
|
Suppose you have a package ``mypkg`` which contains some
|
||||||
|
tests that you can successfully run locally. And you also
|
||||||
|
have a ssh-reachable machine ``myhost``. Then
|
||||||
|
you can ad-hoc distribute your tests by typing::
|
||||||
|
|
||||||
|
ローカルで正常に実行できるテストを含む ``mypkg`` と、ssh でログインできるマシン ``myhost`` もあると仮定します。次のように実行してアドホックに分散テストを実行できます::
|
||||||
|
|
||||||
|
py.test -d --tx ssh=myhostpopen --rsyncdir mypkg mypkg
|
||||||
|
|
||||||
|
..
|
||||||
|
This will synchronize your ``mypkg`` package directory
|
||||||
|
with a remote ssh account and then collect and run your
|
||||||
|
tests at the remote side.
|
||||||
|
|
||||||
|
これはリモートの ssh アカウントで ``mypkg`` パッケージのディレクトリを同期させ、リモートマシン上でテストを実行します。
|
||||||
|
|
||||||
|
..
|
||||||
|
You can specify multiple ``--rsyncdir`` directories
|
||||||
|
to be sent to the remote side.
|
||||||
|
|
||||||
|
リモートマシンへ送るために 複数の ``--rsyncdir`` ディレクトリを指定できます。
|
||||||
|
|
||||||
|
.. XXX CHECK
|
||||||
|
|
||||||
|
**NOTE:** For py.test to collect and send tests correctly
|
||||||
|
you not only need to make sure all code and tests
|
||||||
|
directories are rsynced, but that any test (sub) directory
|
||||||
|
also has an ``__init__.py`` file because internally
|
||||||
|
py.test references tests as a fully qualified python
|
||||||
|
module path. **You will otherwise get strange errors**
|
||||||
|
during setup of the remote side.
|
||||||
|
|
||||||
|
..
|
||||||
|
Sending tests to remote Socket Servers
|
||||||
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
リモートのソケットサーバーへテストを送信
|
||||||
|
++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
..
|
||||||
|
Download the single-module `socketserver.py`_ Python program
|
||||||
|
and run it like this::
|
||||||
|
|
||||||
|
`socketserver.py`_ という単一モジュールの Python プログラムをダウンロードし、次のように実行してください::
|
||||||
|
|
||||||
|
python socketserver.py
|
||||||
|
|
||||||
|
..
|
||||||
|
It will tell you that it starts listening on the default
|
||||||
|
port. You can now on your home machine specify this
|
||||||
|
new socket host with something like this::
|
||||||
|
|
||||||
|
このプログラムはデフォルトのポートで待機状態を起動します。自宅のマシン上で、何かのパッケージと一緒にこの新たなソケットホストを指定できます::
|
||||||
|
|
||||||
|
py.test -d --tx socket=192.168.1.102:8888 --rsyncdir mypkg mypkg
|
||||||
|
|
||||||
|
.. _`atonce`:
|
||||||
|
|
||||||
|
多くのプラットフォーム上で同時にテストを実行
|
||||||
|
++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
..
|
||||||
|
Running tests on many platforms at once
|
||||||
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
..
|
||||||
|
The basic command to run tests on multiple platforms is::
|
||||||
|
|
||||||
|
複数のプラットフォームでテストを実行する基本的なコマンドです::
|
||||||
|
|
||||||
|
py.test --dist=each --tx=spec1 --tx=spec2
|
||||||
|
|
||||||
|
..
|
||||||
|
If you specify a windows host, an OSX host and a Linux
|
||||||
|
environment this command will send each tests to all
|
||||||
|
platforms - and report back failures from all platforms
|
||||||
|
at once. The specifications strings use the `xspec syntax`_.
|
||||||
|
|
||||||
|
Windows ホスト、OSX ホスト、Linux 環境を指定する場合、このコマンドはそれぞれのテストを全てのプラットフォームに送信します。そして、全てのプラットフォームから同時に失敗レポートを受け取ります。この設定には `xspec 構文`_ を使います。
|
||||||
|
|
||||||
|
.. _`xspec syntax`: http://codespeak.net/execnet/basics.html#xspec
|
||||||
|
.. _`xspec 構文`: http://codespeak.net/execnet/basics.html#xspec
|
||||||
|
|
||||||
|
.. _`socketserver.py`: http://bitbucket.org/hpk42/execnet/raw/2af991418160/execnet/script/socketserver.py
|
||||||
|
|
||||||
|
.. _`execnet`: http://codespeak.net/execnet
|
||||||
|
|
||||||
|
..
|
||||||
|
Specifying test exec environments in an ini file
|
||||||
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
Ini ファイルでテスト実行環境の指定
|
||||||
|
++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
..
|
||||||
|
pytest (since version 2.0) supports ini-style configuration.
|
||||||
|
For example, you could make running with three subprocesses your default::
|
||||||
|
|
||||||
|
pytest (バージョン 2.0) は ini スタイルの設定ファイルに対応しています。例えば、デフォルトで3つのサブプロセスを使ってテストを実行させます::
|
||||||
|
|
||||||
|
[pytest]
|
||||||
|
addopts = -n3
|
||||||
|
|
||||||
|
..
|
||||||
|
You can also add default environments like this::
|
||||||
|
|
||||||
|
次のようにしてデフォルト環境も追加できます::
|
||||||
|
|
||||||
|
[pytest]
|
||||||
|
addopts = --tx ssh=myhost//python=python2.5 --tx ssh=myhost//python=python2.6
|
||||||
|
|
||||||
|
..
|
||||||
|
and then just type::
|
||||||
|
|
||||||
|
そして、次のように入力して実行すると::
|
||||||
|
|
||||||
|
py.test --dist=each
|
||||||
|
|
||||||
|
..
|
||||||
|
to run tests in each of the environments.
|
||||||
|
|
||||||
|
それぞれの環境でテストが実行されます。
|
||||||
|
|
||||||
|
..
|
||||||
|
Specifying "rsync" dirs in an ini-file
|
||||||
|
+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
ini ファイルで "rsync" ディレクトリの指定
|
||||||
|
+++++++++++++++++++++++++++++++++++++++++
|
||||||
|
|
||||||
|
..
|
||||||
|
In a ``tox.ini`` or ``setup.cfg`` file in your root project directory
|
||||||
|
you may specify directories to include or to exclude in synchronisation::
|
||||||
|
|
||||||
|
プロジェクトのルートディレクトリに ``tox.ini`` か ``setup.cfg`` ファイルを置き、同期に含める、または除外するディレクトリを指定することもできます::
|
||||||
|
|
||||||
|
[pytest]
|
||||||
|
rsyncdirs = . mypkg helperpkg
|
||||||
|
rsyncignore = .hg
|
||||||
|
|
||||||
|
..
|
||||||
|
These directory specifications are relative to the directory
|
||||||
|
where the configuration file was found.
|
||||||
|
|
||||||
|
ここで設定されるディレクトリは、設定ファイルの場所から相対パスでディレクトリを指定します。
|
||||||
|
|
||||||
|
.. _`pytest-xdist`: http://pypi.python.org/pypi/pytest-xdist
|
||||||
|
.. _`pytest-xdist repository`: http://bitbucket.org/hpk42/pytest-xdist
|
||||||
|
.. _`pytest-xdist リポジトリ`: http://bitbucket.org/hpk42/pytest-xdist
|
||||||
|
.. _`pytest`: http://pytest.org
|
||||||
|
|
|
@ -0,0 +1,107 @@
|
||||||
|
.. _xunitsetup:
|
||||||
|
|
||||||
|
===================================================
|
||||||
|
拡張された xUnit スタイルのセットアップフィクスチャ
|
||||||
|
===================================================
|
||||||
|
|
||||||
|
..
|
||||||
|
====================================
|
||||||
|
Extended xUnit style setup fixtures
|
||||||
|
====================================
|
||||||
|
|
||||||
|
.. _`funcargs`: funcargs.html
|
||||||
|
.. _`test parametrization`: funcargs.html#parametrizing-tests
|
||||||
|
.. _`unittest plugin`: plugin/unittest.html
|
||||||
|
.. _`xUnit`: http://en.wikipedia.org/wiki/XUnit
|
||||||
|
|
||||||
|
..
|
||||||
|
Python, Java and many other languages support xUnit_ style testing.
|
||||||
|
This typically involves the call of a ``setup`` ("fixture") method
|
||||||
|
before running a test function and ``teardown`` after it has finished.
|
||||||
|
``py.test`` supports a more fine-grained model of setup/teardown
|
||||||
|
handling by optionally calling per-module and per-class hooks.
|
||||||
|
|
||||||
|
Python、Java および他の多くの言語は xUnit_ スタイルのテストに対応しています。これはテスト関数の実行前に ``setup`` ("フィクスチャ") メソッドを、テスト関数の実行後に ``teardown`` メソッドを呼び出す典型的なスタイルです。 ``py.test`` は、モジュール単位やクラス単位のフックを必要に応じて呼び出して処理する、より細分化された setup/teardown のモデルに対応しています。
|
||||||
|
|
||||||
|
..
|
||||||
|
Module level setup/teardown
|
||||||
|
=============================================
|
||||||
|
|
||||||
|
モジュールレベルの setup/teardown
|
||||||
|
=================================
|
||||||
|
|
||||||
|
..
|
||||||
|
If you have multiple test functions and test classes in a single
|
||||||
|
module you can optionally implement the following fixture methods
|
||||||
|
which will usually be called once for all the functions::
|
||||||
|
|
||||||
|
1つのモジュールに複数のテスト関数やテストクラスがある場合、必要に応じて、全ての関数に対して通常1度だけ呼び出されるフィクスチャメソッドを実装できます::
|
||||||
|
|
||||||
|
def setup_module(module):
|
||||||
|
""" モジュールの実行に関して任意の状態をセットアップする """
|
||||||
|
|
||||||
|
def teardown_module(module):
|
||||||
|
""" setup_module で事前にセットアップした状態を解体する """
|
||||||
|
|
||||||
|
..
|
||||||
|
Class level setup/teardown
|
||||||
|
=============================================
|
||||||
|
|
||||||
|
クラスレベルの setup/teardown
|
||||||
|
=============================
|
||||||
|
|
||||||
|
..
|
||||||
|
Similarly, the following methods are called at class level before
|
||||||
|
and after all test methods of the class are called::
|
||||||
|
|
||||||
|
同様に、クラスの全てのテストメソッドが呼び出される前後に、クラスレベルで次のメソッドが呼ばれます::
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def setup_class(cls):
|
||||||
|
""" (通常はテストを含む) クラスの実行に関して任意の状態をセットアップする """
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def teardown_class(cls):
|
||||||
|
""" setup_class で事前にセットアップした状態を解体する """
|
||||||
|
|
||||||
|
..
|
||||||
|
Method and function level setup/teardown
|
||||||
|
=============================================
|
||||||
|
|
||||||
|
メソッドや関数レベルの setup/teardown
|
||||||
|
=====================================
|
||||||
|
|
||||||
|
..
|
||||||
|
Similarly, the following methods are called around each method invocation::
|
||||||
|
|
||||||
|
同様に、それぞれのメソッド呼び出しの前後で次のメソッドが呼ばれます::
|
||||||
|
|
||||||
|
def setup_method(self, method):
|
||||||
|
""" クラス内のメソッドの実行に関して任意の状態をセットアップする
|
||||||
|
setup_method はクラスのテストメソッド単位で実行される
|
||||||
|
"""
|
||||||
|
|
||||||
|
def teardown_method(self, method):
|
||||||
|
""" setup_method で事前にセットアップした状態を解体する """
|
||||||
|
|
||||||
|
..
|
||||||
|
If you would rather define test functions directly at module level
|
||||||
|
you can also use the following functions to implement fixtures::
|
||||||
|
|
||||||
|
モジュールレベルで直接的にテスト関数を定義したいなら、次の関数もフィクスチャを実装するのに使えます::
|
||||||
|
|
||||||
|
def setup_function(function):
|
||||||
|
""" 関数の実行に関して任意の状態をセットアップする
|
||||||
|
モジュール内の関数単位で実行される
|
||||||
|
"""
|
||||||
|
|
||||||
|
def teardown_function(function):
|
||||||
|
""" setup_function で事前にセットアップした状態を解体する """
|
||||||
|
|
||||||
|
..
|
||||||
|
Note that it is possible for setup/teardown pairs to be invoked multiple times
|
||||||
|
per testing process.
|
||||||
|
|
||||||
|
テストプロセスにつき複数回実行される setup/teardown の組み合わせに使えることも覚えておいてください。
|
||||||
|
|
||||||
|
.. _`unittest.py module`: http://docs.python.org/library/unittest.html
|
Loading…
Reference in New Issue