Test Driven development - PowerPoint PPT Presentation

1 / 54
About This Presentation
Title:

Test Driven development

Description:

Test Driven development Tor St lhane * * * * * * * * * * * * * * * * * * Interaction assertion 2 A typical case where we would use an interaction assertion is as ... – PowerPoint PPT presentation

Number of Views:100
Avg rating:3.0/5.0
Slides: 55
Provided by: St214
Category:

less

Transcript and Presenter's Notes

Title: Test Driven development


1
Test Driven development
  • Tor Stålhane

2
What we will cover
  • We will cover three aspects of testing
  • Testing for green-field projects. This is TDD as
    it was originally understood and used.
  • Testing for changing legacy code
  • TDD and acceptance testing

3
Development and testing
  • From a TDD point of view, it is unreasonable to
    separate testing and implementation.
  • When we decide on a implementation strategy, we
    have also indirectly chosen a test strategy.
  • The reason for this is that we have to build
    tests for what we later will implement.

4
Why TDD
  • Important advantages of TDD are that it
    encourages
  • Writing clear requirements
  • Development in small steps. This will make
    debugging easier since we will have small code
    chunks to debug.
  • Minimalistic code and enforce the YAGNI principle
    You Aint Gonna Need It

5
Green field projects
6
What is a green field project?
  • A green field project is a project where we start
    out with a clean slate. We are thus free to
    select such things as programming language,
    architecture, development method and detailed
    design.
  • In reality, however, we are often bound by such
    things as company policy, available tools and
    methods and our knowledge and experience.

7
Where to start
  • TDD operates with four pairs of strategies which
    encompass testing and code. We will look at each
    pair in some detail.
  • Details vs. the big picture
  • Uncertain territory vs. the familiar
  • Highest values vs. the low-hanging fruits
  • Happy paths vs. error situations.

8
Details vs. the big picture
  • Start with the detailsSolve all the small
    problems before we combine them into a component
  • Start with the big pictureSolve the design
    problems e.g. component structure and then
    include all the details
  • In most cases, we will start with writing tests
    and then code for our greatest concerns.

9
Uncertain territory vs. the familiar 1
  • The question is about priorities
  • Exploring uncertain territory reduce risk.
  • The familiar what is best understood will in
    many cases bring larger user benefits faster.
  • We an thus look at this as a cost/benefit problem
    reduced risk vs. immediate benefits. We will
    write test and then code in a way that give us
    the best cost/benefit ratio

10
Uncertain territory vs. the familiar 2
  • The main principle is to postpone important
    decisions as long as possible but not longer.
  • In the mean time we should collect info, so as to
    have as much knowledge as possible when the
    decisions have to be made.

11
Uncertain territory vs. the familiar 3
p2
Earn N
Spend X
Wait
Lose M
1 - p2
p1
Earn N
Act now
Lose M
1 p1
12
Highest value vs. low-hanging fruits
  • This is a variation of the previous topic
    familiar vs. unknown and is thus also a
    cost/benefit question.
  • Going for the low-hanging fruits, we can
    demonstrate a lot of functionality early in the
    project without spending too many resources.
  • Since it is easier to write both tests and code
    for the low-hanging fruits, this is the popular
    alternative

13
Happy paths vs. error situations.
  • The choice between a happy path and an error
    situation is mostly an easy choice.
  • Even if the robustness requirements are extreme,
    we will first need tests and code that do
    something useful for the user.
  • There are exceptions situations where we will
    need the error handling quite early. A typical
    example is a log-on function where we need error
    handling like unknown user and wrong password
    right from the start.

14
Essential TDD concepts
  • We will walk through the following concepts
  • Fixtures
  • Test doubles
  • Guidelines for a testable design
  • Unit test patterns
  • Legacy code

15
Fixtures
  • A fixture is a set of objects that we have
    instantiated for our tests to use.
  • This, a fixture is a piece of code that we want
    to test.

16
Test Doubles - 1
  • A test double is an object stand-in. Typical
    features are that it
  • Looks like the real thing from the outside
  • Execute faster
  • Is easier to develop and maintain
  • Test doubles are used for two types of testing
  • State based testing
  • Interaction based testing

17
Test Doubles - 2
  • We can sum up state based and interaction based
    testing in that we use
  • Interaction based testing to verify how an object
    talks to its collaborators. Am I using the
    objects around me correctly?
  • State based testing to test how well the object
    listens. Am I responding correctly to the input
    and responses that I get from others?

