Wednesday, 29 October 2008
GGUG meeting tomorrow
Joda DateTime Ranges
DateTime
values so I could assert in a test that a date time value fell into that range. I was using Joda Time's DateTime
class. The java.util.Date
class is compatible with Groovy's ObjectRange
becuase it's decorated with next
and previous
methods by the GDK. Joda's DateTime
isn't, so I ended up doing this:DateTime start = new DateTime()I could have created a custom Range implementation but I'd have lost the option of using the
DateTime end = start.plusYears(1)
Range range = start.millis..end.millis
x..y
notation and I'm a sucker for brevity. I figured Groovy has an IntRange
class so there's probably a LongRange
as well. As it turns out there isn't and what I ended up with is an ObjectRange
.Fundamentally this works, although I did find something worth bearing in mind. When it came to my assertion I tried to do this:
static void assertInRange(Range expected, actual) {Simple enough, right? Except running the code caused the test to hang. Looking into the implementation of
if (!expected.contains(actual) {
fail("Expected value in range:<${expected}> but was:<${actual}>")
}
}
ObjectRange
it became clear why. Groovy's Range
interface extends java.util.List
and that's where the contains
method is specified. For compatibility with the List
interface ObjectRange
iterates over the values between its from
and to
properties using the next
method I mentioned above. When from
and to
are Long
instances, it turns out this iteration takes a while - on my 2.16GHz iMac the contains
method takes over 4½ minutes on a 1 year range!The
Range
interface also specifies a containsWithinBounds
method and ObjectRange
implements this by simply checking that the argument is >= from
and <=to
. Changing my assertion to use containsWithinBounds
got rid of the long wait.What
ObjectRange
is doing does make perfect sense. Given two arbitrary objects that implement Comparable
and the next
and previous
methods it needs to implement contains
in a way that conforms to the List
interface. When you think about how the GDK implements next
and previous
on java.util.Date
for example you can see that there may be possible values of a given class that fall inside a range but would never be part of the List
generated by repeatedly using next
on the range's from
property. This isn't true of Long
, of course, but ObjectRange
is a general purpose class. The IntRange
class has a much optimised version of contains
and so could a theoretical LongRange
implementation.Anyway, getting back to the example. After changing
contains
to containsWithinBounds
the code ran much faster, unfortunately it also threw java.lang.OutOfMemoryError: Java heap space
. It turns out this is down to how GString
handles the ObjectRange
value I inserted into it. It spots that the object it's got implements List
and uses InvokerHelper.toListString
on it. This will attempt to create a String in the form "[0, 1, 2, 3...]"
. As you can imagine, building such a String is going to take some doing with over 31½ billion elements in the List
, hence the heap space ran out.A final working implementation of my assertion method is:
static void assertInRange(Range expected, actual) {I think going for the custom
if (!expected.containsWithinBounds(actual)) {
fail "Expected:<${expected.toString()}> but was:<${actual}>"
}
}
Range
implementation in the first place might have actually been the right choice.
Saturday, 18 October 2008
Gmock - Groovy Mock
Gmock aims to simplified mocking in Groovy through a intuitive syntax and a great readability. In a nutshell a Gmock test look like:
This is it!. Expectation are being setup by calling normal method on you mock object. The code under test is executed within the play closure and your mocks are automatically verified after it.
void testTree(){
def mockTree = mock()
mockTree.load('fruit').returns('apple')
play {
assertEquals "apple", mockTree.load('fruit')
}
}
The current version gmock-0.2 support the most basic functionality you would expect from a mocking framework. Version 0.3 should see static method mocking and property mocking. Future development are described in the Roadmap.
Wednesday, 15 October 2008
Selenium and Firefox 3
selenium.browser="*custom /usr/lib/firefox/firefox -no-remote -P selenium"
, manually configure the proxy, etc. However, it turns out there's a simpler solution.Please note this is nothing to do with Selenium IDE, if you're having problems with that in conjunction with Firefox 3 this won't help.
Tuesday, 14 October 2008
A “clearfix” CSS redux
We use a CSS technique called "clearfix" within several projects. This is implemented as a class (called "clearfix") that is applied to a parent element that contains floated child elements.
I wrote a post over at Code Couch that attempts to explain the reason for doing this in the first place, describes the CSS that we use and provides plenty of links for detailed reference.
Thursday, 9 October 2008
XHTML — myths and reality
Tina Holmboe is a member of the XHTML Working Group and has an interesting write-up XHTML — myths and reality that discusses the current state of XHTML and dismisses some popular inaccuracies.
Having hyped up the post, it is rather old news - although it is discussed in simple (simplistic?) terms which I find is better than overloading with jargon.
Here are some hilights:
Lack of support for XHTML is a fact of life on the web in 2008. Prior to the 3.0 series of Firefox the XHTML processor in Gecko was so poor that Mozilla's own engineers recommended against it;
No version of Internet Explorer up to, and including, IE 8 support XHTML at all, and a number of other browsers such as Lynx were never written to handle XML in the first place.
I wrote a post for another blog a while back that looked into how you can identify the appropriate doctype for your web page - and stumbled across this "lack of support" for XHTML in modern browsers. You can read the original post How to choose a doctype if you are interested.
Whilst XHTML remains a much more structured (and cleaner) choice to deliver content to the browser, I have yet to work on a single project where it is actually required.
XHTML is the default for use within the Grails framework - even though the worlds most prolific browser doesn't support it. Hmmm.
Programmatic Transactions
Sometimes you need more fine grained control. Here's a link to a great discussion which unfortunately doesn't seem to have made it into the Grails manual yet, however this is still talking about declarative transactions, rather than programmatic ones.
If you really do want programmatic transactions you can use
DomainObj.withTransactions { TransactionStatus ts ->
serviceA.doStuff()
serviceA.doMoreStuff()
serviceB.yawn()
}
But the caveat (and reason for this post) is that in the above scenario will only create a new transaction if one does not already exist. If the above is placed in a controller it will work fine. If it's placed in a service with
static boolean transactional = false
it will work fine, PROVIDING that the service is being called by a controller or other non-transactional service, however if your non-transactional service is called by a transactional one, the withTransactions block will have no effect.