Archive for the ‘Build’ Category
Setting Up An Android Project Build
As the owner of a G1 I’ve played around at several times in the past with simple Android application development. The SDK tools and introductory documentation provided by Google make it easy to get started. Before embarking on a more serious project, however, I decided to figure out how to set up projects in a systematic way that allows for both development and reliable scripted builds (e.g. for continuous integration). Creating a project layout and build that works takes a few steps and tweaks, not all of which are covered in the documentation I found, so I thought I’d walk through my approach to it for those that are interested.
Goals
My goals for this project setup were as follows:
- Support for development in Eclipse using the ADT. Although Eclipse is not my first choice of IDE, it is decent enough and compelling when combined with the ADT tooling.
- Support for building from the command-line, with no dependency on an IDE.
- The ability to run tests on a device (or emulator) using the SDK testing and instrumentation support.
- Containment of all components within a single directory which can be easily versioned.
This all seems like it should be simple: the Android SDK has support for Eclipse, Ant builds, and testing. However, putting it all together can take some work, because not all the pieces play together as nicely as you might hope. First of all, although it is easy to create either an Eclipse project or an Ant one (and both cases are well documented), I would like both. I experimented with two methods: creating an Eclipse project either before or after setting up the Ant build. In my experience adding an Eclipse project to an existing Ant build proved more troublesome, and more difficult to debug if there was an issue. So I recommend starting by setting up your projects (application and test) in Eclipse first.
Setting Up the Eclipse Projects
Select File > New > Project, and choose Android Project in the dialog:
Fill in your Project, Application, Package and Activity names:
Click Next, then check the box to Create a Test Project. So that both projects live under simple, single root directory, uncheck the Use default location box, and specify the location as the “test” subdirectory of your main application’s directory:
Click Finish and the easy part is done: you should have two new projects in your workspace, with the test project nested neatly within the main one1. If you list the contents of your application’s directory, you should see something like:
jsankey@caligula:~$ ls -a1 work/my-app/ . .. AndroidManifest.xml assets bin .classpath default.properties gen .project res .settings src test
Likewise, the test subdirectory should contain:
jsankey@caligula:~$ ls -a1 work/my-app/test . .. AndroidManifest.xml assets bin .classpath default.properties gen .project res .settings src
Adding a Simple Test Case
At this point, it’s worth adding a simple test case to your test project as a starting point. This will allow you to experiment with the Eclipse setup and (forthcoming) Ant builds. To do this, navigate to your test project and select File > New > Class. To actually utilise the instrumentation support in the test project, have your test class extend android.test.ActivityInstrumentationTestCase2:
You’ll need to fill in the generic type parameter for this class, add a constructor, and add a simple test case:
package com.zutubi.android.myapp.test;
import com.zutubi.android.myapp.MyAppActivity;
import android.test.ActivityInstrumentationTestCase2;
public class MyAppActivityTest extends ActivityInstrumentationTestCase2<MyAppActivity> {
public MyAppActivityTest() {
super("com.zutubi.android.myapp", MyAppActivity.class);
}
public void testSanity() {
assertEquals(2, 1 + 1);
}
}
To try it out, select Run > Run As > Android JUnit Test and choose (or start) a device. If the universe is in working order, the test should pass!
Adding Ant Builds
To add standard Android Ant builds to the existing projects, I used the android command line tool from the SDK. Firstly, I added a build to the main application using android update project:
jsankey@caligula:~$ cd /home/jsankey/work/my-app jsankey@caligula:~/work/my-app$ android update project -p . Updated local.properties Added file ./build.xml It seems that there are sub-projects. If you want to update them please use the --subprojects parameter.
As the output suggests, this command adds an Ant build.xml file to your project, and a local.properties file that stores the location of the Android SDK. Notice that the tool has picked up the fact that there is a test/ subdirectory with another project in it. However, do not be tempted to take its advice to run with the –subprojects flag: this will treat your test project as a regular project. Instead, change into the test/ subdirectory and run android update test-project:
jsankey@caligula:~/work/my-app$ cd test jsankey@caligula:~/work/my-app/test$ android update test-project -p . -m .. Resolved location of main project to: /home/jsankey/work/my-app Updated default.properties Updated local.properties Added file ./build.xml Updated build.properties
Again, the build.xml and local.properties files are added, although this time the build file will contain test rules. Notice that the relative path to the main project is passed using the -m flag. You can see the effect of this in the created build.properties file, which sets the value of tested.project.dir.
At this point you can build the project and run the tests from the command line. First ensure that you have only one device available (e.g. one emulator running), then, in the test/ subdirectory where we left off, run ant run-tests:
jsankey@caligula:~/work/my-app/test$ ant run-tests
... clipped several lines of output ...
run-tests:
[echo] Running tests ...
[exec]
[exec] com.zutubi.android.myapp.test.MyAppActivityTest:.
[exec] Test results for InstrumentationTestRunner=.
[exec] Time: 0.158
[exec]
[exec] OK (1 test)
[exec]
[exec]
BUILD SUCCESSFUL
Total time: 10 seconds
Excellent: now we have the build and test working with both Eclipse and Ant (or so it seems…).
Separating the Output Directories
Although on the surface our two methods of building appear to work, once you start working in this environment you will notice problems. Most likely, you will start to see errors showing up in your Eclipse build (or the Android Console) after builds from the command line. By default both the Eclipse and Ant builds use the same folders for generated source (gen/) and output (bin/), which causes this conflict. The Eclipse project does not react well to changes that occur underneath it.
To solve this problem, we can force the two different builds to use different output locations. The Ant build makes it easy to override both the generated source and output locations, using gen.dir and out.dir properties. The best place to set these properties is in the build.properties file for each of the projects:
out.dir=build gen.dir=build/gen
Note that you will need to create build.properties for your main project (your test project should already have one). I chose to put the gen/ directory used by Ant under the output directory just to tidy things up a little.
This should be all that is required, however, thanks to a bug in the default Ant rules, if you customise the output directory your test project will not find the output of your main project to build against. To fix this, you need to edit test/build.xml, and add the line:
<property name="extensible.classpath" value="${tested.project.absolute.dir}/${out.dir}/classes"/>
just before the closing </project> tag. This assumes your test and main projects have the same out.dir, which although slightly lazy is a simpler than loading the main project’s properties to get its out.dir (and a sane assumption in my book).
You can make sure everything works by doing clean builds using Ant:
jsankey@caligula:~/work/my-app/test$ cd ..
jsankey@caligula:~/work/my-app$ ant clean
Buildfile: build.xml
[setup] Android SDK Tools Revision 6
[setup] Project Target: Android 2.2
[setup] API level: 8
[setup] WARNING: No minSdkVersion value set. Application will install on all Android versions.
[setup] Importing rules file: platforms/android-8/ant/ant_rules_r2.xml
clean:
[delete] Deleting directory /home/jsankey/work/my-app/build
[delete] Deleting directory /home/jsankey/work/my-app/build.gen
BUILD SUCCESSFUL
Total time: 0 seconds
jsankey@caligula:~/work/my-app$ cd test
jsankey@caligula:~/work/my-app/test$ ant clean run-tests
... clipped several lines of output ...
run-tests:
[echo] Running tests ...
[exec]
[exec] com.zutubi.android.myapp.test.MyAppActivityTest:.
[exec] Test results for InstrumentationTestRunner=.
[exec] Time: 0.147
[exec]
[exec] OK (1 test)
[exec]
[exec]
BUILD SUCCESSFUL
Total time: 9 seconds
Then switch back to Eclipse, try editing and saving the activity and test cases and ensure everything is happy.
Checking It In
Finally, you can check the project into your version control system. I won’t go into the tool-specific details, just make sure you check in the correct files. You should exclude:
- The bin/, build/, and gen/ directories: as these all contain build output.
- The files local.properties and test/local.properties: which are intended to contain properties specific to your machine (e.g. the location of the Android SDK).
Make sure you don’t forget to check in the hidden Eclipse files .classpath, .project and .settings. By structuring the projects so they live under a single top-level folder, it should be easy to add them to the version control server of your choice.
Wrap Up
That covers the basics of setting up an Android project, with tests, for both development and automated builds. Although some tweaking is required, this setup is still built upon the tooling provided by the Android SDK. I hope that this will mean it is easy to take advantage of new capabilities when new SDK versions are released (which happens pretty frequently at the moment!).
–
1 For reasons unknown to me, when my projects were first created they had build errors. A clean rebuild magically fixed the problem.
Zero To Continuous Integration in Three Minutes
A large part of our focus with Pulse revolves around saving time. We started Pulse with the belief that it shouldn’t be so hard to set up a continuous integration server, nor should it take so much effort to maintain. With that in mind, I’ve highlighted the main ways we achieve simplicity and maintainability in Pulse in two new demo videos:
- Getting Started With Pulse: in which I start from scratch, installing Pulse, adding a new project and running a first build in under three minutes. By watching the video, you’ll see that it is unabridged, and I did nothing but follow the simple steps laid out in front of me.
- Templated Configuration: in which I demonstrate how Pulse’s unique templated configuration system saves you time configuring and (especially) maintaining your continuous integration server. Templates make CI DRY.
We focus on saving time simply because it adds a lot of value to Pulse. Our customers tell us that simplicity, maintainability and dedicated support are the main reasons they chose Pulse to manage their builds. Give it a go yourself: you can get started in no time
.
Article: Optimise Your Acceptance Tests
In a similar vein to my previous post, I’ve revived some old posts about acceptance testing — and made significant additions. The end result is a new article:
Many developers have a love-hate relationship with automated acceptance tests. One major sticking point is the time acceptance tests take to execute, which can easily cause a blow out of project build times. In this article I’ll review 7 successful techniques we’ve put to work in our own projects to optimise our acceptance testing.
You can read the full article at zutubi.com.
Pulse 2.1.11: Get More From Your Build Agents
The latest Pulse 2.1 beta build, 2.1.11, has just been freshly baked. This build includes several new features and improvements. Prominent among them is a new “statistics” tab for agents. This tab lists various figures such as the number of recipes the agent executes each day and how long the average recipe keeps the agent busy. Statistics are also shown for agent utilisation, including a pie chart that makes it easy to visualise:
This allows you to see if you are getting the most out of your agent machines. If you do notice a machine is underutilised, another new feature could help identify the cause: compatibility information for projects and agents. Pulse matches builds to agents by considering if the resources required for the project are all available on the agent. Now when you configure requirements, Pulse shows you which agents those requirements are compatible with. On the flip side, when configuring an agent’s available resources, Pulse shows you which projects those resources satisfy.
Other highlights in this build:
- Optional compression of large build logs (on by default).
- Visual indicators of which users are logged in, and last access times for all users.
- Support for Subversion 1.6 working copies for personal builds.
- Actions can now be performed on all descendants of a project or agent template (e.g. disable all agents with one click).
- New options to terminate a build early if a critical stage or number of stages have already failed.
- The system/agent info tabs now show the Pulse process environment (visible to administrators only).
- Use of bare git repositories on the Pulse master to save disk space.
Yes, we have been busy
. Get over to our website and download the beta now — it’s free to try, and a free upgrade for customers with current support contracts!
Boost.Test XML Reports with Boost.Build
My previous post Using Boost.Test with Boost.Build illustrated how to build and run Boost.Tests tests with the Boost.Build build system. For my own purposes I wanted to take this one step further by integrating Boost.Test results with continuous integration builds in Pulse.
To do this, I needed to get Boost.Test to produce XML output, at the right level of detail, which can be read by Pulse. This is another topic I have covered to some extent before: the key part being to pass the arguments “–log_format=XML –log_level=test_suite” to the Boost.Test binaries. The missing link is how to achieve this using Boost.Build’s run task. Recall that the syntax for the run task is as follows:
rule run (
sources + :
args * :
input-files * :
requirements * :
target-name ? :
default-build * )
Notice in particular that you can pass arguments just after the sources. So I updated my Jamfile to the following:
using testing ;
lib boost_unit_test_framework ;
run NumberTest.cpp /libs/number//number boost_unit_test_framework
: --log_format=XML --log_level=test_suite
;
and lo, the test output was now in XML format:
$ cat bin/NumberTest.test/gcc-4.4.1/debug/NumberTest.output <TestLog><TestSuite name="Number"><TestSuite name="NumberSuite"><TestCase name="checkPass"><TestingTime>0</TestingTime></TestCase><TestCase name="checkFailure"><Error file="NumberTest.cpp" line="15">check Number(2).add(2) == Number(5) failed [4 != 5]</Error><TestingTime>0</TestingTime></TestCase></TestSuite></TestSuite></TestLog> *** 1 failure detected in test suite "Number" EXIT STATUS: 201
The output will not exactly win awards: it has no <?xml …?> declaration, no formatting, and thanks to Boost.Test contains trailing junk. We’ve made sure that the processing in Pulse 2.1 takes care of this, though.
If you are a Pulse user looking to integrate Pulse and Boost.Test, you might also be interested in a new Cookbook article that I’ve written up on this topic.
Using Boost.Test with Boost.Build
In my earlier post C++ Unit Testing With Boost.Test I used make to build my sample code — largely because that is what I am more familiar with. If you’re using Boost for testing, though, you should also consider using it for building. From what I’ve seen you get a lot of functionality for free with Boost.Build if you’re willing to climb the learning curve. In order to help, I’ve put together a simple tutorial that combines Boost.Test and Boost.Build.
Prerequisites
In this tutorial I’m assuming you have Boost installed already. If not, you can refer to my earlier post or the Boost Getting Started Guide.
Installing Boost.Build
If, like me, you installed Boost by using the package manager on your Linux box, you may still not have Boost.Build installed. On Debian-based systems, Boost.Build requires two extra packages:
$ sudo apt-get install bjam boost-build
The bjam package installs Boost’s variant of the jam build tool, whereas the boost-build package installs a set of bjam configurations that form the actual Boost.Build system.
If you’re not lucky enough to have a boost-build package or equivalent, you can get a pre-built bjam binary and sources for Boost.Build, see the official documentation for details.
Once you have everything set up, you should be able to run bjam –version and see similar to the following output:
$ bjam --version Boost.Build V2 (Milestone 12) Boost.Jam 03.1.16
If you don’t see details of the Boost.Build version then it is likely you have only installed bjam and not the full Boost.Build system.
Sample Projects
To demonstrate Boost.Build’s support for multiple projects in a single tree, I split my sample code into two pieces: a simple library, and the test code itself. The library consists of a single Number class, which is an entirely contrived wrapper around an int. The test code exercises this library, and thus needs to link against it.
Boost.Build isn’t particularly fussy about how you lay out your projects, so I went for a simple structure:
$ ls -R .: Jamroot number test ./number: Jamfile Number.cpp Number.hpp ./test: Jamfile NumberTest.cpp
The Jamroot and Jamfiles are build files used by Boost.Build. They are in the same format — the difference in name is used to indicate the top level of the project. Boost.Build subprojects inherit configuration from parent projects by searching up the directory tree for a Jamfile, and will stop when a Jamroot is reached.
Top Level
The top level Jamroot file is incredibly simple in this case:
use-project /libs/number : number ;
In fact this line isn’t even strictly necessary, but it is good practice. It assigns the symbolic name “/libs/number” to the project in the “number” subdirectory. It’s overkill for such a simple example, but this abstraction means our test project will have no dependency on the exact location of the number library. If we refactored and moved the library into a subdirectory called “math”, then we would only need to update the Jamroot.
Number Library
As mentioned above, the number library is a contrived wrapper around an int that I created simply for illustration. The interface for this library is defined in Number.hpp:
#ifndef MY_LIBRARY_H
#define MY_LIBRARY_H
#include <iostream>
class Number
{
public:
Number(int value);
bool operator==(const Number& other) const;
Number add(const Number& other) const;
Number subtract(const Number& other) const;
int getValue() const;
private:
int value;
};
std::ostream& operator<<(std::ostream& output, const Number& n);
#endif
Of greater interest is the Jamfile used to build the library:
project : usage-requirements <include>. ; lib number : Number.cpp ;
Note that the single “lib” line is all that is required to build the library. The lib rule is one of the core rules provided by Boost.Build, and follows its common syntax:
rule rule-name (
main-target-name :
sources + :
requirements * :
default-build * :
usage-requirements * )
So in this case we are instructing Boost.Build to create a library named “number” from the sources “Number.cpp”.
The project declaration, which adds usage-requirements, is a convenience for consumers of this library. This tells the build system that any project that uses the number library should have this directory “.” added to its include path. This makes it easy for those projects to include Number.hpp.
We can build the library by running bjam in the number directory:
$ bjam ...found 12 targets... ...updating 5 targets... MkDir1 ../number/bin MkDir1 ../number/bin/gcc-4.4.1 MkDir1 ../number/bin/gcc-4.4.1/debug gcc.compile.c++ ../number/bin/gcc-4.4.1/debug/Number.o gcc.link.dll ../number/bin/gcc-4.4.1/debug/libnumber.so ...updated 5 targets...
Note that by default Boost.Build produces a dynamic library, and outputs the built artifacts into configuration-specific subdirectories.
Test Project
Finally, our test project consists of a single source file, NumberTest.cpp, with a single test suite:
#define BOOST_TEST_DYN_LINK
#define BOOST_TEST_MODULE Number
#include <boost/test/unit_test.hpp>
#include <Number.hpp>
BOOST_AUTO_TEST_SUITE(NumberSuite)
BOOST_AUTO_TEST_CASE(checkPass)
{
BOOST_CHECK_EQUAL(Number(2).add(2), Number(4));
}
BOOST_AUTO_TEST_CASE(checkFailure)
{
BOOST_CHECK_EQUAL(Number(2).add(2), Number(5));
}
BOOST_AUTO_TEST_SUITE_END()
Note the definition of BOOST_TEST_DYN_LINK: this is essential to link against the Boost.Test dynamic library. Other than that the code is fairly self explanatory.
Again, the Jamfile is what we are really interested in here:
using testing ; lib boost_unit_test_framework ; run NumberTest.cpp /libs/number//number boost_unit_test_framework ;
Starting from the top, the “using testing” line includes Boost.Build’s support for Boost.Test. This support includes rules for building and running tests; for example it defines the “run” rule which is used later in the file.
The “lib” line declares a pre-built library (note that it has no sources) named “boost_unit_test_framework”. We use this later for linking against the Boost.Test dynamic library.
Finally, the “run” rule is used to define how to build an run a Boost.Test executable. The syntax for this rule is:
rule run (
sources + :
args * :
input-files * :
requirements * :
target-name ? :
default-build * )
In our sources we include both the source file and the two libraries that we require. Note that we refer to the number project using the symbolic name declared in our Jamroot.
To build and run the tests, we simply execute bjam in the test directory:
$ bjam ...found 29 targets... ...updating 8 targets... MkDir1 bin MkDir1 bin/NumberTest.test MkDir1 bin/NumberTest.test/gcc-4.4.1 MkDir1 bin/NumberTest.test/gcc-4.4.1/debug gcc.compile.c++ bin/NumberTest.test/gcc-4.4.1/debug/NumberTest.o gcc.link bin/NumberTest.test/gcc-4.4.1/debug/NumberTest testing.capture-output bin/NumberTest.test/gcc-4.4.1/debug/NumberTest.run ====== BEGIN OUTPUT ====== Running 2 test cases... NumberTest.cpp(18): error in "checkFailure": check Number(2).add(2) == Number(5) failed [4 != 5] *** 1 failure detected in test suite "Number" EXIT STATUS: 201 ====== END OUTPUT ====== <snipped diagnostics> ...failed testing.capture-output bin/NumberTest.test/gcc-4.4.1/debug/NumberTest.run... ...failed updating 1 target... ...skipped 1 target... ...updated 6 targets...
Note that the build fails as I have deliberately created a failing test case. The full output is somewhat longer due to the diagnostics given.
Wrap Up
That’s it! The impressive part is how simple it is to build two projects with an interdependency and run a test suite. In total the three build files include just six lines! And I haven’t even explored the fact that Boost.Build allows you to easily build across multiple platforms using various toolchains and configurations.
The hardest part is working through enough of the documentation to find out the few lines you need — hopefully this tutorial goes some way to removing that barrier.
Fencing Selenium With Xephyr
Earlier in the year I put Selenium in a cage using Xnest. This allows me to run browser-popping tests in the background without disturbing my desktop or (crucially) stealing my focus.
On that post Rohan stopped by to mention a nice alternative to Xnest: Xephyr. As the Xephyr homepage will tell you:
Xephyr is a kdrive based X Server which targets a window on a host X Server as its framebuffer. Unlike Xnest it supports modern X extensions ( even if host server doesn’t ) such as Composite, Damage, randr etc (no GLX support now). It uses SHM Images and shadow framebuffer updates to provide good performance. It also has a visual debugging mode for observing screen updates.
It sounded sweet, but I hadn’t tried it out until recently, on a newer box where I didn’t already have Xnest setup. The good news is the setup is as simple as with Xnest in my prior post:
- Install Xephyr: which runs an X server inside a window:
$ sudo apt-get install xserver-xephyr
- Install a simple window manager: again, for old times’ sake, I’ve gone for fvwm:
$ sudo apt-get install fvwm
- Start Xephyr: choose an unused display number (most standard setups will already be using 0) — I chose 1. As with Xnest, the -ac flag turns off access control, which you might want to be more careful about. My choice of window size is largely arbitrary:
$ Xephyr :1 -screen 1024×768 -ac &
- Set DISPLAY: so that subsequent X programs connect to Xephyr, you need to set the environment variable DISPLAY to whatever you passed as the first argument to Xephyr above:
$ export DISPLAY=:1
- Start your window manager: to manage windows in your nested X instance:
$ fvwm &
- Run your tests: however you normally would:
$ ant accept.master
Then just sit back and watch the browsers launched by Selenium trapped in the Xephyr window. Let’s see them take your focus now!
CITCON Paris 2009: Mocks, CI Servers and Acceptance Testing
Following up on my previous post about CITCON Paris, I thought I’d post a few points about each of the other sessions I attended.
Mock Objects
I went along to this session as a chance to hear about mock objects from the perspective of someone involved in their development, Steve Freeman. If you’ve read my Four Simple Rules for Mocking, you’ll know I’m not too keen on setting expectations, or even on verification. I mainly use mocking libraries for stubbing. Martin Fowler’s article Mocks Aren’t Stubs had make me think that Steve would hold the opposite view:
The classical TDD style is to use real objects if possible and a double if it’s awkward to use the real thing. So a classical TDDer would use a real warehouse and a double for the mail service. The kind of double doesn’t really matter that much.
A mockist TDD practitioner, however, will always use a mock for any object with interesting behavior. In this case for both the warehouse and the mail service.
So my biggest takeaway from this topic was that Steve’s view was more balanced and pragmatic than Fowler’s quote suggests. At a high level he explained well how his approach to design and implementation leads to the use of expectations in his tests. I still have my reservations, but was convinced that I should at least take a look at Steve’s new book (which is free online, so I can try a chapter or two before opting for a dead tree version).
A few more concrete pointers can be found in the session notes. A key one for me is to not mock what you don’t own, but to define your own interfaces for interacting with external systems (and then mock those interfaces).
The Future of CI Servers
I wasn’t too keen on this topic, but since it is my business, I felt compelled. I actually proposed a similar topic at my first CITCON back in Sydney and found it a disappointing session then, so my expectations were low. Apart from the less interesting probing of features on the market already, conversation did wander onto the more interesting challenge of scaling development teams.
The agile movement recognises the two main challenges (and opportunities) in software development are people and change. So it was interesting to hear this recast as wanting to return to our “hacker roots” — where we could code away in a room without the challenges of communication, integration and so on. Ideas such as using information radiators to bring a “small team” feel to large and/or distributed teams were mentioned. A less tangible thought was some kind of frequent but subtle feedback of potential integration issues. Most of the time you could code away happily, but in the background your tools would be constantly keeping an eye out for potential problems. What I like about this is the subtlety angle: given the benefits it’s easy to think that more feedback is always better, without thinking of the cost (e.g. interruption of flow).
Acceptance Testing
This year it seemed like every other session involved acceptance testing somehow. Not terribly surprising I guess since it is a very challenging area both technically and culturally. As I missed most of these sessions, they are probably better captured by other posts:
- Top 10 reasons why teams fail with Acceptance Testing by Gojko
- CITCON Paris 2009 by Antony
- CITCON Europe 2009 Sessions on the wiki
One idea I would call attention to is growing a custom, targeted solution for your project. I believe it was Steve Freeman that drew attention to an example in the Eclipse MyFoundation Portal project. If you drill down you can see use cases represented in a custom swim lane layout.
Water Cooler Discussions
Of course a great aspect of the conference is the random discussions you fall into with other attendees. One particular discussion (with JtF) has given me a much-needed kick up the backside. We were talking about the problems with trying to use acceptance tests to make up for a lack of unit testing. This is a tempting approach on projects that don’t have a testable design and infrastructure in place — it’s just easier to start throwing tests on top of your external UI.
Even though I knew all the drawbacks of this approach, I had to confess that this is essentially what has happened with the JavaScript code in Pulse. We started adding AJAX to the Pulse UI in bits and pieces without putting the infrastructure in place to test this code in isolation. Fast forward to today and we have a considerable amount of JavaScript code which is primarily tested via Selenium. So we’re now going to get serious about unit testing this code, which will simultaneously improve our coverage and reduce our build times.
Conclusion
To wrap up, after returning from Paris I plan to:
- Give expectations a fair hearing, by reading Steve’s book.
- Look for ways to improve our own information radiators to help connect Zutubi Sydney and London.
- Get serious about unit testing our JavaScript code.
- Get PJ and JtF to swap the dates for CITCON Asia/Pacific and Europe next year so I can get to both instead of neither!
If I succeed at 4 (sadly not likely!) then I’ll certainly be back next year!
Zutubi @ CITCON Paris 2009
Any excuse is good enough to get me to Paris, especially while it is only a train ride away. Daniel has actually been tempted all the way from Sydney!1 So you’ll find us both at CITCON Europe 2009 tomorrow night and Saturday. We’re both looking forward to a great weekend, after nothing but positive experiences at previous events. Hopefully we’ll even get a few questions about the new Pulse 2.1 Beta while we’re there!
–
1 Although combining it with a well-deserved holiday may have been a factor…
Pulse Continuous Integration Server 2.1 Beta!
Exciting news: today we’ve pushed the latest version of Pulse, namely 2.1, to beta! This is the culmination of months of hard work on a ton of new features and improvements, including:
- Project dependency support.
- Easier multi-command projects.
- Personal build improvements.
- Fine-grained cleanup rules.
- Built-in reference documentation.
- Pluggable commands (build tool support).
- A simpler, faster configuration UI.
The new features are described in more detail on the 2.1 beta page. The largest are the first two: dependencies and multi-command projects.
Project Dependencies
The ability to deliver artifacts from one build to another is a long-standing feature request. Pulse 2.1 supports this as part of a larger dependencies feature. Essentially you can declare one project to be dependent on another, allowing the downstream project to use artifacts built by the upstream one. Artifacts are delivered through an internal artifact repository.
The dependencies feature goes beyond artifact delivery. It also includes smarter triggering for dependent projects, the ability to rebuild a full dependency tree and a new “dependencies” tab which allows you to visualise the dependency graph.
Dependency support is built on top of Apache Ivy. Our aim is for interoperability with existing tools like Ivy and Maven, but without being Java-specific.
Multi-Command Projects
We’ve always had support for multi-command projects in the Pulse build core. However, to access this full flexibility you previously had to write an XML “pulse file” by hand. As of 2.1, the configuration GUI exposes the full flexibility of the underlying build core. This allows you to define multiple recipes per-project, each of which can have multiple commands. All of the advanced command options once restricted to XML files are now also accessible in the GUI.
A key feature related to this is the ability to plug in new commands (e.g. to support a new build tool), and have the plugin seamlessly integrated into the add project wizard. If you plug in support for a command, you get simplified wizard creation of single-command projects using your plugin for free.
Give It A Go!
You can download Pulse today to try it out. Free licenses are available for evaluation, open source projects and small teams.
You are currently browsing the archives for the Build category.






