[Python] unittestモジュールでテストスイートを実現する2つの方法
こんにちは、絶賛Pythonコーディング中の@yoheiMuneです。
今日は前回の「ユニットテストをPythonで書く」からの続きで、unittestモジュールを用いたテストスイートのやり方をブログに書きたいと思います。
前回のブログから引き続きunittestモジュールを用いたテストについて書きたいと思います。unittestモジュールでは、大きく2つの方法でテストスイートを作成することができます。それぞれ見ていきたいと思います。
そしてそれを行うために
これの実行は以下のように行います。
また上記と同じ内容について、コマンドのみでも実行することができます。
あと、discoverされたクラスですが、import地点はdiscoverしているところ(今回だとdiscover.pyのところ)が起点となります。例えば以下の場合には、
- 26.4. unittest — ユニットテストフレームワーク — Python 3.5.2 ドキュメント
- unit testing - Trying to implement python TestSuite - Stack Overflow
- how to run all Python unit tests in a directory - Stack Overflow
最後になりますが本ブログでは、Python・フロントエンド・開発関連・Swift・Linux・Java・機械学習など雑多に情報発信をしていきます。自分の第2の脳にすべく、情報をブログに貯めています。気になった方は、本ブログのRSSやTwitterをフォローして頂けると幸いです ^ ^。
最後までご覧頂きましてありがとうございました!
今日は前回の「ユニットテストをPythonで書く」からの続きで、unittestモジュールを用いたテストスイートのやり方をブログに書きたいと思います。
目次
テストスイートとは
テストスイートとは、複数のテストクラス(やテストスイート)をまとめたもので、まとめたものを一気にテストできる仕組みです。実務でテストをする場合には、機能別にテストを書くことが多く、それらをまとめるためにテストスイートを利用します。ちなみに僕は最初の方では1つのテストクラスに全てのテストケースを書いていましたが、それはなかなか大変でした(行数が多くて見つけづらいし、テストのスキップもしづらい)。前回のブログから引き続きunittestモジュールを用いたテストについて書きたいと思います。unittestモジュールでは、大きく2つの方法でテストスイートを作成することができます。それぞれ見ていきたいと思います。
手動でテストスイートを作成する
まずは自分でテストスイートを作る方法です。以下のように複数のテストクラスがあるとします。. ├── suite.py : テストスイートを定義して実行するクラス(起点となるクラス) ├── test.py : とあるテストクラス1 └── other.py : とあるテストクラス2テストスイートとして読み込む
test.py
とother.py
は、以下のような普通のテストクラスです。test.py
import unittest class MyTest(unittest.TestCase): def test_mytest_01(self): print("test_mytest_01 is called") one = 1 self.assertEqual(one, 1, "one is 1")
other.py
import unittest class OtherTest(unittest.TestCase): def test_other_01(self): print("test_other_01 is called") two = 2 self.assertEqual(two, 2, "two is 2")そして上記2つのテストケースを、
suite.py
では手動でテストスイートとしてまとめます。以下のようにすることでテストスイートを定義できます。suite.py
import unittest # テストケースのクラスをそれぞれ読み込む import test import other # テストスイートを作成して返却します def suite(): # テストスイートを定義します test_suite = unittest.TestSuite() # addTestを用いてテストスイートに追加していきます test_suite.addTest(unittest.makeSuite(test.MyTest)) test_suite.addTest(unittest.makeSuite(other.OtherTest)) return test_suite if __name__ == "__main__": # 作成したテストスイートを呼び出して、TextTestRunnerで実行します mySuite = suite() unittest.TextTestRunner().run(mySuite)そして実行は以下のように、普通な感じに行うことができます。
$ python3 suite.py test_mytest_01 is called .test_other_01 is called . ------------------------- Ran 2 tests in 0.000s OK以上のように、
TestSuite
やaddTest
でテストスイートを作成し、TextTestRunner
で実行することで、手動でテストスイートの作成&実行を行うことができます。自動的にテストスイートを作成する
unittestモジュールの強力な機能の一つで、discover
を用いることで自動的にテストクラスを見つけてきてくれて、それをテストスイートとして作成してくれるものがあります。今回は以下のようなディレクトリ構成としましょう。. ├── discover.py : テスト起動用のスクリプト └── test : テストケースを置いてあるディレクトリ ├── __init__.py ├── test_sub1.py : テストクラス1 ├── test_sub2.py : テストクラス2 └── sub_dir ├── __init__.py └── test_subsub1.py : テストクラス3今回は
test_sub1.py
とtest_sub2.py
とtest_subsub1.py
の3つのテストクラスをもとに、テストスイートを作成してテストを実行します。そしてそれを行うために
discover
を用いて、test
ディレクトリ以下にあるテストケースを自動的に収集してテストスイートを作成します。具体的には以下のように実装します。discover.py
import unittest # テストスイートを作成します def suite(): # 前述と同じく、TestSuiteから空っぽのテストスイートを作成します test_suite = unittest.TestSuite() # discoverメソッドを用いて、testディレクトリ以下からテストクラスを見つけます all_test_suite = unittest.defaultTestLoader.discover("test", pattern="test_*.py") # 見つけたテストクラスをテストスイートに追加します for ts in all_test_suite: test_suite.addTest(ts) return test_suite if __name__ == "__main__": # テストスイートを呼び出して実行します mySuite = suite() unittest.TextTestRunner().run(mySuite)上記のように
discover("test", pattern="test_*.py")
のところでテストケースを走査しています。これの実行は以下のように行います。
$ python3 discover.py test_subsub1_01 is called .test_sub1_01 is called .test_sub2_01 is called . ---------------------------------------------------------------------- Ran 3 tests in 0.001s OKdiscoverを使った方法の方がテストスイートをメンテナンスしなくていいので便利ですね。もしスキップしたいテストなどがある場合には、テストメソッド(またはテストクラス)に
@unittest.skip
をつければスキップもできるので、コントロールも便利です(詳細は前回のブログをご参照ください)。また上記と同じ内容について、コマンドのみでも実行することができます。
$ python -m unittest discover -s test -p "test_*.py" # または省略形でも可 $ python -m unittest discover test "test_*.py"コードでもコマンドでもできるのでお好みの方法で使ってみてください。
あと、discoverされたクラスですが、import地点はdiscoverしているところ(今回だとdiscover.pyのところ)が起点となります。例えば以下の場合には、
. ├── discover.py ├── get_one.py : test_subsub1.pyでインポートしたいクラス └── test ├── __init__.py └── sub_dir ├── __init__.py └── test_subsub1.py : discoverされるクラス
test_subsub1.py
からは以下のようにget_one.py
をインポートして使うことができます。import unittest # discover.pyの地点をルートとしてimportできる from get_one import get_one class SubSub1Test(unittest.TestCase): def test_subsub1_01(self): self.assertEqual(get_one(), 1, "get_one() must return 1")
参考資料
Pythonのunittestモジュールについては、以下の記事を参照しました。ありがとうございます。- 26.4. unittest — ユニットテストフレームワーク — Python 3.5.2 ドキュメント
- unit testing - Trying to implement python TestSuite - Stack Overflow
- how to run all Python unit tests in a directory - Stack Overflow
最後に
最初はテストスイートどうやるんだろうって色々と調べてしまいました。ドキュメントを最初に読むよりは、StackOverFlowとかで事例を見てから、その後にドキュメント読むといいですね。なんとなくすんなり理解できる気がします。Pythonについては細かいところをもっともっと身につけていかないとなーと思う今日この頃です。最後になりますが本ブログでは、Python・フロントエンド・開発関連・Swift・Linux・Java・機械学習など雑多に情報発信をしていきます。自分の第2の脳にすべく、情報をブログに貯めています。気になった方は、本ブログのRSSやTwitterをフォローして頂けると幸いです ^ ^。
最後までご覧頂きましてありがとうございました!