|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||
java.lang.Objecttumbler.Tumbler
public class 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.
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.
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 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.
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 EXPECTATIONYou 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).
java -cp tumbler.jar ExampleToJavaConverter YOUR_SUBJECT_FILE.examplewill generate a SubjectTitleExamples.java file with java representation of the examples.
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])
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.
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.
| 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 |
|---|
public Tumbler()
| Method Detail |
|---|
public static void given(java.lang.String description)
description - description of what is givenpublic static void when(java.lang.String description)
description - description of action being performedpublic static void then(java.lang.String description)
description - description of expected effect / state
|
||||||||||
| PREV CLASS NEXT CLASS | FRAMES NO FRAMES | |||||||||
| SUMMARY: NESTED | FIELD | CONSTR | METHOD | DETAIL: FIELD | CONSTR | METHOD | |||||||||