【初心者〜現場で活躍まで】挫折しないPython勉強方法もっと知る

pytestでよく使うオプションをサンプル付きで紹介

pytestでよく使うオプションをサンプル付きで紹介

pytestには、コマンドオプションがあります。

コマンドオプションを使えば、細かく実行ケースを指定したり、欲しい情報を追加表示することが可能です。

この記事では、 pytestでよく使うコマンドオプションをサンプル付きで紹介します。

pytestでよく使うオプション
  • –collect-only:実行される予定のテストケースを表示
  • -x:テストが失敗した時点で終了する
  • -s:print文を出力させる
  • –lf:失敗しているテストだけを実行する
  • -q:出力する情報を少なくする
  • -k:指定した文字列で検索して、テスト実行する

実行結果もつけていますので、イメージが湧きやすいと思います。

この記事を書いた人

エソラ
  • エンジニア歴10数年
  • SIerでDX推進を仕事に
  • Python、AWSを使ったアーキテクチャ設計・アプリ開発が得意
  • 30代、2児の父でサウナ好き
  • [icon-class=”icon-twitter”]Twitter

ちなみに、私の環境のバージョン情報は以下の通りです。

項目バージョン
Python3.10.6
pytest7.1.3
バージョン情報

それでは、最後までよろしくお願いします。

Pythonの勉強方法は、まとめ記事があります。

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 .

-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 ===========================================

test_calculator.pyでテストが失敗するため、test_fizzbuzz.pyは実行されずに、終了しています。

ちなみに、以下のようにコマンドを打つと、最大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 ===============================================

まとめ:pytestでよく使うオプション

ここまでpytestでよく使うオプションについて、実行例を交えながら、解説しました。

pytestでよく使うオプション
  • –collect-only:実行される予定のテストケースを表示
  • -x:テストが失敗した時点で終了する
  • -s:print文を出力させる
  • –lf:失敗しているテストだけを実行する
  • -q:出力する情報を少なくする
  • -k:指定した文字列で検索して、テスト実行する

コマンドオプションを有効的に使えると、効率よくテストができるようになります。

コマンドを全て覚える必要はないので、よく使うコマンドだけメモして使って下さい。

エソラ

この記事をブックマークしてくれてもいいですね。笑

もっとpytstの使い方を学びたい場合は、以下の書籍がおすすめです。

日本語で唯一、pytestだけに焦点を当てて、詳細に書かれた書籍です。

テスト駆動Python第2版
総合評価
( 5 )
メリット
  • 日本語でpytestの全てについて、解説されている唯一の書籍
  • 段々とステップアップして、深くなるので、初心者でも、中級者でも、上級者でも、学びがある
  • サンプルコードには、サンプルアプリが含まれているため、実践的に学べる工夫あり
  • 章末にまとめがあり、復習の役に立つ
  • 第7章に「どのようなテストを書くのか」についての解説があり、テストに対する考え方が深まる
デメリット
  • 後半になると、かなり高度な内容になるため、初心者には難しい
  • タイトルに「テスト駆動開発」と書かれているが、該当部分の記述が少なく、テスト駆動開発を知りたい人は期待外れになるかも
エソラ

間違えて、第1版を買わないように注意して下さい。

著:Brian Okken, 翻訳:株式会社クイープ, 監修:株式会社クイープ, 監修:安井 力
¥2,970 (2022/11/24 04:05時点 | Amazon調べ)

Pythonの勉強方法は、まとめ記事があります。

Pythonを勉強する時、何から勉強するか分からず、挫折します。初心者でも、中級者でも、レベルに合わせた勉強方法を分かりやすくまとめています。

ここまでお読みいただき、ありがとうございました。

役に立った、面白かったと思ったら、SNSでシェアしてくれると嬉しいです。

エソラ

もし分からないことがあれば、お問い合わせTwitterにご連絡をいただけると嬉しいです。(Twitterの方が返信早いかも…)

\ 更新の励みになるので、ポチッとしてね /

エソラ

他にもスキルアップやキャリアアップの役に立つ情報が満載です。他の記事も読んで、ゆっくりしていってね!

pytestでよく使うオプションをサンプル付きで紹介

この記事が気に入ったら
フォローしてね!

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次