Junit4: BiMatcher階層を導入します

作成日 2018年02月08日  ·  9コメント  ·  ソース: junit-team/junit4

優れた機能は、 BiMatcher階層を導入することです( org.hamcrest.Matcherアナログですが、2つの引数を消費します)。 あるいは、標準のComparatorをこの目的に使用することもできます。 BiPredicateも使用できます(これにより、JUnitがJava-8に関連付けられますが、すぐに使用できるAND / OR / NOTロジックが追加されます)。
それ以降のすべてのコードに関する注意事項:

  • BiMatcherBiPredicate 、およびComparator名前は同じ意味で使用されます。
  • すべてのコードは最終的なものではなく、単なる一般的な考え方です。

Assertクラスに追加する主なメソッド:

  • assertThat(T expected, T actual, Comparator<T> biMatcher);
  • assertThat(String message, T expected, T actual, Comparator<T> biMatcher); (おそらく必要ありません。以下を参照してください)。
  • 複数のassertArray()メソッド(以下を参照)。

動機:オブジェクトのバッチに対して多くの同様のチェックを行う必要がある場合があります。 既存の機能はそれを可能にしますが、多くの追加コード(ループと条件)があります。 Comparatorすると、より少ないコードでより高い柔軟性で実行できます。

実際の例(私が実際にこの機能について考え始めたところ):配列内のすべてのオブジェクトが同じか同じでないかをテストする必要があります(ブールフラグによって異なります)。

現在のJUnit機能では、次のようになります。
短い:

for (int i = 0; i < elements.length - 1; i++) {
  if (checkSame) { // Same
    assertSame("elements must be the same.", elements[i], elements[i + 1]);
  } else { // Not same
    assertNotSame("elements must be not the same.", elements[i], elements[i + 1]);
  }
}

パフォーマンスの向上(ただし、テストでのパフォーマンスを気にする人):

if (checkSame) { // Same
  for (int i = 0; i < elements.length - 1; i++) {
    assertSame("elements must be the same.", elements[i], elements[i + 1]);
  }
else { // Not same
  for (int i = 0; i < elements.length - 1; i++) {
    assertNotSame("elements must be not the same.", elements[i], elements[i + 1]);
  }
}

また、我々は独自実装することができますComparator使いassertTrue()/assertFalse() 、しかし、(私たちはラムダを使用しない限り)コンパレータを作成するためのコードも大きなものとなります。

新しいアプローチでは、次のように、コードは私にとってはるかに短く、きれいに見えます。

Comparator<T> comparator = checkSame ? BiMatchers.same() : BiMatchers.notSame();
String message = checkSame ? "elements must be the same." : "elements must be not the same.";
for (int i = 0; i < elements.length - 1; i++) {
  assertThat(message, elements[i], elements[i + 1], comparator);
}

さらに短くするために、オプションのmessageプロパティを使用してComparatorMessagedComparator拡張できるため、JUnitはそこから何らかの方法でそれを取得します。 このような:

MessagedComparator<T> comparator = checkSame ? BiMatchers.same("elements must be the same.") : BiMatchers.notSame("elements must be not the same.");
for (int i = 0; i < elements.length - 1; i++) {
  assertThat(message, elements[i], elements[i + 1], comparator);
}

結果は非常に広範囲に及びます。
1) Assertクラスは、多くのコードなしで任意の標準または独自のコンパレータを使用できるため、一般的に非常に柔軟性があります。
2)以前の結果として、ラムダをより簡単に使用して、任意の条件を注入できます。
3)追加のロジックカスケード(AND、OR、NOT)をすぐに追加できます( org.hamcrest.CoreMatchers似たもの)。 現在、新しいミニ機能には、新しいメソッドが必要です。たとえば、 assertNotSame()横にあるassertSame()などです。または、 assertTrue()/assertFalse()メソッドが必要です。
4) Assertクラス全体を統一された形式にリファクタリングできます。 ほんの一例:

public static void assertSame(String message, Object expected, Object actual) {
  assertThat(message, expected, actual, BiMatchers.same())
}

public static void assertThat(String message, T expected, T actual, Comparator<T> biMatcher) {
...
}

またはすでに述べたように:

public static void assertSame(String message, Object expected, Object actual) {
  assertThat(expected, actual, BiMatchers.same(message))
}

public static void assertThat(T expected, T actual, MessagedComparator<T> biMatcher) {
...
}

5) assertArray()メソッドを追加できます(したがって、古いメソッドはリファクタリングされます)。 例えば:

public static void assertArrayEquals(boolean[] expecteds, boolean[] actuals) {
  assertArray(expecteds, actuals, BiMatchers.equals());
}

public static void assertArray(boolean[] expecteds, boolean[] actuals, Comparator<Boolean>) {
...
}

したがって、たとえば、2つの配列のすべての要素が次のように簡単にチェックできます。

Assert.assertArray(array1, array2, BiMatchers.same());

また、配列の長さやその他のチェックを個別に制御することもできます。 擬似コード:

Assert.assertArray(array1, array2, and(sameLength(), same()));

全てのコメント9件

この問題を提起していただきありがとうございます。

JUnit4.xがアサーションDSLを追加しないことをお勧めします。 DSLを正しく柔軟にすることは非常に困難であり、TruthやFestのような優れたサードパーティのアサーションフレームワークがある場合、JUnitでDSLに時間と労力を費やすことが理にかなっているとは思えません。

