Build Automation Series: Part 3 – Automated Testing

March 29, 2009

In the last post in this series we added dependency management to our build process.

In this post we add automated testing to our build.

Automated Testing

Previously we have already added JUnit 4.5 as a dependency. To support mocking/stubbing in testing we also add Mockito 1.7 to our ivy.xml file.

We update our build.xml file to have a test target that will execute all JUnit tests (using junit ank task) and generate a html report (using junitreport ant task) at the end. If any of the tests fail the build fails.

Qualities of a Good Build

So far we are saying that a good build is:

  1. Automated
    1. IDE Agnostic – build is performed by some build tool (like ant) and is not tied to any specific IDE (like Eclipse or intelliJ)
    2. Executable tests are run as part of the build.
  2. Repeatable
    1. Is capable of being build on different machines from source checked out from source control.
    2. Clean – this target returns the state of the project to what it was when checked out from source control
    3. Compile – this target is responsible for compiling all source code of the project in a consistent way.
    4. Executable tests are run in a repeatable manner with the same result achievable after each build.
  3. Flexible
    1. Dependencies are easily managed (easy to upgrade to newer version of dependency if need be)

Coming up

In the next post, we will add a build target responsible for building the project and creating a deliverable.

View the code

You can browse the code for this post online at http://code.google.com/p/build-automation-environment/source/browse/#svn/branches/build-automation-series-3.

The code can be checked out from svn following the instructions here http://code.google.com/p/build-automation-environment/source/checkout.

Build Automation Series: Part 2 – Dependencies

March 28, 2009

In the last post in this series we created a simple build for our java project that cleaned and compiled the source code.

Next we want to be able to write automated tests using some java test automation framework. For now we will choose to go with Junit. To use Junit we would need to add the JUnit jar file as a dependency on our project. In the past I would of just simply downloaded the Junit jar myself and placed it within a lib folder of the java project and checked it in along with the rest of the source code for the project. A better approach however is to use a dependency management tool like Ivy.

Dependency Management: Ivy

To use ivy we:

  1. Download ivy (version 2.0)
  2. Create an ivy.xml file for the project
  3. Add ant tasks to our build.xml file

In our ivy.xml file we add our dependencies. By default ivy will look up a maven2 repository for the dependencies you add. If you goto http://www.mvnrepository.com and search for ‘junit’ (lowercase) you will see it find a list of results related to junit. Click on the junit >> junit link you will see it display all the binaries for junit that exist on the repository. Also on the page is the POM Dependency xml:

<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <version>4.5</version>
</dependency>

We use the POM Dependency information on ivy as the following:

<dependencies>
	<dependency org="[groupId]" name="[artifactId]" rev="[version]" />
</dependencies>

so our junit dependency looks like:

<dependencies>
	<dependency org="junit" name="junit" rev="4.5" />
</dependencies>

Dependency Management in the Build: Ant + Ivy

To retrieve the projects dependencies, we need to call ivy:retrieve. The first time we try to retrieve the dependencies ivy will try to download these dependencies over HTTP. These are placed in the lib folder of our project and they are also cached in a local ivy cache. So if we try to retrieve these dependencies again ivy will goto the cache and get rather than going over HTTP.

So we also add a target to our build that allows us to clean the cache if we need to. See the build.xml file with added.

Command line usage

One of the key qualities of our build is that it is IDE agnostic. Ant is our build tool and we need to be able to perform a build using ant only from the command line. To do this the following should be in place:

  1. Download Ant (version 1.7.1)
  2. Set ANT_HOME to location where apache ant was downloaded
  3. Add ANT_HOMEbin to your PATH

Should be able to execute ant -version from anywhere and see it report what version of Ant is installed.

To allow Ivy’s ant tasks to be used within your ant build file from the command line, we add the following xml to our build.xml.

<!-- set path so ivy will be picked up when using ant from the command line -->
<path id="ivy.lib.path">
   <fileset dir="../build-automation-environment/lib" includes="*.jar" />
</path>
<taskdef resource="org/apache/ivy/ant/antlib.xml"
           uri="antlib:org.apache.ivy.ant" classpathref="ivy.lib.path" />

