View on GitHub

GContracts

Design by Contract Library for Groovy

Download this project as a .zip file Download this project as a tar.gz file

Programming by Contract for Groovy

This project aims to provide contract annotations that support the specification of class-invariants, pre- and post-conditions on Groovy classes and interfaces.

In addition, GContracts supports postconditions with the old and result variable and inheritance of all assertion types.

import org.gcontracts.annotations.*

@Invariant({ speed() >= 0 })
class Rocket { 

    @Requires({ isStarted() })
    @Ensures({ old.speed < speed })
    def accelerate() { ... }

    boolean isStarted() { ... } 
    def speed() { ... }
}

GContracts comes as single JAR file, without any third-party dependencies.

More Features

If you want to know about more about some of these features, checkout the Wiki pages.

The Stack Example

The Stack example is a classic way demonstrating the power of contracts in class libraries. Here is a Groovy example leveraging the GContracts library:

@Grab(group='org.gcontracts', module='gcontracts-core', version='[1.2.12,)')
import org.gcontracts.annotations.*

@Invariant({ elements != null })
class Stack<T> {

    List<T> elements

    @Ensures({ is_empty() })
    def Stack()  {
        elements = []
    }

    @Requires({ preElements?.size() > 0 })
    @Ensures({ !is_empty() })
    def Stack(List<T> preElements)  {
        elements = preElements
    }

    boolean is_empty()  {
        return elements.isEmpty()
    }

    @Requires({ !is_empty() })
    T last_item()  {
        return elements.get(count() - 1)
    }

    def count() {
        return elements.size()
    }

    @Ensures({ result == true ? count() > 0 : count() >= 0  })
    boolean has(T item)  {
        return elements.contains(item)
    }

    @Ensures({ last_item() == item })
    def push(T item)  {
       return elements.add(item)
    }

    @Requires({ !is_empty() })
    @Ensures({ last_item() == item })
    def replace(T item)  {
        remove()
        return elements.add(item)
    }

    @Requires({ !is_empty() })
    @Ensures({ result != null })
    T remove()  {
        return elements.remove(count() - 1)
    }

    String toString() { elements.toString() }
}

def stack = new Stack<Integer>()

You can copy and paste the above example to your groovyConsole and hit the run button.

Installation/Requirements

GContracts is available at the central Maven repository and as binary download at Github. Add gcontracts-core-xxx.jar to your project's classpath and you're ready to go.

As of 1.2.11, GContracts comes with embedded support for the Groovy/Grails tool suite >= 3.2.0 (Eclipse) and IntelliJ >= 12.1.

The library runs with Groovy >= 1.8 and can be used in statically (with @CompileStatic) and dynamically typed code.