The Kaptain on … stuff

10 Apr, 2009

More Groovy/Griffon/FEST Testing

Posted by: TheKaptain In: Development

In my continuing exploration of FEST testing using Groovy and the Griffon framework, I’ve added some tests for the ability to change the JXBusyLabel coloration on the fly.

Since FEST allows you to alter the properties of the widgets directly, I didn’t have to do anything special to trigger actions on the JXColorSelectionButton. At first look, I thought that specifying mouse click point locations would be necessary, but after digging a(very little) bit I discoveregroovyd that FEST exposes the underlying Component its’ Fixture classes wrap as an internal ‘target’. Simply grabbing that Component and settings the background color directly was sufficient.
Here is the new definition of the JXBusyLabel and the 3 buttons which controls its color changes. You can see that two of the three color changes happen automagically due to Groovy binding – setting the background color of the label didn’t appear to work for some reason that I have yet to puzzle out, so it gets a PropertyChangeListener ‘old school style’.

baseColBtn = colorButton(name: 'baseColBtn', background: model.baseColor)
highColBtn = colorButton(name: 'highColBtn', background: model.busyColor)
backColBtn = colorButton(name: 'backColBtn', background: PaintUtils.BLUE_EXPERIENCE.getColor1())
backColBtn.addPropertyChangeListener("background", {PropertyChangeEvent evt ->
      label.setBackground((Color) evt.getNewValue())
} as PropertyChangeListener)

label = jxbusyLabel(name: 'busyLabel',
      preferredSize: new Dimension(model.W / 2 as int, model.H / 2 as int),
      busyPainter: busyPainter(
      highlightColor: bind { highColBtn.background }, baseColor: bind {baseColBtn.background},
      points: bind {slider.value}, trailLength: bind {tSlider.value}),
      opaque: false,
      horizontalAlignment: JLabel.CENTER,
      delay: bind {speedSlider.value},
      background: bind{backColBtn.background})

The three associated tests are essentially using the same recipe, so here’s just one of them to give you the idea.

 * Test that changing the 'baseColBtn' background color simultaneously
 * changes the busy label's base color.
 @Test void testBaseColorChange() {
       def button = window.button('baseColBtn')
       def busyLabel = findBusyLabel()
       Color start =
       Color busyStart = busyLabel.busyPainter.baseColor
       Assert.assertEquals(busyStart, start) = Color.RED

       Assert.assertFalse( == start)
       Assert.assertFalse(busyLabel.busyPainter.baseColor == busyStart)
       Assert.assertEquals(busyLabel.busyPainter.baseColor, Color.RED)

Running the test suite takes less than a minute, and most of that time is spend dragging sliders. Those tests are presently going through the entire range of the slider, which is reassuring when actually watching the tests run, but probably overkill in terms of testing. Considering that, running the test suite is pretty painless and quick(the new tests execute in < 1s for instance). And of course the test results are available in the standard, pleasing, and hopefully all green, TestNG output. Which has, by the way, just announced another release thanks very much to its creator Cedric Beust.

I am still having some difficulties in responding to change events on the other sliders in the demo, but I think that I just need to decompose the parts into the MVC structure a little more coherently. In particular, when some sliders are moved, it should trigger some calculations and a repaint of the busy label to reflect the changes(not simple properties that can utilize binding directly). While the original code declares the method inline, I’ve moved it to the controller class and run into some circular dependency problems between the components referenced therein – Component A needs Component B but it hasn’t been instantiated yet in the view, etc. It looks like what is happening is that the change listener is being triggered once when it is assigned to the component, which might be a problem anywhere in Swing/Groovy/Griffon/my implementation. My money is on my own impl, mostly based on the common sense that when you’re writing code in an unfamiliar area you’re bound to meet problems that don’t immediately suggest a solution.

We’ll just have to keep digging and see. 🙂

Get Adobe Flash player