SlideShare a Scribd company logo
1 of 117
Automated Testing in Java By Franz See [email_address] http://twitter.com/franz_see
Problems? Regression Too much time Debugging Waiting for your build to finish Documentation that lies!
What is it? public class Image { public Image(String path) {...}; public MimeType getMimeType() {...}; public Dimension getDimension() {...}; } public class ImageTest extends TestCase { public void testGetMimeType() { Image jpegImage = new Image(“dummy.jpeg”); MimeType mimeType = jpegImage.getMimeType(); assertEquals(MimeType.JPEG, mimeType); } public void testGetDimension() { Image jpegImage = new Image(“dummy.jpeg”); Dimension dimension = jpegImage.getDimension(); assertEquals(new Dimension(400,600), dimension); } }
The Parts  (part1) public class ImageTest extends TestCase { public void testGetMimeType() { // setup Image jpegImage = new Image(“dummy.jpeg”);  // exercise MimeType mimeType = jpegImage.getMimeType(); // verify assertEquals(MimeType.JPEG, mimeType); } // implict teardown public void testGetDimension() { Image jpegImage = new Image(“dummy.jpeg”); Dimension dimension = jpegImage.getDimension(); assertEquals(new Dimension(400,600), dimension); } }
The Parts  (part2) public class ImageTest extends TestCase { private Image jpegImage; protected void setUp() { super.setUp(); jpegImage = new Image(”dummy.jpeg”); } protected void tearDown() { jpegImage = null; super.tearDown(); } public void testGetMimeType() { MimeType mimeType = jpegImage.getMimeType(); assertEquals(MimeType.JPEG, mimeType); } public void testGetDimension() { Dimension dimension = jpegImage.getDimension(); assertEquals(new Dimension(400,600), dimension); } }
The Parts  (part3) // name should be descriptive // i.e.  test<MethodName>[Should] // i.e.  test[Given][When][Then] public void testGetMimeType() { MimeType mimeType = jpegImage.getMimeType(); // [descriptive message,] <expected>, <actual> assertEquals(MimeType.JPEG, mimeType); }
Tips :: Creating Tests ,[object Object]
One assert per test
One test logic per test body
Do not catch exceptions unless that's what you're testing
The Goal Name File functional unit unit integration Controller Service Repository DB My Vaction Pic C:ics01.jpeg Upload should store in repo should persist  in db should  persist inputs should  serve requests
Functional Testing ,[object Object]
Regression for your application's features/ capability
Usually done by ,[object Object]
Driving the layer just below the UI  ,[object Object],[object Object]
To be easy to read / write
Unit Testing ,[object Object]
Atomic Examples public Set select(Matcher matcher) { Set matchingObjects = new HashSet(); for(Object candidate : this.source) { if(matcher.matches(candidate)) { matchingObjects.add(candidate); } } return matchingObjects; } public Person get(Long id) { Assert.notNull(id, “Should have id to retrieve a Person.”); return repo.get(id); }
Test Organization public class PersonManager { public void create(Person person) {…} public Person retrieve(Long id) {…} public void update(Person person) {…} public void delete(Long id) {...} }
Test Organization :: SUT public class Container { public Long add(Object newObject) {…} public Object get(Long id) {…} public void replace(Long id, Object replacement) {…} public void delete(Long id) {...} }
Test Organization ::  Simple Test Per Class public class ContainerTest extends TestCase { public void testAdd() {...} public void testGet() {...} public void testReplace() {...} public void testDelete() {...} }
Test Organization :: Non-Simple Test Per Class public class ContainerTest extends TestCase { public void testGivenNonFull_WhenAdd_ThenPutInContainer() {…} public void testGivenFull_WhenAdd_ThenThrowException() {...} public void testGivenKnownId_WhenGet_ThenReturnObject() {…} public void testGivenUnknownId_WhenGet_ThenNull() {...} public void testGivenKnownId_WhenReplace_ThenRemoveAndAdd() {…} public void testGivenUnknownId_WhenReplace_ThenAdd() {...} public void testGivenKnownId_WhenDelete_ThenRemove() {…} public void testGivenUnknownId_WhenDelete_ThenThrowException() {...} }
Test Organization :: Test Per Fixture public class ContainerTest extends TestSuite { public static class GivenNonFull extends TestCase { public void testWhenAdd_ThenPutInContainer() {...} } public static class GivenFull extends TestCase { public void testWhenAdd_ThenThrowException() {...} } public static class GivenKnownId extends TestCase { public void testWhenGet_ThenReturnObject() {…} public void testWhenReplace_ThenRemoveAndAdd() {…} public void testWhenDelete_ThenRemove() {…} } public static class GivenUnknownId extends TestCase { public void testWhenGet_ThenNull() {...} public void testWhenReplace_ThenAdd() {...} public void testWhenDelete_ThenThrowException() {...} } }
Test Organization :: Test Per Feature public class ContainerTest extends TestCase { public static class WhenAdd extends TestCase { public void testGivenNonFull_ThenPutInContainer() {…} public void testGivenFull_ThenThrowException() {...} } public static class WhenGet extends TestCase { public void testGivenKnownId_ThenReturnObject() {…} public void testGivenUnknownId_ThenNull() {...} } public static class WhenReplace extends TestCase { public void testGivenKnownId_ThenRemoveAndAdd() {…} public void testGivenUnknownId_ThenAdd() {...} } public static class WhenDelete extends TestCase { public void testGivenKnownId_ThenRemove() {…} public void testGivenUnknownId_ThenThrowException() {...} } }
Tip :: Fixtures ,[object Object]
What about reusing fixtures in Non-Test Per Fixture? ,[object Object]
Tip :: Fixtures  (part2) public static class WhenTake extends TestCase { public void testGivenFoodCouponWithinPromoDates_ThenRetrieveFoodGift() { Coupon givenCoupon = new CouponBuilder() .for(CouponType.Food) .within(promoDate.start,promoDate.end) .build(); Gift gift = storeOutlet.take(givenCoupon); assertEquals(Gift.Food, gift); } public void testGivenFoodCouponOutsidePromoDates_ThenRetrieveNull() { Coupon givenCoupon = new CouponBuilder() .for(CouponType.Food) .outside(promoDate.start,promoDate.end) .build(); Gift gift = storeOutlet.take(givenCoupon); assertNull(gift); } }
Isolating your unit ,[object Object]
Mocks
Stubs
Spies
Fakes
Data Flow :: Code public Entity createEntity(Long id, String name) { return new Entity(id, name); }
Data Flow :: Diagram createEntity id name Entity processing
Data Flow :: Code public Entity createEntity(Long id, String name) { Entity entity = registry.contains(id) ? registry.get(id) : new Entity(id); entity.setName(name); registry.store(entity); return entity; }
Data Flow createEntity id name Entity processing contains(..) get(..) store(..) registry
Data Flow createEntity id name Entity processing contains(..) get(..) store(..) Direct Input Indirect Input Direct Output Indirect Output Collaborator registry
Test Doubles :: Dummies  (part1) createEntity id name Entity processing contains(..) get(..) store(..) registry
Test Doubles :: Dummies  (part2) private SystemUnderTest sut; private Registry registry; protected void setUp() { super.setUp(); registry = new RegistryImpl(); sut.setRegistry(registry); } … public void testCreateEntity() { Long givenDummyId = -1L; String givenDummyName = “dummy name”; Entity entity = createEntity(givenDummyId, givenDummyName); assertEquals(“Should have set name of entity.”,  givenDummyName, entity.getName()); }
Test Doubles :: Mocks  (part1) createEntity id name Entity processing contains(..) get(..) store(..) registry
Test Doubles :: Mocks  (part2) ... protected void setUp() { super.setUp(); registry = Mockito.mock(Registry.class); sut.setRegistry(registry); } … public void testCreateEntity() { Long givenContainedId = 10L; String givenDummyName = “dummy name”; Entity containedEntity = new Entity(givenContainedId, givenDummyName); doReturn(containedEntity).when(registry).get(givenContainedId). Entity entity = createEntity(givenContainedId, givenDummyName); assertEquals(“Should retrieved contained entity.”, containedEntity, entity); verify(registry).store( containedEntity ); }
Test Doubles :: Stubs  (part1) createEntity id name Entity processing contains(..) get(..) store(..) registry
Test Doubles :: Stubs  (part2) public class RegistryStub implements Registry { private final boolean contains; private final Entity containedEntity; public Registry(boolean contains, Entity containedEntity) { this.contains = contains; this.cachedEntity = containedEntity; } public boolean contains(Long id) { return contains; } public Entity get(Long id) { return containedEntity; } public void store(Entity enitty) {} }
Test Doubles :: Stubs  (part3) ... private Entity containedEntity; ... protected void setUp() { super.setUp(); containedEntity = new Entity(); registry = new RegistryStub(true, containedEntity); sut.setRegistry(registry); } … public void testCreateEntity() { Long givenContainedId = 10L; String givenDummyName = “dummy name”; Entity entity = createEntity(givenContainedId, givenDummyName); assertSame(“Should retrieved contained entity.”, containedEntity, entity); }
Test Doubles :: Spies  (part1) createEntity id name Entity processing contains(..) get(..) store(..) registry
Test Doubles :: Spies  (part2) public class RegistrySpy implements Registry { private Entity storedEntity; public boolean contains(Long id) { return false; } public Entity get(Long id) { return null; } public void store(Entity entity) { storedEntity = entity; } public Entity getStoredEntity() { return storedEntity; } }
Test Doubles :: Spies  (part3) ... protected void setUp() { super.setUp(); registry = new RegistrySpy(); sut.setRegistry(registry); } … public void testCreateEntity() { Long givenContainedId = 10L; String givenDummyName = “dummy name”; Entity entity = createEntity(givenContainedId, givenDummyName); assertNotNull(“Should have stored entity.”, registry.getStoredEntity()); }
Test Doubles :: Fakes  (part1) createEntity id name Entity processing contains(..) get(..) store(..) registry
Test Doubles :: Fakes  (part2) public class FakeRegistry implements Registry { private final Map<Long,Entity> container; public FakeRegistry(Entity containedEntity) { store(containedEntity); } public boolean contains(Long id) { return container.containsKey(id); } public Entity get(Long id) { return container.get(id); } public void store(Entity entity) { container.put(entity.getId(), entity); } }
Test Doubles :: Fakes  (part3) ... private Entity storedEntity; ... protected void setUp() { super.setUp(); storedEntity = new Entity(10L); registry = new FakeRegistry(storedEntity); sut.setRegistry(registry); } … public void testCreateEntity() { Long givenContainedId = storedEntity.getId(); String givenDummyName = “dummy name”; Entity entity = createEntity(givenContainedId, givenDummyName); assertSame(“Should have retrieved contained entity.”,  storedEntity, entity); }
Integration Testing ,[object Object]
Filesystem
Other applications/services
Time
Etc ,[object Object]
Tip :: which test to start from ,[object Object]
When should you write tests ,[object Object]
KISS
When should you write tests ,[object Object]
Refactoring ,[object Object]
Domain ,[object Object]
Class level – results to simplest model
TicTacToe TicTacToeTest T:14  F:0  E:0  S:14
TicTacToe TicTacToeTest T: 16   F:0  E:0  S: 16 TicTacToe
TicTacToe TicTacToeTest T: 14   F:0  E:0  S: 14 TicTacToe
TicTacToe TicTacToeTest T: 16   F:0  E:0  S: 16 TicTacToe
TicTacToe TicTacToeTest T:16  F:0  E:0  S: 14 TicTacToe Compile Error
TicTacToe TicTacToeTest T:16  F: 1   E:0  S:14 TicTacToe +move(..) +getBoard() GameOverException Board MarkedPosition Mark
TicTacToe TicTacToeTest T:16  F:1  E:0  S:14 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) MarkedPosition Mark
TicTacToe TicTacToeTest T:16  F:1  E:0  S:14 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) MarkedPosition BoardTest T:1  F:1  E:0  S:0 Mark
TicTacToe TicTacToeTest T:16  F: 0   E:0  S:14 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +equals(..) +hashCode() +toString() MarkedPosition +getEffectiveColumn() +getEffectiveRow() +getMark() BoardTest T: 1   F: 0   E:0  S:0 Mark
TicTacToe TicTacToeTest T:16  F: 0   E:0  S: 12 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +equals(..) +hashCode() +toString() MarkedPosition +getEffectiveColumn() +getEffectiveRow() +getMark() BoardTest T: 1   F: 0   E:0  S:0 Compile Error IllegalMoveException Mark
TicTacToe TicTacToeTest T:16  F: 1   E:0  S:12 TicTacToe +move(..) +getBoard() GameOverException MarkedPosition +getEffectiveColumn() +getEffectiveRow() +getMark() +getPosition() BoardTest T:1  F:0  E:0  S:0 IllegalMoveException Position Mark Board +set(..) +contains(..) +equals(..) +hashCode() +toString()
TicTacToe TicTacToeTest T:16  F:1  E:0  S:12 TicTacToe +move(..) +getBoard() GameOverException MarkedPosition +getEffectiveColumn() +getEffectiveRow() +getMark() +getPosition() BoardTest T: 3   F:0  E:0  S: 2 IllegalMoveException Position Mark Board +set(..) +contains(..) +equals(..) +hashCode() +toString()
TicTacToe TicTacToeTest T:16  F:1  E:0  S:12 TicTacToe +move(..) +getBoard() GameOverException MarkedPosition +getEffectiveColumn() +getEffectiveRow() +getMark() +getPosition() BoardTest T: 3   F:0  E:0  S: 2 IllegalMoveException Position Mark Board +set(..) +contains(..) +equals(..) +hashCode() +toString()
TicTacToe TicTacToeTest T:16  F:1  E:0  S:12 TicTacToe +move(..) +getBoard() GameOverException MarkedPosition +getEffectiveColumn() +getEffectiveRow() +getMark() +getPosition() BoardTest T:3  F: 1   E:0  S: 0 IllegalMoveException Position Mark Board +set(..) +contains(..) +equals(..) +hashCode() +toString()
TicTacToe TicTacToeTest T:16  F:1  E:0  S:12 TicTacToe +move(..) +getBoard() GameOverException MarkedPosition +getEffectiveColumn() +getEffectiveRow() +getMark() +getPosition() BoardTest T:3  F:1  E:0  S:0 IllegalMoveException Position +equals(..) +hashCode() +toString() Mark Board +set(..) +contains(..) +equals(..) +hashCode() +toString()
TicTacToe TicTacToeTest T:16  F: 0   E:0  S:12 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getEffectiveColumn() +getEffectiveRow() +getMark() +getPosition() BoardTest T:3  F: 0   E:0  S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark
TicTacToe TicTacToeTest T:16  F:0  E:0  S:12 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:3  F:0  E:0  S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark
TicTacToe TicTacToeTest T: 17   F:0  E: 1   S: 11 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:3  F:0  E:0  S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark
TicTacToe TicTacToeTest T:17  F:0  E:1  S:11 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:3  F:0  E:0  S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark
TicTacToe TicTacToeTest T:17  F:0  E:1  S:11 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:3  F:0  E:0  S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Compile Error Compile Error
TicTacToe TicTacToeTest T:17  F:0  E:1  S:11 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:3  F:0  E:0  S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark
TicTacToe TicTacToeTest T:17  F:0  E:1  S:11 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T: 5   F: 1   E:0  S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark
TicTacToe TicTacToeTest T:17  F: 1   E: 15   S:11 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5  F: 0   E:0  S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark
TicTacToe TicTacToeTest T:17  F: 0   E: 0   S:11 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5  F:0  E:0  S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark
TicTacToe TicTacToeTest T: 19   F: 2   E:0  S:11 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5  F:0  E:0  S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark
TicTacToe TicTacToeTest T:19  F: 0   E:0  S:11 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5  F:0  E:0  S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark
TicTacToe TicTacToeTest T:19  F:0  E:0  S: 10 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5  F:0  E:0  S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark
TicTacToe TicTacToeTest T: 18   F:0  E:0  S:10 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5  F:0  E:0  S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark
TicTacToe TicTacToeTest T:18  F:0  E:0  S: 9 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5  F:0  E:0  S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Compile Error Compile Error
TicTacToe TicTacToeTest T:18  F: 1   E:0  S:9 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5  F:0  E:0  S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result
TicTacToe TicTacToeTest T:18  F: 0   E:0  S:9 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5  F:0  E:0  S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result
TicTacToe TicTacToeTest T:18  F:0  E:0  S: 8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5  F:0  E:0  S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Compile Error Compile Error
TicTacToe TicTacToeTest T:18  F: 1   E:0  S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5  F:0  E:0  S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result
TicTacToe TicTacToeTest T:18  F:1  E:0  S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5  F:0  E:0  S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Compile Error Compile Error
TicTacToe TicTacToeTest T:18  F: 0   E: 14   S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5  F:0  E:0  S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +areAllTheSame()
TicTacToe TicTacToeTest T:18  F:0  E:14  S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T: 6   F:0  E:0  S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Compile Error Compile Error Line +areAllTheSame()
TicTacToe TicTacToeTest T:18  F:0  E:14  S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:6  F: 1   E:0  S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +areAllTheSame()
TicTacToe TicTacToeTest T:18  F: 1   E: 0   S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:6  F:1  E:0  S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +areAllTheSame()
TicTacToe TicTacToeTest T:18  F:1  E:0  S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:6  F: 0   E:0  S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +areAllTheSame() +equals(..) +hashCode() +toString()
TicTacToe TicTacToeTest T:18  F:1  E:0  S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line + isStraight () +equals(..) +hashCode() +toString() BoardTest T:6  F:0  E:0  S:0 LineTest T:2  F:0  E:0  S:0
TicTacToe TicTacToeTest T:18  F:1  E:0  S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +equals(..) +hashCode() +toString() BoardTest T:6  F:0  E:0  S:0 LineTest T:2  F: 1   E:0  S:0
TicTacToe TicTacToeTest T:18  F:1  E:0  S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +equals(..) +hashCode() +toString() BoardTest T:6  F:0  E:0  S:0 LineTest T:2  F: 0   E:0  S:0
TicTacToe TicTacToeTest T:18  F:1  E:0  S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +equals(..) +hashCode() +toString() BoardTest T:6  F:0  E:0  S:0 LineTest T:2  F:0  E:0  S:0
TicTacToe TicTacToeTest T:18  F:1  E:0  S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +equals(..) +hashCode() +toString() BoardTest T:6  F:0  E:0  S:0 LineTest T:2  F:0  E:0  S:0 Compile Error Compile Error
TicTacToe TicTacToeTest T:18  F:1  E:0  S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:6  F:0  E:0  S:0 LineTest T:2  F:0  E:0  S:0
TicTacToe TicTacToeTest T:18  F:1  E:0  S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() + isMarkedTheSame () +equals(..) +hashCode() +toString() BoardTest T:6  F:0  E:0  S:0 LineTest T: 6   F: 3   E:0  S:0
TicTacToe TicTacToeTest T:18  F: 0   E:0  S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() + isMarkedTheSame () +equals(..) +hashCode() +toString() BoardTest T:6  F:0  E:0  S:0 LineTest T: 6   F: 0   E:0  S:0
TicTacToe TicTacToeTest T:18  F: 1   E:0  S: 7 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() + isMarkedTheSame () +equals(..) +hashCode() +toString() BoardTest T:6  F:0  E:0  S:0 LineTest T:6  F:0  E:0  S:0
TicTacToe TicTacToeTest T:18  F:1  E:0  S:7 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() + isMarkedTheSame () +equals(..) +hashCode() +toString() BoardTest T:6  F:0  E:0  S:0 LineTest T: 7   F: 1   E:0  S:0
TicTacToe TicTacToeTest T:18  F: 0   E:0  S:7 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:6  F:0  E:0  S:0 LineTest T:7  F:1  E:0  S:0
TicTacToe TicTacToeTest T:18  F:0  E:0  S:7 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:6  F:0  E:0  S:0 LineTest T:7  F: 0   E:0  S:0
TicTacToe TicTacToeTest T:18  F: 1   E: 1   S: 5 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:6  F:0  E:0  S:0 LineTest T:7  F:0  E:0  S:0
TicTacToe TicTacToeTest T:18  F:1  E:1  S:5 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:6  F:0  E:0  S:0 LineTest T: 9   F: 2   E:0  S:0
TicTacToe TicTacToeTest T:18  F:1  E:1  S:5 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:6  F:0  E:0  S:0 LineTest T:9  F:2  E:0  S:0 Compile Error Compile Error
TicTacToe TicTacToeTest T:18  F:1  E:1  S:5 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:6  F:0  E:0  S:0 LineTest T:9  F:2  E:0  S:0 NumberUtilTest T:3  F:0  E:0  S:0 Compile Error Compile Error

