Presentation is loading. Please wait.

Presentation is loading. Please wait.

SPL/2010 Test-Driven Development (TDD) 1. SPL/2010 2.

Similar presentations


Presentation on theme: "SPL/2010 Test-Driven Development (TDD) 1. SPL/2010 2."— Presentation transcript:

1 SPL/2010 Test-Driven Development (TDD) 1

2 SPL/2010 2

3 What is TDD? 3 changing code without modifying external functional behavior

4 SPL/2010 What is programming? writing code: addressing requirements/solve a problem verify: code answers requirements / program performs according to specifications requirement/specification/verification: complex problem is broken in small problems – can be solved by writing short pieces of code specify (define) and verify small pieces of code 4

5 SPL/2010 What is Development? as we develop more, we understand better… developer asks better questions, and gets better answers requirements of program change over time existing code must be changed... difficult to predict how other parts of the code are affected 5

6 SPL/2010 What is Testing? correctness – code performs by specification 3 types of tests: Unit tests: a particular module is working properly: – Implemented by the programmer. – Simple test cases for all functions and methods. A test case is a program… Integration tests: a combination of modules work well together and exchange messages according to protocols Acceptance tests: a whole system under test to check that the expected functionality meets the requirements – functional and performance criteria. 6

7 SPL/2010 Unit Test Terminology Test case: tests a single scenario of usage. one aspect of the protocol of the object: its invariant, a single pre-condition / post-condition. Test suite: collection of test cases that fully verify the public protocol published by an object Object under test (OUT): the object being tested by a test suite test suite should focus on testing a single object - assuming all other objects perform correctly 7

8 SPL/2010 Unit Test Terminology Test coverage: the part of the code of the object that is executed by running a test suite every code line of OUT should be executed when running test suite Test fixture: other objects that will interact with the OUT A test case must be self-contained: create, initialize and set all the required test fixtures before the test scenario can be executed. Test fixtures must be cleaned up after the test case is run. Mockup: a basic, test-specific, implementation for classes on which OUT depends. OUT is independent of other objects - avoid using existing objects mockup and the "real" object will usually satisfy the same interface Usually: mockup for data-retrieval, not for logical behavior 8

9 SPL/2010 Unit Test Terminology Positive test case: verifies that a public operation of the OUT performs as expected. Negative test case: verifies that a public operation of the OUT fails as expected – a call to a method when a pre-condition does not hold properly throws an exception Repeatable and deterministic tests: runs the same test twice in a row - same result. test case cannot depend on external data or on the timing of RTE scheduler 9

10 SPL/2010 Pseudocode example set_hour (a_hour: INTEGER) -- Set `hour' to `a_hour' require valid_argument: 0 <= a_hour and a_hour <= 23 do hour := a_hour ensure hour_set: hour = a_hour end 10 precondition postcondition

11 SPL/2010 TDD = TFD+refactor 11

12 SPL/2010 What is TDD? Test first design - repeatedly first writing a test case and then implementing the code necessary to pass the test. It is the responsibility of the programmer to define the unit tests as part of the code delivery requirements granularity level of the module module depends on other modules 12

13 SPL/2010 What is TDD? requirements on the code by writing a test test case IS the expression of the requirement implement code to stand by the requirements code pass tests 13

14 SPL/2010 Test First Design cycle Define objects: responsible for specific functionality and interaction Write tests for each OUT: Define the interface of the OUT Define contract for each method of the OUT interface Specify pre-conditions, post-conditions for each method and invariant for the OUT. Write test cases for each invariant, pre and post-condition of each method in the interface. Write the code so it will pass the test Run tests Refactor! improve code design by removing code that "looks bad ("code smells) Repeat process: code changes, rules change, test change When needed - Break the contract, Redefine tests, Refactor code 14

15 SPL/2010 Design By Contract (DBC) Concept that helps programmers express the requirements on an object, correctness criteria: preconditions : things that must be true before we invoke a method postconditions : things that must be true after a method is invoked invariants: things that must be true both before and after a method is invoked 15

16 SPL/2010 TDD benefits validation of correctness: errors caused by code/design modifications are caught quickly by programmer, immediately after the code is changed. courage to make code modifications and refactoring, a change will "break" the program. integration tests - test cases can help design intelligent integration tests. design improvement- writing tests before the OUT is implemented ensures OUT is indeed usable, that it is easy to prepare the context in which the OUT can be invoked. E.g.: OUT depends on too many other objects or global objects, - writing tests becomes very difficult - test cases reveal this - strong incentive to improve the design of the OUT documentation - test classes provide examples of code usage 16

17 SPL/2010 JUnit Junit: a simple framework to write tests (in Eclipse) public default ctor setUp() - prepare pre-conditions (@Before) tearDown() - "clean up" the test object after a test has run (@After), "undoes" what the @Before method did. test method for each test case (@Test) JUnit run: instance of the test class is constructed. run setUp() run test case display test results (pass/fail) run tearDown() 17

18 SPL/2010 Example: Stack data object 18

