Posted on June 14, 2008 at 8:40:48 AM
As I mentioned in an earlier post entitled “Three commands for Subversion enlightenment“, Subversion’s diff command is quite helpful in determining what local changes have been made.
The output of the diff command is somewhat verbose in that it literally compares the local version to what’s in Subversion. If you’ve made a lot of changes, the output can be overwhelming.
For instance, running the diff command (for a sandbox where only one file has changed) yields output like so:
aglover$ svn diff
Index: test.properties
===================================================================
--- test.properties (revision 126)
+++ test.properties (working copy)
@@ -1,5 +1,5 @@
#HSQL Database Engine
-#Tue Jun 03 10:49:01 EDT 2008
+#Thu Jun 12 17:04:23 EDT 2008
hsqldb.script_format=0
runtime.gc_interval=0
sql.enforce_strict_size=false
In truth, most of the time, I just want to know what has changed not necessarily how. Accordingly, you can pipe the output of diff to a grep-like utility searching for the line containing the word “Index:” like so:
%>svn diff | egrep "Index:"
In my case, I’m using egrep to search for a line of text containing the keyword. If, for some reason, the files you are changing actually contain that word, you might want to precede the phrase with a ^ (which matches the starting position of a line).
Consequently, using this pipe filter yields the following output:
aglover$ svn diff | egrep "Index:"
Index: test.properties
Now I can more easily understand what files have changed and update a repository appropriately.
Test Early is sponsored by Stelligent | Stelligent is hiring experts like you!
Posted on June 6, 2008 at 9:18:56 AM
Hudson is an open source CI server that is by far the easiest one to configure. Second to ease of use is Hudson's impressive plug-in framework, which makes it easy to add features. For instance, Hudson has a plug-in for tracking FindBugs issues, PMD issues, and CheckStyle issues over time as well as code coverage. It also trends test results from JUnit, as well as build results and corresponding execution times. In spite of all these cool features, we had to find ways to get around some common issues we faced at work using Hudson.
This article describes a few real-life tips and tricks that we have found at work and will assist in configuring Hudson to work most effectively in your environment as well:
- Changing Hudson home directory
- OutOfMemoryError
- Securing Hudson
- Hudson Views
- Hudson and Groovy
- Spaces in directory names
- Browser to use
Changing Hudson home directory:
Hudson by default uses the $USER/.hudson directory as its home directory. If you want to change the home directory, set the HUDSON_HOME environment variable to some other location before startup. This is where Hudson maintains its configuration files and manages its jobs. If you are using a batch script to run Hudson, you can set the HUDSON_HOME there as well:
set HUDSON_HOME=c:\hudson\ci_jobs
OutOfMemoryError:
If you are seeing this error, than the first thing to do is to set the maximum heap size as such:
java -Xmx512m -jar hudson.war If you are seeing the same error in spite of increasing the memory, report the issue to Hudson mailing list and take a look at the following link:
http://hudson.gotdns.com/wiki/display/HUDSON/I’m+getting+OutOfMemoryError
Securing Hudson:
Hudson does not perform any security check in its default mode. This means any person accessing the website can configure Hudson and jobs, and perform builds, and download all the files from within the workspace. Hudson can be configured to authenticate users and enforce access control. In the “Matrix-based security”, you can basically configure which users have what permissions in a big table. From the Hudson dashboard, click on Manage Hudson link on the left hand side which will take you to a page as shown below:

It is also a good idea to secure the Workspace as shown above. If not, once you have a successful build, anyone can download the source code from the Hudson Dashboard as such:

Hudson Views:
Rather than having a long list of all the Jobs, organize your jobs into different views; like Commit Builds, Nightly Builds and so on.
Hudson and Groovy:
The Groovy plug-in which can be found here is very useful. In our case, we are using it for many purposes. To name a few:
1. To unlock all the files which are locked by the SCM. Download a free utility called unlocker.exe and run the groovy script to unlock files as such:
new File("directory where files are getting locked").eachFileRecurse{file ->
def command = """"C:\\Program Files\\Unlocker\\Unlocker.exe" ${file} -s"""
def proc = command.execute()
proc.waitFor()
}

