New API for programming languages

29 views
Skip to first unread message

aslak hellesoy

unread,
Aug 13, 2009, 8:20:23 PM8/13/09
to cu...@googlegroups.com
As most of you know, Cucumber runs fine on the JVM via JRuby, and this opens up the world of wonderful cukes for most of the languages on the JVM. There is a lot of great innovation on the JVM. Scala, Clojure, Groovy and Ioke to name a few are very interesting languages. And then there is Java of course. Lots of people still use Java.

The same is true for the CLR/DLR (.NET) via IronRuby. C# is actually getting pleasant (and confusing), F# is a wonderful language for functional/object oriented programming similar to Scala.

The Cuke4Duke sister project of Cucumber has shown that JVM language integration is relatively easy to implement. But until recently Cucumber hasn't had a good API to plug in other programming languages than the built-in support for the host language - Ruby. Cuke4Duke started as a proof of concept, and I didn't pay much detail to API design. I just wanted to get something working, so I hacked together a soup of monkey patches in Ruby. Then people started using it :-)

There were several problems with this approach. Setup was clunky. People had to add env.rb files to register their step definitions. Things were kind of working with Java, but it turned out hard to leverage e.g. Groovy's dynamic features so that Step Definitions could be written in a DSL similar to Ruby Step Definitions. There was no way to use two programming languages side by side. There was no clean way to have Cucumber print snippets in another language etc etc.

All of these problems have now been solved. In order to achieve that I had to refactor on both sides. Cucumber now has abstractions for 4 concepts: Programming Language, World blocks, Step Definitions and Hooks. Cuke4Duke's monkey patch soup code in Ruby has been replaced with Java implementations of the new Cucumber Programming Language API. Translation of String and primitive type arguments is handled transparently by JRuby. Table arguments get converted back and forth via a Table java interface.

This means that you can write step definitions in Java (using @Given etc annotations) and Groovy (using a Ruby-like DSL). Step Definitions in those languages have access to almost all of the same Cucumber abstractions as in Ruby. There are a few things missing, like calling Steps from Step Definitions, Receiving a typed Scenario object in Hooks to name a couple, but this is fringe functionality that can be added later.

Scala is coming up pretty soon, with Python to follow. The Twitter community has helped with lots of great suggestions for a Scala DSL. I think I'm going to go with something based on Dean Wampler's gist: http://gist.github.com/161702 (James Strachan, author of Groovy likes it too - https://twitter.com/jstrachan/status/3229533874).

In the context of Cucumber and Language support I like think of 2 distinct levels of interop. The simplest one is indirect interop. This is when you talk to another language from Ruby Step Definitions. Exampes are JRuby and rubypython, and this technique only relies on a 3rd party bridge from Ruby to another language. There are examples of this in examples/java and examples/python. Another example is Ian Dees' Cucumber on the iPhone, which uses HTTP to send commands and retrieve results from the iPhone.

The other kind of interop is bidirectional. This means step definitions are written in another language than Ruby, and Cucumber sends arguments into those step definitions. This is typically done using the same kinds of 3rd party bridges as for indirect iterop, but it's used in the both directions, not just one. The iPhone approach could also be developed further so that people can write Step Definitions in Objective C, testing iPhone apps or OS X apps. Did I mention RubyCocoa?

I have pushed these changes to the programming_language branch in my cucucumber repo. The refactorings shouldn't affect you unless you are using some obscure internal API in Cucumber, but I want to give everyone the chance to play with it before I merge it into master. Currently all the features are passing, but there are currently 33 failing specs. It shouldn't be too hard to fix these. One thing I know broke - Spork. I have fixed this in my own spork fork and pushed it to GitHub. A new release of Spork () will have to be made in order for Spork and Cucumber to work together.

I will be doing a rundown of all of this at the RubyFoo conference in London in a couple of monts.

In the meanwhile I'm looking for feedback and patches ;-)

Cheers,
Aslak

Matt Wynne

unread,
Aug 14, 2009, 12:09:11 PM8/14/09
to cu...@googlegroups.com

This all sounds terrific.

I've been starting to work on a re-usable library of Step Definitions,
pulling all the ones that aren't domain-specific out of songkick's
features directory and into vendor/plugins (for the time being).

I wonder: would this make it possible to use libraries of step
definitions that are written in several languages? So if we had a
library of step definitions packaged as a ruby gem, could people
testing java projects use them, along with their domain-specific steps
written in java?


cheers,
Matt Wynne

http://mattwynne.net
+447974 430184

Aslak Hellesøy

unread,
Aug 14, 2009, 12:33:55 PM8/14/09
to cu...@googlegroups.com, cu...@googlegroups.com
Yep
Reply all
Reply to author
Forward
0 new messages