別のテストのサブセットである単体テストを書くことに価値はありますか?


15

少し不自然な例を挙げるために、関数が2つの数値を返し、最初の数値が2番目の数値よりも小さいことをテストしたいとします。

def test_length():
    result = my_function()
    assert len(result) == 2

def test_order()
    a, b = my_function()
    assert a < b

ここで、test_length失敗したtest_order場合も失敗します。を書くのはベストプラクティスtest_lengthですか?それともスキップするのですか?

編集:この状況では、両方のテストは互いにほとんど独立しており、それぞれを単独で実行することも、逆の順序で実行することもできますが、これは問題ではありません。これらの以前の質問はありません

上記の複製です。



2
@ GlenH7-これは別の質問のようです。「あなたは機能を持っている場合は、他のはあるAのコールBとリターン同じ結果が、あなたは両方をテストする必要がありをAしてB」。これは、テスト中の関数ではなく、テストが重複していることに関するものです。(現在は名前が付けられているため、混乱を招きます)。
テラスティン


1
厳密に言えば、これらのテストは実際には重複していません(成功の依存関係はありません)。関数lambda: type('', (), {'__len__': lambda self: 2})()は最初のものを渡しますが、2番目のものは渡しません。
リオリ

1
@ GlenH7:FWIW、私は質問を実際に変更せず、単にgnatセーフにしようとしました;
Doc Brown

回答:


28

価値はありますが、これは少し臭いです。テストが十分に分離されていない(test_order実際に2つのことをテストしているため)か、テストで独断的になっている(同じ論理的なものをテストする2つのテストを作成している)かのいずれかです。

この例では、2つのテストをマージします。はい、複数のアサートがあることを意味します。残念な。あなたはまだ一つのことをテストしています-関数の結果。現実の世界では、2つのチェックを行うことがあります。


マイナーな点が1つ欠けていますが、私はあなたの答えを支持しました。Pythonでは、2番目のテストもmy_function、アサーションなしで正確に2つの値を返さない場合に失敗します。これは、割り当てにより例外が発生するためです。そのため、実際には、同じことをテストするために複数のアサートと2つのチェックを使用する必要はありません。
ドックブラウン

@DocBrown-私は同じくらい仮定しましたが、情報的な理由でランダムな例外/エラーの代わりにアサート失敗の価値があるかどうかを知るためのPythonのエラーメッセージに精通していません。
テラスティン

現在の状況では、エラーメッセージはおそらく十分な情報になると思います。しかし、一般的にはそうではないかもしれません。そのため、このようなケースの一般的なアプローチは、2つのアサートを使用して「マージ」を考えることです。アサートのいずれかを省略することでテストをさらに簡略化できることが判明した場合は、問題ありません。
ドックブラウン

5
@DocBrownアサートで明示的にチェックすることのもう1つの価値は、テストを調べている人にとって、これがテスト自体ではなく、テスト中のコードの障害であることを明らかにすることです。テストで予期しない例外が発生すると、実際に間違っているものを特定するために常に時間を費やす必要があります。
クリスヘイズ

@ChrisHayes:「価値がない」ではなく、「必要がない」と書いた。
Doc Brown

5

テストは明示的に行う必要があります。text_lengthが失敗するとtest_orderが失敗すると完全に推測されるわけではありません。

あなたが投稿したPythonでそれがどうなるかはわかりませんが、len(result)3の場合、最初のは失敗しますが、2番目は合格する可能性があります(Pythonではない場合はJavaScriptのような言語で確かに)。

あなたが言ったように、関数が2つの数値を返し、それらが正しいことをテストする必要があります。2つのテストです。


1
It's not completely inferred that if text_length fails test_order fails-Pythonでは、例外が発生します。
ドックブラウン

問題はの失敗が失敗をtest_length意味する場合についてだと思いますtest_order。Javascriptで記述された同様のテストのペアが、これら2つのpythonテストと同じように動作しないという事実は、まったく無関係です。
ダウッドはモニカを

2
@DavidWallace:覚えておいて、質問は「test_lengthを書くのがベストプラクティスか、それをスキップするか」でした。Javascriptでは、2つのテストを1つにマージしない場合に問題を見逃していないことを確認するために両方のテストが必要です。Pythonでは、1つ目(この回答の最初の文で拒否され、2つ目で「わからない」と宣言されている)を安全に省略できます。正直なところ、良い答えは違って見えます。ただし、実際に良い部分はJavaScriptの言及であるため、この答えに反対票を投じませんでした。
ドックブラウン

4
@DavidWallace:ここはstackoverflow.comではなく、programmers.comであるため、複数の言語に適用できる回答を特定の言語にのみ提供するよりも、IMHOの方が優れています。ただし、特定の言語を参照する場合、その答えは言語について正しいものであり、一部のプロパティを混同しないようにする必要があります。
ドックブラウン

1
問題は「別のテストのサブセットであるテストを書く価値があるか」であり、この答えは「一部の言語では、どちらのテストも他のテストのサブセットではない」と言い、両方のテストが結論に達することですしたがって必要です。「あなたのコードはC ++でまったくコンパイルされず、C ++では関数は1つの値しか返せないので、テストする必要はありません。2つのテストを返すだけです。」 ;-)
スティーブジェソップ

2

ここでの唯一の価値はtest_length、すべてが合格した場合、その存在自体が「長さ」がテストされたことを示すということです。

したがって、これらの両方のテストを行う必要は本当にありません。test_orderただし、名前の変更を検討してくださいtest_length_and_order

ちなみに、私testは少し不器用な名前で始まる名前を使用しています。私はあなたが主張している条件を実際に説明するテスト名の強力な擁護者です。


1
testいぼは、Pythonのテストフレームワークに意味があります。もちろん、あなたはそれが好きかどうかを変える必要はありませんが、誰かがそれを使うのを止めるのに必要な議論の重みを変えます
スティーブジェソップ

@SteveJessopええ、私はそれが必要であることを忘れ続けています。私が少し前にPythonテストを書いていたとき、私はそれらをすべてtest_that_、などで始める習慣になりましたtest_that_return_values_are_in_order。おそらく、テストフレームワークの将来のバージョンでは、この要件を何らかの形で回避できるでしょう。
ダウッドは、モニカ

@DavidWallace:必要に応じてプレフィックス変更できます。
ライライアン

1

それが進化してきたのであれば、これらのテストを別々にしておきます。はいtest_orderはいつでも失敗する可能性test_lengthがありますが、その理由は間違いなくわかります。

また、test_order最初に現れてテスト可能な障害が見つかった場合、結果が2つの値ではない可能性があり、そのチェックをanとして追加しassert、テストの名前を変更しtest_length_and_orderて意味があることに同意します。

返される値のタイプが整数であることも確認する必要がある場合は、この「オムニバス」結果テストにそれを含めます。

しかし、今、あなたはの結果に対する一連のテストを持っていることに注意してくださいmy_function()。これをテストするためのコンテキストが複数ある場合(または複数のパラメーターが存在する可能性が高い場合)、これはからのすべての結果をテストするサブルーチンになりますmy_function()

ただし、ユニットテストを作成するときは、通常、良好な入力および通常の出力とは別にエッジおよび不良ケースをテストします(一部の「ユニット」テストは多くの場合ミニ統合テストであるため)。デバッグせずにもっと情報が欲しいと思うような方法で失敗した場合、別々のテストに分けます。

私はおそらくあなたの独立したテストを開始し、拡大するようtest_lengthtest_length_and_typesして残しtest_order、後者を想定すると、別の「通常の処理」と見られています。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.