等価性分割: テスト設計手法を実際の例で説明

  1. ホーム
  2. ブログ
  3. ソフトウェアテスト

ソフトウェアテスト

同値分割: 実際の例で説明されるテスト設計テクニック

考えられるすべての入力をテストすることはできません。では、どの値を選択すればよいでしょうか?同値分割により明確な答えが得られます。方法を段階的に学び、実際の例を使って作業し、どこに助けが必要かを確認してください。

読了目安8分
等価分割テスト設計手法を実際の例で説明

ポイント

  • 等価分割は、入力を同じように動作するグループに分割します。
  • すべての値ではなく、各グループから 1 つの代表値をテストします。
  • エラー処理には多くのバグが隠れているため、無効パーティションを常に含めてください。
  • バグはグループの端に位置することが多いため、境界値分析と併用するのが最も効果的です。

18 から 60 までを受け入れる年齢フィールドには、負の数、膨大な数、テキスト、空白を数えると、膨大な数の入力が可能になります。誰もそれらすべてを試すことはできません。 等価分割は、ソフトウェアが同じ方法で扱う必要がある入力をグループ化し、各グループから 1 つの値をテストすることでこれを解決します。

これは、すべてのテスターが学ぶべき最初のテスト設計テクニックの 1 つです。このガイドでは、それを段階的に説明し、Python で 1 つの例をテストします。そのコードを Python 3.13 で実行し、その出力が含まれています。以下のパスワードとクーポンのルールは説明用の例であり、実際のシステムから引用したものではありません。

等価分割とは何ですか?

等価分割は、等価クラス分割 (ECP) とも呼ばれ、ブラック ボックス テスト設計手法です。機能の可能な入力を パーティション、つまりクラスに分割します。パーティション内のすべての値は、同じ種類の動作を生成することが期待されます。

コードを確認する必要がないため、要件から直接適用できます。このスタイルのテストの詳細については、ブラック ボックスとホワイト ボックスのテストをご覧ください。

なぜ効果があるのか

この手法は 1 つの仮定に基づいています。パーティション内の 1 つの値でバグが見つかった場合、そのパーティション内の他の値でもバグが見つかる可能性が高いということです。そして、1 つの値が合格すると、おそらく他の値も合格するでしょう。成人年齢フィールドで 25、26、27 をテストしても、25 だけをテストした場合には分からなかったことがわかる可能性があります。

アプローチ 年齢フィールドのテスト 結果
網羅的 考えられるすべての値 現実的には不可能
ランダムな推測 思い浮かんだことは何でも 重複とギャップ
等価分割 パーティションごとに 1 つ 小さく、意図的にカバーされている

ただし、これは仮定であり、保証するものではありません。ソフトウェアにはパーティション内に特殊なケースが隠されている場合がありますが、この制限については後で説明します。

5つのステップでそれを行う方法

  1. 要件を読み、入力とそのルールを特定します。
  2. 受け入れられるべき値のグループである有効なパーティションを見つけて、範囲が異なると動作が異なるかどうかに注意してください。
  3. 低すぎる値、高すぎる値、間違ったタイプ、空白などの無効なパーティションを見つけます。
  4. 各パーティションから代表的な値を 1 つ選択、通常は中央のどこかにあります。
  5. 他の良いテストケースと同様に、それぞれについて期待される結果を書き留めます。

作業例: 年齢フィールド

要件: 18歳から60歳までのユーザーが登録できます。

パーティション 種類 検査値 期待される結果
18歳未満 無効です 10 拒否されました
18~60 有効 35 承認されました
60以上 無効です 75 拒否されました
数字ではありません 無効です 「ABC」 エラー
空白 無効です (empty) 「必須」メッセージ

5 つのテストにより、要件内のすべての動作をカバーできます。多くのチュートリアルは最初の 3 行で停止しますが、最後の 2 行は実際のユーザーが誤ってトリガーするものです。別の方法で処理できる場合は、負の数または小数の行を追加することもできます。

コードでテストする

以下は、Python の組み込み unittest を使用した、パーティションごとに 1 つの単体テストを含む関数としてのルールです。

import unittest

