Unittest-framework-quick-guide

提供:Dev Guides
移動先:案内検索

UnitTestフレームワーク-概要

ユニットテストは、機能、メソッド、クラスなどのソースコードの個々のユニットをテストして、それらが使用に適しているかどうかを判断するソフトウェアテスト方法です。 直感的には、ユニットをアプリケーションのテスト可能な最小の部分と見なすことができます。 ユニットテストは、開発プロセス中にプログラマーによって作成された短いコードフラグメントです。 コンポーネントテストの基礎を形成します。

ユニットテストは、次の2つの方法で行うことができます-

Manual Testing Automated Testing

Executing the test cases manually without any tool support is known as manual testing.

  • テストケースは人的資源によって実行されるため、非常に*時間がかかり、退屈です*。
  • テストケースは手動で実行する必要があるため、手動テストではより多くのテスターが必要です。
  • 人的エラーのために毎回テストが正確に実行されない可能性があるため、信頼性が低くなります。
  • 隠された情報を取得する高度なテストを作成するためのプログラミングはできません。

a

自動化ツールを使用してツールサポートを取得し、テストケースを実行することを自動化テストと呼びます。

  • Fast Automationは、テストケースを人事よりも大幅に高速に実行します。 * 自動化ツールを使用してテストケースが実行されるため、人的資源への投資は少なくなります。 * 自動化テストは、実行されるたびにまったく同じ操作を実行し、より信頼性が高い。 * テスターは*高度なテスト*をプログラムして、隠れた情報を引き出すことができます。

JUnitは、Javaプログラミング言語の単体テストフレームワークです。 JUnitはテスト駆動開発の開発において重要であり、JUnitを起源とするxUnitとして総称されるユニットテストフレームワークのファミリーの1つです。 ここでlink:/junit/index [JUnitチュートリアル]を見つけることができます。

「PyUnit」とも呼ばれるPythonユニットテストフレームワークは、Kent BeckとErich Gammaによって開発されたJUnitのPython言語バージョンです。 PyUnitは、Pythonバージョン2.1の時点でPython標準ライブラリの一部を形成しています。

Pythonユニットテストフレームワークは、テストの自動化、テストのセットアップおよびシャットダウンコードの共有、テストのコレクションへの集約、レポートフレームワークからのテストの独立性をサポートします。 unittestモジュールは、一連のテストでこれらの品質を簡単にサポートできるクラスを提供します。

このチュートリアルは、初心者がPythonテストフレームワークの基本機能を理解できるように準備されています。 このチュートリアルを完了すると、Pythonテストフレームワークの使用に関する中程度の専門知識が得られ、次のレベルに進むことができます。

Python言語を使用したソフトウェア開発の合理的な専門知識が必要です。 リンク:/python/index [Python tutorial]は、Pythonの学習を始めるのに最適な場所です。 ソフトウェアテストの基礎知識も必要です。

環境設定

テストの記述に必要なクラスは、「unittest」モジュールにあります。 古いバージョンのPython(Python 2.1より前)を使用している場合、モジュールはhttp://pyunit.sourceforge.net/からダウンロードできます。 ただし、unittestモジュールは標準のPythonディストリビューションの一部になりました。したがって、個別にインストールする必要はありません。

UnitTest Framework-フレームワーク

'unittest’は、テストの自動化、テストのセットアップおよびシャットダウンコードの共有、コレクションへのテストの集約、レポートフレームワークからのテストの独立性をサポートします。

unittestモジュールは、一連のテストでこれらの品質を簡単にサポートできるクラスを提供します。

これを達成するために、unittestは次の重要な概念をサポートしています-

  • テストフィクスチャー-これは、1つ以上のテストを実行するために必要な準備、および関連するクリーンアップアクションを表します。 これには、たとえば、一時データベースまたはプロキシデータベース、ディレクトリの作成、サーバープロセスの開始などが含まれます。
  • テストケース-これはテストの最小単位です。 これにより、特定の入力セットに対する特定の応答がチェックされます。 unittestは、新しいテストケースを作成するために使用できる基本クラス TestCase を提供します。
  • テストスイート-これは、テストケース、テストスイート、またはその両方のコレクションです。 これは、一緒に実行する必要があるテストを集約するために使用されます。 テストスイートはTestSuiteクラスによって実装されます。
  • テストランナー-これは、テストの実行を調整し、ユーザーに結果を提供するコンポーネントです。 ランナーは、グラフィカルインターフェイス、テキストインターフェイスを使用するか、テストの実行結果を示す特別な値を返す場合があります。

