Tuesday, October 23, 2012

What Is JUnit



What Is JUnit ?
  • It is a software testing FRAMEWORK for unit testing.
  • It is written in Java and designed to test Java applications.
  • It is an Open Source Software maintained by the JUnit.org community.

JUnit is a simple, open source framework to write and run repeatable tests. It is an instance of the xUnit architecture for unit testing frameworks. 

JUnit features include:
  • Assertions for testing expected results
  • Test fixtures for sharing common test data
  • Test runners for running tests
JUnit was originally written by Erich Gamma and Kent Beck.


JUnit Lifecycle
A JUnit 3.8 test case class contains a setUp() method, a tearDown() method and multiple testXXX() methods. When calling a test runner to run this test class, the runner will execute those methods in a specific order giving the test case class an execution life cycle like this:
setUp()
testXXX1()
tearDown()

setUp()
testXXX2()
tearDown()

setUp()
testXXX3()
tearDown()

...


Why Do You Use JUnit to Test Your Code?
  • I believe that writing more tests will make me more productive, not less productive.
  • I believe that tests should be done as soon as possible at the code unit level.
  • I believe that using JUnit makes unit testing easier and faster.


What Is JUnit TestCase?
JUnit TestCase is the base class, junit.framework.TestCase, used in JUnit 3.8 that allows you to create a test case. TestCase class is no longer supported in JUnit 4.4.
A test case defines the fixture to run multiple tests. To define a test case
  • Implement a subclass of TestCase
  • Define instance variables that store the state of the fixture
  • Initialize the fixture state by overriding setUp
  • Clean-up after a test by overriding tearDown
Each test runs in its own fixture so there can be no side effects among test runs. Here is an example:
import junit.framework.*;
// by FYICenter.com
public class MathTest extends TestCase {
    protected double fValue1;
    protected double fValue2;

    protected void setUp() {
        fValue1= 2.0;
        fValue2= 3.0;
    }
 
    public void testAdd() {
        double result= fValue1 + fValue2;
        assertTrue(result == 5.0);
    }
}



How To Compile a JUnit Test Class?
Compiling a JUnit test class is like compiling any other Java classes. The only thing you need watch out is that the JUnit JAR file must be included in the classpath. For example, to compile the test class HelloTest.java described previously, you should do this:
javac -cp junit-4.4.jar HelloTest.java

dir HelloTest.* 
   453 HelloTest.class
   183 HelloTest.java
The compilation is ok, if you see the HelloTest.class file.

How To Run a JUnit Test Class?
A JUnit test class usually contains a number of test methods. You can run all test methods in a JUnit test class with the JUnitCore runner class. For example, to run the test class HelloTest.java described previously, you should do this:
java -cp .;
junit-4.4.jar org.junit.runner.JUnitCore HelloTest

JUnit version 4.4
.
Time: 0.015

OK (1 test)
This output says that 1 tests performed and passed.

How To Write a JUnit Test Method?
  • You need to mark the method as a JUnit test method with the JUnit annotation: @org.junit.Test.
  • A JUnit test method must be a "public" method. This allows the runner class to access this method.
  • A JUnit test method must be a "void" method. The runner class does not check any return values.
  • A JUnit test should perform one JUnit assertion - calling an org.junit.Assert.assertXXX() method.
Here is a simple JUnit test method:
import org.junit.*; 
// by FYICenter.com
...
    @Test public void testHello() {
        String message = "Hello World!";
        Assert.assertEquals(12, message.length());
    }

What Is JUnit TestSuite?
JUnit TestSuite is a container class, junit.framework.TestSuite, used in JUnit 3.8 that allows you to group multiple test cases into a collection and run them together. TestSuite class is no longer supported in JUnit 4.4.
Each test runs in its own fixture so there can be no side effects among test runs. Here is an example:
import junit.framework.*;
// by FYICenter.com
public class RunTestSuite {
    public static void main(String[] a) {
        TestSuite suite = new TestSuite(MathTest.class);
 TestResult result = new TestResult();
        suite.run(result);
        System.out.println("Was it successful? "
            +result.wasSuccessful());
        System.out.println("How many tests were there? "
            +result.runCount());
    }
}


What Happens If a JUnit Test Method Is Declared as "private"?
If a JUnit test method is declared as "private", the compilation will pass ok. But the execution will fail. This is because JUnit requires that all test methods must be declared as "public". For example:
type HelloTestPrivate.java

import org.junit.Test;
import static org.junit.Assert.*;
// by FYICenter.com
public class HelloTestPrivate {
    @Test private void testHello() {
        String message = "Hello World!";
        assertEquals(12, message.length());
    }
}

javac -cp junit-4.4.jar HelloTestPrivate.java

java -cp .;junit-4.4.jar org.junit.runner.JUnitCore 
   HelloTestPrivate