def can_register(age):
    if not isinstance(age, int) or isinstance(age, bool):
        raise TypeError("age must be a whole number")
    return 18 <= age <= 60

class EquivalenceTests(unittest.TestCase):
    def test_valid_partition(self):
        self.assertTrue(can_register(35))

    def test_too_young_partition(self):
        self.assertFalse(can_register(10))

    def test_too_old_partition(self):
        self.assertFalse(can_register(75))

    def test_wrong_type_partition(self):
        with self.assertRaises(TypeError):
            can_register("abc")

私たちのランは合格しました:

test_too_old_partition ... ok
test_too_young_partition ... ok
test_valid_partition ... ok
test_wrong_type_partition ... ok

実際のプロジェクトでは、pytest のパラメータ化機能 は、単一のテストでパーティション値のテーブルを実行する優れた方法です。

作業例: パスワード

要件: パスワードは 8 ~ 20 文字で、少なくとも 1 つの数字が含まれている必要があります。

これには長さと内容という 2 つのルールがあるため、両方のパーティションを考慮します。

パーティション 種類 検査値 期待される結果
有効な長さ、数字が含まれています 有効 日の出42 承認されました
短すぎる 無効です abc1 エラー: 短すぎます
長すぎます 無効です 数字を含む 30 文字の値 エラー: 長すぎます
有効な長さ、数字なし 無効です 日の出の日 エラー: 数字が必要です
空白 無効です (empty) エラー: 必須

それぞれの無効なテストが 1 つのルールのみ を破ることに注意してください。値が短すぎて桁が欠落している場合、合格したテストではどのチェックが機能したかを判断できません。 1 つのチェックが破られている一方で、もう 1 つは事実を隠している可能性があります。

実用的な例: 数値以外の入力

この手法は数値範囲に限定されません。個別のオプション、カテゴリ、状態もパーティションを形成します。あるショップに次のルールがあるとします。

要件: 配送料はゴールド会員は無料、シルバー会員は50回、その他の会員は100回です。不明な階層値はエラーです。

パーティション 検査値 予定料金
ゴールド ゴールド 0
シルバー 銀色 50
会員権なし (none) 100
不明な層 プラチナ エラー

ここでは、それぞれが異なる動作をする必要があるため、各オプションは独自のパーティションです。その他の一般的なパーティションには、有効および無効なアップロードなどのファイル タイプや、ローンの承認または拒否などの出力ベースのグループが含まれます。

ヒント: インプットだけでなくアウトプットについても考えてください。計算によって割引、割引なし、または警告が生成される場合は、少なくとも 1 つのテストがそれぞれの結果に達することを確認してください。

一度に複数の入力

フィールドが複数あると、組み合わせの数が急速に増加します。それぞれ 4 つのパーティションを持つ 3 つのフィールドでは、64 の組み合わせが得られます。 2 つの戦略が役立ちます。

  • 弱いカバレッジ: 各パーティションが少なくとも 1 つのテストに表示されるようにし、テストごとに複数の 有効な 値を組み合わせます。無効な値については、エラーが相互にマスクしないよう、一度に 1 つずつテストしてください。
  • ルールベースのカバレッジ: メンバーステータスと順序値など、組み合わせによって実際に結果が変わる場合は、デシジョンテーブルテストを使用してそれらを適切にリストします。

境界値分析との組み合わせ

パーティショニングにより、どのグループをテストするかがわかります。虫が群れのどこに隠れたがるのかについてはほとんど言及されておらず、多くの虫は端に隠れています。これを示すために、古典的な 1 つ違いの間違いを含むバグのあるバージョンを作成しました。

def buggy(age):
    return 18 < age <= 60     # should be 18 <= age

[buggy(a) for a in (35, 10, 75)]   # [True, False, False]
buggy(18)                          # False

パーティション値 35、10、および 75 はすべて正しい答えを示したので、これらのテストは合格します。しかし、18歳は不当に拒否されます。これが、2 つのテクニックが一緒に属する理由です。

テクニック 選択します 18 歳から 60 歳までの値
等価分割 各グループ内の 1 つの値 10, 35, 75
境界値解析 各グループの端の値 17, 18, 60, 61

