Jnario is based on Xtend and this release provides compatibility to Xtend 2.6! This means you benefit from all the improvements made in Xtend 2.6 when writing tests with Jnario. One of the most prominent new features is that you can define anonymous classes in your Jnario specs. This is a great way to quickly create test stubs in your specs. Furthermore, the IDE performance in Eclipse has also been greatly improved.
Tables have always been one of my favorite features of Jnario specs. Thanks to Sebastian Poetzsch, using tables has become even more fun in this release! Sebastian contributed an automated formatter for specs, which works also for tables. No more fiddling with spaces when formatting your tables necessary! Just press (CTRL|CMD)+SHIFT+F
and there you go:
The standalone Jnario compiler has been completely rewritten. This lays the foundation for future support for other build environments such as gradle. Right now, this means faster compile times when compiling Jnario specs with Maven. In general the maven support has been improved. For example, in combination m2e, Eclipse will automatically synchronize your maven and project configuration.
There has been lots of fixes for generating html reports from your Jnario specifications. If you are curious, here is a great example for what executable documentations created with Jnario can look like.
Check out the documentation or join the mailing list. You can find the full release notes here
These posts might also be interesting for you:
Happy testing!
]]>When I was still playing basketball, our coach used to let us practice with medicine balls. The ugly brown leather balls weighting a ton. At least they felt that way after the 10th shot.
At first I considered it as just another mean way to improve our fitness. It was not really likely to ever run out of normal basketballs with only medicine balls left to continue playing.
However, after a while I realized that practicing with medicine balls actually helped me become a better basketball player. I learned to adapt my passing and throwing technique to balls of different weights. This helped during long games, when I became tired and had less strength left. In these situations, a basketball felt actually more like a medicine ball. Thanks to my training I was used to this and I was still able to take a proper shot.
Ok, but what does throwing medicine balls have to do with programming?
Playing basketball with a medicine ball is an artificial constraint. Constraining ourselves during training forced us to focus on skills otherwise neglected.
The question is, what is the equivalent of training with medicine balls in programming?
One example is programming without conditional statements. Programming without conditionals is a similar artificial constraint. You most likely will never encounter situations in which you cannot use if statements.
Let's take a look at a simple example in ruby in which we want to print all cells in a game of life:
class Cell def initialize(alive) @alive = alive end def alive? @alive end end def print_world(*cells) cells.each do |cell| if cell.alive? print 'x' else print ' ' end end end print_world(Cell.new(true), Cell.new(false))
Now let's try to get rid of the if statement. We could, for example, replace the conditional with polymorphism. In our case it means to create a separate class for each cell state, where both classes provide different implementations for the to_s
method:
class DeadCell def to_s ' ' end end class AliveCell def to_s '*' end end def print_world(*cells) cells.each do |cell| print cell end end print_world(AliveCell.new, DeadCell.new)
Polymorphism not only helps us to get rid of the if statement, it also makes our code cleaner. It no longer violates the open/closed principle, as we are able to introduce new cell states without having to change the existing cell implementation.
A second possibility would be to use a map to store the mapping between cell states and their string representation:
serializers = { :alive => 'x', :dead => ' ' }
If we wanted to support more sophisticated mappings, we could even use procedures as map values. Our cell implementation just needs a generic state, which we implement using a symbol:
class Cell def initialize(state) @state = state end def state? @state end end
Printing the cells uses the mapping between cell states and their string representation:
def print_world(serializers, *cells) cells.each do |cell| print serializers.fetch(cell.state) end end print_world(serializers, Cell.new(:alive), Cell.new(:dead))
This approach has the benefit that we can easily provide different string representation for the same cell state, as the to string mapping is no longer tied to the cell class. The last implementation is pretty much what is known as the strategy pattern.
Isn't this great? By simply avoiding conditional statements, we discovered and practiced two patterns, which can considerably improve code in our daily life.
I am not saying that everyone should stop using if statements. Instead, we should stop taking everything for granted and try new things. Like in sports, we need to train our skills to become better at what we do. Using artificial constraints is an effective way to focus on otherwise neglected skills. Even though it might not make much sense at first, it turns us into better programmers. Just like throwing medicine balls.
]]>A coderetreat is a daylong event, focused on practicing the basic principles of good design without the pressure of having to get things done. The day is split into six sessions, in which you work on the same problem over and over again. In each session you will pair with a different programmer to maximize the knowledge transfer. The important thing is that after each session all the code that has been written so far is deleted. This gives you the chance in the next session to all start over again without being constrained by any design decisions you made in the previous one. The combination of pair programming with the focus on writing perfect code instead of solving the problem gives you a unique opportunity to improve your skills.
This year we will again host the Coderetreat here in Munich at E.S.R. Labs. If your are interested head over to http://coderetreat-munich.de for registration.
Here are some impressions from last year's event:
]]>
After presenting Jnario at last year's EclipseCon, I decided for this year to focus on a more general topic: how to write fast and maintainable tests for your Eclipse plugin. I am convinced that writing maintainable tests is not that hard if you follow some basic rules. In my presentation I showed some code examples that might sometime turn into a maintenance problem and demonstrated how you can avoid these situation. Check out my slides if you are interested in more details.
]]>In this post I demonstrate how easy it is to write Cucumber style acceptance tests in Jnario. Jnario has some unique features, which makes writing given, when, then style scenarios a lot easier than in Cucumber or JBehave. I will show how to use Jnario by implementing a simple acceptance test for a web app using the browser automation tool Selenium. We will also cover more advanced topics such as how to encapsulate setup and teardown logic for scenarios and how to generate reports from your scenarios.
Jnario is a language specifically designed for testing based on Xtend. Xtend is a new language for the JVM featuring lambda expressions, type-inference, multi-line strings and more. The good thing about Xtend is that it uses the same type system as Java and compiles to readable Java code. This means when writing specs with Jnario, you can use all the goodness of Xtend resulting in less boilerplate code in your specs. Furthermore, Jnario is easy to integrate into existing Java projects, as specifications compile to plain Java JUnit tests.
First you need to install the Jnario tooling for Eclipse (if you haven't already), the easiest way to do this is via the update site or the Eclipse Marketplace. Eclipse is not strictly required for this tutorial, but its going to be a lot more convenient.
We will be using Maven to manage our dependencies and to compile our specs. The easiest way to set up a new Jnario project using maven to use the Jnario Maven Archetype. If your are using the Maven tooling for Eclipse just create a new maven project and select the jnario-archetype:
Otherwise enter the following on the command line to create a new maven project:
$ mvn archetype:generate \ -DarchetypeGroupId=org.jnario \ -DarchetypeArtifactId=jnario-archetype \ -DarchetypeVersion=0.4.2 \ -DgroupId=org.jnario \ -DartifactId=selenium
Afterwards we have to add the selenium dependencies to our pom file:
... <dependencies> ... <dependency> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-java</artifactId> <version>2.32.0</version> </dependency> <dependency> <groupId>com.opera</groupId> <artifactId>operadriver</artifactId> </dependency> </dependencies> <dependencyManagement> <dependencies> <dependency> <groupId>com.opera</groupId> <artifactId>operadriver</artifactId> <version>0.18</version> <exclusions> <exclusion> <groupId>org.seleniumhq.selenium</groupId> <artifactId>selenium-remote-driver</artifactId> </exclusion> </exclusions> </dependency> </dependencies> </dependencyManagement>
That is all we need to do for setting up Jnario. You can verify whether everything works by running:
$ mvn clean install
This will compile and run the example specs in the new project. If the build is successful, we can safely delete the example files "src/main/org/jnario/selenium/HelloWorld.xtend" and "src/test/org/jnario/selenium/HelloWorld.spec" and get started.
To demonstrate how to use Jnario with Selenium, we will test a web app most of us should be familiar with: the Google Search. Our goal is to test, when we search for a certain keyword that the search result contains matching websites.
Jnario features two different languages for writing tests, one for unit tests and one for high-level acceptance tests similar to Cucumber. As the feature we are going to test is pretty high-level and can easily be understood by a non-technical stakeholder, we will be using the acceptance spec language. To create a new feature definition use the wizard via New File->Jnario->Jnario Feature:
Jnario feature files use a format similar to Cucumber with some small differences, which we will look into later. The basic idea is the same, to use Given, When, Then steps to describe simple scenarios. In our example, we establish the precondition in the Given step that we open Google search in a browser. In the following When step we search for the "Jnario" keyword. Afterwards, we describe in the Then step the expected outcome, namely, to find the Jnario slogan "Executable Specifications for Java" in our search results:
package org.jnario.selenium Feature: Searching for web pages via Google In order to safe time As a developer I want to find web sites faster Scenario: Searching for Jnario Given I opened "http://www.google.com" in a browser When I search for "Jnario" Then the result should contain "Jnario - Executable Specifications for Java"
Note that we use quotes to define step parameters, such as "http://www.google.com"
. We will use this later, when we make our specification executable.
So far we have defined a simple acceptance criterion for our feature. We can already execute it as a JUnit test by right-clicking our feature file and selecting Run as->JUnit Test. It might be surprising, but our scenario passes already. The reason is that our scenario will be ignored by JUnit as we haven't provided an implementation for our steps yet.
In Jnario you don't need to define a separate parser for your scenarios. Instead, you can directly add the necessary execution logic into your scenarios. You can think of a scenario as a normal Java class where the scenario is the class and each step is a separate method. So, we can setup the selenium infrastructure by declaring two fields. One field contains the web driver and one the web driver wait util. The web driver is responsible for controlling and accessing the browser. The syntax for declaring fields is similar to Xtend:
Scenario: Searching for Jnario
val driver = new HtmlUnitDriver
val wait = new WebDriverWait(driver, 30)
Now we need to make our Given step executable. We simply use the selenium API to retrieve a webpage via the web driver. Step parameters, such as the URL, can be accessed via the implicit variable args, which is a list of all parameter strings:
Given I opened "http://www.google.com" driver.get(args.first)
The web search is performed using the driver's findElement API. Note that in Jnario static members are accessed by ::
instead of .
as in Java:
When I search for "Jnario"
val searchBox = driver.findElement(By::name("q"))
searchBox.sendKeys(args.first)
searchBox.submit
Finally, we check whether the search results contain the expected string. As it can take a while until the browser returns our search result, we need to define a waiting condition. We use the WebDriverWait, which we declared as a field earlier.
The nice thing in Jnario is that instead of implementing the wait condition in an anonymous subclass, we can use Xtend's lambda expressions. A lambda expression is declared within brackets and will be automatically converted into an instance of Function, which is required by WebDriverWait#until. Lambda expressions are one of the features making code written in Jnario/Xtend a lot more readable than plain Java code.
When the web page is returned on time, we retrieve the content of the webpage and assert that our expected string is contained. The assertion is written using Jnario's should expressions. Finally, we clean up and close the browser via the web driver:
Then the result should contain "Jnario - Executable Specifications for Java" wait.until[ findElement(By::id("resultStats")) != null ] val content = driver.findElement(By::tagName("body")).getText() content should contain args.first driver.close
That's all we need to do to make our scenario executable. We can now run it as a normal JUnit test and check whether the Google search really works as expected. Here is the complete definition of our feature:
package org.jnario.selenium import org.openqa.selenium.By import org.openqa.selenium.support.ui.WebDriverWait import org.openqa.selenium.htmlunit.HtmlUnitDriver Feature: Searching for web pages via Google ... Scenario: Searching for Jnario val driver = new HtmlUnitDriver val wait = new WebDriverWait(driver, 30) Given I opened "http://www.google.com" driver.get(args.first) When I search for "Jnario" val searchBox = driver.findElement(By::name("q")) searchBox.sendKeys(args.first) searchBox.submit Then the result should contain "Jnario - Executable Specifications for Java" wait.until[findElement(By::id("resultStats")) != null] val content = driver.findElement(By::tagName("body")).getText() content should contain args.first driver.close
When you think now that your feature is no longer as readable as before, you might be right, but you can quickly change this by pressing Ctrl/Cmd + SHIFT + f
in the editor to make the code magically disappear (and reappear).
Let's test whether Google search not only works for Jnario, but also for the Xtend homepage. In Jnario you can reuse existing steps and their implementation in other scenarios. So we can easily add another scenario based on our existing steps. We just change the parameters to search for xtend homepage instead.
Feature: Searching for web pages via Google ... Scenario: Searching for Jnario Given I opened "http://www.google.com" in a browser When I search for "Jnario" Then the result should contain "Jnario - Executable Specifications for Java" Scenario: Searching for Xtend Given I opened "http://www.google.com" When I search for "Xtend Lang" Then the result should contain "Xtend - Modernized Java"
The Jnario editor offers code completion via Ctrl + SPACE
showing all available steps. Note how the keyword color varies in steps. It is green if the step has an implementation, red if no step with implementation exists and grey if another step with implementation exists.
There is one problem in the implementation of our scenario. We close the browser in our Then step. This makes it impossible to write tests like:
Scenario: Searching for Something Given I opened "http://www.google.com" When I search for "Something" Then the result should contain "Something" And the result should contain "Something else"
When we execute the Then step a second time we won't be able to retrieve the contents of the web page, as the driver is already closed. We need to move the closing of the driver into a separate tear down method. In Jnario this is supported via spec extensions. A spec extension encapsulates common helper method together with setup and tear down logic.
In our example, we create a new Xtend (or Java) class in which we extend the HtmlUnitDriver:
package org.jnario.selenium import org.junit.After import org.openqa.selenium.htmlunit.HtmlUnitDriver class HtmlUnitDriverExtension extends HtmlUnitDriver { @After override void close(){ super.close() } }
We simply override the close method and add the JUnit @After annotation. This way we tell Jnario to execute this method after our scenario is performed. Now, we need to replace the HtmlUnitDriver in our feature with our HtmlUnitDriverExtension and add the additional extension keyword:
extension HtmlUnitDriverExtension driver = new HtmlUnitDriverExtension
Extensions are a Xtend feature which allows extending the behavior of objects without changing their class. In our example, it is now possible to call all driver methods directly without the field name. For example, we can now write:
val searchBox = findElement(By::name("q"))
instead of:
val searchBox = driver.findElement(By::name("q"))
This makes extension fields a great way to encapsulate testing helpers without adding additional syntactic noise to your tests! Here is our updated scenario:
package org.jnario.selenium import org.openqa.selenium.By import org.openqa.selenium.support.ui.WebDriverWait Feature: Searching for web pages via Google ... Scenario: Searching for Jnario extension HtmlUnitDriverExtension driver = new HtmlUnitDriverExtension val wait = new WebDriverWait(driver, 30) Given I opened "http://www.google.com" get(args.first) When I search for "Jnario" val searchBox = findElement(By::name("q")) searchBox.sendKeys(args.first) searchBox.submit Then the result should contain "Jnario - Executable Specifications for Java" wait.until[findElement(By::id("resultStats")) != null] val content = findElement(By::tagName("body")).getText() content should contain args.first
Another thing, which could be improved in our feature definition, is that we define the same precondition in both scenarios. This is a duplication, which makes it harder to maintain our features in the future. We can avoid this by using background scenarios, similar to Cucumber. A background scenario defines steps to be executed before each scenario. Using a background, we can rewrite our scenario by moving the given step from both scenarios into a single background scenario:
package org.jnario.selenium import org.openqa.selenium.By import org.openqa.selenium.support.ui.WebDriverWait Feature: Searching for web pages via Google ... Background: extension HtmlUnitDriverExtension driver = new HtmlUnitDriverExtension val wait = new WebDriverWait(driver, 30) Given I opened "http://www.google.com" get(args.first) Scenario: Searching for Jnario When I search for "Jnario" val searchBox = findElement(By::name("q")) searchBox.sendKeys(args.first) searchBox.submit Then the result should contain "Jnario - Executable Specifications for Java" wait.until[findElement(By::id("resultStats")) != null] val content = findElement(By::tagName("body")).getText() content should contain args.first Scenario: Searching for Xtend When I search for "Xtend Lang" Then the result should contain "Xtend - Modernized Java"
As we set up our project using maven, we can easily create HTML reports from our spec. The generated reports contain a nicely formatted HTML version of our feature and will also tell us which scenario passed and which failed. These reports are a great way to communicate the current state of a project with the stakeholders.
First we need to execute our spec via maven:
$ mvn clean test
Afterwards we can generate the HTML reports to target/jnario-doc via:
$ mvn org.jnario:report:generate
In this post we have seen how easy it is to write acceptance tests with Jnario. However, Jnario provides a lot more features than what we have covered in this post. If you want try Jnario or learn more about it, head over to the official page www.jnario.org. There is also a mailing list available for questions and discussions. You should follow me on twitter if you want to stay up-to-date with Jnario.
]]>The type system of Xtend has been rewritten from scratch for Xtend 2.4. In the previous Xtend and Jnario releases, some corner cases could result in compile errors in the generated Java code. These are all fixed now. At the same time, the new type system is a lot faster resulting in shorter build times.
Jnario 0.4.0 is now based on the new type system. It further benefits from the type systems increased flexibility. For example, it is now possible to access extension fields from within nested specs:
describe "Extension in nested example groups" { extension Shouter = new Shouter describe "nested example group"{ fact "Hello".shout => "HELLO" } }The same is true for features, where you can use extension which are defined in Background scenarios:
Feature: Extension fields in BackgroundsBackground: extension Shouter = new Shouter Given a background with extension "Hello".shout => "HELLO"
Scenario: Using the background extension Then we can use the extension "Hello".shout => "HELLO"
It has always been possible to generate HTML reports for your specifications written in Jnario. This release adds the possibility to include whether a spec is currently passing or failing. All passing specs will be marked green and all failing specs will be marked red with the failure cause. This makes Jnario reports a great way to communicate the progress of your project with your stakeholders. These reports are generated using Maven. For a full example have a look here.
One feature of Jnario is that you can write more readable assertions using should. It provides a common set of matchers such as be or contains:
"Hello" should not be "World" #["red", "blue"] should contain "red"
But it is also possible to define your own should matchers. This feature has been available for a while, but was not yet featured in the documentation. You can define your own should matchers by defining a method with the prefix shouldXXXX, which needs to return a boolean value. For example, when we define a method shouldeat:
def should_eat(String animal, String food){ animal == "Monkey" && food == "Banana" }
...then we can use eat in our should expressions:
"Monkey" should eat "Banana" "Monkey" should eat "Rocks" throws AssertionError
This release greatly improves the maven support in Jnario. All you need to do to start a new Jnario project is run:
mvn archetype:generate \
-DarchetypeGroupId=org.jnario \
-DarchetypeArtifactId=jnario-archetype \
-DarchetypeVersion=0.4.0 \
-DgroupId=org.example \
-DartifactId=myproject
If you run afterwards:
mvn test
mvn org.jnario:report:generate
You can check out the newly generated doc at "target/jnario-doc".
@Extends(typeof(MySuperClass)) describe "defining super classes"{ ... }
fact "Wait for something"{ // define wait condition using lambdas waitUntil[1 > 0] // configuration options waitUntil[ message = "Custom error message" duration = 100 pollingInterval = 10 1 > 0 ] }]]>
You can find a list of all new features and bug fixes over here. Please note that this release requires Xtend 2.3 and is not compatible with the latest Xtend 2.4 milestones. You can install Jnario via update site or Maven.
]]>Scientific research has shown that it takes about 10 years or 1000 hours of practice to become an expert. The key is deliberative practice: trying new things outside the personal comfort zone. Learning with and from others is arguably the most efficient way to do so. However, finding likeminded developers outside the workplace is often difficult. The Softwerkskammer tackles this problem by providing a platform for software craftsmen across Germany for sharing their knowledge and training their skills. Today, there exist local Softwerkskammer communities in most major German cities and since recently also here in Munich!
If you are living in Munich and keen to practice with other developers, why not come to our next meeting on Thursday, November 15th? We will perform (as always) a hands-on-session, which will be based on the "Taking Baby Steps" format. It is a great way to practice programming and refactoring in small incremental steps. I can promise you this: it will definitely move you out of your comfort zone!
]]>A coderetreat is a daylong event, focused on practicing the basic principles of good design without the pressure of having to get things done. The day is split into six sessions, in which you work on the same problem over and over again. In each session you will pair with a different programmer to maximize the knowledge transfer. The important thing is that after each session all the code that has been written so far is deleted. This gives you the chance in the next session to all start over again without being constrained by any design decisions you made in the previous one. The combination of pair programming with the focus on writing perfect code instead of solving the problem gives you a unique opportunity to improve your skills.
The coderetreat will take place at the E.S.R. Labs office here in Munich. The address is:
St.-Martin-Straße 53
81669 München
We will start the day at 8:15 AM with a small breakfast and we will have time for a beer after the event at 6:00 PM. E.S.R. Labs provides Breakfast, lunch and drinks. The only thing you need to bring is your computer.
The registration starts on Tuesday November 13th. For more information check out the official page.
]]>This time I am especially excited, as Birgit and I will present together our new testing framework Jnario. For Jnario we created a set of DSLs based on Xtend making specifying and testing Java a lot easier. I have been using Jnario myself now for over a year and I can honestly say that I cannot imagine going back to writing plain JUnit tests again. If you want to learn how to write specs that test and document your programs at the same time, join our talk on Thursday 25th, 10:30am - 11:30am for a hands-on demonstration of behavior-driven development with Jnario.
But that is not everything, there are lots of other great talks I am looking forward to attend:
One of the best things about Xtend is that it compiles to readable Java code. No magic transformation into Java byte code that is impossible to understand for mere morals. Instead, it compiles to plain Java code that everyone can understand. You can see the generated code, when you create a new Xtend file in Eclipse. A new source folder xtend-gen
will be created automatically containing the generated Java code. This is really helpful when learning Xtend as you can always see what the generated Java code will look like. Another advantage is that it is no problem to use Xtend classes from normal Java classes and vice versa, because Xtend uses the same type-system as Java. These things makes it easy to integrate Xtend into normal Java projects. The only dependency of Xtend is a small runtime library consisting mostly of Google Guava (which you should be using anyway). This makes Xtend also a great choice for developing Android or GWT applications. One important thing to note is, although the Xtend tooling is based on Eclipse, Xtend is completely independent of Eclipse. You can, for example, compile Xtend files with Maven.
If we look at the following Java code, we notice that the type information on the left hand side of the assignments is actually redundant, as the type is already defined by the right hand side of the assignment:
// variable declaration String greeting = "Hello"; Map<String, Person> persons = new HashMap<String, Person>(); // with the diamond operator in Java 7 Map<String, Person> persons = new HashMap<>(); // with google collections List<String> colors = newArrayList("red", "green", "blue"); // for loops for(String color : colors){ ... }
This increases the syntactic noise in Java programs making them harder to comprehend. Xtend can automatically infer the types of a variable from the type of the right hand side of an assignment. You need to type less and your programs become more readable:
// variable declarations val greeting = "Hello" val persons = <String, Person>newHashMap() val colors = newArrayList("red", "green", "blue") // for loops for(color : colors){ ... }
If you want to, you can also let Xtend infer the type of fields and the return types of methods:
class Example { val greeting = init() def init(){ return "Hello" } }
Type inference is like having a heated steering wheel in your car, once you get used to it, you cannot imagine using a car in winter without one.
The idea behind extension methods is quite simple: you can add new methods to an object without changing it. For example, given a method:
def removeVowels (String s){ s.replaceAll("[aeiouAEIOU]", "") }
In Xtend we can call this method either like in Java:
removeVowels("Hello")
or as an extension method of String:
"Hello".removeVowels
Now, which version is more readable? Extension methods use a simple syntactic trick: the first parameter of a method can either be passed in after opening the parentheses or before the method call. You can either define extension methods in the same class or import static methods as extensions.
import static extension java.util.Collections.* ... val colors = newArrayList("red", "green", "blue") colors.sort colors.printLn // => ["blue", "green", "red"]
However, the real beauty of extension methods reveals when using dependency injection together with fields. For example, given a class Persister, which is responsible for, well, persisting stuff:
class Persister{ def persist(String s){ //... } }
In Java, whenever you use the persister in your class, you need to write something like:
persister.persist("My String");
In Xtend, you can declare the persister as an extension field and call persist directly on strings, which makes your code a lot more readable:
class Document { extension Persister persister String content new(Persister persister) { this.persister = persister } def save(){ content.persist() } }
The advantage is, you can change the implementation of Persister at any time, without sacrificing the readability of your code. By the way, with extension methods the expression problem can be solved with Xtend in an elegant way.
What the heck are lambda expressions and why are they useful? Let's start with an example in Java. Given we want to implement a method that converts each string in a list to its uppercase version. A possible solution would be:
public List<String> toUpperCase(List<String> strings) { List<String> result = new ArrayList<String>(); for (String string : strings) { result.add(string.toUpperCase()); } return result; }
But what if we need another function that replaces each string with its lowercase version? Of course, we could create a second method:
public List<String> toLowerCase(List<String> strings) { List<String> result = new ArrayList<String>(); for (String string : strings) { result.add(string.toLowerCase()); } return result; }
The problem with our solution is that we have a redundancy. Both methods create a list and add values to it. A better approach would be to separate the list modification and the string manipulations. We could do this by declaring a new interface:
public interface Function{ String apply(String input); }
And use this new interface to encapsulate the list creation and modification into a separate method, which applies the passed in function to each string in the input list and adds the result to a new list:
public List<String> map(List<String> strings, Function toApply) { List<String> result = new ArrayList<String>(); for (String string : strings) { result.add(toApply.apply(string)); } return result; }
We can now refactor our original functions to use the new map function:
public List<String> toLowerCase(List<String> strings) { return map(strings, new Function() { public String apply(String input) { return input.toLowerCase(); } }); }
and
public List<String> toUpperCase(List<String> strings) { return map(strings, new Function() { public String apply(String input) { return input.toUpperCase(); } }); }
We encapsulated our string manipulation operation into an anonymous class and pass an instance of this class to the map method which applies it to lists. The result is nice and clean code. Maybe a little bit verbose, but we got rid of all redundancies. What we actually did is, we implemented the concept of an anonymous function in Java using interfaces and anonymous classes. Another name for anonymous function is lambda expression. As we have seen, lambda expressions can be really useful for creating modular and reusable code. This is the reason why Xtend provides native support for lambda expressions. A lambda expression can be defined in Xtend within square brackets:
var lambda = [String s | s.length]
The parameter type can be omitted if the type can be coerced from the expression on the left-hand side:
var (String)=>int lambda = [s | s.length]
(String)=>int
defines a function type with a string parameter and an int return value. Single parameter functions do not need a parameter declaration and the parameter can be accessed via the implicit variable 'it':
var (String)=>int lambda = [it.length]
...and we can even completely remove the 'it' variable:
var (String)=>int lambda = [length] lambda.apply("hello") => 5
Xtend provides a large library of extension functions such as map
providing commonly needed functions. We can write our two functions as:
def toUpperCase(List<String> strings){ strings.map[toUpperCase] }
and:
def toLowerCase(List<String> strings){ strings.map[toLowerCase] }
Which is a lot more concise than the Java version. And again, there is no magic going on here, the generated code is plain and understandable Java code. The generated code is actually similar to the Java example described before.
Xtend has its roots in Xpand, a widely used code generation framework. This is also where Xtend powerful template expressions come from:
val colors = newArrayList("green", "blue", "yellow") val html = ''' <html> <body> My Colors: <ul> «FOR color : colors» <li>«color»</li> «ENDFOR» </ul> </body> </html> ''' println(html)Template expressions are multiline strings enclosed by
'''
. These strings can be further enriched with expressions in so called guillemets «expression»
. Such expressions can be either used to insert the expression result into the resulting string or to control the string generation with loops or conditions.
So far, these features are common to most templating languages. However, where Xtend really shines is when it comes to handling white space. Usually it is pretty hard to generate readable code with proper indentation. Xtend processes whitespaces in a clever way making it easy to generate properly formatted code. You can see in the Eclipse editor clearly which whitespace is generated and which not by the syntax coloring:
This has been my five favorite features of Xtend. For me it is hard to imagine going back normal to Java after using Xtend. The Eclipse tooling is already pretty good with support for refactoring and debugging. There also exists a great testing framework which is based on Xtend. I can definitely recommend giving Xtend a try, especially if you require seamless interoperablity with existing Java code.
]]>This release improves the tooling support for Jnario and fixes some problems when compiling specs. One great new feature is that the Jnario editor provides now quickfixes for creating new Java and Xtend types.
There is also a new quickfix for creating new methods in existing Java and Xtend types. This helps the development flow a lot, easing need-driven development.
The code completion for feature definitions has also been improved. You now get proposals for steps that don't have an implementation yet. The code completion will also automatically add import statements for steps defined in different packages.
Finally, there have been some important fixes making the compilation of specs and features a lot more robust. This makes it now possible to use extension fields in your feature files. You can find a list of all fixed issues here.
The latest release can be installed via the update site or Maven. If you want to learn more about Jnario visit the official homepage www.jnario.org. There is a new tab in the Jnario documentation showing the original Jnario spec from which it is generated. For questions or discussions join the Jnario mailing list.
]]>We completely bootstrapped the implementation of Jnario. This means we write all tests for Jnario with Jnario. One feature of Jnario we are using heavily is the possibility to convert specs to html documents. The complete Jnario documentation is created that way. Each documentation page is generated from an executable spec. Generating the documentation from specs saves a lot of time as you can use the same examples for testing and documenting your application. Furthermore, it ensures that all code samples in the documentation are correct. For example, here is a specification:
and this is what the generated documentation looks like:
However, at one point during the development of Jnario I had the problem that I needed to create an overview page for the documentation. The overview page was supposed to describe the structure of the documentation with links to the different subtopics. Creating it manually felt wrong as it takes away the advantage of being able to just generate the documentation without having to touch it. Furthermore, whenever I change the name of a specification file I would need to manually update the links in the overview page. Considering my forgetfulness, this would mean broken links galore.
When I thought about it, I realized that the underlying use case is actually pretty common: being able to group tests based on certain criteria. In JUnit you would use test suites for this. To solve my problem, I just had to take this concept one step further and add the possibility to provide additional documentation. This is exactly what you can do now with Jnario Suites. A suite looks like a normal document written in markdown syntax, but you have the possibility to reference other specs or suites. These references are actual links to the existing spec files, which means the editor provides code completion for available specs and shows validation errors if specs are missing. Even better a Jnario suite compiles into a normal JUnit test suite. This means you can execute Jnario suites like any other test suite. Here is the suite file for the overview page of the Jnario documentation:
Having to explicitly reference all specs in a project can become quite tedious over time. This is why it also possible to reference multiple specs at once by matching the qualified name of a specs using a regular expressions. Here is another suite from the Jnario code base that we are using to execute all Jnario specs in our test project:
So far I am really happy with the result. Jnario suites fill the gap between being able to write executable specs and being able to generate usable documentation from them. They are also useful during development, for example, I started using suites as todo lists for features that I need to implement (pro tip: there is a quickfix in the suite editor to add missing specs).
If you want to learn more about Jnario visit the official homepage www.jnario.org. There is also a mailing list available for questions and discussions. Follow me on twitter if you want to stay up-to-date with Jnario.
]]>This changed last year, when Xtext introduced the possibility to reuse and integrate all kinds of Java language constructs right into your own DSL. This makes it possible to create DSLs that seamlessly interact with Java objects while providing excellent tool support. A good demonstration of the potential Xtext is Xtend. Xtend is a language extending Java with additional constructs such as lambda expressions that compiles to idiomatic Java code.
Using Xtext, it has now become feasible to create a language specifically for testing Java programs that tightly integrates with Java and features a syntax specifically designed for writing concise and readable tests. This is exactly what I have been working on together with my colleague Birgit. We are now happy to announce the first official Jnario release. To get started head over to the Jnario website.
If you don't know Jnario yet, Jnario is a new test framework for Java enabling you to write concise tests that clearly express the expected behavior of your code (this is why we refer to tests written in Jnario as specs). This is possible, because Jnario is a language being specificially built for the purpose of writing tests. Specs written in Jnario compile into Java source code and you can seamlessly interact with Java objects. Jnario provides two languages for specifying the behavior of your Java programs. The first one is good for writing specs from a developer perspective:
The second one can be used to create executable acceptance specifications from a customer perspective similar to Cucumber:
Jnario provides custom assertion and matchers, for example, you can use should
statement to express the expected behavior of objects. There is also a short cut available: =>
which has the same effect.
// equality true should be true 1 + 1 should not be 1 "something" should not be null 1 + 1 => 2 // expecting exceptions new Stack().pop throws EmptyStackException // types "a string" => typeof(String) // strings "something" should contain "thing" "something" should not contain "any" // iterables list("something") should contain "something" list("something") should not contain "something else" // using xtend's "with" operator "hello world" => [ length => 11 it should startWith("hello") it should endWith("world") ]
When failing, should
and =>
try to give you as much context information as possible.
The error message will print the values of all expressions and their sub-expressions. For example:
Expected x.toUpperCase should not be "HELLO" but x.toUpperCase is "HELLO" x is "hello"
Another great thing about Jnario is that you can easily generate documentation from your specs (the complete Jnario documentation has been generated from specs written in Jnario). This is what the HTML documentation looks like that is generated form the previous stack specification:
and for the calculator example:
Jnario provides a fully integrated IDE for Eclipse, which means its tooling provides all the amenities one would expect from a state of the art IDE: syntax highlighting, code completion, validation, and incremental build. However, this doesn't mean that Jnario is restricted to Eclipse. Compiler, documentation generator and runtime are completely independent from Eclipse and can also be used, for example, via Maven.
In this first release of Jnario we focused on the basic features of each language, but we have lots of ideas about how to further improve Jnario. The three main features that we plan focusing on in the next releases are:
For a more detailed introduction, read my previous post or visit the Jnario website. There is also a mailing list available for questions and discussions.
]]>For those who don't know Jnario yet, Jnario is a new test framework for Java focusing on the design and documentation aspects of testing (for an introduction see my previous blog post).
You might have wondered about the title of this post "20 Facts about Xtend". In Jnario we write specifications by stating facts about our software. Here is a simple fact about Xtend (=>
describes the expected behavior):
fact "'+' concatenates collections"{ list(1, 2) + list(3, 4) => iterable(1, 2, 3, 4) }
Now it should become clear why this post is titled "20 Facts about Xtend" - the Xtend introduction is generated from a spec consisting of 20 facts. Being able to generate HTML documentations from specs is one of my favorite Jnario features. The follwing screenshot shows the spec in the Eclipse editor. Note that you can run this spec as a normal JUnit test. This means code snippets in your documentation will always work, as otherwise the excution will fail. Executable documentation FTW!
Visit www.jnario.org for more information about Jnario. There is also a mailing list available for questions and discussions. Follow me on twitter if you want to stay up-to-date with Jnario.
]]>Jnario is based on Xtend. Xtend enriches Java with lambda expressions, type-inference, multi-line strings and more. The good thing about Xtend is that it uses the same type system as Java and is compiled to readable Java code. This means when writing specs with Jnario, you can use all the goodness of Xtend resulting in less boilerplate code in your specs. Furthermore, Jnario is easy to integrate into existing Java projects, as specifications compile to plain Java JUnit tests.
With Jnario you can create executable acceptance specifications that are easily readable and understandable to business users, developers and testers. Jnario uses a similar textual format to Cucumber. The idea is to describe the features of your application using scenarios. The preconditions, events and expected outcomes of a scenario are described textually with Given, When and Then steps. Here is an example acceptance specification for adding values with a calculator:
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"
These scenarios can be made executable by adding for each step the required code to establish preconditions, trigger events or assert properties of the resulting state. 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. In our example we create a calculator, pass in the parameters defined in the steps (via the implicit variable args
) and check the calculated result:
... Scenario: Add two numbers Calculator 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
This reduces the effort in writing scenarios by not needing to maintain separate step definitions. Of course you are still able to reuse existing step definitions in your scenarios. You even have code completion in the editor showing all existing steps. In our example, the step And I have entered "70" into the calculator
reuses the code of the step Given I have entered "50" into the calculator
with a different parameter value. You might think now that mixing code and text in your specs makes everything pretty unreadable. Actually, this is not a problem, as you can hide the code in the editor to improve the readability:
Scenarios are good for writing high-level acceptance specifications, but writing scenarios for data structures or algorithms quickly becomes tedious. That is why Jnario provides another language for writing unit specifications. This languages removes all the boilerplate from normal JUnit tests helping you to focus on what is important: specifying facts that your code should fulfill. The notion of facts was inspired by Brian Marick and Midje, a test framework for Clojure he developed. A fact can be as simple as a single assertion:
package demo import java.util.Stack describe Stack{ fact new Stack().size => 0 }
We use =>
to describe the expected result of an expression (Jnario also supports assert and should). More complex facts can have an additional description:
package demo import java.util.Stack describe Stack{ fact "size increases when adding elements"{ val stack = new Stack<String> stack.add("something") stack.size => 1 } }
Objects can behave differently in different contexts. For example, calling pop
on a non-empty stack decreases its size. However, if the stack is empty, pop
results in an exception. In Jnario we can explicitly specify such contexts using the context
keyword:
package demo import java.util.Stack describe "A Stack"{ val stack = new Stack<String> context "empty"{ fact stack.size => 0 fact stack.pop throws Exception } context "with one element"{ before stack.add("element") fact stack.size => 1 fact "pop decreases size"{ stack.pop stack.size => 0 } } }
You can execute unit specifications as normal JUnit tests. Note that Jnario uses the description as test name or, if not present, the actual expression being executed. If you look at the executed tests, you see that your specifications effectively document the behavior of your code.
Jnario is not just another testing framework. It is actually two domain-specific languages specifically made for writing executable specifications. If you think about current testing frameworks, they usually "stretch" the syntax of the underlying programming language to be able to write expressive tests. Now imagine a programming language in which the syntax is specifially designed for the purpose of writing tests. For example, a common scenario is to test a class with different sets of input parameters. I don't know about you, but I find it really hard in JUnit to write parameterized tests. Writing such tests in Jnario is really easy as it has a special table syntax:
describe "Addition"{ def examples{ | a | b | sum | | 1 | 2 | 3 | | 4 | 5 | 9 | | 10 | 11 | 20 | | 21 | 21 | 42 | } fact examples.forEach[a + b => sum] }
Tables in Jnario are type safe: the type of a column will be automatically inferred to the common super type of all cells in a column. You can easily iterate over each row in a table and write assertions by accessing the column values as variables. If you execute the example specification it will fail with the following error:
java.lang.AssertionError: examples 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
This demonstrates another advantage of Jnario, it tries to give you as much information as possible about why an assertion failed. 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 an assertion failed. This works out of the box, without any additional constraints such as "your source files must reside in a specific folder".
These are just two examples demonstrating the advantages of test-centric domain-specific language. Having full control over the syntax of the language and its translation into Java code allows us to add features that are helpful when writing tests, but would never make sense in a general purpose language.
A common complaint with new languages is that the tooling support is insufficient. Jnario has been built with Xtext. This means its Eclipse tooling provides all the amenities one would expect from a state of the art IDE: syntax highlighting, code completion, validation, incremental build,... Even better, there is debugging support:
We completely bootstrapped the implementation of Jnario - all tests for Jnario are written with Jnario. After using Jnario for a while now, I can honestly say that I cannot imagine going back to writing normal JUnit tests. Jnario is under active development by myself and my colleague Birgit Engelmann from BMW Car IT. If you want try Jnario or learn more about it, head over to the offical page www.jnario.org. There is also a mailing list available for questions and discussions. You should follow me on twitter if you want to stay up-to-date with Jnario.
]]>While developing, I often store code snipplets in my todo files. To make these more readable, I added support for custom syntax highlighting for different programming languages. The only thing you need to do is to declare the language after the code block literal: '''java public class MyClass{ public static void main(String[] args){ System.out.println("Hello World"); } } ''' Here is an example what it looks like in the editor
You can now specify links and images in the todo files. The editor automatically underlines links within the text. You can open a link by pressing F3 or hold CMD/STRG when clicking on it. Links with descriptions and images can be specified in Markdown syntax:
You might have wondered why one wants to specify links or images in a todo file. This comes in handy with the new export feature: todo files can now be exported into HTML or Confluence Markup using the context menu in the editor. Links and images will be translated into their respective counterparts. Here is an example how this blog post would look like (note that the syntax highlighting in the code snippet is still present).
Other new features are:
A coderetreat is a daylong event, focused on practicing the basic principles of good design without the pressure of having to get things done. The day is split into six sessions, in which you work on the same problem over and over again. In each session you will pair with a different programmer to maximize the knowledge transfer. The important thing is that after each session all the code that has been written so far is deleted. This gives you the chance in the next session to all start over again without being constrained by any design decisions you made in the previous one. The combination of pair programming with the focus on writing perfect code instead of solving the problem gives you a unique opportunity to improve your skills.
Since hearing about coderetreats I have facilitated two internal coderetreats at my workplace. They turned out be great fun and we all learned a lot during the day. This is why I am really happy to announce that we will be facilitating a public coderetreat at BMW Car IT on December 3rd. This coderetreat will be part of the Global Day of Code Retreat initiated by Corey Haines. Coderetreats will take place all over the world. The event is free of charge, food and drinks will be provided by BMW Car IT. If you are a programmer and eager to learn, head over to www.coderetreat-munich.de for more information and registration.
]]>