unit testing, integration testing tdd (test driven...

171
. Unit testing, Integration testing TDD (Test Driven Development) Mocking by Micael Andersson

Upload: others

Post on 21-Jun-2020

10 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

.

Unittesting,IntegrationtestingTDD(TestDrivenDevelopment)

Mocking

byMicaelAndersson

Page 2: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Goals of todays presentation• Automated Testing Theory (Brief overview)

– To introduce and motivate Automated Tests – To describe how Automated Testing fits within a Software Development

Process – To provide a classification of Automated Testing Strategies and Tools

• Unit Testing (Brief overview) – Provide theoretical background for Unit Testing – Hands-on experience with Unit Testing tools and frameworks

• TDD - Test Driven Development (Agile development) – Process, In Practice, Benefits

2

Page 3: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Goals of next presentation

• Integration Testing (Brief overview) – Provide theoretical background for and overview of Integration Testing – Overview of Integration Testing tools and frameworks

• Design for testability (In deep) – Some design patterns

• Mocking (In deep and practice) – Basic principles – Hands-on experience with Mockito

3

Page 4: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Training material - Java

• These slides... • Online resources

– www.junit.org – code.google.com/p/mockito/ – www.dbunit.org – strutstestcase.sourceforge.net

– Source code to exercises

4

Page 5: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

TDDTraining

Testing and

Automated testsPresentation provided by

Combitech JidokaQ

Page 6: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

About Tests …Everybody knows they should, but few actually do

• “Why isn’t this tested before”? – Because it has been too expensive, difficult,

cumbersome to test – Because we have been too busy – Because things have changed

6

Discussion: In case the application you currently work on

lacks tests; - In your opinion; what’s the main reason for this?

Page 7: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Quality Assurance precedes Quality Assessment• Testing is about Quality Assurance, not just Quality

Assessment • Quality Assessment only indirectly affect quality • Testing reveals information • Testing helps focus project activity

7

Page 8: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Test Automation GoalsTests should be S.M.A.R.T:

• Self Checking • Maintainable • Act as documentation • Repeatable and Robust • To the point – provide ”defect

triangulation”

8

Page 9: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Manual Tests are …• Repetitive • Error-prone • Difficult to test other units than

the User Interface

• yet …

• a (Manual) Test Process must be present in order to automate it!

9

Page 10: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Critical Success Factors for Automated Tests• Repeatability and Consistency

– Once the test is complete, it should pass repeatedly, whether it executes by itself or within a test suite.

– When a completed test fails, we need to quickly and accurately pinpoint the cause: did the test uncover a bug in the system, or is the test itself faulty?

• Readability

– The tests are the definitive reference for the system requirements.

• Maintainability

– Iterative, test-first development yields as much (or more) test code than system code

– Thus we have to be as concerned (or more) with the maintenance costs of test code as compared to system code.

10

Page 11: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Testability• Testability consists of two fundamental characteristics:

• Visibility – the tester can see (and understand) what happens within the system (i.e. can observe important aspects of the internal state of the system)

• Control – the tester can force interesting things to happen within the system (i.e. can control its behavior)

• Testability doesn’t just happen. It must be designed and built into a system. Writing tests before designing and building the system (a.k.a. Test-First or Test-Driven Development) is a great way of achieving good testability.

11

Page 12: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Classifying Automated Tests• Granularity

– Entire system – Individual units

• Point of Contact– Existing User Interface – Testability API

• Test Case Production– Record & Play Back – Hand Written (programmatic)

12

API

GU

I

SystemUnit

R & PB Program

Page 13: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Test (and build) automation

13

Page 14: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

TDDTraining

Introduction to

Unit Testing with JUnit and EclipsePresentation provided by

Combitech JidokaQ

Page 15: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Unit Tests• Black-box or White-box test of a logical unit, which

verifies that the logical unit behaves correctly – honors its contract.

15

Page 16: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

What exactly is a Unit Test?• A self-contained software module (in OO languages

typically a Class) containing one or more test scenarios which tests a Unit Under Test in isolation.

• Each test scenario is autonomous, and tests a separate aspect of the Unit Under Test.

16

PlantStructureService PlantStructureDAOPlantStructureServiceTest

Data

Page 17: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Smoke Tests• A set of Unit Tests (which tests a set of logical units)

executed as a whole provides a way to perform a Smoke Test: Turn it on, and make sure that it doesn’t come smoke out of it!

• A relatively cheap way to see that the units “seems to be working and fit together”, even though there are no guarantees for its overall function (which requires functional testing)

17

Page 18: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Developer testing vs Acceptance testing• Unit Tests are written by developers, for developers.

• Unit Tests do not address formal validation and verification of correctness (even though it has indirect impact on it!) - Unit Tests prove that some code does what we intended it to do

• Unit Tests complements Acceptance Tests (it does not replace it)

18

Page 19: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Why should I (as a Developer) bother?• Well-tested code works better. Customers like it better. • Tests support refactoring. Since we want to ship useful function early

and often, we know that we'll be evolving the design with refactoring. • Tests give us confidence. We're able to work with less stress, and we're

not afraid to experiment as we go. • Hence Unit Testing will make my life easier

– It will make my design better – It will give me the confidence needed to refactor when necessary – It will dramatically reduce the time I spend with the debugger – It will make me sleep better when deadlines are closing in

19

Page 20: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Requirements on Unit Tests

• Easy to write a test class • Easy to find test classes • Easy to test different aspects of a contract • Easy to maintain tests • Easy to run tests

20

Page 21: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

XUnit: A Framework for Unit Tests

• www.junit.org • www.csunit.org • www.vbunit.org • cppunit.sourceforge.net

21

Page 22: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

JUnit Test Examplepublic interface Account { public void deposit(int amount); public void withdraw(int amount) throws AccountException; public int getBalance(); … }

public class AccountImplTest { @Test public void testWithdraw() throws AccountException { AccountImpl account = new AccountImpl(“1234-9999”, 2000); account.withdraw(300); Assert.assertEquals(1700, account.getBalance()); }

@Test public void testWithdrawTooMuch() throws AccountException { … } … }

22

Page 23: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Naming Conventions and Directory Structure

• Unit Tests should be named after the Unit that is tested, with "Test" appended.A class usually represents a noun, it is a model of a concept. An instance of one of your tests would be a 'MyUnit test'. In contrast, a method would model some kind of action, like 'test [the] calculate [method]'.

23

• the MyUnit test --> MyUnitTest • test the calculate method -->

testCalculate(); • JUnit tests should be placed

within the same Java package as the Unit under Test, but in a different directory structure.

Page 24: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Test cases and test methodsimport org.junit.Assert;import org.junit.Before;import org.junit.Test;

public class AccountImplTest { @Test public void testWithdraw() throws AccountException { AccountImpl account = new AccountImpl(“1234-9999”, 2000); account.withdraw(300); Assert.assertEquals(1700, account.getBalance()); }

@Test public void testWithdrawTooMuch() throws AccountException { … } … }

24

All methods annotated with

@Test are considered test

scenarios

Page 25: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Assert: Support for verifying conditions

static void assertEquals(int expected, int actual);           // Asserts that two ints are equal.

static void assertEquals(double expected, double actual, double delta);           // Asserts that two doubles are equal concerning a delta.

static void assertEquals(java.lang.Object expected, java.lang.Object actual);           // Asserts that two objects are equal.

static void assertFalse(java.lang.String message, boolean condition);           // Asserts that a condition is false.

static void assertTrue (java.lang.String message, boolean condition);           // Asserts that a condition is true.

static void assertNull(java.lang.String message, java.lang.Object object);           // Asserts that an object is null.

static void assertNotNull(java.lang.String message, java.lang.Object object);           // Asserts that an object isn't null.

// Etc…

25

Page 26: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Executing JUnit Tests: Test Runners

26

Page 27: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

TDDTraining

Exercise 1 (Writing unit tests to Account)

Presentation provided by Combitech JidokaQ

Page 28: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Exercise 1 descriptionSometimes you need to write Unit tests to already existing software when you want to implement a change request e.t.c. In this example we have the source code but no tests, your task is to write them.

28

Page 29: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Exercise 1

• 1 - Create an Unit test case which tests the initial balance of an Account (i e. tests the constructor and GetBalance() method of Account). @Testpublic void testInitialBalance() { … }

• 2 - Add tests for the Deposit() method of Account. @Testpublic void testDeposit() { … }

29

Page 30: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

TDDTraining

Continued introduction to

Unit Testing with JUnit and EclipsePresentation provided by

Combitech JidokaQ

Page 31: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Typical unit test scenario – The Three A’s1. Arrange - Instantiate Unit under Test and set up test data 2. Act - Execute one or more methods on the Unit Under Test 3. Assert - Verify the results

public interface Account { public void deposit(int amount); public void withdraw(int amount) throws AccountException; public int getBalance(); … }public class AccountImplTest { @Test public void testWithdraw() throws AccountException { AccountImpl account = new AccountImpl(“1234-9999”, 2000); // ARRANGE account.withdraw(300); // ACT Assert.assertEquals(1700, account.getBalance()); // ASSERT }

… … …}

31

Page 32: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

General Rules of Thumb• Create a single test class for each non-trivial application class you have. • Give a readable, meaningful name to each test method. A good name candidates

are to name the test method using the same name as the method that it is testing, with some additional info appended to the name. For instance if testing a method called "Withdraw" in an Account class, create a few test methods to test different ways of withdrawal:

@Test public void testWithdrawTooMuch() throws AccountException {…}

@Test public void withdrawBigAmount() throws AccountException {…}

@Test public void withdrawNegativeAmount() throws AccountException {…}

• The scope of how much checking to do in a single test case (test method) is a judgment call. It is usually better to test only one scenario (and hence one potential error condition) in each test method. Remember : tests should be “to the point”.

32

Page 33: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Setup and teardown

• Methods annotated with @Before are executed before every test method.

• Methods annotated with @After are executed after every test method.

33

public class AccountImplTest {

private AccountImpl account;

@Beforepublic void setUp() {

account = new AccountImpl(“1234-9999", 2000);}@Testpublic void testInitialBalance() {

int actualBalance = account.getBalance();Assert.assertEquals(2000, actualBalance);

}@Testpublic void testWithdraw() throws AccountException {

account.withdraw(300); int actualBalance = account.getBalance();

Assert.assertEquals(1700, actualBalance);}

… }

Page 34: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Working with Exceptions• Unexpected exceptions thrown during execution of a test will be caught by

the JUnit framework and reported as Errors (i.e. test will fail) • A Test method must declare that it throws any checked exceptions that the

Unit under Test may throw. If there are several checked exceptions that may occur, it is perfectly valid for a test method to declare throwing java.lang.Exception.

• Expected exceptions (exceptions that the test is expecting the Unit under Test should throw in a certain situation) are expressed using the @Test(expected=ExpectedException.class) annotation attribute

@Test(expected=NastyException.class)public void doSomethingNastyTest() {

SomeUnit target = new SomeUnit();target.doSomethingNasty();

}

34

Page 35: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Working with Exceptions (Contd.)

• Or using the following idiom:

SomeUnit target = new SomeUnit();try {

target.doSomethingNasty();Assert.fail("NastyException expected");

} catch (NastyException expected) {// Expected

}

35

Page 36: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

@Ignore

• To temporary ignore a test, use the Ignore annotation:

@Test@Ignore("Not right now, but most definitely later")public void testThatDoesNotWorkYet(){

SomeUnit target = new SomeUnit(); target.doSomethingThatDoesNotWork(); Assert.assertTrue(target.isValid());}

36

Page 37: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

TDDTraining

Exercise 2 (refactor unit tests to Account)

Presentation provided by Combitech JidokaQ

Page 38: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Exercise 2

• 1 - Refactor your test data from the last example into a @Before annotated setUp() method

• 2 - Add tests for the withdraw() method.

38

Page 39: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

TDDTraining

Continued introduction to

Unit Testing with JUnit and EclipsePresentation provided by

Combitech JidokaQ

Page 40: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Testing private or protected methods/membersJUnit will only test those methods in my class that are public or protected, but… In principle you got four options

• Don't test private methods. (Good or Bad?) • Give the methods package-private access. (Good or

Bad?) • Use a inner class or anonymous class. (Does it work?) • Use reflection. (Is this good?)

http://stackoverflow.com/questions/34571/whats-the-proper-way-to-test-a-class-with-private-methods-using-junit

40

Page 41: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Testing private or protected methods/membersThe best way to test a private method is via another public method. If this cannot be done, then one of the following conditions is true: 1. The private method is dead code. 2. There is a design smell near the class that you are testing. 3. The method that you are trying to test should not be private.

When I have private methods in a class that is sufficiently complicated that I feel the need to test the private methods directly, that could be a code smell: my class is too complicated. But, it might also be SDK or Framework code or Security or encryption/decryption code. That type of code also need tests, but no publicity…

41

Page 42: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Testing protected methods (Java)• Protected methods are visible by default when using the same parallel

package structure for tests, but if in different packages, it will not work! package productionpackage;public class ProtectedMethod {

protected String myProtectedMethod (String s) {return "MyClass: " + s; }

}

package testpackage;public class ProtectedMethodTest {

@Testpublic void testProtectedMethod() {

String expected = "MyClass: Hello";ProtectedMethod unitUnderTest = new ProtectedMethod();String actual = unitUnderTest.myProtectedMethod("Hello");boolean equal = actual.equalsIgnoreCase(expected);Assert.assertTrue("Strings not equal", equal);

}}

42

Will not work!

Page 43: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Testing protected methods (Java)The Subclass and Override idiom is used to write unit tests for protected methods: package productionpackage;public class ProtectedMethodClass {

protected String protectedMethod (String s) {return "Protected: " + s; }

}

package testpackage;public class ProtectedMethodClassTest {

// Create an inner class to expose the protected methodclass ExposeProtectedMethodClass extends ProtectedMethodClass {

public String exposeProtectedMethod(String s) {return super.protectedMethod(s);

}}@Testpublic void testProtectedMethod() {

String expected = "Protected: Hello";ExposeProtectedMethodClass unitUnderTest = new ExposeProtectedMethodClass();String actual = unitUnderTest.exposeProtectedMethod("Hello");boolean equal = actual.equalsIgnoreCase(expected);Assert.assertTrue("Strings not equal", equal);

}}

43

We can live with this since the exposure is done in test package, that will be stripped out in the production code!

Page 44: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Testing Interfaces or Abstract Classes (Java only)• Sometimes, you want to write tests for an Interface or Abstract Class,

and have those tests executed against all implementations. • Specify the tests in an Abstract Test class, with one concrete Test class

for each concrete implementation

44

Page 45: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Testing Interfaces - Java examplepackage somepackage;import org.junit.*;

public abstract class AbstractSomeInterfaceTest { private SomeInterface unitUnderTest; @Before public void setUp() { unitUnderTest = implementSomeInterfaceTest(); } @Test public void testSomeMethodReturnsTrue () { Assert.assertTrue("someMethod() should return true", unitUnderTest.someMethod()); } protected abstract SomeInterface implementSomeInterfaceTest();}

public class ImplementationXTest extends AbstractSomeInterfaceTest {@Overrideprotected SomeInterface implementSomeInterfaceTest() {

return new ImplementationX();}

}

45

package somepackage;public class ImplementationX implements SomeInterface {

@Overridepublic boolean someMethod() {

return false;}

}

Instances like this one, will run automatically according to test scheme in the abstract class.

package somepackage;

public interface SomeInterface {

boolean SomeMethod();}

Page 46: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

TDDTraining

Exercise 3 (refactor unit tests to Account)

Presentation provided by Combitech JidokaQ

Page 47: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Exercise 3 - As Demo• Refactor your test case from the last example into an

abstract test case for the interface Account, with a concrete test of the Account implementation

• Show it by running project TDD_Account_Solution concrete implementation ConcretAccountTest.

47

Page 48: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

What should be tested?• Everything that could possibly break! • Corollary: Don’t test stuff that is too simple to break! • Typical problematic areas:

– Boundary conditions • Conformance • Ordering • Range • Reference • Existence • Cardinality • Time

– Error conditions

48

Page 49: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Exercise 4

Given the following interface for a fax sender service: /* Send the named file as a fax to the given phone number.* Phone numbers should be of the form 0nn-nnnnnn where n is* digit in the range [0-9]*/ public boolean SendFax(String phone, String filename) {

. . .}

What tests for boundary conditions can you think of?

49

Page 50: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

TDDTraining

Introduction to TDD

(Test-Driven Development)Presentation provided by

Combitech JidokaQ

Page 51: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Test-Driven DevelopmentUnit Tests may be written very early. In fact, they may even

be written before any production code exists:

• Write a test that specifies a tiny bit of functionality • Ensure the test fails (you haven't built the functionality yet!) • Write the code necessary to make the test pass • Refactoring the code to remove redundancy

There is a certain rhythm to it: Design a little – test a little – code a little – design a little – test a little – code a little – ...

51

Page 52: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Test-Driven Development (process)1. Think about what you want to do. 2. Think about how to test it. 3. Write a small test. Think about the desired API. 4. Write just enough code to fail the test. 5. Run and watch the test fail (and you’ll get the "Red Bar"). 6. Write just enough code to pass the test (and pass all your previous tests). 7. Run and watch all of the tests pass (and you’ll get the "Green Bar”). 8. If you have any duplicate logic, or inexpressive code, refactor to remove

duplication and increase expressiveness. 9. Run the tests again (you should still have the “Green Bar”). 10. Repeat the steps above until you can't find any more tests that drive

writing new code.

52

Page 53: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Test-Driven Development process (TDD process)

53

Add a test

Run tests see new failure

Write code to fix itRun tests see all pass

Refactor

Page 54: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Simple Design• “Simplicity is more complicated than you think. But it’s

well worth it.” Ron Jeffries

• Satisfy Requirements – No Less – No More

54

You can use your developer intuition to find best choice

Page 55: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Simple Design Criteria• In Priority Order

– The code is appropriate for the intended audience – The code passes all the tests – The code communicates everything it needs to – The code has the smallest number of classes – The code has the smallest number of methods

Should we then have all code in one class and only have the one method the “main”-method? Of course not, but why?

55

Page 56: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Refactoring• Definition: Improve the code without changing its

functionality • Code needs to be refined as additional requirements

(tests) are added • For more information see

Refactoring: Improve the Design of Existing Code – Martin Fowler

56

Page 57: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Working Breadth First - Using a Test List• Work Task Based

– 4-8 hour duration (maximum) • Brainstorm a list of developer tests • Do not get hung up on completeness… you can

always add more later • Describes completion requirements

57

Page 58: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Red/Green/Refactor

58

Write a test for new capability

Start

Compile

Fix compile errors

Run the test And see it failWrite the code

Run the test And see it pass

Refactor as needed

Page 59: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

TDDTraining

TDD (Exercise Stack)

Presentation provided by Combitech JidokaQ

Page 60: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Exercise 5Use TDD to test, design and implement a Stack class for integers. You are not allowed to use any of the built-in collection classes! • Specification:

– “A stack is a data structure in which you can access only the item at the top. With a computer, Stack like a stack of dishes—you add items to the top and remove them from the top.”

Remember: Every single line of production code written must be motivated by a failing test! (N.B Compiler errors are failures as well)

60

Page 61: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Push operation

61

B

OperationInitial State

A C

Push

Unbounded Stack

( isEmpty = false )

C

Final State

B

Unbounded Stack

( isEmpty = false )

A

Page 62: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Pop operation

62

A

OperationInitial State

Pop returns

Unbounded Stack

( isEmpty = false )

Final State

Unbounded Stack

( isEmpty = true )

A

Page 63: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Top operation

63

A

OperationInitial State

Top returns

Unbounded Stack

( isEmpty = false )

Final State

Unbounded Stack

( isEmpty = false )

A

A

Page 64: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Recap: The TDD process Red/Green/Refactor

64

Write a test for new capability

Start

Compile

Fix compile errors

Run the test And see it failWrite the code

Run the test And see it pass

Refactor as needed

Page 65: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Exercise 5• Separate presentation, or demo

65

Page 66: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Solution 5 - Step 1a• Add test of isEmpty() – see it fail

public class SimpleStackTest {

@Testpublic void testNewStackIsEmpty() {

SimpleStack stack = new SimpleStack();Assert.assertTrue("New stack should be empty!",true == stack.isEmpty());

}}

public class SimpleStack {public boolean isEmpty() {

return false; // See it fail!}

}

66

Page 67: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Solution 5 - Step 1b• Add test of isEmpty() – make it work

public class SimpleStackTest {

@Testpublic void testNewStackIsEmpty() {

SimpleStack stack = new SimpleStack();Assert.assertTrue("New stack should be empty!",true == stack.isEmpty());

}}

public class SimpleStack {public boolean isEmpty() {

return true; // See it work!}

}

67

Page 68: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Solution 5 - Step 2a• Add test of push() – see it fail public class SimpleStackTest {

@Testpublic void testNewStackPush() {

SimpleStack stack = new SimpleStack();Assert.assertTrue("New stack should be empty!",true == stack.isEmpty());int item = 1;stack.push(item);Assert.assertFalse("Stack should not be empty after an item has been pushed!”, stack.isEmpty());

}}

public class SimpleStack {public boolean isEmpty() {

return true;}public void push(int item) {

// Pushes to void, but that ok, see it fail.}

}

68

Page 69: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Solution 5 - Step 2b• Add test of push() – make it work public class SimpleStackTest {

@Testpublic void testNewStackPush() {

SimpleStack stack = new SimpleStack();int item = 1;stack.push(item);Assert.assertFalse("Stack should not be empty after an item has been pushed!”, stack.isEmpty());

}}

public class SimpleStack {boolean empty = true; // Add variable to keep a statepublic boolean isEmpty() {

return empty; // Return the state}

public void push(int item) { empty = false; // Still pushes to void, but that is ok, see it work. }}

69

Page 70: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Solution 5 - Step 3• We now have got two tests, refactor (@Before)

public class SimpleStackTest {

@Testpublic void testNewStackIsEmpty() {

SimpleStack stack = new SimpleStack();Assert.assertTrue("New stack should be empty!",true == stack.isEmpty());

}

@Testpublic void testNewStackPush() {

SimpleStack stack = new SimpleStack();int item = 1;stack.push(item);Assert.assertFalse("Stack should not be empty after an item has been pushed!", stack.isEmpty());

}}

70

Page 71: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Solution 5 - Step 4• We now have got two tests, make it work

public class SimpleStackTest {

SimpleStack stack = null; // Declare for commonalities

@Beforepublic void setUp() { // Break out commonalities !

stack = new SimpleStack();}

@Testpublic void testNewStackIsEmpty() {

Assert.assertTrue("New stack should be empty!",true == stack.isEmpty());}

@Testpublic void testNewStackPush() {

int item = 1;stack.push(item);Assert.assertFalse("Stack should not be empty after an item has been pushed!", stack.isEmpty());

}}

71

Page 72: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Solution 5 - Step 5• Add test of pop() of empty stack, see it fail, make it work

@Testpublic void testEmptyStackPop() {

try { // expect an empty stack to throw exception when pop:ed@SuppressWarnings("unused")int topItem = stack.pop();Assert.fail("IllegalStateException expected");

} catch (java.lang.IllegalStateException e) {// Expected

}}// Production codepublic int pop() {

if (isEmpty()) {throw new java.lang.IllegalStateException();

}return 0; // Don’t think ahead, this works for our tests

}

72

Page 73: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Solution 5 - Step 6a (The test)• Add test of pop() of stack with content

@Testpublic void testPopOfStackWithOneItem() {

int item = 10;stack.push(item);int topItem = stack.pop();Assert.assertEquals("Popped item was expected to be 10.", item, topItem);

}

• Run test, see it fail

73

Page 74: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Solution 5 - Step 6b (The production code)• Add implementation of pop() of stack with content, run tests, make it work

public class SimpleStack {boolean empty = true;int stackValue = 0; // We need a variable to hold the stack

public int pop() {if (isEmpty()) {

throw new java.lang.IllegalStateException();}return stackValue;

}

public void push(int item) {stackValue = item;empty = false;

}}

74

Page 75: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Solution 5 - Step 7a (The test code)• Add test for multiple push() and pop() – Run tests, see it fail @Ignorepublic void testStackPushTwice() {

int item = 1;stack.push(item);item = 2;stack.push(item);Assert.assertFalse("New stack should not be empty after an item has been pushed!", stack.isEmpty());

}@Testpublic void testStackPopTwice() {

int item1 = 1; stack.push(item1);

int item2 = 2;stack.push(item2);int topItem = stack.pop();Assert.assertEquals("Popped item was expected to be 2.", item2, topItem);topItem = stack.pop();

Assert.assertEquals("Popped item was expected to be 1.", item1, topItem);Assert.assertTrue("Stack should be empty after all items has been pushed!", stack.isEmpty());

}

75

Page 76: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Solution 5 - Step 7b (The production code)• So far so good. It works, but we need to push our solution to be able to take more push. Time for redesign public class SimpleStack {

private ListElement stackTop = null;

public boolean isEmpty() {return stackTop == null;

}

public int pop() {int returnValue = 0;if (isEmpty()) {

throw new java.lang.IllegalStateException();} else {

returnValue = stackTop.value;stackTop = stackTop.nextElement;

}return returnValue;

}public void push(int item) {

ListElement listElement = new ListElement();listElement.value = item;listElement.nextElement = stackTop;stackTop = listElement;

}}• And, best of all, the tests will be reuse

76

public class ListElement {

public int value = 0;public ListElement nextElement = null;

}

Page 77: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Solution 5 - Step 8• Add tests for top() – make it work

@Testpublic void testEmptyStackTop() {

try {@SuppressWarnings("unused")int top = stack.top();Assert.fail("IllegalStateException expected");

} catch (java.lang.IllegalStateException e) {// Expected

}}

@Testpublic void testStackTopTwice() {

int item1 = 1;stack.push(item1);int topItem = stack.top();Assert.assertEquals("Top item was expected to be 1.", item1, topItem);topItem = stack.top();

Assert.assertEquals("Top item was expected to be 1.", item1, topItem);Assert.assertFalse("Stack should not be empty after stack hass beeb topped!", stack.isEmpty());

}

77

public int top() {int returnValue = 0;if (isEmpty()) {

throw new java.lang.IllegalStateException();} else {

returnValue = stackTop.value;}return returnValue;

}

Page 78: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

TDDTraining

TDD (Benefits)

Presentation provided by Combitech JidokaQ

Page 79: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Obvious Effects of Test-Driven Development• Already automated tests, immediately useful for

– Integration tests – Regression tests

79

Page 80: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Not so obvious effects of Test-Driven Development• Testing as we program means we spend less time

debugging. We get our programs done faster. • Testing as we program means that we don't have long

tedious testing cycles at the end of our projects. • Our tests are the first users of our code. We

experience what it is like to use our code very quickly. Hence, design turns out better.

• Testing before coding is more interesting than testing after we code. Because it's interesting, we find it easier to maintain what we know is a good practice.

80

Page 81: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Not-so-obvious effects of TDD (Contd.)• Intentional Design of Interfaces

– Since the code in question is not written yet, we are free to choose the interface

that is most usable.

• Non-speculative Interfaces – Interfaces provide the functionality which is just enough for right now

• Documented requirements and intended usage – The tests themselves provide immediately useful documentation of the

Interfaces

• Good OO Design: High Cohesion and Low Coupling – If you have to write tests first, you'll devise ways of minimizing dependencies in

your system in order to write your tests.

81

Page 82: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Possible weak points of TDD ?• When test code, very intensively, use production API

then it can impact the ability to refactor.

• Buggy tests – tests that is failing because of bugs in the test themselves.

• It will simply not be worth it, when cost for maintenance of the tests will be higher than benefits.

Hey there! We are developers and should strive to mitigate these weak points, shouldn’t we?

82

Page 83: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Types of tests– Unit test: Specify and test one point of the contract of single method of a class. This should have a very narrow

and well defined scope. Complex dependencies and interactions to the outside world are stubbed or mocked. – Integration test: Test the correct inter-operation of multiple subsystems. There is whole spectrum there, from

testing integration between two classes, to testing integration with the production environment. – Smoke test: A simple integration test where we just check that when the system under test is invoked it returns

normally and does not blow up. It is an analogy with electronics, where the first test occurs when powering up a circuit: if it smokes, it's bad.

– Regression test: A test that was written when a bug was fixed. It ensure that this specific bug will not occur again. The full name is "non-regression test".

– Acceptance test: Test that a feature or use case is correctly implemented. It is similar to an integration test, but with a focus on the use case to provide rather than on the components involved.

– A Canary test is an automated, non-destructive test that is run on a regular basis in a LIVE environment, such that if it ever fails, something really bad has happened.

• Examples might be: • Has data that should only ever be available in DEV/TEST appeared in LIVE. • Has a background process failed to run • Can a user logon • the concept of a canary in a coal mine.

83

Page 84: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Canary Test• In software testing, a canary (also called a canary test) is a push of

programming code changes to a small number of end users who have not volunteered to test anything. The goal of a canary test is to make sure code changes are transparent and work in a real world environment.

• Canary tests, which are often automated, are run after testing in a sandbox environment has been completed. Because the canary is only pushed to a small number of users, its impact is relatively small. If the new code prove to be buggy then the changes can be reversed quickly.

• The word canary was selected to describe the code push, because just like canaries that were once used in coal mining to alert miners when toxic gases reached dangerous levels, end users selected for testing are unaware they are being used to provide an early warning.

84

Page 85: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Designing for Testability: Low Coupling• Minimize dependencies between classes • Only allow “closely related” classes to interact directly

85

FRIENDS

Page 86: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Designing for Testability: Model-View-ControlUser Interfaces are notoriously difficult to test, but…

• Splitting a complex application into separate, cohesive parts which separates presentation from

application logic enables testing of the application logic in isolation

86

Page 87: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Testing User interface (coming…)User Interfaces are notoriously difficult to test, but…

• You can use tools like Selenium, e.t.c…

• If you are using ReactJS (Java script platform) there are framework, test runners and tools like:

• Jasmine

• Mocha

• Jest, WallabyJS

87

Page 88: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Some quotes on Test-Driven Development

• “Test-Driven Development is a powerful way to produce well designed code with fewer defects” – Martin Fowler

• “The best way that I know to write code is to shape it from the beginning with tests” – Ron Jeffries

• “Fewer defects, less debugging, more confidence, better design, and higher productivity in my programming practice” – Kent Beck

88

Page 89: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Code Coverage (Java) • Which statements of my application are being executed? • Useful to identify incomplete testing (ECLemma plug-In) • Option 1: Install from Eclipse Marketplace Client • Option 2: Installation from update site • Option 3: Manual download and installation

89

Page 90: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

But …• Focusing only on coverage is not sufficient, you may

miss: – Missing code – Incorrect handling of boundary conditions – Timing problems – Memory Leaks

• Use coverage sensibly – Objective, but incomplete – Too often distorts sensible action

90

Page 91: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Exercise 6• Run your previous tests from Exercise 5, to make sure

you have adequate Code Coverage! • Use ECLemma (bundled in the JVS Developer Tools)

91

Page 92: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Exercise 7Use TDD to test and implement Naughts and Crosses game board

interface.

Details about game rules can be found here: http://en.wikipedia.org/wiki/Tic-tac-toe

92

Page 93: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

TDD enables cheap, early, and frequent tests!It’s always a bit painful to change your habits, but once

you’ve been there, you’re stuck! • Enables truly iterative projects • Improves your design • Doesn’t cost your project a fortune • It’s even fun! Bottom Line:

Automated Testing and Test-Driven Development is infectious!

93

Page 94: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

TDDTraining

Introduction to

Integration TestingPresentation provided by

Combitech JidokaQ

Page 95: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Integration Tests• An Integration Test is any test which tests a logical

unit together with other units that it depends on, such as other software units but more frequently external resources such as Databases or Message Queues.

• Thus the integration tests share many of the characteristics of Unit Tests, but the granularity is much bigger.

• Due to the performance costs in accessing external resources, the integration tests usually takes much longer time to execute.

95

Page 96: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Ratio between Unit and Integration Tests• Unit tests are naturally the most efficient way of

catching defects on the Unit level. – If a defect can be caught using a Unit Test, it

should therefore be preferred instead of catching it using an Integration test.

– Hence there will typically be many more Unit tests than integration tests.

• Integration tests should be used for testing interaction between units and between units and external resources.

96

Page 97: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

97

Ratio between Unit and Integration Tests

Only Unit test

Page 98: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

98

Only integration test

Ratio between Unit and Integration Tests

Page 99: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Test Data, concurrency and repeatability• Integration tests which have side effects (i.e. which

affects persistent data) are problematic: – Modifying data which other tests may depend on,

may cause subsequent test failures – Several instances of tests which uses the same data

may run concurrently, which may cause test failures • Transaction demarcation is a common idiom to protect

test data from modification: – Start a transaction in [SetUp] – Rollback the transaction in [TearDown]

99

sd IntegrationTest Data Mgmt

IntegrationTestCase TxManagerTestFramework

setUp

begin

tearDown

rollback

Page 100: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Test Data, concurrency and repeatability

100

sd IntegrationTest Data Mgmt

IntegrationTestCase TxManagerTestFramework

setUp

begin

tearDown

rollback

Page 101: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Test Data strategies• Integration tests

– Local test data, owned and managed by test – Global, common test data, pre-populated via

SQL scripts • System tests

– All data owned by test script • Separate Databases

• Primary keys/IDS and Test Data

101

Page 102: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Managing External Test Data Files• Some test data is most easily kept in a file format (e.g. XML files) which

are read and manipulated by the tests. In order to make the tests insulated from how and where they are executed, the tests should not refer to external files via the file system. Both absolute and relative file names may differ depending on the execution environment.

• Instead, the tests may keep data files as “Embedded Resources” within the test assembly itself (src/test/resources).

102

Page 103: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

DbUnit• DbUnit is a JUnit extension targeted at database-

driven applications. • Puts your database into a known state between test

runs. • DbUnit has the ability to export and import your

database data to and from XML datasets. • DbUnit is used by JVS.

103

Page 104: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

TDDTraining

Designing for testability

Presentation provided by Combitech JidokaQ

Page 105: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Designing for Testability : Law of Demeter (LoD or principle of least knowledge)

• Any method should have limited knowledge about its surrounding object structure.

• Named in honor of Demeter, “distribution-mother”, Greek goddess of agriculture

Hence, this is bad…

public class SomeUnit { private IDependee dependee; public SomeUnit() { this.dependee = new SomeDependee(); } ... }

105

Page 106: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Law of Demeter (Contd.)This is better, because no knowledge of SomeDependee class

public class SomeUnit { private IDependee dependee; public SomeUnit() { } public SetDependee(IDependee dependee) { this.dependee = dependee; } ... }

106

Page 107: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Designing for Testability: LoD - Don’t Talk To StrangersIf there are no strong reasons why two classes should talk to each other directly, they shouldn’t!

107

becomes

<<interface>>IDependee

UnitunderTest(UUT) SomeDependee

UnitunderTest(UUT) SomeDependee

Page 108: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Designing for Testability: Dependency InjectionWhat is it?

• Dependency Injection provides a mechanism for managing dependencies between components in a decoupled way.

• Dependency Management where coupling is attached/detached at runtime.

• Makes it easier to unit test components in isolation: Out of container and with mocked dependencies

108

Page 109: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

TDDTraining

Breaking dependencies

Presentation provided by Combitech JidokaQ

Page 110: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Design properties and Design goals

For Units: • Modularity • High cohesion • Low coupling For Tests: • Modularity • Locality

110

UnitTestUnitunderTest

(UUT)

Page 111: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Side effects

But what about units that depend on other units (with potential side effects)?

111

UnitunderTest(UUT)

DataAccessObject(DAO)

- create()- update()- delete()- read()

RDBMS

Page 112: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Strategies for testing Units that depend on other units

• Break the dependency: Let the Test create a synthetic ‘Mock’ context

• Run and test the Unit within it’s natural context (In Container in the case of Java EE or .NET)

• Let the Test create the real context

112

TestUnitunderTest

(UUT) Dependee

Page 113: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Synthetic context – Mocking• Implements the same

interface as the resource that it represents

• Enables configuration of its behavior from outside (i.e. from the test class, in order to achieve locality)

• Enables registering and verifying expectations on how the resource is used

113

UnitunderTest(UUT)

<<interface>>DAO

- create()- update()- delete()- read()

RDBMS

UnitTest creates

RealDAOMockDAO

creates

Page 114: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

TDDTraining

Mocking using plain Java

Presentation provided by Combitech JidokaQ

Page 115: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Why Mock?

Main principle of TDD: Unit tests should act as a safety net and provide quick feedback.

A test may take time to execute due to the following reasons: • Sometimes a test acquires a connection from the database that fetches/updates

data

• It connects to the Internet and downloads files

• It interacts with an SMTP server to send e-mails

• It performs I/O operations

115

Page 116: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Why Mock?

Do we really need to acquire a database connection or download files to test code?

The answer is YES!.If it doesn't connect to a database or download the latest stock price, few parts of the system remain untested. So, DB interaction or network connection is mandatory for a few parts of the system, and these are integration tests.

But! To unit test these parts, the external dependencies need to be mocked out.

116

Page 117: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Test Doubles

117

Doubles

Dummy Stub Mock Fake Spy

Page 118: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

DummyA dummy would be like a movie scene where the double doesn't perform anything but is only present on the screen.

They are used when the actual actor is not present, but their presence is needed for a scene.

118

Page 119: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Dummy exampleSimilarly, dummy objects are passed to avoid NullPointerException for mandatory parameter objects as follows:

@Testpublic void aTestMethod() {

Book javaBook = new Book("Java 101", "123456");Member dummyMember = new DummyMember(); //<-a dummy memberjavaBook.issueTo(dummyMember);assertEquals(javaBook.numberOfTimesIssued(),1);

}

N.B. The need for dummies is decreasing since introduction of the concept of Optional<T> in Java 8.

public final class Optional<T>() extends Object {…}

119

Page 120: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

StubA stub delivers indirect inputs to the caller when the stub's methods are called.

Stubs are programmed only for the test scope.

Stubs may record other information such as the number of times the methods were invoked and so on.

120

Page 121: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Stub example

Account transactions should be rolled back if the ATM's money dispenser fails to dispense money. How can we test this when we don't have the ATM machine, or how can we simulate a scenario where the dispenser fails? We can do this using the following code:

public interface Dispenser { void dispense(BigDecimal amount) throws DispenserFailed;}

public class AlwaysFailingDispenserStub implements Dispenser { public void dispense(BigDecimal amount) throws DispenserFailed { throw new DispenserFailed (ErrorType.HARDWARE, “Failing dispense"); }}

121

Page 122: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Stub example (cont.)

@Testpublic void transaction_is_rolledback_when_hardware_fails() {

// Arrange: set up a failing dispenserAccount myAccount = new Account("John", 2000.00);TransactionManager txMgr = TransactionManager.forAccount(myAccount);txMgr.registerMoneyDispenser(new AlwaysFailingDispenserStub());

// Act:WithdrawalResponse response = txMgr.withdraw(500.00);

// Assert: no success and that no change on the accountassertEquals(false, response.wasSuccess());assertEquals(2000.00, myAccount.remainingAmount());

}

122

Page 123: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Fake

Fake objects are mostly working implementations, the fake class extends the original class, but it usually hacks the performance, which makes it unsuitable for production.

123

Page 124: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Fake examplepublic class AddressDAO extends SimpleJdbcDaoSupport {

public void batchInsertOrUpdate(List<AddressDTO> addressList, User user) {List<AddressDTO> insertList = buildListWhereLastChangeTimeMissing(addressList);List<AddressDTO> updateList = buildListWhereLastChangeTimeValued(addressList);int rowCount = 0;

if (!insertList.isEmpty()) {rowCount = getSimpleJdbcTemplate().batchUpdate(INSERT_SQL, "...");

}if (!updateList.isEmpty()) {

rowCount += getSimpleJdbcTemplate().batchUpdate(UPDATE_SQL, "...");}if (addressList.size() != rowCount) {

raiseErrorForDataInconsistency("...");}

}public SimpleJdbcTemplate getSimpleJdbcTemplate() { // Fake this method !!!

// Long complicated implementation…}

}

124

Page 125: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Fake example (cont.)public class FakeAddressDAO extends AddressDAO {

private SimpleJdbcTemplate jdbcTemplate = new SimpleJdbcTemplate();

@Overridepublic SimpleJdbcTemplate getSimpleJdbcTemplate() {

return jdbcTemplate ;}

}@Testpublic void testAddressDAO() {

//ArrangeAddressDAO addressDAO = new FakeAddressDAO();User user = new User("Apple Inc.");List<AddressDTO> addressList = new ArrayList<AddressDTO>();AddressDTO addressDTO = new AddressDTO("One Infinite Loop", "Cupertino", "CA");addressList.add(addressDTO);// ActaddressDAO.batchInsertOrUpdate(addressList, user);// Assert ....

}

125

Page 126: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

MockMock objects have expectations.

A test expects a value from a mock object, and during execution, a mock object returns the expected result.

Also, mock objects can keep track of the invocation count, that is, the number of times a method on a mock object is invoked.

126

Page 127: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Mock exampleThe following example is a continuation of the ATM example with a mock version. In the previous example, we stubbed the dispense method of the Dispenser interface to throw an exception; here, we'll use a mock object to replicate the same behavior. @RunWith(MockitoJUnitRunner.class)public class ATMTest {

@MockDispenser failingDispenser;@Beforepublic void setUp() throws Exception {

MockitoAnnotations.initMocks(this);}@Testpublic void transaction_is_rolledback_when_hardware_fails() throws DispenserFailed {

Account myAccount = new Account(2000.00, "John");TransactionManager txMgr = TransactionManager.forAccount(myAccount);txMgr.registerMoneyDispenser(failingDispenser);doThrow(new DispenserFailed()).when(failingDispenser).dispense(isA(BigDecimal.class));

txMgr.withdraw(500.00f);

assertEquals(2000.00, myAccount.getRemainingBalance(), 0.01f);verify(failingDispenser, new Times(1)).dispense(isA(BigDecimal.class));

}}

127

Page 128: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Spy

Spy is a variation of a mock/stub, but instead of only setting expectations, it records the calls made to the collaborator.

128

Page 129: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Spy examplepublic class ResourceAdapter {

Printer printer;SecurityService securityService;

public ResourceAdapter(SecurityService securityService, Printer printer) {this.securityService = securityService;this.printer = printer; // <—- Supports dependency injection

}void print(String userId, String document, Object settings) {

if (securityService.canAccess("lanPrinter1", userId)) {printer.print(document, settings);

}}

}

public interface Printer {void print(String document, Object settings);

}

public interface SecurityService {public boolean canAccess(String name, String id);

}

129

Page 130: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Spy Example cont.public class FakeSecurityService implements SecurityService { // <—- Fake a service

public boolean canAccess(String name, String id) {return true;

}}public class SpyPrinter implements Printer { // <—- Implement a Spy

private int noOfTimescalled = 0;@Overridepublic void print(String document, Object settings) {

noOfTimescalled++;}public int getInvocationCount() {

return noOfTimescalled;}

}@Testpublic void verify() throws Exception {

SpyPrinter spyPrinter = new SpyPrinter(); // <—- Arrangeadapter = new ResourceAdapter(new FakeSecurityService(), spyPrinter);adapter.print("john", "helloWorld.txt", "all pages");assertEquals(1, spyPrinter.getInvocationCount());

}

130

Page 131: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

When to use mocking (and when not to)• Mocking is great for

– Breaking dependencies between well-architected layers or tiers – Testing corner cases and exceptional behavior

• Mocking is less ideal for – Replacing awkward 3rd party APIs – Responsibilities which involves large amounts of state or data,

which could be more conveniently expressed in a ”native” format • This is clearly a judgement call: If breaking a dependency using mock

objects cost more effort than living with the dependency, then the mock strategy is probably not a good idea

131

Page 132: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

TDDTraining

Mocking with Mockito (Intro)

Presentation provided by Combitech JidokaQ

Page 133: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Frameworks and tools for mocking• code.google.com/p/mockito/ (Active 2015)

– No expect-run-verify also means that Mockito mocks are often ready without expensive setup

upfront

• www.easymock.org (Active 2015) – Class library which generates Mock Objects

dynamically using the Java Proxy class

• www.mockobjects.org (latest update 2010)

– Commonly used assertions refactored into a number of Expectation classes, which facilitate

writing Mock Objects.

• www.mockmaker.org (latest update 2002) – Tool which automatically generates a MockObject

from a Class or Interface

133

Page 134: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Mockito• Mocks concrete classes as well as interfaces • Little annotation syntax sugar - @Mock • Verification errors are clean - click on stack trace to see failed

verification in test; click on exception's cause to navigate to actual interaction in code. Stack trace is always clean.

• Allows flexible verification in order (e.g: verify in order what you want, not every single interaction)

• Supports exact-number-of-times and at-least-once verification • Flexible verification or stubbing using argument matchers

(anyObject(), anyString() or refEq() for reflection-based equality matching)

• Allows creating custom argument matchers or using existing hamcrest matchers

134

Page 135: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Typical usage scenario for mocking in a test case

1. Instantiate mock objects 2. Set up state in mock objects, which govern their

behavior 3. Set up expectations on mock objects 4. Execute the method(s) on the Unit Under Test,

using the mock objects as resources 5. Verify the results & expectations

135

Page 136: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Mockito - example usage@Testpublic void testNotificationVetoShouldBeHonoured() { int amount = AccountImpl.SUPERVISION_TRESHOLD;

Supervisor mockSupervisor = Mockito.mock(Supervisor.class);

Mockito.when(mockSupervisor.notify(Mockito.anyString(), Mockito.anyString(), (Transaction) Mockito.anyObject())).thenReturn(false);

account.setSupervisor(mockSupervisor);

try { account.deposit(amount); Assert.fail("SupervisorException expected"); } catch (SupervisorException expected) { // expected System.err.println(expected); }

Mockito.verify(mockSupervisor).notify(account.getAccountID(), account.getOwnerName(), new Transaction(Transaction.DEPOSIT, amount));}

• Create MockObject • Let the mock object know how to answer on

an expected call • Inject the MockObject in the class to be tested • Run the test • Verify that the mock object received the

expected calls and parameters

136

Page 137: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Exercise 7• Extend the tests for AccountImpl to use Mockito for

validating correct usage of the Supervisor collaborator!

137

Page 138: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Demo Mocking Raspberry Regulator• Mocking integration to a Raspberry Pi

138

Page 139: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

TDDTraining

Mocking with MockitoPresentation provided by

Combitech JidokaQ

Page 140: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

How to invoke MockitoUnit tests should act as a safety net and provide quick feedback; the main principle of TDD. import org.junit.runner.RunWith;import static org.mockito.Mockito.mock;

@RunWith(MockitoJUnitRunner.class)public class StockBrokerTest {

// Alternative !: Static mockMarketWatcher marketWatcher = mock(MarketWatcher.class);// Alternative 2: Annotated mock// Needs a call to MockitoAnnotations.initMocks(this);@MockPortfolio portfolio;

@Beforepublic void setUp() {

broker = new StockBroker(marketWatcher);MockitoAnnotations.initMocks(this); // <—- Alternative 2 need to call this

}@Testpublic void sanity() throws Exception {

assertNotNull(marketWatcher); // <—- Needed to check that Mockito initiated properlyassertNotNull(portfolio);

}}

140

} Needed these imports and annotations

Page 141: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Stubbing with MockitoThe stubbing process defines the behavior of a mock method such as the value to be returned or the exception to be thrown when the method is invoked.

The Mockito framework supports stubbing and allows us to return a given value when a specific method is called. This can be done using Mockito.when() along with thenReturn(). import static org.mockito.Matchers.anyString;import static org.mockito.Mockito.when;

@RunWith(MockitoJUnitRunner.class)public class StockBrokerTest {

// . . . se previous slide@Testpublic void marketWatcher_Returns_current_stock_status() throws Exception {

BigDecimal aBigDecimal = new BigDecimal(100.00);Stock uvsityCorp = new Stock("UV", "UVSITY Corporation “, aHundred);when(marketWatcher.getQuote(anyString())).thenReturn(uvsityCorp);assertNotNull(marketWatcher.getQuote("UV"));

}}

141

Page 142: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Mockito.when(…).thenNnnn()

The when() method represents the trigger, that is, when Mosquito should stub. The following methods are used to represent what to do when the trigger is triggered:

• thenReturn(x): This returns the x value. • thenThrow(x): This throws an x exception. • thenAnswer(Answer answer): Unlike returning a hardcoded value,

a dynamic user-defined logic is executed. It's more like for fake test doubles, Answer is an interface.

• thenCallRealMethod(): This method calls the real method on the mock object.

142

Page 143: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Verify() with MockitoThe verify() method has an overloaded version that takes Times as an argument. Times is a Mockito framework class of the org.mockito.internal.verification package, and it takes wantedNumberOfInvocations as an integer argument.

@Testpublic void when_ten_percent_gain_then_the_stock_is_sold() { // Arrange Mock

when(portfolio.getAvgPrice(isA(Stock.class))).thenReturn(new BigDecimal("10.00"));Stock aCorp = new Stock("A", "A Corp", new BigDecimal(11.20));when(marketWatcher.getQuote(anyString())).thenReturn(aCorp);broker.perform(portfolio, aCorp); // Act, run business logic verify(portfolio).sell(aCorp, 10); // Verifies method invocation

}

@Testpublic void argument_matcher() { // This example will be more covered under advanced topics

when(portfolio.getAvgPrice(isA(Stock.class))).thenReturn(new BigDecimal("10.00"));Stock blueChipStock = new Stock("FB", "FB Corp”, new BigDecimal(1000.00));Stock otherStock = new Stock("XY", "XY Corp", new BigDecimal(5.00));when(marketWatcher.getQuote(argThat(new BlueChipStockMatcher()))).thenReturn(blueChipStock);when(marketWatcher.getQuote(argThat(new OtherStockMatcher()))).thenReturn(otherStock);

broker.perform(portfolio, blueChipStock);verify(portfolio).sell(blueChipStock, 10); // verifies invocation

broker.perform(portfolio, otherStock);verify(portfolio, new Times(0)).sell(otherStock, 10); // verifies zero invocation

}

143

Page 144: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Methods used in conjunction with verify() The following methods are used in conjunction with verify:

• times(int wantedNumberOfInvocations): This method is invoked exactly n times; if the method is not invoked wantedNumberOfInvocations times, then the test fails.

• never(): This method signifies that the stubbed method is never called or you can use times(0) to represent the same scenario. If the stubbed method is invoked at least once, then the test fails.

• atLeastOnce(): This method is invoked at least once, and it works fine if it is invoked multiple times. However, the operation fails if the method is not invoked.

• atLeast(int minNumberOfInvocations): This method is called at least n times, and it works fine if the method is invoked more than the minNumberOfInvocations times. However, the operation fails if the method is not called minNumberOfInvocations times.

• atMost(int maxNumberOfInvocations): This method is called at the most n times. However, the operation fails if the method is called more than minNumberOfInvocations times.

• only(): The only method called on a mock fails if any other method is called on the mock object.• timeout(int millis): This method is interacted in a specified time range.

Example:verify(portfolio).sell(blueChipStock, 10); // verifies invocationverify(portfolio, new Times(0)).sell(otherStock, 10); // verifies zero invocation

}

144

Page 145: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Verifying zero and no more interactions

The verifyZeroInteractions(Object... mocks) method verifies whether no interactions happened on the given mocks.

The following test code directly calls verifyZeroInteractions and passes the two mock objects. Since no methods are invoked on the mock objects, the test passes:

@Testpublic void verify_zero_interaction() {

verifyZeroInteractions(marketWatcher, portfolio);}

The verifyNoMoreInteractions(Object... mocks) method checks whether any of the given mocks has any unverified interaction. We can use this method after verifying a mock method to make sure that nothing else was invoked on the mock.

// This test will fail, this is to demonstrate the error@Testpublic void verify_no_more_interaction() {

Stock noStock = null;portfolio.getAvgPrice(noStock);portfolio.sell(null, 0);verify(portfolio).getAvgPrice(eq(noStock));// this will fail as the sell method was invokedverifyNoMoreInteractions(portfolio);

}

145

Page 146: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Wildcard matchers Wildcard matchers are used to verify the indirect inputs to the mocked dependencies. The following example describes the context.

In the following code snippet, an object is passed to a method and then a request object is created and passed to service. Now, from a test, if we call the someMethod method and service is a mocked object, then from test, we cannot stub callMethod with a specific request as the request object is local to the someMethod:

public void someMethod(Object object) {Request request = new Request(); // request is local, hencerequest.setValue(object);Response response = service.callMethod(request); // we can't stub callMethod with specific request

}

If we are using argument matchers, all arguments have to be provided by matchers.

We're passing three arguments and all of them are passed using matchers:

@Testpublic void testSomeOtherMethod() {

verify(mock).someOtherMethod(anyInt(), anyString(), eq("third argument"));

verify(mock).someOtherMethod(1, anyString(), "third argument”); <—— will fail}

The last row in the example will fail because the first and the third arguments are not passed using matcher:

146

Page 147: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

TDDTraining

Mocking with Mockito (some more advanced topics)

Presentation provided by Combitech JidokaQ

Page 148: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Using argument matcherArgumentMatcher extends the org.hamcrest.BaseMatcher package. It verifies the indirect inputs into a mocked dependency.

•The Matchers.argThat(Matcher) method is used in conjunction with the verify method to verify whether a method is invoked with a specific argument value.

•Mockito verifies argument values in natural Java style by using an equals() method. Sometimes, we use argument matchers when extra flexibility is required.

148

Page 149: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Built-In matcherMockito provides built-in matchers such as: anyInt(), anyDouble(), anyString(), anyList(), and anyCollection().

Mock objects return expected values, but when they need to return different values for different arguments, argument matcher comes into play.

149

Page 150: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Using argument matcher. cont.Mockito returns expected values when a method is stubbed. If the method takes arguments, the argument must match during the execution; for example, the getValue(int someValue) method is stubbed in the following way:

when(mockObject.getValue(1)).thenReturn(expectedValue);

If, the getValue method is called with mockObject.getValue(100).

Then, the parameter doesn't match (it is expected that the method will be called with 1, but at runtime, it encounters 100), so the mock object fails to return the expected value.

It will return the default value of the return type—if the return type is Boolean, it'll return false; if the return type is object, then null, and so on.

150

Page 151: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Custom Argument matcherLet us create a custom matcher to identify blue chip stocks. The following code shows a custom argument matcher:

class BlueChipStockMatcher extends ArgumentMatcher<String> {@Overridepublic boolean matches(Object symbol) {return "FB".equals(symbol) || "AAPL".equals(symbol);

}}

The following class extends BlueChipStockMatcher and then negates the result to indicate that the stock is not a blue chip stock:

class OtherStockMatcher extends BlueChipStockMatcher {@Overridepublic boolean matches(Object symbol) {return !super.matches(symbol);

}}

151

Page 152: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Using Custom Matcher@Testpublic void argument_matcher() { when(portfolio.getAvgPrice(isA(Stock.class))).thenReturn(new BigDecimal("10.00")); Stock blueChipStock = new Stock("AAPL", "Apple Corp",new BigDecimal(1000.00)); Stock otherStock = new Stock("XY", "XY Corp", new BigDecimal(5.00)); // Matcher when(marketWatcher.getQuote(argThat(new BlueChipStockMatcher()))).

thenReturn(blueChipStock); when(marketWatcher.getQuote(argThat(new OtherStockMatcher()))).thenReturn(otherStock);

broker.perform(portfolio, blueChipStock); verify(portfolio).sell(blueChipStock, 10);

broker.perform(portfolio, otherStock); verify(portfolio, new Times(0)).sell(otherStock, 10); // Alternative 1 verify(portfolio, never()).sell(otherStock, 10); // Alternative 2}

In the preceding code, marketWatcher is stubbed to return a blue chip share when the stock symbol is FB or AAPL; otherwise, it returns a normal stock.

152

Page 153: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Throwing exceptionsMockito provides a method called thenThrow(Throwable); this method throws an exception when the stubbed method is invoked.

We will stub the getAvgPrice method to throw an exception when the method is called, as follows: @Test(expected = IllegalStateException.class)public void testThrowsException() throws Exception {

when(portfolio.getAvgPrice(isA(Stock.class))).thenThrow(new IllegalStateException("Database down"));

portfolio.getAvgPrice(new Stock(null, null, null));fail("Should throw exception");

}

153

Page 154: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Throwing exceptions (with void returned).We are stubbing portfolio to throw an exception when getAvgPrice() is invoked. The following is the syntax to throw an exception from a method that returns void:

doThrow(exception).when(mock).voidmethod(arguments);

The buy() method in Portfolio is a void method; we will stub the buy() method to throw an exception. The following test code throws IllegalStateException when the buy() method is invoked on the portfolio object. Note that doThrow().when() will be used to raise the error from the buy method:

@Test(expected = IllegalStateException.class)public void throwsException_void_methods() throws Exception {

doThrow(new IllegalStateException()).when(portfolio).buy(isA(Stock.class));

portfolio.buy(new Stock(null, null, null));fail("Should throw exception");

}

154

Page 155: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Stubbing consecutive callsStubbing a method for consecutive calls is required in the following situations:

•Calling a stubbed method in a loop when you need different results for different calls.

•When you need one invocation to throw an exception and other invocations to return a value.

•We need to test a condition where the first call will return a value, the next call should not find any value, and then again it should return a value.

The varargs version of thenReturn(objects...) takes comma-separated return values and returns the arguments in order such that if we pass two arguments to the thenReturn method, then the first call to the stubbed method will return the first argument.

Thereafter, all other calls will return the last argument, as shown in the following code:

155

Page 156: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Stubbing consecutive calls, cont.Stubbing a method for consecutive calls is required in the following situations: @Testpublic void consecutive_calls() throws Exception {

// Return sequence is 10,0,0,10, ...... and 10 foreverStock stock = new Stock(null, null, null);when(portfolio.getAvgPrice(stock)).thenReturn(

BigDecimal.TEN, BigDecimal.ZERO, BigDecimal.ZERO,BigDecimal.TEN);

assertEquals(BigDecimal.TEN, portfolio.getAvgPrice(stock));assertEquals(BigDecimal.ZERO, portfolio.getAvgPrice(stock));assertEquals(BigDecimal.ZERO, portfolio.getAvgPrice(stock));assertEquals(BigDecimal.TEN, portfolio.getAvgPrice(stock));assertEquals(BigDecimal.ZERO, portfolio.getAvgPrice(stock));

}

156

Page 157: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

TDDTraining

Mocking a Realworld Example

(with plain Java)Presentation provided by

Combitech JidokaQ

Page 158: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Real World Example

158

sensor<Sensor> actor<Actor>

Regulator

getValue()

<Sensor>

start() stop() - - - - - - - - - getState()

<Actor>

adapter<Adapter> - - - - - - - - - - - - - - - - - getValue()

TempSensor<Sensor>

adapter<Adapter> - - - - - - - - - - - - - - - - - start() stop() getState()

HeaterActor<Actor>

sendMessage() askQuery()

<Adaptor>

sendMessage() askQuery()

HardwareAdaptor<Adaptor>Uses a

Controls a

sendMessage() askQuery()

<Adaptor>

sendMessage() askQuery()

HardwareAdaptor<Adaptor>

Bytestream

Bytestream

Sensors

Actors

Regulator

String msg

String msg

Page 159: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Design with interface

159

sensor<Sensor> actor<Actor>

Regulator

getValue()

<Sensor>

start() stop() - - - - - - - - - getState()

<Actor>

adapter<Adapter> - - - - - - - - - - - - - - - - - getValue()

TempSensor<Sensor>

adapter<Adapter> - - - - - - - - - - - - - - - - - start() stop() getState()

HeaterActor<Actor>

sendMessage() askQuery()

<Adaptor>

sendMessage() askQuery()

HardwareAdaptor<Adaptor>Uses a

Controls a

sendMessage() askQuery()

<Adaptor>

sendMessage() askQuery()

HardwareAdaptor<Adaptor>

Bytestream

Bytestream

This interface enables mocking

These interfaces enables mocking

This interface enables mocking

Sensors

Actors

Regulator

String msg

String msg

Page 160: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Replacing real classes with Mock

160

sensor<Sensor> actor<Actor>

Regulator

getValue()

<Sensor>

start() stop() - - - - - - - - - getState()

<Actor>

adapter<Adapter> - - - - - - - - - - - - - - - - - getValue()

MockTempSensor<Sensor>

adapter<Adapter> - - - - - - - - - - - - - - - - - start() stop() getState()

MockHeaterActor<Actor>

sendMessage() askQuery()

<Adaptor>

sendMessage() askQuery()

HardwareAdaptor<Adaptor>Uses a

Controls a

sendMessage() askQuery()

<Adaptor>

sendMessage() askQuery()

HardwareAdaptor<Adaptor>

Bytestream

Bytestream

A mock instance

These interfaces enables mocking

A mock instance

Another possible mock instance

Another possible mock instance

Sensors

Actors

Regulator

String msg

String msg

Page 161: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Regulator class

161

sensor<Sensor> actor<Actor>

Regulator

getValue()

<Sensor>

start() stop() - - - - - - - - - getState()

<Actor>

adapter<Adapter> - - - - - - - - - - - - - - - - - getValue()

MockTempSensor<Sensor>

adapter<Adapter> - - - - - - - - - - - - - - - - - start() stop() getState()

MockHeaterActor<Actor>

sendMessage() askQuery()

<Adaptor>

sendMessage() askQuery()

HardwareAdaptor<Adaptor>Uses a

Controls a

sendMessage() askQuery()

<Adaptor>

sendMessage() askQuery()

HardwareAdaptor<Adaptor>

Bytestream

Bytestream

A mock instance

These interfaces enables mocking

A mock instance

Another possible mock instance

Another possible mock instance

public class Regulator {

private Sensor temperatureSensor;private Actor heaterActor;private double lowThreshold;

public Regulator(Sensor temperatureSensor, double lowThreshold, Actor heaterActor) {

this.temperatureSensor = temperatureSensor;this.lowThreshold = lowThreshold;this.heaterActor = heaterActor;

}

public void act() {double temperature = temperatureSensor.getValue();if (temperature < lowThreshold) {

heaterActor.start();} else {

heaterActor.stop();}

}}

public interface Sensor {double getValue();

}public interface Actor {

void start();void stop();boolean getState();

}

Regulator

Page 162: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

TempSensor class

162

getValue()

<Sensor>

start() stop() - - - - - - - - - getState()

<Actor>

adapter<Adapter> - - - - - - - - - - - - - - - - - getValue()

TempSensor<Sensor>

adapter<Adapter> - - - - - - - - - - - - - - - - - start() stop() getState()

HeaterActor<Actor>

sendMessage() askQuery()

<Adaptor>

sendMessage() askQuery()

HardwareAdaptor<Adaptor>Uses a

Controls a

sendMessage() askQuery()

<Adaptor>

sendMessage() askQuery()

HardwareAdaptor<Adaptor>

Bytestream

Bytestream

A mock instance

These interfaces enables mocking

A mock instance

Another possible mock instance

Another possible mock instance

public class TempSensor implements Sensor {

private Adapter adapter;

public TempSensor(Adapter adapter) {this.adapter = adapter;

}

@Overridepublic double getValue() {

String response = adapter.askQuery("TempValue");double value = Double.parseDouble(response);return value;

}}

public interface Sensor {double getValue();

}

Page 163: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

HeaterActor class

163

getValue()

<Sensor>

start() stop() - - - - - - - - - getState()

<Actor>

adapter<Adapter> - - - - - - - - - - - - - - - - - getValue()

TempSensor<Sensor>

adapter<Adapter> - - - - - - - - - - - - - - - - - start() stop() getState()

HeaterActor<Actor>

sendMessage() askQuery()

<Adaptor>

sendMessage() askQuery()

HardwareAdaptor<Adaptor>Uses a

Controls a

sendMessage() askQuery()

<Adaptor>

sendMessage() askQuery()

HardwareAdaptor<Adaptor>

Bytestream

Bytestream

A mock instance

These interfaces enables mocking

A mock instance

Another possible mock instance

Another possible mock instance

public class HeaterActor implements Actor {

private Adapter adapter;

public HeaterActor(Adapter adaptert) {this.adapter = adaptert;

}@Overridepublic void start() {

adapter.sendMessage("start");}@Overridepublic void stop() {

adapter.sendMessage("stop");}@Overridepublic boolean getState() {

String state = adapter.askQuery("state");return state.equalsIgnoreCase("on");

}}

public interface Actor {void start();void stop();boolean getState();

}

Page 164: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

MockTempSensor class

164

getValue()

<Sensor>

start() stop() - - - - - - - - - getState()

<Actor>

adapter<Adapter> - - - - - - - - - - - - - - - - - getValue()

MockTempSensor<Sensor>

adapter<Adapter> - - - - - - - - - - - - - - - - - start() stop() getState()

MockHeaterActor<Actor>

sendMessage() askQuery()

<Adaptor>

sendMessage() askQuery()

HardwareAdaptor<Adaptor>Uses a

Controls a

sendMessage() askQuery()

<Adaptor>

sendMessage() askQuery()

HardwareAdaptor<Adaptor>

Bytestream

Bytestream

A mock instance

These interfaces enables mocking

A mock instance

Another possible mock instance

Another possible mock instance

public class MockTempSensor implements Sensor {

private double actualTemperature;

public MockTempSensor(double actualTemperature) {this.actualTemperature = actualTemperature;

}

@Overridepublic double getValue() {

return actualTemperature;}

}

public interface Sensor {double getValue();

}

Page 165: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

MockHeaterActor class

165

getValue()

<Sensor>

start() stop() - - - - - - - - - getState()

<Actor>

adapter<Adapter> - - - - - - - - - - - - - - - - - getValue()

MockTempSensor<Sensor>

adapter<Adapter> - - - - - - - - - - - - - - - - - start() stop() getState()

MockHeaterActor<Actor>

sendMessage() askQuery()

<Adaptor>

sendMessage() askQuery()

HardwareAdaptor<Adaptor>Uses a

Controls a

sendMessage() askQuery()

<Adaptor>

sendMessage() askQuery()

HardwareAdaptor<Adaptor>

Bytestream

Bytestream

A mock instance

These interfaces enables mocking

A mock instance

Another possible mock instance

Another possible mock instance

public class MockHeaterActor implements Actor {

private boolean state = false;;

@Overridepublic void start() {

state = true;}@Overridepublic void stop() {

state = false;}@Overridepublic boolean getState() {

return state;}

}

public interface Actor {void start();void stop();boolean getState();

}

Page 166: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

RegulatorTest class

166

sensor<Sensor> actor<Actor>

Regulator

getValue()

<Sensor>

start() stop() - - - - - - - - - getState()

<Actor>

adapter<Adapter> - - - - - - - - - - - - - - - - - getValue()

MockTempSensor<Sensor>

adapter<Adapter> - - - - - - - - - - - - - - - - - start() stop() getState()

MockHeaterActor<Actor>

sendMessage() askQuery()

<Adaptor>

sendMessage() askQuery()

HardwareAdaptor<Adaptor>Uses a

Controls a

sendMessage() askQuery()

<Adaptor>

sendMessage() askQuery()

HardwareAdaptor<Adaptor>

Bytestream

Bytestream

A mock instance

These interfaces enables mocking

A mock instance

Another possible mock instance

Another possible mock instance

@Testpublic void testTemperatureBelowLowThresholdShouldStartHeater() {

// Arrange: Set up a regulator with a mocked sensor // and a mocked heaterdouble actualTemperature = 0.0f;Sensor temperatureSensor = new MockTempSensor(actualTemperature);

Actor heaterActor = new MockHeaterActor();

Regulator regulator = new Regulator(temperatureSensor,lowThreshold, heaterActor);

// Act: Run one round in regulator actionregulator.act();

// Assert that the heater has startedboolean heater = heaterActor.getState();assertTrue("Expect to have the heater on!", heater);

}

public interface Sensor {double getValue();

}public interface Actor {

void start();void stop();boolean getState();

}

Regulator

Page 167: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

• Project MockingHardwareMockito demo • Show: RegulatorTest.java• Show: Mocking on Sensor level and on Adapter

level

167

Page 168: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

TDDTraining

Mocking a Realworld Example

(with Mockito)Presentation provided by

Combitech JidokaQ

Page 169: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

Demo• Project MockingHardwareMockito demo

• Show: RegulatorMockitoTest.java• If time permits

• Show: RegulatorHysteresisTest.java

• Hysteresis Mock demo, to show arrays of test data-result vectors

169

Page 170: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

RaspBerry Example

170

communicator<Communicator>

Controllerconnection<Adapter> - - - - - - - - - - - - - - - - - - sendIOCommand(Command)

RealCommunicator<Communicator>

createUrl(Command)

URLCreator

establishConnection(Url) getResponse()

Connection http

RaspBerry

Sensors

Actors

TemperatureRegulator

Sends Command

sensor<Sensor> actor<Actor>

CommunicationFactorygetIOState(entity) setIOState(entity, direction, state) setIODirection(entity, direction, state) getADState(entityName) canMakeConnection()

<Communicator>

Has a

This interfaces enables mocking

A real or mock instance

Has a

CommandsCommands

This interfaces enables mocking

Page 171: Unit testing, Integration testing TDD (Test Driven ...ceres.hh.se/mediawiki/images/5/5f/DT8021_guest_lecture_slides_20… · Goals of todays presentation • Automated Testing Theory

• Project: RPi-Client-Full (Needs Raspberry and external hardware)

• Run se.combitech.regulator.TemperatureRegulator.java as an application.

171