7

次の疑似コードを検討してください。成績が合格かどうかを判断するように設計されています。

class Student:
    int grade

    boolean IsStudentPassing():
        return grade >= MIN_PASSING_GRADE


...

// In another file
constant int MIN_PASSING_GRADE = 70

の単体テストを書いている場合IsStudentPassing、定数値を使用できます。

ensure that IsStudentPassing is false when grade is MIN_PASSING_GRADE - 1
ensure that IsStudentPassing is true when grade is MIN_PASSING_GRADE

または、値を手動で選択することもできます。

ensure that IsStudentPassing is false when grade is 69
ensure that IsStudentPassing is true when grade is 70

2 番目のアプローチでは、変更があった場合、テストを書き直す必要がありMIN_PASSING_GRADEます。MIN_PASSING_GRADE最初のアプローチはより柔軟ですが、正しい値を持つことに依存しています。

どちらのアプローチを優先するかは完全にはわかりませんが、一般的にはケースバイケースで選択します。一方では、それMIN_PASSING_GRADEが正気であることを保証することは、別のテストによって処理されるべきです。一方で、おそらく「単体」テストがコードベースの他の多くの場所に触れていることを心配しています。

これは不自然な例ですが、実際のプログラムでも同様の状況がよく発生します。それらに対処するための最良のアプローチは何ですか?

4

3 に答える 3

1

好みにより、実際に合格点を構成するものの気まぐれから単体テストが分離されるように、独自の工夫の 1 つを使用して「定数」値を注入します。これがどの程度簡単かは、プログラミング言語によって異なります。簡単にする言語のこのコードを検討してください。

use MooseX::Declare;
class Student {
    has grade => (
        is => 'ro', isa => 'Num', required => 1,
    );

    method min_passing_grade {
        return MIN_PASSING_GRADE;
    )

    method is_student_passing () {
        return $self->grade >= $self->min_passing_grade
    }
}

class t::Student {
    use Test::Sweet;
    use Test::MockObject::Extends;

    test correctly_determines_student_is_passing () {
        my $student = $self->_make_student($self->_passing_grade);

        ok($student->is_student_passing);
    }

    method _make_student (Num $grade) {
        my $student = Test::MockObject::Extends->new(
            $student->new(grade => $grade)
        );
        # Here's the important line:
        $student->set_always(
            min_passing_grade => $self->_passing_grade
        );
        return $student;
    }

    method _passing_grade () { 40 }

    test correctly_determines_student_is_failing () {
        my $student = $self->_make_student($self->_passing_grade - 1);

        ok(not $student->is_student_passing);
    }
}

さて、これが Perl であり、モンキー パッチの適用が非常に簡単になります (上記の「重要な行」はStudent::min_passing_grade実行時の実装を置き換えます)。また、questino の値を定数にデフォルト設定する属性にすることも、単体テストで使用する特別なバージョンの定数ファイルを提供することもできます。

非常に強力なパフォーマンス要件がないため、値を実際の定数にするよりも、上記を選択します。単体テストから必要な値を挿入する方法が見つからない場合にのみ、一般的に定義された定数に到達します。ほとんどの状況で行うべきではないと私が思うのは、このテストで定数を複製することです。これは、結局のところ、のロジックStudent正しいことを確認するためのものです。

于 2012-09-10T20:36:02.667 に答える
1

定数をまったく使用せず、渡されるインターフェイスのプロパティにすることをお勧めします。これが依存性注入の仕組みです (これが TDD を支援します)。

次に、テスト (またはモック) フレームワークを使用してテストを生成します。注意:おそらく、ターゲット値の両側でいくつかの値をテストしたいと思うでしょう。また、データ型の境界をテストして、オーバーフロー/アンダーフロー エラーをトラップする必要があります。

于 2012-09-12T14:36:43.223 に答える
0

私は過去に常に操作を試みてきましたが、単体テストではすべての可能な境界条件をチェックする必要があります/特定の機能または全体の機能のサブセットをストレステストする必要があり、より大きな回帰スイートでは、ビジネス要件からの妥当性についてプログラム全体をテストする必要があります側。

したがって、あなたの例では、最初のテストは単体テストにあり、2番目のテストは回帰にあります。

しかし、私はこの業界では比較的新参者ですが、自分が正しい方向に進んでいないかどうかを知りたいと思っています。

于 2012-09-10T18:17:29.233 に答える