Ask a question
Saturday, 12 September 2009 13:54

Sample Application - Environment Setup: JDK, Ant, and JUnit

Rate this item
(0 votes)

Java Platform Standard Edition Development Kit (JDK)

Because we are doing Java development, it would make sense to have the necessary Java tools (for example, compiler) set up. If you do not already have the JDK installed on your machine, or if you have an older version than ones required by JUnit and Ant, you should get the latest version from the java.sun.com website and have it set up on your machine so that commands such as java are in your path.

After downloading and installing Java, you should be able to type the command javaversion to test your setup and ensure you have the correct version of the JDK, as shown next:

C:\anil\rapidjava\timex>java -version

java version "1.5.0_06"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_06-b05)
Java HotSpot(TM) Client VM (build 1.5.0_06-b05, mixed mode, sharing)

Directory Structure


Let's revisit the directory structure we covered in the previous chapter. Figure 4.1 shows the directory structure. It is important to see this again now before we jump into the Ant discussion. Let's review some of the more notable subdirectories here:

  •          src directory will contain all the Java, HTML/Javascript, XML, and all other input/source files that we will develop ourselves.
  •          build will contain the output of our builds (for example, compilation, copying of web and library files, and so on).
  •       lib will contain all external JAR files required to run our application.
  •          dist will contain our web archive (.war) file, which contains all the web-related files, compiled .class files, .jar library files, and more.

Ant


I would not be exaggerating by claiming that Ant (ant.apache.org) is perhaps the single most important and widely used tool in the world of Java today! Therefore, mastering this tool is the key to rapid Java development. So, it is no surprise that I'm covering this tool directly after the JDK section, because I consider Ant the most vital tool to install after you are done with the basic Java setup.

By now you probably realize the important role Ant plays in Java development. We will use Ant extensively in this book! For example, we will use it to build our application, deploy it, run various Java programs, create our database, run our tests, and more.

Ant was originally developed by James Duncan Davidson, from the Open Source Program Office at Sun Microsystems. Ant is a cross-platform build tool that eliminates a lot of complexities and quirks that can be found in tools such as Unix make. Instead of using shell commands proprietary to the operating system, Ant uses XML files to specify various tasks. Ant is a highly extensible tool, mainly because of the huge market of builtin and external (open source and commercial) tasks available for Ant, which makes it so powerful. In addition, you can easily write your own custom extensions.

Given that Ant itself is developed in Java, it is portable, and according to the Ant website, it has been tested on various Unix systems, Microsoft Windows, Mac OS X, and others. The ant.apache.org website provides ample (and up-to-date) information on how to get Ant set up on your system; if you do not already have Ant installed on your system, you should go ahead and do so at this point.

When you do have Ant set up successfully, you should be able to run the ant command without specifying the full path. That is, the ant command should be in your path because the remainder of our book will reference ant without the full path. For example, if you typed ant -version on the command line, you would see something similar to what is shown in Figure 4.2

JUnit

JUnit, originally written by Erich Gamma (Gang of Four, Design Patterns book) and Kent Beck (also author of Extreme Programming), is an open source Java testing framework commonly used for unit testing of Java code. It can be downloaded from the junit.org website; this website provides not only setup instructions, but also articles on unit testing and many benefits to writing tests first.

Test-driven development (TDD), a term coined by Kent Beck, can enable better code design, cleaner code (fewer print/debug statements and test scripts), and more efficient code. Because we will follow this approach by writing tests first in this book, it makes sense to cover JUnit directly after JDK and Ant sections.

JUnit Standalone Runners


For setting up JUnit, again I will refer you to the installation instructions found on the product's website, junit.org. The JUnit test runner (Java main class) comes in two flavors: a textual version and a graphical version. The graphical version is available in two variations, a Java Swing-based one (recommended) and an older, AWT-based one.

After you have JUnit set up correctly, you should be able to type the following command (from the JUnit install directory; for example, C:\junit3.8.1) and be able to run the Swing version of JUnit's user interface, shown in Figure 4.5:

java -cp junit.jar junit.swingui. TestRunner

JUnit in Eclipse SDK

In the next chapters, we will continue to use the standalone JUnit test runners for working with JUnit, described here. However, when I introduce Eclipse later in the book, we will switch to using JUnit within Eclipse (shown in Figure 4.6), which makes running and debugging JUnit tests much more convenient. However, there might be times when you want to run batch tests using the Ant junit task on a server or even test a single class outside of the IDE, using one of the JUnit built-in runners.

SimpleTest: Making the Tools Work Together


Assuming we have the JDK, Ant, and JUnit set up correctly, we should be able to now write a sample JUnit Test and try it out.

Regardless of which flavor of JUnit we use, we can either pass it our test class name or type it into the UI runner. For example, if we wanted to write a very simple test case to test the fact that 2 + 3 = 5, we would do the following:
·         Develop a JUnit test classfor example, SimpleTest.java.
·         Run the JUnit class using one of the JUnit runners.

SimpleTest.java

This book's code file (available on the book's website) shows the complete code for SimpleTest.java. The code should be fairly straightforward to follow. There are two test methods: testAddSuccess and testAddFail, as shown here:

public void testAddSuccess()

