pytestには、コマンドオプションがあります。
コマンドオプションを使えば、細かく実行ケースを指定したり、欲しい情報を追加表示することが可能です。
この記事では、 pytestでよく使うコマンドオプションをサンプル付きで紹介します。
- –collect-only:実行される予定のテストケースを表示
- -x:テストが失敗した時点で終了する
- -s:print文を出力させる
- –lf:失敗しているテストだけを実行する
- -q:出力する情報を少なくする
- -k:指定した文字列で検索して、テスト実行する
実行結果もつけていますので、イメージが湧きやすいと思います。
ちなみに、私の環境のバージョン情報は以下の通りです。
項目 | バージョン |
---|---|
Python | 3.10.6 |
pytest | 7.1.3 |
それでは、最後までよろしくお願いします。
Pythonを勉強する時、何から勉強するか分からず、挫折します。初心者でも、中級者でも、レベルに合わせた勉強方法を分かりやすくまとめています。
今回のサンプルプログラム
今回のフォルダ構成は以下のようになります。
pytest-coverage
L src
L calculator.py # テスト対象
L fizzbuzz.py # テスト対象
L test
L unit
L test_calculator.py # テストコード
L test_fizzbuzz.py # テストコード
L requirements.txt
L setup.py
テスト対象のコード
テスト対象のコード
単純な足し算、引き算、掛け算、割り算をするプログラムです。
def sum(x, y):
"""
足し算
"""
return x + y
def subtraction(x, y):
"""
引き算
"""
return x - y
def multiplication(x, y):
"""
掛け算
"""
return x * y
def division(x, y):
"""
割り算
"""
return x / y
有名なFizzBuzz問題を単純化したプログラムです。
def fizzbuzz(num):
if num % 15 == 0:
return 'FizzBuzz'
elif num % 3 == 0:
return 'Fizz'
elif num % 5 == 0:
return 'Buzz'
else:
return str(num)
テストコード
テストコード
calculator.pyのテストコードです。一つだけわざと失敗させるケースを作っています。
import pytest
from src.calculator import sum, subtraction, multiplication, division
@pytest.mark.parametrize(
"x, y, result",
[
(5, 1, 6),
(6, 2, 8),
(100, 10, 110),
],
)
def test_sum(x, y, result):
"""
足し算のテスト
"""
assert result == sum(x, y)
@pytest.mark.parametrize(
"x, y, result",
[
(5, 1, 4),
(6, 2, 4),
(100, 10, 90),
],
)
def test_subtraction(x, y, result):
"""
引き算のテスト
"""
assert result == subtraction(x, y)
@pytest.mark.parametrize(
"x, y, result",
[
(5, 1, 5),
(6, 2, 12),
(100, 10, 1), # わざと間違える
],
)
def test_multiplication(x, y, result):
"""
掛け算のテスト
"""
assert result == multiplication(x, y)
@pytest.mark.parametrize(
"x, y, result",
[
(5, 1, 5),
(6, 2, 3),
(100, 10, 10),
],
)
def test_division(x, y, result):
"""
割り算のテスト
"""
assert result == division(x, y)
fizzbuzz.pyのテストコードです。こちらも一つだけわざと失敗させるケースを作っています。
import pytest
from src.fizzbuzz import fizzbuzz
@pytest.mark.parametrize(
"num, result",
[
(15, 'FizzBuzz'),
(6, 'Fizz'),
(10, 'Buzz'),
(1, '100'), #わざと失敗させる
],
)
def test_fizzbuzz(num, result):
"""
関数をパラメータ化して、FizzBuzzを検証
"""
assert result == fizzbuzz(num)
テストコードはパラメータ化して、データのバリエーションを増やしています。
pytestでパラメータ化する方法は以下の記事で詳しく解説しています。
setup.py
setup.pyは以下のように実装します。
from setuptools import setup, find_packages
setup(name="PACKAGENAME", packages=find_packages())
そして、コマンドプロンプトやターミナルで以下のコマンドを打ちます。
pip install -e .
setup.pyの詳しい使い方は以下の記事で詳しく解説しています。
-v:詳細を表示する
pytestのオプションに「-v」をつけると、通常よりも詳しくテスト結果が出力されます。
$ pytest -v
実行結果は以下の通り。
-vをつけた場合
=============================================== test session starts ===============================================
platform darwin -- Python 3.10.6, pytest-7.1.3, pluggy-1.0.0 -- /Users/xxx/Documents/workspace/python-sample/pytest-sample/venv/bin/python3.10
cachedir: .pytest_cache
rootdir: /Users/xxx/Documents/workspace/python-sample/pytest-sample
plugins: cov-4.0.0
collected 16 items
test/unit/test_calculator.py::test_sum[5-1-6] PASSED [ 6%]
test/unit/test_calculator.py::test_sum[6-2-8] PASSED [ 12%]
test/unit/test_calculator.py::test_sum[100-10-110] PASSED [ 18%]
test/unit/test_calculator.py::test_subtraction[5-1-4] PASSED [ 25%]
test/unit/test_calculator.py::test_subtraction[6-2-4] PASSED [ 31%]
test/unit/test_calculator.py::test_subtraction[100-10-90] PASSED [ 37%]
test/unit/test_calculator.py::test_multiplication[5-1-5] PASSED [ 43%]
test/unit/test_calculator.py::test_multiplication[6-2-12] PASSED [ 50%]
test/unit/test_calculator.py::test_multiplication[100-10-1] FAILED [ 56%]
test/unit/test_calculator.py::test_division[5-1-5] PASSED [ 62%]
test/unit/test_calculator.py::test_division[6-2-3] PASSED [ 68%]
test/unit/test_calculator.py::test_division[100-10-10] PASSED [ 75%]
test/unit/test_fizzbuzz.py::test_fizzbuzz[15-FizzBuzz] PASSED [ 81%]
test/unit/test_fizzbuzz.py::test_fizzbuzz[6-Fizz] PASSED [ 87%]
test/unit/test_fizzbuzz.py::test_fizzbuzz[10-Buzz] PASSED [ 93%]
test/unit/test_fizzbuzz.py::test_fizzbuzz[1-100] FAILED [100%]
==================================================== FAILURES =====================================================
__________________________________________ test_multiplication[100-10-1] __________________________________________
x = 100, y = 10, result = 1
@pytest.mark.parametrize(
"x, y, result",
[
(5, 1, 5),
(6, 2, 12),
(100, 10, 1), # わざと間違える
],
)
def test_multiplication(x, y, result):
"""
掛け算のテスト
"""
> assert result == multiplication(x, y)
E assert 1 == 1000
E + where 1000 = multiplication(100, 10)
test/unit/test_calculator.py:47: AssertionError
______________________________________________ test_fizzbuzz[1-100] _______________________________________________
num = 1, result = '100'
@pytest.mark.parametrize(
"num, result",
[
(15, 'FizzBuzz'),
(6, 'Fizz'),
(10, 'Buzz'),
(1, '100'), # わざと失敗させる
],
)
def test_fizzbuzz(num, result):
"""
関数をパラメータ化して、FizzBuzzを検証
"""
> assert result == fizzbuzz(num)
E AssertionError: assert '100' == '1'
E - 1
E + 100
test/unit/test_fizzbuzz.py:18: AssertionError
============================================= short test summary info =============================================
FAILED test/unit/test_calculator.py::test_multiplication[100-10-1] - assert 1 == 1000
FAILED test/unit/test_fizzbuzz.py::test_fizzbuzz[1-100] - AssertionError: assert '100' == '1'
========================================== 2 failed, 14 passed in 0.26s ===========================================
-vをつけない通常の場合に比べると、出力される情報が増えていることが分かると思います。
-vをつけない場合
$ pytest
=============================================== test session starts ===============================================
platform darwin -- Python 3.10.6, pytest-7.1.3, pluggy-1.0.0
rootdir: /Users/xxx/Documents/workspace/python-sample/pytest-sample
plugins: cov-4.0.0
collected 16 items
test/unit/test_calculator.py ........F... [ 75%]
test/unit/test_fizzbuzz.py ...F [100%]
==================================================== FAILURES =====================================================
__________________________________________ test_multiplication[100-10-1] __________________________________________
x = 100, y = 10, result = 1
@pytest.mark.parametrize(
"x, y, result",
[
(5, 1, 5),
(6, 2, 12),
(100, 10, 1), # わざと間違える
],
)
def test_multiplication(x, y, result):
"""
掛け算のテスト
"""
> assert result == multiplication(x, y)
E assert 1 == 1000
E + where 1000 = multiplication(100, 10)
test/unit/test_calculator.py:47: AssertionError
______________________________________________ test_fizzbuzz[1-100] _______________________________________________
num = 1, result = '100'
@pytest.mark.parametrize(
"num, result",
[
(15, 'FizzBuzz'),
(6, 'Fizz'),
(10, 'Buzz'),
(1, '100'), # わざと失敗させる
],
)
def test_fizzbuzz(num, result):
"""
関数をパラメータ化して、FizzBuzzを検証
"""
> assert result == fizzbuzz(num)
E AssertionError: assert '100' == '1'
E - 1
E + 100
test/unit/test_fizzbuzz.py:18: AssertionError
============================================= short test summary info =============================================
FAILED test/unit/test_calculator.py::test_multiplication[100-10-1] - assert 1 == 1000
FAILED test/unit/test_fizzbuzz.py::test_fizzbuzz[1-100] - AssertionError: assert '100' == '1'
========================================== 2 failed, 14 passed in 0.29s ===========================================
–collect-only:実行される予定のテストケースを表示
pytestのオプションに「–collect-only」をつけると、実行される予定のテストケースを表示することができます。
$ pytest --collect-only
実行結果は以下の通り。
=============================================== test session starts ===============================================
platform darwin -- Python 3.10.6, pytest-7.1.3, pluggy-1.0.0
rootdir: /Users/xxx/Documents/workspace/python-sample/pytest-sample
plugins: cov-4.0.0
collected 16 items
<Module test/unit/test_calculator.py>
<Function test_sum[5-1-6]>
<Function test_sum[6-2-8]>
<Function test_sum[100-10-110]>
<Function test_subtraction[5-1-4]>
<Function test_subtraction[6-2-4]>
<Function test_subtraction[100-10-90]>
<Function test_multiplication[5-1-5]>
<Function test_multiplication[6-2-12]>
<Function test_multiplication[100-10-1]>
<Function test_division[5-1-5]>
<Function test_division[6-2-3]>
<Function test_division[100-10-10]>
<Module test/unit/test_fizzbuzz.py>
<Function test_fizzbuzz[15-FizzBuzz]>
<Function test_fizzbuzz[6-Fizz]>
<Function test_fizzbuzz[10-Buzz]>
<Function test_fizzbuzz[1-100]>
=========================================== 16 tests collected in 0.06s ===========================================
-x:テストが失敗した時点で終了する
pytestのオプションに「-x」をつけると、テストが失敗した時点でプログラムが終了します。
$ pytest -x
実行結果は、以下の通り。
=============================================== test session starts ===============================================
platform darwin -- Python 3.10.6, pytest-7.1.3, pluggy-1.0.0
rootdir: /Users/xxx/Documents/workspace/python-sample/pytest-sample
plugins: cov-4.0.0
collected 16 items
test/unit/test_calculator.py ........F
==================================================== FAILURES =====================================================
__________________________________________ test_multiplication[100-10-1] __________________________________________
x = 100, y = 10, result = 1
@pytest.mark.parametrize(
"x, y, result",
[
(5, 1, 5),
(6, 2, 12),
(100, 10, 1), # わざと間違える
],
)
def test_multiplication(x, y, result):
"""
掛け算のテスト
"""
> assert result == multiplication(x, y)
E assert 1 == 1000
E + where 1000 = multiplication(100, 10)
test/unit/test_calculator.py:47: AssertionError
============================================= short test summary info =============================================
FAILED test/unit/test_calculator.py::test_multiplication[100-10-1] - assert 1 == 1000
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! stopping after 1 failures !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
=========================================== 1 failed, 8 passed in 0.21s ===========================================
ちなみに、以下のようにコマンドを打つと、最大2つのテスト失敗まで、プログラムが終了せずに、続行されます。
pytest --maxfail=2
-s:print文を出力させる
pytestのオプションに「-s」をつけると、print文を出力させることができます。
テストコードにprint文を追加します。
import pytest
from src.fizzbuzz import fizzbuzz
@pytest.mark.parametrize(
"num, result",
[
(15, 'FizzBuzz'),
(6, 'Fizz'),
(10, 'Buzz'),
(1, '100'), # わざと失敗させる
],
)
def test_fizzbuzz(num, result):
"""
関数をパラメータ化して、FizzBuzzを検証
"""
assert result == fizzbuzz(num)
print("#########") #追加
そして、以下のコードを実行します。
$ pytest -s
結果は、以下の通り。期待通り、print文に書いた”#########”が出力されています。
=============================================== test session starts ===============================================
platform darwin -- Python 3.10.6, pytest-7.1.3, pluggy-1.0.0
rootdir: /Users/xxx/Documents/workspace/python-sample/pytest-sample
plugins: cov-4.0.0
collected 16 items
test/unit/test_calculator.py ........F...
test/unit/test_fizzbuzz.py #########
.#########
.#########
.F
(省略)
ちなみにオプションに「-s」をつけていない場合、print文は出力されません。
–lf:失敗しているテストだけを実行する
pytestのオプションに「–lf」をつけると、失敗しているテストだけを実行することができます。
$ pytest --lf
コマンドの結果は以下の通り。失敗していた2ケースだけ、実行されています。
=============================================== test session starts ===============================================
platform darwin -- Python 3.10.6, pytest-7.1.3, pluggy-1.0.0
rootdir: /Users/xxx/Documents/workspace/python-sample/pytest-sample
plugins: cov-4.0.0
collected 2 items
run-last-failure: rerun previous 2 failures
test/unit/test_calculator.py F [ 50%]
test/unit/test_fizzbuzz.py F [100%]
==================================================== FAILURES =====================================================
(省略)
============================================= short test summary info =============================================
FAILED test/unit/test_calculator.py::test_multiplication[100-10-1] - assert 1 == 1000
FAILED test/unit/test_fizzbuzz.py::test_fizzbuzz[1-100] - AssertionError: assert '100' == '1'
================================================ 2 failed in 0.49s ================================================
-q:出力する情報を少なくする
pytestのオプションに「-q」をつけると、出力する情報を少なくすることができます。
$ pytest -q
コマンドの結果は以下の通り。少し出力内容が省略されています。
........F......F [100%]
==================================================== FAILURES =====================================================
__________________________________________ test_multiplication[100-10-1] __________________________________________
x = 100, y = 10, result = 1
@pytest.mark.parametrize(
"x, y, result",
[
(5, 1, 5),
(6, 2, 12),
(100, 10, 1), # わざと間違える
],
)
def test_multiplication(x, y, result):
"""
掛け算のテスト
"""
> assert result == multiplication(x, y)
E assert 1 == 1000
E + where 1000 = multiplication(100, 10)
test/unit/test_calculator.py:47: AssertionError
______________________________________________ test_fizzbuzz[1-100] _______________________________________________
num = 1, result = '100'
@pytest.mark.parametrize(
"num, result",
[
(15, 'FizzBuzz'),
(6, 'Fizz'),
(10, 'Buzz'),
(1, '100'), # わざと失敗させる
],
)
def test_fizzbuzz(num, result):
"""
関数をパラメータ化して、FizzBuzzを検証
"""
> assert result == fizzbuzz(num)
E AssertionError: assert '100' == '1'
E - 1
E + 100
test/unit/test_fizzbuzz.py:18: AssertionError
============================================= short test summary info =============================================
FAILED test/unit/test_calculator.py::test_multiplication[100-10-1] - assert 1 == 1000
FAILED test/unit/test_fizzbuzz.py::test_fizzbuzz[1-100] - AssertionError: assert '100' == '1'
2 failed, 14 passed in 0.12s
-k:指定した文字列で検索して、テスト実行する
pytestのオプションに「-k」をつけると、指定した文字列でテストケースを検索して、該当したテストケースだけを実行できます。
$ pytest -k "sum"
コマンドの結果は以下の通り。test_sum()だけが実行されています。
===================================================== test session starts ======================================================
platform darwin -- Python 3.10.6, pytest-7.1.3, pluggy-1.0.0
rootdir: /Users/xxx/Documents/workspace/python-sample/pytest-sample
plugins: cov-4.0.0
collected 16 items / 13 deselected / 3 selected
test/unit/test_calculator.py ... [100%]
=============================================== 3 passed, 13 deselected in 0.06s ===============================================
Python学習におすすめのコンテンツ
現役シリコンバレーエンジニアが教えるPython 3 入門 + 応用 +アメリカのシリコンバレー流コードスタイル
Udemyの講座でPythonなら、文句なしにおすすめ
- 分かりやすい言葉や具体的なコードで工夫して説明しているので、初心者でも理解できる。
- 初心者でも挫折しないように、丁寧に詳しく手順を説明している。
- 講座内で取り扱う課題は実践的なものが多く、書籍では身につかない応用力を身につけられる。
- 情報量が多いのに、講座の進み方が速いので、一回では理解が追いつかない。
- 課題の難易度が高すぎる場合がある。
- 講師のアクセントが特殊で、聞き取りにくいと感じたことがある。
テスト駆動Python 第2版
日本語で唯一、pytestだけに焦点を当てて、詳細に書かれた書籍です。
- 日本語でpytestの全てについて、解説されている唯一の書籍
- 段々とステップアップして、深くなるので、初心者でも、中級者でも、上級者でも、学びがある
- サンプルコードには、サンプルアプリが含まれているため、実践的に学べる工夫あり
- 章末にまとめがあり、復習の役に立つ
- 第7章に「どのようなテストを書くのか」についての解説があり、テストに対する考え方が深まる
- 後半になると、かなり高度な内容になるため、初心者には難しい
- タイトルに「テスト駆動開発」と書かれているが、該当部分の記述が少なく、テスト駆動開発を知りたい人は期待外れになるかも
間違えて、第1版を買わないように注意して下さい。
まとめ:pytestでよく使うオプション
ここまでpytestでよく使うオプションについて、実行例を交えながら、解説しました。
- –collect-only:実行される予定のテストケースを表示
- -x:テストが失敗した時点で終了する
- -s:print文を出力させる
- –lf:失敗しているテストだけを実行する
- -q:出力する情報を少なくする
- -k:指定した文字列で検索して、テスト実行する
コマンドオプションを有効的に使えると、効率よくテストができるようになります。
コマンドを全て覚える必要はないので、よく使うコマンドだけメモして使って下さい。
この記事をブックマークしてくれてもいいですね。笑
Pythonを勉強する時、何から勉強するか分からず、挫折します。初心者でも、中級者でも、レベルに合わせた勉強方法を分かりやすくまとめています。
コメント