Incremental development with ANT and JUNIT

xiaoxiao2021-03-06  58

Use ANT and JUnit to increase the use of unit tests to gradually improve the code

From http://www-900.ibm.com/developerWorks/cn/java/j-ant/index.shtmlmalcolm Davis consultant November 2000

Content: From class start automation unit test integration into the construction to understand the test work principle is not completely painless to implement 24x7 reference information about the author

Software development habits may have great improvements to software quality. Combine unit tests into the development process, then see how much time and effort can save from a long-term perspective. This paper illustrates the benefits of unit testing by using code samples, especially the various conveniences brought by ANT and JUnit.

Test is one of the basic principles of large development. In any occupation, verification is an important part. The doctor should diagnose the blood test. Boeing has been carefully tested in each component of the aircraft during the development of 777. Why should software should be exceptional?

Previously, this limits the ability to create automated testing due to the close links of GUI and business logic in the application. When we learn to separate commercial logic from the interface via the abstraction, automatic testing of each individual code module replaces manual tests performed by GUI.

Now, the Integrated Development Environment (IDE) can display an error while you enter the code, which has a smart lookup method in the class, which can generate color code using the syntax structure and have many other functions. Therefore, before compiling changed code, you have already considered the class that will build, but whether you consider such modifications to destroy certain features?

Each developer has encountered a "bug". The code modification process may introduce "bug", and if you are handled by the user interface, it will not find it before compiling. You will then take a few days of time tracking the error caused by changes. Recently I did in a project I did, when I changed the backend database by INFORMIX to Oracle, I encountered this situation. Most changes are very smooth, but due to the lack of unit testing of the database layer or using the database layer, it causes a lot of time to spend a large amount of time on attempting to solve the change "bug". I spent two days to find a database syntax change in someone else's code. (Of course, that person is still my friend.)

Although there are many benefits, the general programmers are not interested in testing, and I don't have it when I start. How many times have you heard "it compiled, so it will use" this kind of speech? But "I think, I am" this principle does not apply to high quality software. To encourage programmers to test their code, the process must be simple and painful.

This article begins with a simple class written when you learn from Java language programming. Then, I will tell you how I write unit testing for this class, and how to add unit tests during the build process after writing it. Finally, we will see what happens when "bug" introduces code.

From a typical class, the first typical Java program typically contains main () of "Hello World". In Listing 1, I created an instance of a HelloWorld object and called a SayHello () method, which prints this habit.

Listing 1. My first Java application "Hello World"

/ *

* HelloWorld.java

* My First Java Program

* /

Class helloworld {

/ **

* Print "Hello World"

* /

Void syhello () {

System.out.println ("Hello World");

}

/ **

* Test

* /

Public static void main (string [] args) {helloworld world = new helloworld ();

World.SAYHELLO ();

}

}

The main () method is my test. Oh! I am included in a module in a module. Bless Java! But as the program is getting bigger, this development method will soon start show defects:

The larger the chaotic interface, the greater the main (). The class may be very large because of the normal test. The code expansion is required for the product code than the test. But I don't want to pay the test, but I only want to deliver the product. Test is unreliable. Since Main () is part of the code, main () enjoys access to other developers from private members and methods that cannot be accessed by class interfaces. For this reason, this test method is easily error. It is difficult to automatically test to perform automatic testing, I still have to create another program to pass the parameters to main ().

Class development is for me, class development begins with the written main () method. I define the usage of classes and classes when writing main (), and then implement the interface. Its obvious defects have also begun to show it. A defect is that I passed to main () to perform the number of parameters. Second, main () itself becomes confusing when the caller method, set up code, etc. Sometimes main () will be larger than the rest of the category.

The simplest process I originally practiced some obvious defects. So let's take a look at what other methods can make problems simplify. I still use the code code and give an application example, just like the original main (). Different is that I put the code in another separate class, and this class happens to be my "unit test". This technique has the following benefits:

