スポンサーリンク

Pythonのテスト設計入門|「何をテストするか」が一瞬で分かる思考法

Python入門
  1. はじめに
  2. 1. なぜ「テスト設計」が重要なのか
    1. 手動テストには限界がある
    2. 「祈りのリリース」になっていないか
    3. テストがないコードは、育てられない
  3. 2. Pythonにおけるテストの全体像を整理する
    1. テストは「範囲」と「目的」で分けて考える
    2. 「自動テスト」と「テストの種類」は別物
    3. Pythonでよく使われるテストツール
  4. 3. 「何をテストするか」を一瞬で判断する思考フレーム
    1. 3-1. まずテストすべきコードの特徴
    2. 3-2. あえてテストを書かなくてよいケース
    3. 3-3. 「このテストは何を守っているか」を言語化する
  5. 4. テスト設計の「型」を身につける
    1. 4-1. AAAパターン(Arrange / Act / Assert)
    2. 4-2. Given-When-Thenで仕様をテストに落とす
    3. 4-3. 良いテストの共通点
  6. 5. テスト設計を体系的に学びたい人へ
    1. テスト駆動Python 第2版
  7. 6. Pythonでの具体的なテスト実装手順
    1. 6-1. 仮想環境を用意する
    2. 6-2. unittestによるテストの基本構造
    3. 6-3. setUp / tearDownで前後処理をまとめる
  8. 7. pytestでテストを書くと何が変わるのか
    1. 7-1. テストコードが驚くほどシンプルになる
    2. 7-2. fixtureで「準備コード」を設計できる
    3. 7-3. テストが「仕様書」に近づく
    4. pytestをきちんと理解したい人へ
  9. 8. 一歩先へ:モック・静的解析・CI/CD
    1. 8-1. モックで「テストできない」をなくす
    2. 8-2. 静的解析で「崩れ方」を早めに止める
    3. 8-3. CI/CDでテストを“習慣”にする
  10. まとめ
  11. あわせて読みたい
    1. 参考文献
  12. よくある質問(Q&A)
    1. 関連投稿:

はじめに

Pythonで開発をしていると、こんな不安を感じたことはありませんか?
「ちゃんと動いているはずだけど、どこか壊れていそう…」 「修正したら、別の場所が動かなくなった気がする…」

その不安の正体は、テスト不足というよりも、 「テスト設計が曖昧なこと」にあるケースがとても多いです。

実は、テストを書くうえで一番むずかしいのは、
「どう書くか」ではなく「何をテストするか」を決めること。
ここが整理できていないと、テストは増えるのに安心感は増えず、 だんだん「テストがしんどいもの」になってしまいます。

この記事では、Python初心者の方から、pytestを触ったことがある中級者の方までを対象に、
「何をテストすべきか」を一瞬で判断するための考え方を中心に解説します。

AAAパターンやGiven-When-Thenといった定番の型、 unittest・pytestの使い分け、 そして実務でテストが“武器”になる設計の考え方まで、
できるだけ噛み砕いて、順番にお話ししていきますね。

テストは、開発を縛るものではなく、
安心してコードを書き続けるための味方です。
この記事が、「テスト、ちょっと分かってきたかも😊」と思えるきっかけになれば嬉しいです。




1. なぜ「テスト設計」が重要なのか

テストというと、「あとからバグを見つけるための作業」というイメージを持っている人も多いかもしれません。 ですが実際には、テストはバグを減らすための仕組みというより、 安心して開発を進めるための土台に近い存在です。

特に問題になりやすいのが、設計されていないテストです。 「とりあえず動くか確認する」「重要そうなところだけ何となくテストする」 という状態では、次のような問題が起こりがちです。

手動テストには限界がある

アプリケーションが小さいうちは、手動での確認でも何とか回ります。 しかし機能が増えてくると、
「毎回すべてを確認するのは現実的ではない」 「前は動いていたのに、どこで壊れたのか分からない」 という状況に陥りやすくなります。

人の記憶と注意力に頼ったテストは、どうしても抜け漏れが発生します。 その結果、不具合はリリース直前や本番環境で発覚し、 修正コストが一気に跳ね上がってしまいます。

「祈りのリリース」になっていないか

テスト設計が弱いと、修正を加えるたびに
「ここを直したけど、他は大丈夫だよね……?」
と不安を抱えたままリリースすることになります。

これは決して珍しい話ではなく、 テストが「何を守っているのか分からない」状態であることが原因です。 テストがあっても、設計されていなければ安心感は得られません。

