複数のメソッドを呼び出すメソッドを単体テストする最良の方法は何ですか。次に例を示します。
_modify(string value)
{
if(value.Length > 5) replaceit(value);
else changeit(value);
}
_
この疑似コードには、(現在)replaceit()
またはchangeit()
を呼び出す変更メソッドがあります。私はすでにreplaceit
とchangeit
のテストを作成したので、変更用の新しいテストを作成すると、同じコードセットの99%になります。将来変更される可能性があるので、テストしてみました。
では、既存のテストコードをコピーして貼り付けますか?テストコードを一般的な関数に移動しますか?他のアイデアは?ここでのベストプラクティスはわかりません。
これは、従来の状態ベースのテストと動作ベースのテストのシナリオです。
この途方もなく単純な例では、出力のテストで問題ありません。ただし、ある時点で、実行後の状態の検査が複雑なテストに遭遇します。代わりに、動作を確認します(たとえば、changeitが特定の値で呼び出されたことを確認します)。
その時点で、Rhino.Mocks(.Net)やMockito(Java)などのモックオブジェクトフレームワークを調べて、インターフェイスベースのコードの作成を開始する必要があります。
いくつかのオプションがあります。どちらが最適かは、質問から明確ではない詳細に依存します。
modify
を、無関係なメソッドであるかのようにテストします。利点:ある時点で1つになる可能性があります。replaceit
およびchangeit
の呼び出しはおそらく機能する最も単純な実装です)。 TDDを実践している場合、これは自然に思いつくはずです。replaceit
とchangeit
に定型の回答を含めるか、センシング変数(メソッドが正しい値で呼び出されたかどうかを示す変数)を設定します。利点:テストを単純化する可能性があります(そうでない場合もあります)。replaceit
およびchangeit
メソッドの新しいクラスを、そのクラスのインターフェースを含めて抽出します。 modify
をテストするときに、そのインターフェイスをスタブまたはモックします。利点:どちらの方法でも、設計をよりテストしやすくなる可能性がありますおよび一般的に分離/再利用可能(またはそうでない)。replaceit()
とchangeit()
を個別にすでにテストしている場合、テストする必要があるのはif条件だけです。いくつかの値を使用してmodify()
をテストし、適切な条件(null
およびStrings
の長さが4、5、および6の条件)で適切な関数を呼び出すことを確認します。あなたが与えたサンプルコード)。
modify
をテストしてください。
Modify
は、特定の値を指定すると特定の値を返すことになっています。
それは重要ではない方法変更はその仕事をする-それだけ行うその仕事。
また、将来的にmodify
を変更して別のメソッドを使用する(またはメソッドを使用しない)場合、テストに影響はなく、また、影響しないはずです。
そうは言っても、テストreplaceit' and
changeit`。
優先順に
。
public TestModifyIfValueLength..()
{
string expectedValue = .. ;// literal result of replaceit(value)
Assert.Equals( expectedValue, modify("asd") );
}
仮定
この場合の「テストコード」とは何ですか?結果を設定して確認しますか?もしそうなら、私はそれを別のメソッドにリファクタリングし、各テストからそれを使用します。ただし、この方法のコードを読み取るだけで、テストが行うすべての内容を確認できることには、読みやすさというメリットがあります。
複雑なテスト方法は、最初に、正直に言うとしばしば煩わしくなります-多くの場合、それらは現実的に回避することはできませんが、can簡略化すると、価値がありますそうする。
いいえ、テストコードは99%同じではありません。実際には、replaceit、changeit、modifyがすべて同じ値を返さない限り、ここでは別のテストを行っています。
なぜ難しいのかわかりません。変更メソッドのテストは、約4行の長さである必要があります。基本的な機能を既にテストしていて、この特定のメソッドが壊れないことを確認するだけなので、この関数の2つの可能なコードパスをテストして期待値を返すテストを作成するだけで十分です。
Replaceit()およびchangeit()のテストをすでに作成している場合、変更のテストは、 'value'の値に応じて異なる結果が返されることを確認するだけです。ただし、テストでメソッドのロジックを再実装するだけであり、これは少しばかげています。
この場合、より複雑なロジックになるまで、またはそれ以上の変更が行われるまで、変更をテストしません。テストにとってより重要な別のメソッドによって使用されます。
基本的に2つのテストが必要です。
1)「Quick Brown Fox Jumps!」のような文字列を渡します。 (長さが5を超える)は、値がreplaceit(...)
の影響を受けることを確認します
2) "Foo"(長さが5未満)などの文字列を渡し、値がchangeit(...)
の影響を受けることを確認します
テスト(疑似コード)は次のようになります。
testLongValue() {
string testValue = "A value longer than 5 chars";
string expected = "Replaced!";
string actual = modify(testValue);
assertEqual(expected, actual);
}
testShortValue() {
string testValue = "len4";
string expected = "Changed!";
string actual = modify(testValue);
assertEqual(expected, actual);
}
明らかに、replacit()とchangeit()が何をすることになっているのかを知っていれば、より現実的な例を示すことができますが、これはあなたにアイデアを与えるはずです。元の値参照を返すのではなく変更する場合は、呼び出しが発生した後で実際の値としてtestValueを使用できます。
if (value.length > 5)
のような境界条件をテストするときは、テストデータにvalue
の長さ4
、5
、または6
。
メソッドからfuncを作成し、それらのfuncをモックすることができます。または、仮想メソッドを作成し、Rhinoモックを使用することもできます-部分的なモック、それらの仮想メソッドをモックすることができます。
ジャスティンスタンダードと同じplusnull
を値として渡す(これは、指定したコードスニペットでは明らかに失敗します;))ユニットテストの基本ルールは、「テスト中のメソッド」。そして、別のメソッドを呼び出さないメソッドを持つことは珍しい...