1.概要



ハムクレスト


は、Javaエコシステムの単体テストに使用される有名なフレームワークです。これはJUnitにバンドルされていて、簡単に言うと、アサーションを作成するために既存の述語(マッチャークラスと呼ばれる)を使用します。

このチュートリアルでは、Hamcrest APIを探求し、それを利用してより直感的で直感的なソフトウェアのユニットテストを書く方法を学習します。

2. Hamcrestセットアップ


pom.xml

ファイルに次の依存関係を追加することで、mavenで

Hamcrest

を使用できます。

<dependency>
    <groupId>org.hamcrest</groupId>
    <artifactId>hamcrest-all</artifactId>
    <version>1.3</version>
</dependency>

このライブラリの最新版は常にhttps://search.maven.org/classic/#search%7Cga%7C1%7Ca%3A%22hamcrest-all%22[here]にあります。

3.テスト例

  • Hamcrest ** は

    junit

    や他のテストフレームワークでアサーションを作るためによく使われます。具体的には、

    junit

    の多数の

    assert

    メソッドを使用する代わりに、適切なマッチャーを含むAPIの単一の

    assertThat

    ステートメントのみを使用します。

大文字と小文字を区別せずに2つの

__String

__の等価性をテストする例を見てみましょう。これにより、

Hamcrest

がテスト方法にどのように適合するかについて明確なアイデアが得られます。

public class StringMatcherTest {

    @Test
    public void given2Strings__whenEqual__thenCorrect() {
        String a = "foo";
        String b = "FOO";
        assertThat(a, equalToIgnoringCase(b));
    }
}

以下のセクションでは、他のいくつかの一般的なマッチャー

Hamcrest

が提供するものを見ていきます。

4.

Object

マッチャー

  • Hamcrest ** は任意のJavaオブジェクトに対してアサーションを行うためのマッチャーを提供します。


Object



toString

メソッドが指定された

String

を返すことをアサートするには、

@Test
public void givenBean__whenToStringReturnsRequiredString__thenCorrect(){
    Person person=new Person("Barrack", "Washington");
    String str=person.toString();
    assertThat(person,hasToString(str));
}

あるクラスが別のクラスのサブクラスであることも確認できます。

@Test
public void given2Classes__whenOneInheritsFromOther__thenCorrect(){
        assertThat(Cat.class,typeCompatibleWith(Animal.class));
    }
}

5.ビーンマッチャー

私たちは

Hamcrest

のBeanマッチャーを使ってJava Beanのプロパティを調べることができます。

次の

Person

Beanを想定してください。

public class Person {
    String name;
    String address;

    public Person(String personName, String personAddress) {
        name = personName;
        address = personAddress;
    }
}

Beanが

name

というプロパティを持っているかどうかを調べることができます。

@Test
public void givenBean__whenHasValue__thenCorrect() {
    Person person = new Person("Baeldung", 25);
    assertThat(person, hasProperty("name"));
}


Person



address

プロパティを持っていて、ニューヨークに初期化されているかどうかも確認できます。

@Test
public void givenBean__whenHasCorrectValue__thenCorrect() {
    Person person = new Person("Baeldung", "New York");
    assertThat(person, hasProperty("address", equalTo("New York")));
}

2つの

Person

オブジェクトが同じ値で構成されているかどうかも確認できます。

@Test
public void given2Beans__whenHavingSameValues__thenCorrect() {
    Person person1 = new Person("Baeldung", "New York");
    Person person2 = new Person("Baeldung", "New York");
    assertThat(person1, samePropertyValuesAs(person2));
}

6.

Collection

マッチャー

  • Hamcrest ** は

    __Collection

    __sを検査するためのマッチャーを提供します。


Collection

が空かどうか調べる簡単な確認:

@Test
public void givenCollection__whenEmpty__thenCorrect() {
    List<String> emptyList = new ArrayList<>();
    assertThat(emptyList, empty());
}

__Collectionのサイズを確認するには:

