##
5.4.1 `test`パッケージのためのユニットテストを書く

`test` パッケージ用のテストを書く場合、`unittest` モジュールを使い、以下のいくつかのガイドラインに従うよう推奨します。 一つは、テストモジュールの名前と同様、すべてのテストメソッドの 名前を"`'test_'`"で始めることです。これはテスト駆動プログラムに そのメソッドをテストメソッドとして認識させるためです。 また、テストメソッドにはドキュメンテーション文字列を入れるべきでは ありません。 テストメソッドのドキュメント記述には、 ("`# True あるいは False だけを返すテスト関数`" のような) コメントを使ってください。 これは、ドキュメンテーション文字列が存在する場合にはその内容が出力 されるため、どのテストを実行しているのかをいちいち表示しなくするためです。

以下のような基本的な決まり文句を使います:

    import unittest
    from test import test_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():
        test_support.run_unittest(MyTestCase1,
                                  MyTestCase2,
                                  ... list other tests ...
                                 )

    if __name__ == '__main__':
        test_main()

この定型的なコードによって、テストスイートを`regrtest.py` から起動できると同時に、スクリプト自体からも実行できるようになります。

回帰テストの目的はコードの分解です。 そのためには以下のいくつかのガイドラインに従ってください:

- テストスイートはすべてのクラス、関数および定数を用いるべきです。 これは外部に公開される外部APIだけでなく"非公開"コードも含んでいます。
- ホワイトボックス・テスト (テストを書くときに対象のコードをすぐ テストする) を推奨します。ブラックボックス・テスト (最終的に公開された ユーザーインターフェイスだけをテストする) は、すべての境界条件と 極端条件を確実にテストするには完全ではありません。
- 無効な値を含み、すべての取りうる値を確実にテストするように してください。そうすることで、全ての有効な値を受理するだけでなく、 不適切な値を正しく処理することも確認できます。
- できる限り多くのコード経路を網羅してください。分岐が生じる テストし、入力を調整して、コードの全体に渡って取りえる限りの個々の 処理経路を確実にたどらせるようにしてください。
- テスト対象のコードにどんなバグが発見された場合でも、明示的な テスト追加するようにしてください。そうすることで、将来コードを変更した 際にエラーが再発しないようにできます。
- (一時ファイルをすべて閉じたり削除したりするといった) テストの 後始末を必ず行ってください。
- import するモジュールをできるかぎり少なくし、可能な限り 早期に import を行ってください。そうすることで、てテストの外部依存性を 最小限にし、モジュールの import による副作用から生じる変則的な動作を 最小限にできます。
- コードの再利用を最大限に行うようにしてください。時として、 テストの多様性はどんな型の入力を受け取るかの違いまで小さくなります。 例えば以下のように、入力が指定されたサブクラスで基底テストクラスを サブクラス化して、コードの複製を最小化します:

      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)

参考資料:

Test Driven Development
  コードより前にテストを書く 方法論に関する Kent Beck の著書