§TDD training
1. Overview
2. Fixtures
3. Assertion patterns
4. Test quality
5. Case study
Agenda
§Motivation
The Real Life Software Challenge
Disadvantages Technical Debt
Traditional form of development
Requirements Code Test
Motivation - solving the right problem right
Creating poorly written code
 High defect rates
 Defects make systems unstable, unpredictable, unusable
 Cost of fixing defects caught during testing is typically a
magnitude or two higher than those caught when
introduced into the code base
Motivation - solving the right problem right
 Lack of maintainability
 Code difficult to understand and change
 Break functionality elsewhere in the system
 Duplication
Failing to meet actual client needs!
Test-Driven Development
 Learn how to build the thing right - TDD - internal
quality
 Learn how to build the right thing - Acceptance TDD -
external quality
Builditright - TDD
Buildtheright thing: acceptance TDD
§What is TDD?
TDD Cycle
Recommendations
• Do not skip refactoring
• Get to green fast
• Slow down after a mistake
FIRST
Fast – run (subset of) tests quickly
Isolated – no tests depend on others
Repeatable – run N times, get same result
Self-validating – tests can automatically detect if passed
Timely – written about the same time as code under test
How to select the next test
• Going for the highest value vs picking the low-hanging fruit first
• Treading the happy path first vs starting with handling error situations
• Diving first into details vs starting with the big picture
• Exploring uncertain territory vs sticking with the familiar and comfortable
Implementation strategies
• Faking it - fake a particular functionality to get back to green
• Triangulation - each of the tests constrains the available solution space to one
dimension, thus they narrow down (”triangulate”) the solution
• Obvious implementation
AAA Test Format
@Test
public void sizeOfListReflectsItemsAddedToIt() throws Exception {
List<String> list = new ArrayList<String>(); ARRANGE
list.add("something"); ACT
assertEquals(1, list.size()); ASSERT
}
Exercise 1 – Tax Calculator
Given an amount of taxable income, calculate the net
pay according to the following rules:
• First £11,500 are tax-free
• 20% for £11,500 to £45,000
• 40% for £45,000 to £150,000
• 45% for over £150,000
§
Fixtures
Fixtures
A fixture is a fixed state of a set of objects used as a baseline for running tests.
Useful to:
• Remove duplication
• Allow for more focused tests
Used for state-based tests.
Test doubles
Are objects that stand in for the real thing. They pretend to be something
they’re not, so that the client has no idea, and they typically do it faster than
the real thing.
Dummy A null or dummy object to be used as parameter value when test
doesn’t care
Stub Class with test-specific implementation (hard-coded responses)
Fake A full implementation for test purposes (e.g. in-memory
database)
Mock An interface with expectations set for the test (implementation
generated at runtime by mocking framework) – interaction-
based test
Parameterized creation pattern
Hides the non-important attributes from the setup by extracting the object
creation into a separate creation method, which takes the variable attributes as
arguments and populates the non-important ones with constant or random
values. Our test will populate only the important attributes.
Object mother pattern
Is a sophisticated object factory that provides access to a complete object graph
of valid domain objects, including instances in different states.
- Makes it easy for new developers to write tests
- Powerful when integrated with personas
§
Assertion patterns
Resulting-State Assertion
Exercise some functionality on the fixture objects and afterward assert that the
internal state of the fixture objects match our expectations.
@Test
public void sizeOfListReflectsItemsAddedToIt() throws Exception {
List<String> list = new ArrayList<String>();
list.add("something");
assertEquals(1, list.size()); // state verification
}
Guard Assertion
Make explicit the assumptions made about the fixture right before invoking the
functionality we want to test.
@Test
public void listIsNoLongerEmptyAfterAddingAnItemToIt() throws Exception {
List<String> list = new ArrayList<String>();
assertTrue(list.isEmpty()); // guard assertion
list.add("something");
assertFalse(list.isEmpty()); // state verification
}
Delta Assertion
Test that the difference(delta) between the initial and after states is what we
expect.
private ArrayList<String> list;
@Test
public void sizeOfListReflectsItemsAddedToIt() throws Exception {
int sizeBefore = list.size(); // record the "before" state
list.add("something");
assertEquals(sizeBefore + 1, list.size()); // delta verification
}
Custom Assertion
When the amount of code verifying our expectations vastly exceeds the amount
of code required to invoke the code under test, extract it from the test in order
to encapsulate complex verification logic.
@Test
public void timeslotsAreOnWeekdays() throws Exception {
MeetingCalendar calendar = new MeetingCalendar();
Date time = calendar.nextAvailableStartingTime();
assertIsDuringOfficeHoursOnWeekday(time);}
private void assertIsDuringOfficeHoursOnWeekday(Date time) { … }
Interaction Assertion
Verify that our code
interacts with its
collaborator objects
as we expect it to.
Exercise 2 – Word Wrapper
Develop a word-wrapping algorithm, which is given a string and
a row-length, it returns a list of word-wrapped-rows.
Examples of behaviour:
• If the row-length is 60, and the input string is 30, the result is
just the input string
• If the row-length is 3, and the input string is "abc def" the
result is "abc", "def”
• If the row-length is 3, and the input string is "abcdef" the
result is "abc", "def”
• If the row-length is 3, and the input string is "abcdef abc" the
result is "abc", "def", "abc”
• With row length 3 and "a b c d e f" the result is "a b", "c d",
"e f"
§
Are my tests good quality?
Mutation testing
Principle: change (mutate) certain statements in the source code and check if the
test cases are able to find the errors
- Mutant generation is time-consuming and difficult, so it was automated
- If the tests detect the mutant, then it’s ‘killed’
- Surviving mutants show not tested cases
mutation score = number of mutants killed / total number of mutants
Mutation testing types
Value Mutations: values of primary parameters are modified (e.g. change constants)
Decision Mutations: change decisions/conditions to check for design errors (e.g.
arithmetic, logical or relational operators)
Statement Mutations: changes done to the statements by deleting or duplicating the
line (e.g. copy/paste)
§
How effective is TDD?
Case Study
Participants
 1 development team from IBM
 3 development teams from Microsoft
