Thursday, January 31, 2013

Having fun with Cucumber, Groovy, Jacob, COM, TestComplete and Notepad

Finally I've had some more time to explore new stuff - and since BDD is steadily gaining in popularity I thought I'd try to see how one could achieve BDD with TestComplete - SmartBears indispensible tools for web and GUI testing. And even if you're not interested in TestComplete - please stay with me as I will use a bunch of other cool technologies on the way (as indicated by that seductive title).

The Cast


The main characters in this blog-post are:

  • BDD (Behavioral Driven Development) is an extension of TDD where you define behaviours in an agreed-upon vocabulary and use these to drive your tests (greatly simplified) - read more about the whole idea at http://dannorth.net/introducing-bdd/
  • Cucumber is one of the more popular BDD frameworks out there - here we will be using the java version (Cucumber-JVM) with its integrated support for the groovy language
  • Jacob is an open-source library that makes it really easy to call COM objects on the .NET platfrom from Java - and specifically from groovy via the scriptom library.
  • TestComplete is SmartBears premier tools for automated testing of Web and Desktop applications (for MS platforms)
  • Notepad is the text editor that we all resort to once in a while
Of course several of these could be replaced with others; Cucumber with JBehave, TestComplete with any application that can be automated over COM (Word, Excel, Outlook, you name it) - and notepad with anything you might want to test with TestComplete; your website or a desktop application for example.

The feature definition


I started out by using cucumber and BDD for specifying a simple feature scenario - here it comes in cucumber lingo:


In cucumber (and most other BDD frameworks) you express your requirements in a Given/When/Then kind of syntax - reasonably legible by both business and developers. Agreeing on the vocabulary used in these files is probably one of hardest parts in BDD - and there is much written about it - in this case I've chosen an imperative approach which skips the nitty-gritty steps of the underlying actions (read more about Declarative vs Imperative at http://benmabey.com/2008/05/19/imperative-vs-declarative-scenarios-in-user-stories.html)

The groovy cucumber code


The next step is to write the code that will be invoked to execute these "steps". Cucumber has a nice groovy integration which makes the code pretty straight forward - here it is:



As you can see there are handlers for Given, When and Then "events" in the feature file - these are "found" by cucumber using the specified regular expression syntax which is used to match the correspond Given/When/Then statements in the feature definition and extract arguments from them. The "World" closure at the top of the file should return an object that will be implicitly available in your other handlers, thus the calls to runRoutine and runRoutineEx further down are actually calls to the methods in the created TestCompleteWorld class.

Calling COM from Groovy


Calling into Windows applications can be done in a number of ways, in this case I wanted to access TestComplete via its COM Automation interface (read more about COM automation at wikipedia). This is where the jacob library comes into the picture - it makes it extremely easy to call into COM objects from Java - and thanks to the scriptom library for groovy calling COM from groovy is even easier. Given this, the groovy code here is more or less a proxy for calls made to TestCompletes COM interface, which just "proxies" the calls from cucumber to TestComplete.

To keep this plumbing outside the stepdefs file I have hidden it in the TestCompleteWorld class created in the closure at the top. Here comes the constructor that launches TestComplete and sets it up for handling our calls:


(see the entire class at GitHub)

If you are familiar with COM this is pretty straight-forward; the code creates or connects to an existing TestComplete object and does most of the further automation by calling methods in TestCompletes Integration object - which invokes the corresponding functionality in TestComplete.

The TestComplete scripts


All right - let's have a look at the TestComplete side of things; the project is very simple:



The project specifies notepad under the TestedApps node in the project, and contains two JScript units; "NotepadSteps"  (which you can see in the screenshot) contains the actual handlers called from cucumber, and "NotepadStepsTest" which I used to test the handlers during development. The handlers themselves are pretty simple; they automate notepad (ie run it and invoke it's actions) and write some logging information to the TestComplete Log. Thanks to TestCompletes recording functionality it is easy to create handlers that invoke UI actions - as the recording can be converted to a script that you can refine as desired (which is what I did for the "I_load_the_file" method).

I have set the names of the handlers ("notepad_is_running", "I_load_the_file", etc) to be the same as the corresponding handlers in our groovy Stepdefs above - but this is just a convention, I could have named them anything valid.

The Intellij Project


The corresponding IntelliJ project for the above looks as follows:



Core components (as already described above) are:

  • NotepadStepdefs.groovy - the groovy handlers shown above 
  • TestCompleteWorld - the groovy class shown above
  • notepad.feature - the feature file shown above
Additional resources are:
  • a custom CukeRunner to run JUnit tests with Cucumber (an empty class with some annotations)
  • text files in the src/test/resources/data folder used in the tests themselves
  • the TestComplete project is in the src/test/resource/testcomplete folder
  • the maven pom.xml (although the tests don't run with maven yet - to be fixed)
  • the jacob dlls copied to the root folder of the project (so they can be found during execution). Jacob will choose the one corresponding to your architecture automatically

How it all fits together


Since a picture says more than many words - so here comes a diagram trying to give you an understanding of how all these components fit together:





(the 3 components in green are those that I had to code myself)

Verbally this translates to; when running my tests I use JUnit which uses a custom CukeRunner to invoke Cucumber, which reads the feature file and calls the corresponding handlers in the groovy Stepdefs. These in turn use the Jacob library to launch and automate TestComplete, which in turn automates Notepad via JScript handlers. Piece of cake.

Action!


Instead of showing you a bunch of screenshots of this running I've created a short video - please bare with the quality and enjoy that this actually works :-)




How would one use this?


Here at SmartBear we will be evaluating this framework for automating basic GUI tests of both SoapUI and LoadUI. Given there are three main artifacts required here (the feature files, the stepdefs and the TestComplete handlers) it makes for a pretty good fit for how we work; features are defined together with the product owner and the stepdefs and TestComplete scripts are created by devs and testers in our team - the clear separation between these could make for a nice workflow (but we'll see about that - and I promise to report back even if it fails).

Next Steps?


For us we will be looking at how to get this running from Jenkins (which will pose some challenges in regard to launching windows applications), and we will of course expand our feature vocabulary and corresponding scripts in line with our requirements.

For you? The sky is the limit!

The above code is on GitHub at https://github.com/olensmar/cucumber2testcomplete. - please don't hesitate to comment, complain, suggest or fork!

Thanks for your time,

/Ole

P.S. If anyone could suggest an easy way to get syntax-colored code into a blogger blog-post I would be very grateful, inserting screen-shots of editors seems kind-of flaky...