また、Java8を必要とする機能はhttp://github.com/junit-team/junit5にアクセスする必要があり

@gitIvanB問題を開いていただきありがとうございます。 @kcooneyと同様に、これも

@ kcooney@ marcphilipp 、ヒントをありがとう。 ここでは、アサーションライブラリの使用がベストプラクティスのようです。
もう1つの質問。 経験則として、 Assertは非推奨(または推奨されない)であると使用できますか? 特に、JUnit-4からJUnit-5への将来のアップグレードの可能性を念頭に置いてください。

@gitIvanB質問は少し明確ではありません。 junit4に対して開発する場合は、 org.junit.Assert 、junit5に対して開発する場合は、 org.junit.jupiter.api.Assertions

推奨されるアプローチは、すべての行にAssert.がないように、メソッドを静的にインポートすることです。

@gitIvanB junit.framework.Assertは絶対に使用しないでください。ただし、 org.junit.Assertで問題ありません。 アップグレードを行う場合、IDEを使用してJUnit4をJUnitJupiterアサーションに変換できます(IDEAはすでにサポートしています)。 最大の違いは、オプションのメッセージパラメータがJUnit 4で最初に来て、Jupiterで最後になることです。 または、今すぐ別のアサーションライブラリを使用して、VintageからJupiterに移行するときにそれを使用し続けることもできます。

@ panchenko@ marcphilippつまり、私が理解したように、JUnit-4のorg.junit.Assertは封印されており、新しいメソッドで強化されることはありません。 JUnit-5では、 org.junit.jupiter.api.Assertionsorg.junit.Assert代わりとして)または何らかのアサーションライブラリを使用する必要があります。
JUnit-5を学ぶには少し時間が必要ですが、一見したところorg.junit.jupiter.api.Assertionsは、そのアプローチが一般的にorg.junit.Assert似ているように見えます。 したがって、JUnit-5用に同様のチケットを作成する必要がある可能性が高いです:) JUnit-5は、本格的なアサーションを提供するか、アサーションライブラリに完全に委任する必要があると思います。

@gitIvanB JUnitの哲学は、JavaでJavaのテストを作成するための優れた拡張可能なフレームワークを提供することです。 拡張可能なフレームワークであるため、他のオープンソースプロジェクトがフレームワークを拡張したり、JUnitで使用できる豊富なテストライブラリを提供したりすることがよくあります。

アサーションの場合、拡張可能な方法で、より豊富なアサーションのセットを提供するプロジェクトがいくつかあります。
たとえば、Google Truth(https://github.com/google/truth)、FEST(https://github.com/alexruiz/fest-assert-2.x)、AssertJ(http:// joel- costigliola.github.io/assertj/)およびHamcrest(http://hamcrest.org/JavaHamcrest/)。

驚くべきアサーションライブラリがたくさんあるので、 org.junit.Assert新機能のリクエストを受け入れるのをためらっています。 私はそれが凍結しているとは考えません(私はjunit.framework.Assert凍結していると考えますが)。 実際、4.13ではassertThrowsが導入されます。 しかし、これらのプロジェクトほど豊富なアサーションのセットを持つことは決してないので、基本を提供することに抵抗はありません。

言い換えれば、これらのプロジェクトの使用と維持を中心に熱狂的なコミュニティが形成されているので、私たちはそれらを受け入れてサポートする必要があると思います。

JUnit5について話すことはできませんが、元の開発者は、アサーションメソッドの適切な基盤がなければ次世代のJUnitをリリースできないと感じていたと思います(または、新しいフレームワークが機能していることを確認するための最良の方法のように感じました。洗練されたのは、JUnit5を使用してJUnit5をテストすることでした。 新しいプログラミング手法により、基本的なアサーションAPIがKent、Erich、Davidとはどのように見えるかについて異なる決定を下すようになったため、いくつかの違いがわかります。 しかし、JUnitでは、HamcrestやTruthのような拡張可能なDSLのように豊富なアサーションのセットを目にすることはないでしょう。

どのような種類の変更を検討するかは、JUnit5チームに任せます。 あなたが強く感じるなら
あなたが提案している方法は、良いテストを書くための基礎として重要です。そこで問題を自由に作成してください。

JUnit 5(当時は「JUnitLambda」というコードネーム)の作業を開始したときに、達成したいことの範囲について話し合いました。 新しい種類のアサーションライブラリを作成することは、範囲内にないことが明示的に決定されました。

または、 JUnit5ユーザーガイドに記載されているように:

JUnit Jupiterが提供するアサーション機能は多くのテストシナリオに十分ですが、より多くのパワーとマッチャーなどの追加機能が必要または必要になる場合があります。 このような場合、JUnitチームは、AssertJ、Hamcrest、Truthなどのサードパーティのアサーションライブラリの使用を推奨します。したがって、開発者は自由に選択したアサーションライブラリを使用できます。

したがって、これも凍結されていませんが、目標はJUnit 4と同様です。つまり、ユーザーが開始するための基本的なアサーションのセットを提供することです。 独自の単体テストにもAssertJを使用しています。

このページは役に立ちましたか?
0 / 5 - 0 評価