Skip to content

hikaruy0804/learn_python_testcode

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Pythonテスト駆動開発 学習リポジトリ

1. プロジェクト概要

目的

Pythonコードで、仕様書からテストコードの実装を行います。 また、同じ内容について、Python標準ライブラリunittestと、テストフレームワークpytestの2つを記述します。

学習の進め方

src/bankに実装された銀行口座の仕様(本READMEのセクション5)を読み解き、testsディレクトリにあなた自身のテストコードを記述します。 演習は、まずunittestで実装し、次にpytestで書き直す(リファクタリングする)ことで、両者の違いとpytestの利便性を体感できるように構成されています。

行き詰まった場合は、tests_answerディレクトリに解答例が用意されていますので、参考にしてください。

2. 環境構築

本プロジェクトは、高速なPythonパッケージインストーラであるuvを使用します。

  1. uvのインストール uvが未インストールの場合、公式の指示に従いインストールしてください。 (例: pip install uv または pipx install uv)

  2. リポジトリのクローンと移動

    git clone https://github.com/hikaruy0804/learn_python_testcode.git
    cd learn_python_testcode
  3. 仮想環境の作成

    uv venv

    プロジェクトルートに.venvという仮想環境が作成されます。

  4. 依存パッケージのインストール

    uv sync

    pyproject.tomluv.lockを基に必要なライブラリ(pytestなど)が仮想環境にインストールされます。

3. テストコードの記述(演習ステップ)

この演習は2つのステップで進め、unittestpytestの違いを体感することを目指します。

ステップ1: unittestで記述する

まずは、Pythonの標準ライブラリであるunittestを使い、仕様を満たすテストをtests/test_bank_unittest.pyに記述してみましょう。

unittestの基本:

  • unittest.TestCaseを継承したクラスを作成
  • test_で始まるメソッドを定義
  • self.assertEqual()などでアサーション
  • with self.assertRaises()で例外を検証

unittest

テストの実行:

uv run python -m unittest discover -s tests -p "test_*.py" -v

実行結果の確認: 実行後、コンソールの最終行にOKと表示されれば、すべてのテストが正常に完了しています。

ステップ2: pytestで記述

tests/test_bank_pytest.pypytestを使って同じテストを記述してみましょう。

pytestの実行:

uv run pytest -v tests

実行結果の確認: 実行後、... passed in ...のような緑色のメッセージが表示されれば成功です。

pytestの利点:

  • 記述量の削減: クラス定義が不要になり、コードが簡潔になります。
  • assert: Python標準のassertだけで、より詳細な失敗レポートが得られます。
  • Fixture: @pytest.fixtureを使うことで、テストの準備・後片付け処理を柔軟に共通化できます。
  • Parametrize: @pytest.mark.parametrizeを使うと、複数の入力パターンを持つテストを簡単に自動生成できます。

4. 機能仕様(Bankミニドメイン)

4.1 概要

  • 単純な銀行口座ドメインを実装する。入出金・振替を提供。
  • 金額は整数(最小単位:円)で扱い、小数は不可。
  • 例外と境界条件を明確に定義する(テストしやすい仕様)。

4.2 ユースケース

  • ユーザーは口座を作成し、入金・出金できる。
  • 2つの口座間で振替できる。
  • 口座残高は常に 0 以上でなければならない。

4.3 API(外部公開)

  • クラス:
    • Account(owner: str, balance: int = 0)
      • deposit(amount: int) -> None
      • withdraw(amount: int) -> None
  • 関数:
    • transfer(src: Account, dst: Account, amount: int) -> None
  • 例外:
    • OverdraftError: 残高不足
    • ValueError: 不正金額・同一口座振替などの仕様違反
    • TypeError: 引数の型が不正

4.4 正常系要件

  • deposit: 金額 amountint かつ > 0balance に加算。
  • withdraw: 金額 amountint かつ > 0。残高が足りるときのみ減算。
  • transfer:
    • amountint かつ > 0
    • src is not dst
    • src.withdraw(amount) が成功した場合のみ dst.deposit(amount) を行う(部分更新なし)。

4.5 異常系要件

  • deposit:
    • amount <= 0ValueError
    • amountint 以外 → TypeError
  • withdraw:
    • amount <= 0ValueError
    • amountint 以外 → TypeError
    • amount > balanceOverdraftError
  • transfer:
    • amount <= 0ValueError
    • amountint 以外 → TypeError
    • src is dstValueError
    • src 残高不足 → OverdraftError(この場合 dst は未更新)

4.6 非機能要件(最小)

  • Python 3.10+ / 外部依存なし
  • スレッドセーフ要件は持たない(学習用途のため単一スレッド想定)
  • 例外メッセージは簡潔で一貫

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages