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:
| Code Block |
|---|
// 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:
| Code Block |
|---|
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:
| Code Block |
|---|
// 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:
| Code Block |
|---|
a_default_storer - should_reverse_lists - should_reverse_strings - should_reverse_numbers |