26.8. test — Python用の回帰テストパッケージ—Pythonドキュメント

提供:Dev Guides
< PythonPython/docs/3.6/library/test
移動先:案内検索

26.8。 テスト —Python用の回帰テストパッケージ

ノート

test パッケージは、Pythonによる内部使用のみを目的としています。 Pythonのコア開発者のために文書化されています。 ここに記載されているコードは、Pythonのリリース間で予告なしに変更または削除される可能性があるため、Pythonの標準ライブラリの外部でこのパッケージを使用することはお勧めしません。



test パッケージには、Pythonのすべての回帰テストと、モジュール test.support およびtest.regrtestが含まれています。 test.support はテストを強化するために使用され、test.regrtestはテストスイートを駆動します。

名前がtest_で始まる test パッケージの各モジュールは、特定のモジュールまたは機能のテストスイートです。 すべての新しいテストは、 unittest または doctest モジュールを使用して作成する必要があります。 一部の古いテストは、sys.stdoutに出力された出力を比較する「従来の」テストスタイルを使用して記述されています。 このスタイルのテストは非推奨と見なされます。

も参照してください

モジュールユニットテスト
PyUnit回帰テストの作成。
モジュール doctest
ドキュメント文字列に埋め込まれたテスト。


26.8.1。 のユニットテストの作成テストパッケージ