Eclipse integration

Integration of the build with an IDE can be helpful at times. To integration ivy with eclipse, we add the download version of ivy jar to Windowns->Preferences->Ant->Runtime->Global Entries.

I have also created eclipse launchers that execute a specified target(s) on the build.xml file. These are located in the eclipse-ant folder and can be invoked from the top menu as shown below:

eclipse-launchers

Qualities of a Good Build

So far we are saying that a good build is:

  1. Automated
    1. IDE Agnostic – build is performed by some build tool (like ant) and is not tied to any specific IDE (like Eclipse or intelliJ)
  2. Repeatable
    1. Is capable of being build on different machines from source checked out from source control.
    2. Clean – this target returns the state of the project to what it was when checked out from source control
    3. Compile – this target is responsible for compiling all source code of the project in a consistent way.
  3. Flexible
    1. Dependencies are easily managed (easy to upgrade to newer version of dependency if need be)

Coming up

In the next post, we will add a few tests and add automated testing to our build

View the code

You can browse the code for this post online at http://code.google.com/p/build-automation-environment/source/browse/#svn/branches/build-automation-series-2.

The code can be checked out from svn following the instructions here http://code.google.com/p/build-automation-environment/source/checkout.

Build Automation Series: Part 1 – Automated and Repeatable

March 25, 2009

As part of this series I am going to look at creating an automated build for java projects using the various technologies out there. All code examples will be checked into source control on google code at http://code.google.com/p/build-automation-environment/.

What makes a good build?

A goog build is automated and repeatable

A build should be automated to remove any possibility of human error during the build process. It should also be repeatable as we need to be sure that we will get the same results.

To start we will use a apache’s ant build tool to build our simple Java project.

Simple Java Project Structure

We have a simple java project checked out with the following structure:

simple-java-project-structure

we create the following ant build.xml file that allows us to clean and compile any source or test code.

The above build file allows to to compile our java source and test files in an automated and repeatable way. The clean target will consistently return the project back to the state that is identical to what it was before the build.

Qualities of a Good Build

So far we are saying that a good build is:

  1. Automated and Repeatable
    1. IDE Agnostic – build is performed by some build tool (like ant) and is not tied to any specific IDE (like Eclipse or intelliJ)
    2. Clean – this target returns the state of the project to what it was when checked out from source control
    3. Compile – this target is responsible for compiling all source code of the project in a consistent way.

Coming up:

One of the basic things we need to do when developing is to create Java test’s as well as Java source. To do this we typically will use some thrid party dependencies to aid this such as Junit, TestNG, Mockito, JMock, EasyMock etc

We will look into handling this using a dependency manager like Ivy in the next part of the series.

View the code

You can browse the code for this post online at http://code.google.com/p/build-automation-environment/source/browse/#svn/branches/build-automation-series-1.

The code can be checked out from svn following the instructions here http://code.google.com/p/build-automation-environment/source/checkout.

Kata:

December 30, 2008

