• Save
Data-Driven Unit Testing for Java
Upcoming SlideShare
Loading in...5
×
 

Data-Driven Unit Testing for Java

on

  • 7,452 views

An overview of the mainstream data-driven test frameworks for Java, including pros/cons and code samples.

An overview of the mainstream data-driven test frameworks for Java, including pros/cons and code samples.

Statistics

Views

Total Views
7,452
Views on SlideShare
7,364
Embed Views
88

Actions

Likes
3
Downloads
0
Comments
0

15 Embeds 88

http://sourcepatch.blogspot.com 34
http://www.slideshare.net 28
http://sourcepatch.blogspot.in 6
https://www.calgbapps.org 4
http://sourcepatch.blogspot.jp 3
http://sourcepatch.blogspot.com.br 2
http://www.linkedin.com 2
http://sourcepatch.blogspot.de 2
http://sourcepatch.blogspot.se 1
http://webcache.googleusercontent.com 1
http://sourcepatch.blogspot.fr 1
http://sourcepatch.blogspot.hu 1
http://sourcepatch.blogspot.it 1
http://feeds.feedburner.com 1
https://www.linkedin.com 1
More...

Accessibility

Upload Details

Uploaded via as OpenOffice

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Data-Driven Unit Testing for Java Data-Driven Unit Testing for Java Presentation Transcript

  • Advanced Unit Testing for Java By Denilson Nastacio Data-Driven Unit Testing
  • Your Host
    • Denilson Nastacio
    • 14 years in software development
    • Quality Enthusiast
    • Rational Unified Process practitioner
    • RTP Scrolls ( http://rtpscrolls.blogspot.com )
    • SourcePatch ( http://sourcepatch.blogspot.com )
    • LinkedIn ( http://www.linkedin.com/in/nastacio )
  • Introduction
    • Example
    • Your guessed right, a bank account :-)
    • Conventional unit testing
    • Adequate…sometimes
    • When coverage is not everything
    • Multiple combinations of input values
    • Multiple internal states
    • Complex behavior
    • The Contenders
    • JUnit 3.8
    • JUnit 4.x
    • TestNG
    • DDTUnit
  • Checking Account
    • public class Account {
    • private float balance;
    • private float lineOfCredit;
    • public Account( float balance, float lineOfCredit) {
    • super ();
    • this .balance = balance;
    • this .lineOfCredit = lineOfCredit;
    • }
    • public void deposit( float value) {
    • if (value < = 0) {
    • throw new IllegalArgumentException( “ Deposit value (“ + value + “) is not grater than 0 &quot; );
    • }
    • balance += value;
    • }
    • public float getBalance() {
    • return balance;
    • }
  • Junit 3.8
    • public void test Valid Deposit() {
    • Account acc = new Account(0f , 0f);
    • acc.deposit(50f);
    • assertEquals (50f, acc.getBalance(), 0f);
    • }
    • public void test Zero Deposit() {
    • Account acc = new Account(0f , 0f);
    • try {
    • acc.deposit(0f);
    • fail( &quot;Deposit should fail&quot; );
    • } catch (IllegalArgumentException e) {
    • // expected
    • }
    • }
    • public void test Negative Deposit() {
    • Account acc = new Account(0f , 0f);
    • try {
    • acc.deposit(-50f);
    • fail( &quot;Deposit should fail&quot; );
    • } catch (IllegalArgumentException e) {
    • // expected
    • }
    • }
  • JUnit 3.8 – Pros and Cons
    • Pros
    • Short learning curve
    • Trivial to write
    • Cons
    • Tedious to write
    • Long files
    • Input data mixed with source code: difficult to glean all input combinations
  • JUnit 4.x – Using parameterized tests
    • @RunWith (Parameterized. class )
    • public class AccountTest extends TestCase {
    • private float lineOfCredit;
    • private float deposit;
    • private Object result;
    • @Parameters
    • public static Collection data() {
    • return Arrays. asList ( new Object[][] {
    • { 0f, 50f, 50f },
    • { 0f, 0f, new IllegalArgumentException() },
    • { 0f, -5 0f, new IllegalArgumentException() } });
    • }
    • public AccountTest( float lineOfCredit, float deposit,
    • Object result) {
    • this .lineOfCredit = lineOfCredit;
    • this .deposit = deposit;
    • this .result = result;
    • }
    • @Test
    • public void deposit() {
    • Account acc = new Account(0.0f, lineOfCredit);
    • boolean expectError = false ;
    • if (result instanceof IllegalArgumentException) {
    • expectError = true ;
    • }
    • try {
    • acc.deposit(deposit);
    • if (expectError) {
    • fail( &quot;Deposit should fail&quot; );
    • } else {
    • assertEquals(acc.getBalance(),
    • ((Float) result).floatValue(), 0f);
    • }
    • } catch (IllegalArgumentException e) {
    • if (!expectError) {
    • throw e;
    • }
    • }
    • }
  • JUnit 4.x – Pros and Cons
    • Pros
    • Built-in separation of data and logic
    • Good integration with Eclipse
    • Cons
    • One class per collection of input parameters
    • Difficult to handle collections of input parameters for verification of successful runs versus exception handling.
    • No labels for parameter sets
  • TestNG
    • <!DOCTYPE suite SYSTEM &quot;http://testng.org/testng-1.0.dtd&quot;>
    • <suite name=&quot;banking-test&quot;>
    • <test name=&quot;testValidDeposit&quot;>
    • <parameter name=&quot;lineOfCredit&quot; value=&quot;0f&quot;/>
    • <parameter name=&quot;deposit&quot; value=&quot;50f&quot;/>
    • <parameter name=&quot;result&quot; value=&quot;50f&quot;/>
    • <classes>
    • <class name=&quot; com.ibm.qse.banking.AccountTestNgTest &quot;>
    • <methods>
    • <include name=&quot; testDeposit &quot;/>
    • </methods>
    • </class>
    • </classes>
    • </test>
    • <test name=&quot;testZeroDeposit&quot;>
    • <parameter name=&quot;lineOfCredit&quot; value=&quot;0f&quot;/>
    • <parameter name=&quot;deposit&quot; value=&quot;0f&quot;/>
    • <parameter name=&quot;result&quot; value=&quot;IllegalArgumentException&quot;/>
    • <classes>
    • <class name=&quot; com.ibm.qse.banking.AccountTestNgTest &quot;>
    • ...
    • </class>
    • </classes>
    • </test>
    • <test name=&quot;testNegativeDeposit&quot;>
    • <parameter name=&quot;lineOfCredit&quot; value=&quot;0f&quot;/>
    • <parameter name=&quot;deposit&quot; value=&quot;-50f&quot;/>
    • <parameter name=&quot;result&quot; value=&quot;IllegalArgumentException&quot;/>
    • <classes>
    • <class name=&quot; com.ibm.qse.banking.AccountTestNgTest &quot;>
    • ...
    • </class>
    • </classes>
    • </test>
    • </suite>
    Selected methods must be specified in each “test”element
  • TestNG – Parameterized tests – Java source
    • public class AccountTestNgTest {
    • @Test
    • @Parameters( { &quot;lineOfCredit&quot;, &quot;deposit&quot;, &quot;result&quot; })
    • public void testDeposit( float lineOfCredit, float deposit, String result) {
    • Account acc = new Account(0f, lineOfCredit);
    • float expectedBalance = 0f;
    • try {
    • expectedBalance = Float. parseFloat (result);
    • acc.deposit(deposit);
    • assertEquals (expectedBalance, acc.getBalance());
    • } catch (NumberFormatException e) {
    • try {
    • acc.deposit(deposit);
    • fail ( &quot;Deposit should fail&quot; );
    • } catch (IllegalArgumentException e1) {
    • // expected
    • }
    • }
    • }
    TestNG does not support complex Java objects
  • TestNG – Pros & Cons
    • Pros
    • Complete separation of data and logic; separate files
    • Allows named parameter sets
    • Good support for grouping tests
    • Good integration with Eclipse
    • Cons
    • No support for complex Java types in the testng.xml file (that is a big one)
    • Tests in the xml file grouped by parameters instead of class-methods, must map each input sets to a method every time
    • JUnit competitor (increased learning curve)
    • Additional Eclipse plug-in required
  • DDTUnit – XML file (DDT-AccountTest.xml)
    • <?xml version=&quot;1.0&quot; encoding=&quot;ISO-8859-1&quot;?>
    • <ddtunit xmlns:xsi=&quot;http://www.w3.org/2001/XMLSchema-instance&quot;
    • xsi:noNamespaceSchemaLocation=&quot;ddtunit.xsd&quot;>
    • <cluster id=&quot; AccountTest &quot;>
    • <group id=&quot; testDeposit &quot;>
    • <test id=&quot;valid&quot;>
    • <objs>
    • <obj id= &quot;lineOfCredit&quot; type=&quot;float&quot;>50</obj>
    • <obj id= &quot;deposit&quot; type=&quot;float&quot;>50</obj>
    • </objs>
    • <asserts>
    • <assert id= &quot;balance&quot; type=&quot;float&quot; action=&quot;isEqual&quot;>50.0f</assert>
    • </asserts>
    • </test>
    • <test id=&quot;zero&quot;>
    • <objs>
    • <obj id=&quot;lineOfCredit&quot; type=&quot;float&quot;>50</obj>
    • <obj id=&quot;deposit&quot; type=&quot;float&quot;>0</obj>
    • </objs>
    • <asserts>
    • <exception id=&quot;expectedException&quot; type=&quot;java.lang.IllegalArgumentException&quot;
    • action=&quot;isSimilar&quot;>0</exception>
    • </asserts>
    • </test>
    • <test id=&quot;negative&quot;>
    • <objs>
    • <obj id=&quot;lineOfCredit&quot; type=&quot;float&quot;>50</obj>
    • <obj id=&quot;deposit&quot; type=&quot;float&quot;>-50</obj>
    • </objs>
    • <asserts>
    • <exception id=&quot;expectedException“ type=&quot;java.lang.IllegalArgumentException&quot;
    • action=&quot;isSimilar&quot;>-50</exception>
    • </asserts>
    • </test>
    • </group>
    • </cluster>
    • </ddtunit>
    Class name Method name
  • DDTUnit – Java source
    • public class AccountDDTUnitTest extends DDTTestCase {
    • public void testDeposit() {
    • float lineOfCredit = ((Float)getObject( &quot;lineOfCredit&quot; )).floatValue();
    • float deposit = ((Float)getObject( &quot;deposit&quot; )).floatValue();
    • Account acc = new Account(0f,lineOfCredit);
    • acc.deposit(deposit);
    • addObjectToAssert( &quot;balance&quot; , new Float(acc.getBalance()));
    • }
    • protected void initContext() {
    • initTestData( &quot;AccountTest&quot; );
    • }
    • }
    Inherits from junit.framework.TestCase DDTUnit definition file: DDT-AccountTest.xml
  • DDTUnit – Pros & Cons
    • Pros
    • Complete separation of data and logic; separate files
    • Allows the cleanest Java source code
    • Support for complex Java types
    • Support for verification of exceptions
    • Supports global test data
    • Based on JUnit
    • Good support for grouping tests
    • Cons
    • XML syntax can be a language on its own when dealing with complex structures
    • Poor integration with Eclipse, programmer must rely on console outputs as well
  • DDTUnit – A closer look http://www.flickr.com/photos/xfrf/2260850105/ by xfrf
  • DDTUnit Example: Complex object with a string constructor
    • Class constructor
    • public ObjectName(String name) { ... }
    • Inside DDT-<namekey>.xml file
    • <obj id=&quot; jmxId &quot; type=&quot;javax.management.ObjectName&quot;>
    • <item>WebSphere:type=cellManager</item>
    • </obj>
    • Inside TestCase java file
    • javax.management.ObjectName jmxId =
    • (javax.management.ObjectName)getObject(&quot; jmxId &quot; );
  • DDTUnit Example: Complex object with a complex constructor
    • Class constructor
    • public Attribute(String name, String value) {... }
    • Inside DDT-<namekey>.xml file
    • < obj id= &quot; jmxAttr &quot; type=&quot;javax.management.Attribute&quot; hint=&quot;call&quot;
    • method=&quot;constructor&quot;>
    • <item type=&quot;string&quot;>fileName</item>
    • <item type=&quot;string&quot;> directory< /item>
    • </item>
    • Inside TestCase java file
    • javax.management. Attribute jmxId =
    • (javax.management. Attribute )getObject(&quot; jmxAttr &quot; );
  • DDTUnit Example Defining a java.util.ArrayList
    • Inside DDT-<namekey>.xml file
    • <obj id= “ profileLocations &quot; type=&quot;java.util. ArrayList &quot; hint=&quot;collection&quot; valuetype=&quot;string&quot;>
    • <item>/opt/IBM/WebSphere/AppServer/profiles/s1</item>
    • <item>/opt/IBM/WebSphere/AppServer/profiles/s 2 </item>
    • <item>/opt/IBM/WebSphere/AppServer/profiles/s 3 </item>
    • </obj>
    • Inside TestCase java file
    • ArrayList <String> profileLocations =
    • ( ArrayList <String>)getObject(&quot; profileLocations &quot; );
  • DDTUnit Example Array of complex objects
    • Inside DDT-<namekey>.xml file
    • <obj id=&quot; arrayId &quot; type=“ java.util .A rray List&quot; hint=&quot;collection&quot;>
    • <item type=&quot;javax.management.Attribute&quot; hint=&quot;call&quot; method=&quot;constructor&quot;>
    • <item type=&quot;string&quot;>fileName</item>
    • <item type=&quot;string&quot;>${SERVER_ROOT}/trace.log</item>
    • </item>
    • </obj>
    • Inside TestCase java file
    • ArrayList<Attribute > profileLocations =
    • ( ArrayList < Attribute >)getObject(&quot; arrayId &quot; );
  • DDTUnit and Eclipse Snippets http://sourcepatch.blogspot.com/2009/08/ddtunit-and-eclipse-snippets.html
  • Other noteworthy frameworks
    • JTestCase
      • Similar to DDTUnit but lacks a test runner
      • Requires testcase to extract data from XML file and pass it to fixtures
    • Fit
      • High-level data definition using MS-Word and MS-Excel
      • Inadequate for unit testing, support for strings and basic numeric types
    • Jetif
      • Full replacement for JUnit + JTestCase
      • Lost me on “full replacement”
  • Resources
    • JUnit ( http:// www.junit.org / )
    • DDTUnit ( http://sourceforge.net/projects/ddtunit )
    • TestNG ( http://testng.org/doc/ )
    • JTestCase ( http://jtestcase.sourceforge.net/ )
    • Jetif ( http:// jetif.sourceforge.net )
    • FIT ( http://fit.c2.com/ )
    • My del.icio.us bookmarks for this presentation (tag: qse-ddt)
      • http://delicious.com/nastacio/qse-ddt