A mechanism for designing a class is unlikely to utilize the internal functions of classes through the interface. But because I am a developer of the target class, I have the "window" that I have internal work, so the test is not a real black box. With this only, it is sufficient to infer enough to develop the developer himself while writing the target class while responsible for the development of testing, not by anyone else. Examples of class usage are separated from the implementation, and developers can improve their speed faster, and no need to entangle unclear on the source code. This separation also helps prevent developers from using the internal functions of classes, as these functions may no longer exist. There is no confusing main () I am no longer limited by main (). I have to pass multiple parameters to main () to test different configurations. Now I can create many separate test classes, each maintained their respective setup code.

Next we put this separate unit test object in the build process. This way, we can provide a method of automatic confirmation process.

Ensure that any changes made will not adversely affect others. We can test the code before performing source control, without waiting for compilation testing or build testing at night. This helps to capture "bug" as soon as possible, thereby reducing costs that produce high quality code. By providing incremental testing processes, we offer a better implementation process. As IDE helps us capture syntax or compile "Bug" when entering, the incremental unit test also helps us capture the code to change "bug" when building.

Using the JUnit Automation unit test To make test automation, you need a test framework. You can develop or purchase themselves, or you can use some open source tools, such as JUnit. I chose Junit for several reasons:

You don't need to write your own framework. It is open source, so it is not necessary to purchase a framework. Other developers in the open source community will use it, so many examples can be found. It allows me to separate the test code from the product code. It is easy to integrate into my build process.

Test layout Figure 1 shows the JUnit TestSuite layout using sample Testsuite. Each test consists of several separate test cases. Each test case is a separate class, which extends the TestClass class and contains my test code, that is, the code that has appeared in main (). In this example, I added two tests to TestSuite: one is Skeletontest, I use it as the starting point for all new categories and HelloWorld classes. Figure 1. TestSuite layout

Test class HelloWorldTest.java Contacts, the name of the test class contains the name of the class I tested, but attached Test to the end. In this example, our test class is HelloWorldtest.java. I copied the code in Skeletontest and added TestSayhello () to test SayHello (). Note that HelloWorldTest extends Testcase. The JUnit Framework provides an Assert and Assertequals method, we can use these methods to verify. HelloWorldTest.java is displayed in Listing 2.

Listing 2. HelloWorldtest.java

Package test.com.Company;

Import com.company.helloworld;

Import junit.framework.testcase;

Import junit.framework.assertionfaileder;

/ **

* JUnit 3.2 Testcases for HelloWorld

* /

Public class helloworldtest extends Testcase {

Public HelloWorldTest (String Name) {

Super (Name);

}

Public static void main (string args []) {

JUnit.textui.teStrunner.run (HelloWorldtest.class);

}

Public void testsayhello () {

HelloWorld World = New HelloWorld ();

Assert (world! = null);

Assertequals ("Hello World", World.SAYHELLO ());

}

}

Testsayhello () looks similar to the original main method in HelloWorld.java, but there is a major difference. It is not executing system.out.println and displays the result, but adds an assertequals () method. If the two values ​​are different, Assertequals will printed two input values. You may have noticed that this method doesn't work! The SayHello () method in HelloWorld does not return a string. If I write test first, I will capture this. I linked the "Hello World" string with the output stream. In this way, helloWorld is overwritten as shown in Listing 3, remove main (), and change the return type of SayHello ().

Listing 3. Hello World test case.

Package com.Company;

Public class helloworld {

Public String Sayhello () {

Return "Hello World";

}

}

If I retain main () and modify contact, the code looks as follows:

Public static void main (String [] args) {

HelloWorld World = New HelloWorld (); System.out.Println (World.SAYHELLO ());

}

New main () is very similar to Testsayhello () in my test program. Yes, it looks not like a problem in a real world (this is a human example problem), but it explains the problem. Writing main () in a separate application can improve your design while helping you design test. Now we have created a test class, let us use Ant to integrate it into the build.

Integrated testing into builds using Ant to build the ANT tool as "Make short-on". Ant is becoming the actual standard in the open source code. The reason is very simple: ANT is written in Java language, which allows the build process to be used on a variety of platforms. This characteristic simplifies the cooperation between programmers between different OS platforms, and cooperation is a need for open source and code communities. You can develop and build on your own platform. The features of Ant include:

