Jemmy in Scala and readying for deployment

June 11, 2009 at 10:08 pm (Scala, Week 12) (, , , )

I spent most of the morning working on integration tests to make sure I’ve got control of the Swing side of things. Jemmy is the library I’m using to drive these high-level tests. It’s great that I can now find some text on a button and click that element – it gives me a high level of confidence that I’m not going to break things when I go in and refactor things a bit later on. There were a few gotchas I ran across, so I thought I’d share those for anyone else trying to integrate Jemmy into a Scala project.

First of all, getting up and running was a bit of a trial. I knew I wanted to drive the tests with the same framework I’m using for the rest of my testing on this project: Scalatest (which is awesome, by the way – lots of choices for test syntax, though no mocking capabilities that I know of). There was some talk in the Jemmy docs online about writing a main function in your test class, which I wanted to avoid, and the only way I found to fire up the application was something like this:

new ClassReference("SwingTicTacToe").startApplication()
mainWindow = new JFrameOperator("Tic-Tac-Toe")

And, to end it:

Thread.sleep(200)
mainWindow.close()

The sleep was a workaround for what I believe to be a threading problem – I spent about an hour trying to figure out why my tests were not failing as they should have been if mainWindow was closed after they ran, only to find that there was apparently a timing issue going on when I added a println right before closing the window. The println took just long enough to give me the right behavior a little more than 50% of the time. All of this weirdness leads me to believe that there’s an easier way to do this. Eric Smith worked around it in a Java application he’s working on by using Mockito to mock out the application itself (sounds like he’s restricting Jemmy testing to his view), but I’m not sure how I’d do that in Scala.

Another problem I encountered was getting the tests running in an Ant task. I ended up with this:

<target name="test-integration" depends="clean, init, build.compile, test-integration.compile">
   <exec executable="scala">
     <arg line="-cp ${statemap.jar}:${scalatest.jar}:${jemmy.jar}:${build.dir}" />
     <arg line="org.scalatest.tools.Runner" />
     <arg line="-p ${build.dir}" />
     <arg line="-o" />
   </exec>
</target>

Of course, this is relying on some other definitions elsewhere in my build.xml file, but the problem I had was that I didn’t have a task like I would have with Java. Also, it’s important to note that all the arg tags have attributes name “line”. When I was following examples I saw in the Ant documentation, I saw lots of tags that looked like <arg value="..." />. This didn’t work in my case, apparently because “value” mangles strings with spaces somehow. Changing “value” to “line” did the trick immediately.

I also spent some time breaking my previously single-directory, default-package code into parallel test and source directories, with four packages: basegame, gui, console, and players. I still have some final code quality checks I want to do, but it’s very close. If I have time left over after passing through again for SOLID violations, I may work on some styling and learn about graphics objects and drawing in Swing (gradients, specifically).

Permalink Leave a Comment