この記事は公開されてから1年以上経過しています。情報が古い可能性がありますので、ご注意ください。
pytestの使い方を学びます。テストケースには、個人的に直近で利用していたPandas, OpenPyXLを利用したいと思います。 手順は、pytest を参考にさせていただきます。
環境/前提
こちらの記事と同様の環境を利用します。
なお、今回は追加で以下のパッケージが必要です。
- numpy 1.23.3
- pytest 7.1.3
テストの書き方/テスト実行(アサーションチェック)
まずは、単純なテストケースを利用し、pytestの書き方を学びます。
pytest は test_ で始まるファイル・関数を単体テストのコードとみなします
テストの書き方
pandas Testingのassert_series_equal
関数は、デフォルトでdtypeまで確認してくれます(第3引数: check_dtype=True1)。
テストケースは、Book1.xlsxファイルの2行目(A:E)に入っているデータが期待したものになっているかのチェック
です。
import pytest
import numpy as np
import pandas as pd
from pandas.testing import assert_series_equal
import openpyxl
def test_read_excel():
actual = pd.read_excel('Book1.xlsx', sheet_name='Sheet1', usecols="A:E", dtype = {
'メールアドレス1(必須)': 'string',
'メールアドレス2(任意)': 'string',
'メールアドレス3(任意)': 'string'
})
assert_series_equal(actual['ID'], pd.Series([12345], dtype=np.int64, name='ID'))
assert_series_equal(actual['日付'], pd.Series([pd.to_datetime('2022/08/31')], dtype='datetime64[ns]', name='日付'))
assert_series_equal(actual['メールアドレス1(必須)'], pd.Series(['shiraishi@example.com'], dtype='string', name='メールアドレス1(必須)'))
assert_series_equal(actual['メールアドレス2(任意)'], pd.Series(['shiraishi@example.com'], dtype='string', name='メールアドレス2(任意)'))
assert_series_equal(actual['メールアドレス3(任意)'], pd.Series(['shiraishi@example.com'], dtype='string', name='メールアドレス3(任意)'))
$ pytest test_xl_test.py
======================================================================================== test session starts =========================================================================================
platform darwin -- Python 3.10.6, pytest-7.1.3, pluggy-1.0.0
rootdir: /Desktop/test_python
collected 1 item
test_xl_test.py . [100%]
========================================================================================= 1 passed in 0.61s ==========================================================================================
パラメータ化したテスト
次に@pytest.mark.parametrize
デコレータを使います。
デコレータは、テストで使用する値をパラメータとして持つことができます。初めの引数(expected)は、テスト関数に渡すパラメータの引数名を指定することができます。
テストケースは、Book1.xlsxファイルの2行目1列(A2)に入っている'ID'が期待したものになっているかのチェック
です。
import pytest
import numpy as np
import pandas as pd
from pandas.testing import assert_series_equal
import openpyxl
@pytest.mark.parametrize(('expected'), [
(pd.Series([12345], dtype=np.int64, name='ID')),
])
def test_read_excel_2(expected):
actual = pd.read_excel('Book1.xlsx', sheet_name='Sheet1', usecols="A:E", dtype = {
'メールアドレス1(必須)': 'string',
'メールアドレス2(任意)': 'string',
'メールアドレス3(任意)': 'string'
})
assert_series_equal(actual['ID'], expected)
$ pytest test_xl_test.py
======================================================================================== test session starts =========================================================================================
platform darwin -- Python 3.10.6, pytest-7.1.3, pluggy-1.0.0
rootdir: /Desktop/test_python
collected 2 items
test_xl_test.py .. [100%]
========================================================================================= 2 passed in 0.63s ==========================================================================================
フィクスチャ
最後にフィクスチャを利用します。
フィクスチャでは、テスト関数を実行する前の前処理を記述することができます。今回は、前処理としてBook1.xlsxの2行目(A:E)のデータを書き換えます。
テストケースは、Book1.xlsxファイルの2行目1列(A2)に入っている'ID'が期待したもの(書き変わった値)になっているかのチェック
です。
import pytest
import logging
import numpy as np
import pandas as pd
from pandas.testing import assert_series_equal
import openpyxl
@pytest.fixture
def xl_name() -> str:
wb = openpyxl.load_workbook('Book1.xlsx')
ws = wb["Sheet1"]
for i, values in enumerate([['55555', '2022/09/30', 'shiraishi@example.com', 'shiraishi@example.com', 'shiraishi@example.com']]):
for j, value in enumerate(values):
if value is None:
continue
ws.cell(row=2+i, column=1+j, value=value)
wb.save('Book1.xlsx')
yield 'Book2.xlsx'
def test_read_excel_3(xl_name):
actual = pd.read_excel(xl_name, sheet_name='Sheet1', usecols="A:E", dtype = {
'メールアドレス1(必須)': 'string',
'メールアドレス2(任意)': 'string',
'メールアドレス3(任意)': 'string'
})
assert_series_equal(actual['ID'], pd.Series([55555], dtype=np.int64, name='ID'))
$ pytest test_xl_test.py
======================================================================================== test session starts =========================================================================================
platform darwin -- Python 3.10.6, pytest-7.1.3, pluggy-1.0.0
rootdir: /Desktop/test_python
collected 3 items
test_xl_test.py ... [100%]
========================================================================================= 3 passed in 0.64s ==========================================================================================
所感
昔、xSpec系のテストを学ぶ機会がありました2。xUnit系のテストをあまり書いた経験がなかったのですが、pytestは、このような良い指南書もあり、入門には良いテストライブラリだと感じました。次のステップとしては、どのように考え、どのようなテストを行うか、やテストダブルのおさらいをしたいと思います。以上、pytest入門でした。
参考
- pytest
- BUG: dtype not working with datetime64 #34928