テストごとに1つのアサーションのみが必要な場合。複数の入力をテストする方法は?


15

私はいくつかのテストケースを構築しようとしていますが、テストケースごとのアサーションの数を制限するようにしてください。

したがって、私の質問は、複数の入力を持つ関数をテストするための最善の方法は何ですか?たとえば、ユーザーからの文字列を解析し、分数を返す関数があります。文字列は、週、時間、日、および分数"5w6h2d1m"w, h, d, m対応する形式で指定できます。

「テストルールごとに1つのアサーション」に従う場合、入力のバリエーションごとに複数のテストを作成する必要がありますか?それはばかげているように見えるので、代わりに私は次のようなものを持っています:

self.assertEqual(parse_date('5m'), 5)
self.assertEqual(parse_date('5h'), 300)
self.assertEqual(parse_date('5d') ,7200)
self.assertEqual(parse_date('1d4h20m'), 1700)

1つのテストケース。もっと良い方法はありますか?


そのための最良の方法は、パラメーターを使用することです(一部のフレームワークはこの機能をサポートしていますが、すべてのフレームワークがサポートする必要があります)。この方法では、単一の動作をテストしていますが、多くのテストケースを考慮し、エラーが発生した場合にどのパラメーター値がエラーを引き起こしたかを確認できます
Kemoda

回答:


23

テスト「ルール」ごとに1つのアサートを表示するより実用的な方法は、単一のテストでのアサートを単一の概念に対応させることです。

この方法では、単一のテストで単一のコンセプトをテストしています。あなたの場合、入力文字列が単一の日付で正しく解析されるかどうか。

ケースバイケースで判断して、複数のアサーションで単一のコンセプトをテストするか、多くのテストで単一のアサーションを使用する方が良いかどうかを確認する必要があります。

テストがメソッドのさまざまな失敗ポイントを強調表示できるようにしつつ、テストをより明確にし、繰り返しを少なくするオプションを選択します。テストをデバッグして問題点を特定するのではなく、テストが正確に失敗したときに明確にする必要があります。


17

テストライブラリに大きく依存します。C#ライブラリNUnitでは、次のようなことができます。

[TestCase('5m', 5)]
[TestCase('5h', 300)]
[TestCase('5d', 7200)]
[TestCase('1d4h20m', 1700)]
public void ParseDateTest(inputString, expectedMinutes)
{
    Assert.That(parse_date(inputString), Is.EqualTo(expectedMinutes));
}

TestNGの持つJavaでは、あなたは@dataProvider方法持っている
Kemoda

それが最高のソリューションです。ほとんどすべての言語で、テストをパラメーター化できます。Javaの場合:@ParameterizedJunitParamsZohhak
piotrek

3

ええ、入力のバリエーションごとに複数のテストを行います。

テストガイドラインごとに1つのアサーションの主な目標は、(理想的には)1つのエラーが1つのテストの失敗につながり、その逆も同じであるため、失敗したものを正確に把握することです。次に、1つの非常に正確なテストを使用して根本原因をデバッグし、検証できます。1つのアサートでこれを破ることができ、複数のアサートで大丈夫です。この特定のシナリオでは、各サフィックスと順序付けのいくつかの組み合わせに対してテストを行います。

テストを分離することが利点である理由が明確になれば幸いです。問題が発生したときにデバッグに費やす時間を短縮できます。ここで、テストが失敗する可能性が非常に低く、テストを追跡するオーバーヘッドが小さいと本当に確信している場合は、実装時間を節約するために一度にすべてをテストするのが理にかなっています。

しかし、歴史は、コードの読み取り/使用を犠牲にしてコードを書く時間を少し節約すること決して価値がないことを示しています。したがって、ガイドライン。


1

純粋主義者は、入力の異なる値に対するアサーションは、テストクラス内の個別のテストメソッドに配置する必要があると言うでしょう。その理由の1つは、テストUIによっては、個々のアサーション間よりも個々のテストの失敗を区別する方が簡単な場合が多いため、失敗の原因をより迅速に特定できる可能性があるためです。

JUnitを使用してテストする場合、assert *メソッドのバージョンを初期String引数とともに使用して、同じテストメソッド内でアサーションを別のアサーションと区別することにより、これを回避できます。

self.assertEqual("just minutes", parse_date('5m'), 5)
self.assertEqual("just hours", parse_date('5h'), 300)
self.assertEqual("just days", ('5d') ,7200)
self.assertEqual("days, hours, minutes", parse_date('1d4h20m'), 1700)
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.