#+TITLE: java-check Property-based testing within the [[http://junit.org/][JUnit]] test framework. Using ~java-check~ you can write ~@Property~ tests. These tests will have any parameters randomly generated (using generators marked with ~@DataSource~). This allows you to write tests which assert general properties rather than specific cases. As an example, let's test the ~Collections.reverse~ function. One simple property of ~Collections.reverse~ is that reversing a list twice results in the original list (ie. ~reverse(reverse(x)) = x)~). Let's write a property for this: #+BEGIN_SRC java @RunWith(Properties.class) public class ExampleTest { @DataSource public static Generator> integerList = listOf(integer()); @Property public void reverseIsInvolution(List list) { List reversed = new ArrayList<>(list); Collections.reverse(reversed); // reverse(reversed); assertEquals(list, reversed); } } #+END_SRC Oh no! The test above is incorrect! I've accidentally commented out the second ~reverse(reversed)~ line, which means I'm trying to test whether ~reverse(x) = x~. That means this test should fail: #+BEGIN_EXAMPLE au.id.zancanaro.javacheck.junit.PropertyError: reverseIsInvolution([0, -1]) Seed: 1433134487916 Expected :[0, -1] Actual :[-1, 0] at au.id.zancanaro.javacheck.junit.Properties$GenerativeTester.evaluate(Properties.java:217) ... (extra stack trace entries have been removed for clarity) Caused by: java.lang.AssertionError: expected:<[0, -1]> but was:<[-1, 0]> at org.junit.Assert.fail(Assert.java:88) ... (extra stack trace entries have been removed for clarity) #+END_EXAMPLE The test has failed, and it's managed to reduce the failing case to the smallest possible failing case: a two-element list with both elements being different. It's easy for us to fix the test, and here is the complete file for ~ExampleTest.java~: #+BEGIN_SRC java package com.example; import au.id.zancanaro.javacheck.Generator; import au.id.zancanaro.javacheck.annotations.DataSource; import au.id.zancanaro.javacheck.annotations.Property; import au.id.zancanaro.javacheck.junit.Properties; import org.junit.runner.RunWith; import java.util.ArrayList; import java.util.List; import static au.id.zancanaro.javacheck.Generators.integer; import static au.id.zancanaro.javacheck.Generators.listOf; import static java.util.Collections.reverse; import static org.junit.Assert.assertEquals; @RunWith(Properties.class) public class ExampleTest { @DataSource public static Generator> integerList = listOf(integer()); @Property public void reverseIsInvolution(List list) { List reversed = new ArrayList<>(list); reverse(reversed); reverse(reversed); assertEquals(list, reversed); } } #+END_SRC