• Save
Embrace Unit Testing
Upcoming SlideShare
Loading in...5
×
 

Embrace Unit Testing

on

  • 16,942 views

The presentation contains a definition and survey of the benefits of Unit Testing, and a little coding example to get the feeling of Unit Testing using JUnit, EasyMock and XMLUnit.

The presentation contains a definition and survey of the benefits of Unit Testing, and a little coding example to get the feeling of Unit Testing using JUnit, EasyMock and XMLUnit.

Statistics

Views

Total Views
16,942
Views on SlideShare
16,851
Embed Views
91

Actions

Likes
53
Downloads
0
Comments
6

16 Embeds 91

http://www.slideshare.net 29
http://ivalmiki.com 22
http://wiki.bcmoney-mobiletv.com 8
http://www.jroller.com 6
http://www.stevens.edu 5
http://www.wake.com 4
http://wiki.servercentralen.net 3
http://localhost 3
http://jroller.com 2
http://livebuzz.com.br 2
http://static.slidesharecdn.com 2
http://test.takeoverapp.com 1
https://lti-examples.heroku.com 1
http://learnweb.l3s.uni-hannover.de 1
file:// 1
http://www.docshut.com 1
More...

Accessibility

Upload Details

Uploaded via as OpenOffice

Usage Rights

CC Attribution License

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel

15 of 6 Post a comment

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
  • very nice one, can you please explain how we can achieve the same when we need to deal with complex UI (Eclipse SWT/JFACE)...
    Are you sure you want to
    Your message goes here
    Processing…
  • good ppt
    if possible
    please mail
    ksubbaraju.tm@gmail.com
    Are you sure you want to
    Your message goes here
    Processing…
  • As a management instructor I appreciate viewing the function of others. This is among the best demonstration on planning I have viewed.
    Sharika
    http://financeadded.com http://traveltreble.com
    Are you sure you want to
    Your message goes here
    Processing…
  • good ppt...appreciate if you can send it to met meera_visa@yahoo.com
    Are you sure you want to
    Your message goes here
    Processing…
  • this is very nice
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Embrace Unit Testing Embrace Unit Testing Presentation Transcript

  • JUG Roma 26 th September 2006 “ Embrace Unit Testing” Alessio Pace alessio.pace [AT] gmail.com http://www.jroller.com/page/alessiopace
  • 3 things about me..
    • Master Degree in Computer Engineering
    • Java fan
    • Just “Puccio” for the friends
  • About this presentation
    • What you will find:
      • definition and survey of the benefits of Unit Testing
        • reusing material from the Web and books (see references at the end)
      • a little coding example to get the feeling of Unit Testing using JUnit, EasyMock and XMLUnit
    • What you won't find:
      • an in-depth explanation about the internals of the above testing frameworks
      • a Test Driven example
  • Agenda
    • Introduction:
      • The programmer life without Unit Testing
      • What is and what is not Unit Testing
      • The benefits of Unit Testing
      • Bad rumours about Unit Testing, and the answers to them
    • Practical example in Java:
      • JUnit + EasyMock
      • JUnit + EasyMock + XMLUnit
  • INTRODUCTION
  • Programmer life without Unit Testing
    • Write a lot of code...and someday something doesn't work / stops working
    • Just fixing a bug is easy, but finding it can be a nightmare:
      • hours in front of the debugger
      • interact like a monkey with the browser or reading the output on console
    • Fixing it could break other parts
    • The bug could appear again later
  • What is Unit Testing
    • A unit test is an automated and self-checked procedure used to validate that a particular module of source code works correctly
      • a module: a single Java class
    • The procedure is to write tests for all the methods or functions of the module
    • The class under test should be tested in isolation
  • “A set of Unit Testing rules”
    • A test is not a unit test if:
      • It talks to the database
      • It communicates across the network
      • It touches the file system
      • It can't run at the same time as any of your other unit tests
      • You have to do special things to your environment (such as editing config files) to run it
      • You are not testing a class in isolation from other concrete classes
  • The benefits of Unit Testing (1)
    • Isolate each part of the program and check that the individual parts work
    • Strict, written contract that the piece of code must satisfy
    • Allows to refactor code and make sure it still works correctly ( regression testing )
  • The benefits of Unit Testing (2)
    • Simplifies integration :
      • testing the parts of a program first and then testing their integration
    • Provides documentation :
      • clients and other developers can look at the unit tests to gain a basic understanding of the APIs and determine how to use the module to fit their needs
    • Improves code quality :
      • code that cannot be easily tested is not factored properly
  • The benefits of Unit Testing (3)
    • Separation of interface from implementation :
      • a class may have some collaborator classes, testing that class can frequently lead into testing the other classes..
      • unit test should never go outside of its own class boundary:
        • abstract an interface around the collaborator class, and implements that interface with a mock object (see later). This results in loosely coupled code, minimizing dependencies in the system
  • Bad rumours about Unit Testing
    • “ It requires time, and I am always overscheduled”
    • “ It is a waste of time: if I change my classes, I have to rewrite the tests!”
    • “ My code is rock solid, I don't need tests!”
  • Answers to the bad rumours (1/2)
    • The “I'm in hurry” issue leads to a vicious cycle:
      • more pressure you feel -> less tests you write
      • less tests you write -> less productive you are and the less stable your code becomes
      • the less productive and accurate you are -> more pressure you feel
  • Answers to the bad rumours (2/2)
    • Unit Testing speeds up your development :
      • automated and self-checked code reduces the time to manually debug your code
      • writing unit tests immediately after you code new features (or even better, before ) lets you find bugs sooner and isolated (easy to correct)
    • Unit Testing lets you refactor safely:
      • a change in code that causes a regression is immediately found
  • A short parenthesis on Refactoring
    • Refactoring , a definition:
      • “ A change made to the internal structure of software to make it easier to understand and cheaper to modify without changing its observable behaviour” (“Refactoring”, Martin Fowler)
    • Unit Testing and Refactoring go together:
      • before refactoring a section of code you better have solid tests that cover it
      • test, small change, test, small change, test, ..
  • PRACTICAL EXAMPLE
  • Let's get into a coding example!
    • A practical example showing the very basics of:
      • JUnit 4.x + EasyMock 2.2
      • JUnit 4.x + EasyMock 2.2 + XMLUnit
    • See the References at the end for more tutorials and explanations about the internals of the frameworks
  • Our example: a high level description
    • Suppose we are already given a IBookService interface, which defines a method to retrieve an IBook by its code
    • Suppose also we are already given an implementation of it: RemoteBookService
    • We want to implement and test:
      • a trivial CachedIBookService implementation, which decorates an IBookService by caching subsequent calls for the same book code value
  • Our example: UML Class Diagram We have to implement and test the CachedBookService class
  • Constructor implementation of CachedBookService public class CachedBookService implements IBookService { private IBookService remoteBookService ; public CachedBookService(IBookService bookService){ if(bookService == null){ throw new IllegalArgumentException(); } this.remoteBookService = bookService; } public IBookService getRemoteBookService() { return remoteBookService; } public IBook getBook(String code) throws NoSuchElementException { // implementation left out for the moment throw new NotImplementedException(); } } Ok, let's test the constructor
  • How to automatically test the constructor?
    • We must check that:
      • when passing a valid argument the object state after the construction is correct (the instance variable remoteBookService is set)
      • when passing a null argument an IllegalArgumentException is thrown
    • We will use a testing framework: JUnit
  • JUnit: description
    • JUnit is just a general testing framework which provides assertion methods
    • You can use it to do unit testing :
      • testing a single class in isolation, eventually using EasyMock (or other mock objects frameworks) to mock collaborators classes
    • You can use it to do integration testing :
      • testing the interactions of a class with real collaborator classes
    • Almost a de-facto standard in the Java field (but have a look also at TestNG ..)
  • Writing a JUnit 4.x test class
    • A test class is just a Java class
    • Test methods must be annotated with @Test
    • Two configuration levels:
      • before/after each test method call ( @Before / @After annotated methods)
      • before/after the test class is processed ( @BeforeClass / @AfterClass annotated methods)
    • Launch the test class from an IDE (“run as JUnit Test”) or the command line
  • Testing object state after constructor import static org.junit.Assert.*; import org.junit.Test; public class CachedBookServiceTest { @Test public void testConstructor () { // anonymous class to test in isolation CachedBookService constructor IBookService bookServiceParameter = new IBookService(){ public IBook getBook(String code) throws NoSuchElementException { return null; } }; CachedBookService cachedBookService = new CachedBookService(bookServiceParameter); assertNotNull ("Assert not null", cachedBookService.getRemoteBookService()); /* 3 identical ways to test the reference value: */ assertTrue ("Assert same reference", bookServiceParameter == cachedBookService.getRemoteBookService()); // assertSame ("Assert same reference", bookServiceParameter, cachedBookService.getRemoteBookService()); // assertEquals (“Assert same reference”, bookServiceParameter, cachedBookService.getRemoteBookService()) }
  • Testing exception is thrown // CachedBookServiceTest.java @Test(expected=IllegalArgumentException.class) public void testConstructorWithNullArg () { // should throw IllegaArgumentException with null arg new CachedBookService( null ); } }
  • Enjoy the green bar :-)
  • Now let's implement getBook() method public class CachedBookService implements IBookService { private IbookService remoteBookService; private Map<String, IBook> cache; public CachedBookService(IBookService bookService){ if(bookService == null){ throw new IllegalArgumentException(); } this.remoteBookService = bookService; this.cache = new HashMap<String, IBook>(); } public IBook getBook(String code) throws NoSuchElementException { IBook ibook = cache.get(code); if(ibook != null){ return ibook; }else{ IBook result = this.remoteBookService.getBook(code); this.cache.put(code, result); return result; } } Ok, let's test getBook()
  • How to test getBook()?
    • The class must be tested in isolation:
      • we don't want to rely on a concrete IBookService collaborator object
    • We must test the interactions of the class under test with the collaborator object:
      • first request for an IBook code must be delegated to the remoteBookService
      • following requests for the same IBook code must be served from the cache
    • We are going to use JUnit with a Mock Objects framework: EasyMock
  • What are Mock Objects?
    • Most software units do not work alone, but collaborate with other units
    • To test a unit in isolation , the collaborators must be simulated
    • Mock objects have the same interfaces of the objects they mimic
      • a mock is configured to simulate the object behaviour that it replaces
      • In contrast to a stub , a mock object also verifies whether it is used as expected
  • Why are Mocks useful?
    • Isolate bugs
    • Depend on an interface and not on an implementation (which couldn't exist yet)
    • Endo testing :
      • not just testing the output of a method, but testing the interactions of a unit with the collaborator object(s)
      • also called “interaction based testing” (as opposed to “state based testing” )
  • EasyMock 2.2
    • EasyMock 2.2, two libraries:
      • one to generate mocks for interfaces only ( easymock )
      • one to generate mocks for non-final concrete classes and interfaces ( easymock-classextension )
    • Benefits:
      • hand writing mocks is not needed
      • supports compiler check and refactoring
      • supports method return values and exceptions
      • supports checking the order and count of method calls
      • ...
  • How to get a mock object with EasyMock 2.2
    • create a Mock Object for the interface to simulate
    • record the expected behavior
    • switch the mock object to replay state
    • perform the method call to the class under test that is supposed to interact with the mock obejct
    • verify the mock has been used correctly
  • Testing getBook() - 1 st test method @Test public void testGetBook () { // (1) create the mock for the collaborating object IBookService mockBookService = EasyMock.createMock(IBookService.class); // a mock with no behaviour as return value of getBook() IBook mockBook = EasyMock.createMock(IBook.class); // (2) record the expected behaviour EasyMock.expect(mockBookService.getBook(&quot;id123&quot;)).andReturn(mockBook); // (3) switch the mock to replay state EasyMock.replay(mockBookService); CachedBookService cachedBookService = new CachedBookService(mockBookService); // (4) perform the call to the class under test which interacts with the mock IBook result = cachedBookService.getBook(&quot;id123&quot;); assertSame(“Assert same reference”, mockBook, result); // (5) verify the mock has been used as expected EasyMock.verify(mockBookService); }
  • Testing getBook() - 2 nd test method @Test public void testGetBookTwoDifferentCodes () { // (1) create the mock for the collaborating object IBookService mockBookService = EasyMock.createMock(IBookService.class); // a mock with no behaviour as return value of getBook() IBook mockBook = EasyMock.createMock(IBook.class); IBook mockBook2 = EasyMock.createMock(IBook.class); // (2) record two expected calls EasyMock.expect(mockBookService.getBook(&quot;id123&quot;)).andReturn(mockBook); EasyMock.expect(mockBookService.getBook(&quot;id456&quot;)).andReturn(mockBook2); // (3) switch the mock to replay state EasyMock.replay(mockBookService); CachedBookService cachedBookService = new CachedBookService(mockBookService); // (4) perform the call to the class under test which interacts with the mock IBook result = cachedBookService.getBook(&quot;id123&quot;); assertSame(“Assert same reference”, mockBook, result); IBook result2 = cachedBookService.getBook(&quot;id456&quot;); assertSame(“Assert same reference”, mockBook2, result2); // (5) verify the mock has been used as expected EasyMock.verify(mockBookService); }
  • Testing getBook() - 3 rd test method @Test public void testGetSameBookTwoTimes () { IBookService mockBookService = EasyMock.createMock(IBookService.class); IBook mockBook = EasyMock.createMock(IBook.class); // record only one call EasyMock.expect(mockBookService.getBook(&quot;id123&quot;)).andReturn(mockBook); EasyMock.replay(mockBookService); CachedBookService cachedBookService = new CachedBookService(mockBookService); IBook result = cachedBookService.getBook(&quot;id123&quot;); assertSame(mockBook, result); IBook secondResult = cachedBookService.getBook(&quot;id123&quot;); assertSame(result, secondResult); EasyMock.verify(mockBookService); }
  • Adding an IBookXmlSerializer
    • We are already given an IBookXmlSerializer interface to serialize an IBook to XML
    • We have to implement and test a simple IBookXmlSerializerImpl which writes an XML representation of an IBook
  • IBookXmlSerializer
  • IBookXmlSerializerImpl public class IBookXmlSerializerImpl implements IBookXmlSerializer { public String serialize(IBook book) { StringBuilder sb = new StringBuilder(&quot;&quot;); sb.append(&quot;<book>&quot;); sb.append(&quot; <code>&quot; + book.getCode() + &quot;</code>&quot;); sb.append(&quot; <title>&quot; + book.getTitle() + &quot;</title>&quot;); sb.append(&quot; <author>&quot; + book.getAuthor() + &quot;</author>&quot;); sb.append(&quot;</book>&quot;); return sb.toString(); } } Ok, let's test serialize()
  • How to test serialize()?
    • We must check that the XML output is correct
    • We must test the class in isolation:
      • we can't rely on a concrete IBook implementation (we don't have it..)
    • We are going to use JUnit, EasyMock and XMLUnit
  • Testing XML with XMLUnit
    • “ XMLUnit extends JUnit to simplify unit testing of XML”
    • “ It compares a control XML document to a test document or the result of a transformation, validates documents against a DTD, and compares the results of XPath expressions”
  • IbookXmlSerializerTest - Part 1 import org.custommonkey.xmlunit.XMLTestCase; public class IBookXmlSerializerImplTest { private IBookXmlSerializer serializer; private IBook book; private XMLTestCase xmlTestCase; @Before public void setUp() throws Exception { this.serializer = new IBookXmlSerializerImpl(); this.book = EasyMock.createMock(IBook.class); this.xmlTestCase = new XMLTestCase(); } // .... The method annotated with @Before is executed before every @Test method execution
  • IbookXmlSerializerTest - Part 2 @Test public void testSerialize() throws Exception { final String code = &quot;id1&quot;; EasyMock.expect(this.book.getCode()).andReturn(code); final String title = &quot;Unit Testing&quot;; EasyMock.expect(this.book.getTitle()).andReturn(title); final String author = &quot;Mario Rossi&quot;; EasyMock.expect(this.book.getAuthor()).andReturn(author); // switch to replay state EasyMock.replay(this.book); String xml = this.serializer.serialize(book); this.xmlTestCase.assertXpathExists(&quot;/book&quot;, xml); this.xmlTestCase.assertXpathEvaluatesTo(code, &quot;/book/code&quot;, xml); this.xmlTestCase.assertXpathEvaluatesTo(title, &quot;/book/title&quot;, xml); this.xmlTestCase.assertXpathEvaluatesTo(author, &quot;/book/author&quot;, xml); // verify mock EasyMock.verify(this.book); }
  • If you appreciated Unit Testing...
    • ...you will want to try also:
      • Test Driven Development (TDD)
      • Continous Integration
      • Test Coverage tools
      • ..
  • Test coverage with Cobertura
      • Open discussion
  • Some references 1/2
    • Wikipedia:
      • http://en.wikipedia.org/wiki/Unit_testing
      • http://en.wikipedia.org/wiki/Mock_object
    • “ A Set of Unit Testing Rules” by Michael Feathers:
      • http://www.artima.com/weblogs/viewpost.jsp?thread=126923
    • “ Extreme Programing Explained / Installed” by Kent Beck / Ron Jeffries
    • “ Refactoring” by Martin Fowler
    • “ JUnit Test Infected: Programmers Love Writing Tests”:
      • http://junit.sourceforge.net/doc/testinfected/testing.htm
    • JUnit 4.x Cookbok:
      • http://junit.sourceforge.net/doc/cookbook/cookbook.htm
  • Some references 2/2
    • “ Endo-Testing: Unit Testing with Mock Objects”:
      • www.connextra.com/aboutUs/mockobjects.pdf
    • EasyMock 2.2 Documentation:
      • http://easymock.org/EasyMock2_2_Documentation.html
      • http://easymock.org/EasyMock2_2_ClassExtension _Documentation.html
    • “ Partial Mocks with EasyMock”:
      • http://www.jroller.com/page/alessiopace?entry=partial_mocks_with_easymock
    • “ Making more objects mockable with ASM Definalizer”
      • http://sixlegs.com/blog/java/definalizer.html
    • XMLUnit:
      • http://xmlunit.sourceforge.net/