@Test
public void givenAList__whenChecksSize__thenCorrect() {
    List<String> hamcrestMatchers = Arrays.asList(
      "collections", "beans", "text", "number");
    assertThat(hamcrestMatchers, hasSize(4));
}

これを使用して、配列に必要なサイズがあることを表明することもできます。

@Test
public void givenArray__whenChecksSize__thenCorrect() {
    String[]hamcrestMatchers = { "collections", "beans", "text", "number" };
    assertThat(hamcrestMatchers, arrayWithSize(4));
}

順序に関係なく、

Collection

に特定のメンバーが含まれているかどうかを確認するには、次の手順を実行します。

@Test
public void givenAListAndValues__whenChecksListForGivenValues__thenCorrect() {
    List<String> hamcrestMatchers = Arrays.asList(
      "collections", "beans", "text", "number");
    assertThat(hamcrestMatchers,
    containsInAnyOrder("beans", "text", "collections", "number"));
}


Collection

メンバーが指定された順序であることをさらに主張するには、

@Test
public void givenAListAndValues__whenChecksListForGivenValuesWithOrder__thenCorrect() {
    List<String> hamcrestMatchers = Arrays.asList(
      "collections", "beans", "text", "number");
    assertThat(hamcrestMatchers,
    contains("collections", "beans", "text", "number"));
}

配列に与えられた要素が1つあるかどうかを調べる

@Test
public void givenArrayAndValue__whenValueFoundInArray__thenCorrect() {
    String[]hamcrestMatchers = { "collections", "beans", "text", "number" };
    assertThat(hamcrestMatchers, hasItemInArray("text"));
}

同じテストに別のマッチャーを使うこともできます。

@Test
public void givenValueAndArray__whenValueIsOneOfArrayElements__thenCorrect() {
    String[]hamcrestMatchers = { "collections", "beans", "text", "number" };
    assertThat("text", isOneOf(hamcrestMatchers));
}

それでもやはり、以下のように別のマッチャーでも同じことができます。

@Test
public void givenValueAndArray__whenValueFoundInArray__thenCorrect() {
    String[]array = new String[]{ "collections", "beans", "text",
      "number" };
    assertThat("beans", isIn(array));
}

順序に関係なく、配列に与えられた要素が含まれているかどうかも確認できます。

@Test
public void givenArrayAndValues__whenValuesFoundInArray__thenCorrect() {
    String[]hamcrestMatchers = { "collections", "beans", "text", "number" };
      assertThat(hamcrestMatchers,
    arrayContainingInAnyOrder("beans", "collections", "number",
      "text"));
}

配列に与えられた要素が与えられた順序で含まれているかどうかをチェックするには:

@Test
public void givenArrayAndValues__whenValuesFoundInArrayInOrder__thenCorrect() {
    String[]hamcrestMatchers = { "collections", "beans", "text", "number" };
    assertThat(hamcrestMatchers,
    arrayContaining("collections", "beans", "text", "number"));
}


Collection



Mapの場合、

それぞれの関数で次のようなマッチャーを使用できます。

特定のキーが含まれているかどうかを確認するには

@Test
public void givenMapAndKey__whenKeyFoundInMap__thenCorrect() {
    Map<String, String> map = new HashMap<>();
    map.put("blogname", "baeldung");
    assertThat(map, hasKey("blogname"));
}

そして与えられた値:

@Test
public void givenMapAndValue__whenValueFoundInMap__thenCorrect() {
    Map<String, String> map = new HashMap<>();
    map.put("blogname", "baeldung");
    assertThat(map, hasValue("baeldung"));
}

そして最後に与えられたエントリ(キー、値):

@Test
public void givenMapAndEntry__whenEntryFoundInMap__thenCorrect() {
    Map<String, String> map = new HashMap<>();
    map.put("blogname", "baeldung");
    assertThat(map, hasEntry("blogname", "baeldung"));
}

7.

Number

マッチャー


Number

matcherは

Number

クラスの変数に対してアサーションを実行するために使用されます。


greaterThan

状態を確認するには

