pytestのpytest-descrbeでテストを構造化して実行しよう!

eyecatch-pytest-describe
目次

概要

テストの構造化とBDD

テストコードは一つの関数について多くのパターンを実装することが多く、可読性を上げるためにも構造化をすることが重要です。テストを構造的に実装する際の考え方としてBDD(振る舞い駆動開発)があります。

BDDはソフトウェアの振る舞いを仕様書として明示し、その仕様に基づいたテストを書く開発手法です。BDDの目的は、技術者だけでなく非技術者(ビジネス担当者、顧客など)も含めたチーム全体で仕様を理解し、共有できるようにすることです。そのため、テストケースや仕様が読みやすく自然な言語で書かれていることが重要です。

BDDのテストは通常、Given-When-Then形式で記述されます

  • Given: 前提条件や設定を示す部分(何かが既に存在する、どのような状態であるか)
  • When: 操作やイベントを示す部分(ユーザーが何かアクションを起こした)
  • Then: 結果や期待される振る舞いを示す部分(どうなるべきか)

pytest-describe&pytest-spec

pytest-describeはpytest用のプラグインで、テストの可読性を高めるためにネストされた記述的なテスト構造を提供します。describeを用いて構造的に記述することで、テストのシナリオや意図を明確にしやすくします。特にソフトウェアの動作を自然言語で定義した後、テストを記述していくBDD(振る舞い駆動開発)と相性が良いといわれています。さらにpytest-specを導入することでテスト結果を仕様書のようにわかりやすく可視化することができます。

pytest-describeの使い方

前提

pytest-describeを使うためにはpytestがインストールされている必要があります。もしインストールされていない場合は下記を参考にインストールをしてください。

# 仮想環境の構築(実行は任意ですが、仮想環境で実行すると環境を汚さずに済みます)
python -m venv pytest-env
cd pytest-env
source bin/activate
(pytest_env) [ec2-user@ip-172-31-38-158 pytest_env]$ 

# pytest.markを利用するためにpytest.markを利用するために必要
pip install pytest

# pytest-describe pytest-specもインストールが必要
pip install pytest-describe pytest-spec

その他にpytestの実装に関する基本的なことを学びたい方は下記の記事をご参考ください

pytest-describe&pytest-specの使い方

pytest-describeは、BDDの考え方に基づいて、テストケースをわかりやすく構造化し、自然言語に近い形でテストを書くことができるためBDDと非常に相性が良いです。Given-When-Thenのうち特にWhen-Thenに関わる部分の記述で利用されます。(ちなみにGivenはpytestのフィクスチャという前処理・後処理を制御する機能で実現されます。)

5行目や13行目のdescribeブロックでは、テスト対象となる機能やコンポーネントをまとめて表現するためのものです。BDDの文脈では、Givenに相当する部分やシナリオ全体を整理するために使われます。例えば、「加算機能のテスト」や「ユーザーログインの振る舞い」のように大きな機能単位で分けられます。

7、10、15、18行目のitは具体的なテストケースを記述する部分で、「何が期待されるか」(Thenに相当)を記述します。自然言語に近い形で「この振る舞いが期待される」ということを明示できるため、読みやすく、意図がはっきりしたテストを書けます。

def describe_user_authentication():

    def describe_when_user_logs_in():
        
        def it_succeeds_with_correct_credentials():
            assert login("valid_user", "correct_password") == "Login successful"

        def it_fails_with_incorrect_credentials():
            assert login("valid_user", "wrong_password") == "Login failed"

    def describe_when_user_registers():
        
        def it_succeeds_with_valid_information():
            assert register("new_user", "valid_password") == "Registration successful"

        def it_fails_with_existing_username():
            assert register("existing_user", "any_password") == "Username already taken"

続いてテストの出力結果の例です。通常のpytest -vでもどの関数が実行されたがわかりま。慣れていればもんだいないかもしれませんが、初めのうちは少々見づらさを感じるかもしれません。

# 通常のpytest出力結果、コマンドオプションに-vをつけて実行
pytest -v

================================ test session starts ================================
collected 4 items

test_user_authentication.py::describe_user_authentication::describe_when_user_logs_in::it_succeeds_with_correct_credentials PASSED
test_user_authentication.py::describe_user_authentication::describe_when_user_logs_in::it_fails_with_incorrect_credentials PASSED
test_user_authentication.py::describe_user_authentication::describe_when_user_registers::it_succeeds_with_valid_information PASSED
test_user_authentication.py::describe_user_authentication::describe_when_user_registers::it_fails_with_existing_username PASSED

================================= 4 passed in 0.01s =================================

そこでpytest-specをインストールすることで下記のように構造化された出力が表示され、テスト結果がとても見やすくなります。

# pytest-specを利用した場合の出力結果例
User Authentication
  When user logs in
     succeeds with correct credentials
     fails with incorrect credentials
  When user registers
     succeeds with valid information
     fails with existing username

===================================== 4 passed in 0.01s =====================================
User Authentication
  When user logs in
     succeeds with correct credentials
     fails with incorrect credentials
  When user registers
     succeeds with valid information
     fails with existing username

===================================== 4 passed in 0.01s =====================================

まとめ

本記事ではpytest-descrbeについて解説しました。BDDと合わせてぜひ開発の現場でも積極的に使用して見やすいテストの記述ができるようにトレーニングしてみてください!

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

この記事を書いた人

Hack Luck Labの管理人hakula(ハクラ)です。2012年にSIerに新卒入社し、SE、新規事業、情シスを担当。その後、ITコンサルを経て、現在はバックエンドエンジニア。過去にはC#、SQL Server、JavaScriptで開発を行い、現在はPython、Rest Framework、Postgresql、Linux、AWSなどを使用しています。ノーコードツールやDX関連も興味あり。「技術は価値を生むために使う」ことが信条で、顧客や組織への貢献を重視しています。

目次