Notice: This Wiki is now read only and edits are no longer possible. Please see: https://gitlab.eclipse.org/eclipsefdn/helpdesk/-/wikis/Wiki-shutdown-plan for the plan.
Difference between revisions of "User:Michael.norman.oracle.com/Info on JUnit4"
(→Information on JUnit4) |
m (Jesse.Weinstein.clinicomp.com moved page /User:Michael.norman.oracle.com/Info on JUnit4 to User:Michael.norman.oracle.com/Info on JUnit4) |
||
(27 intermediate revisions by the same user not shown) | |||
Line 1: | Line 1: | ||
− | == | + | == 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 9: | Line 9: | ||
**** 4.3.1 2007-03-28 | **** 4.3.1 2007-03-28 | ||
*** 4.4 (current as of 071204) 2007-07-18 | *** 4.4 (current as of 071204) 2007-07-18 | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | + | === based on Java 5 features === | |
− | '''<font color="#7f0055">import</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 color="#7f0055">public class</font>''' CalculatorTest '''<s><font color="#7f0055">extends</font>''' TestCase</s> { |
@Test | @Test | ||
− | '''<font color="#7f0055">public | + | '''<font color="#7f0055">public void</font>''' <s>test</s>add() { |
.... | .... | ||
'''assertEquals'''(4, calculator.add( 1, 3 )); | '''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
Contents
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
- JUnit 4 released 2006-02-16
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)
importjunit.framework.TestCase; import org.junit.Test; import static org.junit.Assert.*; public class CalculatorTestextendsTestCase { @Test public voidtestadd() { .... 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