[java] 왜 전통적인 assertXXX ()-메소드 대신 Hamcrest-Matcher와 assertThat ()을 사용해야합니까?

Assert 클래스 JavaDoc의 예제를 볼 때

assertThat("Help! Integers don't work", 0, is(1)); // fails:
// failure message:
// Help! Integers don't work
// expected: is <1> 
// got value: <0>
assertThat("Zero is one", 0, is(not(1))) // passes

나는 큰 이점을 보지 못한다 assertEquals( 0, 1 ).

구조가 더 복잡해 지지만 더 많은 이점이 있다면 메시지에 좋을 것입니다. 가독성?



답변

assertFoo의도가 정확히 일치 하는 경우에는 큰 이점이 없습니다 . 이 경우 그들은 거의 동일하게 동작합니다.

그러나 다소 복잡한 검사를 수행하면 이점이 더 눈에 띄게됩니다.

assertTrue(foo.contains("someValue") && foo.contains("anotherValue"));

vs.

assertThat(foo, hasItems("someValue", "anotherValue"));

어느 것이 더 읽기 쉬운 지 논의 할 수 있지만 일단 어설 션에 실패하면에서 좋은 오류 메시지를받을 수 assertThat있지만 에서 최소한의 정보 만 얻을 수 있습니다 assertTrue.

assertThat어설 션이 무엇인지, 대신 무엇을 얻었는지 알려줍니다. assertTrue당신이 당신이 false예상했던 곳을 가지고 있다고 말할 것입니다 true.


답변

버전 4.4 용 JUnit 릴리스 노트 (소개)에는 다음과 같은 네 가지 장점이 있습니다.

  • 보다 읽기 쉽고 타이핑 가능 :이 구문을 사용하면 동사, 오브젝트, 주제를 사용하는 assertEquals 대신 주제, 동사, 오브젝트 (어설 션 “x is 3”)로 생각할 수 있습니다 (어설 션 “equals 3 x”)
  • 조합 : 모든 matcher 문은 무효화되거나 ( not (s) , 결합 되거나 (s .. (t) ), 콜렉션에 매핑 되거나 () 각각의 사용자 정의 조합 ( afterFiveSeconds )에 사용될 수 있습니다. )
  • 읽을 수있는 오류 메시지 (…)
  • 커스텀 매처. Matcher 인터페이스를 직접 구현하면 사용자 지정 어설 ​​션에 대한 위의 모든 이점을 얻을 수 있습니다.

새로운 구문을 만든 사람의 더 자세한 논증 : here .


답변

기본적으로 코드의 가독성높이기위한 것입니다 .

hamcrest 외에도 fest 주장을 사용할 수 있습니다 . 그들은이 몇 가지 장점 hamcrest 이상 등을 :

몇 가지 예

import static org.fest.assertions.api.Assertions.*;

// common assertions
assertThat(yoda).isInstanceOf(Jedi.class);
assertThat(frodo.getName()).isEqualTo("Frodo");
assertThat(frodo).isNotEqualTo(sauron);
assertThat(frodo).isIn(fellowshipOfTheRing);
assertThat(sauron).isNotIn(fellowshipOfTheRing);

// String specific assertions
assertThat(frodo.getName()).startsWith("Fro").endsWith("do")
                           .isEqualToIgnoringCase("frodo");

// collection specific assertions
assertThat(fellowshipOfTheRing).hasSize(9)
                               .contains(frodo, sam)
                               .excludes(sauron);


// map specific assertions (One ring and elves ring bearers initialized before)
assertThat(ringBearers).hasSize(4)
                       .includes(entry(Ring.oneRing, frodo), entry(Ring.nenya, galadriel))
                       .excludes(entry(Ring.oneRing, aragorn));

2016 년 10 월 17 일 업데이트

페스트는 더 이상 활성화되지 않습니다 . 대신 AssertJ를 사용하십시오.


답변

매우 기본적인 타당성은 새로운 구문을 망치기가 어렵다는 것입니다.

테스트 후 특정 값 foo가 1이어야한다고 가정하십시오.

assertEqual(1, foo);

–또는–

assertThat(foo, is(1));

첫 번째 방법을 사용하면 올바른 순서를 잊어 버리고 뒤로 입력하는 것이 매우 쉽습니다. 그런 다음 테스트가 1을 기대하고 2를 얻었으므로 테스트에 실패했다고 말하는 것이 아니라 메시지가 거꾸로 나타납니다. 테스트에 통과 할 때는 문제가되지 않지만 테스트에 실패하면 혼동 될 수 있습니다.

두 번째 버전에서는이 실수를하는 것이 거의 불가능합니다.


답변

예:

assertThat(5 , allOf(greaterThan(1),lessThan(3)));
//  java.lang.AssertionError:
//  Expected: (a value greater than <1> and a value less than <3>)
//       got: <5>
assertTrue("Number not between 1 and 3!", 1 < 5 && 5 < 3);
//  java.lang.AssertionError: Number not between 1 and 3!
  1. 테스트를보다 구체적으로 만들 수 있습니다
  2. 테스트가 실패하면 더 자세한 예외가 발생합니다.
  3. 시험을보다 쉽게 ​​읽을 수 있습니다

btw : assertXXX로 텍스트를 쓸 수도 있습니다 …


답변

assertThat(frodo.getName()).isEqualTo("Frodo");

자연어에 가깝습니다.

쉽게 읽고 분석하기 쉬운 코드. 프로그래머는 새로운 코드를 작성하는 것보다 코드를 분석하는 데 더 많은 시간을 소비합니다. 따라서 코드를 쉽게 분석 할 수 있다면 개발자의 생산성이 높아집니다.

PS 코드는 잘 작성된 책이어야합니다. 자체 문서화 된 코드.


답변

assertEquals
보다 assertThat의 장점이 있습니다.- 1) 더 읽기 쉬움
2) 실패에 대한 추가 정보
3) 런타임 오류가 아닌 컴파일 시간 오류
4) 테스트 조건 작성의 유연성
5) 이식성-hamcrest를 사용하는 경우 jUnit을 사용할 수 있습니다 또는 기본 프레임 워크로 TestNG.