25.5。 テスト —Python用の回帰テストパッケージ
ノート
test パッケージは、Pythonによる内部使用のみを目的としています。 Pythonのコア開発者のために文書化されています。 ここに記載されているコードは、Pythonのリリース間で予告なしに変更または削除される可能性があるため、Pythonの標準ライブラリの外部でこのパッケージを使用することはお勧めしません。
test パッケージには、Pythonのすべての回帰テストと、モジュール test.support およびtest.regrtest
が含まれています。 test.support はテストを強化するために使用され、test.regrtest
はテストスイートを駆動します。
名前がtest_
で始まる test パッケージの各モジュールは、特定のモジュールまたは機能のテストスイートです。 すべての新しいテストは、 unittest または doctest モジュールを使用して作成する必要があります。 一部の古いテストは、sys.stdout
に出力された出力を比較する「従来の」テストスタイルを使用して記述されています。 このスタイルのテストは非推奨と見なされます。
25.5.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 ...
def test_main():
support.run_unittest(MyTestCase1,
MyTestCase2,
... list other tests ...
)
if __name__ == '__main__':
test_main()
この定型コードにより、テストスイートをtest.regrtest
で実行することも、スクリプトとして単独で実行することもできます。
回帰テストの目標は、コードを解読しようとすることです。 これにより、従うべきいくつかのガイドラインが導き出されます。
テストスイートは、すべてのクラス、関数、および定数を実行する必要があります。 これには、外部に提示される外部APIだけでなく、「プライベート」コードも含まれます。
ホワイトボックステスト(テストの作成時にテストされるコードを調べる)が推奨されます。 ブラックボックステスト(公開されたユーザーインターフェイスのみをテストする)は、すべての境界およびエッジケースがテストされていることを確認するのに十分なほど完全ではありません。
無効な値を含め、すべての可能な値がテストされていることを確認してください。 これにより、すべての有効な値が受け入れられるだけでなく、不適切な値が正しく処理されるようになります。
できるだけ多くのコードパスを使い果たします。 分岐が発生する場所をテストし、入力を調整して、コード内でできるだけ多くの異なるパスが使用されることを確認します。
テストされたコードで発見されたバグの明示的なテストを追加します。 これにより、将来コードが変更された場合にエラーが再発しないようになります。
テスト後は必ずクリーンアップしてください(すべての一時ファイルを閉じて削除するなど)。
テストがオペレーティングシステムの特定の条件に依存している場合は、テストを試行する前に、条件がすでに存在することを確認してください。
できるだけ少ないモジュールをインポートし、できるだけ早く実行します。 これにより、テストの外部依存関係が最小限に抑えられ、モジュールのインポートの副作用による異常な動作の可能性も最小限に抑えられます。
コードの再利用を最大化するようにしてください。 場合によっては、使用される入力のタイプと同じくらい小さいものによってテストが異なることがあります。 基本的なテストクラスを入力を指定するクラスでサブクラス化することにより、コードの重複を最小限に抑えます。
class TestFuncAcceptsSequences(unittest.TestCase): func = mySuperWhammyFunction def test_func(self): self.func(self.arg) class AcceptLists(TestFuncAcceptsSequences): arg = [1, 2, 3] class AcceptStrings(TestFuncAcceptsSequences): arg = 'abc' class AcceptTuples(TestFuncAcceptsSequences): arg = (1, 2, 3)
も参照してください
- テスト駆動開発
- コードの前にテストを書くことに関するケントベックの本。
25.5.2。 コマンドラインインターフェイスを使用したテストの実行
test.regrtest
モジュールは、 -m オプション python -m test.regrtest のおかげで、Pythonの回帰テストスイートを駆動するスクリプトとして実行できます。 スクリプトを単独で実行すると、 test パッケージ内のすべての回帰テストの実行が自動的に開始されます。 これは、名前がtest_
で始まるパッケージ内のすべてのモジュールを検索してインポートし、存在する場合は関数test_main()
を実行することによって行われます。 実行するテストの名前もスクリプトに渡される場合があります。 単一の回帰テスト( python -m test.regrtest test_spam )を指定すると、出力が最小化され、テストが成功したか失敗したかのみが出力されるため、出力が最小化されます。
test.regrtest
を直接実行すると、テストに使用できるリソースを直接設定できます。 これを行うには、-u
コマンドラインオプションを使用します。 -u
オプションの値としてall
を指定すると、すべての可能なリソースが有効になります: python -m test.regrtest -uall 。 1つを除くすべてのリソースが必要な場合(より一般的なケース)、不要なリソースのコンマ区切りリストがall
の後にリストされる場合があります。 コマンド python -m test.regrtest -uall、-audio、-largefile は、audio
およびlargefile
リソースを除くすべてのリソースでtest.regrtest
を実行します。 すべてのリソースとその他のコマンドラインオプションのリストについては、 python -m test.regrtest -h を実行してください。
回帰テストを実行する他のいくつかの方法は、テストが実行されているプラットフォームによって異なります。 Unixでは、Pythonが構築された最上位ディレクトリで make test を実行できます。 Windowsでは、PCBuild
ディレクトリから rt.bat を実行すると、すべての回帰テストが実行されます。
バージョン2.7.14で変更: test パッケージはスクリプトとして実行できます: python -m test 。 これは、test.regrtest
モジュールを実行するのと同じように機能します。
25.6。 test.support —テスト用の効用関数
ノート
test.test_support
モジュールは、Python3.xおよび2.7.14で test.support に名前が変更されました。 名前test.test_support
は、2.7でエイリアスとして保持されています。
test.support モジュールは、Pythonの回帰テストのサポートを提供します。
このモジュールは、次の例外を定義します。
- exception test.support.TestFailed
- テストが失敗したときに発生する例外。 これは、 unittest ベースのテストと unittest.TestCase のアサーションメソッドを優先して非推奨になりました。
- exception test.support.ResourceDenied
- unittest.SkipTest のサブクラス。 リソース(ネットワーク接続など)が利用できない場合に発生します。 require()関数によって発生します。
test.support モジュールは、次の定数を定義します。
- test.support.verbose
- 詳細出力が有効な場合は True 。 実行中のテストについてより詳細な情報が必要な場合は、チェックする必要があります。 verbose は
test.regrtest
によって設定されます。
- test.support.have_unicode
- Unicodeサポートが利用可能な場合は True 。
- test.support.is_jython
- 実行中のインタープリターがJythonの場合、 True 。
- test.support.TESTFN
- 一時ファイルの名前として安全に使用できる名前に設定します。 作成された一時ファイルはすべて閉じて、リンクを解除(削除)する必要があります。
- test.support.TEST_HTTP_URL
- ネットワークテスト専用のHTTPサーバーのURLを定義します。
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])
- リソースが利用できない場合は、 ResourceDenied を上げます。 msg は、 ResourceDenied が発生した場合の引数です。
__name__
が'__main__'
である関数によって呼び出された場合、常に True を返します。test.regrtest
でテストを実行する場合に使用します。
- test.support.findfile(filename)
- filename という名前のファイルへのパスを返します。 一致するものが見つからない場合は、ファイル名が返されます。 これはファイルへのパスである可能性があるため、失敗と同じではありません。
- test.support.run_unittest(*classes)
関数に渡された unittest.TestCase サブクラスを実行します。 この関数は、プレフィックス
test_
で始まるメソッドのクラスをスキャンし、テストを個別に実行します。文字列をパラメータとして渡すことも合法です。 これらは
sys.modules
のキーである必要があります。 関連する各モジュールは、unittest.TestLoader.loadTestsFromModule()
によってスキャンされます。 これは通常、次のtest_main()
関数で見られます。def test_main(): support.run_unittest(__name__)
これにより、指定されたモジュールで定義されたすべてのテストが実行されます。
- 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 が指定されている場合、またはオプションのキーワード引数 quick が False の場合、警告が期待どおりであることを確認します。指定された各フィルター同封のコードによって発生した警告の少なくとも1つに一致する必要があります。一致しない場合、テストは失敗します。指定されたフィルターのいずれにも一致しない警告が発生した場合、テストは失敗します。 これらの最初のチェックを無効にするには、 quick を True に設定します。引数が指定されていない場合、デフォルトで次のようになります。
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
ここですべての警告がキャッチされ、テストコードはキャプチャされた警告を直接テストします。
バージョン2.6の新機能。
バージョン2.7で変更:新しいオプションの引数フィルターおよびクワイエット。
- test.support.check_py3k_warnings(*filters, quiet=False)
check_warnings()に似ていますが、Python3の互換性に関する警告があります。
sys.py3kwarning == 1
の場合、警告が効果的に発生するかどうかを確認します。sys.py3kwarning == 0
の場合、警告が発生していないことを確認します。("message regexp", WarningCategory)
の形式の2タプルを位置引数として受け入れます。 オプションのキーワード引数 quiet が True の場合、フィルターが何もキャッチしなくても失敗しません。 引数がない場合、デフォルトで次のようになります。check_py3k_warnings(("", DeprecationWarning), quiet=False)
バージョン2.7の新機能。
- test.support.captured_stdout()
これは、sys.stdoutとして StringIO.StringIO オブジェクトを使用して、 with ステートメント本体を実行するコンテキストマネージャーです。 そのオブジェクトは、 with ステートメントの
as
句を使用して取得できます。使用例:
with captured_stdout() as s: print "hello" assert s.getvalue() == "hello\n"
バージョン2.6の新機能。
- test.support.import_module(name, deprecated=False)
この関数は、指定されたモジュールをインポートして返します。 通常のインポートとは異なり、この関数は、モジュールをインポートできない場合に unittest.SkipTest を発生させます。
deprecated が True の場合、モジュールとパッケージの非推奨メッセージはこのインポート中に抑制されます。
バージョン2.7の新機能。
- test.support.import_fresh_module(name, fresh=(), blocked=(), deprecated=False)
この関数は、インポートを実行する前に
sys.modules
から名前付きモジュールを削除することにより、名前付きPythonモジュールの新しいコピーをインポートして返します。 reload()とは異なり、元のモジュールはこの操作の影響を受けないことに注意してください。fresh は、インポートを実行する前に
sys.modules
キャッシュからも削除される追加のモジュール名の反復可能です。blocked は、インポート中にモジュールキャッシュ内で
0
に置き換えられるモジュール名の反復可能であり、それらをインポートしようとするとImportError
が発生します。指定されたモジュールと、 fresh および blocked パラメーターで指定されたモジュールは、インポートを開始する前に保存され、新規インポートが完了すると
sys.modules
に再挿入されます。deprecated が True の場合、モジュールとパッケージの非推奨メッセージはこのインポート中に抑制されます。
指定されたモジュールをインポートできない場合、この関数は unittest.SkipTest を発生させます。
使用例:
# 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'])
バージョン2.7の新機能。
test.support モジュールは、次のクラスを定義します。
- class test.support.TransientResource(exc[, **kwargs])
インスタンスは、指定された例外タイプが発生した場合に ResourceDenied を発生させるコンテキストマネージャーです。 キーワード引数はすべて、 with ステートメント内で発生した例外と比較される属性/値ペアとして扱われます。 すべてのペアが例外の属性と適切に一致する場合にのみ、 ResourceDenied が発生します。
バージョン2.6の新機能。
- class test.support.EnvironmentVarGuard
環境変数を一時的に設定または設定解除するために使用されるクラス。 インスタンスはコンテキストマネージャーとして使用でき、基になる
os.environ
をクエリ/変更するための完全な辞書インターフェイスを備えています。 コンテキストマネージャーを終了すると、このインスタンスを介して行われた環境変数へのすべての変更がロールバックされます。バージョン2.6の新機能。
バージョン2.7で変更:辞書インターフェースを追加。
- EnvironmentVarGuard.set(envvar, value)
- 環境変数
envvar
を一時的にvalue
の値に設定します。
- EnvironmentVarGuard.unset(envvar)
- 環境変数
envvar
の設定を一時的に解除します。
- class test.support.WarningsRecorder
単体テストの警告を記録するために使用されるクラス。 詳細については、上記の check_warnings()のドキュメントを参照してください。
バージョン2.6の新機能。