パーティショニングを使用してグループを見つけ、次に境界を使用してグループが出会う場所をテストします。私たちのコードでは、17、18、60、および 61 の別のテストが正しい関数を渡し、そのバグをキャッチします。私たちの 境界値分析ガイド では、これについて完全に説明しています。

利点と制限

利点 制限事項
検査数を大幅に削減 パーティションが正しいかどうかに依存する
明確で説明可能な内容を提供する 境界でバグを見逃す可能性がある
コードにアクセスする必要はありません 隠された特殊なケースを見逃す可能性がある
要件からでも早めに申請可能 シーケンスや組み合わせを適切にモデル化していない

最大のリスクは誤った仮定です。コードに 1 つの特定の値に対する隠されたルールがある場合、選択したテストではそのルールに到達できない可能性があります。 探索的テストとコード カバレッジは、パーティションに欠けているものを見つけるのに役立ちます。

よくある間違い

  • 無効なパーティションを忘れます。 正常なパスのみをテストすると、エラー処理が未チェックのままになります。
  • 1 つのパーティションから複数の値をテストします。 これにより、新しい情報が得られずにコストが追加されます。
  • 1 つのテストで複数の無効な値を組み合わせる。 1 つのエラーが別のエラーを隠す可能性があります。
  • 境界のスキップ。 パーティション テストだけでは、off-by-one のバグを見逃すことがよくあります。
  • ルールを推測します。 要件が不明瞭な場合は、質問してください。 60には60歳半の人も含めるべきでしょうか?

まとめ

等価分割は、「テストをいくつ書く必要があるか?」を置き換えます。 「どのような動作が存在しますか? それぞれについて説明しましたか?」という、より良い質問があります。これを試してみるには、今日テストしているフォームを用意し、無効なパーティションも含めてそのパーティションを紙にリストします。次に境界を追加します。多くの場合、より多くのバグを発見するテストの数が減ることになります。

よくある質問

テストにおける等価分割とは何ですか?

これは、入力を同様に動作すると予想されるグループに分割するブラック ボックス手法です。次に、すべての値ではなく、各グループから 1 つの代表値をテストします。

同値分割と境界値分析の違いは何ですか?

パーティショニングでは、各グループ内から 1 つの値が選択されます。境界値分析では、それらのグループのエッジの値をテストします。通常、これらは一緒に使用されます。

同値分割にはいくつのテスト ケースが必要ですか?

通常、有効と無効の両方でパーティションごとに少なくとも 1 つ。年齢範囲フィールドには通常、約 3 ~ 5 つのテストが必要です。

等価分割はブラックボックスですか、それともホワイトボックスですか?

パーティションは要件に基づいて作成され、コードを必要としないため、これはブラック ボックス手法です。ただし、開発者は単体テストにも適用できます。

有効なパーティションと無効なパーティションとは何ですか?

有効なパーティションには、システムが受け入れる必要がある値が含まれています。無効なパーティションには、範囲外の数値、間違った型、空白など、拒否する必要がある値が含まれています。

学び続ける

Stack Quoraと連携する

テスト、WordPress、または SEO についてサポートが必要ですか?

私たちは、チームがより優れたソフトウェアを出荷し、サイトを成長させるのを支援します。あなたが取り組んでいることを教えてください。明確な次のステップを提案します。

読み続けてください

詳しいガイドはこちら テスト、AI、最新の開発

この記事は気に入りましたか?トピックを選択して、最新のチュートリアルに直接アクセスしてください。

人工知能

AI 幻覚の説明: 言語モデルが物事をでっち上げる理由とそれを軽減する方法

AI 幻覚について説明しました。幻覚とは何か、言語モデルが幻覚を生成する理由、一般的な種類、グラウンディングとプロンプトで幻覚を軽減する方法、そして私たちが実行した簡単なチェックです。

記事を読む →
DevOps

環境変数の説明: .env ファイル、シークレット、および設定が正しく行われている

実行した Python の例を使用して環境変数について説明します。環境変数の読み取りと設定、すべての値が文字列である理由、.env ファイル、プロセスの継承、シークレット、検証について説明します。

記事を読む →
ソフトウェア開発

API レート制限の説明: アルゴリズム、ヘッダー、および 429 エラーの処理