単体テストの作成

次の手順は、単純な単体テストの作成に関係しています-

  • ステップ1 *-プログラムにunittestモジュールをインポートします。
  • ステップ2 *-テストする関数を定義します。 次の例では、add()関数がテストの対象となります。
  • ステップ3 *-unittest.TestCaseをサブクラス化してテストケースを作成します。
  • ステップ4 *-クラス内のメソッドとしてテストを定義します。 メソッドの名前は「test」で始まる必要があります。
  • ステップ5 *-各テストはTestCaseクラスのassert関数を呼び出します。 アサートには多くの種類があります。 次の例では、assertEquals()関数を呼び出します。
  • ステップ6 *-assertEquals()関数は、add()関数の結果をarg2引数と比較し、比較が失敗した場合にassertionErrorをスローします。
  • ステップ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()
  • ステップ8 *-コマンドラインから上記のスクリプトを実行します。
C:\Python27>python SimpleTest.py
.
----------------------------------------------------------------------
Ran 1 test in 0.000s
OK
  • ステップ9 *-次の3つは、テストの結果の可能性があります-
Sr.No Message & Description
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
Sr.No Option & Description
1

-h, --help

このメッセージを表示

2

v, --verbose

詳細な出力

3

-q, --quiet

最小限の出力

4

-f, --failfast

最初の失敗で停​​止

5

-c, --catch

control-Cをキャッチして結果を表示する

6

-b, --buffer

テスト実行中の標準出力と標準エラーのバッファ

UnitTest Framework-API

この章では、unittestモジュールで定義されているクラスとメソッドについて説明します。 このモジュールには5つの主要なクラスがあります。

TestCaseクラス

このクラスのオブジェクトは、テスト可能な最小単位を表します。 テストルーチンを保持し、各ルーチンの準備とその後のクリーンアップのためのフックを提供します。

次のメソッドはTestCaseクラスで定義されています-

Sr.No. Method & Description
1

setUp()

テストフィクスチャを準備するために呼び出されるメソッド。 これは、テストメソッドを呼び出す直前に呼び出されます

2

tearDown()

テストメソッドが呼び出され、結果が記録された直後に呼び出されるメソッド。 これは、テストメソッドが例外を発生させた場合でも呼び出されます。

3

setUpClass()

個々のクラスのテストの前に呼び出されるクラスメソッド。

4

tearDownClass()

個々のクラスのテストが実行された後に呼び出されるクラスメソッド。

5

run(result = None)

テストを実行し、_result_として渡されたテスト結果オブジェクトに結果を収集します。

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クラスによって使用可能になります。

次の手順は、テストスイートの作成と実行に関係しています。

  • ステップ1 *-TestSuiteクラスのインスタンスを作成します。
suite = unittest.TestSuite()
  • ステップ2 *-スイートのTestCaseクラス内にテストを追加します。
suite.addTest(testcase class)
  • ステップ3 *-makeSuite()メソッドを使用してクラスからテストを追加することもできます
suite = unittest.makeSuite(test case class)
  • ステップ4 *-個々のテストをスイートに追加することもできます。