テストがないコードは、育てられない

もうひとつ大きな問題は、リファクタリングができなくなることです。

テストがないコードは、
「触ったら壊れそう」 「どこまで変更していいのか分からない」
という状態になりがちです。

その結果、小さな改善が先延ばしにされ、 コードは少しずつ読みにくく、変更しづらくなっていきます。 これがいわゆる技術的負債です。

逆に、設計されたテストがあるコードは、 「壊れていないことをすぐ確認できる」ため、 安心して手を入れることができます。

だからこそ重要なのが、
「とにかくテストを書く」ことではなく、「何を守るためのテストなのか」を決めること
ここを明確にするのが、テスト設計の役割です。




2. Pythonにおけるテストの全体像を整理する

テスト設計を考えるうえで、まず押さえておきたいのが 「テストにはいくつかの役割と粒度がある」という点です。

ここが曖昧なままだと、
「このテストは何のために書いているのか?」 「どこまで確認すれば十分なのか?」
が分からなくなり、テストが増えるほど混乱してしまいます。

テストは「範囲」と「目的」で分けて考える

Pythonのテストは、大きく分けると テスト対象の範囲によって分類できます。

  • ユニットテスト(単体テスト)
    関数やメソッドなど、最小単位のロジックが 期待通りの結果を返すかを確認するテストです。 ロジックの正しさを素早く検証できるため、 Python開発では最も数が多くなります。
  • 統合テスト
    複数のコンポーネントを組み合わせたときに、 データの受け渡しや振る舞いが正しく連携しているかを確認します。 API、DB、外部サービスとの連携部分が対象になることが多いです。
  • リグレッションテスト(回帰テスト)
    修正や機能追加によって、 既存の動作が壊れていないことを保証するためのテストです。 自動テストとして継続的に実行されるのが一般的です。

「自動テスト」と「テストの種類」は別物

よく混同されがちですが、 自動テストという言葉は テストの「種類」ではなく実行方法を指します。

ユニットテストも統合テストも、 スクリプトで自動実行されていれば自動テストですし、 人が画面を操作して確認すれば手動テストになります。

設計の観点では、
「どのレベルのテストを、どこまで自動化するか」
を分けて考えることが重要です。

Pythonでよく使われるテストツール

Pythonには、テストを書くための環境が最初から整っています。

  • unittest
    Python標準ライブラリに含まれるテストフレームワーク。 クラスベースで明示的に書くスタイルのため、 テストの構造を理解しやすいのが特徴です。
  • pytest
    よりシンプルな記述でテストを書ける人気のフレームワーク。 fixtureやパラメータ化など、 テスト設計の表現力が高いのが強みです。

どちらが正解ということはなく、 重要なのは「どんなテストを、なぜ書くのか」です。 ツールは、その考え方を実装するための手段にすぎません。

次のセクションでは、
「すべてをテストしなくていい理由」と、 本当にテストすべきポイントの見極め方
を具体的な基準として整理していきます。




3. 「何をテストするか」を一瞬で判断する思考フレーム

テスト設計で一番悩みやすいのが、 「どこまでテストを書けばいいのか分からない」という問題です。

すべての関数・すべての分岐をテストしようとすると、 テストを書くこと自体が目的になり、 開発スピードもモチベーションも下がってしまいます。

大切なのは、
壊れたら困るところから優先的に守る
という考え方です。

3-1. まずテストすべきコードの特徴

次のようなコードは、優先的にテストを書く価値があります。

  • 重要なユースケース
    ユーザー登録、決済処理、データ保存など、 アプリケーションの中核となる処理。 ここが壊れると、サービス全体が成り立たなくなります。
  • 複雑なロジック
    条件分岐が多い、計算が入り組んでいる、 一目で正しさが判断できない処理。 人間の目だけでの確認には限界があります。
  • 境界値・エッジケース
    0、空文字、最大値・最小値など、 普段は意識しづらい入力に対する挙動。 バグはこうした「境目」で起こりがちです。
  • 過去にバグを出した箇所
    一度壊れた場所は、また壊れやすい場所です。 再発防止としてテストを書くことで、 同じミスを繰り返さずに済みます。

3-2. あえてテストを書かなくてよいケース

逆に、次のような箇所は 無理にテストを書かなくても問題ないことが多いです。

  • フレームワークが保証している単純な設定や配線だけのコード
  • 単なるデータの受け渡しだけをしている薄いラッパー
  • 仕様が頻繁に変わる初期段階のプロトタイプ