2. And also to change the file permissions on directories.
def ant = new AntBuilder()
ant.chmod(dir:"directory which needs the permission to be changed", perm:"ugo+rw", includes:"**/*.*")
println "changed permissions on dirs"
Troubleshoot Hudson:
If you want to troubleshoot Hudson, you can run arbitrary Groovy scripts. In order to do so go to the Hudson Dashboard and click on the Manage Hudson which brings up the screen as shown below:

Click on the Script Console, which will bring you another page where in you can run any Groovy script to troubleshoot Hudson.

Hudson Environment Variables:
You can easily incorporate the environment variables which are easily available within your build scripts as such:
<target name="retrieve-env-variables">
<property environment="env" />
<echo message="${env.BUILD_TAG}"/>
<echo message="${env.BUILD_NUMBER}"/>
<echo message="${env.BUILD_ID}"/>
</target>
Spaces in directory names:
If you use the default setting for Hudson-Home; it is in the "Documents and Setting" folder. This causes Ant build files to fail. Make sure you set your Hudson-Home to a directory without spaces.
Also, while creating a new Job in Hudson, it has been seen that Job names which have spaces cause trouble while running the Ant build scripts.
Use anything but IE:
Last but not the least, if you are using Internet Explorer as the default browser, switch to some other browser. I spent a day trying to fix the matrix based security and also trying to rearrange the Build Steps, and enter a Groovy Command. All worked seamlessly when I switched to Firefox.
Links to additional tips and tricks already posted here:
1. Retrieving error level
2. Versioning Hudson job cofigurations
3. Hudson’s so Groovy
4. Matrix based security and IE
Test Early is sponsored by Stelligent | Stelligent is hiring experts like you!
Posted on May 22, 2008 at 10:46:28 AM

Everyone loves sparklines, and if you want to build them using Groovy, here’s some code that I took from a fabulous example in JRuby, and modified:
package com.stelligent.gsparkyimport org.jfree.chart.JFreeChart
import org.jfree.chart.axis.NumberAxis
import org.jfree.chart.plot.XYPlot
import org.jfree.chart.renderer.xy.StandardXYItemRenderer
import org.jfree.data.general.Dataset
import org.jfree.data.xy.XYSeries
import org.jfree.data.xy.XYSeriesCollection
import org.jfree.chart.ChartUtilities
class GSparky {
def DEFAULT_HEIGHT = 30
def DEFAULT_WIDTH = 150
boolean build( def data, def imgPath, def height = DEFAULT_HEIGHT, def width = DEFAULT_WIDTH ) {
def chart = buildChartFromData(data)
return buildImageFromChart( chart: chart, height: height, width: width, path: imgPath)
}
private JFreeChart buildChartFromData( data ) {
def dataset = generateDataset(data)
def plot = new XYPlot()
plot.dataset = dataset
plot.domainAxis = minimalAxis()
plot.rangeAxis = minimalAxis()
plot.domainGridlinesVisible = false
plot.domainCrosshairVisible = false
plot.rangeGridlinesVisible = false
plot.rangeCrosshairVisible = false
plot.outlinePaint = null
plot.renderer = new StandardXYItemRenderer(StandardXYItemRenderer.LINES)
def chart = new JFreeChart(null, JFreeChart.DEFAULT_TITLE_FONT, plot, false)
chart.borderVisible = false
return chart
}
private boolean buildImageFromChart( args ) {
ChartUtilities.saveChartAsPNG( new File(args.path), args.chart, args.width, args.height )
return true
}
private Object minimalAxis() {
def a = new NumberAxis()
a.tickLabelsVisible = false
a.tickMarksVisible = false
a.axisLineVisible = false
a.negativeArrowVisible = false
a.positiveArrowVisible = false
a.visible = false;
return a
}
private Dataset generateDataset(def data) {
def series = new XYSeries("Sparkline")
def i = 0
data.each { y -> series.add(i++, y) }
def dataset = new XYSeriesCollection()
dataset.addSeries(series)
return dataset
}
}
And.. a test to demonstrate how it works:
package com.stelligent.gsparky
class GSparklineTest extends GroovyTestCase {
public void testBuildSparklineImage() {
def gs = new GSparky()
def data = [20]
def r = new Random( new Date().getTime() )
(0..99).each { x ->
def y = data.get(x) + (x/2 - r.nextInt(x + 1))
data << y
}
assert gs.build( data, "out/GSparklineTest_test1.png")
}
}
Test Early is sponsored by Stelligent | Stelligent is hiring experts like you!
Posted on May 19, 2008 at 10:50:33 AM
InfoQ recently published an interview with Joshua Bloch, who is the author of “Effective Java”– an updated second edition was released, which includes some tips with dealing with Java’s generics, autoboxing, and annotations, to name a few.
“Effective Java” is one of the best books I’ve ever read regarding the Java language and has served me well over the years– the second edition also appears to follow suit. InfoQ also has a sample chapter available, which focuses on Generics and already I’ve found it helpful.
Don’t forget to read the interview as well– the author has some great insights into refactoring and Java in general. My favorite part of the interview was this exchange:
Do you believe that other tools and processes such as unit testing, Test-driven development or pair programming also aid in programming effectively in Java?
Joshua’s response is right on:
Absolutely. Unit testing is key. And writing your tests first is a great thing. Pair programming works very well for some people, as do variants such as “buddy programming” (where you show your code to someone else after you’ve written it, and refactor as necessary together). Writing code in a vacuum is bad thing. Code reviews (which I view as another variant) are essential…
If you don’t have a copy of Joshua’s book, pick one up as soon as possible– your users will thank you!
Test Early is sponsored by Stelligent | Stelligent is hiring experts like you!
Posted on May 16, 2008 at 4:15:03 PM

