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


153

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 ).

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

답변:


172

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

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

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

vs.

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

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

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


나도이 질문을 생각했다. 고마워요, 나는 이런 식으로 생각하지 않았습니다.
wheaties 2009

1
또한 테스트 당 하나의 어설 션의 "규칙"을 지원하고 BDD 스타일 사양과 더 쉽게 혼합됩니다.
Nils Wloka 2009

2
그리고 어설 션 메커니즘을 조건 (더 나은 오류 메시지로 연결)에서 분리합니다.
SteveD

2
아무도 거의 단일 assertTrue을 사용하지 않으므로 예제는 타당하지 않습니다 &&. 두 가지 조건으로 분리하면 JUnit에서도 문제의 원인이 분명해집니다. 나를 잘못 이해하지 마라. 나는 당신에게 동의합니다. 나는 단지 당신의 모범을 싫어합니다.
maaartinus

48

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

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

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


39

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

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를 사용하십시오.


4
페스트가 죽은 것 같지만 포크 AssertJ는 매우 살아 있습니다.
Amedee Van Gasse

18

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

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

assertEqual(1, foo);

--또는--

assertThat(foo, is(1));

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

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


... 그리고 Eclipse가 어설 션 실패를보고 할 때 전통적인 assertThat ()에서 인수를 잘못된 방식으로 넣으면 오류가 의미가 없습니다.
Sridhar Sarnobat

9

예:

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로 텍스트를 쓸 수도 있습니다 ...


1
더 좋은 방법 assertThat은 자동으로받는 메시지가 "예상 : (<1>보다 큰 값과 <3>보다 작은 값)"과 같은 정보를 제공하기 때문에 문자열 인수를 생략하는 것입니다 .
MatrixFrog

네, 맞아요. 내 답변을 편집합니다. 원래 나는 (Matcher).와 (Matcher)를 모두 사용하고 싶지만 작동하지 않았습니다.
MartinL

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

자연어에 가깝습니다.

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

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


4
좋아 그리고…? 그것이 왜 좋은지 설명함으로써 당신의 주장을지지하는 것이 좋습니다.
Nathan Tuggy

0

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

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.