Sophie

Sophie

distrib > Fedora > 18 > i386 > by-pkgid > 7f671eb35339cf812de52087b0d93519 > files > 322

python3-pytest-2.3.5-3.fc18.noarch.rpm

..
    ==============================================================
    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 --fixtures 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


.. _`fixture function`:
.. _factory:

funcarg **request** オブジェクト
================================

..
    The funcarg **request** object
    =============================================

..
    Each fixture function receives a **request** object tied to a specific test
    function call.  A request object is passed to a fixture function and provides
    access to test configuration and context:

funcarg ファクトリー関数は、特別なテスト関数呼び出しに関連付けられた **request** オブジェクトを受け取ります。request オブジェクトは funcarg ファクトリーへ渡されて、テスト設定とコンテキストへのアクセスを提供します:

.. autoclass:: _pytest.python.FixtureRequest()
    :members: function,cls,module,keywords,config

.. _`useful caching and finalization helpers`:

.. automethod:: FixtureRequest.addfinalizer

.. automethod:: FixtureRequest.cached_setup

.. automethod:: FixtureRequest.applymarker

.. automethod:: FixtureRequest.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.fixturenames:
            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.fixturenames``: set of required function arguments for given function

``metafunc.fixturenames``: テスト関数へ渡される引数セット

..
    ``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)