2016년 7월 27일 수요일

What is Hamcrest?

현재 JUnit4.4 , 배포된 JAR 살펴보면 무언가 다른 점을 알아차릴 것이다.: org.juit* 패키지에 더하여 재밌는 이름의 org.hamcrest.* 패키지가 두드러져 보인다. 최근에 Hamcrest 의존성이 강해지는프로젝트를 보았을 것이다. 그리고 나는 그것이 무엇인지 궁금해 것이라고 확신한다. 이제 그것에 대해 알아보자.
Introduction
현재 hamcrest 대한 구글 서치는 Hamcrest 대해 언급하는 Google Code 페이지로 당신을 인도한다:
거기서는 matcher object  라이브러리를 제공한다(이는 또한 constraints predicates 로도 알려져 있다 'match' 룰은 선언적으로 정의될 있도록 하며 다른 프레임워크에서도 사용될 있다.
당신이 이미 Matcher 무엇인지 알고 있다면 이는 매우 유용한 설명이다. 그러나 초심자에게는 많은 설명이 필요하다. 그래서 Hamcrest 무엇을 한단 말인가?

그것을 생각해낼 좋은 방법은 정규 표현식이 텍스트에 대한 것이라면 Hamcrest 객체에대한 것이라는 것이다. Hamcrest 객체에 대한 pattern-matching 수행하는 DSL 효과적으로 정의하는 여러 메소드를 제공한다. 무슨 용도로 사용할 있을까? 정규표현식과 같이 가능성은 무궁무진하다. 최근에 몇몇 참신한 사용으로 나타났다그러나 대부분의 주요 사용분야는 테스팅 영역이다. 그러한 이유로 Junit 의존적이다.
A Brief History
Hamcrest는 JMock 라이브러리로 부터 발전하였다. 거기서 실행상황을 대신하는 Mock object에게 발생할 것으로 예상되는 것들에 대한 제약사항들을 명세하는데 사용되었다. 더욱 유창한 assertion syntax 당신이 주요 constraint calls 하나의 assertThat 메소드로 함께 엮어주도록 하는 constraints로부터 발생했다. 이후 Jmock 저자, Joe Waines constraint API Hamrest 불리는 라이브러리로 리팩토링 하였다. 그리고 사람들은 다른 다양한 것들을 위해 테스팅 프레임워크 외부에서 그것을 사용하는데 흥미를 갖게 되었다. 또한 몇몇 무리에서는 "predicates" 부르는 constraints "matcher" 부르기 시작했다. 의존성을 요청하지 않는것으로 악명 높았고 개념적으로 작게 유지되었던 다른 테스팅 프레임워크와 심지어 Junit마저도 재빠르게 움직였다.
이들 모두 오래되고 친근한 org.jnit.Assert.* static mehods들은 여전히 Junit 4.4+ 유지하고 있다. 특정한 측면에서 그것들은 유용하지만 대체로 유행에 뒤쳐져 있다. Junit assertThat 메소드는 당신이 특별한 assert 메소드를 사용하여 assertion 생성할 있도록 Matcher 전달한다. assertThat 유용할까? 몇가지의 이유가 있다.그것은 assertion 명세하는 제너릭한 방식을 제공할 뿐만 아니라 프레임워크가 당신이 시도하는 assert 무엇인지 명확하게 알게해 준다. 이것은 프레임워크가 당신을 위한 실패 메시지를 생성하게 한다.
Fail message… win?
failer 메시지를 위한 스트링을 파라미터로받는 assertX 메소드의 오버라이딩 버전을 사용하는 것은 좋은 아이디어였다. 예를 들어:
assertTrue(blackbeard.getOccupations().contains("pirate") ||
  blackbeard.getOccupations().contains(
"captain"),
 
"Expected Blackbeard to be a pirate or a captain");
만약 Blackbeard 어린시절 버전을 나타내는 객체를 전달하면 우리는 다음과 같은 실패 메시지를 기대하게될 것이다:
java.lang.AssertionError: Expected Blackbeard to be a pirate or a captain
이들 메시지를 제공하는 것은 좋은 아이디어였다. 그러나 반복적이고, 지루하고, 쓸모없는 것들을 피할 수는 없다. assertThat 함게 Hamcrest matcher 사용하면 당신은 의미있는 실패 메시지를 생성할 만큼 스마트한 Junit 만날 있다: Hamcrest matcher 사용하여 당신의 assertion 사용하는 것은 프레임워크가 충분한 문백 정보를 가지고 당신을 도와주는 의미있는 실패메시지를 생성하게 해준다. 그리고 당신의 실패한 assertions 이해할 추가적인 여분의 스트링을 유지할 필요가 없다 :
assertThat(blackbeard.getOccupations(), anyOf(hasItem("pirate"),hasItem("captain")));

그닥 개선이 이루진 것처럼 보이지 않을 있다. 그러나 나쁘게 읽히지는 않는다. 우리는 여분의 스트링 파라미터를 버릴 있다. 이것이 실패했을 때 우리는 매우 간단한 실패 메시지를 무료로 만날 것이다:

java.lang.AssertionError:
  Expected: (a collection containing
"pirate" or a collection containing "captain")
    got:  [] >
Note: I'm using JUnit 4.6 - 당신에 작동하는 문구를 만나기 위해 몇몇 static imports 필요하다.
import static org.junit.Assert.*;
import static org.hamcrest.CoreMatchers.*;
import static org.junit.matchers.JUnitMatchers.*;

나는 이것을 동작시킬 없었지만, DSL Junit에서 잘읽을 있도록 여전히 할일이 있다; 다음과 같이:
assertThat(blackbeard.getOccupations(), either(hasItem("pirate")).or(hasItem("captain")));
Other Cool Stuff
Getting Reused
TestNG, JMock그리고 다른 테스팅 프레임워크가 Hamcrest 제공한 것으로부터 확실히 이득을 얻을 것이다. 그러나 우리는 이것이 다른 많은 곳에서 사용되는 것을 보게될 것이다. matcher 어떻게 동작하는지 보는 것에 관심을 갖게 것이고 그것은 비교적 생성하기 쉽다는 견해가 유지될 것이다. 바라건데 프레임워크는 프로젝트에 유용한 matcher 제공할 것이다.
Chaining
matcher method chaining idiom 이용하여 DSL 구현되었기 때문에 조합하거나 확장하는 것이 매우 쉽다.
Matchers For Regular Expressions
블로그 포스트를 가져오면서 이전에 포스트를 발견했다: the Hamcrest Text Patterns project. 이것의 목표는 matcher 사용해 Hamcrest 스타일의 정규 표현식을 작성해서 가독성 높은 정규 표현식 코드를 생상하도록 하는 것이다. 예를 들어 프로젝트에서 발견한 다음 테스트를 보아라:
PatternMatcher emailAddressMatcher = new PatternMatcher(sequence(
  capture(
"user", oneOrMore(anyCharacter())),
 
"@",
  capture(
"host", oneOrMore(anyCharacter()))
));

PatternMatcher mailToURLMatcher =
new PatternMatcher(sequence(
  capture(
"scheme", text("mailto")),
 
":",
  capture(
"email", emailAddressMatcher)
));

assertThat(
"mailto:npryce@users.sf.net", matchesPattern(mailToURLMatcher));
capture(user, host, scheme, email) 대해 친숙한 이름을 제공함으로써 어떤 것이 매칭하고 매칭하지 않는지에 대한 프로그래밍측면에서 의미있는 메시지를 제공할 있다.
Many more uses
Matchers 적용하는 많은 방식을 보기 위해 UsesOfHamcrest 체크해라.
컬렉션을 처리하기, 로깅에 사용하기 위한 필터 생성하기
Conclusion
당신이 Hamcrest 자세히 살펴보기 원한다. 왜냐면 그만한 가치가 있고 우리를 가독성이 높은 코드를 작성하도록 가이드해 줄것이다.
I hope you choose to take a closer look at Hamcrest because it brings a big bang-for-the-buck and has the potential to guide us to more human-friendly, readable code.
Further Reading


댓글 없음: