うるおろぐ

うるおろぐはうるおのろぐ

pytest入門 #1

プログラミング言語Pythonを使うことが多いが、テストがよくわからないのでデファクトスタンダードと思われるpytestに入門しました。

目次

環境

PC: MacBook Air (2017年)
仮想環境: venv

インストール

$ pip install pytest

実行の流れ

基本的にはこの流れになると思います。(TDDであれば1, 2逆ですかね)

  1. 関数作成
    • 実際に行いたい処理を作ります。
  2. テスト用関数作成
    • 関数に対するテスト用関数を作ります。
    • 基本的にassert文で期待値と結果が同一であるか判定する処理を書きます。
  3. pytest実行
    • CLIでpytestコマンドを実行します。

命名規則

pytestではテストファイル、メソッドとして認識されるように命名規則があります。

命名規則 補足
テストファイル test_<foo>.py OR <bar>_test.py プレフィックスで付けている人が多そうです。
テストメソッド test_<foo>
テストクラス Test<foo>

テストしたいソースファイルやメソッドなどと対になる形で定義するのが分かりやすそうです。

  • テスト対象ファイル: main.py
    • テストファイル: test_main.py
  • テスト対象メソッド: main
    • テストメソッド: test_main

なお、この探索の設定(テストディスカバリ)を変更することもできるようです。

ディレクトリ構成

命名規則ほどの決まりはなさそうだが、構成としては下記が多そうです。

.
├── pytest.ini
├── src
│   └── ソースファイル1
└── tests
    └── テストファイル1

path周りの設定はpytest.iniで設定してあげます。

pytest.ini

[pytest]
pythonpath = src # ソースファイルの場所
testpaths = tests # テストファイルの場所

サンプルテスト

ここまでの内容を基にサンプルを作成し、テストしてみます。構成は下記。

.
├── pytest.ini
├── src
│   └── repeat.py
└── tests
    └── test_repeat.py

pytest.ini

[pytest]
pythonpath = src
testpaths = tests

src/repeat.py

def repeat_word(word: str, num: int) -> str:
    return word * num

シンプルな処理なので内容は割愛します。

tests/test_repeat.py

from repeat import repeat_word

def test_repeat_word():
    word = "Hello"
    repeat_times = 3
    expected_value = word * repeat_times
    return_value = repeat_word(word, repeat_times)
    assert expected_value == return_value

まず、repeat.pyからrepeat_wordをimportしています。
対応するtest_repeat_wordを作成し、期待値を定義しています。
importしたrepeat_wordに引数を与え、assertで判定しています。

実行結果

platform darwin -- Python 3.9.6, pytest-7.4.0, pluggy-1.2.0
rootdir: /Users/uruo/Work/sample/prac_test/ch1
configfile: pytest.ini
testpaths: tests
collected 1 item

tests/test_repeat.py .                                          [100%]

==========================1 passed in 0.02s ==========================

成功しました!

感想

基本中の基本なところですが、テストが通ると嬉しいです。
実際はもっと複雑な処理に対するテストを書くと思うので、引き続き学習したいと思います。

参考