Growing object-oriented software in JRuby - Part 1
As part of my constant quest to overcome the feeling of, "There has to be a better way to do this," I've been reading Growing Object-Oriented Software, Guided by Tests.
One of the things that the authors endorse, and which now seems so obvious that I can't believe I've never done it, is to start development with an end-to-end test. They define end-to-end as including the whole deployment pipeline and all the services that the application is expected to use. This forces the developers to integrate with a lot of different systems. The upside is that this shakes out a whole bunch of problems very early on. The downside is that the developers may experience a lot of pain before they've shipped a single feature. Still, that's better than experiencing all that pain at the end of a delivery cycle with a looming deadline.
With that in mind, I started trying to implement their non-trivial worked example while working through the book. Their code is in Java. I've worked in a bunch of C family languages and I don't enjoy it very much (they're very verbose) so I thought I'd try implementing the example in Ruby instead.
The example is a Desktop application. I've never developed a desktop application in Ruby and I wondered how to drive the application during automated tests. Ruby is well served by Capybara for web application testing but I wasn't aware of a desktop GUI equivalent. I started to research this, realised that the majority of tools might be based on functionality missing from my desktop environment, and decided pretty quickly to back-pedal.
At this point, I was tempted to resort to using Java after all. Any dislike of Java on my part is not a huge deal and in the past I've written some trivial Java programs. On reflection though, I decided that I was going through the "front-loaded pain" associated with constructing my end-to-end test and gave myself a break. Instead of using Java I had a look at JRuby. JRuby runs on the JVM and should give me access to the same GUI driver, WindowLicker, that the authors were using. Hey, why not?
This turned out to be non-trivial partly because of some poor error messages on JRuby's part, and partly because of my ingrained habit of letting tests and/or compilers tell me what's wrong rather than activating my under-used initiative...
WindowLicker requires another library called Hamcrest. Apparently Hamcrest is useful to Java programmers for implementing "matchers". The examples I've seen would be pretty trivial in Ruby so I haven't had enough stimulus to properly try grokking this library yet. Anyway, I hadn't downloaded Hamcrest when I first tried to use WindowLicker and rather than a useful error message ("Hey buddy, you're missing a dependency!") I got this...
NameError: missing class or uppercase package name (`com.objogate.wl.swing.driver.JFrameDriver') get_proxy_or_package_under_package at org/jruby/javasupport/JavaUtilities.java:54 method_missing at file:/home/justin/.rvm/rubies/jruby-1.7.3/lib/jruby.jar!/jruby/java/java_package_module_template.rb:14 (root) at /home/justin/code/goos/app/application_runner.rb:7 require at org/jruby/RubyKernel.java:1027 (root) at file:/home/justin/.rvm/rubies/jruby-1.7.3/lib/jruby.jar!/jruby/kernel19/kernel.rb:1 require_relative at file:/home/justin/.rvm/rubies/jruby-1.7.3/lib/jruby.jar!/jruby/kernel19/kernel.rb:19 load at org/jruby/RubyKernel.java:1046 (root) at /home/justin/code/goos/tests/end-to-end.spec:1 each at org/jruby/RubyArray.java:1613 (root) at /home/justin/.rvm/gems/jruby-1.7.3@goos/gems/rspec-core-2.14.5/lib/rspec/core/configuration.rb:1 load_spec_files at /home/justin/.rvm/gems/jruby-1.7.3@goos/gems/rspec-core-2.14.5/lib/rspec/core/configuration.rb:896 load_spec_files at /home/justin/.rvm/gems/jruby-1.7.3@goos/gems/rspec-core-2.14.5/lib/rspec/core/configuration.rb:896 run at /home/justin/.rvm/gems/jruby-1.7.3@goos/gems/rspec-core-2.14.5/lib/rspec/core/command_line.rb:22
Now that I've solved that, I'll get on with the rest of my end-to-end test...