• No results found

Running Specific Tests 1 Problem

Another Technique

3.17 Running Specific Tests 1 Problem

3.17.2 Solution

Use the

junit

task with a nested

test

element.

3.17.3 Discussion

Recipe 3.16 showed how to use

junit

in conjunction with

batchtest

to run every test in one or more paths. There may be times, however, when you want to selectively run a single test. For

instance, you might be working on a specific class and don't want to run hundreds of tests for each change you make. To run a single test using Ant, use the

test

element instead of

batchtest

. Example 3-8 shows how to define a target that runs a specific test.

Example 3-8. Running a single test

<target name="junit2" depends="compile">

<!-- you may override this on the command line:

ant -Dtestcase=com/oreilly/javaxp/junit/TestGame

junit2 -->

<property name="testcase"

value="com/oreilly/javaxp/junit/TestPerson"/>

<junit fork="false">

<classpath refid="classpath.project"/>

<formatter type="plain" usefile="false"/>

<test name="${testcase}"/>

</junit>

</target>

Rather than hardcode the name of the test, our example allows the user to specify the test name on the Ant command line. This takes advantage of Ant's ability to obtain properties from the command line using the

-D

syntax.

3.17.4 See Also

The previous recipe showed how to run all tests.

3.18 Generating a Test Report

3.18.1 Problem

You want to produce a nicely formatted HTML report that summarizes results from all of your tests.

3.18.2 Solution

3.18.3 Discussion

In earlier examples, we sent test results directly to the console. In order to format our results as HTML, we need to first write the test results to a series of XML files. We do this with the following line:

<formatter type="xml"/>

This causes test results to go to a series of XML files, one per test. The XML files are written to the directory named by the

todir

attribute of the

junit

task or the nested

batchtest

element. Once the files are created,

junitreport

uses XSLT stylesheets to convert the XML files into a nice HTML report. The complete Ant target is shown in Example 3-9.

Example 3-9. Generating a test report

<target name="junit" depends="compile">

<junit printsummary="on" fork="false" haltonfailure="false">

<classpath refid="classpath.project"/>

<formatter type="xml"/>

<batchtest todir="${dir.build}">

<fileset dir="${dir.src}">

<include name="**/Test*.java"/>

</fileset>

</batchtest>

</junit>

<junitreport todir="${dir.build}">

<fileset dir="${dir.build}">

<include name="TEST-*.xml"/>

</fileset>

<report format="frames" todir="${dir.build}"/>

</junitreport>

<!-- convert an Ant path to a fully-qualified platform

specific path -->

<pathconvert dirsep="/" property="reportUrl">

<path>

<pathelement location="${dir.build}/index.html"/>

</path>

</pathconvert>

<!-- launch a web browser to view the results -->

<exec executable="cmd" os="Windows XP">

<arg value="${reportUrl}"/> <!-- the full path to the

report -->

</exec>

</target>

Our buildfile runs all tests in the src directory tree and then sends XML results to the build directory, which was specified in the

todir

attribute of

junitreport

. After

junitreport

runs, we launch a web browser to view the test results. This last portion of the example only works on

Microsoft Windows. If you are on a different platform, simply change the

exec

task to point to your browser.

3.18.4 See Also

The previous two recipes show other ways to run tests.

3.19 Checking Out Code from CVS

3.19.1 Problem

You want your Ant buildfile to check out code from CVS before compiling.

3.19.2 Solution

Use Ant's

cvs

task.

3.19.3 Discussion

You can use the

cvs

Ant task to execute any CVS command. In order for this to work, you must have installed the cvs executable on your system path. If Ant does not find cvs, it issues an error and the build fails.

By default, the

cvs

task executes a

checkout

command. Here is the syntax to checkout the cookbook module from CVS:

<cvs cvsroot="${cvsroot}"

package="cookbook"/>

You can also execute any other CVS command, such as

update

as shown here:

<cvs command="update -dP"

cvsroot="${cvsroot}"

dest="cookbook"/>

This tells CVS to update the most recent files in the cookbook directory, creating missing directories and pruning empty directories.

If

cvsroot

is not specified, the already-defined CVS root from the checked out project is used.

3.19.4 See Also

See the CVS documentation for information about all of the CVS commands.

3.20 Bootstrapping a Build

3.20.1 Problem

You want to use Ant to kick off a nightly build process.

3.20.2 Solution

Create a "bootstrap" buildfile that checks out a clean copy of all sources from revision control. Then, pass off control to the main buildfile that was one of the files just checked out.

