ユニットテストケースはどのように作成しますか?


14

時には、他の開発者が書いたコードの単体テストケースを書くことになります。開発者が何をしようとしているか(ビジネスの部分)が本当にわからない場合があり、テストケースを操作して緑色の線を取得するだけです。これらのことは業界では普通ですか?

通常の傾向は何ですか?開発者は自分で書いたコードの単体テストケースを書くことになっていますか?


2
「ディント」?「dint」とはどういう意味ですか?
-S.Lott

回答:


12

このブログ投稿「グレートユニットテストの作成:ベストプラクティスとワーストプラクティス」をお読みください。

しかし、ウェブには無数の人がいます。

あなたの質問に直接答えて...

  1. 「通常の傾向」-これは場所によって異なる可能性があると思いますが、私にとって普通のことは他の人にとっては奇妙かもしれません。
  2. (私のオプションでは)コードを記述する開発者は、理想的にはコードの前にテストを記述するTDDのようなメソッドを使用して、テストを記述する必要があります。しかし、他の人はここで異なる方法とアイデアを持っているかもしれません!

そして、あなたの質問を書いたテストの記述方法はまったく間違っています!!


9

このアプローチにより、単体テストは価値がなくなります。

一部の実際のアクションが意図したとおりに機能しない場合は、ユニットテストを失敗させる必要があります。そうしないと、テストするコードの前にテストを書くことさえできれば、機能していない煙アラームを持っているようなものです。


8
これはまったく正しくありません。むしろ、理想的な世界では真実です。しかし、残念ながら、私たちはしばしばそれから遠く離れています。テストや仕様のないレガシーコード、および特定のコードが正確に何をするのかを正確に伝えることができる人がいないことを考慮してください(これ既存のプロジェクトの大部分で現実です)。この場合でも、コードの現在の状態をロックし、将来のリファクタリング、バグ修正、または拡張機能で何かを壊さないようにするために、単体テストを書く価値があります。
ペテルトレック

2
また、「テストするコードのにテストを書く」ことを意味していたと思いますか?
ペテルトレック

@ピーター、言葉遣いが間違っていた-あなたはそれを正解しました。しかし、テストを書くことに決めた場合は、役に立つようにする必要があります。それがテストであると言ってやみくもにコードを呼び出すことは-私の意見では-テストではありません

ørn、あなたが私たちの単体テストで意味のある主張をしなければならないということを意味するなら、テストされたコードが実際に私たちが思うことをすることを確認するために、私は完全に同意します。
ペテルトレック

3

関数が何をするのかわからない場合、そのための単体テストを書くことはできません。あなたが知っているすべてのために、それはそれが期待されることさえしません。最初に何をすべきかを知る必要があります。次に、テストを記述します。


3

現実の世界では、他の誰かのコードの単体テストを書くことはまったく普通です。確かに、元の開発者はすでにこれを行っているはずですが、多くの場合、これが行われなかったレガシーコードを受け取ります。ちなみに、そのレガシーコードが数十年前に遠く、遠くの銀河から来たのか、同僚が先週チェックしたのか、今日書いたのかは関係ありません。レガシーコードはテストなしのコードです

自問してください:なぜ単体テストを書くのですか?グリーン化は明らかに目的を達成するための単なる手段であり、最終的な目標はテスト対象のコードに関する主張を証明または反証することです。

浮動小数点数の平方根を計算するメソッドがあるとします。Javaでは、インターフェースは次のように定義します。

public double squareRoot(double number);

実装を書いたかどうか、他の誰かが書いたかどうかは関係ありません。squareRootのいくつかのプロパティをアサートする必要があります。

  1. sqrt(4.0)のような単純なルートを返すことができること
  2. sqrt(2.0)のような実際のルートを妥当な精度で見つけることができること
  3. sqrt(0.0)が0.0であることがわかります
  4. 負の数が与えられた場合、つまりsqrt(-1.0)でIllegalArgumentExceptionがスローされること

したがって、これらを個別のテストとして書き始めます。

