Advanced Unit Testing for Java By Denilson Nastacio Data-Driven Unit Testing
Your Host <ul><li>Denilson Nastacio </li></ul><ul><li>14 years in software development </li></ul><ul><li>Quality Enthusias...
Introduction <ul><li>Example </li></ul><ul><li>Your guessed right, a bank account :-) </li></ul><ul><li>Conventional unit ...
Checking Account <ul><li>public   class  Account { </li></ul><ul><li>private   float  balance; </li></ul><ul><li>private  ...
Junit 3.8 <ul><li>public   void  test Valid Deposit() { </li></ul><ul><li>Account acc =  new  Account(0f , 0f); </li></ul>...
JUnit 3.8 – Pros and Cons <ul><li>Pros </li></ul><ul><li>Short learning curve </li></ul><ul><li>Trivial to write </li></ul...
JUnit 4.x – Using parameterized tests <ul><li>@RunWith (Parameterized. class ) </li></ul><ul><li>public   class  AccountTe...
JUnit 4.x – Pros and Cons <ul><li>Pros </li></ul><ul><li>Built-in separation of data and logic </li></ul><ul><li>Good inte...
TestNG <ul><li><!DOCTYPE suite SYSTEM &quot;http://testng.org/testng-1.0.dtd&quot;> </li></ul><ul><li><suite name=&quot;ba...
TestNG – Parameterized tests – Java source  <ul><li>public   class  AccountTestNgTest { </li></ul><ul><li>@Test </li></ul>...
TestNG – Pros & Cons <ul><li>Pros </li></ul><ul><li>Complete separation of data and logic; separate files </li></ul><ul><l...
DDTUnit – XML file (DDT-AccountTest.xml) <ul><li><?xml version=&quot;1.0&quot; encoding=&quot;ISO-8859-1&quot;?> </li></ul...
DDTUnit – Java source <ul><li>public   class  AccountDDTUnitTest  extends  DDTTestCase { </li></ul><ul><li>public   void  ...
DDTUnit – Pros & Cons <ul><li>Pros </li></ul><ul><li>Complete separation of data and logic; separate files </li></ul><ul><...
DDTUnit – A closer look http://www.flickr.com/photos/xfrf/2260850105/  by xfrf
DDTUnit Example: Complex object with a string constructor <ul><li>Class constructor </li></ul><ul><li>public ObjectName(St...
DDTUnit Example: Complex object with a complex constructor <ul><li>Class constructor </li></ul><ul><li>public Attribute(St...
DDTUnit Example Defining a java.util.ArrayList <ul><li>Inside DDT-<namekey>.xml file </li></ul><ul><li><obj id= “ profileL...
DDTUnit Example Array of complex objects <ul><li>Inside DDT-<namekey>.xml file </li></ul><ul><li><obj id=&quot; arrayId &q...
DDTUnit and Eclipse Snippets http://sourcepatch.blogspot.com/2009/08/ddtunit-and-eclipse-snippets.html
Other noteworthy frameworks <ul><li>JTestCase </li></ul><ul><ul><li>Similar to DDTUnit but lacks a test runner </li></ul><...
Resources <ul><li>JUnit ( http:// www.junit.org / ) </li></ul><ul><li>DDTUnit ( http://sourceforge.net/projects/ddtunit ) ...
Upcoming SlideShare
Loading in...5
×

Data-Driven Unit Testing for Java

6,212

Published on

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

Published in: Technology, News & Politics
0 Comments
3 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total Views
6,212
On Slideshare
0
From Embeds
0
Number of Embeds
11
Actions
Shares
0
Downloads
0
Comments
0
Likes
3
Embeds 0
No embeds

No notes for slide

Transcript of "Data-Driven Unit Testing for Java"

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

×