UnitTestフレームワーク-クイックガイド
単体テストは、関数、メソッド、クラスなどのソースコードの個々のユニットをテストして、それらが使用に適しているかどうかを判断するソフトウェアテスト方法です。直感的には、ユニットをアプリケーションのテスト可能な最小の部分と見なすことができます。単体テストは、開発プロセス中にプログラマーによって作成された短いコードフラグメントです。これは、コンポーネントテストの基礎を形成します。
ユニットテストは、次の2つの方法で実行できます。
手動テスト | 自動テスト |
---|---|
ツールのサポートなしでテストケースを手動で実行することは、手動テストと呼ばれます。
|
自動化ツールを使用してツールサポートを取得し、テストケースを実行することは、自動化テストと呼ばれます。
|
JUnitは、Javaプログラミング言語のユニットテストフレームワークです。JUnitは、テスト駆動開発の開発において重要であり、JUnitに端を発したxUnitと総称される単体テストフレームワークのファミリーの1つです。あなたは見つけることができますJUnitのチュートリアルをここに。
「PyUnit」と呼ばれることもあるPythonユニットテストフレームワークは、KentBeckとErichGammaによって開発されたJUnitのPython言語バージョンです。PyUnitは、Pythonバージョン2.1以降のPython標準ライブラリの一部を形成します。
Pythonユニットテストフレームワークは、テストの自動化、テストのセットアップコードとシャットダウンコードの共有、テストのコレクションへの集約、およびレポートフレームワークからのテストの独立性をサポートします。unittestモジュールは、一連のテストでこれらの品質を簡単にサポートできるようにするクラスを提供します。
このチュートリアルは、初心者がPythonテストフレームワークの基本的な機能を理解できるように作成されています。このチュートリアルを完了すると、Pythonテストフレームワークの使用に関する中程度の専門知識が得られ、そこから次のレベルに進むことができます。
Python言語を使用したソフトウェア開発に関する合理的な専門知識が必要です。私たちのPythonチュートリアルは、Pythonの学習を始めるのに適した場所です。ソフトウェアテストの基本に関する知識も必要です。
環境設定
テストの作成に必要なクラスは、「unittest」モジュールにあります。古いバージョンのPython(Python 2.1より前)を使用している場合、モジュールはからダウンロードできます。http://pyunit.sourceforge.net/。ただし、unittestモジュールは標準のPythonディストリビューションの一部になりました。したがって、個別にインストールする必要はありません。
「unittest」は、テストの自動化、テストのセットアップコードとシャットダウンコードの共有、テストのコレクションへの集約、およびレポートフレームワークからのテストの独立性をサポートします。
unittestモジュールは、一連のテストでこれらの品質を簡単にサポートできるようにするクラスを提供します。
これを達成するために、unittestは次の重要な概念をサポートしています-
test fixture−これは、1つ以上のテストを実行するために必要な準備、および関連するクリーンアップアクションを表します。これには、たとえば、一時データベースまたはプロキシデータベース、ディレクトリの作成、またはサーバープロセスの開始が含まれる場合があります。
test case−これはテストの最小単位です。これにより、特定の入力セットに対する特定の応答がチェックされます。unittestは基本クラスを提供します。TestCase、新しいテストケースを作成するために使用できます。
test suite−これは、テストケース、テストスイート、またはその両方のコレクションです。これは、一緒に実行する必要があるテストを集約するために使用されます。テストスイートは、TestSuiteクラスによって実装されます。
test runner−これは、テストの実行を調整し、ユーザーに結果を提供するコンポーネントです。ランナーは、グラフィカルインターフェイス、テキストインターフェイスを使用するか、テストの実行結果を示す特別な値を返すことができます。
ユニットテストの作成
次の手順は、簡単な単体テストの作成に関係しています。
Step 1 −プログラムにunittestモジュールをインポートします。
Step 2−テストする関数を定義します。次の例では、add()関数をテストします。
Step 3 −unittest.TestCaseをサブクラス化してテストケースを作成します。
Step 4−クラス内のメソッドとしてテストを定義します。メソッドの名前は「test」で始まる必要があります。
Step 5−各テストは、TestCaseクラスのassert関数を呼び出します。アサーションには多くの種類があります。次の例では、assertEquals()関数を呼び出します。
Step 6 − assertEquals()関数は、add()関数の結果をarg2引数と比較し、比較が失敗した場合はassertionErrorをスローします。
Step 7 −最後に、unittestモジュールからmain()メソッドを呼び出します。
import unittest
def add(x,y):
return x + y
class SimpleTest(unittest.TestCase):
def testadd1(self):
self.assertEquals(add(4,5),9)
if __name__ == '__main__':
unittest.main()
Step 8 −コマンドラインから上記のスクリプトを実行します。
C:\Python27>python SimpleTest.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
Step 9 −次の3つは、テストの可能な結果である可能性があります−
シニア番号 | メッセージと説明 |
---|---|
1 | OK テストに合格します。「A」がコンソールに表示されます。 |
2 | FAIL テストは合格せず、AssertionError例外が発生します。「F」がコンソールに表示されます。 |
3 | ERROR このテストでは、AssertionError以外の例外が発生します。コンソールに「E」が表示されます。 |
これらの結果は、コンソールにそれぞれ「。」、「F」、「E」で表示されます。
コマンドラインインターフェイス
unittestモジュールは、コマンドラインから使用して、単一または複数のテストを実行できます。
python -m unittest test1
python -m unittest test_module.TestClass
python -m unittest test_module.TestClass.test_method
unittestは、次のコマンドラインオプションをサポートしています。すべてのコマンドラインオプションのリストについては、次のコマンドを使用してください-
Python –m unittest -h
シニア番号 | オプションと説明 |
---|---|
1 | -h, --help このメッセージを表示する |
2 | v, --verbose 冗長出力 |
3 | -q, --quiet 最小限の出力 |
4 | -f, --failfast 最初の失敗で停止 |
5 | -c, --catch コントロールCをキャッチして結果を表示する |
6 | -b, --buffer テスト実行中のバッファstdoutとstderr |
この章では、unittestモジュールで定義されているクラスとメソッドについて説明します。このモジュールには5つの主要なクラスがあります。
TestCaseクラス
このクラスのオブジェクトは、テスト可能な最小単位を表します。テストルーチンを保持し、各ルーチンを準備し、その後クリーンアップするためのフックを提供します。
以下のメソッドは、TestCaseクラスで定義されています-
シニア番号 | 方法と説明 |
---|---|
1 | setUp() テストフィクスチャを準備するために呼び出されるメソッド。これは、テストメソッドを呼び出す直前に呼び出されます |
2 | tearDown() テストメソッドが呼び出され、結果が記録された直後に呼び出されたメソッド。これは、テストメソッドで例外が発生した場合でも呼び出されます。 |
3 | setUpClass() 個々のクラスの実行前に呼び出されるクラスメソッド。 |
4 | tearDownClass() 個々のクラスのテストが実行された後に呼び出されるクラスメソッド。 |
5 | run(result = None) 渡されたテスト結果オブジェクトに結果を収集し、テストを実行した結果。 |
6 | skipTest(reason) テストメソッドまたはsetUp()中にこれを呼び出すと、現在のテストがスキップされます。 |
7 | debug() 結果を収集せずにテストを実行します。 |
8 | shortDescription() テストの1行の説明を返します。 |
備品
TestCaseクラス内には多数のテストが記述されている可能性があります。これらのテスト方法では、データベース接続、一時ファイル、またはその他のリソースを初期化する必要がある場合があります。これらはフィクスチャと呼ばれます。TestCaseには、テストに必要なフィクスチャを構成およびクリーンアップするための特別なフックが含まれています。フィクスチャを設定するには、setUp()をオーバーライドします。クリーンアップするには、tearDown()をオーバーライドします。
次の例では、2つのテストがTestCaseクラス内に記述されています。2つの値の加算と減算の結果をテストします。setup()メソッドは、各テストのshortDescription()に基づいて引数を初期化します。teardown()メソッドは、各テストの最後に実行されます。
import unittest
class simpleTest2(unittest.TestCase):
def setUp(self):
self.a = 10
self.b = 20
name = self.shortDescription()
if name == "Add":
self.a = 10
self.b = 20
print name, self.a, self.b
if name == "sub":
self.a = 50
self.b = 60
print name, self.a, self.b
def tearDown(self):
print '\nend of test',self.shortDescription()
def testadd(self):
"""Add"""
result = self.a+self.b
self.assertTrue(result == 100)
def testsub(self):
"""sub"""
result = self.a-self.b
self.assertTrue(result == -10)
if __name__ == '__main__':
unittest.main()
上記のコードをコマンドラインから実行します。次の出力が得られます-
C:\Python27>python test2.py
Add 10 20
F
end of test Add
sub 50 60
end of test sub
.
================================================================
FAIL: testadd (__main__.simpleTest2)
Add
----------------------------------------------------------------------
Traceback (most recent call last):
File "test2.py", line 21, in testadd
self.assertTrue(result == 100)
AssertionError: False is not true
----------------------------------------------------------------------
Ran 2 tests in 0.015s
FAILED (failures = 1)
クラスフィクスチャ
TestCaseクラスにはsetUpClass()メソッドがあり、TestCaseクラス内の個々のテストを実行する前にオーバーライドして実行できます。同様に、tearDownClass()メソッドは、クラス内のすべてのテストの後に実行されます。どちらのメソッドもクラスメソッドです。したがって、@ classmethodディレクティブで装飾する必要があります。
次の例は、これらのクラスメソッドの使用法を示しています。
import unittest
class TestFixtures(unittest.TestCase):
@classmethod
def setUpClass(cls):
print 'called once before any tests in class'
@classmethod
def tearDownClass(cls):
print '\ncalled once after all tests in class'
def setUp(self):
self.a = 10
self.b = 20
name = self.shortDescription()
print '\n',name
def tearDown(self):
print '\nend of test',self.shortDescription()
def test1(self):
"""One"""
result = self.a+self.b
self.assertTrue(True)
def test2(self):
"""Two"""
result = self.a-self.b
self.assertTrue(False)
if __name__ == '__main__':
unittest.main()
TestSuiteクラス
Pythonのテストフレームワークは、テストする機能に応じてテストケースインスタンスをグループ化できる便利なメカニズムを提供します。このメカニズムは、unittestモジュールのTestSuiteクラスによって利用可能になります。
次の手順は、テストスイートの作成と実行に関係しています。
Step 1 −TestSuiteクラスのインスタンスを作成します。
suite = unittest.TestSuite()
Step 2 −スイートのTestCaseクラス内にテストを追加します。
suite.addTest(testcase class)
Step 3 − makeSuite()メソッドを使用して、クラスからテストを追加することもできます
suite = unittest.makeSuite(test case class)
Step 4 −スイートに個別のテストを追加することもできます。
suite.addTest(testcaseclass(""testmethod")
Step 5 −TestTestRunnerクラスのオブジェクトを作成します。
runner = unittest.TextTestRunner()
Step 6 − run()メソッドを呼び出して、スイート内のすべてのテストを実行します
runner.run (suite)
TestSuiteクラスでは以下のメソッドが定義されています-
シニア番号 | 方法と説明 |
---|---|
1 | addTest() テストスイートにテストメソッドを追加します。 |
2 | addTests() 複数のTestCaseクラスからテストを追加します。 |
3 | run() このスイートに関連付けられたテストを実行し、結果をテスト結果オブジェクトに収集します |
4 | debug() 結果を収集せずに、このスイートに関連付けられたテストを実行します。 |
5 | countTestCases() このテストオブジェクトによって表されるテストの数を返します |
次の例は、TestSuiteクラスの使用方法を示しています-
import unittest
class suiteTest(unittest.TestCase):
def setUp(self):
self.a = 10
self.b = 20
def testadd(self):
"""Add"""
result = self.a+self.b
self.assertTrue(result == 100)
def testsub(self):
"""sub"""
result = self.a-self.b
self.assertTrue(result == -10)
def suite():
suite = unittest.TestSuite()
## suite.addTest (simpleTest3("testadd"))
## suite.addTest (simpleTest3("testsub"))
suite.addTest(unittest.makeSuite(simpleTest3))
return suite
if __name__ == '__main__':
runner = unittest.TextTestRunner()
test_suite = suite()
runner.run (test_suite)
makeSuite()メソッドを持つ行とコメントステートメントのコメントを解除することで、addTest()メソッドを試すことができます。
TestLoaderクラス
unittestパッケージには、クラスとモジュールからテストスイートを作成するために使用されるTestLoaderクラスがあります。デフォルトでは、unittest.main(0メソッドが呼び出されると、unittest.defaultTestLoaderインスタンスが自動的に作成されます。ただし、明示的なインスタンスを使用すると、特定のプロパティをカスタマイズできます。
次のコードでは、TestLoaderオブジェクトを使用して、2つのクラスのテストがリストに収集されます。
import unittest
testList = [Test1, Test2]
testLoad = unittest.TestLoader()
TestList = []
for testCase in testList:
testSuite = testLoad.loadTestsFromTestCase(testCase)
TestList.append(testSuite)
newSuite = unittest.TestSuite(TestList)
runner = unittest.TextTestRunner()
runner.run(newSuite)
次の表に、TestLoaderクラスのメソッドのリストを示します。
S.No | 方法と説明 |
---|---|
1 | loadTestsFromTestCase() TestCaseクラスに含まれるすべてのテストケースのスイートを返します |
2 | loadTestsFromModule() 指定されたモジュールに含まれるすべてのテストケースのスイートを返します。 |
3 | loadTestsFromName() 文字列指定子を指定して、すべてのテストケースのスイートを返します。 |
4 | discover() 指定された開始ディレクトリからサブディレクトリに再帰してすべてのテストモジュールを検索し、TestSuiteオブジェクトを返します |
TestResultクラス
このクラスは、成功したテストと失敗したテストに関する情報をコンパイルするために使用されます。TestResultオブジェクトは、一連のテストの結果を格納します。TestResultインスタンスは、TestRunner.run()メソッドによって返されます。
TestResultインスタンスには次の属性があります-
シニア番号 | 属性と説明 |
---|---|
1 | Errors 2タプルのTestCaseインスタンスとフォーマットされたトレースバックを保持する文字列を含むリスト。各タプルは、予期しない例外を発生させたテストを表します。 |
2 | Failures 2タプルのTestCaseインスタンスとフォーマットされたトレースバックを保持する文字列を含むリスト。各タプルは、TestCase.assert *()メソッドを使用して障害が明示的に通知されたテストを表します。 |
3 | Skipped TestCaseインスタンスの2タプルと、テストをスキップする理由を保持する文字列を含むリスト。 |
4 | wasSuccessful() これまでに実行されたすべてのテストに合格した場合はTrueを返し、それ以外の場合はFalseを返します。 |
5 | stop() このメソッドを呼び出して、実行中の一連のテストを中止する必要があることを通知できます。 |
6 | startTestRun() テストが実行される前に1回呼び出されます。 |
7 | stopTestRun() すべてのテストが実行された後に1回呼び出されます。 |
8 | testsRun これまでに実行されたテストの総数。 |
9 | Buffer trueに設定すると、 sys.stdout そして sys.stderr startTest()とstopTest()が呼び出される間にバッファリングされます。 |
次のコードはテストスイートを実行します-
if __name__ == '__main__':
runner = unittest.TextTestRunner()
test_suite = suite()
result = runner.run (test_suite)
print "---- START OF TEST RESULTS"
print result
print "result::errors"
print result.errors
print "result::failures"
print result.failures
print "result::skipped"
print result.skipped
print "result::successful"
print result.wasSuccessful()
print "result::test-run"
print result.testsRun
print "---- END OF TEST RESULTS"
コードを実行すると、次の出力が表示されます-
---- START OF TEST RESULTS
<unittest.runner.TextTestResult run = 2 errors = 0 failures = 1>
result::errors
[]
result::failures
[(<__main__.suiteTest testMethod = testadd>, 'Traceback (most recent call last):\n
File "test3.py", line 10, in testadd\n
self.assertTrue(result == 100)\nAssert
ionError: False is not true\n')]
result::skipped
[]
result::successful
False
result::test-run
2
---- END OF TEST RESULTS
Pythonテストフレームワークは、特定の条件をテストするPythonの組み込みassert()関数を使用します。アサーションが失敗した場合、AssertionErrorが発生します。次に、テストフレームワークはテストを失敗として識別します。その他の例外はエラーとして扱われます。
次の3セットのアサーション関数がunittestモジュールで定義されています-
- 基本的なブールアサート
- 比較アサート
- コレクションのアサート
基本的なアサート関数は、操作の結果がTrueかFalseかを評価します。すべてのassertメソッドはmsg 指定されている場合、失敗時のエラーメッセージとして使用される引数。
シニア番号 | 方法と説明 |
---|---|
1 | assertEqual(arg1, arg2, msg = None) arg1とarg2が等しいことをテストします。値が等しく比較されない場合、テストは失敗します。 |
2 | assertNotEqual(arg1, arg2, msg = None) arg1とarg2が等しくないことをテストします。値が等しく比較される場合、テストは失敗します。 |
3 | assertTrue(expr, msg = None) exprが真であることをテストします。falseの場合、テストは失敗します |
4 | assertFalse(expr, msg = None) exprがfalseであることをテストします。trueの場合、テストは失敗します |
5 | assertIs(arg1, arg2, msg = None) arg1とarg2が同じオブジェクトに評価されることをテストします。 |
6 | assertIsNot(arg1, arg2, msg = None) arg1とarg2が同じオブジェクトに評価されないことをテストします。 |
7 | assertIsNone(expr, msg = None) exprがNoneであることをテストします。なしでない場合、テストは失敗します |
8 | assertIsNotNone(expr, msg = None) exprがNoneではないことをテストします。なしの場合、テストは失敗します |
9 | assertIn(arg1, arg2, msg = None) arg1がarg2にあることをテストします。 |
10 | assertNotIn(arg1, arg2, msg = None) arg1がarg2にないことをテストします。 |
11 | assertIsInstance(obj, cls, msg = None) objがclsのインスタンスであることをテストします |
12 | assertNotIsInstance(obj, cls, msg = None) objがclsのインスタンスではないことをテストします |
上記のアサーション関数の一部は、次のコードで実装されています。
import unittest
class SimpleTest(unittest.TestCase):
def test1(self):
self.assertEqual(4 + 5,9)
def test2(self):
self.assertNotEqual(5 * 2,10)
def test3(self):
self.assertTrue(4 + 5 == 9,"The result is False")
def test4(self):
self.assertTrue(4 + 5 == 10,"assertion fails")
def test5(self):
self.assertIn(3,[1,2,3])
def test6(self):
self.assertNotIn(3, range(5))
if __name__ == '__main__':
unittest.main()
上記のスクリプトを実行すると、test2、test4、test6に失敗が表示され、その他は正常に実行されます。
FAIL: test2 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Python27\SimpleTest.py", line 9, in test2
self.assertNotEqual(5*2,10)
AssertionError: 10 == 10
FAIL: test4 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Python27\SimpleTest.py", line 13, in test4
self.assertTrue(4+5==10,"assertion fails")
AssertionError: assertion fails
FAIL: test6 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Python27\SimpleTest.py", line 17, in test6
self.assertNotIn(3, range(5))
AssertionError: 3 unexpectedly found in [0, 1, 2, 3, 4]
----------------------------------------------------------------------
Ran 6 tests in 0.001s
FAILED (failures = 3)
アサーション関数の2番目のセットは comparative asserts −
assertAlmostEqual (1番目、2番目、場所= 7、msg =なし、delta =なし)
テストことを第一及び第二の約(またはしない略)は、小数点以下の所定数に丸める、差を計算することによって等しく場所(デフォルト7)、
assertNotAlmostEqual (1番目、2番目、場所、メッセージ、デルタ)
差を計算し、指定された小数点以下の桁数(デフォルトは7)に丸め、ゼロと比較して、1番目と2番目がほぼ等しくないことをテストします。
上記の両方の関数で、場所の代わりにデルタが指定されている場合、1番目と2番目の差はデルタ以下(またはそれより大きい)である必要があります。
デルタと場所の両方を指定すると、TypeErrorが発生します。
assertGreater (最初、2番目、msg =なし)
メソッド名に応じて、最初が2番目より大きいことをテストします。そうでない場合、テストは失敗します。
assertGreaterEqual (最初、2番目、msg =なし)
メソッド名に応じて、firstがsecond以上であることをテストします。そうでない場合、テストは失敗します
assertLess (最初、2番目、msg =なし)
メソッド名に応じて、最初が2番目未満であることをテストします。そうでない場合、テストは失敗します
assertLessEqual (最初、2番目、msg =なし)
メソッド名に応じて、最初が2番目以下であることをテストします。そうでない場合、テストは失敗します。
assertRegexpMatches (テキスト、正規表現、メッセージ=なし)
正規表現検索がテキストと一致することをテストします。失敗した場合、エラーメッセージにはパターンとテキストが含まれます。regexpは、正規表現オブジェクト、またはでの使用に適した正規表現を含む文字列です。re.search()。
assertNotRegexpMatches (テキスト、正規表現、メッセージ=なし)
正規表現検索がテキストと一致しないことを確認します。パターンと一致するテキストの部分を含むエラーメッセージで失敗します。regexpは、正規表現オブジェクト、またはでの使用に適した正規表現を含む文字列です。re.search()。
アサーション関数は次の例で実装されています-
import unittest
import math
import re
class SimpleTest(unittest.TestCase):
def test1(self):
self.assertAlmostEqual(22.0/7,3.14)
def test2(self):
self.assertNotAlmostEqual(10.0/3,3)
def test3(self):
self.assertGreater(math.pi,3)
def test4(self):
self.assertNotRegexpMatches("Tutorials Point (I) Private Limited","Point")
if __name__ == '__main__':
unittest.main()
上記のスクリプトは、test1とtest4を失敗として報告します。test1では、22/7の除算は3.14の小数点以下7桁以内ではありません。同様に、2番目の引数は最初の引数のテキストと一致するため、test4はAssertionErrorになります。
=====================================================FAIL: test1 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "asserttest.py", line 7, in test1
self.assertAlmostEqual(22.0/7,3.14)
AssertionError: 3.142857142857143 != 3.14 within 7 places
================================================================
FAIL: test4 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "asserttest.py", line 13, in test4
self.assertNotRegexpMatches("Tutorials Point (I) Private Limited","Point")
AssertionError: Regexp matched: 'Point' matches 'Point' in 'Tutorials Point (I)
Private Limited'
----------------------------------------------------------------------
Ran 4 tests in 0.001s
FAILED (failures = 2)
コレクションのアサート
この一連のassert関数は、List、Tuple、Dictionary、SetなどのPythonのコレクションデータ型で使用することを目的としています。
シニア番号 | 方法と説明 |
---|---|
1 | assertListEqual (list1, list2, msg = None) 2つのリストが等しいことをテストします。そうでない場合は、2つの違いのみを示すエラーメッセージが作成されます。 |
2 | assertTupleEqual (tuple1, tuple2, msg = None) 2つのタプルが等しいことをテストします。そうでない場合は、2つの違いのみを示すエラーメッセージが作成されます。 |
3 | assertSetEqual (set1, set2, msg = None) 2つのセットが等しいことをテストします。そうでない場合は、セット間の違いをリストするエラーメッセージが作成されます。 |
4 | assertDictEqual (expected, actual, msg = None) 2つの辞書が等しいことをテストします。そうでない場合は、辞書の違いを示すエラーメッセージが作成されます。 |
次の例では、上記のメソッドを実装しています-
import unittest
class SimpleTest(unittest.TestCase):
def test1(self):
self.assertListEqual([2,3,4], [1,2,3,4,5])
def test2(self):
self.assertTupleEqual((1*2,2*2,3*2), (2,4,6))
def test3(self):
self.assertDictEqual({1:11,2:22},{3:33,2:22,1:11})
if __name__ == '__main__':
unittest.main()
上記の例では、test1とtest3はAssertionErrorを示しています。エラーメッセージには、リストオブジェクトとディクショナリオブジェクトの違いが表示されます。
FAIL: test1 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "asserttest.py", line 5, in test1
self.assertListEqual([2,3,4], [1,2,3,4,5])
AssertionError: Lists differ: [2, 3, 4] != [1, 2, 3, 4, 5]
First differing element 0:
2
1
Second list contains 2 additional elements.
First extra element 3:
4
- [2, 3, 4]
+ [1, 2, 3, 4, 5]
? +++ +++
FAIL: test3 (__main__.SimpleTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "asserttest.py", line 9, in test3
self.assertDictEqual({1:11,2:22},{3:33,2:22,1:11})
AssertionError: {1: 11, 2: 22} != {1: 11, 2: 22, 3: 33}
- {1: 11, 2: 22}
+ {1: 11, 2: 22, 3: 33}
? +++++++
----------------------------------------------------------------------
Ran 3 tests in 0.001s
FAILED (failures = 2)
TestLoaderクラスにはdiscover()関数があります。Pythonテストフレームワークは、これを使用して簡単なテスト検出を行います。互換性を保つには、テストを含むモジュールとパッケージがトップレベルのディレクトリからインポート可能である必要があります。
以下は、テスト検出の基本的なコマンドラインの使用法です。
Python –m unittest discover
インタプリタは、テストを含むすべてのモジュールを現在のディレクトリと内部ディレクトリから再帰的にロードしようとします。その他のコマンドラインオプションは次のとおりです。
シニア番号 | オプションと説明 |
---|---|
1 | -v, --verbose 冗長出力 |
2 | -s, --start-directory ディレクトリ検出を開始するディレクトリ(デフォルト) |
3 | -p, --pattern patternテストファイルに一致するパターン(test * .pyのデフォルト) |
4 | -t, --top-level-directory directoryプロジェクトの最上位ディレクトリ(デフォルトは開始ディレクトリ) |
たとえば、「tests」ディレクトリで名前が「assert」で始まるモジュールのテストを検出するには、次のコマンドラインを使用します。
C:\python27>python –m unittest –v –s "c:\test" –p "assert*.py"
テスト検出は、テストをインポートしてロードします。テストディスカバリーは、指定した開始ディレクトリからすべてのテストファイルを検出すると、パスをパッケージ名に変換してインポートします。
開始ディレクトリをディレクトリへのパスではなくパッケージ名として指定した場合、discoverは、インポート元の場所が目的の場所であると想定するため、警告は表示されません。
Python 2.7以降、テストのスキップのサポートが追加されました。条件付きおよび無条件で、個々のテストメソッドまたはTestCaseクラスをスキップすることができます。フレームワークでは、特定のテストを「予期される失敗」としてマークすることができます。このテストは「失敗」しますが、TestResultでは失敗としてカウントされません。
メソッドを無条件にスキップするには、次のunittest.skip()クラスメソッドを使用できます。
import unittest
def add(x,y):
return x+y
class SimpleTest(unittest.TestCase):
@unittest.skip("demonstrating skipping")
def testadd1(self):
self.assertEquals(add(4,5),9)
if __name__ == '__main__':
unittest.main()
skip()はクラスメソッドであるため、プレフィックスとして@トークンが付けられます。このメソッドは、スキップの理由を説明するログメッセージという1つの引数を取ります。
上記のスクリプトを実行すると、コンソールに次の結果が表示されます-
C:\Python27>python skiptest.py
s
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK (skipped = 1)
文字「s」は、テストがスキップされたことを示します。
テストをスキップするための代替構文は、テスト関数内でインスタンスメソッドskipTest()を使用することです。
def testadd2(self):
self.skipTest("another method for skipping")
self.assertTrue(add(4 + 5) == 10)
次のデコレータは、テストのスキップと予想される失敗を実装します-
シニア番号 | 方法と説明 |
---|---|
1 | unittest.skip(reason) 装飾されたテストを無条件にスキップします。理由は、テストがスキップされる理由を説明する必要があります。 |
2 | unittest.skipIf(condition, reason) 条件が真の場合、装飾されたテストをスキップします。 |
3 | unittest.skipUnless(condition, reason) 条件が真でない限り、装飾されたテストをスキップします。 |
4 | unittest.expectedFailure() テストを予想される失敗としてマークします。実行時にテストが失敗した場合、テストは失敗としてカウントされません。 |
次の例は、条件付きスキップの使用と予想される失敗を示しています。
import unittest
class suiteTest(unittest.TestCase):
a = 50
b = 40
def testadd(self):
"""Add"""
result = self.a+self.b
self.assertEqual(result,100)
@unittest.skipIf(a>b, "Skip over this routine")
def testsub(self):
"""sub"""
result = self.a-self.b
self.assertTrue(result == -10)
@unittest.skipUnless(b == 0, "Skip over this routine")
def testdiv(self):
"""div"""
result = self.a/self.b
self.assertTrue(result == 1)
@unittest.expectedFailure
def testmul(self):
"""mul"""
result = self.a*self.b
self.assertEqual(result == 0)
if __name__ == '__main__':
unittest.main()
上記の例では、testsub()とtestdiv()はスキップされます。前者の場合、a> bは真ですが、後者の場合、b == 0は真ではありません。一方、testmul()は予想される失敗としてマークされています。
上記のスクリプトを実行すると、スキップされた2つのテストで「s」が表示され、予想される失敗は「x」で表示されます。
C:\Python27>python skiptest.py
Fsxs
================================================================
FAIL: testadd (__main__.suiteTest)
Add
----------------------------------------------------------------------
Traceback (most recent call last):
File "skiptest.py", line 9, in testadd
self.assertEqual(result,100)
AssertionError: 90 != 100
----------------------------------------------------------------------
Ran 4 tests in 0.000s
FAILED (failures = 1, skipped = 2, expected failures = 1)
Pythonテストフレームワークは、例外が発生したことを確認するために次のアサーションメソッドを提供します。
assertRaises(exception、callable、* args、** kwds)
関数が位置引数またはキーワード引数を使用して呼び出されたときに、例外(最初の引数)が発生することをテストします。予期された例外が発生した場合はテストに合格し、別の例外が発生した場合はエラーになり、例外が発生しなかった場合は失敗します。例外のグループのいずれかをキャッチするために、例外クラスを含むタプルを例外として渡すことができます。
以下の例では、ZeroDivisionErrorが発生したかどうかを確認するためのテスト関数が定義されています。
import unittest
def div(a,b):
return a/b
class raiseTest(unittest.TestCase):
def testraise(self):
self.assertRaises(ZeroDivisionError, div, 1,0)
if __name__ == '__main__':
unittest.main()
testraise()関数はassertRaises()関数を使用して、div()関数が呼び出されたときにゼロによる除算が発生するかどうかを確認します。上記のコードは例外を発生させます。ただし、div()関数の引数を次のように変更します-
self.assertRaises(ZeroDivisionError, div, 1,1)
これらの変更を加えてコードを実行すると、ZeroDivisionErrorが発生しないため、テストは失敗します。
F
================================================================
FAIL: testraise (__main__.raiseTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "raisetest.py", line 7, in testraise
self.assertRaises(ZeroDivisionError, div, 1,1)
AssertionError: ZeroDivisionError not raised
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (failures = 1)
assertRaisesRegexp(exception、regexp、callable、* args、** kwds)
発生した例外の文字列表現で正規表現が一致することをテストします。regexpは、正規表現オブジェクト、またはre.search()での使用に適した正規表現を含む文字列です。
次の例は、assertRaisesRegexp()の使用方法を示しています-
import unittest
import re
class raiseTest(unittest.TestCase):
def testraiseRegex(self):
self.assertRaisesRegexp(TypeError, "invalid", reg,"Point","TutorialsPoint")
if __name__ == '__main__':
unittest.main()
ここで、testraseRegex()テストは最初の引数として失敗しません。「ポイント」は2番目の引数文字列にあります。
================================================================
FAIL: testraiseRegex (__main__.raiseTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:/Python27/raiseTest.py", line 11, in testraiseRegex
self.assertRaisesRegexp(TypeError, "invalid", reg,"Point","TutorialsPoint")
AssertionError: TypeError not raised
----------------------------------------------------------------------
ただし、変更は以下のとおりです。
self.assertRaisesRegexp(TypeError, "invalid", reg,123,"TutorialsPoint")
TypeError例外がスローされます。したがって、次の結果が表示されます-
================================================================
FAIL: testraiseRegex (__main__.raiseTest)
----------------------------------------------------------------------
Traceback (most recent call last):
File "raisetest.py", line 11, in testraiseRegex
self.assertRaisesRegexp(TypeError, "invalid", reg,123,"TutorialsPoint")
AssertionError: "invalid" does not match
"first argument must be string or compiled pattern"
----------------------------------------------------------------------
JavaユニットテストフレームワークであるJunit(PyunitはJUnitの実装です)には、タイムアウトの便利なオプションがあります。テストに指定された時間がかかる場合、失敗としてマークされます。
Pythonのテストフレームワークには、タイムアウトのサポートは含まれていません。ただし、timeout-decoratorと呼ばれる3番目の部分のモジュールがその仕事をすることができます。
-からモジュールをダウンロードしてインストールします
https://pypi.python.org/packages/source/t/timeout-decorator/timeout-decorator-0.3.2.tar.gz
- コードにtimeout_decoratorをインポートします
- テストの前にタイムアウトデコレータを配置する
- @timeout_decorator.timeout(10)
この行より下のテストメソッドがここに記載されているタイムアウト(10分)を超えると、TimeOutErrorが発生します。例-
import time
import timeout_decorator
class timeoutTest(unittest.TestCase):
@timeout_decorator.timeout(5)
def testtimeout(self):
print "Start"
for i in range(1,10):
time.sleep(1)
print "%d seconds have passed" % i
if __name__ == '__main__':
unittest.main()
unittest2は、Python2.7以降のPythonテストフレームワークに追加された追加機能のバックポートです。Python 2.6、2.7、および3. *で実行することがテストされています。最新バージョンはからダウンロードできますhttps://pypi.python.org/pypi/unittest2
unittestの代わりにunittest2を使用するには、importunittestをimportunittest2に置き換えるだけです。
unittest2のクラスは、unittestの適切なクラスから派生しているため、すべてのテストをすぐにunittest2の使用に切り替えることなく、unittest2テスト実行インフラストラクチャを使用できるはずです。新しい機能を実装する場合は、テストケースをからサブクラス化します。unittest2.TestCase unittest.TestCaseの代わりに
以下は、unittest2の新機能です。
addCleanups より良いリソース管理のために
多くの新しいassertメソッドが含まれています
assertRaises コンテキストマネージャーとして、後で例外にアクセスできます
次のようなモジュールレベルのフィクスチャがあります setUpModule そして tearDownModule
含まれています load_tests モジュールまたはパッケージからテストをロードするためのプロトコル
startTestRun そして stopTestRun TestResultのメソッド
Python 2.7では、でunittestコマンドライン機能(テスト検出を含む)を呼び出します。 python -m unittest <args>。
代わりに、unittest2にはスクリプトunit2が付属しています。
unit2 discover
unit2 -v test_module
テスト実行中のcontrol-Cのより効率的な処理は、unittestの-c / -catchコマンドラインオプションと、 catchbreakパラメータ。キャッチブレーク動作を有効にすると、control-Cで現在実行中のテストを完了できるようになり、テストの実行が終了して、これまでのすべての結果が報告されます。2番目のcontrol-cは、通常の方法でKeyboardInterruptを発生させます。
unittestハンドラーが呼び出されたが、signal.SIGINTハンドラーがインストールされていない場合は、デフォルトのハンドラーが呼び出されます。これは通常、インストールされたハンドラーを置き換えてそれに委任するコードによって期待される動作になります。unittest control-c処理を無効にする必要がある個々のテストでは、removeHandler()デコレータを使用できます。
次のユーティリティ関数は、テストフレームワーク内でcontrol-c処理機能を有効にします-
unittest.installHandler()
control-cハンドラーをインストールします。いつsignal.SIGINT 登録されたすべての結果が受信され、TestResult.stop()が呼び出されます。
unittest.registerResult(result)
登録する TestResultcontrol-c処理のオブジェクト。結果を登録すると、その結果への弱参照が格納されるため、結果がガベージコレクションされるのを防ぐことはできません。
unittest.removeResult(result)
登録された結果を削除します。結果が削除されると、control-cに応答してその結果オブジェクトでTestResult.stop()が呼び出されなくなります。
unittest.removeHandler(function = None)
この関数を引数なしで呼び出すと、control-cハンドラーがインストールされている場合は削除されます。この関数は、テストの実行中にハンドラーを一時的に削除するためのテストデコレータとしても使用できます。
GUIテストランナー
unittestモジュールは、テストをインタラクティブに検出して実行するためにインストールされます。このユーティリティ、Pythonスクリプト「inittestgui.py」は、TKグラフィックツールキットのPythonポートであるTkinterモジュールを使用します。検出とテストの実行に使いやすいGUIを提供します。
Python unittestgui.py
[テストの検出]ボタンをクリックします。テストを実行するディレクトリとモジュールを選択できる小さなダイアログボックスが表示されます。
最後に、スタートボタンをクリックします。選択したパスとモジュール名からテストが検出され、結果ペインに結果が表示されます。
個々のテストの詳細を表示するには、結果ボックスでテストを選択してクリックします-
Pythonのインストールでこのユーティリティが見つからない場合は、プロジェクトページから入手できます。 http://pyunit.sourceforge.net/。
同様に、wxpythonツールキットに基づくユーティリティもここで利用できます。
Pythonの標準ディストリビューションには「Doctest」モジュールが含まれています。このモジュールの機能により、インタラクティブなPythonセッションのように見えるテキストを検索し、これらのセッションを実行して、表示されているとおりに機能するかどうかを確認できます。
Doctestは、次のシナリオで非常に役立ちます-
すべてのインタラクティブな例が文書化されたとおりに機能することを確認することにより、モジュールのdocstringが最新であることを確認します。
テストファイルまたはテストオブジェクトのインタラクティブな例が期待どおりに機能することを確認して、回帰テストを実行します。
パッケージのチュートリアルドキュメントを作成するには、入出力の例を自由に示します。
Pythonでは、「docstring」は、クラス、関数、またはモジュールの最初の式として表示される文字列リテラルです。スイートの実行時には無視されますが、コンパイラによって認識され、__doc__囲んでいるクラス、関数、またはモジュールの属性。イントロスペクションを介して利用できるため、オブジェクトを文書化するための標準的な場所です。
Pythonコードのさまざまな部分の使用例をdocstring内に配置するのが通常の方法です。doctestモジュールを使用すると、これらのdocstringがコードの断続的なリビジョンで最新であることを確認できます。
次のコードでは、階乗関数が使用例を散在させて定義されています。使用例が正しいかどうかを確認するには、doctestモジュールでtestmod()関数を呼び出します。
"""
This is the "example" module.
The example module supplies one function, factorial(). For example,
>>> factorial(5)
120
"""
def factorial(x):
"""Return the factorial of n, an exact integer >= 0.
>>> factorial(-1)
Traceback (most recent call last):
...
ValueError: x must be >= 0
"""
if not x >= 0:
raise ValueError("x must be >= 0")
f = 1
for i in range(1,x+1):
f = f*i
return f
if __name__ == "__main__":
import doctest
doctest.testmod()
上記のスクリプトを入力してFactDocTest.pyとして保存し、コマンドラインからこのスクリプトを実行してみてください。
Python FactDocTest.py
例が失敗しない限り、出力は表示されません。ここで、コマンドラインを次のように変更します-
Python FactDocTest.py –v
コンソールに次の出力が表示されます-
C:\Python27>python FactDocTest.py -v
Trying:
factorial(5)
Expecting:
120
ok
Trying:
factorial(-1)
Expecting:
Traceback (most recent call last):
...
ValueError: x must be >= 0
ok
2 items passed all tests:
1 tests in __main__
1 tests in __main__.factorial
2 tests in 2 items.
2 passed and 0 failed.
Test passed.
一方、factorial()関数のコードでdocstringに期待される結果が得られない場合は、失敗の結果が表示されます。たとえば、上記のスクリプトでf = 1の代わりにf = 2を変更して、doctestを再実行します。結果は次のようになります-
Trying:
factorial(5)
Expecting:
120
**********************************************************************
File "docfacttest.py", line 6, in __main__
Failed example:
factorial(5)
Expected:
120
Got:
240
Trying:
factorial(-1)
Expecting:
Traceback (most recent call last):
...
ValueError: x must be >= 0
ok
1 items passed all tests:
1 tests in __main__.factorial
**********************************************************************
1 items had failures:
1 of 1 in __main__
2 tests in 2 items.
1 passed and 1 failed.
***Test Failed*** 1 failures.
Doctest:テキストファイルの例を確認する
doctestのもう1つの簡単なアプリケーションは、テキストファイルでインタラクティブな例をテストすることです。これは、testfile()関数を使用して実行できます。
次のテキストは、「example.txt」という名前のテキストファイルに保存されます。
Using ''factorial''
-------------------
This is an example text file in reStructuredText format. First import
''factorial'' from the ''example'' module:
>>> from example import factorial
Now use it:
>>> factorial(5)
120
ファイルの内容はdocstringとして扱われます。テキストファイルの例を確認するには、doctestモジュールのtestfile()関数を使用します。
def factorial(x):
if not x >= 0:
raise ValueError("x must be >= 0")
f = 1
for i in range(1,x+1):
f = f*i
return f
if __name__ == "__main__":
import doctest
doctest.testfile("example.txt")
testmod()と同様に、testfile()は、例が失敗しない限り何も表示しません。例が失敗した場合、失敗した例と失敗の原因が、testmod()と同じ形式を使用してコンソールに出力されます。
ほとんどの場合、インタラクティブコンソールセッションのコピーアンドペーストは正常に機能しますが、doctestは特定のPythonシェルの正確なエミュレーションを実行しようとはしていません。
期待される出力は、コードを含む最後の「>>>」または「...」行の直後に続く必要があり、期待される出力(存在する場合)は、次の「>>>」またはすべて空白の行まで拡張されます。
期待される出力にすべて空白の行を含めることはできません。このような行は、期待される出力の終了を示すために使用されるためです。期待される出力に空白行が含まれている場合は、doctestの例に<BLANKLINE>を配置して、空白行が期待される場所に配置します。
doctest APIは、docstringからのインタラクティブな例を格納するために使用される次の2つのコンテナクラスを中心に展開します-
Example −期待される出力とペアになった単一のPythonステートメント。
DocTest −通常、単一のdocstringまたはテキストファイルから抽出された例のコレクション。
次の追加の処理クラスは、doctestの例を検索、解析、実行、およびチェックするために定義されています。
DocTestFinder −指定されたモジュール内のすべてのdocstringを検索し、DocTestParserを使用して、インタラクティブな例を含むすべてのdocstringからDocTestを作成します。
DocTestParser −文字列(オブジェクトのdocstringなど)からdoctestオブジェクトを作成します。
DocTestRunner − doctestの例を実行し、OutputCheckerを使用してそれらの出力を検証します。
OutputChecker − doctestの例からの実際の出力を期待される出力と比較し、それらが一致するかどうかを判断します。
DocTestFinderクラス
これは、特定のオブジェクトに関連するdoctestを、そのdocstringおよび含まれているオブジェクトのdocstringから抽出するために使用される処理クラスです。現在、Doctestは、モジュール、関数、クラス、メソッド、staticmethods、classmethods、およびプロパティのオブジェクトタイプから抽出できます。
このクラスは、find()メソッドを定義します。オブジェクトのdocstring、または含まれているオブジェクトのdocstringのいずれかによって定義されたDocTestのリストを返します。
DocTestParserクラス
これは、文字列からインタラクティブな例を抽出し、それらを使用してDocTestオブジェクトを作成するために使用される処理クラスです。このクラスは次のメソッドを定義します-
get_doctest() −指定された文字列からすべてのdoctestの例を抽出し、それらを DocTest オブジェクト。
get_examples(string[, name]) −指定された文字列からすべてのdoctestの例を抽出し、それらをのリストとして返します Exampleオブジェクト。行番号は0から始まります。オプションの引数名は、この文字列を識別する名前であり、エラーメッセージにのみ使用されます。
parse(string[, name]) −与えられた文字列を例と間にあるテキストに分割し、それらを交互のリストとして返します Examplesと文字列。の行番号Examples0ベースです。オプションの引数名は、この文字列を識別する名前であり、エラーメッセージにのみ使用されます。
DocTestRunnerクラス
これは、DocTestでインタラクティブな例を実行および検証するために使用される処理クラスです。以下のメソッドが定義されています-
report_start()
テストランナーが指定された例を処理しようとしていることを報告します。このメソッドは、のサブクラスを許可するために提供されていますDocTestRunner出力をカスタマイズする。直接呼び出すべきではありません
report_success()
与えられた例が正常に実行されたことを報告します。このメソッドは、DocTestRunnerのサブクラスが出力をカスタマイズできるようにするために提供されています。直接呼び出すべきではありません。
report_failure()
与えられた例が失敗したことを報告します。このメソッドは、のサブクラスを許可するために提供されていますDocTestRunner出力をカスタマイズする。直接呼び出すべきではありません。
report_unexpected_exception()
与えられた例が予期しない例外を引き起こしたことを報告してください。このメソッドは、DocTestRunnerのサブクラスが出力をカスタマイズできるようにするために提供されています。直接呼び出すべきではありません。
run(テスト)
test(DocTestオブジェクト)で例を実行し、writer関数outを使用して結果を表示します。
要約([詳細])
このDocTestRunnerによって実行されたすべてのテストケースの要約を出力し、名前付きタプルTestResults(失敗、試行)を返します。オプションのverbose引数は、要約の詳細度を制御します。詳細度が指定されていない場合は、DocTestRunnerの詳細度が使用されます。
OutputCheckerクラス
このクラスは、doctestの例からの実際の出力が期待される出力と一致するかどうかを確認するために使用されます。
このクラスでは、次のメソッドが定義されています-
check_output()
戻る True例からの実際の出力(got)が期待される出力(want)と一致する場合。これらの文字列は、同一である場合は常に一致すると見なされます。ただし、テストランナーが使用しているオプションフラグによっては、いくつかの不正確な一致タイプも考えられます。オプションフラグの詳細については、セクションオプションフラグとディレクティブを参照してください。
output_difference()
特定の例(example)の期待される出力と実際の出力(got)の違いを説明する文字列を返します。
DocTestとUnittestの統合
doctestモジュールは、モジュールとdoctestを含むテキストファイルから単体テストテストスイートを作成するために使用できる2つの関数を提供します。単体テストのテスト検出と統合するには、テストモジュールにload_tests()関数を含めます-
import unittest
import doctest
import doctestexample
def load_tests(loader, tests, ignore):
tests.addTests(doctest.DocTestSuite(doctestexample))
return tests
unittestとdoctestのテストを組み合わせたTestSuiteが形成され、unittestモジュールのmain()メソッドまたはrun()メソッドで実行できるようになります。
以下は、作成するための2つの主な機能です。 unittest.TestSuite doctestsを使用したテキストファイルおよびモジュールからのインスタンス-
doctest.DocFileSuite()
doctestテストを1つ以上のテキストファイルからに変換するために使用されます unittest.TestSuite。返されたunittest.TestSuiteは、unittestフレームワークによって実行され、各ファイルでインタラクティブな例を実行します。ファイル内の例のいずれかが失敗した場合、合成された単体テストは失敗し、failureException テストを含むファイルの名前と(場合によってはおおよその)行番号を示す例外が発生します。
doctest.DocTestSuite()
モジュールのdoctestテストをに変換するために使用されます unittest.TestSuite。
返されたunittest.TestSuiteは、unittestフレームワークによって実行され、モジュール内の各doctestを実行します。doctestのいずれかが失敗した場合、合成された単体テストは失敗し、failureException テストを含むファイルの名前と(場合によってはおおよその)行番号を示す例外が発生します
裏で、DocTestSuite()は unittest.TestSuite doctest.DocTestCaseインスタンスのうち、DocTestCaseはunittest.TestCaseのサブクラスです。
同様に、DocFileSuite()はdoctest.DocFileCaseインスタンスからunittest.TestSuiteを作成し、DocFileCaseはDocTestCaseのサブクラスです。
したがって、unittest.TestSuiteを作成する両方の方法で、DocTestCaseのインスタンスを実行します。doctest関数を自分で実行する場合、オプションフラグをdoctest関数に渡すことにより、使用中のdoctestオプションを直接制御できます。
ただし、unittestフレームワークを作成している場合、unittestは最終的にテストをいつどのように実行するかを制御します。フレームワークの作成者は通常、doctestレポートオプション(たとえば、コマンドラインオプションで指定)を制御したいと考えていますが、unittestを介してdoctestテストランナーにオプションを渡す方法はありません。
ホルガークレケルが彼の名前を変更したのは2004年でした stdパッケージは、Pythonに付属している標準ライブラリの名前と混同されることが多く、(少しだけ紛らわしい)名前「py」になっています。パッケージにはいくつかのサブパッケージが含まれていますが、現在はpy.testフレームワークでほぼ完全に知られています。
py.testフレームワークは、Pythonテストの新しい標準を設定し、今日多くの開発者に非常に人気があります。テスト作成のために導入されたエレガントでPythonicのイディオムにより、テストスイートをはるかにコンパクトなスタイルで作成できるようになりました。
py.testは、Pythonの標準のunittestモジュールに代わるボイラープレートなしのモジュールです。フル機能で拡張可能なテストツールであるにもかかわらず、シンプルな構文を誇っています。テストスイートの作成は、いくつかの関数を備えたモジュールを作成するのと同じくらい簡単です。
py.testは、Pythonバージョン2.6以降のすべてのPOSIXオペレーティングシステムとWINDOWS(XP / 7/8)で実行されます。
インストール
次のコードを使用して、現在のPythonディストリビューションにpytestモジュールとpy.test.exeユーティリティをロードします。テストは両方を使用して実行できます。
pip install pytest
使用法
テストの期待値をアサートするには、assertステートメントを使用するだけです。pytestのassertイントロスペクションは、assert式の中間値をインテリジェントに報告し、の多くの名前を学習する必要から解放します。JUnit legacy methods。
# content of test_sample.py
def func(x):
return x + 1
def test_answer():
assert func(3) == 5
次のコマンドラインを使用して、上記のテストを実行します。テストが実行されると、次の結果がコンソールに表示されます-
C:\Python27>scripts\py.test -v test_sample.py
============================= test session starts =====================
platform win32 -- Python 2.7.9, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 -- C:\Pyth
on27\python.exe
cachedir: .cache
rootdir: C:\Python27, inifile:
collected 1 items
test_sample.py::test_answer FAILED
================================== FAILURES =====================
_________________________________ test_answer _________________________________
def test_answer():
> assert func(3) == 5
E assert 4 == 5
E + where 4 = func(3)
test_sample.py:7: AssertionError
========================== 1 failed in 0.05 seconds ====================
–mスイッチを使用してpytestモジュールを含めることにより、コマンドラインからテストを実行することもできます。
python -m pytest test_sample.py
1つのクラスに複数のテストをグループ化する
いくつかのテストを開始したら、クラスやモジュールでテストを論理的にグループ化することが理にかなっていることがよくあります。2つのテストを含むクラスを書いてみましょう-
class TestClass:
def test_one(self):
x = "this"
assert 'h' in x
def test_two(self):
x = "hello"
assert hasattr(x, 'check')
以下のテスト結果が表示されます-
C:\Python27>scripts\py.test -v test_class.py
============================= test session starts =====================
platform win32 -- Python 2.7.9, pytest-2.9.1, py-1.4.31, pluggy-0.3.1 -- C:\Pyt
on27\python.exe
cachedir: .cache
rootdir: C:\Python27, inifile:
collected 2 items
test_class.py::TestClass::test_one PASSED
test_class.py::TestClass::test_two FAILED
================================== FAILURES =====================
_____________________________ TestClass.test_two ______________________________
self = <test_class.TestClass instance at 0x01309DA0>
def test_two(self):
x = "hello"
> assert hasattr(x, 'check')
E assert hasattr('hello', 'check')
test_class.py:7: AssertionError
===================== 1 failed, 1 passed in 0.06 seconds ======================
ノーズプロジェクトは翌年の2005年にリリースされました py.testその現代的な装いを受け取りました。これは、py.testによって開拓されたものと同じテストイディオムをサポートするためにJason Pellerinによって作成されましたが、インストールと保守がより簡単なパッケージになっています。
ザ・ nose モジュールはpipユーティリティを使用してインストールできます
pip install nose
これにより、現在のPythonディストリビューションとnosetest.exeにnoseモジュールがインストールされます。つまり、このユーティリティと–mスイッチを使用してテストを実行できます。
C:\python>nosetests –v test_sample.py
Or
C:\python>python –m nose test_sample.py
nose からテストを収集します unittest.TestCaseもちろん、サブクラス。単純なテスト関数や、unittest.TestCaseのサブクラスではないテストクラスを作成することもできます。noseは、時限テストの作成、例外のテスト、およびその他の一般的な使用例に役立つ多くの関数も提供します。
noseテストを自動的に収集します。テストケースを手動でテストスイートに収集する必要はありません。テストの実行はレスポンシブです。nose 最初のテストモジュールがロードされるとすぐにテストの実行を開始します。
unittestモジュールと同様に、 nose パッケージ、モジュール、クラス、およびテストケースレベルでフィクスチャをサポートするため、コストのかかる初期化を可能な限り頻繁に実行できません。
基本的な使用法
以前に使用したスクリプトと同様のnosetest.pyを考えてみましょう-
# content of nosetest.py
def func(x):
return x + 1
def test_answer():
assert func(3) == 5
上記のテストを実行するには、次のコマンドライン構文を使用します-
C:\python>nosetests –v nosetest.py
コンソールに表示される出力は次のようになります-
nosetest.test_answer ... FAIL
================================================================
FAIL: nosetest.test_answer
----------------------------------------------------------------------
Traceback (most recent call last):
File "C:\Python34\lib\site-packages\nose\case.py", line 198, in runTest
self.test(*self.arg)
File "C:\Python34\nosetest.py", line 6, in test_answer
assert func(3) == 5
AssertionError
----------------------------------------------------------------------
Ran 1 test in 0.000s
FAILED (failures = 1)
nose を使用してDocTestと統合できます with-doctest boveコマンドラインのオプション。
\nosetests --with-doctest -v nosetest.py
あなたは使用することができます nose テストスクリプトで-
import nose
nose.main()
テストスクリプトを成功時に0、失敗時に1で終了させたくない場合は(unittest.mainのように)、代わりにnose.run()を使用します-
import nose
result = nose.run()
結果は、テストの実行が成功した場合はtrueになり、失敗した場合やキャッチされなかった例外が発生した場合はfalseになります。
noseパッケージ、モジュール、クラス、およびテストレベルでフィクスチャ(セットアップおよびティアダウンメソッド)をサポートします。py.testまたはunittestフィクスチャと同様に、セットアップは常にテスト(またはテストパッケージとモジュールのテストのコレクション)の前に実行されます。テスト実行のステータスに関係なく、セットアップが正常に完了すると、ティアダウンが実行されます。
nose.toolsモジュールは、テストの実行時間を制限したり、例外をテストしたりするためのデコレータや、unittest.TestCaseにあるすべての同じassertXメソッドなど、役立つと思われる多くのテスト支援機能を提供します。
nose.tools.ok_(expr, msg = None) −アサートの省略形。
nose.tools.eq_(a, b, msg = None) −'assert a == b、“%r!=%r”%(a、b)の省略形
nose.tools.make_decorator(func) −鼻の追加のもの(つまり、セットアップと分解)を含む、装飾された関数のメタデータを適切に複製するように、テストデコレータをラップします。
nose.tools.raises(*exceptions) −テストに合格するには、予想される例外の1つを発生させる必要があります。
nose.tools.timed(limit) −合格するには、指定された制限時間内にテストを終了する必要があります
nose.tools.istest(func) −関数またはメソッドをテストとしてマークするデコレータ
nose.tools.nottest(func) −関数またはメソッドをテストではないものとしてマークするデコレータ
パラメータ化されたテスト
Pythonのテストフレームワークであるunittestには、パラメーター化されたテストケースを実行する簡単な方法がありません。言い換えれば、引数を簡単に渡すことはできませんunittest.TestCase 外から。
ただし、pytestモジュールポートは、いくつかの十分に統合された方法でパラメーター化をテストします。
pytest.fixture() フィクスチャ機能のレベルでパラメータ化を定義できます。
@pytest.mark.parametrize関数またはクラスレベルでパラメータ化を定義できます。特定のテスト関数またはクラスに複数の引数/フィクスチャセットを提供します。
pytest_generate_tests 独自のカスタム動的パラメーター化スキームまたは拡張機能の実装を可能にします。
サードパーティのモジュール「nose-parameterized」を使用すると、Pythonテストフレームワークを使用したパラメータ化されたテストが可能になります。このリンクからダウンロードできます-https://github.com/wolever/nose-parameterized