18
Test Doubles 3
  • We have three types of test doubles
  • Stubs the simplest possible implementation of an
    interface
  • Fakes more sophisticated than a stub e.g. an
    alternative, simpler implementation
  • Mocks more sophisticated than a fake. It can
    contain
  • Assertions
  • The ability to return hard coded values
  • A fake implementation of the logic

19
Why use test doubles 1
  • Important reasons
  • Can test an object without writing all its
    environment
  • Allows a stepwise implementation as we
    successively replace more and more doubles
  • When something is wrong we can be almost sure
    that the problem is in the new object and not in
    its environment.

20
Why use test doubles 2
21
Unit-testing patterns 1
  • The most important unit test patters are
    assertion patters. A typical example is shown
    below.
  • public static void assertEquals(java.lang.Stri
    ng expected,
  • java.lang.String actual
    )
  • Asserts that two strings are equal. Throws an
    AssertionFailedError if not.

22
Unit-testing patterns 2
  • Sourceforge uses six basic assertions
  • assertFalse. Check that the condition is false
  • assertTrue. Check that the condition is true
  • assertEquals. Check that two parameters are
    equal.
  • assertNotEquals. Check that two parameters are
    not equal.
  • assertNotSame. Check that two objects do not
    refer to the same object
  • fail. Fail a test

23
Unit-testing patterns 3
  • In the general case, an assertion should be
    placed
  • As close as possible to the new code for
    instance right after the last statement.
  • Right after each important new chunk of code.
  • The intention is to discover any error as soon as
    possible in order to reduce the debugging effort

24
Unit-testing patterns 4
  • It is important to discover any error as soon as
    possible. By doing this we have less code to go
    through in order to find the cause of the error.
  • In order to achieve this, we need assertions
    whenever we want to check that we are on the
    right course.

25
Assertion types
  • An assertions type depends on its usage. The
    most important types are
  • Resulting state assertion
  • Guard assertion
  • Delta assertion
  • Custom assertion
  • Interaction assertion

26
Resulting state assertion
  • The main idea here is to
  • Execute some functionality
  • Check that the resulting state is as expected.
    This is done using one or more assertions most
    often assertEquals assertions.

27
Guard assertion
  • The guard assertion is used to check that our
    assumptions of what the status is before
    executing the new code is correct. E.g.
  • assertTrue(java.lang.String message,
  • boolean condition)
  • New code to be tested
  • assertNotSame(java.lang.Object expected,
  • java.lang.Object actua
    l)

28
Delta assertion 1
  • A delta assertion is an assertion where we,
    instead of checking an absolute value, checks the
    expected delta change of the value. This has
    at least two advantages
  • We do not need a magic number in the test.
  • The test will be more robust to changes in the
    code.

29
Delta assertion 2
  • test_var_1 current value
  • new code which, among other things, increase the
    current value by x
  • assertEquals(test_var_1, test_var_1 x)
  • This assertion will hold whatever value we have
    for test_var_1.

30
Custom assertion 1
  • Custom assertion covers a wide range of
    customized assertion patterns also called
    fuzzy assertions.
  • Con they have to be tailored to the assertion
    that we want to make.
  • Pro
  • They can cover a wide range of important test
    situations.
  • Over time we can build up a library of custom
    assertions thus reducing the need for writing new
    ones.

31
Custom assertion 2
  • In most cases we can obtain the custom assertion
    effect by using more complex predicates and
    expressions in the usual assertions. However, the
    custom assertion will enable better error
    handling and allow more informative error
    messages.

32
Custom assertion example
  • custom_assertInrange(in_value,
  • message)
  • assertTrue(message, (in_value lt max)
    (in_value gt min))
  • As the conditions get more complex, the custom
    assertion becomes a more attractive alternative

33
Interaction assertion 1
  • The interaction assertion does not check that our
    code works as expected.
  • Its role is to check that our code cooperate with
    our collaborator objects as expected.
  • This can be done using any of the assertion
    patterns that we have discussed earlier, e.g.
    assertFalse, assertSame, assertEquals or
    assertTrue.

34
Interaction assertion 2
  • A typical case where we would use an interaction
    assertion is as follows
  • We download a freeware component plus some
    documentation.
  • Based on the documentation we believe that if we
    do A then the component will return B.
  • Use an assertion to check if this is true.