@Test
public void givenAnInteger__whenGreaterThan0__thenCorrect() {
    assertThat(1, greaterThan(0));
}


greaterThan

または

equalTo

状態を確認するには

@Test
public void givenAnInteger__whenGreaterThanOrEqTo5__thenCorrect() {
    assertThat(5, greaterThanOrEqualTo(5));
}


lessThan

状態を確認するには

@Test
public void givenAnInteger__whenLessThan0__thenCorrect() {
    assertThat(-1, lessThan(0));
}


lessThan

または

equalTo

状態を確認するには

@Test
public void givenAnInteger__whenLessThanOrEqTo5__thenCorrect() {
    assertThat(-1, lessThanOrEqualTo(5));
}


closeTo

状態を確認するには

@Test
public void givenADouble__whenCloseTo__thenCorrect() {
    assertThat(1.2, closeTo(1, 0.5));
}

最後のマッチャー__closeToに注意を払いましょう。最初の引数であるオペランドは、ターゲットが比較されるもので、2番目の引数はオペランドからの許容偏差です。偏差またはオペランド偏差の場合、テストは成功します。

8.テキストマッチャー


__String

__sのアサーションは、

Hamcrest

のテキストマッチャーによって、より簡単に、よりきれいにそしてより直感的になります。このセクションでそれらを見ていきます。


String

が空かどうかを確認するには

@Test
public void givenString__whenEmpty__thenCorrect() {
    String str = "";
    assertThat(str, isEmptyString());
}


String

が空か

null

かを確認するには、次のようにします。

@Test
public void givenString__whenEmptyOrNull__thenCorrect() {
    String str = null;
    assertThat(str, isEmptyOrNullString());
}

空白を無視して2つの

__String

__が等しいかどうかをチェックするには、次のようにします。

@Test
public void given2Strings__whenEqualRegardlessWhiteSpace__thenCorrect() {
    String str1 = "text";
    String str2 = " text ";
    assertThat(str1, equalToIgnoringWhiteSpace(str2));
}

与えられた

String

の中に、与えられた順序で1つ以上のサブストリングが存在するかどうかを調べることもできます。

@Test
public void givenString__whenContainsGivenSubstring__thenCorrect() {
    String str = "calligraphy";
    assertThat(str, stringContainsInOrder(Arrays.asList("call", "graph")));
}

最後に、大文字と小文字を区別せずに2つの

__String

__が等しいことを確認できます。

@Test
 public void given2Strings__whenEqual__thenCorrect() {
    String a = "foo";
    String b = "FOO";
    assertThat(a, equalToIgnoringCase(b));
}

9.コアAPI

  • Hamcrest ** コアAPIは、サードパーティのフレームワークプロバイダによって使用されることになっています。しかし、それは私達に私達のユニットテストをもっと読みやすくするために私達にいくつかの素晴らしい構造と同様に簡単に使用することができるいくつかのコアマッチャーを提供します。

マッチャーの

is

構文による読みやすさ:

@Test
public void given2Strings__whenIsEqualRegardlessWhiteSpace__thenCorrect() {
    String str1 = "text";
    String str2 = " text ";
    assertThat(str1, is(equalToIgnoringWhiteSpace(str2)));
}

単純データ型の

is

構文

@Test
public void given2Strings__whenIsEqual__thenCorrect() {
    String str1 = "text";
    String str2 = "text";
    assertThat(str1, is(str2));
}

マッチャーの

not

構文による否定:

@Test
public void given2Strings__whenIsNotEqualRegardlessWhiteSpace__thenCorrect() {
    String str1 = "text";
    String str2 = " texts ";
    assertThat(str1, not(equalToIgnoringWhiteSpace(str2)));
}

単純なデータ型の

not

構文

@Test
public void given2Strings__whenNotEqual__thenCorrect() {
    String str1 = "text";
    String str2 = "texts";
    assertThat(str1, not(str2));
}


String

に指定のサブストリングが含まれているかどうかを確認してください。