3.20.3 Discussion

Many projects set up a build server that performs complete, clean builds at scheduled times. A clean build ensures that every file in the system compiles. If you do not start with a clean slate, you may end up with a successful build just because some obsolete source or class files are lingering in your directory structure.

A clean build consists of the following high-level steps:

1. Start the build with a scheduling mechanism of some sort. This is generally platform-specific and is not covered here.

2. Use a script to checkout all files into a clean directory. This is what we are covering in this recipe.

3. Once all files are checked out, including the main project buildfile, invoke Ant on the main buildfile.

Example 3-10 shows the complete Ant buildfile for performing a bootstrap build. The buildfile uses the

cvs

task as shown in Recipe 3.19 to checkout or update the entire cookbook directory. Once the latest files are obtained, we invoke Ant on cookbook/build.xml to perform the clean build.

Example 3-10. Bootstrap buildfile

<?xml version="1.0"?>

<project name="Java XP Cookbook" default="build" basedir=".">

<target name="prepare">

<!-- convert the CVS repository directory into

a fully-qualitied Windows directory -->

<pathconvert targetos="windows"

property="cvsrepository.path">

<path>

<pathelement location="repository"/>

</path>

</pathconvert>

<!-- store the CVS root in a property -->

<property name="cvsroot"

value=":local:${cvsrepository.path}"/>

<!-- determine if the files have been checked out -->

<available file="cookbook" type="dir"

property="already.checked.out"/>

</target>

<target name="clean"

description="Remove the entire cookbook directory.">

<delete dir="cookbook"/>

</target>

<target name="cvscheckout" depends="prepare"

unless="already.checked.out">

<cvs cvsroot="${cvsroot}"

package="cookbook"/>

</target>

<target name="cvsupdate" depends="prepare"

if="already.checked.out">

<cvs command="update -dP"

cvsroot="${cvsroot}"

dest="cookbook"/>

</target>

<target name="build" depends="cvscheckout,cvsupdate">

<ant dir="cookbook" target="all" inheritAll="false"/>

</target>

</project>

3.20.4 See Also

Windows users can use "Scheduled Tasks" under the Control Panel to schedule builds for certain times of day. The CruiseControl tool is designed to help with continuous integration, and is available at http://cruisecontrol.sourceforge.net.

Section 4.1. Introduction Section 4.2. Getting Started Section 4.3. Running JUnit

Section 4.4. assertXXX( ) Methods Section 4.5. Unit Test Granularity Section 4.6. Set Up and Tear Down

Section 4.7. One-Time Set Up and Tear Down Section 4.8. Organizing Tests into Test Suites Section 4.9. Running a Test Class Directly Section 4.10. Repeating Tests

Section 4.11. Test Naming Conventions Section 4.12. Unit Test Organization Section 4.13. Exception Handling

Section 4.14. Running Tests Concurrently Section 4.15. Testing Asynchronous Methods Section 4.16. Writing a Base Class for Your Tests Section 4.17. Testing Swing Code

Section 4.18. Avoiding Swing Threading Problems Section 4.19. Testing with the Robot

Section 4.20. Testing Database Logic

Section 4.21. Repeatedly Testing the Same Method

4.1 Introduction

Unit testing is at the heart of XP, and it is a central theme of this book. JUnit,[1] available from http://www.junit.org, is the de facto standard for Java unit testing. It is a simple framework for creating automated unit tests. JUnit test cases are Java classes that contain one or more unit test methods, and these tests are grouped into test suites. You can run tests individually, or you can run entire test suites.

[1] We cover JUnit Version 3.8.1 in this chapter.

Ant includes the

junit

task for running JUnit tests. We show how to run JUnit tests using Ant in Chapter 3.

Each JUnit test method should execute quickly. Speed is important because as more tests are written and integrated into the build process, it takes longer to run the entire test suite. Programmers do not want to be interrupted for long periods of times while tests run—so the longer the tests take to execute the greater the likelihood programmers will skip this critical phase.

You can also increase the likelihood that programmers will run the tests by making it extremely easy, preferably with a single command. The ability to run all tests with a single command or button click is nearly a requirement to claim that your project is doing XP. We showed how to run tests with Ant in the previous chapter, and many IDEs now make it possible to run tests by clicking on a menu item. JUnit tests are pass/fail tests explicitly designed to run without human intervention. Because of this design, you can (and should) add your test suite to your continuous integration build process so the tests run automatically.

4.2 Getting Started