こうした部分まで完璧にテストしようとすると、 テストのメンテナンスコストばかりが増えてしまいます。

3-3. 「このテストは何を守っているか」を言語化する

テストを書く前に、
「このテストが失敗したら、何が困るのか」
を一度言葉にしてみてください。

たとえば、
「不正な入力を弾けなくなる」 「計算結果がズレる」 「権限のない操作が通ってしまう」
といった具体的なリスクが思い浮かぶなら、 それはテストを書く価値のある対象です。

この視点を持つだけで、 テストは「量」ではなく「意味」で選べるようになります。

次は、
テストを読みやすく、壊れにくくするための「設計の型」
を紹介します。 ここを押さえると、テストを書くスピードも一気に上がりますよ。




4. テスト設計の「型」を身につける

「何をテストするか」が決まったら、次に大切なのが テストをどういう形で書くかです。

テストは動けばOKではなく、
あとから読んだときに意図がすぐ分かること
がとても重要です。

そこで役に立つのが、テスト設計の定番の型です。 型を使うことで、テストの読みやすさと保守性が一気に上がります。

4-1. AAAパターン(Arrange / Act / Assert)

AAAパターンは、テストを次の3段階に分けて考える方法です。

  1. Arrange(準備)
    テストに必要な入力データや初期状態を用意します。
  2. Act(実行)
    テスト対象の関数やメソッドを実行します。
  3. Assert(検証)
    実行結果が期待通りかを確認します。

この順番を守るだけで、
「何を準備して、何を試して、何を確認しているテストなのか」
が一目で分かるようになります。

特にPythonのテストでは、 Arrangeが長くなりすぎていないかを見るだけでも、 「このテスト、ちょっと責務が重いかも?」 と気づけるようになります。

4-2. Given-When-Thenで仕様をテストに落とす

Given-When-Thenは、 仕様を文章の形で整理し、そのままテストに落とす考え方です。

  • Given:どんな前提条件か
  • When:どんな操作・処理を行ったか
  • Then:どんな結果になるべきか

この構造でテストを考えると、
「実装のテスト」ではなく「振る舞いのテスト」
になりやすいのが大きなメリットです。

実装の細かい中身が変わっても、 振る舞いが変わらなければテストは壊れません。 これは、将来のリファクタリングをとても楽にしてくれます。

4-3. 良いテストの共通点

AAAやGiven-When-Thenを意識して書かれたテストには、 次のような共通点があります。

  • テスト名を読むだけで、何を確認しているか分かる
  • 1つのテストで確認していることが1つだけ
  • 失敗したときに、原因の見当がすぐ付く

テストは「安心を増やすためのコード」です。 型を使って設計することで、 テストはどんどん心強い味方になっていきます。

次は、
テスト設計を体系的に学びたい人向けのおすすめ書籍
を紹介します。




5. テスト設計を体系的に学びたい人へ

ここまでで、
「何をテストするか」 「どういう型でテストを書くか」
という考え方の土台はだいぶ見えてきたと思います。

ただ、実務でテスト設計を身につけるには、 まとまった形でのインプットもやはり強力です。

特に、
「テストを書く理由が腹落ちしない」 「テスト駆動開発って結局何がいいの?」
と感じている方には、次の一冊がおすすめです。

テスト駆動Python 第2版

この本の特徴は、 テストコードの書き方よりも、 なぜそのテストを書くのかに重点が置かれている点です。

小さなテストを書き、 実装し、 リファクタリングする。
その一連の流れを追体験することで、 テストが設計そのものを支えている感覚が自然と身についていきます。

「テスト=面倒な作業」から
「テスト=設計を助けてくれる存在」
に意識が変わる一冊です。

テスト駆動Python 第2版
Amazonでチェックする| ✅ 楽天でチェックする

次のセクションでは、
unittestの基本を踏まえたうえで、 pytestを使うとテスト設計がどう変わるのか
を具体的に見ていきます。




6. Pythonでの具体的なテスト実装手順

ここからは、
これまで整理してきたテスト設計の考え方を、 実際のPythonコードにどう落とし込むかを見ていきます。

まずは基本となる環境づくりと、 Python標準の unittest を使ったテストの構造から確認しましょう。

6-1. 仮想環境を用意する

テストを書く前に、プロジェクトごとに 依存関係を分離する環境を用意しておくのがおすすめです。

Pythonでは、標準機能だけで簡単に仮想環境を作れます。

python -m venv venv