More Related Content

Featured

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by HubspotMarius Sescu
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTExpeed Software
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsPixeldarts
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthThinkNow
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfmarketingartwork
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024Neil Kimberley
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)contently
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024Albert Qian
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsKurio // The Social Media Age(ncy)
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Search Engine Journal
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summarySpeakerHub
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next Tessa Mero
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentLily Ray
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best PracticesVit Horky
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project managementMindGenius
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...RachelPearson36
 

Featured (20)

2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot2024 State of Marketing Report – by Hubspot
2024 State of Marketing Report – by Hubspot
 
Everything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPTEverything You Need To Know About ChatGPT
Everything You Need To Know About ChatGPT
 
Product Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage EngineeringsProduct Design Trends in 2024 | Teenage Engineerings
Product Design Trends in 2024 | Teenage Engineerings
 
How Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental HealthHow Race, Age and Gender Shape Attitudes Towards Mental Health
How Race, Age and Gender Shape Attitudes Towards Mental Health
 
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdfAI Trends in Creative Operations 2024 by Artwork Flow.pdf
AI Trends in Creative Operations 2024 by Artwork Flow.pdf
 
Skeleton Culture Code
Skeleton Culture CodeSkeleton Culture Code
Skeleton Culture Code
 
PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024PEPSICO Presentation to CAGNY Conference Feb 2024
PEPSICO Presentation to CAGNY Conference Feb 2024
 
Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)Content Methodology: A Best Practices Report (Webinar)
Content Methodology: A Best Practices Report (Webinar)
 
