環境
- Windows 10
- Python 3.10.1
- VSCode
pytestとは?
Pythonで書いたプログラムをテストするためのフレームワーク
導入手順
pip等でpytestをインストールする
pip install pytest
実装
- testで始まる名前の関数が自動的にテスト対象になる
- 各関数の中で、結果がTrueになるべき式をassert文で記述する
from shared.Application.check_is_valid_url_service import CheckIsValidUrlService
from shared.Domain.xurl import XUrl
def test_任意のurlが有効かどうかチェックできること():
x_url = XUrl("https://maasaablog.com/")
is_valid_url = CheckIsValidUrlService().execute(xurl=x_url)
assert is_valid_url
def test_無効なurlの場合はFalseを返すこと():
x_url = XUrl("https://hfefejjekfogehoge.com/")
is_valid_url = CheckIsValidUrlService().execute(xurl=x_url)
assert not is_valid_url
テストの実行
引数にスクリプトファイル名を指定してpytestコマンドを実行
pytest tests/test_check_is_valid_url_service.py
========================== 2 passed in 0.48s ===========================
- 引数を省略すると、カレントディレクトリにあるtest_*.pyという名前のスクリプトが自動的にテスト対象になる
- 以下のように実行すると、testsディレクトリ直下のtest_*.pyが実行される
pytest tests
その他のTips
異常系のテスト
- with pytest.raises(Exception) を使うと、with文の中で指定した例外が送出されるかどうかを検証可能
- 以下はEnumクラスに存在しない値を指定した時に、ValueErrorが生じるかどうかの検証
import pytest
from shared.Enums.ScrapingType import ScrapingType
def test_存在しない種別の場合は例外():
with pytest.raises(ValueError):
ScrapingType(99) == ScrapingType.SELENIUM
fixture
- 他の言語のテスト用フレームワークでいうところのsetupのようなもの
- 引数にfixtureとして定義したメソッド名を書くことで、各テスト開始直前に実行される
tests\test_str.py
import pytest
from shared.Domain.xstr import XStr
@pytest.fixture
def setuped_xstr():
xstr = XStr("masayan")
return xstr
def test_対象の文字列に特定の文字が含まれているかチェックできること_含まれていない場合(setuped_xstr):
assert setuped_xstr.is_contain("hoge") == False
def test_対象の文字列に特定の文字が含まれているかチェックできること_含まれている場合(setuped_xstr):
assert setuped_xstr.is_contain("yan") == True
- teardown(テスト終了後に行う特定の処理)は、以下のようにfixureの中でyieldを使用することで実現可能
@pytest.fixture
def setuped_xfile() -> None:
x_url = XUrl(href="https://www.home-movie.biz/mov/hts-samp001.mp4")
x_file = XFile(x_url)
yield x_file
x_file_system_path = XFileSystemPath(XStr("tests"))
downloaded_file_path = x_file_system_path.join(x_file.get_file_name())
downloaded_file_path.delete()
yield以降の処理がテスト終了後に必ず実行されます。また、setupの関数が返り値を必要とする場合は、returnは不要で、yield 返り値のように記述すればOKです
また、fixture
のスコープを指定することも可能です
@pytest.fixture(scope="module")
def sut():
・・・
fixture
のスコープは以下の通りです
- function
テストケースごとに1回実行、未指定の場合のデフォルト - class
テストクラス全体で1回実行、テストメソッドがクラスに含まれていなくても実行される。 - module
テストファイル全体で1回実行 - session
テスト全体で1回実行
pytest.fixtureで引数を渡すには以下のように(関数を返すように)します
@pytest.fixture
def something_fixture():
def func(a, b):
return a*b
return func
def test_hoge(something_fixture):
・・・・
スキップしたいテスト
スキップしたいテストの場合は、@pytest.mark.skipifを指定すればOK
@pytest.mark.skipif(True, reason="[スキップする理由などをここに記載する]")
def test_特定のセルを取得できる(setuped_worksheet: XWorksheet):
assert setuped_worksheet.get_cell(2, 1) == "Python"
まとめ
いかがでしたでしょうか。本記事では、pytestでPythonスクリプトの単体テストを行う方法について紹介しています。ぜひ参考にしてみてください