suite.addTest(testcaseclass(""testmethod")
  • ステップ5 *-TestTestRunnerクラスのオブジェクトを作成します。
runner = unittest.TextTestRunner()
  • ステップ6 *-run()メソッドを呼び出して、スイート内のすべてのテストを実行します
runner.run (suite)

次のメソッドはTestSuiteクラスで定義されています-

Sr.No. Method & Description
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クラスのメソッドのリストを示しています-

Sr.No Method & Description
1

loadTestsFromTestCase()

TestCaseクラスに含まれるすべてのテストケースのスイートを返します

2

loadTestsFromModule()

指定されたモジュールに含まれるすべてのテストケースのスイートを返します。

3

loadTestsFromName()

文字列指定子を指定して、すべてのテストケースのスイートを返します。

4

discover()

指定された開始ディレクトリからサブディレクトリに再帰してすべてのテストモジュールを検索し、TestSuiteオブジェクトを返します。

TestResultクラス

このクラスは、成功したテストと失敗したテストに関する情報をコンパイルするために使用されます。 TestResultオブジェクトには、一連のテストの結果が格納されます。 TestRunnerインスタンスはTestRunner.run()メソッドによって返されます。

TestResultインスタンスには次の属性があります-

Sr.No. Attribute & Description
1

Errors

2組のTestCaseインスタンスとフォーマットされたトレースバックを保持する文字列を含むリスト。 各タプルは、予期しない例外を発生させたテストを表します。

2

Failures

2組のTestCaseインスタンスとフォーマットされたトレースバックを保持する文字列を含むリスト。 各タプルは、TestCase.assert *()メソッドを使用して障害が明示的に通知されたテストを表します。

3

Skipped

2組のTestCaseインスタンスと、テストをスキップする理由を保持する文字列を含むリスト。

4

wasSuccessful()

これまでに実行されたすべてのテストに合格した場合はTrueを返し、そうでない場合はFalseを返します。

5

stop()

このメソッドを呼び出して、実行中のテストセットを中止する必要があることを通知できます。

6

startTestRun()

テストが実行される前に1回呼び出されます。

7

stopTestRun()

すべてのテストが実行された後に1回呼び出されます。

8

testsRun

これまでに実行されたテストの総数。

9

Buffer

trueに設定すると、 sys.stdoutsys.stderr は、https://docs.python.org/2/library/unittestl#unittest.TestResult.startTest [startTest()]とhttpsの間にバッファリングされます。//docs.python.org/2/library/unittestl#unittest.TestResult.stopTest [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

UnitTest Framework-アサーション

Pythonテストフレームワークは、特定の条件をテストするPythonの組み込みのassert()関数を使用します。 アサーションが失敗すると、AssertionErrorが発生します。 テストフレームワークは、テストを失敗として識別します。 他の例外はエラーとして扱われます。

次の3セットのアサーション関数は、unittestモジュールで定義されています-

  • 基本的なブールアサート
  • 比較アサート
  • コレクションのアサート

基本的なアサート関数は、操作の結果がTrueまたはFalseであるかどうかを評価します。 すべてのassertメソッドは、指定されている場合、失敗時のエラーメッセージとして使用される msg 引数を受け入れます。

Sr.No. Method & Description
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であることをテストします。 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番目のセットは*比較アサーション-*です

  • assertAlmostEqual (最初、2番目、場所= 7、メッセージ=なし、デルタ=なし) + _first_と_second_がほぼ等しい(またはほぼ等しくない)ことを、差を計算し、指定された10進数_places_の数(デフォルトは7)に丸めてテストします。
  • assertNotAlmostEqual (first、second、places、msg、delta) +差を計算し、指定された小数点以下の桁数(デフォルトは7)に丸め、ゼロと比較して、1番目と2番目がほぼ等しくないことをテストします。 +上記の両方の機能で、場所の代わりにデルタが指定されている場合、1番目と2番目の差はデルタ以下でなければなりません。 +デルタと場所の両方を指定すると、TypeErrorが発生します。
  • assertGreater (最初、2番目、msg =なし) +メソッド名に応じて、_first_が_second_より大きいことをテストします。 そうでない場合、テストは失敗します。
  • assertGreaterEqual (最初、2番目、msg =なし) +メソッド名に応じて、_first_が_second_以上であることをテストします。 そうでない場合、テストは失敗します
  • assertLess (最初、2番目、msg =なし) +メソッド名に応じて、_first_が_second_より小さいことをテストします。 そうでない場合、テストは失敗します
  • assertLessEqual (最初、2番目、msg =なし) +メソッド名に応じて、_first_が_second_以下であることをテストします。 そうでない場合、テストは失敗します。
  • assertRegexpMatches (text、regexp、msg =なし) +正規表現検索がテキストと一致することをテストします。 失敗した場合、エラーメッセージにはパターンとテキストが含まれます。 regexpは、* re.search()*による使用に適した正規表現オブジェクトまたは正規表現を含む文字列です。
  • assertNotRegexpMatches (text、regexp、msg =なし) + _regexp_検索が_text_と一致しないことを確認します。 パターンと一致する_text_の部分を含むエラーメッセージで失敗します。 _regexp_は、正規表現オブジェクトまたはhttps://docs.python.org/2/library/rel#re.search [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)

コレクションのアサート

このアサート関数のセットは、List、Tuple、Dictionary、SetなどのPythonのコレクションデータ型で使用するためのものです。

Sr.No. Method & Description
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)

UnitTest Framework-テスト検出

TestLoaderクラスにはdiscover()関数があります。 Pythonテストフレームワークは、これを使用して簡単なテスト検出を行います。 互換性を保つには、テストを含むモジュールとパッケージを最上位ディレクトリからインポートできる必要があります。

以下は、テスト検出の基本的なコマンドラインの使用法です-

Python –m unittest discover

インタープリターは、テストを含むすべてのモジュールを現在のディレクトリと内部ディレクトリから再帰的にロードしようとします。 他のコマンドラインオプションは-

Sr.No. Options & Description
1

-v, --verbose

詳細な出力

2

-s, --start-directory

ディレクトリディスカバリを開始するディレクトリ(。 デフォルト)

3

-p, --pattern

patternテストファイルに一致するパターン(test *.pyデフォルト)

4
  • -t, --top-level-directory*

ディレクトリプロジェクトの最上位ディレクトリ(デフォルトは開始ディレクトリ)

たとえば、「tests」ディレクトリで「assert」で始まる名前のモジュールでテストを検出するには、次のコマンドラインが使用されます-

C:\python27>python –m unittest –v –s "c:\test" –p "assert*.py"

テスト検出では、テストをインポートしてロードします。 テスト検出により、指定した開始ディレクトリからすべてのテストファイルが検出されると、インポートするパッケージ名にパスが変換されます。

ディレクトリへのパスではなくパッケージ名として開始ディレクトリを指定すると、discoverはインポート元の場所が意図した場所であると想定するため、警告は表示されません。

UnitTest Framework-テストをスキップ

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)