unittest モジュールを使用するテストはいくつかのガイドラインに従うことが望ましいです。 1つは、test_で開始してテストモジュールに名前を付け、テストするモジュールの名前で終了することです。 テストモジュールのテストメソッドは、test_で始まり、メソッドがテストしている内容の説明で終わる必要があります。 これは、メソッドがテストドライバーによってテストメソッドとして認識されるために必要です。 また、メソッドのドキュメント文字列を含めることはできません。 コメント(# Tests function returns only True or Falseなど)を使用して、テストメソッドのドキュメントを提供する必要があります。 これが行われるのは、ドキュメント文字列が存在する場合は印刷され、実行されているテストが指定されていないためです。

基本的な定型文がよく使用されます。

import unittest
from test import support

class MyTestCase1(unittest.TestCase):

    # Only use setUp() and tearDown() if necessary

    def setUp(self):
        ... code to execute in preparation for tests ...

    def tearDown(self):
        ... code to execute to clean up after tests ...

    def test_feature_one(self):
        # Test feature one.
        ... testing code ...

    def test_feature_two(self):
        # Test feature two.
        ... testing code ...

    ... more test methods ...

class MyTestCase2(unittest.TestCase):
    ... same structure as MyTestCase1 ...

... more test classes ...

if __name__ == '__main__':
    unittest.main()

このコードパターンにより、テストスイートをtest.regrtestで実行したり、 unittest CLIをサポートするスクリプトとして単独で実行したり、python -m unittest CLIを介して実行したりできます。

回帰テストの目標は、コードを解読しようとすることです。 これにより、従うべきいくつかのガイドラインが導き出されます。

  • テストスイートは、すべてのクラス、関数、および定数を実行する必要があります。 これには、外部に提示される外部APIだけでなく、「プライベート」コードも含まれます。

  • ホワイトボックステスト(テストの作成時にテストされるコードを調べる)が推奨されます。 ブラックボックステスト(公開されたユーザーインターフェイスのみをテストする)は、すべての境界およびエッジケースがテストされていることを確認するのに十分なほど完全ではありません。

  • 無効な値を含め、すべての可能な値がテストされていることを確認してください。 これにより、すべての有効な値が受け入れられるだけでなく、不適切な値が正しく処理されるようになります。

  • できるだけ多くのコードパスを使い果たします。 分岐が発生する場所をテストし、入力を調整して、コード内でできるだけ多くの異なるパスが使用されることを確認します。

  • テストされたコードで発見されたバグの明示的なテストを追加します。 これにより、将来コードが変更された場合にエラーが再発しないようになります。

  • テスト後は必ずクリーンアップしてください(すべての一時ファイルを閉じて削除するなど)。

  • テストがオペレーティングシステムの特定の条件に依存している場合は、テストを試行する前に、条件がすでに存在することを確認してください。

  • できるだけ少ないモジュールをインポートし、できるだけ早く実行します。 これにより、テストの外部依存関係が最小限に抑えられ、モジュールのインポートの副作用による異常な動作の可能性も最小限に抑えられます。

  • コードの再利用を最大化するようにしてください。 場合によっては、使用される入力のタイプと同じくらい小さいものによってテストが異なることがあります。 基本的なテストクラスを入力を指定するクラスでサブクラス化することにより、コードの重複を最小限に抑えます。

    class TestFuncAcceptsSequencesMixin:
    
        func = mySuperWhammyFunction
    
        def test_func(self):
            self.func(self.arg)
    
    class AcceptLists(TestFuncAcceptsSequencesMixin, unittest.TestCase):
        arg = [1, 2, 3]
    
    class AcceptStrings(TestFuncAcceptsSequencesMixin, unittest.TestCase):
        arg = 'abc'
    
    class AcceptTuples(TestFuncAcceptsSequencesMixin, unittest.TestCase):
        arg = (1, 2, 3)

    このパターンを使用するときは、 unittest.TestCase から継承するすべてのクラスがテストとして実行されることに注意してください。 上記の例のMixinクラスにはデータがないため、単独で実行することはできません。したがって、 unittest.TestCase から継承しません。

も参照してください

テスト駆動開発
コードの前にテストを書くことに関するケントベックの本。


26.8.2。 コマンドラインインターフェイスを使用したテストの実行

test パッケージは、 -m オプション python -m test のおかげで、Pythonの回帰テストスイートを駆動するスクリプトとして実行できます。 内部では、test.regrtestを使用します。 以前のPythonバージョンで使用されていた python -m test.regrtest の呼び出しは引き続き機能します。 スクリプトを単独で実行すると、 test パッケージ内のすべての回帰テストの実行が自動的に開始されます。 これは、名前がtest_で始まるパッケージ内のすべてのモジュールを検索してインポートし、存在する場合は関数test_main()を実行するか、test_mainは存在しません。 実行するテストの名前もスクリプトに渡される場合があります。 単一の回帰テスト( python -m test test_spam )を指定すると、出力が最小化され、テストが成功したか失敗したかのみが出力されます。

test を直接実行すると、テストに使用できるリソースを直接設定できます。 これを行うには、-uコマンドラインオプションを使用します。 -uオプションの値としてallを指定すると、すべての可能なリソースが有効になります: python -m test -uall 。 1つを除くすべてのリソースが必要な場合(より一般的なケース)、不要なリソースのコンマ区切りリストがallの後にリストされる場合があります。 コマンド python -m test -uall、-audio、-largefile は、audioおよびlargefileリソースを除くすべてのリソースで test を実行します。 すべてのリソースとその他のコマンドラインオプションのリストについては、 python -m test -h を実行してください。

回帰テストを実行する他のいくつかの方法は、テストが実行されているプラットフォームによって異なります。 Unixでは、Pythonが構築された最上位ディレクトリで make test を実行できます。 Windowsでは、PCBuildディレクトリから rt.bat を実行すると、すべての回帰テストが実行されます。


26.9。 test.support —Pythonテストスイートのユーティリティ

test.support モジュールは、Pythonの回帰テストスイートのサポートを提供します。

ノート

test.support はパブリックモジュールではありません。 Python開発者がテストを作成するのに役立つように、ここに文書化されています。 このモジュールのAPIは、リリース間の下位互換性の懸念なしに変更される可能性があります。


このモジュールは、次の例外を定義します。

exception test.support.TestFailed
テストが失敗したときに発生する例外。 これは、 unittest ベースのテストと unittest.TestCase のアサーションメソッドを優先して非推奨になりました。
exception test.support.ResourceDenied
unittest.SkipTest のサブクラス。 リソース(ネットワーク接続など)が利用できない場合に発生します。 require()関数によって発生します。

test.support モジュールは、次の定数を定義します。

test.support.verbose
True詳細出力が有効な場合。 実行中のテストについてより詳細な情報が必要な場合は、チェックする必要があります。 verbosetest.regrtestによって設定されます。
test.support.is_jython
True実行中のインタープリターがJythonの場合。
test.support.TESTFN
一時ファイルの名前として安全に使用できる名前に設定します。 作成された一時ファイルはすべて閉じて、リンクを解除(削除)する必要があります。

test.support モジュールは、次の関数を定義します。

test.support.forget(module_name)
module_name という名前のモジュールをsys.modulesから削除し、モジュールのバイトコンパイルされたファイルをすべて削除します。
test.support.is_resource_enabled(resource)
リソースが有効で使用可能な場合は、Trueを返します。 利用可能なリソースのリストは、test.regrtestがテストを実行しているときにのみ設定されます。
test.support.requires(resource, msg=None)
リソースが利用できない場合は、 ResourceDenied を上げます。 msg は、 ResourceDenied が発生した場合の引数です。 __name__'__main__'である関数によって呼び出された場合、常にTrueを返します。 test.regrtestでテストを実行する場合に使用します。
test.support.findfile(filename, subdir=None)

filename という名前のファイルへのパスを返します。 一致するものが見つからない場合は、ファイル名が返されます。 これはファイルへのパスである可能性があるため、失敗と同じではありません。

subdir を設定すると、パスディレクトリを直接調べるのではなく、ファイルを見つけるために使用する相対パスが示されます。

test.support.run_unittest(\*classes)

関数に渡された unittest.TestCase サブクラスを実行します。 この関数は、プレフィックスtest_で始まるメソッドのクラスをスキャンし、テストを個別に実行します。

文字列をパラメータとして渡すことも合法です。 これらはsys.modulesのキーである必要があります。 関連する各モジュールは、unittest.TestLoader.loadTestsFromModule()によってスキャンされます。 これは通常、次のtest_main()関数で見られます。

def test_main():
    support.run_unittest(__name__)

これにより、指定されたモジュールで定義されたすべてのテストが実行されます。

test.support.run_doctest(module, verbosity=None)

指定されたモジュールdoctest.testmod()を実行します。 (failure_count, test_count)を返します。

verbosityNoneの場合、 doctest.testmod()は、vervosityを verbose に設定して実行されます。 それ以外の場合は、詳細度をNoneに設定して実行されます。

test.support.check_warnings(\*filters, quiet=True)

warnings.catch_warnings()の便利なラッパーで、警告が正しく発生したことを簡単にテストできます。 これは、 warnings.simplefilter()alwaysに設定し、記録された結果を自動的に検証するオプションを指定してwarnings.catch_warnings(record=True)を呼び出すのとほぼ同じです。

check_warningsは、位置引数として("message regexp", WarningCategory)の形式の2タプルを受け入れます。 1つ以上の filters が提供されている場合、またはオプションのキーワード引数 quickFalseの場合、警告が期待どおりであることを確認します。指定された各フィルターは必須です。同封のコードによって発生した警告の少なくとも1つに一致するか、テストが失敗し、指定されたフィルターのいずれにも一致しない警告が発生した場合、テストは失敗します。 これらの最初のチェックを無効にするには、 quickTrueに設定します。

引数が指定されていない場合、デフォルトで次のようになります。

check_warnings(("", Warning), quiet=True)

この場合、すべての警告がキャッチされ、エラーは発生しません。

コンテキストマネージャーに入ると、WarningRecorderインスタンスが返されます。 catch_warnings()の基になる警告リストは、レコーダーオブジェクトの warnings 属性を介して利用できます。 便宜上、最新の警告を表すオブジェクトの属性には、レコーダーオブジェクトから直接アクセスすることもできます(以下の例を参照)。 警告が発生していない場合、警告を表すオブジェクトで予期される属性はすべてNoneを返します。

レコーダオブジェクトには、警告リストをクリアするreset()メソッドもあります。

コンテキストマネージャーは、次のように使用するように設計されています。

with check_warnings(("assertion is always true", SyntaxWarning),
                    ("", UserWarning)):
    exec('assert(False, "Hey!")')
    warnings.warn(UserWarning("Hide me!"))

この場合、警告が発生しなかった場合、またはその他の警告が発生した場合、 check_warnings()はエラーを発生させます。

テストで警告が発生したかどうかを確認するだけでなく、警告をより深く調べる必要がある場合は、次のようなコードを使用できます。

with check_warnings(quiet=True) as w:
    warnings.warn("foo")
    assert str(w.args[0]) == "foo"
    warnings.warn("bar")
    assert str(w.args[0]) == "bar"
    assert str(w.warnings[0].args[0]) == "foo"
    assert str(w.warnings[1].args[0]) == "bar"
    w.reset()
    assert len(w.warnings) == 0

ここですべての警告がキャッチされ、テストコードはキャプチャされた警告を直接テストします。

バージョン3.2で変更:新しいオプションの引数フィルターおよびクワイエット

test.support.captured_stdin()
test.support.captured_stdout()
test.support.captured_stderr()

名前付きストリームを io.StringIO オブジェクトに一時的に置き換えるコンテキストマネージャー。

出力ストリームでの使用例:

with captured_stdout() as stdout, captured_stderr() as stderr:
    print("hello")
    print("error", file=sys.stderr)
assert stdout.getvalue() == "hello\n"
assert stderr.getvalue() == "error\n"

入力ストリームでの使用例:

with captured_stdin() as stdin:
    stdin.write('hello\n')
    stdin.seek(0)
    # call test code that consumes from sys.stdin
    captured = input()
self.assertEqual(captured, "hello")
test.support.temp_dir(path=None, quiet=False)

path に一時ディレクトリを作成し、そのディレクトリを生成するコンテキストマネージャ。

pathNoneの場合、一時ディレクトリは tempfile.mkdtemp()を使用して作成されます。 quickFalseの場合、コンテキストマネージャーはエラー時に例外を発生させます。 それ以外の場合、パスが指定されていて作成できない場合は、警告のみが発行されます。

test.support.change_cwd(path, quiet=False)

現在の作業ディレクトリをパスに一時的に変更し、ディレクトリを生成するコンテキストマネージャ。

quickFalseの場合、コンテキストマネージャーはエラー時に例外を発生させます。 それ以外の場合は、警告のみを発行し、現在の作業ディレクトリを同じに保ちます。

test.support.temp_cwd(name='tempcwd', quiet=False)

新しいディレクトリを一時的に作成し、現在の作業ディレクトリ(CWD)を変更するコンテキストマネージャ。

コンテキストマネージャは、現在の作業ディレクトリを一時的に変更する前に、 name という名前で現在のディレクトリに一時ディレクトリを作成します。 nameNoneの場合、一時ディレクトリは tempfile.mkdtemp()を使用して作成されます。

quietFalseであり、CWDを作成または変更できない場合、エラーが発生します。 それ以外の場合は、警告のみが発生し、元のCWDが使用されます。

test.support.temp_umask(umask)
プロセスのumaskを一時的に設定するコンテキストマネージャー。
test.support.can_symlink()
OSがシンボリックリンクをサポートしている場合はTrueを返し、そうでない場合はFalseを返します。
@test.support.skip_unless_symlink
シンボリックリンクのサポートを必要とするテストを実行するためのデコレータ。
@test.support.anticipate_failure(condition)
unittest.expectedFailure()でテストを条件付きでマークするデコレータ。 このデコレータを使用する場合は、関連するトラッカーの問題を特定するコメントを関連付ける必要があります。
@test.support.run_with_locale(catstr, *locales)
別のロケールで関数を実行するためのデコレータ。終了後に関数を正しくリセットします。 catstr は、文字列としてのロケールカテゴリです(たとえば、"LC_ALL")。 渡された locales が順番に試行され、最初の有効なロケールが使用されます。
test.support.make_bad_fd()
一時ファイルを開いたり閉じたりして、その記述子を返すことにより、無効なファイル記述子を作成します。
test.support.import_module(name, deprecated=False)

この関数は、指定されたモジュールをインポートして返します。 通常のインポートとは異なり、この関数は、モジュールをインポートできない場合に unittest.SkipTest を発生させます。

deprecatedTrueの場合、モジュールとパッケージの非推奨メッセージはこのインポート中に抑制されます。

バージョン3.1の新機能。

test.support.import_fresh_module(name, fresh=(), blocked=(), deprecated=False)

この関数は、インポートを実行する前にsys.modulesから名前付きモジュールを削除することにより、名前付きPythonモジュールの新しいコピーをインポートして返します。 reload()とは異なり、元のモジュールはこの操作の影響を受けないことに注意してください。

fresh は、インポートを実行する前にsys.modulesキャッシュからも削除される追加のモジュール名の反復可能です。

blocked は、インポート中にモジュールキャッシュ内でNoneに置き換えられるモジュール名の反復可能であり、それらをインポートしようとすると ImportError が発生します。

指定されたモジュールと、 fresh および blocked パラメーターで指定されたモジュールは、インポートを開始する前に保存され、新規インポートが完了するとsys.modulesに再挿入されます。

deprecatedTrueの場合、モジュールとパッケージの非推奨メッセージはこのインポート中に抑制されます。

指定されたモジュールをインポートできない場合、この関数は ImportError を発生させます。

使用例:

# Get copies of the warnings module for testing without affecting the
# version being used by the rest of the test suite. One copy uses the
# C implementation, the other is forced to use the pure Python fallback
# implementation
py_warnings = import_fresh_module('warnings', blocked=['_warnings'])
c_warnings = import_fresh_module('warnings', fresh=['_warnings'])

バージョン3.1の新機能。

test.support.bind_port(sock, host=HOST)

ソケットを空きポートにバインドし、ポート番号を返します。 バインドされていないポートを使用していることを確認するために、エフェメラルポートに依存しています。 特にビルドボット環境では、多くのテストが同時に実行される可能性があるため、これは重要です。 このメソッドは、sock.familyAF_INET で、sock.typeSOCK_STREAM であり、ソケットにSO_REUSEADDRまたはSO_REUSEPORTが設定されています。 テストでは、TCP / IPソケットにこれらのソケットオプションを設定しないでください。 これらのオプションを設定する唯一のケースは、複数のUDPソケットを介したマルチキャストのテストです。

さらに、SO_EXCLUSIVEADDRUSEソケットオプションが利用可能な場合(つまり、 Windowsの場合)、ソケットに設定されます。 これにより、テスト期間中、他の人がホスト/ポートにバインドするのを防ぐことができます。

test.support.find_unused_port(family=socket.AF_INET, socktype=socket.SOCK_STREAM)

バインドに適しているはずの未使用のポートを返します。 これは、sockパラメーター(デフォルトは AF_INETSOCK_STREAM )と同じファミリーとタイプの一時ソケットを作成し、それを指定されたホストにバインドすることで実現されます。ポートを0に設定したアドレス(デフォルトは0.0.0.0)で、OSから未使用のエフェメラルポートを引き出します。 その後、一時ソケットが閉じられて削除され、エフェメラルポートが返されます。

このメソッドまたは bind_port()は、テスト中にサーバーソケットを特定のポートにバインドする必要があるすべてのテストに使用する必要があります。 どちらを使用するかは、呼び出し元のコードがPythonソケットを作成しているかどうか、または未使用のポートをコンストラクターで提供する必要があるか、外部プログラムに渡す必要があるかによって異なります(つまり、 opensslのs_serverモードに対する-accept引数)。 可能な場合は、 find_unused_port()よりも bind_port()を常に優先します。 ハードコードされたポートを使用すると、テストの複数のインスタンスを同時に実行できなくなる可能性があるため、お勧めしません。これは、ビルドボットの問題です。

test.support.load_package_tests(pkg_dir, loader, standard_tests, pattern)

テストパッケージで使用するための unittest load_testsプロトコルの汎用実装。 pkg_dir はパッケージのルートディレクトリです。 ローダーstandard_tests 、およびパターンは、load_testsで予期される引数です。 単純なケースでは、テストパッケージの__init__.pyは次のようになります。

import os
from test.support import load_package_tests

def load_tests(*args):
    return load_package_tests(os.path.dirname(__file__), *args)
test.support.detect_api_mismatch(ref_api, other_api, *, ignore=())

ignore で指定されたこのチェックで無視される項目の定義済みリストを除いて、 other_api で見つからない ref_api の属性、関数、またはメソッドのセットを返します。 。

デフォルトでは、これは「_」で始まるプライベート属性をスキップしますが、すべてのマジックメソッドが含まれます。 '__'で始まり '__'で終わるもの。

バージョン3.5の新機能。

test.support.check__all__(test_case, module, name_of_module=None, extra=(), blacklist=())

module__all__変数にすべてのパブリック名が含まれていることを表明します。

モジュールのパブリック名(そのAPI)は、パブリック名の規則に一致し、モジュールで定義されているかどうかに基づいて自動的に検出されます。

name_of_module 引数は、パブリックAPIとして検出されるためにAPIを定義できるモジュールを(文字列またはそのタプルとして)指定できます。 この1つのケースは、 module がパブリックAPIの一部を他のモジュール(おそらくCバックエンド(csvやその_csvなど)からインポートする場合)です。

extra 引数は、適切な__module__属性のないオブジェクトのように、他の方法では「パブリック」として自動的に検出されない名前のセットにすることができます。 提供されている場合は、自動的に検出されたものに追加されます。

blacklist 引数は、名前が別の方法で示している場合でも、パブリックAPIの一部として扱われてはならない名前のセットにすることができます。

使用例:

import bar
import foo
import unittest
from test import support

class MiscTestCase(unittest.TestCase):
    def test__all__(self):
        support.check__all__(self, foo)

class OtherTestCase(unittest.TestCase):
    def test__all__(self):
        extra = {'BAR_CONST', 'FOO_CONST'}
        blacklist = {'baz'}  # Undocumented name.
        # bar imports part of its API from _bar.
        support.check__all__(self, bar, ('bar', '_bar'),
                             extra=extra, blacklist=blacklist)

バージョン3.6の新機能。

test.support モジュールは、次のクラスを定義します。

class test.support.TransientResource(exc, **kwargs)
インスタンスは、指定された例外タイプが発生した場合に ResourceDenied を発生させるコンテキストマネージャーです。 キーワード引数はすべて、 with ステートメント内で発生した例外と比較される属性/値ペアとして扱われます。 すべてのペアが例外の属性と適切に一致する場合にのみ、 ResourceDenied が発生します。
class test.support.EnvironmentVarGuard

環境変数を一時的に設定または設定解除するために使用されるクラス。 インスタンスはコンテキストマネージャーとして使用でき、基になるos.environをクエリ/変更するための完全な辞書インターフェイスを備えています。 コンテキストマネージャーを終了すると、このインスタンスを介して行われた環境変数へのすべての変更がロールバックされます。

バージョン3.1で変更:辞書インターフェースを追加。

EnvironmentVarGuard.set(envvar, value)
環境変数envvarを一時的にvalueの値に設定します。
EnvironmentVarGuard.unset(envvar)
環境変数envvarの設定を一時的に解除します。
class test.support.SuppressCrashReport

サブプロセスのクラッシュが予想されるテストでのクラッシュダイアログポップアップの防止を試みるために使用されるコンテキストマネージャー。

Windowsでは、 SetErrorMode を使用してWindowsエラー報告ダイアログを無効にします。

UNIXでは、 resource.setrlimit()を使用して resource.RLIMIT_CORE のソフト制限を0に設定し、コアダンプファイルが作成されないようにします。

どちらのプラットフォームでも、古い値は__exit__()によって復元されます。

class test.support.WarningsRecorder
単体テストの警告を記録するために使用されるクラス。 詳細については、上記の check_warnings()のドキュメントを参照してください。
class test.support.FakePath(path)
単純なパスのようなオブジェクトpath 引数を返すだけの__fspath__()メソッドを実装します。 path が例外の場合、__fspath__()で発生します。