Instinct is a Behaviour Driven Development (BDD) framework for Java. Inspired by RSpec, Instinct provides:
- flexible annotation of contexts, specifications, test actors, etc. (via Java 1.5 annotations, marker interfaces or naming conventions)
- automatic creation of test doubles (dummies, mocks and stubs) and test subjects
- state and behavioural (mocks) expectation API
- JUnit test runner integration
- Ant tasks
The sections below illustrate using Instinct for the examples from Using Testing Frameworks with Groovy.
The Stack Example
Here is how you might use Instinct to test the Stack Example:
// require(url:'http://code.google.com/p/instinct', jar:'instinct-0.1.5.jar') // require(url:'http://geekscape.org/static/boost.html', jar:'boost-982.jar') // require(groupId:'org.jmock', artifactId:'jmock', version:'2.2.0') import com.googlecode.instinct.marker.annotate.* import com.googlecode.instinct.runner.TextRunner class AlmostEmptyFixedStackContext { private stack @BeforeSpecification void initially() { stack = new FixedStack() stack.push 'anything' assert !stack.isEmpty() } @Specification void shouldRemainNotEmptyAfterPeek() { stack.peek() assert !stack.isEmpty() } @Specification void shouldBecomeEmptyAfterPop() { stack.pop() assert stack.isEmpty() } } class AlmostFullFixedStackContext { private stack @BeforeSpecification void initially() { stack = new FixedStack() (1..<FixedStack.MAXSIZE).each{ x -> stack.push x } assert !stack.isFull() } @Specification void shouldBecomeFullAfterPush() { stack.push 'anything' assert stack.isFull() } } class EmptyFixedStackContext extends GroovyTestCase { private stack = new FixedStack() @BeforeSpecification void preConditions() { assert stack.isEmpty() } @Specification void shouldNoLongerBeEmptyAfterPush() { stack.push 'anything' assert !stack.isEmpty() } @Specification void shouldComplainWhenSentPeek() { shouldFail(StackUnderflowException) { stack.peek() } } @Specification void shouldComplainWhenSentPop() { shouldFail(StackUnderflowException) { stack.pop() } } } class FullFixedStackContext extends GroovyTestCase { private stack @BeforeSpecification void initially() { stack = new FixedStack() (1..FixedStack.MAXSIZE).each{ x -> stack.push x } assert stack.isFull() } @Specification void shouldRemainFullAfterPeek() { stack.peek() assert stack.isFull() } @Specification void shouldNoLongerBeFullAfterPop() { stack.pop() assert !stack.isFull() } @Specification void shouldComplainOnPush() { shouldFail(StackOverflowException) { stack.push 'anything' } } } class NonEmptyFixedStackContext { private stack @BeforeSpecification void setUp() { stack = new FixedStack() ('a'..'c').each{ x -> stack.push x } assert !stack.isEmpty() } @Specification void shouldAddToTheTopWhenSentPush() { stack.push 'd' assert stack.peek() == 'd' } @Specification void shouldBeUnchangedWhenSentPushThenPop() { stack.push 'anything' stack.pop() assert stack.peek() == 'c' } @Specification void shouldReturnTheTopItemWhenSentPeek() { assert stack.peek() == 'c' } @Specification void shouldNotRemoveTheTopItemWhenSentPeek() { assert stack.peek() == 'c' assert stack.peek() == 'c' } @Specification void shouldReturnTheTopItemWhenSentPop() { assert stack.pop() == 'c' } @Specification void shouldRemoveTheTopItemWhenSentPop() { assert stack.pop() == 'c' assert stack.pop() == 'b' } } TextRunner.runContexts( AlmostEmptyFixedStackContext, AlmostFullFixedStackContext, EmptyFixedStackContext, FullFixedStackContext, NonEmptyFixedStackContext )
which outputs:
AlmostEmptyFixedStackContext - shouldBecomeEmptyAfterPop - shouldRemainNotEmptyAfterPeek AlmostFullFixedStackContext - shouldBecomeFullAfterPush EmptyFixedStackContext - shouldComplainWhenSentPeek - shouldNoLongerBeEmptyAfterPush - shouldComplainWhenSentPop FullFixedStackContext - shouldComplainOnPush - shouldNoLongerBeFullAfterPop - shouldRemainFullAfterPeek NonEmptyFixedStackContext - shouldAddToTheTopWhenSentPush - shouldBeUnchangedWhenSentPushThenPop - shouldReturnTheTopItemWhenSentPop - shouldReturnTheTopItemWhenSentPeek - shouldNotRemoveTheTopItemWhenSentPeek - shouldRemoveTheTopItemWhenSentPop
The Item Storer Example
Here is how you might use Instinct to integration test the Item Storer Example:
// require(url:'http://code.google.com/p/instinct', jar:'instinct-0.1.5.jar') // require(url:'http://geekscape.org/static/boost.html', jar:'boost-982.jar') // require(groupId:'org.jmock', artifactId:'jmock', version:'2.2.0') import com.googlecode.instinct.marker.annotate.BeforeSpecification as initially import com.googlecode.instinct.marker.annotate.Specification as spec import static com.googlecode.instinct.runner.TextRunner.runContexts as check_specs_for class a_default_storer { def storer @initially void create_new_storer() { storer = new Storer() } private check_persist_and_reverse(value, expectedReverse) { storer.put(value) def persisted = storer.get() assert persisted == value def reversed = storer.reverse assert reversed == expectedReverse } @spec def should_reverse_numbers() { check_persist_and_reverse 123.456, -123.456 } @spec def should_reverse_strings() { check_persist_and_reverse 'hello', 'olleh' } @spec def should_reverse_lists() { check_persist_and_reverse([1, 3, 5], [5, 3, 1]) } } check_specs_for a_default_storer
We have used some BDD-flavoured method naming conventions here, but they are not compulsory. Here is the output:
a_default_storer - should_reverse_lists - should_reverse_strings - should_reverse_numbers