次のデコレータは、テストのスキップと予期される失敗を実装します-

S.No. Method & Description
1

unittest.skip(reason)

装飾されたテストを無条件にスキップします。 _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が真ですが、2番目のケースでは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)

UnitTest Framework-例外テスト

Pythonテストフレームワークは、例外が発生したことを確認するために次のアサーションメソッドを提供します。

assertRaises(例外、呼び出し可能、* 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_が一致することをテストします。 regexpは、正規表現オブジェクト、またはre.search()による使用に適した正規表現を含む文字列です。

次の例は、assertRaisesRegexp()の使用方法を示しています-

import unittest
import re

class raiseTest(unittest.TestCase):
   def testraiseRegex(self):
      self.assertRaisesRegexp(TypeError, "invalid", reg,"Point","finddevguides")

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","finddevguides")
AssertionError: TypeError not raised
----------------------------------------------------------------------

ただし、変更は次のようになります-

self.assertRaisesRegexp(TypeError, "invalid", reg,123,"finddevguides")

TypeError例外がスローされます。 したがって、次の結果が表示されます-

================================================================
FAIL: testraiseRegex (__main__.raiseTest)
----------------------------------------------------------------------
Traceback (most recent call last):
   File "raisetest.py", line 11, in testraiseRegex
      self.assertRaisesRegexp(TypeError, "invalid", reg,123,"finddevguides")
AssertionError: "invalid" does not match
   "first argument must be string or compiled pattern"
----------------------------------------------------------------------

UnitTest Framework-タイムテスト

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()

UnitTestフレームワーク-Unittest2

unittest2は、Python 2.7以降のPythonテストフレームワークに追加された追加機能のバックポートです。 Python 2.6、2.7、および3. *での実行がテストされています。 最新バージョンはhttps://pypi.python.org/pypi/unittest2からダウンロードできます

unittestの代わりにunittest2を使用するには、import unittestをimport unittest2に置き換えるだけです。

unittest2のクラスはunittestの適切なクラスから派生するため、すべてのテストをすぐにunittest2の使用に切り替えることなく、unittest2テスト実行インフラストラクチャを使用できるようにする必要があります。 新しい機能を実装する場合は、unittest.TestCaseの代わりに unittest2.TestCase からテストケースをサブクラス化します

以下はunittest2の新機能です-

  • リソース管理を改善するための addCleanups
  • 多くの新しいアサートメソッドが含まれています
  • コンテキストマネージャーとしての assertRaises 、その後の例外へのアクセス
  • setUpModuletearDownModule などのモジュールレベルのフィクスチャがあります
  • モジュールまたはパッケージからテストをロードするための load_tests プロトコルが含まれています
  • TestResultの startTestRun および stopTestRun メソッド

Python 2.7では、 python -m unittest <args> を使用して、unittestコマンドライン機能(テスト検出を含む)を呼び出します。

代わりに、unittest2にはスクリプトunit2が付属しています。

unit2 discover
unit2 -v test_module

UnitTestフレームワーク-信号処理

テスト実行中のcontrol-Cのより効率的な処理は、 catchbreak パラメーターとともに、unittestの-c/-catchコマンドラインオプションによって提供されます。 キャッチブレーク動作を有効にすると、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)

