- このレポジトリは、pytestの書き方を簡単に説明するためのもの
- Dockerコンテナにパッケージ管理ツール
poetryを使って分析環境を構築する。
以下のコマンドによりDockerイメージのビルドとコンテナを起動できる。
docker-compose up -d
※Dockerfileを変更しリビルドしたい場合はdocker-compose up -d --buildを実行する
以下のコマンドを実行することでshellに入ることができる。
$ docker exec -i -t <container ID> bash
上記、コンテナ名を得るには、以下のdocker コマンドをローカルホストにて実行して挙動中のコンテナのリストを見る。
docker ps
すると、以下のようなリストが見れるので、そこから CONTAINER IDを取得
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ac810f0ca5a7 pytest-sample_eda "jupyter lab --ip=0.…" 15 minutes ago Up 15 minutes 0.0.0.0:8888->8888/tcp pytest-sample_eda_1
もしも停止中も含めた全てのコンテナを見たい場合は docker ps -a と a optionで全てを見る
reference: https://docs.docker.com/engine/reference/commandline/ps/
コンテナ実行後、以下にアクセスすることでJupyter labにアクセスできる。
http://localhost:8888/lab
以下のコマンドでPythonパッケージを追加できる。
poetry add <追加したいパッケージ>
- test_xxxx.py というテストモジュールを自動的に探してテストを開始するので、tests directoryで以下のコマンドを実行
$ pytest -vv
(the first v shows all test methods and the second v shows the slowest 10 test durations)
$ python -m pytest tests --cov-report=term --cov=tests/
-
ユニット=塊。
-
なんの塊をテストするかはチームで決める。xUnitパターンとか読んで勉強すればよい。
-
今回の対象はあくまでもバッチ処理などで使われる関数などのテストで、Webは対象ではない(webtestなどいろんなものがある)
-
テストの距離
-
テストで直接対象のAPIを呼ぶ(距離1)
-
APIを使っているview関数等を呼ぶ(距離N)
-
距離が遠いとテストケースが複雑になる
- 細かいテスト(ユニットテスト)を積み上げるのが基本パターン
-
- 関数単位でテストしましょう。
- inputとoutputを明確にしましょう。
- それを通るように実装しましょう。
- 不必要に複雑なテストは要らない、そのため不要になったテストコードはドンドン消して負債を減らす
- テスト対象はfixtureデコレーターで囲み、target関数とする
例:
def target(self):
from main import add
return add
- test時には対象をcall, そしてassertして検証するだけのようなテストにする
例:
def test_addint(self, target):
# call
actual = target(1, 2)
# verify
expect = 3
assert actual == expect
-
複数ケースのテストの場合は、parametrizeをつかうのはよい
-
テスト対象ではない、しかし依存関係のあるclassなどは、patch デコレーターでpatchを当てるとテストしやすい
-
pytest
-
失敗時はテストコードも表示してくれるので結果が見やすい。
-
unittest.TestCaseを継承する必要がない。
- assertEqualが使えなくなる。
- assert で十分になる。
-
parametrize が使える。
-
for文を書かなくてもよくなる
-
入力値毎に別のテストケースとして実行できる。
- unittest だと for 文内の assert は 1テスト扱い。
-
-
fixture が使える。
-
test_で始まる関数ならテストとして認識してくれる。
-
dict型やlist型等にも対応。
- -v, -vvオプションでどこがエラーか詳細が表示される。
-
-
doctest
-
一番単純。
-
実装に書いてあるので、利用者にとって分かりやすい。
-
複雑なテストには向かない。(import 文とか書き出すと...)
-
ドキュメントに書いてあるヘルプが実装と乖離していないかをチェックするため。
-
ドキュメントのテストと考えてもよい。
-
例:
def add(a, b): """ この関数は a + b の結果を返します 例: >>> add(1, 2) 3 >>> add('abc', 'def') 'abcdef' 以上 """ return a + b- 実行例:
$ python -m doctest main.py -v Trying: add(1, 2) Expecting: 3 ok Trying: add('abc', 'def') Expecting: 'abcdef' ok 1 items had no tests: main 1 items passed all tests: 2 tests in main.add 2 tests in 2 items. 2 passed and 0 failed. Test passed. -
-
assert 文
- AsseriionErrorの内容が分かりにくい
-
assertEqual
- AssertionErrorの内容が assert 文より分かりやすい
-
Pythonプロフェッショナルプログラミング第2版 by (株)ビープラウド 8章 モジュール分割設計と単体テスト