API レート制限については、実行したシミュレーションで説明します。トークン バケット、固定ウィンドウ、スライディング ウィンドウ、429 応答、レート制限ヘッダー、バックオフによる再試行、およびテスト制限です。

記事を読む →
テスト自動化

Python でのモッキング:unittest.mock、patch、およびテストを嘘にする間違い

Python でのunittest.mockによるモック、テスト済み: モックとreturn_value、side_effect、名前が使用されている場所のパッチ、仕様と自動仕様、日付のモック、およびよくある間違い。

記事を読む →
ソフトウェアテスト

コードカバレッジの説明: 回線カバレッジとブランチカバレッジ、および 100% の実際の意味

実際のcoverage.pyの実行でコードカバレッジを説明: 行、分岐、条件のカバレッジ、レポートの読み取り、100%のカバレッジでもバグを見逃す可能性がある理由、および賢明なターゲット。

記事を読む →
データベースとSQL

SQL における DELETE、TRUNCATE、DROP: 違い、ロールバック、およびそれぞれをいつ使用するか

DELETE、TRUNCATE、DROP について、テスト済み SQL を使用して説明します。それぞれの削除内容、ロールバック、トリガー、ID リセット、速度、PostgreSQL、MySQL、SQL Server、SQLite の違いについて説明します。

記事を読む →
データベースとSQL

SQL ビューの説明: 作成、使用、落とし穴の回避、例を示します

SQL ビューについて、実行したクエリとともに説明しました。ビューの作成、ライブ結果、列の非表示、パフォーマンス、更新可能なビューと具体化されたビュー、壊れた依存関係、ベスト プラクティスについて説明します。

記事を読む →
ソフトウェア開発

TypeScript インターフェイスと型: 実際の違い、コンパイラでテスト

TypeScript インターフェイスと型、実際のコンパイラでチェック: 両方でできること、片方だけでできること、宣言のマージ、拡張と交差、および従うべき簡単なルール。

記事を読む →
ソフトウェア開発

Python *args と **kwargs の説明: 柔軟な関数と明確な例

Python の *args と **kwargs について、実行したコードで説明しました。パッキングとアンパッキング、パラメーターの順序、キーワードのみの引数と位置のみの引数、デコレーター、一般的なエラーです。

記事を読む →
ソフトウェア開発

Python Lambda 関数: 構文、実際の用途、および使用すべきでない場合

Python のラムダ関数について、実行したコードとともに説明します。構文、キーによるソート、マップとフィルター、クロージャー、遅延バインディング トラップ、通常の def がより適切な選択である場合。

記事を読む →
人工知能

AIエージェントとは何ですか?シンプルなエージェント ループを実行できる仕組み

AIエージェントとは何ですか?エージェント ループ、ツール、メモリ、ガードレール、実行した小さな Python ループ、実際のリスク、およびシンプルなチャットボットがより良い選択である場合についてのわかりやすいガイドです。

記事を読む →
DevOps

モニタリングと可観測性: ログ、メトリクス、トレースによる本当の違い

モニタリングと可観測性について説明: 既知および未知の障害、ログ、メトリクスとトレース、チェックアウト インシデントのウォークスルー、ゴールデン シグナル、OpenTelemetry、および便利なアラート。

記事を読む →
DevOps

Docker ボリュームとバインド マウント: コンテナ データを正しい方法で保持する

Docker ボリュームとバインド マウントについて説明します。コンテナ データが消える理由、名前付きボリューム、バインド マウント、tmpfs、Compose の例、バックアップ、アクセス許可、およびそれぞれをいつ使用するかについて説明します。

記事を読む →
テスト自動化

TDD と BDD: 主な違い、1 つの機能が両方の方法で構築され、それぞれをいつ使用するか

TDD と BDD は、両方の方法で構築された 1 つの割引機能で説明されています。実行したコードによるレッド-グリーン-リファクタリング、Given-When-Then シナリオ、ツール、トレードオフ、およびそれぞれをいつ使用するかです。

記事を読む →
ソフトウェアテスト

ユーザー受け入れテスト (UAT): プロセス、チェックリスト、および実際の例

ユーザー受け入れテストの説明: 誰が実行するか、QA との違い、7 段階のプロセス、UAT テスト ケース テンプレート、チェックリスト、サインオフ基準、およびよくある間違い。

