Fork me on GitHub

Jnario

Executable Specifications for Java.

News

Clutter-free specs for Java

Jnario is a language making it possible to write concise tests that can effectively document the behavior of your Java programs.



describe "The String 'Hello World'"{
  facts "about Hello World" => [
    length should be 11
    it should startWith "Hello"
    it should endWith "World"
    it should contain "Wor"
  ]
}

Specify executable scenarios

You can write executable acceptance specifications similiar to Cucumber, but with less maintenance overhead.

Feature: Jnario Introduction
  In order to demonstrate Jnario
  As a Developer
  I want the Jnario homepage to show examples 

  Scenario: Example on Homepage
    Given the Jnario homepage
    When I open it in the browser
    Then it should show an example specification

Run with JUnit

Jnario is easy to integrate into existing projects as specs compile into idiomatic Java source code being executable with Junit.

Full Java interoperability

Jnario's type system resembles the one of Java making it easy to interact with Java objects.

import java.util.ArrayList

describe ArrayList{
  fact "adding increases size"{
    val list = new ArrayList<String>()
    list.size => 0
    list.add("something")
    list.size => 1
  }
}

Built with Xtend

This means when writing specs with Jnario, you can use all the goodness of Xtend resulting in less boilerplate code in your specs.

describe "Map/Reduce"{
  fact "count chars in a list"{
    val l = list("red", "blue", "green")
    l.map[length].reduce[sum, length | sum + length] => 12
  }
}

Unit & integration specs

Write facts about your code

Describe the intended behavior of your code using examples. A fact can be as simple as a single expression asserting a certain property. You can use should or => to describe the desired behavior of your objects.

describe Stack{
  val stack = new Stack
  context "empty"{
    fact stack.pop throws EmptyStackException
  }
  context "one element"{
    before stack.add("something")
    fact stack.pop => "something"
  }
}

A DSL designed for testing

Jnario syntax is specifially tailored to the purpose of writing tests. For example, Jnario supports tables for simplify specifying different sets of inputs and expected outputs.

describe "Arithmetic"{
  def additions{
        |  a  |  b  |  sum  |
        |  1  |  2  |   3   |
        |  4  |  5  |   9   |
        | 10  | 11  |  20   | 
        | 21  | 21  |  42   | 
  }
  fact additions.forEach[a + b => sum]
}

Self-explaining assertions

A failed assertion prints the values of all evaluated sub-expressions. This means you don’t need to debug your tests anymore to find the exact reason why it failed.

java.lang.AssertionError: additions failed

        | a      | b      | sum     |
        | 1      | 2      | 3       | ✓
        | 4      | 5      | 9       | ✓
        | 10     | 11     | 20      | ✘     (1)
        | 21     | 21     | 42      | ✓

(1) Expected a + b => sum but
         a + b is 21
         a is 10
         b is 11
         sum is 20

Acceptance specs

Cucumber-style scenarios...

With Jnario you can create executable acceptance specifications that are easily readable and understandable to business users, developers and testers, similar to Cucumber.

Feature: Addition

  In order to avoid silly mistakes
  As a math idiot
  I want to be told the sum of two numbers
  
  Scenario: Add two numbers
    Given I have entered "50" into the calculator
    And I have entered "70" into the calculator
    When I press "add"
    Then the result should be "120" 

...with a twist...

There is one big difference between Jnario and Cucumber. You don’t need to create separate step definitions to make your steps executable. You can directly add the necessary code below your steps.

Feature: addition
  ...
  Scenario: Add two numbers
    val calculator = new Calculator()
    Given I have entered "50" into the calculator
      calculator.enter(args.first)
    And I have entered "70" into the calculator
    When I press "add"
      calculator.press(args.first)
    Then the result should be "120" 
      calculator.result => args.first
						

...and proper tooling

Mixing code and text in your specs is not a problem, as you can hide the code in the editor to improve readability.

Jnario Suites

Orchestrate spec execution

Use suites to groups multiple specifications and execute them together. You can either directly reference specs or include multiple specs at the same time using regular expressions.

package demo

import specs.*
import features.*

#My Suite

- "My Feature"
- "My Spec"

...and document

Jnario generates HTML documents for suites making them a great way to provide additional documentation. You can use suites to document the overall architecture of your application with links to other specifications describing the different parts in more detail.

package demo

import specs.*

#My Suite

This is the description of the suite. It is possible to use 
[Markdown](http://daringfireball.net/projects/markdown)
for **formatting** the text and adding images or links. 

##My Specs

This is a subsection in which we list all our unit specs:

- "My Spec": this is an example unit spec.
   with a multiline description.

##My Features

...and here we list all our features using a regular expression:

- \.*features.*\

Generate documentation from your specs

Specs are a great way to document the behavior of your code. For example, the complete Jnario documentation is generated from specs written with Jnario. Specs can be transformed into a corresponding HTML documents. Here are some example specs with their generated documentation (you can click on the images to enlarge).