# TDD is not JUST

### Fabrizio Romano

@gianchub

ProgSCon - London

April 22th, 2016

# Hello London!

## Thank you for being here!

I'm a Computer Science Engineer, addicted to Python, clean code and books.

I'm the author of Learning Python (Packt Publishing, 12.2015).

Sr. Platform Developer

@ student.com

We're

hiring!

## The plan:

...and let's have some fun while we do it

1. What drew me to TDD
2. Why would you need it?

## A little disclaimer

• This is my own view
• Simple examples
• No definitions
• Code is in Python, but

# What drew me to TDD?

It all happened when I moved to London...

Don't worry, TDD will take us there

- Mark Henwood

Too much logic!

- Ondrej Kohout

A couple of colleagues were a great inspiration:

# Why do we need TDD?

``````def is_positive(n):
# We assume n is integer.
return n > 0``````

# Example #1

How do we test this function?

## Boundaries

``````def is_positive(n):
# We assume n is integer.
return n > 0

eq(False, is_positive(0))
eq(False, is_positive(-3))
eq(True, is_positive(3))``````

Is this a good test?

``````def is_positive(n):
# We assume n is integer.
return n > 1

eq(False, is_positive(0))   # still passing
eq(False, is_positive(-3))  # still passing
eq(True, is_positive(3))    # still passing``````

## Granularity

``````def is_positive(n):
# We assume n is integer.
return n > 1

eq(False, is_positive(0))   # still passing
eq(False, is_positive(-1))  # still passing
eq(True, is_positive(1))    # NOW FAILS!``````

Much better!

The boundary cannot jiggle any more!

``````def is_positive(n):
# We assume n is integer.
return n > 0

eq(False, is_positive(0))

for n in range(1, 10 ** 4):
eq(False, is_positive(-n))
eq(True, is_positive(n))``````

Even better!

But unit tests need to be FAST...

# So, can we test everything?

``````def is_positive(n):
# We assume n is integer.
if n == 10 ** 16:
return 'Hola!'
return n > 0
``````

If you could test 1'000'000'000 numbers a second, it would take about 4 months to spot this.

## We cannot test everything.

``````def get_squares(v):
# assumes v is a list of integers
if not v:
return []
return [n ** 2 for n in v]``````

# Example #2

How do we test this function?

``````def get_squares(v):
# assumes v is a list of integers
if not v:
return []
return [n ** 2 for n in v]

eq([1, 0, 4, 9], get_squares([-1, 0, 2, -3]))
eq([], get_squares([]))``````

We may not notice it, if we tested AFTERWARDS

``````def get_squares(v):
# assumes v is a list of integers
if not v:
return []
return [n ** 2 for n in v]
``````
``````# this test would cause us to write get_squares2
eq([1, 0, 4, 9], get_squares2([-1, 0, 2, -3]))

# and this would automatically pass, thanks to
# the list comprehension
eq([], get_squares2([]))``````

Had we written the tests first, there would be no redundancy.

``````def get_squares2(v):
# assumes v is a list of integers
return [n ** 2 for n in v]``````

# Once Upon a Time...

## there was a frog

He was in love with a beautiful princess. One day, at the pond, the frog took courage, jumped out of the water and told her:

I am a prince under a spell, kiss me,

break the spell and marry me!

Prince? Intriguing!

## But she was a Geek...

TDD?

Let me get back

to you on this...

Kent Beckowl

Robert Martinowl

TDD strooong

in them was...

# TDD

## Test Driven Development

TDD is a Software Development Process based on the repetition of a very short development cycle.

Def:

# Steps

• Short at first
• With experience: longer
• Trouble? Go back to short

# Where does it start?

OMG! It's like

having 2 brains!

## TDD common aspects

• KISS
• YAGNI
• Architecture design (during refactoring)
• Three strikes and refactor
(Test-Driven Development with Python - H. Percival)
• Triangulation

# ?

## Triangulation

``````eq(4, square(-2))

def square(n):
# we can cheat, it is
# the only requirement
return 4``````

First step

"Fake it 'till you make it"

``````eq(4, square(-2))
eq(9, square(3))

def square(n):
return n ** 2``````

With Triangulation

You write

the actual logic.

## Main Benefits

• Refactor with Confidence
• Loose Coupling
• Easier to test and maintain
• Test first => Better understanding of requirements
• Small units => easier debugging and tests as docs
• Higher speed:
It takes less to write tests and code
than to write code and debug

## Main Shortcomings

• Whole company needs to believe
• Blind spots
• Badly written tests are hard to maintain
• Hard to do it when dealing with new tools
• Hard to do it when the task isn't fully specified, and we have exploration to do

# Changing a horribly long view

``````def get(request, *args, **kwargs):

# imagine many lines of code here...

data = get_data(**search_params)

# here we work on the data and
# eventually we put it in the context
# dict we use to render the template

return render(template_name, context, extra_params)``````

### We need to insert pagination, filtering, sorting

``````def get(request, *args, **kwargs):

# same as before

original_data = get_data(**search_params)

filtered_data = filter_data(
original_data, **filter_params)

sorted_data = sort_data(
filtered_data, **sort_params)

data = paginate_data(
sorted_data, **pagination_params)

# same as before

return render(template_name, context, extra_params)``````

# Introducing a new functionality in existing code

## We need to add a feature to a long piece of untested code.

``````def very_long_function(*args, **kwargs):

# nasty piece of code that does
# a lot of things.

return result``````

## One possible solution:

``````def test_new_functionality():
# preparation stage

result = very_long_function(*args, **kwargs)

eq(expected_result, result)

def very_long_function(*args, **kwargs):

# same nasty piece of code
# with NEW FUNCTIONALITY IN

return result``````

# Thank you! Come say hi!

gianchub

gianchub

gianchub [at] gmail [dot] com

#### TDD is not just about tests (Progscon, London)

By Fabrizio Romano

# TDD is not just about tests (Progscon, London)

TDD is not just about tests. (Progscon 2016.04.22, London)

• 2,067