Skip to: Site menu | Main content

Groovy 

      Download | Documentation | Developers | Community

An agile dynamic language for the Java Platform

Using Instinct with Groovy Add comment to Wiki View in Wiki Edit Wiki page Printable Version

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