The class scalability Java class can be used to extend the build feature without having to use the shell-based command. Open source code because ANT is open source, so the class extension example is sufficient. I have found that it is great to learn from example. XML configurable ANT is not only based on Java, it also uses the XML file configuration process. Assuming that the build is actually a layered, the MAKE process using the XML is the logic layer. Also, if you understand XML, you should learn how to configure the build.

Figure 2 briefly introduces a profile. The configuration file is constructed by the target tree. Each goal contains tasks to be executed, where the task is the code that can be performed. In this example, mkdir is the task of the target Compile. MKDir is a task built in Ant for creating a directory. Ant has a sound built-in task. You can also add your own features by extending the ANT task class.

Each goal has a unique name and optional correlation. Target correlation needs to be executed before performing a list of target tasks. For example, as shown in Figure 2, you need to run the JUnit target before performing the tasks in the Compile target. This type of configuration allows you to have multiple trees in one configuration.

Figure 2. Ant XML build diagram

Similarity with the classic Make utility is very significant. This is a matter of course, because Make is Make. But also remember that there are some differences: cross-platform and scalability implemented through Java, through XML implementation, and open source.

Download and install Ant first download Ant (see Resources). Decompress the ANT to the Tools directory and add the Ant bin directory to the path. (In my machine is E: / TOOLS / ANT / BIN.) Set the ANT_HOME environment variable. In NT, this means entering the system properties, then adds Ant_Home in the form of a value of values. Ant_home should be set to the ANT root directory, which contains the directory of the bin and lib directory. (For me, E: / TOOLS / ANT.) Make sure the Java_Home environment variable is set to the Directory for the JDK. The ANT documentation is about the installation details.

Download and Install JUnit Download JUnit 3.2 (see Resources).

Unlock JUnit.zip and add JUnit.jar to ClassPath. If you are unpacking junit.zip into a classpath, you can test the installation by running the following: Java junit.textui.teestrunner junit.samples.alltests

Defining a directory structure requires a project layout before starting our build and test procedures. Figure 3 shows the layout of my sample item. The layout of the list of layouts: Build - temporary build locations for class files. The build process will create this directory. SRC - The location of the source code. SRC is divided into a Test folder and a main folder, for all test code, while the latter contains deliverable code. Separate test code with major code separation. First, reduce the chaos in the main code. Second, it allows the package to be aligned. I am passionate with the classes and their associated packages. Test should be tested together. It also helps the distribution process, because you can't intend to distribute unit tests to our customers.

In practice, we have multiple directories, such as Distribution and Documentation. We will also have multiple directorys for packages, such as com.company.util.

Because the directory structure is often changed, there is important to have these changes in Build.xml.

Figure 3. Project layout map

Ant build configuration file example Next, we want to create a configuration file. Listing 4 shows an example of an ANT build file. The key to build files is the target called Runtests. This goal is branch judge and runs an external program, where the external program is the previously installed junit.textui.teestrunner. We specify which test suite to use the statement TEST.COMPANY.ALLJUNITTESTS to run.

Listing 4. Build a file example

Basedir = "$ {build.dir}" includes = "com / **" />

TaskName = "junit" FailοnerRοr = "true">

The next step in running the Ant build sample development process is to run the build and test the build of the HelloWorld class. Listing 5 shows the results of the build, including each target portion. The coolest part is Runteests output statement: it tells us that the entire test suite is running correctly.

I showed the JUnit GUI in Figures 4 and 5, where what to do is to change the RUNTEST target from junit.textui.teStrunner to junit.ui.Testrunner. When you use the JUnit's GUI section, you must select the exit button to continue the build process. If you build a package with a JUnit GUI, it will be more difficult to integrate with a large build process. In addition, the text output is also more consistent with the build process and can be directed to a text file for mainly built records. This is very suitable for the construction of every night.

Listing 5. Constructing an example

E: / Projects / Sample> Ant Runtests

Searching for build.xml ...