IBM Team
 Products: device drivers
 Legacy product
 New product using a new platform
 Comparison between 7th release of legacy product and 1st
release of new product
 The two products exposed the same interfaces for the same set
of devices
Microsoft Teams
 Products: Windows, MSN, Visual Studio
 Windows: Networking team - networking common library written as
a reusable set of modules for different projects
 MSN: Web services application
 Developer Division: part of the Visual Studio (VS) software
development system
Metrics IBM
(legacy+new)
Ms Windows Ms MSN Ms Vista
Defect density not
using TDD
w x y z
Defect density using
TDD
0.6w 0.38x 0.24 y 0.19z
Increase in time to
code
15-20% 25-35% 15% 25-20%
Study Results
Exercise 3 – Berlin Clock
- the top yellow lamp blinks to
show seconds - on for even
seconds and off for odd seconds
- the next two rows represent
hours
- the upper row has 5 hour blocks
and is made up of 4 red lamps
- the lower row has 1 hour blocks
and is also made up of 4 red
lamps
- the final two rows represent the
minutes
- the upper row has 5 minute
blocks, and is made up of 11
lamps, every 3rd lamp is red, the
rest are yellow
- the bottom row has 1 minute
blocks, and is made up of 4
yellow lamps
TDD Advantages
TDD
Encourages
good design
Prevents over-
engineering
because of flawed
assumptions
Documents how
the code is
intended to work
Gradually
enhances a
working product
Enables effective
learning through early
feedback from client
Less time spent
fixing defects
Produces
testable code
Reduces bugs
with up to 90%
References
References
• https://people.engr.ncsu.edu/gjin2/Classes/5
91/Spring2017/case-tdd-b.pdf
• http://junit.org/junit5/docs/current/user-
guide/
• http://www.guru99.com/mutation-
testing.html
§
Thanks!

