<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml"> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> <title>優れたインテグレーションプラクティス</title> <link rel="stylesheet" href="_static/sphinxdoc.css" type="text/css" /> <link rel="stylesheet" href="_static/pygments.css" type="text/css" /> <script type="text/javascript"> var DOCUMENTATION_OPTIONS = { URL_ROOT: '', VERSION: '2.2.4.0', COLLAPSE_INDEX: false, FILE_SUFFIX: '.html', HAS_SOURCE: true }; </script> <script type="text/javascript" src="_static/jquery.js"></script> <script type="text/javascript" src="_static/underscore.js"></script> <script type="text/javascript" src="_static/doctools.js"></script> <script type="text/javascript" src="_static/translations.js"></script> <link rel="top" title="None" href="index.html" /> <link rel="up" title="基本から始めよう" href="overview.html" /> <link rel="next" title="プロジェクトの例" href="projects.html" /> <link rel="prev" title="使用方法とテスト実行" href="usage.html" /> </head> <body> <div class="related"> <h3>ナビゲーション</h3> <ul> <li class="right" style="margin-right: 10px"> <a href="py-modindex.html" title="Pythonモジュール索引" >モジュール</a></li> <li class="right" > <a href="projects.html" title="プロジェクトの例" accesskey="N">次へ</a> |</li> <li class="right" > <a href="usage.html" title="使用方法とテスト実行" accesskey="P">前へ</a> |</li> <li><a href="contents.html">pytest-2.2.4.0</a> »</li> <li><a href="overview.html" accesskey="U">基本から始めよう</a> »</li> </ul> </div> <div class="sphinxsidebar"> <div class="sphinxsidebarwrapper"> <h3><a href="contents.html">目次</a></h3> <ul> <li><a class="reference internal" href="#">優れたインテグレーションプラクティス</a><ul> <li><a class="reference internal" href="#id2">仮想環境での作業</a></li> <li><a class="reference internal" href="#tox">tox と継続的インテグレーションサーバーの利用</a></li> <li><a class="reference internal" href="#py-test">単独実行できる py.test スクリプトの作成</a></li> <li><a class="reference internal" href="#python-setup-py-test-distutils"><tt class="docutils literal"><span class="pre">python</span> <span class="pre">setup.py</span> <span class="pre">test</span></tt> による distutils との連携</a></li> <li><a class="reference internal" href="#setuptools-distribute">setuptools/distribute のテストコマンドとの組み合わせ</a></li> <li><a class="reference internal" href="#python">Python テスト探索の規約</a></li> <li><a class="reference internal" href="#id3">テストレイアウト選択とインポートルール</a></li> </ul> </li> </ul> <h4>前のトピックへ</h4> <p class="topless"><a href="usage.html" title="前の章へ">使用方法とテスト実行</a></p> <h4>次のトピックへ</h4> <p class="topless"><a href="projects.html" title="次の章へ">プロジェクトの例</a></p> <div id="searchbox" style="display: none"> <h3>クイック検索</h3> <form class="search" action="search.html" method="get"> <input type="text" name="q" /> <input type="submit" value="検索" /> <input type="hidden" name="check_keywords" value="yes" /> <input type="hidden" name="area" value="default" /> </form> <p class="searchtip" style="font-size: 90%"> モジュール、クラス、または関数名を入力してください </p> </div> <script type="text/javascript">$('#searchbox').show(0);</script> </div> </div> <div class="document"> <div class="documentwrapper"> <div class="bodywrapper"> <div class="body"> <div class="section" id="goodpractises"> <span id="id1"></span><h1>優れたインテグレーションプラクティス<a class="headerlink" href="#goodpractises" title="このヘッドラインへのパーマリンク">¶</a></h1> <div class="section" id="id2"> <h2>仮想環境での作業<a class="headerlink" href="#id2" title="このヘッドラインへのパーマリンク">¶</a></h2> <p><a class="reference external" href="http://pypi.python.org/pypi/virtualenv">virtualenv</a> 環境を構築して、 <tt class="docutils literal"><span class="pre">pytest</span></tt> パッケージとその他に依存するアプリケーションをインストールするのに <a class="reference external" href="http://pypi.python.org/pypi/distribute">easy_install</a> (または <a class="reference external" href="http://pypi.python.org/pypi/pip">pip</a>) を使うことをお奨めします。 <a class="reference external" href="http://codespeak.net/tox">tox</a> という、複数の依存設定や Python インタープリターに対して自動的にテストを実行する便利なツールがあります。</p> </div> <div class="section" id="tox"> <h2>tox と継続的インテグレーションサーバーの利用<a class="headerlink" href="#tox" title="このヘッドラインへのパーマリンク">¶</a></h2> <p>もし頻繁にコードを一般向けにリリースするなら、virtualenv のテスト自動化とその <a class="reference external" href="http://codespeak.net/tox/example/pytest.html">pytest サポート</a> を行う <a class="reference external" href="http://codespeak.net/tox">tox</a> を調べてみたくなるでしょう。基本的な考え方は、 <tt class="docutils literal"><span class="pre">--junitxml=PATH</span></tt> オプションにより JUnitXML ファイルを生成します。そして <a class="reference external" href="http://jenkins-ci.org/">Jenkins</a> のような継続的インテグレーションサーバーがそのファイルを取得してレポートを生成します。</p> </div> <div class="section" id="py-test"> <span id="genscript-method"></span><span id="standalone"></span><h2>単独実行できる py.test スクリプトの作成<a class="headerlink" href="#py-test" title="このヘッドラインへのパーマリンク">¶</a></h2> <p>あなたがメンテナーまたはアプリケーション開発者で、他の人にも簡単にテストを実行させたいなら、単独で実行できる “py.test” スクリプトを作成できます:</p> <div class="highlight-python"><div class="highlight"><pre><span class="n">py</span><span class="o">.</span><span class="n">test</span> <span class="o">--</span><span class="n">genscript</span><span class="o">=</span><span class="n">runtests</span><span class="o">.</span><span class="n">py</span> </pre></div> </div> <p>基本的に <tt class="docutils literal"><span class="pre">py.test</span></tt> スクリプトと完全に同機能をもつ <tt class="docutils literal"><span class="pre">runtests.py</span></tt> スクリプトを生成します。このスクリプトは Python2 と Python3 においても修正せず実行できます。このスクリプトをダウンロードして、例えば、次のように実行してくださいと伝えれば良いです:</p> <div class="highlight-python"><pre>python runtests.py</pre> </div> </div> <div class="section" id="python-setup-py-test-distutils"> <h2><tt class="docutils literal"><span class="pre">python</span> <span class="pre">setup.py</span> <span class="pre">test</span></tt> による distutils との連携<a class="headerlink" href="#python-setup-py-test-distutils" title="このヘッドラインへのパーマリンク">¶</a></h2> <p>プロジェクトベースの distutils または setuptools でテスト実行を連携できます。単独で実行できる py.test スクリプトを生成するには <a class="reference internal" href="#genscript-method"><em>genscript メソッド</em></a> を使ってください:</p> <div class="highlight-python"><div class="highlight"><pre><span class="n">py</span><span class="o">.</span><span class="n">test</span> <span class="o">--</span><span class="n">genscript</span><span class="o">=</span><span class="n">runtests</span><span class="o">.</span><span class="n">py</span> </pre></div> </div> <p>このスクリプトを配布物の一部にして <tt class="docutils literal"><span class="pre">setup.py</span></tt> ファイルに次のコードを追加します:</p> <div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">distutils.core</span> <span class="kn">import</span> <span class="n">setup</span><span class="p">,</span> <span class="n">Command</span> <span class="c"># setuptools からもインポートできます</span> <span class="k">class</span> <span class="nc">PyTest</span><span class="p">(</span><span class="n">Command</span><span class="p">):</span> <span class="n">user_options</span> <span class="o">=</span> <span class="p">[]</span> <span class="k">def</span> <span class="nf">initialize_options</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">pass</span> <span class="k">def</span> <span class="nf">finalize_options</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="k">pass</span> <span class="k">def</span> <span class="nf">run</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="kn">import</span> <span class="nn">sys</span><span class="o">,</span><span class="nn">subprocess</span> <span class="n">errno</span> <span class="o">=</span> <span class="n">subprocess</span><span class="o">.</span><span class="n">call</span><span class="p">([</span><span class="n">sys</span><span class="o">.</span><span class="n">executable</span><span class="p">,</span> <span class="s">'runtest.py'</span><span class="p">])</span> <span class="k">raise</span> <span class="ne">SystemExit</span><span class="p">(</span><span class="n">errno</span><span class="p">)</span> <span class="n">setup</span><span class="p">(</span> <span class="c">#...,</span> <span class="n">cmdclass</span> <span class="o">=</span> <span class="p">{</span><span class="s">'test'</span><span class="p">:</span> <span class="n">PyTest</span><span class="p">},</span> <span class="c">#...,</span> <span class="p">)</span> </pre></div> </div> <p>ここで次のように実行します:</p> <div class="highlight-python"><pre>python setup.py test</pre> </div> <p>これは <tt class="docutils literal"><span class="pre">runtest.py</span></tt> を使ってテストを実行します。このように、単独で実行できる <tt class="docutils literal"><span class="pre">py.test</span></tt> スクリプトは、そのテストコマンドを呼び出すために依存パッケージをインストールする必要がありません。さらにテストディレクトリやその他のオプションなど、subprocess.call に追加の引数として渡せます。</p> </div> <div class="section" id="setuptools-distribute"> <span id="python-test-discovery"></span><span id="test-discovery"></span><h2>setuptools/distribute のテストコマンドとの組み合わせ<a class="headerlink" href="#setuptools-distribute" title="このヘッドラインへのパーマリンク">¶</a></h2> <p>setuptools/distribute は、テストに必要なパッケージ要件から pytest を実行するテストコマンドをとても簡単に拡張できる tests_require に対応しています:</p> <div class="highlight-python"><div class="highlight"><pre><span class="kn">from</span> <span class="nn">setuptools.command.test</span> <span class="kn">import</span> <span class="n">test</span> <span class="k">as</span> <span class="n">TestCommand</span> <span class="k">class</span> <span class="nc">PyTest</span><span class="p">(</span><span class="n">TestCommand</span><span class="p">):</span> <span class="k">def</span> <span class="nf">finalize_options</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="n">TestCommand</span><span class="o">.</span><span class="n">finalize_options</span><span class="p">(</span><span class="bp">self</span><span class="p">)</span> <span class="bp">self</span><span class="o">.</span><span class="n">test_args</span> <span class="o">=</span> <span class="p">[]</span> <span class="bp">self</span><span class="o">.</span><span class="n">test_suite</span> <span class="o">=</span> <span class="bp">True</span> <span class="k">def</span> <span class="nf">run_tests</span><span class="p">(</span><span class="bp">self</span><span class="p">):</span> <span class="c"># 外部で egg を読み込ませたくないならここでインポートしてください</span> <span class="kn">import</span> <span class="nn">pytest</span> <span class="n">pytest</span><span class="o">.</span><span class="n">main</span><span class="p">(</span><span class="bp">self</span><span class="o">.</span><span class="n">test_args</span><span class="p">)</span> <span class="n">setup</span><span class="p">(</span> <span class="c">#...,</span> <span class="n">tests_require</span><span class="o">=</span><span class="p">[</span><span class="s">'pytest'</span><span class="p">],</span> <span class="n">cmdclass</span> <span class="o">=</span> <span class="p">{</span><span class="s">'test'</span><span class="p">:</span> <span class="n">pytest</span><span class="p">},</span> <span class="p">)</span> </pre></div> </div> <p>ここで次のように実行します:</p> <div class="highlight-python"><pre>python setup.py test</pre> </div> <p>必要に応じて py.test をダウンロードしてから、期待した通りに py.test を実行します。</p> </div> <div class="section" id="python"> <h2>Python テスト探索の規約<a class="headerlink" href="#python" title="このヘッドラインへのパーマリンク">¶</a></h2> <p><tt class="docutils literal"><span class="pre">py.test</span></tt> は次のテスト探索標準を実装します:</p> <ul class="simple"> <li>コレクションは、ディレクトリ、ファイル名、テスト ID といった最初に与えたコマンドライン引数から開始する</li> <li><a class="reference internal" href="customize.html#confval-norecursedirs"><tt class="xref std std-confval docutils literal"><span class="pre">norecursedirs</span></tt></a> に一致しない限り、ディレクトリを再帰的に探索する</li> <li><a class="reference internal" href="#package-name">package name</a> でインポートされる <tt class="docutils literal"><span class="pre">test_*.py</span></tt> または <tt class="docutils literal"><span class="pre">*_test.py</span></tt> ファイル</li> <li><tt class="docutils literal"><span class="pre">Test</span></tt> という接頭辞をもつテストクラス (<tt class="docutils literal"><span class="pre">__init__</span></tt> メソッドをもたない)</li> <li><tt class="docutils literal"><span class="pre">test_</span></tt> という接頭辞をもつテスト関数やメソッドがテスト項目になる</li> </ul> <p>テスト探索をカスタマイズする方法の例は <a class="reference internal" href="example/pythoncollection.html"><em>標準的な (Python) テスト探索の変更</em></a> を参照してください。</p> <p>Python モジュール内では、py.test も標準ライブラリの <a class="reference internal" href="unittest.html#unittest-testcase"><em>unittest.TestCase</em></a> のサブクラス化を使ってテストを探索します。</p> </div> <div class="section" id="id3"> <h2>テストレイアウト選択とインポートルール<a class="headerlink" href="#id3" title="このヘッドラインへのパーマリンク">¶</a></h2> <p>py.test は一般的なテストレイアウトに対応しています:</p> <ul> <li><p class="first">アプリケーション内に test ディレクトリを配置しています。(ユニット) テストを保持して実際にテストされたコードを一緒にしておくのに役立ちます:</p> <div class="highlight-python"><pre>mypkg/ __init__.py appmodule.py ... test/ test_app.py ...</pre> </div> </li> </ul> <ul> <li><p class="first">テストをアプリケーションコードの外部に配置しています。多くの機能テストがある、または実際のアプリケーションコードからテストを分離して保持したいときに役立ちます:</p> <div class="highlight-python"><pre>mypkg/ __init__.py appmodule.py tests/ test_app.py ...</pre> </div> </li> </ul> <p>どちらの場合も、普通に <tt class="docutils literal"><span class="pre">mypkg</span></tt> がインポートできることを保証する必要があります。例えば、setuptools の <tt class="docutils literal"><span class="pre">python</span> <span class="pre">setup.py</span> <span class="pre">develop</span></tt> メソッドを使います。</p> <p>次のようにテストを実行できます:</p> <div class="highlight-python"><pre>py.test tests/test_app.py # 外部のテストディレクトリ py.test mypkg/test/test_app.py # 内部のテストディレクトリ py.test mypkg # テストディレクトリ配下にある全てのテストを実行 py.test # カレントディテクリ配下にある全てのテストを実行 ...</pre> </div> <div class="admonition note" id="package-name"> <p class="first admonition-title">ノート</p> <p>py.test がファイルシステムを再帰的に辿って “a/b/test_module.py” テストファイルを検出する場合、インポート名を次のようにして決定します。</p> <ul class="simple"> <li><tt class="docutils literal"><span class="pre">basedir</span></tt> を検出する – これは <tt class="docutils literal"><span class="pre">__init__.py</span></tt> を含まない最初の “upward” (ルートに向かう) ディレクトリです。 <tt class="docutils literal"><span class="pre">a</span></tt> と <tt class="docutils literal"><span class="pre">b</span></tt> のディレクトリ両方に <tt class="docutils literal"><span class="pre">__init__.py</span></tt> を含む場合、basedir は <tt class="docutils literal"><span class="pre">a</span></tt> の親ディレクトリになります</li> <li>テストモジュールを完全修飾インポート名でインポートできるようにするために <tt class="docutils literal"><span class="pre">sys.path.insert(0,</span> <span class="pre">basedir)</span></tt> を実行します</li> <li>パス区切り文字 <tt class="docutils literal"><span class="pre">/</span></tt> を ”.” に変換することで決まる <tt class="docutils literal"><span class="pre">import</span> <span class="pre">a.b.test_module</span></tt> を行う、つまりインポート名に直接ディレクトリやファイル名を対応付ける規約に従わないといけません</li> </ul> <p class="last">この少し進化したインポートテクニックを使う理由は、巨大なプロジェクトでは複数のテストモジュールがお互いにインポートする可能性があるからです。そして、このように導出されたインポート名の標準化は、テストモジュールを2回インポートしてしまって驚かないようにするのに役立ちます。</p> </div> </div> </div> </div> </div> </div> <div class="clearer"></div> </div> <div class="related"> <h3>ナビゲーション</h3> <ul> <li class="right" style="margin-right: 10px"> <a href="py-modindex.html" title="Pythonモジュール索引" >モジュール</a></li> <li class="right" > <a href="projects.html" title="プロジェクトの例" >次へ</a> |</li> <li class="right" > <a href="usage.html" title="使用方法とテスト実行" >前へ</a> |</li> <li><a href="contents.html">pytest-2.2.4.0</a> »</li> <li><a href="overview.html" >基本から始めよう</a> »</li> </ul> </div> <div class="footer"> © Copyright 2011, holger krekel et alii. このドキュメントは <a href="http://sphinx.pocoo.org/">Sphinx</a> 1.1.3 で生成しました。 </div> </body> </html>