BuildFile: E: /Projects/sample/build.xml

JUnit:

Compile:

[MKDIR] Created Dir: E: / Projects / Sample / Build / Classes

[Javac] Compiling 1 Source File to E: / Projects / Sample / Build / Classes

JAR:

[MKDIR] Created Dir: E: / Projects / Sample / Build / LIB

[jar] building jar: E: /Projects/sample/build/lib/sample.jar

CompileTests:

[MKDIR] Created Dir: E: / Projects / Sample / Build / Testcases

[Javac] Compiling 3 Source Files To E: / Projects / Sample / Build / Testcases

Runtests:

[junit] ..

[junit] Time: 0.031

[junit]

[JUnit] OK (2 tests)

[junit]

Build Successful

Total Time: 1 Second

Figure 4. JUnit GUI test success

Figure 5. JUnit GUI test failed

Understanding the working principle of the test, let us get some destruction, then look at what will happen. Night, we decided to turn "Hello World" into a static string. During the changes, we accidentally went wrong with the letters, turned "O" into "0", as shown in Listing 6.

Listing 6. Hello World class change

Package com.Company;

Public class helloworld {

Private final static string hello_world = "Hell0 World";

Public String Sayhello () {

Return hello_world;

}

}

When building a package, we saw the error. Listing 7 shows the errors in RUNTEST. It shows the failed test class and test method, and explains why it will fail. We returned to the code and left after correcting the error.

Listing 7. Sample buffer example

E: / Projects / Sample> Ant Runtests

Searching for build.xml ...

BuildFile: E: /Projects/sample/build.xml

JUnit:

Compile:

JAR:

CompileTests:

Runtests:

[junit] ..f

[junit] Time: 0

[junit]

[JUnit] Failures !!!

[junit] Test Results:

[JUnit] Run: 2 Failures: 1 Errors: 0

[JUnit] There was 1 Failure:

[junit] 1) Testsayhello (Test.com.comPany.Helloworldtest "Expected:

World> But Was: "

[junit]

Build Failed

E: /Projects/sample/build.xml: 35: Java Returned: -1

Total Time: 0 second SECONDS

Not completely painless process is not completely painless. In order to make cell tests become part of development, you must take the following steps:

Download and install JUnit. Download and install ANT. To build a separate structure. Implement the test class separate from the primary class. Learn the ANT build process. But the benefits far exceeded the pain. By making unit testing into part of the development process, you can:

Automatically verify to capture the "Bug" from the interface angle design class to provide a clean example to avoid code confusion and class expansion in the issuing package.

Implementation 24x7 guarantees the quality of the product to spend a lot of money, but if the quality is defect, the money spent is more. How can I make the money spending to ensure product quality?

Review design and code. The effect that the review can be achieved is half a simple test. Confirm that the module can be used by unit testing. Although the test has long been present, with the continuous development of development practices, unit tests have gradually become a part of the daily development process.

In my 10 years of development, it is one of the most important parts for Emageon.com. When eMageon.com, design review, code review and unit testing are things you have to do every day. This daily development habit has made the highest quality product. Software is zero in the first year of the customer's location, is a real 24x7 product. Unit tests are like brushing: You don't have to do it, but if you do, the quality of life is better. Reference

Download the sample code referenced in this article. Download ANT from the Apache website. For Ant documents, FAQ, and other downloads, visit the ANT home page of the Jakarta project. The JUnit Home provides additional test examples, documents, articles, and FAQ. You can download JUnit 3.2 from www.xprogramming.com. The "Simple SmallTalk Test" written by Kent Beck discusses a simple test policy and supports its framework. Please refer to the Comments on Unit Testing for other developers. To learn more about other useful development habits, access the ultimate programmming home page.

About the author Malcolm G. Davis has its own consulting firm, and serves as the president of the company, the company is located in Birmingham in Alabama, USA. He regards himself as a Java officer. In the work, he likes to run, and play with his children. You can contact Malcolm via Malcolm@Nuearth.com.

转载请注明原文地址:https://www.9cbs.com/read-113012.html

New Post(0)