control-c処理のために TestResult オブジェクトを登録します。 結果を登録すると、それに対する弱い参照が格納されるため、結果がガベージコレクションされるのを防ぐことはできません。

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ツールキットに基づくユーティリティも利用できます。

UnitTest Framework-Doctest

Pythonの標準ディストリビューションには「Doctest」モジュールが含まれています。 このモジュールの機能により、インタラクティブなPythonセッションのように見えるテキストを検索し、これらのセッションを実行して、表示どおりに機能するかどうかを確認できます。

Doctestは、次のシナリオで非常に役立ちます-

  • モジュールのドキュメント文字列が最新であることを確認するには、すべてのインタラクティブな例がドキュメントどおりに機能することを確認します。
  • テストファイルまたはテストオブジェクトからの対話型の例が期待どおりに機能することを確認して、回帰テストを実行します。
  • パッケージのチュートリアルドキュメントを書くために、入出力の例で自由に説明します

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>を入れます。

UnitTest Framework-Doctest API

doctest APIは、docstringsからインタラクティブな例を保存するために使用される次の2つのコンテナクラスを中心に展開します-

  • -期待される出力とペアになった単一の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()メソッドを定義します。 object’s docstring、またはそれに含まれるオブジェクトのdocstringで定義されたDocTestのリストを返します。

DocTestParserクラス

文字列からインタラクティブな例を抽出し、それらを使用してDocTestオブジェクトを作成するために使用される処理クラスです。 このクラスは、次のメソッドを定義します-

  • * get_doctest()-指定された文字列からすべてのdoctestの例を抽出し、それらを *DocTest オブジェクトに収集します。
  • * get_examples(string [、name])-指定された文字列からすべてのdoctestの例を抽出し、それらを *Example オブジェクトのリストとして返します。 行番号は0から始まります。 オプションの引数名は、この文字列を識別する名前であり、エラーメッセージにのみ使用されます。
  • * parse(string [、name])*-指定された文字列を例と介入テキストに分割し、それらを*例*と文字列が交互に並んだリストとして返します。 *例*の行番号は0から始まります。 オプションの引数名は、この文字列を識別する名前であり、エラーメッセージにのみ使用されます。

DocTestRunnerクラス

これは、DocTestのインタラクティブな例を実行および検証するために使用される処理クラスです。 次のメソッドが定義されています-

report_start()

テストランナーが特定の例を処理しようとしていることを報告します。 このメソッドは、 DocTestRunner のサブクラスが出力をカスタマイズできるようにするために提供されています。直接呼び出さないでください

report_success()

指定された例が正常に実行されたことを報告します。 このメソッドは、DocTestRunnerのサブクラスが出力をカスタマイズできるようにするために提供されています。直接呼び出さないでください。

report_failure()

指定された例が失敗したことを報告します。 このメソッドは、 DocTestRunner のサブクラスが出力をカスタマイズできるようにするために提供されています。直接呼び出さないでください。

report_unexpected_exception()

指定された例で予期しない例外が発生したことを報告します。 このメソッドは、https://docs.python.org/2/library/doctestl#doctest.DocTestRunner [DocTestRunner]のサブクラスが出力をカスタマイズできるようにするために提供されています。直接呼び出すことはできません。

実行(テスト)

test(DocTestオブジェクト)の例を実行し、ライター関数_out_を使用して結果を表示します。

サマリ([詳細])

このDocTestRunnerによって実行されたすべてのテストケースの概要を出力し、named tuple TestResults(failed、attempted)を返します。 オプションの_verbose_引数は、要約の詳細度を制御します。 冗長性が指定されていない場合、DocTestRunnerの冗長性が使用されます。

OutputCheckerクラス

このクラスは、doctestの例からの実際の出力が期待される出力と一致するかどうかを確認するために使用されます。

次のメソッドは、このクラスで定義されています-

check_output()

例からの実際の出力(got)が期待される出力(want)と一致する場合、 True を返します。 これらの文字列は、同一の場合、常に一致すると見なされます。ただし、テストランナーが使用しているオプションフラグによっては、いくつかの非完全一致タイプも可能です。 オプションフラグの詳細については、セクション_Option Flags_および_Directives_を参照してください。

output_difference()

指定された例(example)の期待される出力と実際の出力(got)の違いを説明する文字列を返します。

UnittestとDocTestの統合

doctestモジュールは、doctestを含むモジュールおよびテキストファイルからユニットテストテストスイートを作成するために使用できる2つの関数を提供します。 unittestテスト検出と統合するには、テストモジュールに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()メソッドによって実行できるようになりました。

