G53QAT- Quality Assurance and Test [JUnit] Report on the unit testing framework JUnit By Irshad A. Qabool 2009 Table of Contents Introduction .......................................................................................................................... 3 Background Information ........................................................................................................ 3 Unit Testing ........................................................................................................................... 4 JUnit Testing Process.............................................................................................................. 5 Writing Tests in JUnit ............................................................................................................. 6 JUnit Test Results ................................................................................................................... 8 Final Glance at JUnit............................................................................................................... 9 References........................................................................................................................... 10 2|Page Introduction Any programmer, experienced or inexperienced, would know that testing is essential in the development of software applications. Whether it’s a small application or a large application it is safe to assume that some form of testing is preformed throughout the development cycle. This fact is independent of the programming language, the operating system, or the software developer. However these factors among others will affect the type of test that is preformed and the manner in which it is executed. There are some programming techniques used by developers in order to test various parts of their applications. For example the use of print statements, debugger statements, test scripts etc, however such techniques are both time consuming, difficult to keep track off, and potentially inefficient. Different programming languages such as C/C++, Java, Haskell, etc have third party testing frameworks or automated testing tools available to them that assist in the testing of software applications. Traditionally software testing is split up into white box testing and black box testing. With black box the internal structure of the test subject is unknown, only information on relevant inputs and output is required. White box testing takes an internal perspective of the application and designs tests based on the internal structure, the code. JUnit is a type of white box testing. Specifically it is a type of unit testing which is an instance of the xUnit, a collection of unit testing frameworks. Please refer to the section on unit testing for more information. JUnit is designed to write and run tests on Java applications. The framework is open source and free to download as a library contained within a JAR file. The library offers support for the developer to write test cases that will check units within their application. It also provides runtime tools that will execute the test cases and output relevant test results. Background information JUnit was designed by Erich Gamma and Kent Beck, the creator of extreme programming, test driven development, and sUnit. JUnit has been important in the development of test driven development. It has been ported to other languages such as Ada(AUnit), PHP(PHPUnit), C#(NUnit), Python(PyUnit), Fortan(fUnit), Delphi(DUnit), Free Pascal(FPCUnit), Perl(Test::Class and Test::Unit), C++(CPPUnit) and JavaScript(JSUnit). 3|Page Unit testing As previously stated JUnit is a unit testing framework, by this we mean that JUnit works by taking the smallest possible part of testable software (a unit), isolating this part from the rest of the software and in turn validating that it works as it is required to work. The testing procedure uses verification and validation methods which may differ from framework to framework but will all essentially test if a specific unit is fit for use. In JUnit the testable units will be the methods within a class and the validation methods are dependent on the JUnit framework, which we will see later on. Some of the benefits gained when performing unit tests: Unit tests enable refactoring – When changes are made to the code within a unit, tests are readily available to check if the changes produce a fault. Units can be checked at all times to make sure that functionality is maintained. Unit tests allow collective ownership – The code is not owned by an individual, changes may be made by all relevant parties. This is because unit tests guard the validity of the code so that after changes are made the unit must be tested to assure that all functionality still remains. Unit tests simplify integration – Units are checked to make sure they are fully functional, reducing the chance of failures when integrating different parts of the software together. In test-driven development unit tests can verify that the implementation of software adheres to the design. If the implementation does not follow the design of a test case then it will fail the testing process. Some disadvantages of performing unit tests: Unit tests only test the functionality of the units themselves. Unit tests cannot check errors that occur on the integration level, even though most bugs found may be due to integration between 2 classes or 2 applications. Also it cannot detect broader systemlevel errors such as performance issues and memory leaks. Unit tests consume time to write and check. The developer is required to write the code for the unit tests. Although libraries and tools make this process easier it still takes time to write the tests for each unit, plus check over the code to assure that it is bug free, although buggy code may still be present. As previously mentioned JUnit is an instance of xUnit which is a family of family of unit testing frameworks. The xUnit frameworks allow the testing of units and provide an automated solution with no need to create the same tests many times and no need to remember the results each test produces. It is based on sUnit which was also developed by Kent Beck. 4|Page JUnit testing process The JUnit testing process from writing a relevant test class to obtaining the final test results is quite simple. Below we can see how this process might work. Suppose we have a class called ‘ClassA’and we wish to test units within this class, in order to do so we must create a test class with our test cases, let’s call this ‘TestClassA’. TestClassA will import the relevent classes from the JUnit library and be compiled with the JUnit framework. After this we will use the JUnit tool runner provided by the framework to run the class and check for faults. The tool runner will check if a unit fails or passes the test, it will then output the results of the test showing how and where(line number) a test has failed. The developer must then check the failure and change ClassA where appropiate. After this the test class must be run with tool runner again to ensure that the changes made have enabled functionality to the unit(s). 5|Page Writing Tests in JUnit Writing tests in JUnit has changed significantly as of JUnit 4 compared to its predecessors. JUnit has never been more easy to use or more flexible and writing a test for smaller methods can be extremely simple. In addition the JUnit library offers a variety of methods that can be used for more complex applications that require finer tuning and more attention to detail. The current release of JUnit relies on annotations for indentifying test methods as well as other methods that perform test related operations. These annotations are attached to the start of every relevant method that requires it. This differs from previous versions which required specific naming procedures of each method in order to identify the function it will perform. Due to these annotations test cases are more organized and easier to understand, developers have more freedom in naming their tests and it’s easier to implement collective ownership. So how is this put into practice? Before creating a test class it is best practice to import the relevant classes from the JUnit library that is required. For example importing ‘org.junit.Test’ or ‘org.junit.*’ enables the use of ‘@Test’ before every test method. The same applies for methods used from the JUnit library such as assertTrue, this method takes a Boolean condition and asserts if it is true or false. Here is an example JUnit test class: import org.junit.* ; import static org.junit.Assert.* ; public class SubscriptionTest { @Test public void test_returnEuro() { System.out.println("Test if pricePerMonth returns Euro...") ; Subscription S = new Subscription(200,2) ; assertTrue(S.pricePerMonth() == 1.0) ; } @Test public void test_roundUp() { System.out.println("Test if pricePerMonth rounds up correctly...") ; Subscription S = new Subscription(200,3) ; assertTrue(S.pricePerMonth() == 0.67) ; } } Obtained from: http://code.google.com/p/t2framework/wiki/JUnitQuickTutorial From this code we can see the structure of a basic JUnit test class and how both the @Test annotation and assertTrue method is put into practice. This test is used to check whether certain units within the class ‘Subscription’ function correctly and give the correct output. Apart from the JUnit specific methods and annotations the rest of the code uses normal java syntax. 6|Page A variety of other classes are available for use from the JUnit library. API documentation generated with javadoc is available for online viewing and download which include all classes and methods contained within the framework. The framework also enables the developer an easier solution to setting up fixtures. A fixture is a set of objects initialized so that two or more test cases can perform test operations on the objects. Fixtures save time, it enables us to write the code necessary to initialize and cleanup the commonly used objects only once, stops duplication. The fixtures are initialized within a method using the @Before (org.junit.Before) annotation. Instance variables must be declared prior to the set up method and the method itself must be a public void method. The @After(org.junit.After) will release any permanent resources you allocated in the set up method. Multiple @Before and @After methods are permitted. After the fixtures are set up each test methods can run the fixtures within their own isolated tests, this will mean that all changes made in the test method will not affect other tests. Tests can use variables within a fixture and invoke different methods and assert different expected results. An example of a fixture using @Before and @After methods: package junitfaq; import org.junit.*; import static org.junit.Assert.*; import java.io.*; public class OutputTest { private File output; @Before public void createOutputFile() { output = new File(...); } @After public void deleteOutputFile() { output.delete(); } } Obtained from: http://junit.sourceforge.net/doc/faq/faq.htm The features explained above are only some of the features offered in JUnit, numerous other features are available such as suite-wide initialization, testing exceptions, ignored test and timed tests. 7|Page JUnit Test Results The final part of a testing cycle is obtaining the test results. After the tool runner verifies and validates the provided test class it will output the results of each test case to the person running the test. The results will portray which results failed their test case and which passed. The results are then displayed to the user either through an IDE with integrated JUnit support or through a command line terminal. The data shown will contain relevant information on each test such as the time taken, how many tests were conducted, the number of tests that passed and the number of test that failed, as well as information on each failed test. Details of a failed test case will include the method name of the test case that failed, the name of the test class, the class on which the test was conducted, and other relevant line related information including the line number that a test failed in. An example of the output from a single test case which passed: . Time: 0,005 OK (1 test) An example of the output from multiple test failures: Time: 0,015 There were 2 failures: 1) test_returnsEuro(SubscriptionTest) java.lang.AssertionError: ... at SubscriptionTest.test_returns_Euro(SubscriptionTest.java:13) ... 2) test_roundUp(SubscriptionTest) ... at SubscriptionTest.test_roundUp(SubscriptionTest.java:19) ... Tests run: 2, Failures: 2 Obtained from: http://code.google.com/p/t2framework/wiki/JUnitQuickTutorial 8|Page Final glance at JUnit JUnit has a strong standing in terms of unit testing software in the java world. It is one of the most used third party software in java and has helped to greatly improve java applications by making the code more reliable and bug-free. However we must remember that JUnit is just a tool, it relies on the programmer to develop tests that will be efficient in checking functionality, at the end of the day ‘a fool with a tool is still a fool’. Also JUnit has disadvantages in different testing areas, a major one being that it can only run tests on one JVM (Java virtual machine). As such developers are unable to test applications that require multiple JVMs such as opening a TCP Socket connection. There are also many other testing frameworks that have risen quite quickly and wish to overtake JUnit as the leading Java unit testing framework, e.g. TestNG. But I believe that JUnit will stand strong and continue to help software developers and companies create more robust and reliable software. 9|Page References JUnit Homepage - http://www.junit.org/ JUnit Starters Guide - http://junit.sourceforge.net/ JUnit API - http://junit.org/junit/javadoc/4.5/ JUnit Cookbook - http://junit.sourceforge.net/doc/cookbook/cookbook.htm JUnit FAQ - http://junit.sourceforge.net/doc/faq/faq.htm JUnitQuickTutorial by Wishnu Prasetya http://code.google.com/p/t2framework/wiki/JUnitQuickTutorial JUnit – Wikipedia - http://en.wikipedia.org/wiki/JUnit JUnit A Cooks Tour - http://junit.sourceforge.net/doc/cookstour/cookstour.htm An early look at JUnit by Elliotte Rusty Harold http://www.ibm.com/developerworks/java/library/j-junit4.html?ca=dgr-lnxw01JUnit4 Unit testing – MSDN - http://msdn.microsoft.com/enus/library/aa292197%28VS.71%29.aspx xUnit – Wikipedia - http://en.wikipedia.org/wiki/XUnit Unit Testing – Wikipedia - http://en.wikipedia.org/wiki/Unit_testing Article Kent Beck: "We thought we were just programming on an airplane” by Ed Burnette - http://blogs.zdnet.com/Burnette/?p=118 In pursuit of code quality: JUnit 4 vs. TestNG by Andrew Glover http://www.ibm.com/developerworks/java/library/j-cq08296/ Extreme Programming – Unit testing http://www.extremeprogramming.org/rules/unittests.html 10 | P a g e