Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.
Comment: Migrated to Confluence 4.0

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