以下は、doctestを使用してテキストファイルとモジュールから unittest.TestSuite インスタンスを作成するための2つの主な機能です-

doctest.DocFileSuite()

doctestテストを1つ以上のテキストファイルから unittest.TestSuite に変換するために使用されます。 返されるunittest.TestSuiteは、unittestフレームワークによって実行され、各ファイルでインタラクティブな例を実行します。 ファイルの例のいずれかが失敗すると、合成された単体テストは失敗し、テストと(場合によっては)行番号を含むファイルの名前を示す failureException 例外が発生します。

doctest.DocTestSuite()

モジュールのdoctestテストを unittest.TestSuite に変換するために使用されます。

返されるunittest.TestSuiteは、unittestフレームワークによって実行され、モジュール内の各doctestを実行します。 doctestのいずれかが失敗すると、合成された単体テストは失敗し、テストと(場合によっては)行番号を含むファイルの名前を示す failureException 例外が発生します

カバーの下で、DocTestSuite()はdoctest.DocTestCaseインスタンスから unittest.TestSuite を作成し、DocTestCaseはunittest.TestCaseのサブクラスです。

同様に、DocFileSuite()はdoctest.DocFileCaseインスタンスからunittest.TestSuiteを作成し、DocFileCaseはDocTestCaseのサブクラスです。

そのため、unittest.TestSuiteを作成する両方の方法でDocTestCaseのインスタンスが実行されます。 doctest関数を自分で実行する場合、オプションフラグをdoctest関数に渡すことにより、使用中のdoctestオプションを直接制御できます。

ただし、ユニットテストフレームワークを記述している場合、ユニットテストは最終的にテストをいつどのように実行するかを制御します。 通常、フレームワークの作成者はdoctestレポートオプション(たとえば、コマンドラインオプションで指定される)を制御したいと考えていますが、unittestを介してdoctestテストランナーにオプションを渡す方法はありません。

UnitTest Framework-Py.testモジュール

2004年にHolger Krekelが std パッケージの名前を変更しました。このパッケージの名前は、Pythonに同梱されている標準ライブラリの名前とよく混同されますが、(少しだけ混同が少ない)名前を「py」に変更しました。パッケージにはいくつかのサブパッケージが含まれていますが、現在はほぼ完全にpy.testフレームワークで知られています。

py.testフレームワークはPythonテストの新しい標準を設定し、今日多くの開発者に非常に人気があります。 テスト作成のために導入されたエレガントでPythonicのイディオムにより、テストスイートをはるかにコンパクトなスタイルで作成できるようになりました。

py.testは、Pythonの標準のunittestモジュールの定型的な代替手段です。 完全に機能する拡張可能なテストツールであるにもかかわらず、シンプルな構文を誇っています。 テストスイートの作成は、いくつかの機能を持つモジュールを作成するのと同じくらい簡単です。

py.testは、すべてのPOSIXオペレーティングシステムおよびPythonバージョン2.6以降を搭載したWINDOWS(XP/7/8)で実行されます。

インストール

次のコードを使用して、py.test.exeユーティリティと同様に、現在のPythonディストリビューションにpytestモジュールをロードします。 テストは両方を使用して実行できます。

pip install pytest

使用法

assertステートメントを使用して、テストの期待値をアサートできます。 pytestのassertイントロスペクションは、assert式の中間値をインテリジェントに報告するため、* JUnitレガシーメソッド*の多くの名前を学ぶ必要がなくなります。

# 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

クラス内の複数のテストのグループ化

一度に数個以上のテストを開始したら、クラスとモジュールでテストを論理的にグループ化することが理にかなっています。 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 ======================

鼻のテスト-フレームワーク

noseプロジェクトは、 py.test が最新の装いを受け取った翌年の2005年にリリースされました。 Jason Pellerinによって書かれたもので、py.testによって開拓されたのと同じテストイディオムをサポートしますが、インストールと保守が簡単なパッケージです。

*nose* モジュールは、pipユーティリティを使用してインストールできます。
pip install nose

これにより、noseモジュールが現在のPythonディストリビューションとnosetest.exeにインストールされます。つまり、このユーティリティと–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* は、上記のコマンドラインで *with-doctest* オプションを使用してDocTestと統合できます。
\nosetests --with-doctest -v nosetest.py

テストスクリプトで nose を使用できます-

import nose
nose.main()

あなたが(unittest.mainのように)成功時に0で、終了時に1でテストスクリプトを終了したくない場合は、代わりに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