仮想環境を使うことで、
・ライブラリのバージョン違いによる事故を防げる ・テスト環境を再現しやすくなる
といったメリットがあります。

6-2. unittestによるテストの基本構造

unittestでは、 TestCaseクラスを継承したクラスを作り、 その中にテストを書いていきます。

ポイントは次の3つです。

  • テストクラスは unittest.TestCase を継承する
  • テストメソッド名は test_ で始める
  • assert系メソッドで結果を検証する

assertEqual や assertRaises などを使うことで、 「何を期待しているテストなのか」が明確になります。

6-3. setUp / tearDownで前後処理をまとめる

テストごとに同じ準備処理を書くのは、 読みにくく、修正もしづらくなりがちです。

unittestでは、 setUptearDown を使って テスト前後の処理をまとめられます。

  • setUp:各テストの前に毎回実行される
  • tearDown:各テストの後に毎回実行される

これにより、
「準備 → 実行 → 検証」
というAAAパターンが、自然な形でコードに現れます。

次のセクションでは、
pytestを使うことで、テスト設計と記述がどう変わるのか
を見ていきましょう。




7. pytestでテストを書くと何が変わるのか

unittestでテストの基本構造が分かってくると、 次に気になってくるのが 「pytestって何がそんなに良いの?」 という点だと思います。

結論から言うと、pytestは
テスト設計の意図を、よりシンプルにコードで表現できる
フレームワークです。

7-1. テストコードが驚くほどシンプルになる

pytestでは、unittestのように TestCaseクラスを継承する必要がありません。

関数としてテストを書くだけでよいため、 「準備・実行・検証」の流れがとても読みやすくなります。

特に、
・テストコードが長くなりがち ・初見の人が意図を読み取りにくい
と感じていた方には、大きな変化を感じやすいはずです。

7-2. fixtureで「準備コード」を設計できる

pytestの大きな特徴が、 fixtureという仕組みです。

fixtureを使うことで、
「どんな前提条件でテストしているのか」
を関数として明示的に表現できます。

これは単なる便利機能ではなく、 テスト設計そのものを整理する道具として非常に強力です。

7-3. テストが「仕様書」に近づく

pytestは、 Given-When-Thenの考え方とも相性がよく、 振る舞いベースのテストを書きやすいのが特徴です。

その結果、
・テストを読むだけで仕様が分かる ・実装が変わってもテストが壊れにくい
という状態を作りやすくなります。

「pytestを使うと楽になる」というより、
設計の意図が、テストコードに素直に現れる
と考えるとイメージしやすいかもしれません。

pytestをきちんと理解したい人へ

pytestは手軽に始められる一方で、 fixtureやパラメータ化など、 設計に直結する機能も多くあります。

「なんとなく使っている状態」から一歩進みたい方には、 次のガイドがとても参考になります。

pytest Quick Start Guide
Amazonでチェックする| ✅ 楽天でチェックする

次は、
テストを「書いて終わり」にしないための応用テクニック
として、モック・静的解析・CI/CD連携をまとめて紹介します。




8. 一歩先へ:モック・静的解析・CI/CD

テスト設計ができるようになると、 次に大事になるのが 「テストを継続して回せる仕組み」です。

テストは、書いた瞬間だけ役に立つものではなく、 変更し続けるコードを守り続けるものです。 そのために、ここから紹介する3つの要素が効いてきます。

8-1. モックで「テストできない」をなくす

テストが難しくなる代表例は、 外部に依存している処理です。

  • 外部APIへのリクエスト
  • データベースへの読み書き
  • ファイルI/O(読み込み・保存)
  • 時刻や乱数など、毎回結果が変わる要素

これらをそのままテストすると、
・ネットワーク状態で結果が変わる ・テストが遅い ・失敗原因がコードなのか外部なのか分からない
という「しんどいテスト」になりがちです。

そこで使うのがモックです。 外部依存を「仮のオブジェクト」に置き換えることで、 テスト対象のロジックだけを安定して検証できます。

コツは、モックを多用することではなく、 「どこまでを自分の責任範囲としてテストするか」 をはっきりさせることです。

8-2. 静的解析で「崩れ方」を早めに止める

テストは動作の保証ですが、 読みやすさ一貫性まで守るには、 静的解析(リンター・フォーマッター)が効きます。

  • black:コードを自動整形して、見た目のブレをなくす
  • flake8:スタイル違反や、よくあるミスを早期に検出する

これらは「正しさ」そのものではなく、 コードが壊れやすくなる兆候を早めに止めてくれます。