How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024How to Prepare For a Successful Job Search for 2024
How to Prepare For a Successful Job Search for 2024
 
Social Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie InsightsSocial Media Marketing Trends 2024 // The Global Indie Insights
Social Media Marketing Trends 2024 // The Global Indie Insights
 
Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024Trends In Paid Search: Navigating The Digital Landscape In 2024
Trends In Paid Search: Navigating The Digital Landscape In 2024
 
5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary5 Public speaking tips from TED - Visualized summary
5 Public speaking tips from TED - Visualized summary
 
ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd ChatGPT and the Future of Work - Clark Boyd
ChatGPT and the Future of Work - Clark Boyd
 
Getting into the tech field. what next
Getting into the tech field. what next Getting into the tech field. what next
Getting into the tech field. what next
 
Google's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search IntentGoogle's Just Not That Into You: Understanding Core Updates & Search Intent
Google's Just Not That Into You: Understanding Core Updates & Search Intent
 
How to have difficult conversations
How to have difficult conversations How to have difficult conversations
How to have difficult conversations
 
Introduction to Data Science
Introduction to Data ScienceIntroduction to Data Science
Introduction to Data Science
 
Time Management & Productivity - Best Practices
Time Management & Productivity -  Best PracticesTime Management & Productivity -  Best Practices
Time Management & Productivity - Best Practices
 
