Skip to content

Commit 377bce9

Browse files
committed
Move wiki pages to docs
1 parent 3fe2fc8 commit 377bce9

File tree

3 files changed

+332
-2
lines changed

3 files changed

+332
-2
lines changed

docs/distributables.md

Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
---
2+
title: Hamcrest Distributables
3+
layout: default
4+
---
5+
# Hamcrest Distributables
6+
7+
## Introduction
8+
9+
Hamcrest consists of a single jar, called `java-hamcrest-<version>.jar` (where `<version>` refers to the specific version of Hamcrest).
10+
11+
Currently, the latest version of Java Hamcrest is `2.0.0.0`, and so the binary distributable is called `java-hamcrest-2.0.0.0.jar`.
12+
13+
## Adding Hamcrest to your Project
14+
15+
### Gradle
16+
17+
Add `"org.hamcrest:java-hamcrest:$hamcrestVersion"` to the dependencies section of your `build.gradle`, for example:
18+
19+
```gradle
20+
apply plugin: 'java'
21+
22+
dependencies {
23+
testImplementation 'org.hamcrest:java-hamcrest:2.0.0.0'
24+
}
25+
```
26+
27+
Note: older versions of Gradle use the `testCompile` configuration
28+
instead of the `testImplementation` configuration.
29+
30+
### Maven
31+
32+
Add the following dependency declaration to your `pom.xml`:
33+
34+
```xml
35+
<dependency>
36+
<groupId>org.hamcrest</groupId>
37+
<artifactId>java-hamcrest</artifactId>
38+
<version>2.0.0.0</version>
39+
<scope>test</scope>
40+
</dependency>
41+
```
42+
43+
### Download
44+
45+
You can download the jar directly from Maven Central. Hamcrest does
46+
not have any transitive dependencies, so you only need to download
47+
a single jar.
48+
49+
You can find the jar by searching Maven Central for groupId `org.hamcrest`
50+
and artifactId `java-hamcrest` using the following link:
51+
52+
> [https://search.maven.org/search?q=g:org.hamcrest%20AND%20a:java-hamcrest](https://search.maven.org/search?q=g:org.hamcrest%20AND%20a:java-hamcrest)
53+
54+
## Previous Versions
55+
56+
Prior to version 2.0.0.0, Java Hamcrest was distributed as different
57+
jars matching the different needs of applications. This document
58+
describes these distributables and the functionality contained in
59+
each of them.
60+
61+
### `hamcrest-core-1.3.jar`
62+
63+
This is the core API to be used by third-party framework providers.
64+
This includes a foundation set of matcher implementations for common
65+
operations. This API is stable and will rarely change. You will
66+
need this library as a minimum. From version 2.0.0.0, this is
67+
included in `java-hamcrest.jar`.
68+
69+
### `hamcrest-library-1.3.jar`
70+
71+
The library of Matcher implementations which are based on the core
72+
functionality in hamcrest-core.jar. From version 2.0.0.0, this is
73+
included in `java-hamcrest.jar`.
74+
75+
### `hamcrest-generator-1.3.jar`
76+
77+
A tool to allow many Matcher implementations to be combined into
78+
a single class with static methods returning the different matchers
79+
so users don't have to remember many classes/packages to import.
80+
Generates code. This library is only used internally at compile time.
81+
It is not necessary for the use of any of the other hamcrest libraries
82+
at runtime.
83+
84+
### `hamcrest-integration-1.3.jar`
85+
86+
Provides integration between Hamcrest and other testing tools,
87+
including JUnit (3 and 4), TestNG, jMock and EasyMock. Uses
88+
hamcrest-core.jar and hamcrest-library.jar.
89+
90+
### `hamcrest-all.jar`
91+
92+
One jar containing all classes of all the other jars.
93+
94+
### Previous Maven Versions
95+
96+
The description above also applies to the hamcrest Maven
97+
artifacts. The dependencies of the jars (`hamcrest-integration`
98+
uses `hamcrest-library` which uses `hamcrest-core`) is represented
99+
by the Maven dependency mechanism. There is no `hamcrest-all`
100+
library in the Maven repo prior to version 2.0.0.0. Just use hamcrest-integration which
101+
references all the other hamcrest libraries. After version 2.0.0.0,
102+
all the specified jars have been replaced by `java-hamcrest`.

docs/index.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,12 @@ layout: default
88

99
### Documentation
1010

11-
* [Getting Started](https://github.com/hamcrest/JavaHamcrest/wiki/The-Hamcrest-Tutorial)
11+
* [Getting Started](tutorial)
1212
* [API Documentation (JavaDoc)](javadoc/)
1313

1414
### Downloads
1515

16-
* [Distributables and Dependency Configuration](https://github.com/hamcrest/JavaHamcrest/wiki/Hamcrest-Distributables)
16+
* [Distributables and Dependency Configuration](distributables)
1717
* [Source Repository](http://github.com/hamcrest/JavaHamcrest)
1818
* [Project License](http://opensource.org/licenses/BSD-3-Clause)
1919
* [Extensions](https://github.com/hamcrest/JavaHamcrest/wiki/Related-Projects)

docs/tutorial.md

Lines changed: 228 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,228 @@
1+
---
2+
title: Hamcrest Tutorial
3+
layout: default
4+
---
5+
# Hamcrest Tutorial
6+
7+
## Introduction
8+
Hamcrest is a framework for writing matcher objects allowing 'match' rules to be defined declaratively. There are a number of situations where matchers are invaluble, such as UI validation, or data filtering, but it is in the area of writing flexible tests that matchers are most commonly used. This tutorial shows you how to use Hamcrest for unit testing.
9+
10+
When writing tests it is sometimes difficult to get the balance right between overspecifying the test (and making it brittle to changes), and not specifying enough (making the test less valuable since it continues to pass even when the thing being tested is broken). Having a tool that allows you to pick out precisely the aspect under test and describe the values it should have, to a controlled level of precision, helps greatly in writing tests that are "just right". Such tests fail when the behaviour of the aspect under test deviates from the expected behaviour, yet continue to pass when minor, unrelated changes to the behaviour are made.
11+
12+
### My first Hamcrest test
13+
We'll start by writing a very simple JUnit 3 test, but instead of using JUnit's `assertEquals` methods, we use Hamcrest's `assertThat` construct and the standard set of matchers, both of which we statically import:
14+
15+
```java
16+
import static org.hamcrest.MatcherAssert.assertThat;
17+
import static org.hamcrest.Matchers.*;
18+
import junit.framework.TestCase;
19+
20+
public class BiscuitTest extends TestCase {
21+
public void testEquals() {
22+
Biscuit theBiscuit = new Biscuit("Ginger");
23+
Biscuit myBiscuit = new Biscuit("Ginger");
24+
assertThat(theBiscuit, equalTo(myBiscuit));
25+
}
26+
}
27+
```
28+
29+
The `assertThat` method is a stylized sentence for making a test assertion. In this example, the subject of the assertion is the object biscuit that is the first method parameter. The second method parameter is a matcher for Biscuit objects, here a matcher that checks one object is equal to another using the Object equals method. The test passes since the Biscuit class defines an equals method.
30+
31+
If you have more than one assertion in your test you can include an identifier for the tested value in the assertion:
32+
33+
```java
34+
assertThat("chocolate chips", theBiscuit.getChocolateChipCount(), equalTo(10));
35+
36+
assertThat("hazelnuts", theBiscuit.getHazelnutCount(), equalTo(3));
37+
```
38+
39+
### Other test frameworks
40+
Hamcrest has been designed from the outset to integrate with different unit testing frameworks. For example, Hamcrest can be used with JUnit 3 and 4 and TestNG. (For details have a look at the examples that come with the full Hamcrest distribution.) It is easy enough to migrate to using Hamcrest-style assertions in an existing test suite, since other assertion styles can co-exist with Hamcrest's.
41+
42+
Hamcrest can also be used with mock objects frameworks by using adaptors to bridge from the mock objects framework's concept of a matcher to a Hamcrest matcher. For example, JMock 1's constraints are Hamcrest's matchers. Hamcrest provides a JMock 1 adaptor to allow you to use Hamcrest matchers in your JMock 1 tests. JMock 2 doesn't need such an adaptor layer since it is designed to use Hamcrest as its matching library. Hamcrest also provides adaptors for EasyMock 2. Again, see the Hamcrest examples for more details.
43+
44+
### A tour of common matchers
45+
Hamcrest comes with a library of useful matchers. Here are some of the most important ones.
46+
47+
#### Core
48+
`anything` - always matches, useful if you don't care what the object under test is
49+
50+
`describedAs` - decorator to adding custom failure description
51+
52+
`is` - decorator to improve readability - see "Sugar", below
53+
54+
#### Logical
55+
`allOf` - matches if all matchers match, short circuits (like Java &&)
56+
57+
`anyOf` - matches if any matchers match, short circuits (like Java ||)
58+
59+
`not` - matches if the wrapped matcher doesn't match and vice versa
60+
61+
#### Object
62+
`equalTo` - test object equality using Object.equals
63+
64+
`hasToString` - test Object.toString
65+
66+
`instanceOf`, `isCompatibleType` - test type
67+
68+
`notNullValue`, `nullValue` - test for null
69+
70+
`sameInstance` - test object identity
71+
72+
#### Beans
73+
`hasProperty` - test JavaBeans properties
74+
75+
#### Collections
76+
`array` - test an array's elements against an array of matchers
77+
78+
`hasEntry`, `hasKey`, `hasValue` - test a map contains an entry, key or value
79+
80+
`hasItem`, `hasItems` - test a collection contains elements
81+
82+
`hasItemInArray` - test an array contains an element
83+
84+
#### Number
85+
`closeTo` - test floating point values are close to a given value
86+
87+
`greaterThan`, `greaterThanOrEqualTo`, `lessThan`, `lessThanOrEqualTo` - test ordering
88+
89+
#### Text
90+
`equalToIgnoringCase` - test string equality ignoring case
91+
92+
`equalToIgnoringWhiteSpace` - test string equality ignoring differences in runs of whitespace
93+
94+
`containsString`, `endsWith`, `startsWith` - test string matching
95+
96+
#### Sugar
97+
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:
98+
99+
```java
100+
assertThat(theBiscuit, equalTo(myBiscuit));
101+
assertThat(theBiscuit, is(equalTo(myBiscuit)));
102+
assertThat(theBiscuit, is(myBiscuit));
103+
```
104+
The last form is allowed since is(T value) is overloaded to return `is(equalTo(value))`.
105+
106+
### Writing custom matchers
107+
Hamcrest comes bundled with lots of useful matchers, but you'll probably find that you need to create your own from time to time to fit your testing needs. This commonly occurs when you find a fragment of code that tests the same set of properties over and over again (and in different tests), and you want to bundle the fragment into a single assertion. By writing your own matcher you'll eliminate code duplication and make your tests more readable!
108+
109+
Let's write our own matcher for testing if a double value has the value NaN (not a number). This is the test we want to write:
110+
111+
```java
112+
public void testSquareRootOfMinusOneIsNotANumber() {
113+
assertThat(Math.sqrt(-1), is(notANumber()));
114+
}
115+
```
116+
117+
And here's the implementation:
118+
119+
```java
120+
package org.hamcrest.examples.tutorial;
121+
122+
import org.hamcrest.Description;
123+
import org.hamcrest.Factory;
124+
import org.hamcrest.Matcher;
125+
import org.hamcrest.TypeSafeMatcher;
126+
127+
public class IsNotANumber extends TypeSafeMatcher {
128+
129+
@Override
130+
public boolean matchesSafely(Double number) {
131+
return number.isNaN();
132+
}
133+
134+
public void describeTo(Description description) {
135+
description.appendText("not a number");
136+
}
137+
138+
@Factory
139+
public static Matcher notANumber() {
140+
return new IsNotANumber();
141+
}
142+
143+
}
144+
```
145+
146+
The `assertThat` method is a generic method which takes a Matcher parameterized by the type of the subject of the assertion. We are asserting things about Double values, so we know that we need a `Matcher<Double>`. For our Matcher implementation it is most convenient to subclass `TypeSafeMatcher`, which does the cast to a Double for us. We need only implement the `matchesSafely` method - which simply checks to see if the Double is NaN - and the `describeTo` method - which is used to produce a failure message when a test fails. Here's an example of how the failure message looks:
147+
148+
```java
149+
assertThat(1.0, is(notANumber()));
150+
151+
// fails with the message
152+
153+
java.lang.AssertionError: Expected: is not a number got : <1.0>
154+
155+
```
156+
The third method in our matcher is a convenience factory method. We statically import this method to use the matcher in our test:
157+
158+
```java
159+
import static org.hamcrest.MatcherAssert.assertThat;
160+
import static org.hamcrest.Matchers.*;
161+
162+
import static org.hamcrest.examples.tutorial.IsNotANumber.notANumber;
163+
164+
import junit.framework.TestCase;
165+
166+
public class NumberTest extends TestCase {
167+
168+
public void testSquareRootOfMinusOneIsNotANumber() {
169+
assertThat(Math.sqrt(-1), is(notANumber()));
170+
}
171+
}
172+
```
173+
174+
Even though the `notANumber` method creates a new matcher each time it is called, you should not assume this is the only usage pattern for your matcher. Therefore you should make sure your matcher is stateless, so a single instance can be reused between matches.
175+
176+
### Sugar generation (TBD)
177+
If you produce more than a few custom matchers it becomes annoying to have to import them all individually. It would be nice to be able to group them together in a single class, so they can be imported using a single static import much like the Hamcrest library matchers. Hamcrest helps out here by providing a way to do this by using a generator.
178+
179+
First, create an XML configuration file listing all the Matcher classes that should be searched for factory methods annotated with the org.hamcrest.Factory annotation. For example:
180+
181+
```
182+
TBD
183+
```
184+
185+
Second, run the org.hamcrest.generator.config.XmlConfigurator command-line tool that comes with Hamcrest. This tool takes the XML configuration file and generates a single Java class that includes all the factory methods specified by the XML file. Running it with no arguments will display a usage message. Here's the output for the example.
186+
187+
```java
188+
package org.hamcrest.examples.tutorial;
189+
190+
public class Matchers {
191+
192+
public static org.hamcrest.Matcher is(T param1) {
193+
return org.hamcrest.core.Is.is(param1);
194+
}
195+
196+
public static org.hamcrest.Matcher is(java.lang.Class param1) {
197+
return org.hamcrest.core.Is.is(param1);
198+
}
199+
200+
public static org.hamcrest.Matcher is(org.hamcrest.Matcher param1) {
201+
return org.hamcrest.core.Is.is(param1);
202+
}
203+
204+
public static org.hamcrest.Matcher notANumber() {
205+
return org.hamcrest.examples.tutorial.IsNotANumber.notANumber();
206+
}
207+
208+
}
209+
```
210+
211+
Finally, we can update our test to use the new Matchers class.
212+
213+
```java
214+
import static org.hamcrest.MatcherAssert.assertThat;
215+
216+
import static org.hamcrest.examples.tutorial.Matchers.*;
217+
218+
import junit.framework.TestCase;
219+
220+
public class CustomSugarNumberTest extends TestCase {
221+
222+
public void testSquareRootOfMinusOneIsNotANumber() {
223+
assertThat(Math.sqrt(-1), is(notANumber()));
224+
}
225+
}
226+
```
227+
228+
Notice we are now using the Hamcrest library is matcher imported from our own custom Matchers class.

0 commit comments

Comments
 (0)