If you are in Ireland (or close enough to get there easily!) the week of June 9th, then you’ll want to come to the International Conference on Agile Processes and eXtreme Programming in Software Engineering as I’ll be giving a tutorial on Continuous Integration!
The tutorial will walk students through a series of exercises on a project where an automated build system is created that facilitates compilation, testing, inspection, and deployment. This build system will then be plugged into a CI server (Hudson in this case) and students will code a series of features using Agile techniques like developer testing, which will ultimately demonstrate how a Continuous Integration process reduces risk and improves software quality. Students will then toast to CI over a pint of Guinness!
If this sounds like a blast to you, then register today! If you plan on attending, drop me an email and I look forward to meeting you!
Test Early is sponsored by Stelligent | Stelligent is hiring experts like you!
Posted on May 14, 2008 at 9:33:42 AM
For any developer looking to test web services, there are a number of tools out there that seem to fit the bill. When you need one that allows you to interact and create functional and load tests with relative ease, soapUI is bound to be the tool you can’t live without.
To help get you started, Meera Subbarao has authored a how-to series on testing web services using soapUI. Published by JavaLobby and entitled, “Functional Web Services Testing Made Easy with SoapUI,” the series is broken up into three installments; with each article demonstrating an important soapUI feature that will make web services development easier for you.
Part 1 explores soapUI basics including how to write functional tests for your web services and how to add assertions to these tests. In short, soapUI emphasizes a good balance between simplicity and rich features and as Subbarao notes in Part 1,
Once soapUI has been downloaded and installed, you can have functional tests up and running in minutes.
For more elaborate programming tasks, Part 2 examines soapUI’s relationship with Groovy. Groovy is used in soapUI primarily for test setup, test teardown, and to decide which steps to start based on the results of the older ones. If you know Java, writing Groovy scripts with the UI will make your testing even easier.
soapUI also includes command-line utilities for running tests and mocks in a continuous integration environment so you’re able to run the test cases you’ve created within it and above all fail the build just like you would when any other unit test fails. Stayed tuned for the third and final part of this series which will cover integrating tests with your build tool, running these tests as part of your builds, and creating JUnit reports.
Test Early is sponsored by Stelligent | Stelligent is hiring experts like you!