とくにテストコードは、 「急いで書いて雑になりがち」なので、 自動で整えてくれる仕組みがあると安心です。

8-3. CI/CDでテストを“習慣”にする

最後に、実務で一番効くのがここです。 テストは「書ける」だけでは足りなくて、 毎回自動で回る状態になって初めて強いです。

たとえばGitHub Actionsなどを使うと、
・プッシュしたら自動でテスト ・PRを出したら自動でテスト
という流れが作れます。

この状態になると、 テストは“頑張って実行するもの”から“勝手に守ってくれるもの” に変わります。

そしてこれが、テスト設計の価値を一段引き上げます。
「壊れないことを確認しながら、安心して改善できる」
という状態が作れるからです。




まとめ

この記事では、Pythonにおけるテスト設計について、
「何をテストするか」をどう判断するか
という視点を中心に解説してきました。

もう一度、ポイントを振り返ってみましょう。

  • テスト設計で一番大切なのは、すべてをテストすることではない
  • 壊れたら困る場所・バグが出やすい場所から優先的に守る
  • AAAパターンやGiven-When-Thenといったを使うと、テストは一気に読みやすくなる
  • pytestやfixtureは、テストを楽にするだけでなく設計の意図を表現する道具
  • モック・静的解析・CI/CDと組み合わせることで、テストは「書いて終わり」にならない

テスト設計を、よく 「建設現場の足場」 に例えられることがあります。

足場がしっかりしていれば、 高い場所でも安心して作業ができ、 スピードも精度も上がります。
テストもまさに同じで、 安心してコードを育て続けるための土台です。

最初から完璧なテスト設計を目指す必要はありません。
まずは、 「この変更で、どこが壊れたら一番困るか?」
を考えながら、1つずつテストを積み上げていけば大丈夫です。

テストが増えるほど、
「修正するのが怖いコード」から 「触るのが楽しいコード」
に変わっていきます。

この記事が、 テスト設計に対するハードルを少し下げるきっかけ になっていたら嬉しいです 😊


あわせて読みたい

テスト設計の考え方が見えてきたら、 次は実装力コード品質を一緒に伸ばしていくのがおすすめです。 ここでは、今回の内容と相性の良い関連記事を紹介します。

テスト設計は単独のスキルではなく、 設計・実装・改善とつながっています。 関連記事もあわせて読むことで、理解がより立体的になりますよ。


参考文献

本記事の内容は、上記の資料や実務での一般的なベストプラクティスをもとに整理しています。 テスト設計についてさらに深掘りしたい場合は、ぜひあわせて参照してみてください。


よくある質問(Q&A)

Q
すべての関数にテストを書くべきですか?
A

いいえ、必ずしもそうではありません。
大切なのは「壊れたら困るかどうか」です。

ビジネスロジックの中核や、条件分岐が多い処理、 過去にバグを出した箇所などは優先的にテストすべきです。 一方で、単なるデータ変換やフレームワーク任せの部分まで 完璧にテストしようとすると、保守コストの方が大きくなります。

「このテストが失敗したら、何が一番困るか?」
これを基準に判断すると、迷いにくくなります。

Q
pytestだけ覚えればunittestは不要ですか?
A

pytestだけでも実務は十分に回せますが、 unittestの基本構造を理解しておく価値はあります。

unittestはクラス構造やライフサイクルが明示的なため、
「テストはどういう部品で成り立っているのか」
を理解するのに向いています。

そのうえでpytestを使うと、 「なぜpytestが書きやすいのか」が腑に落ちやすくなります。 両方を知っておくと、チームや既存コードへの対応力も上がります。

Q
個人開発や小規模なスクリプトでもテストは必要ですか?
A

規模が小さくても、 「あとで触る可能性があるコード」ならテストは役に立ちます。

個人開発では、
「しばらく触っていなかったコードを修正する」
という場面がよくあります。

そのときにテストがあると、 思い出し作業のコスト修正の不安を大きく減らせます。

最初は1つ2つの重要な処理だけで構いません。
テストは「完璧にやるもの」ではなく、 未来の自分を助けるためのメモくらいの感覚で十分です。

※当サイトはアフィリエイト広告を利用しています。リンクを経由して商品を購入された場合、当サイトに報酬が発生することがあります。

※本記事に記載しているAmazon商品情報(価格、在庫状況、割引、配送条件など)は、執筆時点のAmazon.co.jp上の情報に基づいています。
最新の価格・在庫・配送条件などの詳細は、Amazonの商品ページをご確認ください。

スポンサーリンク