eecs 394 software project management
play

EECS 394 Software Project Management Chris Riesbeck Testing: BDD - PowerPoint PPT Presentation

EECS 394 Software Project Management Chris Riesbeck Testing: BDD and Mock Objects Thursday, May 12, 2011 Behavior Driven Development Dan North evolved BDD from unit style TDD http://dannorth.net/introducing-bdd/ Test method names


  1. EECS 394 Software Project Management Chris Riesbeck Testing: BDD and Mock Objects Thursday, May 12, 2011

  2. Behavior Driven Development � Dan North evolved BDD from unit style TDD � http://dannorth.net/introducing-bdd/ � Test method names better as "should" sentences � testShouldFailForMissingSurname � Really about defining desired behaviors � self-testing is a secondary aspect � Behaviors derive ultimately from user stories: � As a [user] I want [feature] so that [benefit] � User story acceptance tests (scenarios): � Given some context, When some event, then some outcomes should be true. 2 Thursday, May 12, 2011

  3. In unit testing framework public class WindowControlBehavior { @Test public void shouldCloseWindows() { // Given WindowControl control = new WindowControl("My AFrame"); AFrame frame = new AFrame(); // When control.closeWindow(); // Then assert(!frame.isShowing()); } } 3 Thursday, May 12, 2011

  4. Tools for BDD � North created JBehave (Java) then RBehave (Ruby) � RSpec (BDD for Ruby) incorporated RBehave � http://www.infoq.com/news/2007/10/RSpec- incorporates-RBehave � Then Cucumber replaced RBehave � http://upstre.am/blog/2008/08/cucumber-next- generation-rspec-story-runner/ � https://github.com/aslakhellesoy/cucumber/wiki/ � note the return of the "5 whys" halfway down � Main goal: make user acceptance tests readable, less obscured by code details 4 Thursday, May 12, 2011

  5. Cucumber � A text-based story runner � written in Ruby for RSpec � now supports Java, .Net, Flex and webapps � Write acceptance tests in plain English � Regular expression matching links text to code � http://cukes.info/ � http://railscasts.com/episodes/155-beginning-with- cucumber (15 minutes) � http://teachmetocode.com/screencasts/introduction-to- outside-in-development-with-cucumber/ (25 minutes) 5 Thursday, May 12, 2011

  6. Fitnesse � Tests as decision tables in web pages � preceded Cucumber � tests that client can read � all-in-one server with wiki-based editor � originally for Java, now many languages � http://fitnesse.org/ 6 Thursday, May 12, 2011

  7. easyb � Story verification framework for Java using the Groovy scripting language � http://www.easyb.org/ 7 Thursday, May 12, 2011

  8. Levels of testing � Unit tests � test individual modules (methods, classes) � should be numerous, fast, detailed, automated � System integration tests � test collections of communicating modules � should include all major communication paths � typically fewer and slower than unit tests � integration failures should generate new unit tests � User acceptance tests � integration tests specified and run by client � define essential functionality for entire system 8 Thursday, May 12, 2011

  9. Discussions about acceptance tests � http://blog.8thlight.com/articles/2011/4/26/10- ways-to-do-acceptance-testing-wrong � http://jamesshore.com/Blog/The-Problems-With- Acceptance-Testing.html � http://jamesshore.com/Blog/Alternatives-to- Acceptance-Testing.html 9 Thursday, May 12, 2011

  10. Unit Test Problem � Unit tests � test individual modules (methods, classes) � should be numerous, fast, detailed, automated � should not cross module boundaries � should test the unit, not other classes � How can you unit test code � that calls other code � that may be very slow, e.g., database connections � that may not exist yet 10 Thursday, May 12, 2011

  11. Unit testing we want to test Order public class OrderStateTester extends TestCase { private static String TALISKER = "Talisker"; private Warehouse warehouse = new WarehouseImpl(); but we have to create a protected void setUp() throws Exception { Warehouse object warehouse.add(TALISKER, 50); } public void testOrderIsFilledIfEnoughInWarehouse() { Order order = new Order(TALISKER, 50); modify it order.fill(warehouse); assertTrue(order.isFilled()); assertEquals(0, warehouse.getInventory(TALISKER)); } and test it public void testOrderNotFilledIfNotEnoughInWarehouse() { Order order = new Order(TALISKER, 51); order.fill(warehouse); assertFalse(order.isFilled()); assertEquals(50, warehouse.getInventory(TALISKER)); } } http://martinfowler.com/articles/mocksArentStubs.html 11 Thursday, May 12, 2011

  12. Solution: Mock objects � A mock object is � a stub that imitates an object needed by the code being tested � a "tape recorder" that can verify that the mock object was used as intended � Must have an interface for the object to be mocked � Implementing mock objects by hand can be tedious for classes with many methods � Mock libraries provide tools for making mocks in just a few steps 12 Thursday, May 12, 2011

  13. jMock 1: using Mock class public class OrderTester extends TestCase { private Warehouse warehouse = new WarehouseImpl(); ... public void testOrderIsFilledIfEnoughInWarehouse() { Order order = new Order(TALISKER, 50); order.fill(warehouse); assertTrue(order.isFilled()); assertEquals(0, warehouse.getInventory(TALISKER)); } public class OrderTester extends MockObjectTestCase { ... create a mock Warehouse public void testOrderIsFilledIfEnoughInWarehouse() { Order order = new Order(TALISKER, 50); Mock warehouseMock = new Mock(Warehouse.class); ... pass the mock to Order order.fill((Warehouse) warehouseMock.proxy()); assertTrue(order.isFilled()); warehouseMock.verify(); verify the mock's } expectations http://martinfowler.com/articles/mocksArentStubs.html 13 Thursday, May 12, 2011

  14. jMock 1: using mock() method public class OrderTester extends TestCase { private Warehouse warehouse = new WarehouseImpl(); ... public void testOrderNotFilledIfNotEnoughInWarehouse() { Order order = new Order(TALISKER, 51); order.fill(warehouse); assertFalse(order.isFilled()); assertEquals(50, warehouse.getInventory(TALISKER)); } defines mock() method public class OrderTester extends MockObjectTestCase { ... call mock() to make public void testOrderNotFilledIfNotEnoughInWarehouse() { Order order = new Order(TALISKER, 51); mocked object Mock warehouse = mock(Warehouse.class); ... order.fill((Warehouse) warehouse.proxy()); assertFalse(order.isFilled()); mocked() objects are } verified automatically when test finishes http://martinfowler.com/articles/mocksArentStubs.html 14 Thursday, May 12, 2011

  15. jMock 1: setting expectations public void testOrderIsFilledIfEnoughInWarehouse() { expectations define the Order order = new Order(TALISKER, 50); expected usage of mock Mock warehouseMock = new Mock(Warehouse.class); object in a specific test warehouseMock.expects(once()).method("hasInventory") .with(eq(TALISKER),eq(50)) .will(returnValue(true)); hasInventory(TALISKER, 50) warehouseMock.expects(once()).method("remove") should be called once, and .with(eq(TALISKER), eq(50)) will return true .after("hasInventory"); order.fill((Warehouse) warehouseMock.proxy()); remove(TALISKER, 50) warehouseMock.verify(); should be called once, after assertTrue(order.isFilled()); hasInventory() call } http://martinfowler.com/articles/mocksArentStubs.html 15 Thursday, May 12, 2011

  16. EasyMock 1: setting expectations public class OrderEasyTester extends TestCase { normal JUnit TestCase ... private MockControl warehouseControl; private Warehouse warehouseMock; public void setUp() { warehouseControl = MockControl.createControl(Warehouse.class); warehouseMock = (Warehouse) warehouseControl.getMock(); } public void testOrderIsFilledIfEnoughInWarehouse() { Order order = new Order(TALISKER, 50); record and replay approach warehouseMock.hasInventory(TALISKER, 50); to setting expectations warehouseControl.setReturnValue(true); warehouseMock.remove(TALISKER, 50); warehouseControl.replay(); compiled method calls order.fill(warehouseMock); warehouseControl.verify(); assertTrue(order.isFilled()); } http://martinfowler.com/articles/mocksArentStubs.html 16 Thursday, May 12, 2011

  17. jMock 2: generic API public class OrderTester extends MockObjectTestCase { ... with Java generics, public void testOrderIsFilledIfEnoughInWarehouse() { no Mock class, no final Order order = new Order(TALISKER, 50); typecasting final Warehouse warehouseMock = mock(Warehouse.class); checking(new Expectations() {{ Java Double-Brace final Sequence ordering = sequence("ordering"); initializer block oneOf (warehouseMock).hasInventory(TALISKER, 50); inSequence(ordering); oneOf (wareHouseMock).remove(TALISKER, 50); expectations stored inSequence(ordering); in separate }} Expectations object order.fill(warehouseMock); assertTrue(order.isFilled()); } sequences are optional and separate objects EasyMock 3.0 also has a generic API 17 Thursday, May 12, 2011

  18. Mock libraries � Ruby - list of options � http://www.ruby-toolbox.com/categories/mocking.html � PHP � SimpleTest includes a mocking API: � http://www.lastcraft.com/mock_objects_documentation.php � Mockery, usable with PHPUnit � http://blog.astrumfutura.com/2010/05/mockery-from-mock- objects-to-test-spies/ � Python � Mocker -- uses record/replay approach � http://labix.org/mocker � Fudge - modeled on jMock � http://farmdev.com/projects/fudge/ 18 Thursday, May 12, 2011

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend