Skip to main content

Notice: this Wiki will be going read only early in 2024 and edits will no longer be possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.

Jump to: navigation, search

Difference between revisions of "User:Michael.norman.oracle.com/Info on JUnit4"

(Information on JUnit4)
 
(35 intermediate revisions by one other user not shown)
Line 1: Line 1:
== Information on JUnit4 ==
+
== Introduction to JUnit4 ==
  
 
* successor to most widely used unit-testing framework for Java, JUnit3
 
* successor to most widely used unit-testing framework for Java, JUnit3
Line 8: Line 8:
 
*** 4.3 2006-11-16
 
*** 4.3 2006-11-16
 
**** 4.3.1 2007-03-28
 
**** 4.3.1 2007-03-28
*** 4.4 (current as of 071204) 2007-03-28
+
*** 4.4 (current as of 071204) 2007-07-18
* based on Java 5 annotations
+
** no longer need to extend class <tt>TestCase</tt>
+
** test-method names do not have to start with the prefix <tt>test</tt>
+
** mark your test method with a @Test annotation
+
  
<font color="#000000">'''<s><font color="#7f0055">import</font>'''<font color="#7f0055"> junit</font><font color="#7f0055">.</font><font color="#7f0055">framework</font><font color="#7f0055">.</font><font color="#7f0055">TestCase</font><font color="#7f0055"><nowiki>;</nowiki></font></s>
+
=== based on Java 5 features ===
  '''<font color="#7f0055">import</font>'''<font color="#7f0055"> org</font><font color="#7f0055">.</font><font color="#7f0055">junit</font><font color="#7f0055">.</font><font color="#7f0055">Test</font><font color="#7f0055"><nowiki>;</nowiki></font>
+
* no longer need to extend class <tt>TestCase</tt>
 +
* test-method names do not have to start with the prefix <tt>test</tt>
 +
* mark your test method with a @Test annotation
 +
* use static import's to get <tt>assert</tt> methods (instead of via inheritance)
 +
 
 +
'''<s><font color="#7f0055">import</font>''' junit.framework.TestCase;</s>
 +
  '''<font color="#7f0055">import</font>''' org.junit.Test;
 +
'''<font color="#7f0055">import static</font>''' org.junit.Assert.*;
 
   
 
   
  '''<font color="#7f0055">public</font>''' '''<font color="#7f0055">class</font>''' CalculatorTest '''<s><font color="#7f0055">extends</font>''' TestCase</s> {
+
  '''<font color="#7f0055">public class</font>''' CalculatorTest '''<s><font color="#7f0055">extends</font>''' TestCase</s> {
 
   
 
   
 
     @Test
 
     @Test
     '''<font color="#7f0055">public</font>''' '''<font color="#7f0055">void</font>''' <s>test</s>add() {  
+
     '''<font color="#7f0055">public void</font>''' <s>test</s>add() {  
 
         ....
 
         ....
 +
        '''assertEquals'''(4, calculator.add( 1, 3 ));
 
     }  
 
     }  
 
  }
 
  }
  </font>
+
 
 +
=== improved test lifecycle management ===
 +
* <tt>setUp()</tt> and <tt>tearDown()</tt> replaced with @Before and @After annotations (allows for multiple @Before/@After methods)
 +
 
 +
  '''<font color="#7f0055">public class'''</font> CalculatorTest {
 +
 +
  @Before
 +
  '''<font color="#7f0055">public void'''</font> prepareTestData() { ... }
 +
 +
  @Before
 +
  '''<font color="#7f0055">public void'''</font> setupMocks() { ... }
 +
 +
  @After
 +
  '''<font color="#7f0055">public void'''</font> cleanupTestData() { ... }
 +
}
 +
 
 +
=== improved fixture management ===
 +
JUnit3:
 +
'''<font color="#7f0055">import'''</font> junit.framework.*;
 +
'''<font color="#7f0055">import'''</font> junit.extensions.TestSetup;
 +
 +
'''<font color="#7f0055">public class'''</font> AllTestsOneTimeSetup {
 +
 +
    '''<font color="#7f0055">public static'''</font> Connection conn; // database connection
 +
 +
    '''<font color="#7f0055">public static'''</font> Test suite() {
 +
        TestSuite suite = new TestSuite();
 +
        TestSetup wrapper = new TestSetup(suite) {
 +
            protected void setUp() {
 +
                setUpDatabaseConnection();
 +
            }
 +
            protected void tearDown() {
 +
                tearDownDatabaseConnection();
 +
            }
 +
        };
 +
        return wrapper;
 +
    }
 +
 +
    '''<font color="#7f0055">public static void'''</font> setUpDatabaseConnection() {
 +
        // one-time initialization code
 +
        conn = ...;
 +
    }
 +
 +
    '''<font color="#7f0055">public static void'''</font> tearDownDatabaseConnection() {
 +
        // one-time initialization code
 +
        conn.close() ...;
 +
    }
 +
}
 +
JUnit4: multiple @BeforeClass/@AfterClass annotations
 +
'''<font color="#7f0055">import'''</font> org.junit.AfterClass;
 +
'''<font color="#7f0055">import'''</font> org.junit.BeforeClass;
 +
 +
'''<font color="#7f0055">public class'''</font> TestWithDatabaseConnection {
 +
 +
    '''<font color="#7f0055">public static'''</font> Connection conn; // database connection fixture
 +
    '''<font color="#7f0055">public static'''</font> Object foo; // another fixture
 +
 +
    @BeforeClass
 +
    '''<font color="#7f0055">public static void'''</font> setUpDatabaseConnection() {
 +
        conn = ...;
 +
    }
 +
 +
    @BeforeClass
 +
    '''<font color="#7f0055">public static void'''</font> setUpFoo() {
 +
        foo = ...;
 +
    }
 +
 +
    @AfterClass
 +
    '''<font color="#7f0055">public static void'''</font> tearDownDatabaseConnection() {
 +
        conn.close() ...;
 +
    }
 +
 +
}
 +
 
 +
=== Test Management ===
 +
* handle expected exceptions more easily
 +
* timeouts
 +
* omit tests
 +
JUnit3 style:
 +
 
 +
    '''<font color="#7f0055">public void'''</font> testDivideByZero() {
 +
        boolean worked = false;
 +
        try {
 +
            new Calculator().divide( 4, 0 );
 +
        }
 +
        catch (ArithmeticException e) {
 +
            worked = true;
 +
        }
 +
        assertTrue("did not catch expected exception ", worked);
 +
    }
 +
 
 +
JUnit4 style:
 +
 
 +
    @Test(expected=ArithmeticException.class,timeout=5000) // set timeout so that we don't wait too long
 +
    '''<font color="#7f0055">public void'''</font> divideByZero() {
 +
      new Calculator().divide( 4, 0 );
 +
    }
 +
 +
    @Ignore
 +
    '''<font color="#7f0055">public void'''</font> notQuiteReady() {
 +
      ...
 +
    }
 +
 
 +
=== Multiple Tests ===
 +
* <tt>suite()</tt> method:
 +
'''<font color="#7f0055">public class'''</font> AllTests extends TestCase {
 +
 +
    '''<font color="#7f0055">public static'''</font> Test suite() {
 +
        TestSuite suite = new TestSuite();
 +
        suite.addTestSuite(CalculatorTest.class);
 +
        suite.addTestSuite(AnotherTest.class);
 +
        return suite;
 +
    }
 +
* vs. @SuiteClasses:
 +
@RunWith(value=Suite.class)
 +
@SuiteClasses(value={CalculatorTest.class, AnotherTest.class})
 +
'''<font color="#7f0055">public class'''</font> AllTests {
 +
  ...
 +
}
 +
 
 +
=== Custom Runners ===
 +
In the previous section, we saw that the <tt>suite()</tt> was replaced with the @Suite annotation. This is an example of how JUnit4 has been designed to allow for extension and customization. The @RunWith annotation allows for custom behaviour to be implemented before, during or after each test and/or suite is run.
 +
 
 +
== Weaknesses ==
 +
* Tools integration
 +
:JUnit3 has been integrated into alot of tools (Ant, Eclipse IDE, IDEA, etc). JUnit4 is at a disadvantage because it is new. I have written a special JUnit4 runner for Ant (works in 1.6.5 and 1.7.0) but it is not standard.
 +
* Reporting
 +
:The Ant JUnit3 runner has custom behaviour that allowed the run-output to be customized, generating aesthetically pleasing HTML pages. JUnit4 does not yet have this
 +
* JDK 5 only

Latest revision as of 20:13, 10 March 2014

Introduction to JUnit4

  • successor to most widely used unit-testing framework for Java, JUnit3
  • under active development (last JUnit3 release 3.8.2 2006-03-03)
    • JUnit 4 released 2006-02-16
      • 4.1 2006-04-27
      • 4.2 2006-11-16
      • 4.3 2006-11-16
        • 4.3.1 2007-03-28
      • 4.4 (current as of 071204) 2007-07-18

based on Java 5 features

  • no longer need to extend class TestCase
  • test-method names do not have to start with the prefix test
  • mark your test method with a @Test annotation
  • use static import's to get assert methods (instead of via inheritance)
import junit.framework.TestCase;
import org.junit.Test;
import static org.junit.Assert.*;

public class CalculatorTest extends TestCase {

    @Test
    public void testadd() { 
        ....
        assertEquals(4, calculator.add( 1, 3 ));
    } 
}

improved test lifecycle management

  • setUp() and tearDown() replaced with @Before and @After annotations (allows for multiple @Before/@After methods)
public class CalculatorTest {

  @Before
  public void prepareTestData() { ... }

  @Before
  public void setupMocks() { ... }

  @After
  public void cleanupTestData() { ... }
}

improved fixture management

JUnit3:

import junit.framework.*;
import junit.extensions.TestSetup;

public class AllTestsOneTimeSetup {

   public static Connection conn; // database connection

   public static Test suite() {
       TestSuite suite = new TestSuite();
       TestSetup wrapper = new TestSetup(suite) {
           protected void setUp() {
               setUpDatabaseConnection();
           }
           protected void tearDown() {
               tearDownDatabaseConnection();
           }
       };
       return wrapper;
   }

   public static void setUpDatabaseConnection() {
       // one-time initialization code
       conn = ...;
   }

   public static void tearDownDatabaseConnection() {
       // one-time initialization code
       conn.close() ...;
   }
}

JUnit4: multiple @BeforeClass/@AfterClass annotations

import org.junit.AfterClass;
import org.junit.BeforeClass;

public class TestWithDatabaseConnection {

   public static Connection conn; // database connection fixture
   public static Object foo; // another fixture

   @BeforeClass
   public static void setUpDatabaseConnection() {
       conn = ...;
   }

   @BeforeClass
   public static void setUpFoo() {
       foo = ...;
   }

   @AfterClass
   public static void tearDownDatabaseConnection() {
       conn.close() ...;
   }

}

Test Management

  • handle expected exceptions more easily
  • timeouts
  • omit tests

JUnit3 style:

   public void testDivideByZero() {
       boolean worked = false;
       try {
           new Calculator().divide( 4, 0 );
       }
       catch (ArithmeticException e) {
           worked = true;
       }
       assertTrue("did not catch expected exception ", worked);
   }

JUnit4 style:

   @Test(expected=ArithmeticException.class,timeout=5000) // set timeout so that we don't wait too long
   public void divideByZero() {
      new Calculator().divide( 4, 0 );
   }

   @Ignore
   public void notQuiteReady() {
      ...
   }

Multiple Tests

  • suite() method:
public class AllTests extends TestCase {

   public static Test suite() {
       TestSuite suite = new TestSuite();
       suite.addTestSuite(CalculatorTest.class);
       suite.addTestSuite(AnotherTest.class);
       return suite;
   }
  • vs. @SuiteClasses:
@RunWith(value=Suite.class)
@SuiteClasses(value={CalculatorTest.class, AnotherTest.class})
public class AllTests {
 ...
}

Custom Runners

In the previous section, we saw that the suite() was replaced with the @Suite annotation. This is an example of how JUnit4 has been designed to allow for extension and customization. The @RunWith annotation allows for custom behaviour to be implemented before, during or after each test and/or suite is run.

Weaknesses

  • Tools integration
JUnit3 has been integrated into alot of tools (Ant, Eclipse IDE, IDEA, etc). JUnit4 is at a disadvantage because it is new. I have written a special JUnit4 runner for Ant (works in 1.6.5 and 1.7.0) but it is not standard.
  • Reporting
The Ant JUnit3 runner has custom behaviour that allowed the run-output to be customized, generating aesthetically pleasing HTML pages. JUnit4 does not yet have this
  • JDK 5 only

Back to the top