@Test
public void givenAStrings__whenContainsAnotherGivenString__thenCorrect() {
    String str1 = "calligraphy";
    String str2 = "call";
    assertThat(str1, containsString(str2));
}


String

が与えられた部分文字列で始まっているかどうかをチェックします。

@Test
public void givenAString__whenStartsWithAnotherGivenString__thenCorrect() {
    String str1 = "calligraphy";
    String str2 = "call";
    assertThat(str1, startsWith(str2));
}


String

が与えられた部分文字列で終わっているか確認してください。

@Test
public void givenAString__whenEndsWithAnotherGivenString__thenCorrect() {
    String str1 = "calligraphy";
    String str2 = "phy";
    assertThat(str1, endsWith(str2));
}

2つの

__Object

__が同じインスタンスであるかどうかを確認してください。

@Test
public void given2Objects__whenSameInstance__thenCorrect() {
    Cat cat=new Cat();
    assertThat(cat, sameInstance(cat));
}


Object

が特定のクラスのインスタンスであるかどうかを確認します。

@Test
public void givenAnObject__whenInstanceOfGivenClass__thenCorrect() {
    Cat cat=new Cat();
    assertThat(cat, instanceOf(Cat.class));
}


Collection

のすべてのメンバが条件を満たしているかどうかを確認します。

@Test
public void givenList__whenEachElementGreaterThan0__thenCorrect() {
    List<Integer> list = Arrays.asList(1, 2, 3);
    int baseCase = 0;
    assertThat(list, everyItem(greaterThan(baseCase)));
}


String



null

ではないことを確認してください。

@Test
public void givenString__whenNotNull__thenCorrect() {
    String str = "notnull";
    assertThat(str, notNullValue());
}

条件をまとめて、targetがいずれかの条件を満たすと、テストはパスします。論理ORと同様です。

@Test
public void givenString__whenMeetsAnyOfGivenConditions__thenCorrect() {
    String str = "calligraphy";
    String start = "call";
    String end = "foo";
    assertThat(str, anyOf(startsWith(start), containsString(end)));
}

条件をまとめて、論理ANDと同様に、ターゲットがすべての条件を満たす場合にのみテストに合格します。

@Test
public void givenString__whenMeetsAllOfGivenConditions__thenCorrect() {
    String str = "calligraphy";
    String start = "call";
    String end = "phy";
    assertThat(str, allOf(startsWith(start), endsWith(end)));
}

10.カスタムマッチャー


TypeSafeMatcher

を拡張することで、独自のマッチャーを定義できます。このセクションでは、ターゲットが正の整数の場合にのみテストがパスするようにするカスタムマッチャーを作成します。

public class IsPositiveInteger extends TypeSafeMatcher<Integer> {

    public void describeTo(Description description) {
        description.appendText("a positive integer");
    }

    @Factory
    public static Matcher<Integer> isAPositiveInteger() {
        return new IsPositiveInteger();
    }

    @Override
    protected boolean matchesSafely(Integer integer) {
        return integer > 0;
    }

}

ターゲットが実際に正の整数であることを確認する

matchSafely

メソッドと、テストが失敗した場合に失敗メッセージを生成する

describeTo

メソッドを実装するだけです。

これが私たちの新しいカスタムマッチャーを使ったテストです。

@Test
public void givenInteger__whenAPositiveValue__thenCorrect() {
    int num = 1;
    assertThat(num, isAPositiveInteger());
}

そして、これは正でない整数を渡したので得られる失敗メッセージです。

java.lang.AssertionError: Expected: a positive integer but: was <-1>

11.結論

このチュートリアルでは、Hamcrest API ** を調べ、それを使ってより良く、より保守可能な単体テストを書く方法を学びました。

これらすべての例とコードスニペットの完全な実装は私のhttps://github.com/eugenp/tutorials/tree/master/guava/src/test/java/org/baeldung/hamcrest[Hamcrest github project]にあります** – これはEclipseベースのプロジェクトなので、そのままインポートして実行するのは簡単なはずです。