35
Keep or throw away 1
  • We need to decide whether we want to keep the
    assertion in the production code or not.
  • Pro keeping itWill quickly diagnose new errors.
  • Con keeping itMay need updates when the code is
    changed, e.g. during maintenance

36
Keep or throw away 2
  • The decision may vary depending on the assertion
    pattern used.
  • E.g. the delta pattern and the custom pattern
    will be more robust against code changes than for
    instance the resulting state pattern, especially
    if it contains one or more magic numbers.

37
Legacy code
38
Legacy code 1
  • Much of the development done may be even most
    of the development done is changing an existing
    code base.
  • TDD assumes that we write tests, then write code
    and then run the tests. This approach is not
    useful for legacy code and we cannot use TDD
    directly as described earlier.

39
Legacy code 2
  • The following process should be used
  • Identify the change point in the legacy code
  • Identify an inflection point
  • Cover the identified inflection point
  • Break internal dependencies
  • Break external dependencies
  • Write tests
  • Make changes
  • Refactor covered code

40
Legacy code 3
  • Note that the test in step 3 on the previous
    slide are not tests to check your changes.
  • These tests are called characterization tests.
    Their purpose is to help you understand the
    behavior of the current code. We could thus apply
    interaction assertion patterns even if there may
    be no real interactions

41
Inflection points 1
  • An inflection point also called a test point
    is defined as follows
  • An inflection point is a point downstream from
    the change point in your code where you can
    detect any change in the codes behavior relevant
    to your changes.
  • Everything else considered equal, we will prefer
    an inflection point as close as possible to the
    change point.

42
Inflection points 2
  • We will use a remote inflection point if we e.g.
    are concerned with side effects from our changes.
    The side effects may show up only late in the
    execution and thus a distant inflection point
    will be a better solution.

43
Test and change
  • As we change the legacy code we will use both the
    characterization tests and the new-code tests.
  • New code tests to check that our changes have the
    intended effect
  • Characterization tests to check that we o not
    break any of the behavior that we want to keep.

44
Acceptance testing
45
The TDD acceptance testing process
46
TDD acceptance testing
  • We will look in more details on the three first
    steps of the process
  • Pick a user story
  • Write tests for the story
  • Automate tests

47
Pick a user story 1
  • We have already partly covered this in an earlier
    section Where to start. Thus, in many cases,
    the user stories already are prioritized.
  • Otherwise, the user stories should be prioritized
    based on
  • Business value what is it worth to the
    customer.
  • Technical risk how difficult is it to
    implement.

48
Pick a user story 2
  • More formally, we can use business value and
    technical risk to assess the leverage of each
    user story
  • Leverage
  • (Business value Tech. risk) / Tech. risk

49
Pick a user story 3
  • When we reach this stage in system development,
    developers, testers and customers already have
    had a lot of informal discussions on what the
    customer needs, when and why.
  • This knowledge will be included in the decision
    of which user story to pick next.

50
Write tests for the story 1
  • One common way to do this is as follows
  • Sit down with the customer and describe the most
    important scenarios for this user story.
  • Reach an agreement on what functionality needs to
    be implemented in order to realize each scenario.

51
Write tests for the story 2
  • The results of the process described on the
    previous slide are
  • A set of well defined tests a testing plan for
    the user story
  • Expected results acceptance criteria for each
    test. This must include both
  • Expected output
  • Expected new system state

52
Automate the tests
  • How to automate tests will depend on the tools
    used. A the present, it seems that table
    presentation ala FITNESS are much used. In all
    cases we need
  • Id of function to be tested
  • Input parameters
  • Expected result
  • See also the earlier FITNESS presentation

53
Summing up
  • The most important thing to remember about TDD is
    that the concept contains both testing and
    development.
  • This does not imply that we must use an agile
    development process.
  • However, it implies that we must consider
    implementation and testing as two parallel
    activities we cannot ignore one and only focus
    on the other.

54
Acknowledgement
  • Most of the content of these slides are taken
    from chapters 4 and 5 in the book Test Driven
    by L. Koskella.
  • More on assertions can be found at
  • http//junit-addons.sourceforge.net/junitx/framewo
    rk/Assert.html
Write a Comment
User Comments (0)
About PowerShow.com