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:


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="" />
     <arg line="-p ${build.dir}" />
     <arg line="-o" />

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

Week 5, Tuesday

April 21, 2009 at 9:26 pm (Java, Week 5) (, , , , , , , , )

Eric and I spent the morning making some styling tweaks to the Rails application, and I moved back to Tic-Tac-Toe in the afternoon. I got the board score caching to work almost immediately, or so I thought. Micah sat down with me to help me with my Ant build, which had been broken since I split the project up into packages. The fix there turned out to be easy (with the right knowledge): I needed to add JUnit to the compile classpath. For some reason I had it in the classpath for the <junit> element for running the actual tests, but not in the compile.

So then we took a look at my caching mechanism, which was taking up the whole heap and throwing errors at 6 levels deep in the game tree. Micah helped me to increase the heap size to 512MB, which got us to 9 or 10 levels deep, but we still eventually took up the whole heap again. We spent some time with a profiler tracking down the objects being created, and of course it was the hashed objects (~ 6 million of them) taking up all the memory. We worked for awhile to decrease the memory we were using, but we didn’t end up making it any more levels deep. At this point, the 4×4 computer player still makes some weird moves near the start of the game, but he gets smarter towards the end and avoids losses.

Micah noticed that my caching didn’t have tests (cringe), so that was my next assignment. Because my minimax method was so big and complicated, I kind of went to town with the Extract Method refactoring and eventually figured out a way to get some tests written on the caching part. Along the way, I discovered that JUnit doesn’t allow you to test private methods, and got some “Extract Class” knowledge dropped on me by Doug, who said that if I had a private method that wasn’t already covered by tests on my public methods, maybe those private methods really belonged somewhere else, as public methods on another class! For now, I’m just changing the method I wanted to test into a public method.

I like the looks of this class a lot better now that it has smaller methods – it’s a lot more readable. I think I picked some decent names, like writeScoreToCache(), getCachedScore(), getValueToOtherPlayer(), finalScore(), calculateBestScore(), etc. There is still a lot to be done for this program to look like something out of one of these books I’ve been reading, but it’s getting closer. And I’m getting a lot better at seeing what the differences are, which I think is really positive.

Permalink 1 Comment

Week 2, Friday

April 3, 2009 at 8:09 pm (Java, System Administration, Week 2) (, , , , , , )

Time is flying a lot faster now. Today I looked at some new technologies (new to me, anyway): Ant and the KML API for Google Maps.

For Rubyists out there, Ant is analogous to Rake, but in the Java world (and Make for C/C++/others). It’s kind of an automated build tool, so that you can avoid duplicating labor each time you want to build a project and run the test suite (or any number of other things). Micah wanted me to build an Ant task that would run all of my tests. So I checked out the Ant manual, but it wasn’t much help at all to me until I’d seen and worked my way through a concrete example. It’s pretty nifty – until now, as far as I knew, I’d have to either let IntelliJ run the tests for me or go through each test class manually running the JUnit tests.

I also had to fix my directory structure to make it more idiomatic for a Java project. Previously I just had my src directory with all my *.java files under version control, but it turned out that what I really needed was to go up a directory and have the main project under version control (Git). This presented a problem for me in that if I just moved my .git directory up to the main project directory, it would appear to Git that I’d deleted and re-added a bunch of files, which would mean that every file’s history would begin again, and I’d lose the ability to see small changes from the previous commit to the next one (just for a certain commit, but still, I didn’t like it). Here’s the workflow I used to move Git’s notion of the structure up a directory, in case anybody else runs into the same issue:

  1. mkdir src/src
    because I knew I was going to need to see the current source files in an src directory, but it needed to be relative to the current Git location, src
  2. git mv src/*.java src/src
    here’s where I’m telling Git to rename the files – the key action that allowed me to preserve history on the same file
  3. mv src/src src_new
    moving the actual source files up to a new folder in the root (which is going to be src eventually, but since “src” is taken for now…
  4. mv src/.git .
    one of the many cool things about Git is that ALL of the versioning information is contained in a single directory – no .svn directories littering the project and making change like this difficult
  5. mv src src_old
    making way for the new src directory
  6. mv src_new src
    in place the way we need it
  7. git status
    checking to make sure things look good, with files being renamed instead of added and deleted)

Pretty simple, considering my initial worries. Thanks, Git!

My time with KML so far has been pretty educational, but I haven’t actually gotten anything done yet, I’ve just been investigating options. I’m working on a problem where I have points on a map with identical latitudes and longitudes, and I need to tell Google Maps to display them as separate points somehow. I’ve found a way to make Google Earth do it fine, but Google Maps is a different story.

Another task I’ve got before I get going on 3-D Tic-Tac-Toe is to split my 2-D version into packages. So I’m going to bone up on the package principles this weekend. I have a tentative separation already (there was some Git love that needed to happen there, too, when I moved files around), but I know have some Common Closure Principle violations I need to take care of before daring to show it to Micah.

Permalink 1 Comment