4

具体的には、このシナリオが心配です:

1) 1 つのメンバー変数とコピー関数を持つクラスを作成します。

class MyClass
{
private:
int grade;

public:
void setGrade(int x) { grade = x; }
int getGrade() { return grade; }
void copyFrom(const MyClass* src) { grade = src->grade; }
}

2) これらの行に沿って単体テストを作成します

void testCopyFrom()
{
MyClass mc1;
MyClass mc2;
mc1.setGrade(-347);
mc2.setGrade(10);
mc2.copyFrom(&mc1);
TS_ASSERT_EQUALS(mc2.getGrade(), -347);
}

3) 数か月後、2 番目のメンバー変数を追加します。

private:
int grade, extra;

そして、(ご想像のとおりです!) それに応じて copyFrom() 関数を更新するのを忘れています。

この場合、単体テストは誤って success を報告します。テストの設計に何か問題がありましたか?

4

2 に答える 2

5

TDD は最初にテストすることを意味します。コードを変更する前に、コードを更新する必要があります。この場合、追加することにした場合extraは、API のテストを追加する必要がありますextra(これまでのところ、何もありませんが、必要になる場合もありますgetExtra())。その後、テストを追加および修正するときに、と を追加する必要があることsetExtra()に注意してgetExtra()くださいtestCopyFrom()

この段階では、テストはほとんど失敗します ()。その後、実際のコードを実行して合格するようにし ()、最後にクリーンアップとリファクタリングを行い、テストをガイドとして使用して、壊れているかどうかを確認します。なんでも。

red-green-refactor の詳細をお読みください— それTDD です。

getGrade()また、次のようconstにマークする必要があります。

int getGrade() const { return grade; }

これはconst、インスタンスへのポインターまたは参照を使用しMyClassてグレードを取得できることを意味します。

于 2012-05-18T01:14:48.537 に答える
0

この特定のケースでは、テストは間違っていません。設定したとおりに実行 (およびレポート) しています単体テストは、ターゲットの実装を気にしません。つまり、2 番目のプロパティを追加したかどうかは気にしません。

これ拾うのは、コピー後に新しいプロパティをチェックする別のテストを書くことです。テストが実際に伝えてcopyFromいることは、copyFrom 操作を呼び出したときに成功したように見えるということです。コピー操作の範囲については保証されないため、別のテストを作成する必要があります。

別の見方をすると、関数を呼び出して例外をスローせずに返されたからといって、それ自体は成功または失敗を示すものではなく、呼び出し元に返されただけです。成功/失敗の表示を返す (または失敗時に例外をスローする)ように を変更するかcopyFrom、成功または失敗を判断するためにターゲットの環境をさらに検査する必要があります。

于 2012-05-18T01:03:30.630 に答える