{

    assertTrue(value1 + value2 == expectedResult);
}

public void testAddFail()

{
    assertTrue(value1 - value2 == expectedResult);
}

The testAddSuccess method will be successful, whereas the testAddFail method will fail (because 2 minus 3 does not equal 5). The success or failure is determined by the JUnit assert methods, which throw an exception if the test failed.

JUnit Assert Methods

We saw an example of JUnit's assertTrue method in our example previously; JUnit also provides several other flavors of assert methods, as shown next:
·         assertEquals
·         assertFalse
·         assertNotNull
·         assertNotSame
·         assertNull
·         assertSame
·         assertTrue

Running SimpleTest (a Single JUnit TestCase)

To try out the code we saw for SimpleTest, we need to create the SimpleTest.java file, compile it, and try running it. So, let's create the SimpleTest.java file under our src/java/com/visualpatterns/timex/test/ directory. Then we can simply type the ant command from the timex/ directory to compile our unit test source code.

Now, let's try running our SimpleTest test case (from the top-level timex/ directory) using the JUnit test runner, as demonstrated here:

C:\anil\rapidjava\timex>java
 -cp \junit3.8.1\junit.jar;build/timex/WEB-INF/classes
 junit.textui. TestRunner com.visualpatterns.timex.test. SimpleTest

We should see something similar to what is shown in Figure 4.7.

We could also run SimpleTest.class in the JUnit swing runner, as shown next (Figure 4.8 shows the result of this command):

java -cp \junit3.8.1\junit.jar;build/timex/WEB-INF/classes
 junit.swingui. TestRunner
com.visualpatterns.timex.test. SimpleTest 

The junit.framework. AssertionFailedError related messages you see in both the test runners is actually a good thing; these are valid JUnit errors because our testAddFail method failed.

Running JUnit Tests in a Batch

There is one more way we can run JUnitthat is, as an Ant task. Next we'll take a look at how we do that.

First, let's copy the junit.jar file from the JUnit install directory to the /lib directory; for example, on Microsoft Windows you would type something like copy \junit3.8.1\junit.jar \apache-ant-1.6.5\lib. This enables us to use the junit Ant task.

Second, we need to copy the same junit.jar to our timex/lib directory; this also will assist with our builds using Ant.

Now let's revisit our build.xml file. This file contains a target named test, which uses the junit task, as shown in the following excerpt:




        
      
               
       
 
If we run the command ant test, the results of the batch test would appear in a file named TEST-com.visualpatterns.timex.test. SimpleTest.txt in the current directory, an excerpt of which is shown here:

Testsuite: com.visualpatterns.timex.test. SimpleTest
Tests run: 2, Failures: 1, Errors: 0, Time elapsed: 0.021 sec

Testcase: testAddSuccess took 0.004 sec
Testcase: testAddFail took 0.003 sec
FAILED

That's pretty much all there is to JUnit! Although JUnit is a simple framework, it is powerful because you can have several test methods within each JUnit TestCase subclass (a suite). Furthermore, you can roll up the individual suites within other suites (with no limit). For example, you can create a class named AllTests, which calls the suites of all other Test classes in the test package.

 

Test First Design and Refactoring

Test-driven development (TDD) has brought the concept of test first design to the fore-front. This approach has several benefits and hence we will write tests first in this book, whenever possible.

Writing tests first takes a little bit of getting used to, and many times, you will wonder if you really have the time to write tests given the pressure of deliverables. However, I find it is a nicer way to code (after you get the hang of it), particularly because it helps me think of how to design/develop my classes. Also, if you factor in the time you spend unit testing and fixing defects discovered during functional and user testing, you will find that this style of working can actually save time in the end.

Writing tests first has several benefits. For example, writing tests first ensures that you write only functional code that will actually be used; this is based on the assumption that you have written code to satisfy the unit tests, which themselves are based on the acceptance tests specified earlier in our business requirements. Second, if your code passes the unit and acceptance tests, you are done with that part of the code. Third, it can help you design your classes better because when you write the test first, you are experiencing firsthand how your actual classes/methods will be used. Last, test first can also help you to refactor with confidence because you can retest your refactored code quickly through JUnit unit tests to ensure that the refactored code works as the original version did (assuming there is little or no change to the external interface, as defined on refactoring.com).

Although, unit testing is only one part of the overall testing that occurs in corporations, it is something that developers should always do. Other testing includes functional testing, user acceptance testing (UAT), system integration testing (also known as interface testing), stress/load testing, and more.

We will use JUnit to implement our acceptance tests. The following are sample files to demonstrate our class-naming convention for test classes:

·         test/TimesheetListControllerTest.java
·         test/TimesheetManagerTest.java
·         test/ReminderEmailTest.java

I have chosen to keep our JUnit test classes in a separate test package (that is, com.visualpatterns.timex.test) because I believe this is a cleaner design. However, I've also seen other developers keep the JUnit test classes in the same directory as the code being tested. For example, in this scenario, our TimesheetListControllerTest.java would be placed in our controller package.
 
Last modified on Wednesday, 23 September 2009 21:17
Administrator

Administrator

E-mail: This e-mail address is being protected from spambots. You need JavaScript enabled to view it