記事を読む →
データベースとSQL

SQL NULL 値の説明: IS NULL、COALESCE、NULLIF、および回避すべきトラップ

SQL の NULL 値について、実行したクエリで説明しました。3 つの値のロジック、IS NULL、COALESCE、NULLIF、集計、結合、並べ替えでの NULL の扱い方、およびそれが密かに引き起こすバグです。

記事を読む →
データベースとSQL

SQL CASE WHEN ステートメント: 構文、実際の例、およびよくある間違い

SQL CASE WHEN では、単純な検索フォーム、条件順序、SUM を使用したピボット、COUNT トリック、カスタム並べ替え、更新、回避すべき NULL トラップなど、実行したクエリを使用して説明しました。

記事を読む →
ソフトウェア開発

JWTとは何ですか? JSON Web トークンを実際の例で説明する

JWTとは何ですか? JSON Web トークンについて説明しました。3 つの部分、実行したコード内で構築および改ざんされたトークン、JWT とセッション、ストレージ、リフレッシュ トークン、およびセキュリティ上の間違いです。

記事を読む →
ソフトウェア開発

JavaScript イベントループの説明: コールスタック、マイクロタスク、タイマーと例

JavaScript イベント ループについて、実行したコードで説明しました。コール スタック、タスク キュー、マイクロタスク キュー、setTimeout 0 が即時ではない理由、ブロッキング、スターベーション、およびインタビュー クイズです。

記事を読む →
ソフトウェア開発

Python ジェネレーターと収量の説明: 実際の例でメモリを節約する

Python ジェネレーターと Yield について、実行したコードを使用して説明します。一時停止と再開の方法、メモリ節約の測定、パイプライン、無限シーケンス、Yield from、send、および一般的なトラップについて説明します。

記事を読む →
人工知能

埋め込みとは何ですか?ベクトルとコサインの類似度を簡単に説明

埋め込みとは何ですか?ベクトル、コサイン類似度、セマンティック検索に関する平易なガイド。私たちが実行した小さな例、一般的な使用法、モデルの選択、既知の制限が含まれています。

記事を読む →
DevOps

Blue-Green デプロイメントと Canary デプロイメント: 違い、トレードオフ、および選択方法

ブルー グリーン デプロイメントとカナリア デプロイメントについて説明: それぞれの仕組み、コスト、リスクとロールバック、テストした安定したユーザー バケット化、データベース移行、ローリング アップデート、および選択方法。

記事を読む →
テスト自動化

不安定なテスト: 問題の原因とそれを永久に修正する方法

不安定なテストについては、私たちが実行したデモを使用して説明しました。主な原因、確認および診断する方法、タイミングの適切な修正、共有された状態と日付、隔離プロセスなどです。

記事を読む →
ソフトウェアテスト

負荷テストとストレス テスト: 違い、メトリクス、および k6 の例

ロード テストとストレス テストについて説明します。それぞれが何を証明するか、スパイク テストとソーク テスト、重要な指標、平均値が誤解を招く理由、K6 の例、テストの計画方法について説明します。

記事を読む →
ソフトウェアテスト

テスト ケースとテスト シナリオ: 主な違い、例、およびそれぞれをいつ使用するか

テスト ケースとテスト シナリオの説明: 明確な定義、並べて表、シナリオからケースへの 1 つのパスワード リセット機能、テンプレート、およびそれぞれをいつ使用するか。

記事を読む →
データベースとSQL

SQL クエリの最適化: 実行プランを読み取り、タイミングを考慮して遅いクエリを修正

SQL クエリの最適化は 100 万行でテストされています。実行プランの読み取り、適切なインデックスの追加、検索対象外のフィルターの修正、複合インデックスとキーセットのページネーションの使用。

記事を読む →
データベースとSQL

SQL UNION と UNION ALL: 違い、例、テストされたパフォーマンス

SQL UNION と UNION ALL について、実行したクエリで説明しました。重複、両方に従うルール、実際のデータのバグ、測定されたパフォーマンス、INTERSECT と EXCEPT、およびそれぞれをいつ使用するかについて説明します。

