tumbler
Class Tumbler

java.lang.Object
  extended by tumbler.Tumbler

public class Tumbler
extends java.lang.Object

Tumbler



What is the first thing you do when you want to make your favourite drink? Prepare a proper glass. It will lead the process of creating a tasty and good-looking drink by defining amounts of its ingredients and how they should be placed for the drink to look nice.

Tumbler is a library which will help you do the same with your code. It will lead the way you think about and build your code, as well as help you remember what should be implemented and when. As a side-effect you'll be able to impress your customer with always up-to-date reports of what has already been implemented (and whether it works or not), and what's still pending.


Contents

1. Intro
2. Usage example
3. Generating Java from examples
4. Generating reports from Java
5. Integration with JUnit
6. Annotating subjects and examples

1. Introduction

Tumbler is a coding-by-example library. It supports BDD-like way of thinking about the application you're building. No longer do you write tests and test methods. Now you're thinking about a Subject (functionality) in terms of Examples of its use/work. All your examples start with a magical word should which means, that we're going to say how a given subject should behave.

2. Usage example

Let's give a real-life example. I have a library. I can lend books and accept them back. Let me specify this functionality in terms of examples with the following description:

 Subject: Library
     Example: lend an existing book from the library
         Given 'Children from Bullerbyn' book in the library
         When this book is borrowed from the library
         Then the library doesn't contain it anymore.
 
     Example: not lend a nonexisting book from the library
         Given empty library
         When we try to borrow 'Children from Bullerbyn' from the library
         Then the library doesn't let it to be borrowed.
 
     Example: accept back a book previously borrowed
         Given 'Children from Bullerbyn' has been borrowed from the library
         When this book is given back
         Then the library contains it.
 
     Example: not accept back a book which does not belong to the library
         Given 'Children from Bullerbyn' book has not been borrowed the library
         When this book is given back
         Then the library does not accept it.
 

You can represent exactly this way of thinking about your functionalities in a form of Tumbler examples:

You can see that we're using a TumblerRunner to run examples with JUnit, define a Subject with the proper name, and specify all Examples as pending - meaning that they have not been implemented yet, so should be ignored during execution.
All examples have names that start with the should word, and contain given, when and then sections which define: initial state for the example, action to be performed and expected output accordingly. The only thing that's lacking is... the example implementation.

Let me quickly show you how a sample implementation of one of the methods could look like:

See? Not only do you have a documentation of your functionalities, but you just got an acceptance-testing framework!

You can see, that I now removed the pending = true from the @Example annotation - that's because the example has its implementation and the it should be failing/red now, so that you can produce production code that realises this example and makes it passing/green.

3. Generating Java from examples

So far so good. But now remember that according to basically any agile method you should be working on requirements / examples together with business people. Java code is not really readable for them. So as as helper in your cooperation with your business you are free to write your examples in the form given before like this:

 Subject: SUBJECT TITLE
 Example: EXAMPLE TITLE
 Given INPUT CONDITIONS
 When ACTION TO BE PERFORMED
 Then EXPECTATION
 
You can have as many examples for a subject as you like (obviously they must have unique names.) There should be one subject per file, and it should be defined in the first line of the file. Whitespaces and newlines are not important (so format the document to make it readable).
Now a simple call
 java -cp tumbler.jar ExampleToJavaConverter YOUR_SUBJECT_FILE.example
 
will generate a SubjectTitleExamples.java file with java representation of the examples.

4. Generating reports from Java

But, say, now you filled in all the examples, implemented the functionality that realises the examples and you'd like to show to your business what's already there. It's as easy as running all the tests with -DgenerateExampleFiles=true. Now you have .example files for all your examples. It is exactly the same file format as you might have used while defining the examples together with business people, with additional information about examples' statuses ([PENDING,PASSED,FAILED])

5. Integration with JUnit

Tubmler is integrated with JUnit (>=v4.5). You can use it together with your existing junit code. Just add all the newcoming tests as Tubmler examples. The integration is pretty deep - just look at the JUnit tests window in your IDE. You'll see all subjects and examples as full sentences instead of camel-case'ed names. Here is what I now can see in my eclipse:

This looks much better than your normal tests, right?
You can see, that the first example of Java generator subject passed, the second one failed, and the third one was ignored - it's either set to pending or annotated with JUnit's @Ignore attribute.
The only problem with eclipse is that you cannot double-click on examples in JUnit window. I mean, you can, but it won't lead you to the example method - will only open the proper class. Having spent some time looking into JUnit eclipse plugin I realised it cannot be accomplished, since the plugin is using the same name for showing entries and for finding them in code.
While I'm fine with finding the right method by using Ctrl-O, not all of you may be. So I added the possibility to stick by the old camel-case names (just as normal JUnit tests) so that you can navigate from the plugin. In order to do so, just annotate your examples class with @CamelCase. The generated report will still have proper full-text names.

Each example can be in one of four states: passing, failing, pending and ignored. If a test is ignored (@Ignore) it won't generated in the .examples file - for Tumbler it means you're not interested in it anymore. If you just want an example to be skipped, but to be taken into account in report generation, set it to the pending state.

6. Annotating Subjects and Examples

You don't need to annotate subjects in your Java code. The subject name is automatically resolved from the Java class name. Still, you may want to use some special characters, or simply have your code more intention-revealing (that's always a good thing to have!). In such case just annotate your examples class with:

 @Subject("Some subject name")
 
Examples must be annotated - in the end Tumbler must know which methods are examples and which serve some other purpose. So each example method must be annotated with @Example. Examples can have full-text names different to method names. Just give the name as the annotation value like this:
 @Example("Some other name")
 
Examples can also be set to pending state, which means that their implementation has not been finished yet. In such cases annotate such examples with:
 @Example(pending = true)
 
This is also the way they always get generated using ExamplesToJavaConverter since obvioulsy all generated examples need proper implementation first.

Author:
Pawel Lipinski

Constructor Summary
Tumbler()
           
 
Method Summary
static void given(java.lang.String description)
          'Given' section of an example
static void then(java.lang.String description)
          'Then' section of an example
static void when(java.lang.String description)
          'When' section of an example
 
Methods inherited from class java.lang.Object
clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Constructor Detail

Tumbler

public Tumbler()
Method Detail

given

public static void given(java.lang.String description)
'Given' section of an example

Parameters:
description - description of what is given

when

public static void when(java.lang.String description)
'When' section of an example

Parameters:
description - description of action being performed

then

public static void then(java.lang.String description)
'Then' section of an example

Parameters:
description - description of expected effect / state


Copyright © 2010. All Rights Reserved.