19 SPL/2010 TDD Requirement: write a simple Stack data object, what is a "Stack"? informal description: Stack is a container of Objects. Objects are ordered in Last-In-First-Out order. Add/Remove an Object to Stack 19

20 SPL/2010 Interface Turn Description into interface (formalize ) 20 Javadoc: inline tag {@link URL}

21 SPL/2010 Generics it is a "code smell", to let a container receive any object (too general)… Object = haven't thought enough about specific objects 21

22 SPL/2010 fill interface – what means to use a Stack? DBC: methods, preconditions, postconditions, invariants 22

23 SPL/2010 test class test-class skeleton for the interface 23

24 SPL/2010 define tests think of complicated scenarios/ usage: parameters, exceptions, return values think of complicated behavior/sequences: – push-pop-pop, pop-Exception – isEmpty returns true or false, – push objects of different types push a null - What should we do? Change Stack API, - add Exception to push() do not change interface - specify in Javadoc expected behavior 24

25 SPL/2010 Implement tests TFD: think of tests BEFORE implementing define Stack assume "this.stack" is already instantiated add @Before method to create the stack 25

26 SPL/2010 first tests 26

27 SPL/2010 27

28 SPL/2010 more complex tests 28

29 SPL/2010 29

30 SPL/2010 implement Stack interface write minimum! code to pass tests if no test fails, we don't need to write code passing code is valid Stack implementation. additional classes require their test cases Tip: override (and test) toString method, for all classes 30

31 SPL/2010 Refactoring tests test (positive) for push() pop() to test push() – circular pop() changes the state of the stack (removes top item) 31

32 SPL/2010 Refactoring tests Weak pop() test: - push an item and pop without exception Better test: returns last element pushed on the stack; stack has one element less … a copy of testPush() - one test for two functions …complex post-conditions - rethink! - analyze contract of pop() pop() does 2 things: removes an item from the stack returns the value of this item. design (if possible) methods to do one thing - reusable, testable. 32

33 SPL/2010 Refactoring tests: 6 principles for writing testable interfaces 1. Separate commands and queries: Queries return a value and do not change the visible state of the object – methods with side-effect on the object - push() Commands change the internal state of the object and do not return values – functions that only get information - isEmpty() 33

34 SPL/2010 Refactor pop() pop() does not stand by this rule: it is neither a command nor a query replace pop() with primitive methods: top() returns the value of the top object remove() removes top object from the stack keep pop(): T pop() { T top = top(); remove(); return top; } 34

35 SPL/2010 35

36 SPL/2010 2. Separate Basic Queries from Derived Queries Is this test strong enough? What could go wrong? Change hats: assume person writing the code tries to pass the test with minimal effort push=replace testStackLIFO – 3 item stack 36

37 SPL/2010 count() – add new query that indicates how many elements are stored in Stack use to write post-condition of push(), remove() @pre(count()) - refer to value of count() before command is executed isEmpty(): count()==0 count() - primitive query isEmpty() - derived query post-condition computed based on primitive query 37

38 SPL/2010 2. Separate basic and derived queries Derived queries can be specified in terms of basic queries. 3. Define derived queries in terms of basic queries Define the post-conditions of derived queries in terms of basic queries only 38

39 SPL/2010 4. For each basic command, write post-conditions that specify values of basic queries a command modifies the state of OUT test modification, with basic queries: review post-conditions of command by available basic queries of object if no basic queries is affected – extend/revise interface isEmpty() is a derived query (count()) – can be removed 39

40 SPL/2010 Refactor remove() contract encoded in the pre, post-conditions remove() removes one element from stack cannot call when the stack is empty. WHICH element is removed (top)? more specific contract basic observe query 40

41 SPL/2010 41

42 SPL/2010 Did this make our post-condition for remove() stronger? count() has been decreased by one Do we need to check that the last element is the one that is removed? itemAt for all values of i=1 to new count() are not affected Did itemAt() break encapsulation? stack limit access to only the top element 42

43 SPL/2010 5. For each basic command and query, express pre-conditions in terms of basic queries reminder: basic queries are sufficient to capture post-conditions of basic commands 43

44 SPL/2010 6. Specify class invariants that impose always true constraints on basic queries class invariants: properties that remain true in all legal states: @inv count() >= 0 verify contract of commands that affect count() cannot break this invariant. remove() : verify that the pre-condition prevents count() from changing from 0 to -1 44

45 SPL/2010 Summary specify the interface of objects before implement interface specification includes contract for methods, expressed in terms of @pre, @post and @inv conditions. write tests for interface to verify contract is enforced before implementation design objects interface to be testable: Separate commands and queries. Separate basic queries and derived queries. Define derived queries in terms of basic queries. For each basic command, write post-conditions that specify values of basic queries For each basic command and query, express the pre-conditions in terms of basic queries. Specify class invariants that impose always true constraints on basic queries 45


Download ppt "SPL/2010 Test-Driven Development (TDD) 1. SPL/2010 2."

Similar presentations


Ads by Google