summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichał Górny <mgorny@gentoo.org>2023-02-05 12:10:13 +0100
committerMichał Górny <mgorny@gentoo.org>2023-02-05 12:10:13 +0100
commit9ab20cd7a6c7046b6d62bee094a18049bf22cfa4 (patch)
treebc11d3d956820ef8067f496cd13327d48de13e4f /guide/test.html
parentUpdate Guide to 3f1ccee (diff)
downloadpython-9ab20cd7a6c7046b6d62bee094a18049bf22cfa4.tar.gz
python-9ab20cd7a6c7046b6d62bee094a18049bf22cfa4.tar.bz2
python-9ab20cd7a6c7046b6d62bee094a18049bf22cfa4.zip
Update Guide to 51dd5f6
Signed-off-by: Michał Górny <mgorny@gentoo.org>
Diffstat (limited to 'guide/test.html')
-rw-r--r--guide/test.html291
1 files changed, 280 insertions, 11 deletions
diff --git a/guide/test.html b/guide/test.html
index 7f7d192..ec74507 100644
--- a/guide/test.html
+++ b/guide/test.html
@@ -6,7 +6,7 @@
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" /><meta name="generator" content="Docutils 0.19: https://docutils.sourceforge.io/" />
- <title>Resolving test suite problems &#8212; Gentoo Python Guide documentation</title>
+ <title>Tests in Python packages &#8212; Gentoo Python Guide documentation</title>
<link rel="stylesheet" type="text/css" href="_static/pygments.css" />
<link rel="stylesheet" type="text/css" href="_static/alabaster.css" />
<script data-url_root="./" id="documentation_options" src="_static/documentation_options.js"></script>
@@ -14,8 +14,8 @@
<script src="_static/sphinx_highlight.js"></script>
<link rel="index" title="Index" href="genindex.html" />
<link rel="search" title="Search" href="search.html" />
- <link rel="next" title="pytest recipes" href="pytest.html" />
- <link rel="prev" title="Advanced dependencies" href="depend.html" />
+ <link rel="next" title="distutils-r1 legacy concepts" href="distutils-legacy.html" />
+ <link rel="prev" title="distutils-r1 — standard Python build systems" href="distutils.html" />
<link rel="stylesheet" href="_static/custom.css" type="text/css" />
@@ -32,8 +32,249 @@
<div class="body" role="main">
- <section id="resolving-test-suite-problems">
-<h1>Resolving test suite problems<a class="headerlink" href="#resolving-test-suite-problems" title="Permalink to this heading">¶</a></h1>
+ <section id="tests-in-python-packages">
+<h1>Tests in Python packages<a class="headerlink" href="#tests-in-python-packages" title="Permalink to this heading">¶</a></h1>
+<section id="why-is-running-tests-important">
+<h2>Why is running tests important?<a class="headerlink" href="#why-is-running-tests-important" title="Permalink to this heading">¶</a></h2>
+<p>Since Python performs only minimal build-time (or more precisely,
+import-time) checking of correctness, it is important to run tests
+of Python packages in order to catch any problems early. This is
+especially important for permitting others to verify support for new
+Python implementations.</p>
+</section>
+<section id="using-distutils-enable-tests">
+<span id="index-0"></span><h2>Using distutils_enable_tests<a class="headerlink" href="#using-distutils-enable-tests" title="Permalink to this heading">¶</a></h2>
+<section id="basic-use-case">
+<h3>Basic use case<a class="headerlink" href="#basic-use-case" title="Permalink to this heading">¶</a></h3>
+<p>The simplest way of enabling tests is to call <code class="docutils literal notranslate"><span class="pre">distutils_enable_tests</span></code>
+in global scope, passing the test runner name as the first argument.
+This function takes care of declaring test phase, setting appropriate
+dependencies and <code class="docutils literal notranslate"><span class="pre">test</span></code> USE flag if necessary. If called after
+setting <code class="docutils literal notranslate"><span class="pre">RDEPEND</span></code>, it also copies it to test dependencies.</p>
+<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="w"> </span><span class="c1"># Copyright 1999-2020 Gentoo Authors</span>
+<span class="w"> </span><span class="c1"># Distributed under the terms of the GNU General Public License v2</span>
+
+<span class="w"> </span><span class="nv">EAPI</span><span class="o">=</span><span class="m">7</span>
+
+<span class="w"> </span><span class="nv">PYTHON_COMPAT</span><span class="o">=(</span><span class="w"> </span>python2_7<span class="w"> </span>python3_<span class="o">{</span><span class="m">6</span>,7,8<span class="o">}</span><span class="w"> </span>pypy3<span class="w"> </span><span class="o">)</span>
+<span class="w"> </span>inherit<span class="w"> </span>distutils-r1
+
+<span class="w"> </span><span class="nv">DESCRIPTION</span><span class="o">=</span><span class="s2">&quot;An easy whitelist-based HTML-sanitizing tool&quot;</span>
+<span class="w"> </span><span class="nv">HOMEPAGE</span><span class="o">=</span><span class="s2">&quot;https://github.com/mozilla/bleach https://pypi.org/project/bleach/&quot;</span>
+<span class="w"> </span><span class="nv">SRC_URI</span><span class="o">=</span><span class="s2">&quot;mirror://pypi/</span><span class="si">${</span><span class="nv">PN</span><span class="p">:</span><span class="nv">0</span><span class="p">:</span><span class="nv">1</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">PN</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">P</span><span class="si">}</span><span class="s2">.tar.gz&quot;</span>
+
+<span class="w"> </span><span class="nv">LICENSE</span><span class="o">=</span><span class="s2">&quot;Apache-2.0&quot;</span>
+<span class="w"> </span><span class="nv">SLOT</span><span class="o">=</span><span class="s2">&quot;0&quot;</span>
+<span class="w"> </span><span class="nv">KEYWORDS</span><span class="o">=</span><span class="s2">&quot;~alpha ~amd64 ~arm ~arm64 ~hppa ~ia64 ~mips ~ppc ~ppc64 ~s390 ~sparc ~x86&quot;</span>
+
+<span class="w"> </span><span class="nv">RDEPEND</span><span class="o">=</span><span class="s2">&quot;</span>
+<span class="s2"> dev-python/six[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
+<span class="s2"> dev-python/webencodings[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
+<span class="s2"> &quot;</span>
+
+<span class="hll"><span class="w"> </span>distutils_enable_tests<span class="w"> </span>pytest
+</span></pre></div>
+</div>
+<p>The valid values include:</p>
+<ul class="simple">
+<li><p><code class="docutils literal notranslate"><span class="pre">nose</span></code> for <code class="docutils literal notranslate"><span class="pre">dev-python/nose</span></code> (<em>deprecated</em>)</p></li>
+<li><p><code class="docutils literal notranslate"><span class="pre">pytest</span></code> for <code class="docutils literal notranslate"><span class="pre">dev-python/pytest</span></code></p></li>
+<li><p><code class="docutils literal notranslate"><span class="pre">setup.py</span></code> to call <code class="docutils literal notranslate"><span class="pre">setup.py</span> <span class="pre">test</span></code> (<em>deprecated</em>)</p></li>
+<li><p><code class="docutils literal notranslate"><span class="pre">unittest</span></code> to use built-in unittest discovery</p></li>
+</ul>
+<p>See <a class="reference internal" href="#choosing-the-correct-test-runner">choosing the correct test runner</a> for more information.</p>
+</section>
+<section id="adding-more-test-dependencies">
+<h3>Adding more test dependencies<a class="headerlink" href="#adding-more-test-dependencies" title="Permalink to this heading">¶</a></h3>
+<p>Additional test dependencies can be specified in <code class="docutils literal notranslate"><span class="pre">test?</span></code> conditional.
+The flag normally does not need to be explicitly declared,
+as <code class="docutils literal notranslate"><span class="pre">distutils_enable_tests</span></code> does that in the majority of cases.</p>
+<p>Please read the section on <a class="reference internal" href="#undesirable-test-dependencies">undesirable test dependencies</a> too.</p>
+<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="w"> </span><span class="c1"># Copyright 1999-2020 Gentoo Authors</span>
+<span class="w"> </span><span class="c1"># Distributed under the terms of the GNU General Public License v2</span>
+
+<span class="w"> </span><span class="nv">EAPI</span><span class="o">=</span><span class="m">6</span>
+
+<span class="w"> </span><span class="nv">PYTHON_COMPAT</span><span class="o">=(</span><span class="w"> </span>python2_7<span class="w"> </span>python3_<span class="o">{</span><span class="m">6</span>,7,8<span class="o">}</span><span class="w"> </span>pypy3<span class="w"> </span><span class="o">)</span>
+<span class="w"> </span>inherit<span class="w"> </span>distutils-r1
+
+<span class="w"> </span><span class="nv">DESCRIPTION</span><span class="o">=</span><span class="s2">&quot;Universal encoding detector&quot;</span>
+<span class="w"> </span><span class="nv">HOMEPAGE</span><span class="o">=</span><span class="s2">&quot;https://github.com/chardet/chardet https://pypi.org/project/chardet/&quot;</span>
+<span class="w"> </span><span class="nv">SRC_URI</span><span class="o">=</span><span class="s2">&quot;https://github.com/chardet/chardet/archive/</span><span class="si">${</span><span class="nv">PV</span><span class="si">}</span><span class="s2">.tar.gz -&gt; </span><span class="si">${</span><span class="nv">P</span><span class="si">}</span><span class="s2">.tar.gz&quot;</span>
+
+<span class="w"> </span><span class="nv">LICENSE</span><span class="o">=</span><span class="s2">&quot;LGPL-2.1&quot;</span>
+<span class="w"> </span><span class="nv">SLOT</span><span class="o">=</span><span class="s2">&quot;0&quot;</span>
+<span class="w"> </span><span class="nv">KEYWORDS</span><span class="o">=</span><span class="s2">&quot;~alpha amd64 arm arm64 hppa ia64 ~m68k ~mips ppc ppc64 s390 ~sh sparc x86 ~x64-cygwin ~amd64-linux ~x86-linux ~x64-macos ~x86-macos ~x64-solaris&quot;</span>
+
+<span class="w"> </span><span class="nv">DEPEND</span><span class="o">=</span><span class="s2">&quot;</span>
+<span class="hll"><span class="s2"> test? ( dev-python/hypothesis[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">] )</span>
+</span><span class="s2"> &quot;</span>
+
+<span class="hll"><span class="w"> </span>distutils_enable_tests<span class="w"> </span>pytest
+</span></pre></div>
+</div>
+<p>Note that <code class="docutils literal notranslate"><span class="pre">distutils_enable_tests</span></code> modifies variables directly
+in the ebuild environment. This means that if you wish to change their
+values, you need to append to them, i.e. the bottom part of that ebuild
+can be rewritten as:</p>
+<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="w"> </span>distutils_enable_tests<span class="w"> </span>pytest
+
+<span class="hll"><span class="w"> </span><span class="nv">DEPEND</span><span class="o">+=</span><span class="s2">&quot;</span>
+</span><span class="s2"> test? ( dev-python/hypothesis[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">] )</span>
+<span class="s2"> &quot;</span>
+</pre></div>
+</div>
+</section>
+<section id="installing-the-package-before-running-tests">
+<h3>Installing the package before running tests<a class="headerlink" href="#installing-the-package-before-running-tests" title="Permalink to this heading">¶</a></h3>
+<p>In PEP 517 mode, the eclass automatically exposes a venv-style install
+tree to the test phase. No explicit action in necessary.</p>
+<p>In the legacy mode, <code class="docutils literal notranslate"><span class="pre">distutils_enable_tests</span></code> has an optional
+<code class="docutils literal notranslate"><span class="pre">--install</span></code> option that can be used to force performing an install
+to a temporary directory. More information can be found in the legacy
+section.</p>
+</section>
+<section id="customizing-the-test-phase">
+<h3>Customizing the test phase<a class="headerlink" href="#customizing-the-test-phase" title="Permalink to this heading">¶</a></h3>
+<p>If additional pre-/post-test phase actions need to be performed,
+they can be easily injected via overriding <code class="docutils literal notranslate"><span class="pre">src_test()</span></code> and making
+it call <code class="docutils literal notranslate"><span class="pre">distutils-r1_src_test</span></code>:</p>
+<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="w"> </span><span class="c1"># Copyright 1999-2020 Gentoo Authors</span>
+<span class="w"> </span><span class="c1"># Distributed under the terms of the GNU General Public License v2</span>
+
+<span class="w"> </span><span class="nv">EAPI</span><span class="o">=</span><span class="m">7</span>
+
+<span class="w"> </span><span class="nv">PYTHON_COMPAT</span><span class="o">=(</span><span class="w"> </span>python3_<span class="o">{</span><span class="m">6</span>,7,8<span class="o">}</span><span class="w"> </span><span class="o">)</span>
+<span class="w"> </span>inherit<span class="w"> </span>distutils-r1
+
+<span class="w"> </span><span class="nv">DESCRIPTION</span><span class="o">=</span><span class="s2">&quot;Extra features for standard library&#39;s cmd module&quot;</span>
+<span class="w"> </span><span class="nv">HOMEPAGE</span><span class="o">=</span><span class="s2">&quot;https://github.com/python-cmd2/cmd2&quot;</span>
+<span class="w"> </span><span class="nv">SRC_URI</span><span class="o">=</span><span class="s2">&quot;mirror://pypi/</span><span class="si">${</span><span class="nv">PN</span><span class="p">:</span><span class="nv">0</span><span class="p">:</span><span class="nv">1</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">PN</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">P</span><span class="si">}</span><span class="s2">.tar.gz&quot;</span>
+
+<span class="w"> </span><span class="nv">LICENSE</span><span class="o">=</span><span class="s2">&quot;MIT&quot;</span>
+<span class="w"> </span><span class="nv">SLOT</span><span class="o">=</span><span class="s2">&quot;0&quot;</span>
+<span class="w"> </span><span class="nv">KEYWORDS</span><span class="o">=</span><span class="s2">&quot;~amd64 ~arm ~arm64 ~ppc64 ~x86 ~amd64-linux ~x86-linux&quot;</span>
+
+<span class="w"> </span><span class="nv">RDEPEND</span><span class="o">=</span><span class="s2">&quot;</span>
+<span class="s2"> dev-python/attrs[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
+<span class="s2"> &gt;=dev-python/colorama-0.3.7[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
+<span class="s2"> &gt;=dev-python/pyperclip-1.6[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
+<span class="s2"> dev-python/six[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
+<span class="s2"> dev-python/wcwidth[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
+<span class="s2"> &quot;</span>
+<span class="w"> </span><span class="nv">BDEPEND</span><span class="o">=</span><span class="s2">&quot;</span>
+<span class="s2"> dev-python/setuptools_scm[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
+<span class="s2"> &quot;</span>
+
+<span class="w"> </span>distutils_enable_tests<span class="w"> </span>pytest
+
+<span class="hll"><span class="w"> </span>src_test<span class="o">()</span><span class="w"> </span><span class="o">{</span>
+</span><span class="hll"><span class="w"> </span><span class="c1"># tests rely on very specific text wrapping...</span>
+</span><span class="hll"><span class="w"> </span><span class="nb">local</span><span class="w"> </span>-x<span class="w"> </span><span class="nv">COLUMNS</span><span class="o">=</span><span class="m">80</span>
+</span><span class="hll"><span class="w"> </span>distutils-r1_src_test
+</span><span class="hll"><span class="w"> </span><span class="o">}</span>
+</span></pre></div>
+</div>
+<p>If the actual test command needs to be customized, or a non-standard
+test tool needs to be used, you can define a <code class="docutils literal notranslate"><span class="pre">python_test()</span></code> sub-phase
+function. This function is called for every enabled Python target
+by the default <code class="docutils literal notranslate"><span class="pre">src_test</span></code> implementation. This can either be combined
+with <code class="docutils literal notranslate"><span class="pre">distutils_enable_tests</span></code> call, or used instead of it. In fact,
+the former function simply defines a <code class="docutils literal notranslate"><span class="pre">python_test()</span></code> function as part
+of its logic.</p>
+<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span><span class="w"> </span><span class="c1"># Copyright 1999-2020 Gentoo Authors</span>
+<span class="w"> </span><span class="c1"># Distributed under the terms of the GNU General Public License v2</span>
+
+<span class="w"> </span><span class="nv">EAPI</span><span class="o">=</span><span class="m">7</span>
+
+<span class="w"> </span><span class="nv">PYTHON_COMPAT</span><span class="o">=(</span><span class="w"> </span>python<span class="o">{</span>2_7,3_6,3_7,3_8<span class="o">}</span><span class="w"> </span>pypy3<span class="w"> </span><span class="o">)</span>
+<span class="w"> </span>inherit<span class="w"> </span>distutils-r1
+
+<span class="w"> </span><span class="nv">DESCRIPTION</span><span class="o">=</span><span class="s2">&quot;Bash tab completion for argparse&quot;</span>
+<span class="w"> </span><span class="nv">HOMEPAGE</span><span class="o">=</span><span class="s2">&quot;https://pypi.org/project/argcomplete/&quot;</span>
+<span class="w"> </span><span class="nv">SRC_URI</span><span class="o">=</span><span class="s2">&quot;mirror://pypi/</span><span class="si">${</span><span class="nv">PN</span><span class="p">:</span><span class="nv">0</span><span class="p">:</span><span class="nv">1</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">PN</span><span class="si">}</span><span class="s2">/</span><span class="si">${</span><span class="nv">P</span><span class="si">}</span><span class="s2">.tar.gz&quot;</span>
+
+<span class="w"> </span><span class="nv">LICENSE</span><span class="o">=</span><span class="s2">&quot;Apache-2.0&quot;</span>
+<span class="w"> </span><span class="nv">SLOT</span><span class="o">=</span><span class="s2">&quot;0&quot;</span>
+<span class="w"> </span><span class="nv">KEYWORDS</span><span class="o">=</span><span class="s2">&quot;~amd64 ~arm ~arm64 ~hppa ~x86 ~amd64-linux ~x86-linux ~x64-macos&quot;</span>
+<span class="hll"><span class="w"> </span><span class="nv">IUSE</span><span class="o">=</span><span class="s2">&quot;test&quot;</span>
+</span><span class="hll"><span class="w"> </span><span class="nv">RESTRICT</span><span class="o">=</span><span class="s2">&quot;!test? ( test )&quot;</span>
+</span>
+<span class="w"> </span><span class="nv">RDEPEND</span><span class="o">=</span><span class="s2">&quot;</span>
+<span class="s2"> </span><span class="k">$(</span>python_gen_cond_dep<span class="w"> </span><span class="s1">&#39;</span>
+<span class="s1"> &lt;dev-python/importlib_metadata-2[${PYTHON_USEDEP}]</span>
+<span class="s1"> &#39;</span><span class="w"> </span>-2<span class="w"> </span>python3_<span class="o">{</span><span class="m">5</span>,6,7<span class="o">}</span><span class="w"> </span>pypy3<span class="k">)</span><span class="s2">&quot;</span>
+<span class="w"> </span><span class="c1"># pip is called as an external tool</span>
+<span class="w"> </span><span class="nv">BDEPEND</span><span class="o">=</span><span class="s2">&quot;</span>
+<span class="s2"> dev-python/setuptools[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
+<span class="hll"><span class="s2"> test? (</span>
+</span><span class="hll"><span class="s2"> app-shells/fish</span>
+</span><span class="hll"><span class="s2"> app-shells/tcsh</span>
+</span><span class="hll"><span class="s2"> dev-python/pexpect[</span><span class="si">${</span><span class="nv">PYTHON_USEDEP</span><span class="si">}</span><span class="s2">]</span>
+</span><span class="hll"><span class="s2"> dev-python/pip</span>
+</span><span class="hll"><span class="s2"> )&quot;</span>
+</span>
+<span class="hll"><span class="w"> </span>python_test<span class="o">()</span><span class="w"> </span><span class="o">{</span>
+</span><span class="hll"><span class="w"> </span><span class="s2">&quot;</span><span class="si">${</span><span class="nv">EPYTHON</span><span class="si">}</span><span class="s2">&quot;</span><span class="w"> </span>test/test.py<span class="w"> </span>-v<span class="w"> </span><span class="o">||</span><span class="w"> </span>die
+</span><span class="hll"><span class="w"> </span><span class="o">}</span>
+</span></pre></div>
+</div>
+<p>Note that <code class="docutils literal notranslate"><span class="pre">python_test</span></code> is called by <code class="docutils literal notranslate"><span class="pre">distutils-r1_src_test</span></code>,
+so you must make sure to call it if you override <code class="docutils literal notranslate"><span class="pre">src_test</span></code>.</p>
+</section>
+<section id="customizing-the-test-phase-for-pytest">
+<span id="index-1"></span><h3>Customizing the test phase for pytest<a class="headerlink" href="#customizing-the-test-phase-for-pytest" title="Permalink to this heading">¶</a></h3>
+<p>For the relatively frequent case of pytest-based packages needing
+additional customization, a <code class="docutils literal notranslate"><span class="pre">epytest</span></code> helper is provided. The helper
+runs <code class="docutils literal notranslate"><span class="pre">pytest</span></code> with a standard set of options and automatic handling
+of test failures.</p>
+<p>For example, if upstream uses <code class="docutils literal notranslate"><span class="pre">network</span></code> marker to disable
+network-based tests, you can override the test phase in the following
+way:</p>
+<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>distutils_enable_tests<span class="w"> </span>pytest
+
+python_test<span class="o">()</span><span class="w"> </span><span class="o">{</span>
+<span class="w"> </span>epytest<span class="w"> </span>-m<span class="w"> </span><span class="s1">&#39;not network&#39;</span>
+<span class="o">}</span>
+</pre></div>
+</div>
+</section>
+<section id="running-tests-with-virtualx">
+<span id="index-2"></span><h3>Running tests with virtualx<a class="headerlink" href="#running-tests-with-virtualx" title="Permalink to this heading">¶</a></h3>
+<p>Test suites requiring a display to work correctly can often be appeased
+usng Xvfb. If the package in question does not start Xvfb directly,
+<code class="docutils literal notranslate"><span class="pre">virtualx.eclass</span></code> can be used to do that. Whenever possible, it is
+preferable to run a single server in <code class="docutils literal notranslate"><span class="pre">src_test()</span></code> for all passes
+of the test suite, e.g.:</p>
+<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>distutils_enable_tests<span class="w"> </span>pytest
+
+src_test<span class="o">()</span><span class="w"> </span><span class="o">{</span>
+<span class="w"> </span>virtx<span class="w"> </span>distutils-r1_src_test
+<span class="o">}</span>
+</pre></div>
+</div>
+<p>Note that <code class="docutils literal notranslate"><span class="pre">virtx</span></code> implicitly enables nonfatal mode. This means that
+e.g. <code class="docutils literal notranslate"><span class="pre">epytest</span></code> will no longer terminate the ebuild on failure, and you
+need to use <code class="docutils literal notranslate"><span class="pre">die</span></code> explicitly for it:</p>
+<div class="highlight-bash notranslate"><div class="highlight"><pre><span></span>src_test<span class="o">()</span><span class="w"> </span><span class="o">{</span>
+<span class="w"> </span>virtx<span class="w"> </span>distutils-r1_src_test
+<span class="o">}</span>
+
+python_test<span class="o">()</span><span class="w"> </span><span class="o">{</span>
+<span class="w"> </span>epytest<span class="w"> </span>-m<span class="w"> </span><span class="s2">&quot;not network&quot;</span><span class="w"> </span><span class="o">||</span><span class="w"> </span>die<span class="w"> </span><span class="s2">&quot;Tests failed with </span><span class="si">${</span><span class="nv">EPYTHON</span><span class="si">}</span><span class="s2">&quot;</span>
+<span class="o">}</span>
+</pre></div>
+</div>
+<div class="admonition warning">
+<p class="admonition-title">Warning</p>
+<p>Explicit <code class="docutils literal notranslate"><span class="pre">||</span> <span class="pre">die</span></code> is only necessary when overriding <code class="docutils literal notranslate"><span class="pre">python_test</span></code>
+and running <code class="docutils literal notranslate"><span class="pre">epytest</span></code> inside a <code class="docutils literal notranslate"><span class="pre">nonfatal</span></code>. The <code class="docutils literal notranslate"><span class="pre">virtx</span></code> command
+runs its arguments via a <code class="docutils literal notranslate"><span class="pre">nonfatal</span></code>. The default <code class="docutils literal notranslate"><span class="pre">python_test</span></code>
+implementation created by <code class="docutils literal notranslate"><span class="pre">distutils_enable_tests</span></code> accounts for
+this. In other contexts, <code class="docutils literal notranslate"><span class="pre">epytest</span></code> will die on its own.</p>
+</div>
+</section>
+</section>
<section id="choosing-the-correct-test-runner">
<h2>Choosing the correct test runner<a class="headerlink" href="#choosing-the-correct-test-runner" title="Permalink to this heading">¶</a></h2>
<p>There are a few modules used to run tests in Python packages. The most
@@ -71,6 +312,31 @@ as the latter has ceased development and requires downstream patching.
If you have some free time, convincing upstream to switch from nose
to pytest is a worthwhile goal.</p>
</section>
+<section id="undesirable-test-dependencies">
+<h2>Undesirable test dependencies<a class="headerlink" href="#undesirable-test-dependencies" title="Permalink to this heading">¶</a></h2>
+<p>There is a number of packages that are frequently listed as test
+dependencies upstream but have little to no value for Gentoo users.
+It is recommended to skip those test dependencies whenever possible.
+If tests fail to run without them, it is often preferable to strip
+the dependencies and/or configuration values enforcing them.</p>
+<p><em>Coverage testing</em> establishes how much of the package’s code is covered
+by the test suite. While this is useful statistic upstream, it has
+no value for Gentoo users who just want to install the package. This
+is often represented by dependencies on <code class="docutils literal notranslate"><span class="pre">dev-python/coverage</span></code>,
+<code class="docutils literal notranslate"><span class="pre">dev-python/pytest-cov</span></code>. In the latter case, you usually need
+to strip <code class="docutils literal notranslate"><span class="pre">--cov</span></code> parameter from <code class="docutils literal notranslate"><span class="pre">pytest.ini</span></code>.</p>
+<p><em>PEP-8 testing</em> enforces standard coding style across Python programs.
+Issues found by it are relevant to upstream but entirely irrelevant
+to Gentoo users. If the package uses <code class="docutils literal notranslate"><span class="pre">dev-python/pep8</span></code>,
+<code class="docutils literal notranslate"><span class="pre">dev-python/pycodestyle</span></code>, <code class="docutils literal notranslate"><span class="pre">dev-python/flake8</span></code>, strip that
+dependency.</p>
+<p><code class="docutils literal notranslate"><span class="pre">dev-python/pytest-runner</span></code> is a thin wrapper to run pytest
+from <code class="docutils literal notranslate"><span class="pre">setup.py</span></code>. Do not use it, just call pytest directly.</p>
+<p><code class="docutils literal notranslate"><span class="pre">dev-python/tox</span></code> is a convenient wrapper to run tests for multiple
+Python versions, in a virtualenv. The eclass already provides the logic
+for the former, and an environment close enough to the latter. Do not
+use tox in ebuilds.</p>
+</section>
<section id="missing-test-files-in-pypi-packages">
<h2>Missing test files in PyPI packages<a class="headerlink" href="#missing-test-files-in-pypi-packages" title="Permalink to this heading">¶</a></h2>
<p>One of the more common test-related problems is that PyPI packages
@@ -411,11 +677,11 @@ into it for the purpose of testing. Note that <code class="docutils literal not
<li class="toctree-l1"><a class="reference internal" href="single.html">python-single-r1 — single-impl packages</a></li>
<li class="toctree-l1"><a class="reference internal" href="multi.html">python-r1 — multi-impl packages</a></li>
<li class="toctree-l1"><a class="reference internal" href="distutils.html">distutils-r1 — standard Python build systems</a></li>
-<li class="toctree-l1"><a class="reference internal" href="distutils-legacy.html">distutils-r1 legacy concepts</a></li>
-<li class="toctree-l1"><a class="reference internal" href="helper.html">Common helper functions</a></li>
-<li class="toctree-l1"><a class="reference internal" href="depend.html">Advanced dependencies</a></li>
-<li class="toctree-l1 current"><a class="current reference internal" href="#">Resolving test suite problems</a><ul>
+<li class="toctree-l1 current"><a class="current reference internal" href="#">Tests in Python packages</a><ul>
+<li class="toctree-l2"><a class="reference internal" href="#why-is-running-tests-important">Why is running tests important?</a></li>
+<li class="toctree-l2"><a class="reference internal" href="#using-distutils-enable-tests">Using distutils_enable_tests</a></li>
<li class="toctree-l2"><a class="reference internal" href="#choosing-the-correct-test-runner">Choosing the correct test runner</a></li>
+<li class="toctree-l2"><a class="reference internal" href="#undesirable-test-dependencies">Undesirable test dependencies</a></li>
<li class="toctree-l2"><a class="reference internal" href="#missing-test-files-in-pypi-packages">Missing test files in PyPI packages</a></li>
<li class="toctree-l2"><a class="reference internal" href="#importerrors-for-c-extensions">ImportErrors for C extensions</a></li>
<li class="toctree-l2"><a class="reference internal" href="#checklist-for-dealing-with-test-failures">Checklist for dealing with test failures</a></li>
@@ -425,6 +691,9 @@ into it for the purpose of testing. Note that <code class="docutils literal not
<li class="toctree-l2"><a class="reference internal" href="#installing-extra-dependencies-in-test-environment-pep-517-mode">Installing extra dependencies in test environment (PEP 517 mode)</a></li>
</ul>
</li>
+<li class="toctree-l1"><a class="reference internal" href="distutils-legacy.html">distutils-r1 legacy concepts</a></li>
+<li class="toctree-l1"><a class="reference internal" href="helper.html">Common helper functions</a></li>
+<li class="toctree-l1"><a class="reference internal" href="depend.html">Advanced dependencies</a></li>
<li class="toctree-l1"><a class="reference internal" href="pytest.html">pytest recipes</a></li>
<li class="toctree-l1"><a class="reference internal" href="concept.html">Advanced concepts</a></li>
<li class="toctree-l1"><a class="reference internal" href="expert-multi.html">Expert python-r1 usage</a></li>
@@ -440,8 +709,8 @@ into it for the purpose of testing. Note that <code class="docutils literal not
<h3>Related Topics</h3>
<ul>
<li><a href="index.html">Documentation overview</a><ul>
- <li>Previous: <a href="depend.html" title="previous chapter">Advanced dependencies</a></li>
- <li>Next: <a href="pytest.html" title="next chapter">pytest recipes</a></li>
+ <li>Previous: <a href="distutils.html" title="previous chapter">distutils-r1 — standard Python build systems</a></li>
+ <li>Next: <a href="distutils-legacy.html" title="next chapter">distutils-r1 legacy concepts</a></li>
</ul></li>
</ul>
</div>