TDD Training

  • 1.
  • 2.
    1. Overview 2. Fixtures 3.Assertion patterns 4. Test quality 5. Case study Agenda
  • 3.
  • 4.
    The Real LifeSoftware Challenge Disadvantages Technical Debt Traditional form of development Requirements Code Test
  • 5.
    Motivation - solvingthe right problem right Creating poorly written code  High defect rates  Defects make systems unstable, unpredictable, unusable  Cost of fixing defects caught during testing is typically a magnitude or two higher than those caught when introduced into the code base
  • 6.
    Motivation - solvingthe right problem right  Lack of maintainability  Code difficult to understand and change  Break functionality elsewhere in the system  Duplication Failing to meet actual client needs!
  • 7.
    Test-Driven Development  Learnhow to build the thing right - TDD - internal quality  Learn how to build the right thing - Acceptance TDD - external quality
  • 8.
    Builditright - TDD Buildtherightthing: acceptance TDD
  • 9.
  • 10.
  • 11.
    Recommendations • Do notskip refactoring • Get to green fast • Slow down after a mistake
  • 12.
    FIRST Fast – run(subset of) tests quickly Isolated – no tests depend on others Repeatable – run N times, get same result Self-validating – tests can automatically detect if passed Timely – written about the same time as code under test
  • 13.
    How to selectthe next test • Going for the highest value vs picking the low-hanging fruit first • Treading the happy path first vs starting with handling error situations • Diving first into details vs starting with the big picture • Exploring uncertain territory vs sticking with the familiar and comfortable
  • 14.
    Implementation strategies • Fakingit - fake a particular functionality to get back to green • Triangulation - each of the tests constrains the available solution space to one dimension, thus they narrow down (”triangulate”) the solution • Obvious implementation
  • 15.
    AAA Test Format @Test publicvoid sizeOfListReflectsItemsAddedToIt() throws Exception { List<String> list = new ArrayList<String>(); ARRANGE list.add("something"); ACT assertEquals(1, list.size()); ASSERT }
  • 16.
    Exercise 1 –Tax Calculator Given an amount of taxable income, calculate the net pay according to the following rules: • First £11,500 are tax-free • 20% for £11,500 to £45,000 • 40% for £45,000 to £150,000 • 45% for over £150,000
  • 17.
  • 18.
    Fixtures A fixture isa fixed state of a set of objects used as a baseline for running tests. Useful to: • Remove duplication • Allow for more focused tests Used for state-based tests.
  • 19.
    Test doubles Are objectsthat stand in for the real thing. They pretend to be something they’re not, so that the client has no idea, and they typically do it faster than the real thing. Dummy A null or dummy object to be used as parameter value when test doesn’t care Stub Class with test-specific implementation (hard-coded responses) Fake A full implementation for test purposes (e.g. in-memory database) Mock An interface with expectations set for the test (implementation generated at runtime by mocking framework) – interaction- based test
  • 20.
    Parameterized creation pattern Hidesthe non-important attributes from the setup by extracting the object creation into a separate creation method, which takes the variable attributes as arguments and populates the non-important ones with constant or random values. Our test will populate only the important attributes.
  • 21.
    Object mother pattern Isa sophisticated object factory that provides access to a complete object graph of valid domain objects, including instances in different states. - Makes it easy for new developers to write tests - Powerful when integrated with personas
  • 22.
  • 23.
    Resulting-State Assertion Exercise somefunctionality on the fixture objects and afterward assert that the internal state of the fixture objects match our expectations. @Test public void sizeOfListReflectsItemsAddedToIt() throws Exception { List<String> list = new ArrayList<String>(); list.add("something"); assertEquals(1, list.size()); // state verification }
  • 24.
    Guard Assertion Make explicitthe assumptions made about the fixture right before invoking the functionality we want to test. @Test public void listIsNoLongerEmptyAfterAddingAnItemToIt() throws Exception { List<String> list = new ArrayList<String>(); assertTrue(list.isEmpty()); // guard assertion list.add("something"); assertFalse(list.isEmpty()); // state verification }
  • 25.
    Delta Assertion Test thatthe difference(delta) between the initial and after states is what we expect. private ArrayList<String> list; @Test public void sizeOfListReflectsItemsAddedToIt() throws Exception { int sizeBefore = list.size(); // record the "before" state list.add("something"); assertEquals(sizeBefore + 1, list.size()); // delta verification }
  • 26.
    Custom Assertion When theamount of code verifying our expectations vastly exceeds the amount of code required to invoke the code under test, extract it from the test in order to encapsulate complex verification logic. @Test public void timeslotsAreOnWeekdays() throws Exception { MeetingCalendar calendar = new MeetingCalendar(); Date time = calendar.nextAvailableStartingTime(); assertIsDuringOfficeHoursOnWeekday(time);} private void assertIsDuringOfficeHoursOnWeekday(Date time) { … }
  • 27.
    Interaction Assertion Verify thatour code interacts with its collaborator objects as we expect it to.
  • 28.
    Exercise 2 –Word Wrapper Develop a word-wrapping algorithm, which is given a string and a row-length, it returns a list of word-wrapped-rows. Examples of behaviour: • If the row-length is 60, and the input string is 30, the result is just the input string • If the row-length is 3, and the input string is "abc def" the result is "abc", "def” • If the row-length is 3, and the input string is "abcdef" the result is "abc", "def” • If the row-length is 3, and the input string is "abcdef abc" the result is "abc", "def", "abc” • With row length 3 and "a b c d e f" the result is "a b", "c d", "e f"
  • 29.
    § Are my testsgood quality?
  • 30.
    Mutation testing Principle: change(mutate) certain statements in the source code and check if the test cases are able to find the errors - Mutant generation is time-consuming and difficult, so it was automated - If the tests detect the mutant, then it’s ‘killed’ - Surviving mutants show not tested cases mutation score = number of mutants killed / total number of mutants
  • 31.
    Mutation testing types ValueMutations: values of primary parameters are modified (e.g. change constants) Decision Mutations: change decisions/conditions to check for design errors (e.g. arithmetic, logical or relational operators) Statement Mutations: changes done to the statements by deleting or duplicating the line (e.g. copy/paste)
  • 32.
  • 33.
    Case Study Participants  1development team from IBM  3 development teams from Microsoft
  • 34.
    IBM Team  Products:device drivers  Legacy product  New product using a new platform  Comparison between 7th release of legacy product and 1st release of new product  The two products exposed the same interfaces for the same set of devices
  • 35.
    Microsoft Teams  Products:Windows, MSN, Visual Studio  Windows: Networking team - networking common library written as a reusable set of modules for different projects  MSN: Web services application  Developer Division: part of the Visual Studio (VS) software development system
  • 36.
    Metrics IBM (legacy+new) Ms WindowsMs MSN Ms Vista Defect density not using TDD w x y z Defect density using TDD 0.6w 0.38x 0.24 y 0.19z Increase in time to code 15-20% 25-35% 15% 25-20% Study Results
  • 37.
    Exercise 3 –Berlin Clock - the top yellow lamp blinks to show seconds - on for even seconds and off for odd seconds - the next two rows represent hours - the upper row has 5 hour blocks and is made up of 4 red lamps - the lower row has 1 hour blocks and is also made up of 4 red lamps - the final two rows represent the minutes - the upper row has 5 minute blocks, and is made up of 11 lamps, every 3rd lamp is red, the rest are yellow - the bottom row has 1 minute blocks, and is made up of 4 yellow lamps
  • 38.
    TDD Advantages TDD Encourages good design Preventsover- engineering because of flawed assumptions Documents how the code is intended to work Gradually enhances a working product Enables effective learning through early feedback from client Less time spent fixing defects Produces testable code Reduces bugs with up to 90%
  • 39.
  • 40.
  • 41.