The six step guide to practical project management
The six step guide to practical project managementThe six step guide to practical project management
The six step guide to practical project management
 
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
Beginners Guide to TikTok for Search - Rachel Pearson - We are Tilt __ Bright...
 

Automated Testing In Java

  • 1. Automated Testing in Java By Franz See [email_address] http://twitter.com/franz_see
  • 2. Problems? Regression Too much time Debugging Waiting for your build to finish Documentation that lies!
  • 3. What is it? public class Image { public Image(String path) {...}; public MimeType getMimeType() {...}; public Dimension getDimension() {...}; } public class ImageTest extends TestCase { public void testGetMimeType() { Image jpegImage = new Image(“dummy.jpeg”); MimeType mimeType = jpegImage.getMimeType(); assertEquals(MimeType.JPEG, mimeType); } public void testGetDimension() { Image jpegImage = new Image(“dummy.jpeg”); Dimension dimension = jpegImage.getDimension(); assertEquals(new Dimension(400,600), dimension); } }
  • 4. The Parts (part1) public class ImageTest extends TestCase { public void testGetMimeType() { // setup Image jpegImage = new Image(“dummy.jpeg”); // exercise MimeType mimeType = jpegImage.getMimeType(); // verify assertEquals(MimeType.JPEG, mimeType); } // implict teardown public void testGetDimension() { Image jpegImage = new Image(“dummy.jpeg”); Dimension dimension = jpegImage.getDimension(); assertEquals(new Dimension(400,600), dimension); } }
  • 5. The Parts (part2) public class ImageTest extends TestCase { private Image jpegImage; protected void setUp() { super.setUp(); jpegImage = new Image(”dummy.jpeg”); } protected void tearDown() { jpegImage = null; super.tearDown(); } public void testGetMimeType() { MimeType mimeType = jpegImage.getMimeType(); assertEquals(MimeType.JPEG, mimeType); } public void testGetDimension() { Dimension dimension = jpegImage.getDimension(); assertEquals(new Dimension(400,600), dimension); } }
  • 6. The Parts (part3) // name should be descriptive // i.e. test<MethodName>[Should] // i.e. test[Given][When][Then] public void testGetMimeType() { MimeType mimeType = jpegImage.getMimeType(); // [descriptive message,] <expected>, <actual> assertEquals(MimeType.JPEG, mimeType); }
  • 7.
  • 9. One test logic per test body
  • 10. Do not catch exceptions unless that's what you're testing
  • 11. The Goal Name File functional unit unit integration Controller Service Repository DB My Vaction Pic C:ics01.jpeg Upload should store in repo should persist in db should persist inputs should serve requests
  • 12.
  • 13. Regression for your application's features/ capability
  • 14.
  • 15.
  • 16. To be easy to read / write
  • 17.
  • 18. Atomic Examples public Set select(Matcher matcher) { Set matchingObjects = new HashSet(); for(Object candidate : this.source) { if(matcher.matches(candidate)) { matchingObjects.add(candidate); } } return matchingObjects; } public Person get(Long id) { Assert.notNull(id, “Should have id to retrieve a Person.”); return repo.get(id); }
  • 19. Test Organization public class PersonManager { public void create(Person person) {…} public Person retrieve(Long id) {…} public void update(Person person) {…} public void delete(Long id) {...} }
  • 20. Test Organization :: SUT public class Container { public Long add(Object newObject) {…} public Object get(Long id) {…} public void replace(Long id, Object replacement) {…} public void delete(Long id) {...} }
  • 21. Test Organization :: Simple Test Per Class public class ContainerTest extends TestCase { public void testAdd() {...} public void testGet() {...} public void testReplace() {...} public void testDelete() {...} }
  • 22. Test Organization :: Non-Simple Test Per Class public class ContainerTest extends TestCase { public void testGivenNonFull_WhenAdd_ThenPutInContainer() {…} public void testGivenFull_WhenAdd_ThenThrowException() {...} public void testGivenKnownId_WhenGet_ThenReturnObject() {…} public void testGivenUnknownId_WhenGet_ThenNull() {...} public void testGivenKnownId_WhenReplace_ThenRemoveAndAdd() {…} public void testGivenUnknownId_WhenReplace_ThenAdd() {...} public void testGivenKnownId_WhenDelete_ThenRemove() {…} public void testGivenUnknownId_WhenDelete_ThenThrowException() {...} }
  • 23. Test Organization :: Test Per Fixture public class ContainerTest extends TestSuite { public static class GivenNonFull extends TestCase { public void testWhenAdd_ThenPutInContainer() {...} } public static class GivenFull extends TestCase { public void testWhenAdd_ThenThrowException() {...} } public static class GivenKnownId extends TestCase { public void testWhenGet_ThenReturnObject() {…} public void testWhenReplace_ThenRemoveAndAdd() {…} public void testWhenDelete_ThenRemove() {…} } public static class GivenUnknownId extends TestCase { public void testWhenGet_ThenNull() {...} public void testWhenReplace_ThenAdd() {...} public void testWhenDelete_ThenThrowException() {...} } }
  • 24. Test Organization :: Test Per Feature public class ContainerTest extends TestCase { public static class WhenAdd extends TestCase { public void testGivenNonFull_ThenPutInContainer() {…} public void testGivenFull_ThenThrowException() {...} } public static class WhenGet extends TestCase { public void testGivenKnownId_ThenReturnObject() {…} public void testGivenUnknownId_ThenNull() {...} } public static class WhenReplace extends TestCase { public void testGivenKnownId_ThenRemoveAndAdd() {…} public void testGivenUnknownId_ThenAdd() {...} } public static class WhenDelete extends TestCase { public void testGivenKnownId_ThenRemove() {…} public void testGivenUnknownId_ThenThrowException() {...} } }
  • 25.
  • 26.
  • 27. Tip :: Fixtures (part2) public static class WhenTake extends TestCase { public void testGivenFoodCouponWithinPromoDates_ThenRetrieveFoodGift() { Coupon givenCoupon = new CouponBuilder() .for(CouponType.Food) .within(promoDate.start,promoDate.end) .build(); Gift gift = storeOutlet.take(givenCoupon); assertEquals(Gift.Food, gift); } public void testGivenFoodCouponOutsidePromoDates_ThenRetrieveNull() { Coupon givenCoupon = new CouponBuilder() .for(CouponType.Food) .outside(promoDate.start,promoDate.end) .build(); Gift gift = storeOutlet.take(givenCoupon); assertNull(gift); } }
  • 28.
  • 29. Mocks
  • 30. Stubs
  • 31. Spies
  • 32. Fakes
  • 33. Data Flow :: Code public Entity createEntity(Long id, String name) { return new Entity(id, name); }
  • 34. Data Flow :: Diagram createEntity id name Entity processing
  • 35. Data Flow :: Code public Entity createEntity(Long id, String name) { Entity entity = registry.contains(id) ? registry.get(id) : new Entity(id); entity.setName(name); registry.store(entity); return entity; }
  • 36. Data Flow createEntity id name Entity processing contains(..) get(..) store(..) registry
  • 37. Data Flow createEntity id name Entity processing contains(..) get(..) store(..) Direct Input Indirect Input Direct Output Indirect Output Collaborator registry
  • 38. Test Doubles :: Dummies (part1) createEntity id name Entity processing contains(..) get(..) store(..) registry
  • 39. Test Doubles :: Dummies (part2) private SystemUnderTest sut; private Registry registry; protected void setUp() { super.setUp(); registry = new RegistryImpl(); sut.setRegistry(registry); } … public void testCreateEntity() { Long givenDummyId = -1L; String givenDummyName = “dummy name”; Entity entity = createEntity(givenDummyId, givenDummyName); assertEquals(“Should have set name of entity.”, givenDummyName, entity.getName()); }
  • 40. Test Doubles :: Mocks (part1) createEntity id name Entity processing contains(..) get(..) store(..) registry
  • 41. Test Doubles :: Mocks (part2) ... protected void setUp() { super.setUp(); registry = Mockito.mock(Registry.class); sut.setRegistry(registry); } … public void testCreateEntity() { Long givenContainedId = 10L; String givenDummyName = “dummy name”; Entity containedEntity = new Entity(givenContainedId, givenDummyName); doReturn(containedEntity).when(registry).get(givenContainedId). Entity entity = createEntity(givenContainedId, givenDummyName); assertEquals(“Should retrieved contained entity.”, containedEntity, entity); verify(registry).store( containedEntity ); }
  • 42. Test Doubles :: Stubs (part1) createEntity id name Entity processing contains(..) get(..) store(..) registry
  • 43. Test Doubles :: Stubs (part2) public class RegistryStub implements Registry { private final boolean contains; private final Entity containedEntity; public Registry(boolean contains, Entity containedEntity) { this.contains = contains; this.cachedEntity = containedEntity; } public boolean contains(Long id) { return contains; } public Entity get(Long id) { return containedEntity; } public void store(Entity enitty) {} }
  • 44. Test Doubles :: Stubs (part3) ... private Entity containedEntity; ... protected void setUp() { super.setUp(); containedEntity = new Entity(); registry = new RegistryStub(true, containedEntity); sut.setRegistry(registry); } … public void testCreateEntity() { Long givenContainedId = 10L; String givenDummyName = “dummy name”; Entity entity = createEntity(givenContainedId, givenDummyName); assertSame(“Should retrieved contained entity.”, containedEntity, entity); }
  • 45. Test Doubles :: Spies (part1) createEntity id name Entity processing contains(..) get(..) store(..) registry
  • 46. Test Doubles :: Spies (part2) public class RegistrySpy implements Registry { private Entity storedEntity; public boolean contains(Long id) { return false; } public Entity get(Long id) { return null; } public void store(Entity entity) { storedEntity = entity; } public Entity getStoredEntity() { return storedEntity; } }
  • 47. Test Doubles :: Spies (part3) ... protected void setUp() { super.setUp(); registry = new RegistrySpy(); sut.setRegistry(registry); } … public void testCreateEntity() { Long givenContainedId = 10L; String givenDummyName = “dummy name”; Entity entity = createEntity(givenContainedId, givenDummyName); assertNotNull(“Should have stored entity.”, registry.getStoredEntity()); }
  • 48. Test Doubles :: Fakes (part1) createEntity id name Entity processing contains(..) get(..) store(..) registry
  • 49. Test Doubles :: Fakes (part2) public class FakeRegistry implements Registry { private final Map<Long,Entity> container; public FakeRegistry(Entity containedEntity) { store(containedEntity); } public boolean contains(Long id) { return container.containsKey(id); } public Entity get(Long id) { return container.get(id); } public void store(Entity entity) { container.put(entity.getId(), entity); } }
  • 50. Test Doubles :: Fakes (part3) ... private Entity storedEntity; ... protected void setUp() { super.setUp(); storedEntity = new Entity(10L); registry = new FakeRegistry(storedEntity); sut.setRegistry(registry); } … public void testCreateEntity() { Long givenContainedId = storedEntity.getId(); String givenDummyName = “dummy name”; Entity entity = createEntity(givenContainedId, givenDummyName); assertSame(“Should have retrieved contained entity.”, storedEntity, entity); }
  • 51.
  • 54. Time
  • 55.
  • 56.
  • 57.
  • 58. KISS
  • 59.
  • 60.
  • 61.
  • 62. Class level – results to simplest model
  • 64. TicTacToe TicTacToeTest T: 16 F:0 E:0 S: 16 TicTacToe
  • 65. TicTacToe TicTacToeTest T: 14 F:0 E:0 S: 14 TicTacToe
  • 66. TicTacToe TicTacToeTest T: 16 F:0 E:0 S: 16 TicTacToe
  • 67. TicTacToe TicTacToeTest T:16 F:0 E:0 S: 14 TicTacToe Compile Error
  • 68. TicTacToe TicTacToeTest T:16 F: 1 E:0 S:14 TicTacToe +move(..) +getBoard() GameOverException Board MarkedPosition Mark
  • 69. TicTacToe TicTacToeTest T:16 F:1 E:0 S:14 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) MarkedPosition Mark
  • 70. TicTacToe TicTacToeTest T:16 F:1 E:0 S:14 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) MarkedPosition BoardTest T:1 F:1 E:0 S:0 Mark
  • 71. TicTacToe TicTacToeTest T:16 F: 0 E:0 S:14 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +equals(..) +hashCode() +toString() MarkedPosition +getEffectiveColumn() +getEffectiveRow() +getMark() BoardTest T: 1 F: 0 E:0 S:0 Mark
  • 72. TicTacToe TicTacToeTest T:16 F: 0 E:0 S: 12 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +equals(..) +hashCode() +toString() MarkedPosition +getEffectiveColumn() +getEffectiveRow() +getMark() BoardTest T: 1 F: 0 E:0 S:0 Compile Error IllegalMoveException Mark
  • 73. TicTacToe TicTacToeTest T:16 F: 1 E:0 S:12 TicTacToe +move(..) +getBoard() GameOverException MarkedPosition +getEffectiveColumn() +getEffectiveRow() +getMark() +getPosition() BoardTest T:1 F:0 E:0 S:0 IllegalMoveException Position Mark Board +set(..) +contains(..) +equals(..) +hashCode() +toString()
  • 74. TicTacToe TicTacToeTest T:16 F:1 E:0 S:12 TicTacToe +move(..) +getBoard() GameOverException MarkedPosition +getEffectiveColumn() +getEffectiveRow() +getMark() +getPosition() BoardTest T: 3 F:0 E:0 S: 2 IllegalMoveException Position Mark Board +set(..) +contains(..) +equals(..) +hashCode() +toString()
  • 75. TicTacToe TicTacToeTest T:16 F:1 E:0 S:12 TicTacToe +move(..) +getBoard() GameOverException MarkedPosition +getEffectiveColumn() +getEffectiveRow() +getMark() +getPosition() BoardTest T: 3 F:0 E:0 S: 2 IllegalMoveException Position Mark Board +set(..) +contains(..) +equals(..) +hashCode() +toString()
  • 76. TicTacToe TicTacToeTest T:16 F:1 E:0 S:12 TicTacToe +move(..) +getBoard() GameOverException MarkedPosition +getEffectiveColumn() +getEffectiveRow() +getMark() +getPosition() BoardTest T:3 F: 1 E:0 S: 0 IllegalMoveException Position Mark Board +set(..) +contains(..) +equals(..) +hashCode() +toString()
  • 77. TicTacToe TicTacToeTest T:16 F:1 E:0 S:12 TicTacToe +move(..) +getBoard() GameOverException MarkedPosition +getEffectiveColumn() +getEffectiveRow() +getMark() +getPosition() BoardTest T:3 F:1 E:0 S:0 IllegalMoveException Position +equals(..) +hashCode() +toString() Mark Board +set(..) +contains(..) +equals(..) +hashCode() +toString()
  • 78. TicTacToe TicTacToeTest T:16 F: 0 E:0 S:12 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getEffectiveColumn() +getEffectiveRow() +getMark() +getPosition() BoardTest T:3 F: 0 E:0 S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark
  • 79. TicTacToe TicTacToeTest T:16 F:0 E:0 S:12 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:3 F:0 E:0 S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark
  • 80. TicTacToe TicTacToeTest T: 17 F:0 E: 1 S: 11 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:3 F:0 E:0 S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark
  • 81. TicTacToe TicTacToeTest T:17 F:0 E:1 S:11 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:3 F:0 E:0 S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark
  • 82. TicTacToe TicTacToeTest T:17 F:0 E:1 S:11 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:3 F:0 E:0 S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Compile Error Compile Error
  • 83. TicTacToe TicTacToeTest T:17 F:0 E:1 S:11 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:3 F:0 E:0 S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark
  • 84. TicTacToe TicTacToeTest T:17 F:0 E:1 S:11 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T: 5 F: 1 E:0 S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark
  • 85. TicTacToe TicTacToeTest T:17 F: 1 E: 15 S:11 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5 F: 0 E:0 S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark
  • 86. TicTacToe TicTacToeTest T:17 F: 0 E: 0 S:11 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5 F:0 E:0 S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark
  • 87. TicTacToe TicTacToeTest T: 19 F: 2 E:0 S:11 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5 F:0 E:0 S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark
  • 88. TicTacToe TicTacToeTest T:19 F: 0 E:0 S:11 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5 F:0 E:0 S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark
  • 89. TicTacToe TicTacToeTest T:19 F:0 E:0 S: 10 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5 F:0 E:0 S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark
  • 90. TicTacToe TicTacToeTest T: 18 F:0 E:0 S:10 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5 F:0 E:0 S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark
  • 91. TicTacToe TicTacToeTest T:18 F:0 E:0 S: 9 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5 F:0 E:0 S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Compile Error Compile Error
  • 92. TicTacToe TicTacToeTest T:18 F: 1 E:0 S:9 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5 F:0 E:0 S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result
  • 93. TicTacToe TicTacToeTest T:18 F: 0 E:0 S:9 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5 F:0 E:0 S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result
  • 94. TicTacToe TicTacToeTest T:18 F:0 E:0 S: 8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5 F:0 E:0 S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Compile Error Compile Error
  • 95. TicTacToe TicTacToeTest T:18 F: 1 E:0 S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5 F:0 E:0 S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result
  • 96. TicTacToe TicTacToeTest T:18 F:1 E:0 S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5 F:0 E:0 S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Compile Error Compile Error
  • 97. TicTacToe TicTacToeTest T:18 F: 0 E: 14 S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:5 F:0 E:0 S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +areAllTheSame()
  • 98. TicTacToe TicTacToeTest T:18 F:0 E:14 S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T: 6 F:0 E:0 S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Compile Error Compile Error Line +areAllTheSame()
  • 99. TicTacToe TicTacToeTest T:18 F:0 E:14 S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:6 F: 1 E:0 S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +areAllTheSame()
  • 100. TicTacToe TicTacToeTest T:18 F: 1 E: 0 S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:6 F:1 E:0 S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +areAllTheSame()
  • 101. TicTacToe TicTacToeTest T:18 F:1 E:0 S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() BoardTest T:6 F: 0 E:0 S:0 IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +areAllTheSame() +equals(..) +hashCode() +toString()
  • 102. TicTacToe TicTacToeTest T:18 F:1 E:0 S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line + isStraight () +equals(..) +hashCode() +toString() BoardTest T:6 F:0 E:0 S:0 LineTest T:2 F:0 E:0 S:0
  • 103. TicTacToe TicTacToeTest T:18 F:1 E:0 S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +equals(..) +hashCode() +toString() BoardTest T:6 F:0 E:0 S:0 LineTest T:2 F: 1 E:0 S:0
  • 104. TicTacToe TicTacToeTest T:18 F:1 E:0 S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +equals(..) +hashCode() +toString() BoardTest T:6 F:0 E:0 S:0 LineTest T:2 F: 0 E:0 S:0
  • 105. TicTacToe TicTacToeTest T:18 F:1 E:0 S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +equals(..) +hashCode() +toString() BoardTest T:6 F:0 E:0 S:0 LineTest T:2 F:0 E:0 S:0
  • 106. TicTacToe TicTacToeTest T:18 F:1 E:0 S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +equals(..) +hashCode() +toString() BoardTest T:6 F:0 E:0 S:0 LineTest T:2 F:0 E:0 S:0 Compile Error Compile Error
  • 107. TicTacToe TicTacToeTest T:18 F:1 E:0 S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:6 F:0 E:0 S:0 LineTest T:2 F:0 E:0 S:0
  • 108. TicTacToe TicTacToeTest T:18 F:1 E:0 S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() + isMarkedTheSame () +equals(..) +hashCode() +toString() BoardTest T:6 F:0 E:0 S:0 LineTest T: 6 F: 3 E:0 S:0
  • 109. TicTacToe TicTacToeTest T:18 F: 0 E:0 S:8 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() + isMarkedTheSame () +equals(..) +hashCode() +toString() BoardTest T:6 F:0 E:0 S:0 LineTest T: 6 F: 0 E:0 S:0
  • 110. TicTacToe TicTacToeTest T:18 F: 1 E:0 S: 7 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() + isMarkedTheSame () +equals(..) +hashCode() +toString() BoardTest T:6 F:0 E:0 S:0 LineTest T:6 F:0 E:0 S:0
  • 111. TicTacToe TicTacToeTest T:18 F:1 E:0 S:7 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() + isMarkedTheSame () +equals(..) +hashCode() +toString() BoardTest T:6 F:0 E:0 S:0 LineTest T: 7 F: 1 E:0 S:0
  • 112. TicTacToe TicTacToeTest T:18 F: 0 E:0 S:7 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:6 F:0 E:0 S:0 LineTest T:7 F:1 E:0 S:0
  • 113. TicTacToe TicTacToeTest T:18 F:0 E:0 S:7 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:6 F:0 E:0 S:0 LineTest T:7 F: 0 E:0 S:0
  • 114. TicTacToe TicTacToeTest T:18 F: 1 E: 1 S: 5 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:6 F:0 E:0 S:0 LineTest T:7 F:0 E:0 S:0
  • 115. TicTacToe TicTacToeTest T:18 F:1 E:1 S:5 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:6 F:0 E:0 S:0 LineTest T: 9 F: 2 E:0 S:0
  • 116. TicTacToe TicTacToeTest T:18 F:1 E:1 S:5 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:6 F:0 E:0 S:0 LineTest T:9 F:2 E:0 S:0 Compile Error Compile Error
  • 117. TicTacToe TicTacToeTest T:18 F:1 E:1 S:5 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:6 F:0 E:0 S:0 LineTest T:9 F:2 E:0 S:0 NumberUtilTest T:3 F:0 E:0 S:0 Compile Error Compile Error
  • 118. TicTacToe TicTacToeTest T:18 F:1 E:1 S:5 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:6 F:0 E:0 S:0 LineTest T:9 F:2 E:0 S:0 NumberUtilTest T:3 F:0 E:0 S:0 Compile Error Compile Error NumberUtil +getOrder(..)
  • 119. TicTacToe TicTacToeTest T:18 F:1 E:1 S:5 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:6 F:0 E:0 S:0 LineTest T:9 F:2 E:0 S:0 NumberUtilTest T:3 F:0 E:0 S:0 Compile Error Compile Error NumberUtil +getOrder(..) MarkedPositionTest T:5 F:0 E:0 S:0
  • 120. TicTacToe TicTacToeTst T:18 F: 2 E: 0 S:5 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() +compareTo(..) IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:6 F:0 E:0 S:0 LineTest T:9 F: 0 E:0 S:0 NumberUtilTest T:3 F:0 E:0 S:0 NumberUtil +getOrder(..) MarkedPositionTest T:5 F:0 E:0 S:0
  • 121. TicTacToe TicTacToeTest T:18 F: 3 E:0 S:5 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() +compareTo(..) IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:6 F:0 E:0 S:0 LineTest T:9 F:0 E:0 S:0 NumberUtilTest T:3 F:0 E:0 S:0 NumberUtil +getOrder(..) MarkedPositionTest T:5 F:0 E:0 S:0
  • 122. TicTacToe TicTacToeTest T:18 F:3 E:0 S:5 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() +compareTo(..) IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:6 F:0 E:0 S:0 LineTest T:9 F:0 E:0 S:0 NumberUtilTest T:3 F:0 E:0 S:0 NumberUtil +getOrder(..) MarkedPositionTest T:5 F:0 E:0 S:0 Compile Error Compile Error
  • 123. TicTacToe TicTacToeTest T:18 F:3 E:0 S:5 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() +compareTo(..) IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T: 7 F:0 E:0 S:0 LineTest T:9 F:0 E:0 S:0 NumberUtilTest T:3 F:0 E:0 S:0 NumberUtil +getOrder(..) MarkedPositionTest T:5 F:0 E:0 S:0 Compile Error Compile Error
  • 124. TicTacToe TicTacToeTest T:18 F: 0 E: 14 S:5 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getColumn(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() +compareTo(..) IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:7 F: 1 E:0 S:0 LineTest T:9 F:0 E:0 S:0 NumberUtilTest T:3 F:0 E:0 S:0 NumberUtil +getOrder(..) MarkedPositionTest T:5 F:0 E:0 S:0
  • 125. TicTacToe TicTacToeTest T:18 F: 2 E: 0 S:5 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getColumn(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() +compareTo(..) IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:7 F: 0 E:0 S:0 LineTest T:9 F:0 E:0 S:0 NumberUtilTest T:3 F:0 E:0 S:0 NumberUtil +getOrder(..) MarkedPositionTest T:5 F:0 E:0 S:0
  • 126. TicTacToe TicTacToeTest T:18 F:2 E:0 S:5 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getColumn(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() +compareTo(..) IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:7 F:0 E:0 S:0 LineTest T:9 F:0 E:0 S:0 NumberUtilTest T:3 F:0 E:0 S:0 NumberUtil +getOrder(..) MarkedPositionTest T:5 F:0 E:0 S:0 Compile Error Compile Error
  • 127. TicTacToe TicTacToeTest T:18 F: 0 E: 14 S:5 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getColumn(..) +getDiagonals(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() +compareTo(..) IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:7 F:0 E:0 S:0 LineTest T:9 F:0 E:0 S:0 NumberUtilTest T:3 F:0 E:0 S:0 NumberUtil +getOrder(..) MarkedPositionTest T:5 F:0 E:0 S:0
  • 128. TicTacToe TicTacToeTest T:18 F:0 E:14 S:5 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getColumn(..) +getDiagonals(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() +compareTo(..) IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T: 11 F:0 E: 4 S:0 LineTest T:9 F:0 E:0 S:0 NumberUtilTest T:3 F:0 E:0 S:0 NumberUtil +getOrder(..) MarkedPositionTest T:5 F:0 E:0 S:0
  • 129. TicTacToe TicTacToeTest T:18 F:0 E: 0 S:5 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getColumn(..) +getDiagonals(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() +compareTo(..) IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:11 F:0 E: 0 S:0 LineTest T:9 F:0 E:0 S:0 NumberUtilTest T:3 F:0 E:0 S:0 NumberUtil +getOrder(..) MarkedPositionTest T:5 F:0 E:0 S:0
  • 130. TicTacToe TicTacToeTest T:18 F:0 E:0 S:5 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getColumn(..) +getDiagonals(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() +compareTo(..) IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:11 F:0 E:0 S:0 LineTest T: 4 F:0 E:0 S:0 NumberUtilTest T:3 F:0 E:0 S:0 NumberUtil +getOrder(..) MarkedPositionTest T:5 F:0 E:0 S:0
  • 131. TicTacToe TicTacToeTest T:18 F: 1 E:0 S: 3 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getColumn(..) +getDiagonals(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() +compareTo(..) IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:11 F:0 E:0 S:0 LineTest T:4 F:0 E:0 S:0 NumberUtilTest T:3 F:0 E:0 S:0 NumberUtil +getOrder(..) MarkedPositionTest T:5 F:0 E:0 S:0
  • 132. TicTacToe TicTacToeTest T:18 F: 0 E:0 S:3 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getColumn(..) +getDiagonals(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() +compareTo(..) IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:11 F:0 E:0 S:0 LineTest T:4 F:0 E:0 S:0 NumberUtilTest T:3 F:0 E:0 S:0 NumberUtil +getOrder(..) MarkedPositionTest T:5 F:0 E:0 S:0
  • 133. TicTacToe TicTacToeTest T:18 F:0 E:0 S: 1 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getColumn(..) +getDiagonals(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() +compareTo(..) IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:11 F:0 E:0 S:0 LineTest T:4 F:0 E:0 S:0 NumberUtilTest T:3 F:0 E:0 S:0 NumberUtil +getOrder(..) MarkedPositionTest T:5 F:0 E:0 S:0
  • 134. TicTacToe TicTacToeTest T:18 F: 1 E:0 S: 0 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getColumn(..) +getDiagonals(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() +compareTo(..) IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:11 F:0 E:0 S:0 LineTest T:4 F:0 E:0 S:0 NumberUtilTest T:3 F:0 E:0 S:0 NumberUtil +getOrder(..) MarkedPositionTest T:5 F:0 E:0 S:0
  • 135. TicTacToe TicTacToeTest T:18 F: 0 E:0 S:0 TicTacToe +move(..) +getBoard() GameOverException Board +set(..) +isMarked(..) +contains(..) +getColumn(..) +getDiagonals(..) +getRow(..) +equals(..) +hashCode() +toString() MarkedPosition +getMark() +getPosition() +equals(..) +hashCode() +toString() +compareTo(..) IllegalMoveException Position +getEffectiveColumn() +getEffectiveRow() +equals(..) +hashCode() +toString() Mark Result Line +isStraight() +isMarkedTheSame() +equals(..) +hashCode() +toString() BoardTest T:11 F:0 E:0 S:0 LineTest T:4 F:0 E:0 S:0 NumberUtilTest T:3 F:0 E:0 S:0 NumberUtil +getOrder(..) MarkedPositionTest T:5 F:0 E:0 S:0
  • 137.
  • 138. Working Effectively with Legacy Code