Download - Test-Driven Development (TDD)
![Page 1: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/1.jpg)
SPL/2010SPL/2010
Test-Driven Development (TDD)
1
![Page 2: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/2.jpg)
SPL/2010SPL/2010 2
![Page 3: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/3.jpg)
SPL/2010SPL/2010
What is TDD?
3
changing code without modifying external functional behavior
![Page 4: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/4.jpg)
SPL/2010SPL/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
![Page 5: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/5.jpg)
SPL/2010SPL/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
![Page 6: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/6.jpg)
SPL/2010SPL/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
![Page 7: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/7.jpg)
SPL/2010SPL/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
![Page 8: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/8.jpg)
SPL/2010SPL/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
![Page 9: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/9.jpg)
SPL/2010SPL/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
![Page 10: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/10.jpg)
SPL/2010SPL/2010
Pseudocode exampleset_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
![Page 11: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/11.jpg)
SPL/2010SPL/2010
TDD = TFD+refactor
11
![Page 12: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/12.jpg)
SPL/2010SPL/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
![Page 13: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/13.jpg)
SPL/2010SPL/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
![Page 14: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/14.jpg)
SPL/2010SPL/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
![Page 15: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/15.jpg)
SPL/2010SPL/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
![Page 16: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/16.jpg)
SPL/2010SPL/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
![Page 17: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/17.jpg)
SPL/2010SPL/2010
JUnitJunit: 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
![Page 18: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/18.jpg)
SPL/2010SPL/2010
Example: Stack data object
18
![Page 19: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/19.jpg)
SPL/2010SPL/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
![Page 20: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/20.jpg)
SPL/2010SPL/2010
Interface
Turn Description into interface (formalize )
20
Javadoc: inline tag {@link URL}
![Page 21: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/21.jpg)
SPL/2010SPL/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
![Page 22: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/22.jpg)
SPL/2010SPL/2010
fill interface – what means to use a Stack?
● DBC: methods, preconditions, postconditions, invariants
22
![Page 23: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/23.jpg)
SPL/2010SPL/2010
test class● test-class skeleton for the interface
23
![Page 24: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/24.jpg)
SPL/2010SPL/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 <T>
● push a null - What should we do?● Change Stack API, - add Exception to push()● do not change interface - specify in Javadoc
expected behavior24
![Page 25: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/25.jpg)
SPL/2010SPL/2010
Implement tests● TFD: think of tests BEFORE implementing● define Stack<Integer>● assume "this.stack" is already
instantiated● add @Before method to create the stack
25
![Page 26: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/26.jpg)
SPL/2010SPL/2010
first tests
26
![Page 27: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/27.jpg)
SPL/2010SPL/2010 27
![Page 28: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/28.jpg)
SPL/2010SPL/2010
more complex tests
28
![Page 29: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/29.jpg)
SPL/2010SPL/2010 29
![Page 30: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/30.jpg)
SPL/2010SPL/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
![Page 31: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/31.jpg)
SPL/2010SPL/2010
Refactoring tests● test (positive) for push()
● pop() to test push() – circular● pop() changes the state of the stack
(removes top item)
31
![Page 32: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/32.jpg)
SPL/2010SPL/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
![Page 33: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/33.jpg)
SPL/2010SPL/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
![Page 34: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/34.jpg)
SPL/2010SPL/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
![Page 35: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/35.jpg)
SPL/2010SPL/2010 35
![Page 36: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/36.jpg)
SPL/2010SPL/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
![Page 37: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/37.jpg)
SPL/2010SPL/2010
● count() – add new query that indicates how many elements are stored in Stack
●
use to write post-conditionof 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
![Page 38: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/38.jpg)
SPL/2010SPL/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
![Page 39: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/39.jpg)
SPL/2010SPL/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
![Page 40: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/40.jpg)
SPL/2010SPL/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
![Page 41: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/41.jpg)
SPL/2010SPL/2010 41
![Page 42: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/42.jpg)
SPL/2010SPL/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
![Page 43: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/43.jpg)
SPL/2010SPL/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
![Page 44: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/44.jpg)
SPL/2010SPL/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
![Page 45: Test-Driven Development (TDD)](https://reader036.vdocuments.us/reader036/viewer/2022062410/56815c63550346895dca702a/html5/thumbnails/45.jpg)
SPL/2010SPL/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