Hamcrest is about making your test readable. Hamcrest is a framework that allows us to use object matchers for developing stylized sentences in assertions.
Let's look some examples:
Why write this:
double calculatedValue = 1000D;
...
assertEquals(1000, calculatedValue, 0)
When you can write this:
assertThat(calculatedValue, is(1000));
Or Why write off all this code:
List
String result = .....;
assertFalse(validResults.contains(result));
When you can write:
assertThat("1+", not(isIn(validResults)));
Three points should get your attention:
I. Using assertEquals (in our case with double) is not readable, what is the meaning of third parameter in previous example ?¿ What's happen if instead of 0 I pass a 1?¿.
II. When you speak yourself repeating a requirement, you say: "calculated value should be 1000", but it is rarely common to think "1000 should be my calculated value". Moreover, for example String assertEquals method contains 2 parameters, which of two are the expected value and current value?
III. Flexible notation in contrast to JUnit notation. For specifying that an element cannot be into a collection, in Junit assertFalse is used, and that's sounds strange using with a contains method of a list you can misunderstood exactly what are being test. Look Hamcrest expression, no possible error, we are asserting that "1+" not in validResults. Hamcrest has a module for treating collections expressions, like anyOf, isOneOf, hasItem, hasItems...
But wait, there is more, you can also build you own Hamcrest Matcher. A matcher is the responsible for validating if something is what expected. Hamcrest comes with a lot of built-in Matchers, but what's happen if we need one new matcher? Let's look an example:
Hamcrest does NOT comes with File matchers. We need to validate if after our business logic, a file is created in a directory.
- In Junit like expressions, would look something like:
final File createdFile = new File("test1");
assertTrue(createdFile.exists());
- In Hamcresst with built-in matchers:
final File createdFile = new File("test1");
assertThat(createdFile.exists(), is(true));
Maybe better than JUnit but expressiveness may be missing.
- What about that:
final File createdFile = new File("test1");
assertThat(createdFile, exists());
Better I think.
But a Matcher for asserting that, does not exists, so let's write one:
public class ExistsFileMatcher extends TypeSafeMatcher{
@Override
public void describeTo(final Description description) {
description.appendText("does not exists.");
}
@Override
public boolean matchesSafely(final File expectedFile) {
return expectedFile.exists();
}
@Factory
public staticMatcher exists() {
return new ExistsFileMatcher();
}
}
One will agree that is so simple, only one method that validates the expression, other one that describes the error, and finally a factory.
And this matcher can be used in conjunction with other matchers. It is also valid that one:
final File createdFile = new File("test1");
assertThat(createdFile, not(exists()));
And that's Hamcrest, don't you think is a better way to express assertions rather than plain JUnit?
3 comentarios:
Hi Alex,
I think that you should give a look at fest-assert : http://docs.codehaus.org/display/FEST/Fluent+Assertions+Module
I've used for a few years Hamcrest and now I am only using fest-assert.
Assertions are more fluents, and in some cases more easier to use.
An example :
List newEmployees = employees.hired(TODAY);
assertThat(newEmployees).hasSize(6)
.contains(frodo, sam);
Regards,
Maxime
Thanks for the comment I will take a look.
read this article advice their website click now my sources check out this site
Publicar un comentario