티스토리 뷰

tdd

hamcrest matcher 사용하기

zican 2012. 5. 15. 21:47

hamcrest는 matchers의  철자순서를 바꾼말로

매치되는 조건들을 서술적으로 나열할 수 있도록 만들어주는 프레임웍이다.

예를 들면 아래와 같이

assertThat(theBiscuit, equalTo(myBiscuit));

theBiscuit이 myBiscuit과 동일한지를 체크하는 조건을 영어로 말하듯이 기술할 수 있다.

여러개의 기본정의된 matcher(제약사항이나 술어)들이 있고 

이 matcher들을 JUnit과 같은 unit testing framework에서 사용할 수 있다.

공식 홈페이지 내용을 보면 아래와 같다.

Provides a library of matcher objects (also known as constraints or predicates) allowing 'match' rules to be defined declaratively, to be used in other frameworks. Typical scenarios include testing frameworks, mocking libraries and UI validation rules.

Hamcrest has been ported to Java, C++, Objective-C, Python, PHP and Erlang.

Note: Hamcrest it is not a testing library: it just happens that matchers are very useful for testing.

Hamcrest 자체는 테스팅 라이브러리가 아니다. 테스팅할때 유용하게 사용하는 매처들이다. 따라서 JUnit3에서도 쓸수 있고 JUnit4에서도 쓸 수 있다.

http://code.google.com/p/hamcrest/

https://github.com/hamcrest


hamcrest가 나온 배경은 아래 위키페이지 내용처럼 assert문과 관련이 있다.

assert문의 세대별 진화를 보자

"First generation" unit test frameworks provide an 'assert' statement, allowing one to assert during a test that a particular condition must be true. If the condition is false, the test fails. For example:

  assert(x == y);

But this syntax fails to produce a sufficiently good error message if 'x' and 'y' are not equal. It would be better if the error message displayed the value of 'x' and 'y'. To solve this problem, "second generation" unit test frameworks provide a family of assertion statements, which produce better error messages. For example,

  assert_equal(x, y);
  assert_not_equal(x, y);

But this leads to an explosion in the number of assertion macros, as the above set is expanded to support comparisons different from simple equality. So "third generation" unit test frameworks use a library such as Hamcrest to support an 'assert_that' operator that can be combined with 'matcher' objects, leading to syntax like this:

  assert_that(x, equal_to(y))
  assert_that(x, is_not(equal_to(y)))

The benefit is that you still get fluent error messages when the assertion fails, but now you have greater extensibility. It is now possible to define operations that take matchers as arguments and return them as results, leading to a grammar that can generate a huge number of possible matcher expressions from a small number of primitive matchers.

These higher-order matcher operations include logical connectives (and, or and not), and operations for iterating over collections. This results in a rich matcher language which allows complex assertions over collections to be written in a declarative, rather than a procedural, programming style.

http://en.wikipedia.org/wiki/Hamcrest

assert_equal과 같이 assert뒤에조건을 붙이면 assert 매크로가 엄청 많아질 수 있다 이를 해결하기 위해 assert_that이라는 하나의 연산자를 만들어놓고 나머지 세부조건에 대해서는 몇가지의 매처를 조합해서 쓰는 방식으로 처리한다.  

hamcrest matcher들을 사용하면 직관적으로 말로하듯이 매칭조건을 기술 할 수 있으며 이에 따라 assert가 fail난 상황에서  좀 더 자연스러운 에러설명을 해줄 수 있다. 매처들은 다른 매처들을 인자로 받을 수 있기때문에  몇가지 기본적인 매처를 결합함으로 여러가지 복잡한 조건에 표현할 수 있다.

사용예는 아래를 참조하자. 

http://code.google.com/p/hamcrest/wiki/Tutorial

import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.*;

import junit.framework.TestCase;

public class BiscuitTest extends TestCase {
 
public void testEquals() {
   
Biscuit theBiscuit = new Biscuit("Ginger");
   
Biscuit myBiscuit = new Biscuit("Ginger");
    assertThat
(theBiscuit, equalTo(myBiscuit));
 
}
}


assertThat("chocolate chips", theBiscuit.getChocolateChipCount(), equalTo(10));
assertThat
("hazelnuts", theBiscuit.getHazelnutCount(), equalTo(3));
여러개의 assert가 있는 경우 처음인자에 구분하기위한 스트링을 넣을 수 있다.

A tour of common matchers

Hamcrest comes with a library of useful matchers. Here are some of the most important ones.

  • Core
    • anything - always matches, useful if you don't care what the object under test is
    • describedAs - decorator to adding custom failure description
    • is - decorator to improve readability - see "Sugar", below
  • Logical
    • allOf - matches if all matchers match, short circuits (like Java &&)
    • anyOf - matches if any matchers match, short circuits (like Java ||)
    • not - matches if the wrapped matcher doesn't match and vice versa
  • Object
    • equalTo - test object equality using Object.equals
    • hasToString - test Object.toString
    • instanceOfisCompatibleType - test type
    • notNullValuenullValue - test for null
    • sameInstance - test object identity
  • Beans
    • hasProperty - test JavaBeans properties
  • Collections
    • array - test an array's elements against an array of matchers
    • hasEntryhasKeyhasValue - test a map contains an entry, key or value
    • hasItemhasItems - test a collection contains elements
    • hasItemInArray - test an array contains an element
  • Number
    • closeTo - test floating point values are close to a given value
    • greaterThangreaterThanOrEqualTolessThanlessThanOrEqualTo - test ordering
  • Text
    • equalToIgnoringCase - test string equality ignoring case
    • equalToIgnoringWhiteSpace - test string equality ignoring differences in runs of whitespace
    • containsStringendsWithstartsWith - test string matching

Sugar

Hamcrest strives to make your tests as readable as possible. For example, the is matcher is a wrapper that doesn't add any extra behavior to the underlying matcher. The following assertions are all equivalent:

assertThat(theBiscuit, equalTo(myBiscuit));
assertThat
(theBiscuit, is(equalTo(myBiscuit)));
assertThat
(theBiscuit, is(myBiscuit));

The last form is allowed since is(T value) is overloaded to return is(equalTo(value)).

is는 테스트 매칭룰이 좀 더 읽기 편하도록 들어간 아무 짓도 안하는 장식용 매처다. 

Writing custom matchers

필요한 경우 custom 매처나 sugar를 만들어 기능을 확장할 수 있다.


JUnit과 함께 사용하기

JUnit currently ships with a few matchers, defined in org.hamcrest.CoreMatchers and org.junit.matchers.JUnitMatchers
To use many, many more, consider downloading the full hamcrest package.



junit에 기본적인 매처들이 같이 들어있고 더 많은 매처들을 사용하고 싶다면 hamcrest쪽 라이브러리를 다운받아서 쓰면된다.
아래 JUnitMatchers의 메소드 시그너처를 보면 알수 있듯이 리턴값으로 org.hamcrest.Matcher 인터페이스를 사용하고 있다.



공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2025/05   »
1 2 3
4 5 6 7 8 9 10
11 12 13 14 15 16 17
18 19 20 21 22 23 24
25 26 27 28 29 30 31
글 보관함