Matcher<T> matcher) <T> void assertThat(String reason, T actual, Matcher<T> matcher) Parameters: reason description displayed when assertion fails (optional) actual actual value matcher Hamcrest matcher that checks the actual value March 14, 2011 6
public void withoutMatchers() { assertEquals(2, 1 + 1); } @Test public void withMatchers() { assertThat(1 + 1, is(2)); } } No more guessing about order of arguments Often more readable than traditional assertions March 14, 2011 7
public void withoutMatchers() { assertEquals(2, 1 + 1); } @Test public void withMatchers() { assertThat(1 + 1, is(2)); } } No more guessing about order of arguments Often more readable than traditional assertions March 14, 2011 7
public void withoutMatchers() { assertEquals(2, 1 + 1); } @Test public void withMatchers() { assertThat(1 + 1, is(2)); } } No more guessing about order of arguments Often more readable than traditional assertions March 14, 2011 7
public void withoutMatchers() { assertEquals(2, 1 + 1); } @Test public void withMatchers() { assertThat(1 + 1, is(2)); } } No more guessing about order of arguments Often more readable than traditional assertions March 14, 2011 7
Result: AssertionError: at de.andrena.junit... New assertion with matcher assertThat(asList(1, 2, 3), not(hasItem(2))); Result: AssertionError: Expected: not a collection containing <2> got: <[1, 2, 3]> March 14, 2011 9
Result: AssertionError: at de.andrena.junit... New assertion with matcher assertThat(asList(1, 2, 3), not(hasItem(2))); Result: AssertionError: Expected: not a collection containing <2> got: <[1, 2, 3]> March 14, 2011 9
nullValue, . . . Strings containsString, startsWith, endsWith, . . . Collections hasItem, hasItems, isIn, empty, hasSize, . . . JUnit includes only a small fraction: org.hamcrest.CoreMatchers org.junit.matchers.JUnitMatchers Hamcrest offers additional matchers (hamcrest-all.jar). In addition, you can write your own matchers. March 14, 2011 10
nullValue, . . . Strings containsString, startsWith, endsWith, . . . Collections hasItem, hasItems, isIn, empty, hasSize, . . . JUnit includes only a small fraction: org.hamcrest.CoreMatchers org.junit.matchers.JUnitMatchers Hamcrest offers additional matchers (hamcrest-all.jar). In addition, you can write your own matchers. March 14, 2011 10
with static methods we would like to import Requires manual setup of preferences in IDE . . . for all developers! Solution Generate your own matcher library March 14, 2011 13
<factory class="org.hamcrest.core.Is"/> <factory class="de.andrena.junit.hamcrest.IsEmptyCollection"/> </matchers> 2. Run org.hamcrest.generator.config.XmlConfigurator 3. Combines all @Factory methods into a single generated class: public class Matchers { public static <T> Matcher<? super T> is(T param1) { return org.hamcrest.core.Is.is(param1); } /* ... */ public static Matcher<Collection<?>> empty() { return de.andrena.junit.hamcrest.IsEmptyCollection.empty(); } } March 14, 2011 14
assertion methods are still clearer sometimes Problem Java type system often gets in one’s way Requires boxing for primitive types assertThat(1 + 1, is(2)) Insufficient type inference assertThat(new TreeSet<String>(), Matchers.<String>empty()); March 14, 2011 15
to supply parameters to test class constructors Arguments are defined in a public, static method @Parameters annotation Return type: List<Object[]> The runner creates an instance of the test class for each pair of test method and argument definition and executes the test. Useful when testing a calculation with a large number of input values. March 14, 2011 17
or methods Any number of datapoints Different types Test methods are parameterized No boilerplate code (Constructor + instance variables) Different types of parameters possible Theories can do everything Parameterized tests can, but more! March 14, 2011 22
behaviour under selected inputs Examples ought to be characteristic (hopefully) A theory generalizes a set of tests: precondition is made explicit assertions apply for all inputs that satisfy preconditions March 14, 2011 23
folder; @Before public void createTemporaryFolder() throws Exception { folder = File.createTempFile("myFolder", ""); folder.delete(); folder.mkdir(); } @Test public void test() throws Exception { File file = new File(folder, "test.txt"); file.createNewFile(); assertTrue(file.exists()); } @After public void deleteTemporaryFolder() { recursivelyDelete(folder); // does not fit on current slide... } March 14, 2011 26
folder; @Before public void createTemporaryFolder() throws Exception { folder = File.createTempFile("myFolder", ""); folder.delete(); folder.mkdir(); } @Test public void test() throws Exception { File file = new File(folder, "test.txt"); file.createNewFile(); assertTrue(file.exists()); } @After public void deleteTemporaryFolder() { recursivelyDelete(folder); // does not fit on current slide... } March 14, 2011 26
test to fail with an aggregated list of failures at the end. TestName Provides access to the name of the currently executing test method. Timeout Applies the same timeout to all test methods in the test class. March 14, 2011 31
Composable You can use any number of rules in one test class. Delegation over inheritance Help to avoid test class hierarchies. Extendable Writing your own rules is easy. March 14, 2011 35
interface Slow {} Only for one test: @Category(Slow.class) @Test public void test() {} All tests in a test class: @Category(Slow.class) public class B { @Test public void c() {} } March 14, 2011 37
@SuiteClasses( { A.class, B.class }) public class AllTests {} All tests in category Slow: @RunWith(Categories.class) @IncludeCategory(Slow.class) public class AllSlowTests extends AllTests {} All other tests: @RunWith(Categories.class) @ExcludeCategory(Slow.class) public class AllFastTests extends AllTests {} March 14, 2011 38
difference between theory and practice. But, in practice, there is. Jan L. A. van de Snepscheut/Yogi Berra Thank you! Mail [email protected] Twitter @marcphilipp Blog http://marcphilipp.tumblr.com/ March 14, 2011 41