記事を読む →
ソフトウェア開発

JavaScript Fetch API チュートリアル: GET、POST、エラー処理、タイムアウト

ローカル サーバーに対してテストされた JavaScript Fetch API チュートリアル: GET と POST、404 がスローされない理由、再利用可能なヘルパー、クエリ文字列、タイムアウト、CORS、およびよくある間違い。

記事を読む →
ソフトウェア開発

Python ファイル処理: 読み取り、書き込み、CSV、JSON、パスライブラリと例

Python のファイル処理について、実行したコードで説明します。オープン モード、大きいファイルの読み取り、CSV、JSON、パスライブラリ、バイナリ ファイル、安全な書き込み、エラー処理、およびよくある間違いについて説明します。

記事を読む →
ソフトウェア開発

Python のクラスとオブジェクト: 実際の例を含む OOP チュートリアル

Python のクラスとオブジェクトについて、実行したコードとともに説明します: __init__、メソッド、クラスとインスタンスの属性、継承、プロパティ、ダンダー メソッド、データクラス、およびよくある間違い。

記事を読む →
人工知能

大規模言語モデルとは何ですか? LLM の仕組みを誇大広告なしで説明

大規模言語モデルとは何ですか? LLM は、トークン、エンベディング、アテンション、トレーニング、温度およびコンテキスト ウィンドウ、小さな次の単語のデモ、実際の制限など、平易な言葉で説明されています。

記事を読む →
DevOps

初心者のための Linux コマンド: 例を含む基本ターミナル ガイド

初心者向けの Linux コマンド。ナビゲーション、ファイル、ログの表示、grep、パイプ、権限、プロセス、アーカイブなどのタスク別にグループ化されており、実用的なログ分析の例も含まれています。

記事を読む →
テスト自動化

Selenium と Playwright: 主な違い、コードの比較、どちらを選択するか

Selenium と Playwright の比較: アーキテクチャ、待機、ブラウザと言語のサポート、デバッグ、両方のツールでの同じテスト、移行のアドバイスと選択方法。

記事を読む →
ソフトウェアテスト

等価性分割: テスト設計手法を実際の例で説明

等価性パーティション化について説明しました。有効なパーティションと無効なパーティションを見つける方法、年齢、パスワード、クーポンに関する実際の例、実行したテスト、境界と組み合わせる理由。

記事を読む →
ソフトウェアテスト

ソフトウェアテストにおける重大度と優先度: 相違点、マトリックス、および実際の例

ソフトウェア テストにおける重大度と優先度について説明します。明確な定義、例を含む 4 方向のマトリックス、レベル スケール、それぞれの設定者、バグ トリアージの実行方法。

記事を読む →
データベースとSQL

SQL サブクエリのチュートリアル: 型、相関サブクエリ、および EXISTS と例

実行したクエリを含む SQL サブクエリのチュートリアル: スカラー、IN、FROM、SELECT サブクエリ、相関サブクエリ、EXISTS、NOT IN NULL トラップ、サブクエリ対 JOIN 対 CTE。

記事を読む →
データベースとSQL

SQL トランザクションと ACID の説明: COMMIT、ROLLBACK、分離レベル

SQL トランザクションと ACID について、実行した銀行振込で説明しました。COMMIT、ROLLBACK、セーブポイント、ロック、分離レベル、ダーティ リード、デッドロック、ベスト プラクティスについて説明します。

記事を読む →
ソフトウェア開発

Git mergeとrebaseの違い:例と使い分け

Git mergeとrebaseの違いを、実際のログ出力、比較表、rebaseの黄金律、安全なチームワークフローで解説します。

記事を読む →
ソフトウェア開発

Pythonのリスト内包表記:構文・例・使うべきでない場面

Pythonのリスト内包表記を解説:構文、フィルタ、if-else、ネストしたループ、実測した処理時間、そして通常のforループの方が良い場面。

記事を読む →
データベースとSQL

SQL JOINを例で解説(Inner・Left・Right・Full)

サンプルのテーブルとクエリでSQL JOINを順に解説。INNER、LEFT、RIGHT、FULL、CROSS、SELFに加え、よくある間違いとパフォーマンスのコツも紹介します。

記事を読む →