31

時折、何もアサートしない単体テストに出くわします。私が今朝遭遇した特定の例は、条件が満たされたときにログ ファイルが書き込まれることをテストすることでした。エラーがスローされなければ、テストは成功したと想定されていました。

私は個人的にこれに問題はありませんが、アサーションが関連付けられていない単体テストを作成するのは少し「コードの匂い」のようです。

これについて人々の意見がどうなっているのか疑問に思っていますか?

4

15 に答える 15

23

これは非常に最小限のテストであり、そのように文書化する必要があります。実行時に爆発しないことを確認するだけです。このようなテストの最悪の部分は、誤った安心感を与えることです。コード カバレッジは上がりますが、それは幻想です。非常に悪臭。

于 2008-09-26T02:32:45.193 に答える
20

これはそれを行うための公式の方法です:

// Act
Exception ex = Record.Exception(() => someCode());

// Assert
Assert.Null(ex);
于 2008-09-26T02:39:07.127 に答える
15

アサーションがない場合、それはテストではありません。

怠け者になるのはやめましょう。アサーションをそこに入れる方法を理解するのに少し時間がかかるかもしれませんが、期待どおりの動作をしたことを知るだけの価値があります。

于 2008-09-26T03:32:11.493 に答える
8

そのようなテストはにおいがします。ファイルが書き込まれたこと、少なくとも変更時刻がおそらく更新されたことを確認する必要があります。

私はこのように書かれたかなりの数のテストを見て、結局何もテストしませんでした。つまり、コードは機能しませんでしたが、それも爆発しませんでした。

テスト対象のコードが例外をスローしないという明示的な要件があり、この事実を明示的に呼び出したい場合(要件ドキュメントとしてテスト)、次のようにします。

try
{
  unitUnderTest.DoWork()
}
catch
{
  Assert.Fail("code should never throw exceptions but failed with ...")
}

...しかし、これはまだ少し臭いがします。おそらくそれはネガティブなことを証明しようとしているからでしょう。

于 2008-09-26T02:40:44.190 に答える
8

これらはスモークテストとして知られており、一般的です。それらは基本的な健全性チェックです。しかし、それらが唯一の種類のテストであってはなりません。別のテストでは、何らかの検証が必要です。

于 2008-09-26T03:24:36.207 に答える
4

特に代替手段がまったくテストされていない場合、これは優れた実用的な解決策になる可能性があります。

問題は、呼び出されたすべての関数がノーオペレーションの場合にテストがパスすることです。しかし、副作用が期待したものであることを確認できない場合もあります。理想的な世界では、すべてのテストの小切手を書くのに十分な時間があります...しかし、私はそこに住んでいません。

私がこのパターンを使用したもう 1 つの場所は、一部のパフォーマンス テストを単体テストに埋め込むことです。これは、ビルドごとにテストを実行する簡単な方法だったからです。テストは何も主張しませんが、テストにかかった時間を測定してログに記録します。

于 2008-09-26T02:35:35.793 に答える
3

ある意味では、コードが例外をスローしないという暗黙のアサーションを行っています。もちろん、実際にファイルを取得して適切な行を見つける方がより価値がありますが、何もないよりは何かがあると思います。

于 2008-09-26T02:29:53.843 に答える
2

一般に、これは統合テストで発生することがわかります。何かが成功して完了したという事実だけで十分です。この場合、私はそれでクールです。

単体テストで何度も何度も見たら、テストが実際にどれほど役立つか興味があると思います。

編集: OP によって与えられた例では、いくつかのテスト可能な結果 (ログファイルの結果) があるため、エラーがスローされなかった場合、それが機能したと仮定するのは面倒です。

于 2008-09-26T02:30:37.443 に答える
1

私たちはいつもこれを行っています。JMockを使用して依存関係をモックしているので、ある意味でJMockフレームワークがアサーションを実行していると思います...しかし、これは次のようになります。テストしたいコントローラーがあります。

Class Controller {
  private Validator validator;

  public void control(){
    validator.validate;
  }

  public setValidator(Validator validator){ this.validator = validator; }
}

さて、Controllerをテストするとき、独自のテストがあるため、Validatorをテストしたくありません。したがって、validateを呼び出すことを確認するために、JMockを使用してテストを行います。

public void testControlShouldCallValidate(){
  mockValidator.expects(once()).method("validate");
  controller.control;
}

そして、それだけです。表示する「アサーション」はありませんが、controlを呼び出し、「validate」メソッドが呼び出されない場合、JMockフレームワークは例外をスローします(「予期されるメソッドが呼び出されない」など)。

私たちはいたるところにそれらを持っています。基本的にアサーションを設定してから、テストされたメソッドを呼び出すため、少し逆になります。

于 2008-09-26T02:48:30.303 に答える
1

私は以前にこのようなことを見たことがありますが、これは単にコード カバレッジの数値を上げるために行われたと思います。おそらく、コードの動作を実際にテストしているわけではありません。いずれにせよ、明確にするためにそれ(意図)をテストで文書化する必要があることに同意します。

于 2008-09-26T03:22:37.850 に答える
1

テストの名前はこれを文書化する必要があります。

void TestLogDoesNotThrowException(void) {
    log("blah blah");
}

ログがアサーションなしで書き込まれたかどうかをテストでどのように確認しますか?

于 2009-07-01T19:20:50.023 に答える
1

選択したユニット テスト フレームワーク (NUnit) を使用して、コードの特定の部分へのエントリ ポイントとして機能するメソッドを構築することがあります。これらのメソッドは、コードのサブセットのパフォーマンス、メモリ消費、およびリソース消費をプロファイリングするのに役立ちます。

これらのメソッドは ( [Test]属性でマークされていても) ユニット テストではないことは明らかであり、ソース管理にチェックインされると、常に無視されるようにフラグが付けられ、明示的に文書化されます。

また、これらのメソッドを Visual Studio デバッガーのエントリ ポイントとして使用することもあります。Resharper を使用して、テストに直接ステップインし、次にデバッグするコードにステップインします。これらのメソッドは、ソース管理まで到達しないか、独自のアサートを取得します。

私の「実際の」単体テストは、通常の TDD サイクル中に構築され、直接ではありませんが、常に何かをアサートします。アサーションがモック フレームワークの一部である場合もあれば、同様のアサーションを 1 つのメソッドにリファクタリングできる場合もあります。これらのリファクタリングされたメソッドの名前は、わかりやすいように常に「Assert」というプレフィックスで始まります。

于 2008-10-01T07:36:38.843 に答える
0

テストは常に何かを主張する必要があります。そうでない場合、何を証明し、コードが機能するという証拠を一貫して再現するにはどうすればよいですか?

于 2008-09-26T02:46:49.793 に答える
0

正しくログに記録していることを検証する単体テストを書いたことがないことを認めなければなりません。しかし、私はそれについて考え、JUnit と Log4J を使用してそれを行う方法についてのこの議論に出くわしました。あまりきれいではありませんが、うまくいきそうです。

于 2008-09-26T02:35:43.767 に答える