JUnit version 4.4
.E
Time: 0
There was 1 failure:
1) initializationError0(HelloTestPrivate)
java.lang.Exception: Method testHello should be public
at org.junit.internal.runners.MethodValidator.validateTestMethod
at org.junit.internal.runners.MethodValidator.validateInstanceMe
at org.junit.internal.runners.MethodValidator.validateMethodsFor
at org.junit.internal.runners.JUnit4ClassRunner.validate(JUnit4C
at org.junit.internal.runners.JUnit4ClassRunner.<init>(JUn
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeC
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Del
at java.lang.reflect.Constructor.newInstance(Constructor.java:51
at org.junit.internal.requests.ClassRequest.buildRunner(ClassReq
at org.junit.internal.requests.ClassRequest.getRunner(ClassReque
at org.junit.internal.requests.ClassesRequest.getRunner(ClassesR
at org.junit.runner.JUnitCore.run(JUnitCore.java:109)
at org.junit.runner.JUnitCore.run(JUnitCore.java:100)
at org.junit.runner.JUnitCore.runMain(JUnitCore.java:81)
at org.junit.runner.JUnitCore.main(JUnitCore.java:44)

FAILURES!!!
Tests run: 1,  Failures: 1

What Happens If a JUnit Test Method Is Declared to Return "String"?
If a JUnit test method is declared to return "String", the compilation will pass ok. But the execution will fail. This is decause JUnit requires that all test methods must be declared to return "void". For example:
type HelloTestNonVoid.java

import org.junit.Test;
import static org.junit.Assert.*;
// by FYICenter.com
public class HelloTestNonVoid {
    @Test public String testHello() {
        String message = "Hello World!";
        assertEquals(12, message.length());
        return message;
    }
}

javac -cp junit-4.4.jar HelloTestNonVoid.java

java -cp .;junit-4.4.jar org.junit.runner.JUnitCore 
   HelloTestNonVoid

JUnit version 4.4
.E
Time: 0
There was 1 failure:
1) initializationError0(HelloTestNonVoid)
java.lang.Exception: Method testHello should be void
        at org.junit.internal.runners.MethodValidator.validateTe
        at org.junit.internal.runners.MethodValidator.validateIn
        at org.junit.internal.runners.MethodValidator.validateMe
        at org.junit.internal.runners.JUnit4ClassRunner.validate
        at org.junit.internal.runners.JUnit4ClassRunner.<init>(J
        at sun.reflect.NativeConstructorAccessorImpl.newInstance
        at sun.reflect.NativeConstructorAccessorImpl.newInstance
        at sun.reflect.DelegatingConstructorAccessorImpl.newInst
        at java.lang.reflect.Constructor.newInstance(Constructor
        at org.junit.internal.requests.ClassRequest.buildRunner(
        at org.junit.internal.requests.ClassRequest.getRunner(Cl
        at org.junit.internal.requests.ClassesRequest.getRunner(
        at org.junit.runner.JUnitCore.run(JUnitCore.java:109)
        at org.junit.runner.JUnitCore.run(JUnitCore.java:100)
        at org.junit.runner.JUnitCore.runMain(JUnitCore.java:81)
        at org.junit.runner.JUnitCore.main(JUnitCore.java:44)

FAILURES!!!
Tests run: 1,  Failures: 1







Assertion

Assertions are disabled by default in Sun's JVM. You can selectively enable them by class loader, package, or class by calling some new methods of the ClassLoader class, or more commonly via command-line arguments when you invoke the Java Virtual Machine. The command-line arguments aren't part of the spec, but in Sun's implementation you would use the -ea and -da options to enable and disable assertions, respectively. For example, to enable all assertions except for those in the com.astrel.util package, you would write

java -ea -da:com.astrel.util MyApp
If you then wanted to reenable assertions for the Heap class within com.astrel.util, you could write
java -ea -da:com.astrel.util \
-ea:com.astrel.util.Heap MyApp
Although the ClassLoader methods can be invoked at any time, they'll only affect classes loaded after the call. In other words, the status of a class's assertions - enabled or disabled - is determined once and for all when the class is loaded.

StatementDescription
fail(String)Let the method fail. Might be used to check that a certain part of the code is not reached. Or to have failing test before the test code is implemented.
assertTrue(true) / assertTrue(false)Will always be true / false. Can be used to predefine a test result, if the test is not yet implemented.
assertTrue([message], boolean condition)Checks that the boolean condition is true.
assertsEquals([String message], expected, actual)Tests that two values are the same. Note: for arrays the reference is checked not the content of the arrays.
assertsEquals([String message], expected, actual, tolerance)Test that float or double values match. The tolerance is the number of decimals which must be the same.
assertNull([message], object)Checks that the object is null.
assertNotNull([message], object)Checks that the object is not null.
assertSame([String], expected, actual)Checks that both variables refer to the same object.
assertNotSame([String], expected, actual)Checks that both variables refer to different objects.

No comments:

Post a Comment