February 15, 2016

Test-Driven Development
(aka TDD)

Overview

  • Some jibber jabber about quality
  • Introduction to TDD
  • Hands-on TDD exercise

♡1♡♡♡1♡♡♡11♡1111♡11♡111♡♡♡1♡♡111♡111♡1♡♡♡♡1♡♡♡♡♡♡11♡♡♡1♡♡11♡♡1♡1♡♡1♡♡♡♡♡♡11♡11♡♡♡11♡♡♡♡1♡1111♡1♡♡1111♡♡1♡♡1♡11♡♡♡♡1♡♡♡♡♡♡111♡1♡♡♡11♡♡1♡1♡111♡♡11♡111♡1♡♡♡♡1♡♡♡♡♡♡1111♡♡1♡11♡1111♡111♡1♡1♡111♡♡1♡♡♡1♡♡♡♡♡♡11♡♡♡11♡11♡1111♡11♡♡1♡♡♡11♡♡1♡1♡♡1♡♡♡♡1

Back in the 1980s Ford Motor Co. had a marketing slogan: “Quality Is Job Done.”

...  all American cars of 1980s and 90s vintage were junk

Japanese auto makers soon took center stage in car quality and thus sales

Have you ever been in the following scenario

  • finish a task, which you consider is DONE

  • merge code into dev branch, send build to QA

  • they come back with a problem

  • you rejoice: "that an easy fix, just a null check and it's DONE"

Quality = \frac{\text{Result of work efforts}}{\text{Total costs}}
Quality=Result of work effortsTotal costsQuality = \frac{\text{Result of work efforts}}{\text{Total costs}}
  • When organisations focus primarily on quality, defined by the following ratio:

Then quality tends to increase and costs fall over time.

  • However, when organizations focus primarily on costs, costs tend to rise and quality declines over time

he taught Japan’s top management how to improve design and product quality

  • Your individual definition of DONE, has a direct impact on the overall product quality
  • The values you code by everyday, have a direct impact on your team and eventually on your company

you might have heard the phrase, "in this company we do things this way"! That's the way of the people, which becomes the way of the company

Could you say "assuring code quality is deeply rooted in my everyday process"?

Traditional cost of change curve

Augmented traditional cost of change curve, IBM

Kent Beck's cost of change curve, with the TDD approach

The social duty of a developer is to build quality products, therefore test your code and make everybody's life better

Young K was working on a high school project

But he made a bit of a mess ...

... by not working incrementally

He could have definitely done better!

... by knowing about a structure which helps to "do right thing" / "build the code right"

TDD is such a structure

Basic TDD rules

  1. Maintain a set of automated tests
  2. Only add production code once there is a test that requires that code
  3. Only refactor code when all of the tests are passing
  4. Never go more than a few minutes without all of the tests passing again

The TDD Cycle

Write a failing test

Watch the test fail

Write just enough code to make it pass

Watch the test pass

Fix the design (code and test)

Ensure that all tests still pass

A closer look

Minute-by-minute cycles:

Per-task cycles:

  • Integrate new code and tests
  • Re-run all tests in the codebase to ensure the new code does not break them
  • Refactor the implementation or test code (as necessary)
  • Re-run all tests in the code base 
  • Write a small number of new and failing automated unit tests
  • Implement the code to make the tests pass
  • Re-run the new unit tests to ensure the now pass

TDD Benefits

  • Increased confidence in developers working on test-driven code bases
  • Increased protection from defects, especially regressions
  • Better code quality (in particular, less coupling and higher cohesion)
  • Tests as a replacement/supplement to other forms of documentation
  • Improved maintainability and changeability of code bases
  • Ability to  refactor  without fear of breaking things
  • Earlier detection of misunderstandings/ambiguities in requirements
  • Smaller production code bases with more simple designs
  • Reduced need for manual testing
  • Faster feedback loop for discovering whether an implementation is correct

In other words

  • Set up a fast feedback loop (test first)
  • Get frequent feedback from the running code
  • Stay "check-in-able" at all times
     
  • TDD is an effective discipline for working incrementally at the smallest scale
     
  • Continually deliver small bits of value
    (specify, test, code, design)

... I don't like testing old code

... feels like there's not much value in it, now that the code is already built and working

TDD give you quality for "free", while helping you keep focused on what's truly important ... writing code :)

It might feel slower in the beginning, but once you get used to the process, it's proven to reduce costs

String Calculator

The following is a TDD Kata- an exercise in coding, refactoring and test-first, that you should apply daily for at least 15 minutes

Before you start: 

  • Try not to read ahead
  • Do one task at a time. The trick is to learn to work incrementally
  • Make sure you only test for correct inputs. there is no need to test for invalid inputs for this kata

1. Create a simple String calculator with a method 
int Add(string numbers) :

  • The method can take 0, 1 or 2 numbers, and will return their sum (for an empty string it will return 0) for example “” or “1” or “1,2”
  • Start with the simplest test case of an empty string and move to 1 and two numbers
  • Remember to solve things as simply as possible so that you force yourself to write tests you did not think about
  • Remember to refactor after each passing test

2. Allow the add method to handle an unknown amount of numbers

3. Allow the add method to handle new lines between numbers (instead of commas):

  • the following input is ok:  “1\n2,3”  (will equal 6)
  • the following input is NOT ok:  “1,\n” (not need to prove it - just clarifying)

4. Support different delimiters

  • to change a delimiter, the beginning of the string will contain a separate line that looks like this:
    //[delimiter]\n[numbers…] for example
    //;\n1;2 should return three where the default delimiter is ‘;’

     
  • the first line is optional; all existing scenarios should still be supported

5. Calling add with a negative number will throw an exception “negatives not allowed” - and the negative that was passed. If there are multiple negatives, show all of them in the exception message

6. Numbers bigger than 1000 should be ignored, so adding 2 + 1001  = 2

7. Delimiters can be of any length with the following format:  “//[delimiter]\n” for example: “//[***]\n1***2***3should return 6

8. Allow multiple delimiters like this:  “//[delim1][delim2]\n” for example “//[*][%]\n1*2%3should return 6.

9. Make sure you can also handle multiple delimiters with length longer than one char

Some might wonder ...

... what's QA gonna do?

Keep in mind that TDD is more of a design process than a test process

... a process once mastered, will help you achieve intrinsic quality in any code you write!

February 10, 2016

Thank You!

TDD for 3Pillar

By Karoly Szanto

TDD for 3Pillar

An introduction to TDD with focus on the importance of unit testing practices

  • 508