@Test
public void canFindSimpleRoot() {
  assertEquals(2, squareRoot(4), epsilon);
}

エラー:このテストは既に失敗しています:

java.lang.AssertionError: Use assertEquals(expected, actual, delta) to compare floating-point numbers

浮動小数点演算を忘れました。OK、あなたは紹介double epsilon=0.01して行きます:

@Test
public void canFindSimpleRootToEpsilonPrecision() {
  assertEquals(2, squareRoot(4), epsilon);
}

そして、他のテストを追加します:最後に

@Test
@ExpectedException(IllegalArgumentException.class)
public void throwsExceptionOnNegativeInput() {
  assertEquals(-1, squareRoot(-1), epsilon);
}

おっと、再び:

java.lang.AssertionError: expected:<-1.0> but was:<NaN>

テストする必要があります。

@Test
public void returnsNaNOnNegativeInput() {
  assertEquals(Double.NaN, squareRoot(-1), epsilon);
}

ここで何をしましたか?メソッドの動作についていくつかの仮定から始めて、すべてが真実ではないことがわかりました。次に、テストスイートGreenを作成し、修正された仮定に従ってメソッドが動作することを証明します。これで、このコードのクライアントはこの動作に依存できます。誰かが実際のsquareRootの実装を他の何か、たとえばNaNを返す代わりに実際に例外をスローしたものと交換した場合、テストはこれをすぐにキャッチします。

この例は簡単ですが、多くの場合、実際に何をするのかが不明な大きなコードを継承します。その場合、通常はコードの周りにテストハーネスを配置します。コードがどのように動作するかについてのいくつかの基本的な前提から始め、それらの単体テストを作成し、テストします。緑の場合、良い、もっとテストを書いてください。赤の場合、仕様に対して保持できるアサーションが失敗しています。レガシーコードにバグがあるのか​​もしれません。たぶん、この特定の入力についての仕様は不明です。たぶん、あなたは仕様を持っていません。その場合、予期しない動作を文書化するようにテストを書き直してください。

@Test
public void throwsNoExceptionOnNegativeInput() {
  assertNotNull(squareRoot(-1)); // Shouldn't this fail?
}

時間が経つにつれて、コードが実際にどのように動作し、コード化された仕様の一種になるかを文書化するテストハーネスになります。レガシコードを変更したり、他のコードに置き換えたい場合は、テストハーネスを使用して、新しいコードが同じように動作すること、または新しいコードが期待され制御された方法で異なる動作をすることを確認します(たとえば、実際に修正が期待されるバグを修正します)。このハーネスは初日に完全である必要はありません。実際、不完全なハーネスを使用する方が、ハーネスをまったく使用しないよりもほとんど常に優れています。ハーネスがあると、クライアントコードをより簡単に記述できるようになり、何かを変更したときにどこで壊れるのか、最終的にどこで壊れたのかがわかります。

フォームの必須フィールドに入力するのと同じように、ユニットテストを書く必要があるという考え方から抜け出そうとする必要があります。そして、赤い線を緑にするためだけに単体テストを書くべきではありません。単体テストは敵ではなく、単体テストは友人です。


1

テストケース(プリンター用)を書くとき、私は各小さなコンポーネントを考えようとします。たとえば、スキャナーに、どのコマンドが(pjl printer-job-languageで)使用するか、機能のすべてのビットをテストするために何を書くことができるか、と言いましょう....

私は主要なコンポーネントごとにそれをしようとしていますが、ソフトウェアに関してはハードウェアではなく、各メソッド/機能を調べて境界などを確認したいです。


1

ユニットテストを行わない他の開発者と作業している(または他の開発者が作成したコードを管理している)ようです。その場合、テストしているオブジェクトまたはメソッドが何をすべきかを確実に知り、それに対してテストを作成したいと思うと思います。

最初にテストを作成しなかったため、TDDにはなりませんが、状況を改善できます。また、スタブを使用してテスト対象オブジェクトのコピーを作成すると、コードが失敗したときにテストが適切に機能することを確認できます。

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