Having watched Micah Martins presentation on Katas (http://rubyconf2008.confreaks.com/ruby-kata-and-sparring.html) I have decided that they are a excellent way of practicing your skills around different languages, tools and techniques.

I hope to start adding my own Katas in Java at first and hopefully other languages.

Exploring Spring Secuirty Series: part 13 to part 16

December 29, 2008

In spring security series parts 13 to 16, we revert back a bit to take a closer look at how spring security filters work. We clean up our configuration to allow us to have uri level security and method level security in place by part 16.

In subsequent parts of the series, we will continue on to look at the ACL feature of spring security.

part 13
part 14
part 15
part 16

Exploring Spring Secuirty Series: part 11 & 12

December 22, 2008

In part 11 , we start looking at spring security’s ACL features. We create the schema and populate the database with test data as well as the ACL tables.

In part 12 , we add code that enables us to see the data entered into our Projects (domain) table and also the corresponding entries in our ACL tables.

see http://heraclitusonsoftware.wordpress.com/software-development/spring/simple-web-application-with-spring-security-part-11

see http://heraclitusonsoftware.wordpress.com/software-development/spring/simple-web-application-with-spring-security-part-12/

Unit Testing in a Test Driven Manner:

December 18, 2008

In a previous post [http://heraclitusonsoftware.wordpress.com/2008/12/16/endo-testing-discussion/], I wrote a response to a post from Dan North around the subject of endo-testing and unit testing using Mockito/JMock.

In this post I want to illustrate reasons why I have chosen to switch to Mockito as my ‘mocking’ tool of choice. To help me do this I am going to use the example of an Order and a Warehouse taken from [1].

Description of Problem

We want to take an order object and fill it from a warehouse object. The order is very simple, with only one product and a quantity. The warehouse holds inventories of different products. When we ask an order to fill itself from a warehouse there are two possible responses. If there’s enough product in the warehouse to fill the order, the order becomes filled and the warehouse’s amount of the product is reduced by the appropriate amount. If there isn’t enough product in the warehouse then the order isn’t filled and nothing happens in the warehouse.

Creating a Unit Test in a TDD manner

I add the first test to verify expected behaviour of filling an order from a warehouse. Thus I need to represent an Order and a Warehouse.

package com.heraclitus.tddexample;

import org.junit.Test;

/**
 * I test {@link Order}.
 */
public class OrderTest {

    // system-under-test
    private Order order;

    // depended-on-component
    private Warehouse warehouse;

    @Test
    public void shouldFillOrderWithWarehouse() {

        // exercise test
        order.fill(warehouse);

    }

}

Above is my shell of test so far based on the description of the problem at hand. Order is the SUT, Warehouse a known depended-on-component and the method fill a required behaviour of Order. At his point, the act of writing the test shell is still a design activity. If Order and Warehouse don’t exist within the application domain, I create them (in an abstract way so I choose as an Interface) and if the method fill doesn’t exist I add this behaviour to the Order interface.

Trying to execute as is will result in a null pointer so I must setup the test to use a real instance of an Order.

@Test
public void shouldFillOrderWhenEnoughAvailableInWarehouse() {

        // setup
        final int requiredAmount = 50;
        final String productName = "product1";

        final Order order = new OrderImpl(productName, requiredAmount);

        // exercise test
        order.fill(warehouse);

        // state verification
        assertTrue("order is showing as not filled when it should be filled.",
                order.isFilled());
}

Above, I have renamed the name of the test to be something more meaningful, added the setup which has forced me to create an implementation of the SUT (if it didn’t already exist). Added some state-based verification at the end to ensure that the state of Order has been changed to Filled after exercising the behaviour we are adding. Running the test of course fails cause we still yet haven’t implemented fill.

An implementation of Order:

public class OrderImpl implements Order {

    private final String productName;
    private final int requiredAmount;
    private boolean filled = false;

    public OrderImpl(final String productName, final int requiredAmount) {
        this.productName = productName;
        this.requiredAmount = requiredAmount;
    }

    public void fill(final Warehouse warehouse) {
       filled = warehouse.removeFromInventoryIfAvailable(requiredAmount,
                productName);
    }

    public boolean isFilled() {
        return filled;
    }

}

I implement the fill behaviour to use the depended-on-component Warehouse. Doing so causes me to discover a new behaviour needed on Warehouse.

Note: Often in TDD examples, you see people enter a constant here, in this case hard coding the state of filled to be true within the fill method. Then writing another test where this code can no longer satisfy and requiring them to rewrite a better implementation, in this case I am using what I perceive to be an obvious implementation by delegating the responsibility of removing inventory to the Warehouse type and getting it to return state indicating success/failure.

Returning to my test and executing it, it fails as of yet I have initialized my depended-on-component that is crucial to the actual implementation and the test. It is at this point that we become interested in the differing techniques used along with TDD in unit tests.

Classical TDD

In [1], Fowler distinguishes between Classical and Mockist TDD’ers. If I were a classical TDD’er they I would use the actual implementation of Warehouse within the unit test.

Example:

@Test
public void shouldFillOrderWhenEnoughAvailableInWarehouse() {

        // setup
        final int requiredAmount = 50;
        final String productName = "product1";

        order = new OrderImpl(productName, requiredAmount);

        warehouse = new WarehouseImpl();
        warehouse.addInventory(200, "product1");

        // exercise test
        order.fill(warehouse);

        // state verification
        assertTrue("order is showing as not filled when it should be filled.",
                order.isFilled());
    }

Using the classical approach, we use the actual implementation and set its state up in a way that will force out test down the path we wish to check. For this test to pass now we require:

  1. The actual implementation of Warehouse and newly discovered behaviour must be implemented sufficiently to allow the test to pass
  2. If the depended-on-component also requires that other components be set up for it to work, the setup for this test ends up starting to grow and become more complex

Taking the case that in fact the true implementation of Warehouse does use at least one other component which is required to be setup, we may opt to use a Test Double to avoid adding complexity to the test and keep its setup simple (hopefully).

Mockist TDD

A mockist approach to TDD (as far as I understand) is when we opt to use a Test Double to represent the depended-on-component in place of the actual implementation. I use the term test double (taken from [2]) to emphasize that this test double does not have to be a mock but can be one of the other members of the test double taxonomy (stub etc)

Mockist TDD: Hand Rolled Test Stub Example

In this example we write our own test stub implementation of a Warehouse:

/**
 * Configurable Test Stub implementation of {@link Warehouse} that uses a
 * {@link HashMap} to store its inventory state and makes no use of any
 * collaborators/depended-on-components.
 */
public class WarehouseConfigurableTestStub implements Warehouse {

    private final Map inventoryStore = new HashMap();

    public Integer getInventoryCount(final String productName) {
        if (inventoryStore.containsKey(productName)) {
            return inventoryStore.get(productName).intValue();
        }
        return Integer.valueOf(-1);
    }

    public void addInventory(final int numOfItems, final String productName) {
        if (inventoryStore.containsKey(productName)) {
            final int currentInventoryCount = inventoryStore.get(productName)
                    .intValue();
            inventoryStore.put(productName, currentInventoryCount + numOfItems);
        } else {
            inventoryStore.put(productName, numOfItems);
        }
    }

    public boolean removeFromInventoryIfAvailable(final int requiredAmount,
            final String productName) {
        if (inventoryStore.containsKey(productName)
                && inventoryStore.get(productName).intValue() >= requiredAmount) {
            decreaseInventory(requiredAmount, productName);
            return true;
        }
        return false;
    }

    private void decreaseInventory(final int numItems, final String productName) {
        if (inventoryStore.containsKey(productName)) {
            final int currentInventoryCount = inventoryStore.get(productName)
                    .intValue();
            inventoryStore.put(productName, currentInventoryCount - numItems);
        } else {
            throw new IllegalStateException(
                    "produce does not exist to decrease");
        }
    }
}

with the test looking like so:

@Test
public void shouldFillOrderWhenEnoughAvailableInWarehouse() {

        // setup
        final int requiredAmount = 50;
        final String productName = "product1";

        order = new OrderImpl(productName, requiredAmount);

        warehouse = new WarehouseConfigurableTestStub();
        warehouse.addInventory(200, "product1");

        // exercise test
        order.fill(warehouse);

        // state verification
        assertTrue("order is showing as not filled when it should be filled.",
                order.isFilled());
    }

While this approach solves our problems of using the real implementation of Warehouse (which required too much setup to use), we now have the problem of having to maintain this extra test code. The test code of any reasonably complex system would grow quite large in relation to our production code. Because of this, a lot of people prefer to use ‘mocking’ frameworks that allow them to create an instance that emulates the depended-on-component required for the test.

Mockist TDD: JMock Stub Example

Using a tool such as JMock we can remove the need for creating our own hand rolled stubs. Our test would look as follows:

    // mockery
    private final Mockery mockery = new JUnit4Mockery();

    @Test
    public void shouldFillOrderWhenEnoughAvailableInWarehouseAndReduceWarehouseInventory() {

        // setup
        final int requiredAmount = 50;
        final String productName = "product1";

        order = new OrderImpl(productName, requiredAmount);

        warehouse = mockery.mock(Warehouse.class);

        // stubbing (to force down path for happy path test)
        mockery.checking(new Expectations() {
            {
                allowing(warehouse).removeFromInventoryIfAvailable(
                        requiredAmount, productName);
                will(returnValue(true));
            }
        });

        // exercise test
        order.fill(warehouse);

        // state verification
        assertTrue("order is showing as not filled when it should be filled.",
                order.isFilled());
}

JMock now reduces the amount of test code we need and allows us to ‘Stub’ the removeFromInventoryIfAvailable method of Warehouse to force it to return true allowing us to test the happy path of the fill behaviour quiet easily.

Mockist TDD: Mockito Stub Example

Mockito is another tool that allows us to avoid creating hand rolled mocks. Our test would look as follows:

@Test
public void shouldFillOrderWhenEnoughAvailableInWarehouse() {

        // setup
        final int requiredAmount = 50;
        final String productName = "product1";

        order = new OrderImpl(productName, requiredAmount);

        warehouse = mock(Warehouse.class, "warehouseStub");

        // stubbing
        stub(warehouse.removeFromInventoryIfAvailable(requiredAmount,productName))
        .toReturn(true);

        // exercise test
        order.fill(warehouse);

        // state verification
        assertTrue("order is showing as not filled when it should be filled.",
                order.isFilled());
}

I believe that this shows that Mockito provides a slightly cleaner example of ‘stubbing’ than JMock as it has less boilerplate code. It also reads better. From the Mockito syntax, its clear I am using warehouse as a ‘stub’ and the comment above it could go, however on the JMock code, I prefer to leave it as the JMock code uses terms such as checking, expectations and allowing; none of which may allude to the fact that I am trying to stub the method unless you were familiar with the tool.

The test shown explaining the classical and mockist approaches to TDD were all examples of tests that fall under the category of state-based tests. An Order was a good example of when to use a state-based test as it did have state that was affected by its fill behaviour and at the end of the test we added assertions about the state of the system-under-test (Order) that will either pass or fail the test (no in-between).

Their are times when it is not the state of the SUT we care about but the interaction of the SUT with a depended-on-component. This style of test is known as an interaction-based test. We typically use a mock or a test spy as a test double for the depended-on-component to carry out interaction-based tests. As an example we write a unit test for WarehouseImpl.

Interaction-Based Test: JMock Example

/**
 * I test {@link WarehouseImpl}
 */
@RunWith(JMock.class)
public class WarehouseImplTest {

    // system under test (SUT)
    private Warehouse warehouse;

    // depended-on-components
    private InventoryService inventoryService;

    private final Mockery mockery = new JUnit4Mockery();

    @Test
    public void shouldRemoveInventoryWhenContainsEnoughStockOfProduct() {

        // setup
        inventoryService = mockery.mock(InventoryService.class);
        warehouse = new WarehouseImpl(inventoryService);

        final int requiredAmount = 50;
        final String productName = "fakeProduct";

        // behaviour verification
        mockery.checking(new Expectations() {
            {
                one(inventoryService).containsEnoughStock(requiredAmount,
                        productName);
                will(returnValue(true));

                one(inventoryService).removeFromInventoryStock(requiredAmount,
                        productName);
            }
        });

        // exercise test
        warehouse.removeFromInventoryIfAvailable(requiredAmount, productName);
    }
}

Things to note:

  1. There are no assertions at all in this test. It is a purely concerned with the interaction of the SUT with the InventoryService component.
  2. Using JMock, we use expectations about what will happen
  3. When the test runs, the test will fail fast if a method that is not expected on the inventoryService mock is invoked
  4. Whent the test is complete, JMock verifies that all the expectations were satisfied

Interaction-Based Test: Mockito Example

/**
 * I test {@link WarehouseImpl}.
 */
public class WarehouseImplMockitoTest {

    // system under test (SUT)
    private Warehouse warehouse;

    // depended-on-components
    private InventoryService inventoryService;

    @Test
    public void shouldRemoveInventoryWhenContainsEnoughStockOfProduct() {

        // setup
        inventoryService = mock(InventoryService.class);
        warehouse = new WarehouseImpl(inventoryService);

        final int requiredAmount = 50;
        final String productName = "fakeProduct";

        // stubbing (part of set up really)
        stub(inventoryService.containsEnoughStock(requiredAmount, productName))
                .toReturn(true);

        // exercise test
        warehouse.removeFromInventoryIfAvailable(requiredAmount, productName);

        // behaviour verification
        verify(inventoryService).containsEnoughStock(requiredAmount,
                productName);
        verify(inventoryService).removeFromInventoryStock(requiredAmount,
                productName);
    }

}

Things to note:

  1. Using Mockito, we stub methods on our test spy of inventoryService to force execution down a praticular path.
  2. The behaviour verification is done after the test is executed (as test spy observes what happens during test execution which allows us to make assertions about the interactions later).
  3. Using mockito we do have assertions of a type; we assert only what we care about, if there were other interactions that occured that we don’t care about, we don’t have to make any assertion about them
  4. This interaction-based test feels exactly like our state-based test.

Can we have a test that verifies State and Interactions?

It is possible to write a simple test that verifies both the state of something and the interaction of the SUT with one of its components.

Using the last example we could of written the test as:

 @Test
    public void shouldRemoveInventoryWhenContainsEnoughStockOfProductAndReturnTrue() {

        // setup
        inventoryService = mock(InventoryService.class);
        warehouse = new WarehouseImpl(inventoryService);

        final int requiredAmount = 50;
        final String productName = "fakeProduct";

        // stubbing (part of set up really)
        stub(inventoryService.containsEnoughStock(requiredAmount, productName))
                .toReturn(true);

        // exercise test
        final boolean result = warehouse.removeFromInventoryIfAvailable(
                requiredAmount, productName);

        // verification
        // behaviour verification
        verify(inventoryService).containsEnoughStock(requiredAmount,
                productName);
        verify(inventoryService).removeFromInventoryStock(requiredAmount,
                productName);

        // state verification
        assertTrue(result);
    }

Its probably best to avoid this. It would be better to write two tests, one that concentrates expressing the interaction for whatever reason that is important and another that verifies the state returned from the method.

Observations

With regards the Classical versus Mockist TDD approaches, I largely favor the Mockist approach but do at times use real implementations as opposed to test doubles when they are simple objects that are easy to setup (zero components) such as Value objects.

On State-based versus Interaction-based tests: both types of tests will most likely need to be written when using TDD as a technique to develop.

Using ‘mocking frameworks’ such as JMock and Mockito helps keep the amount of test code. It allows a TDD’er to use TDD more as a design activity. We can quickly discover new types and behaviour needed for the system. Using Mockito I find allows for the writing of cleaner tests that better express the intention of the developer.

Bibliography

[1] Mocks Aren’t Stubs: Martin Fowler
[2] xUnit Test Patterns: Gerard Meszaros

Endo-Testing: Discussion

December 16, 2008

I read Dan North’s blog the-end-of-endotesting sometime ago and have been meaning to write up a response of my own for sometime.

The thing about it I initially found confusing was the reference to endo-testing. It would seem that he believed that using the tool Mockito instead of other expect-run-verify mocking frameworks meant that you weren’t doing what was described as endo-testing in [1].

Up until now I have used JMock as my mocking framework of choice. I had read of Mockito and intended to take it for a test drive but until now I just haven’t found the time. My assumptions (from what I had read so far) about Mockito were that it used a test spy as a test double whereas mocking frameworks such as EasyMock and JMock were using a mock as the test double for the depended-on-component.

Note: I am using the terminology Gerard Meszaros describes in [2].

The difference between these approaches is the difference between observation and expectation. The observation approach of a test spy allows for us to exercise the test and then make assertions about what did happen to our test double (test spy) whereas the expectation approach requires us to make expectations about what will happen to our test double (mock) before we exercise the test.

In summary

In summary I think that both approaches can be classified as what was coined endo-testing in [1].

When writing unit tests its important that we know the difference between the types of test doubles described in [2] and know when its best to use them (for the sake of the test).

When I first used JMock, it felt weird that the behaviour verification part of the test had to be implemented (before the exercising of the method under test). When writing tests it does feel more natural to do assertions about what did happen whether those assertions are to do with the state of the system under test (SUT) or assertions to do with what interaction occurred between the SUT and the test double.

So I will also be converting from JMock to using Mockito for my unit tests. There is still a place for the the expect-run-verify mocking frameworks such as EasyMock and JMock but I think that most tests that I am required to write will be benefit from using Mockito.

In another blog I hope to discuss reasons why I am going to use Mockito as opposed to JMock. State-based testing, interaction-based testing, TDD, and classical TDD versus Mockist TDD approaches will most likely come up in the discussion.


Bibliography


[1] Endo-Testing: Unit Testing with Mock Objects; Mackinnon, Freeman and Craig
[2] xUnit Test Patterns; Gerard Meszaros

Adding basic build automation for a web application project using ANT

December 9, 2008

We add the ability to build the projects source and generate an executable artifact that can be deployed to an application server capable of running WAR files. In this example we are using tomcat and thus also add support for managing the application through ANT to aid development.

We also add eclipse launch configurations so the developer can easily execute specific ant targets rather than typing they via the command link or executing them from eclipses ANT view.

Creating ANT build.xml

The build.xml goes at the root of the project and within it we add the following public.

  1. Clean – responsible for cleaning generated files that are not part of the source of the application i.e. .class files. Basically clean should be able to revert the workspace to the same state repeatedly and that should mirror the state of the project when checked out of source control.
  2. Compile – responsible for compiling all source files required for the application. Thus it will require knowledge of the dependencies required for the source to compile.
  3. Test – this target will invoke all tests that are added. The method behind the development of this software is that developers add tests as new functionality is added and all tests should be passing before checking the code back into source control.
  4. Build – this target is responsible for generating the software deliverable we need;  A WAR file. It cleans, compiles, tests and then packages up the compiled code into a WAR file for deployment to a web container.

Adding tomcat support for Development

We can use the catalina-ant.jar file from the tomcat distribution and create macros around them to allow developers to quickly deploy, undeploy applications on a specific tomcat instance.

To do this we create tomcat.properties, tomcatTasks.properties and tomcat-macros.xml files. Then we adding the following public targets to our build.xml file

  1. deploy
  2. undeploy

Using Eclipse External Tool Configurations

To make things even easier, we can integrate our IDE (Eclipse) and our build tool (ANT) and create configurations that we can maintain in source control. As these are IDE specific, they can be contained within a folder within the project but the build itself knows nothing of this folder.

Choose option from eclipse configuration menu:
eclipse-configuration-menu

The project structure after build automation has been added
build-automation-with-eclipse-launch-configurations

Note: the eclipse specific launch configuration files

Dependencies of Spring/Hibernate/HSQLDB web application

December 7, 2008

Add the following dependencies to your project as described below and show in the picture:

Test dependencies

Put the following dependencies into the lib/test folder:

  1. junit-4.4.jar
  2. jmock-2.5.1.jar + dependencies
  3. hamcrest-core-1.1.jar + hamcrest-library-1.1.jar from Jmock download

Tools/Compilation dependencies

Put the following dependencies into the lib/compile folder:

  1. hibernate-tools.jar + dependencies (latest version compatible with hibernate 3.3.x
  2. catalina-ant.jar from tomcat 6.0.18 download
  3. servlet-api-2.5.jar from tomcat 6.0.18 download

Runtime dependencies

Put the following dependencies into the lib folder:

  1. spring 2.5.6 + dependencies
  2. spring-webmvc.jar
  3. jstl.jar and standard.jar (from spring framework download dist folder)
  4. joda-time-1.6.jar
  5. hsqldb-1.8.0.7.jar
  6. hibernate3.3.1.jar + dependencies (including slf4j-simple-1.5.2.jar)
  7. commons-logging.jar, commons-lang.jar, commons-collections-3.1.jar (from spring framework download dist folder)

Dependencies of Spring/Hibernate Web Application

hibernate-spring-web-dependencies


Follow

Get every new post delivered to your Inbox.