56
Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution Lice See http://software-carpentry.org/license.html for more informati Testing

Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Embed Size (px)

Citation preview

Page 1: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Unit Testing

Copyright © Software Carpentry 2010

This work is licensed under the Creative Commons Attribution License

See http://software-carpentry.org/license.html for more information.

Testing

Page 2: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Studying impact of climate change on agriculture

Page 3: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Studying impact of climate change on agriculture

Have aerial photos of farms from 1980–83

Page 4: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Studying impact of climate change on agriculture

Have aerial photos of farms from 1980–83

Want to compare with photos from 2007–present

Page 5: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Studying impact of climate change on agriculture

Have aerial photos of farms from 1980–83

Want to compare with photos from 2007–present

First step is to find regions where fields overlap

Page 6: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Luckily, these fields are in Saskatchewan...

Page 7: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Luckily, these fields are in Saskatchewan...

...where fields are rectangles

Page 8: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

A student has written a function that finds

the overlap between two rectangles

Page 9: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

A student has written a function that finds

the overlap between two rectangles

We want to test it before using it

Page 10: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

A student has written a function that finds

the overlap between two rectangles

We want to test it before using it

We're also planning to try to speed it up...

Page 11: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

A student has written a function that finds

the overlap between two rectangles

We want to test it before using it

We're also planning to try to speed it up...

...and want tests to make sure we don't break it

Page 12: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

A student has written a function that finds

the overlap between two rectangles

We want to test it before using it

We're also planning to try to speed it up...

...and want tests to make sure we don't break it

Use Python's Nose library

Nose

Page 13: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Each test is a function

Nose

Page 14: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Each test is a function

– Whose name begins with test_

Nose

Page 15: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Each test is a function

– Whose name begins with test_

Group related tests in files

Nose

Page 16: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Each test is a function

– Whose name begins with test_

Group related tests in files

– Whose names begin with test_

Nose

Page 17: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Each test is a function

– Whose name begins with test_

Group related tests in files

– Whose names begin with test_

Run the command nosetests

Nose

Page 18: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Each test is a function

– Whose name begins with test_

Group related tests in files

– Whose names begin with test_

Run the command nosetests

– Which automatically search the current

directory and sub-directories for tests

Nose

Page 19: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Simple example: testing dna_starts_with

Page 20: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Simple example: testing dna_starts_with

def test_starts_with_itself():

dna = 'actgt'

assert dna_starts_with(dna, dna)

def test_starts_with_single_base_pair():

assert dna_starts_with('actg', 'a')

def does_not_start_with_single_base_pair():

assert not dna_starts_with('ttct', 'a')

Page 21: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Simple example: testing dna_starts_with

def test_starts_with_itself():

dna = 'actgt'

assert dna_starts_with(dna, dna)

def test_starts_with_single_base_pair():

assert dna_starts_with('actg', 'a')

def does_not_start_with_single_base_pair():

assert not dna_starts_with('ttct', 'a')

Give tests

meaningful

names

Page 22: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Simple example: testing dna_starts_with

def test_starts_with_itself():

dna = 'actgt'

assert dna_starts_with(dna, dna)

def test_starts_with_single_base_pair():

assert dna_starts_with('actg', 'a')

def does_not_start_with_single_base_pair():

assert not dna_starts_with('ttct', 'a')

Use

assert

to check

results

Page 23: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Simple example: testing dna_starts_with

def test_starts_with_itself():

dna = 'actgt'

assert dna_starts_with(dna, dna)

def test_starts_with_single_base_pair():

assert dna_starts_with('actg', 'a')

def does_not_start_with_single_base_pair():

assert not dna_starts_with('ttct', 'a')

Use

variables

for fixtures

to prevent

typing

mistaeks

Page 24: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Simple example: testing dna_starts_with

def test_starts_with_itself():

dna = 'actgt'

assert dna_starts_with(dna, dna)

def test_starts_with_single_base_pair():

assert dna_starts_with('actg', 'a')

def does_not_start_with_single_base_pair():

assert not dna_starts_with('ttct', 'a')Test lots

of cases

Page 25: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

"Test lots of cases"

Page 26: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

"Test lots of cases"

How many?

Page 27: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

"Test lots of cases"

How many?

Page 28: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

"Test lots of cases"

How many?

How to choose cost-effective tests?

Page 29: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

"Test lots of cases"

How many?

How to choose cost-effective tests?

If we test dna_starts_with('atc', 'a'),

we're unlikely to learn much from testing

dna_starts_with('ttc', 't')

Page 30: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

"Test lots of cases"

How many?

How to choose cost-effective tests?

If we test dna_starts_with('atc', 'a'),

we're unlikely to learn much from testing

dna_starts_with('ttc', 't')

So choose tests that are as different from each

other as possible

Page 31: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

"Test lots of cases"

How many?

How to choose cost-effective tests?

If we test dna_starts_with('atc', 'a'),

we're unlikely to learn much from testing

dna_starts_with('ttc', 't')

So choose tests that are as different from each

other as possible

Look for boundary cases

Page 32: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Apply this to overlapping rectangles

Page 33: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

A "normal" case

Apply this to overlapping rectangles

Page 34: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

A "normal" case

What else would be useful?

Apply this to overlapping rectangles

Page 35: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

A "normal" case

What else would be useful?

Apply this to overlapping rectangles

Page 36: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Page 37: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Page 38: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Page 39: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Page 40: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

?

Page 41: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

?

?

Page 42: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

?

?

Tests help us define

what "correct"

actually means

Page 43: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Turn this into code

Page 44: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Turn this into code

def test_touch_on_corner():

one = ((0, 0), (1, 1))

two = ((1, 1), (2, 2))

assert overlap(one, two) == None

Page 45: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

Turn this into code

def test_touch_on_corner():

one = ((0, 0), (1, 1))

two = ((1, 1), (2, 2))

assert overlap(one, two) == None

An unambiguous, runnable answer to our

question about touching on corners

Page 46: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

def test_unit_with_itself():

unit = ((0, 0), (1, 1))

assert overlap(unit, unit) == unit

Page 47: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

def test_unit_with_itself():

unit = ((0, 0), (1, 1))

assert overlap(unit, unit) == unit

Wasn't actually in the set of test cases

we came up with earlier

Page 48: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

def test_partial_overlap():

red = ((0, 3), (2, 5))

blue = ((1, 0), (2, 4))

assert overlap(red, blue) == ((1, 3), (2, 4))

Page 49: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

def test_partial_overlap():

red = ((0, 3), (2, 5))

blue = ((1, 0), (2, 4))

assert overlap(red, blue) == ((1, 3), (2, 4))

This test actually turned up a bug

Page 50: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

def overlap(red, blue):

'''Return overlap between two rectangles, or None.'''

((red_lo_x, red_lo_y), (red_hi_x, red_hi_y)) = red

((blue_lo_x, blue_lo_y), (blue_hi_x, blue_hi_y)) = blue

if (red_lo_x >= blue_hi_x) or (red_hi_x <= blue_lo_x) or \

(red_lo_y >= blue_hi_x) or (red_hi_y <= blue_lo_y):

return None

lo_x = max(red_lo_x, blue_lo_x)

lo_y = max(red_lo_y, blue_lo_y)

hi_x = min(red_hi_x, blue_hi_x)

hi_y = min(red_hi_y, blue_hi_y)

return ((lo_x, lo_y), (hi_x, hi_y))

Page 51: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

def overlap(red, blue):

'''Return overlap between two rectangles, or None.'''

((red_lo_x, red_lo_y), (red_hi_x, red_hi_y)) = red

((blue_lo_x, blue_lo_y), (blue_hi_x, blue_hi_y)) = blue

if (red_lo_x >= blue_hi_x) or (red_hi_x <= blue_lo_x) or \

(red_lo_y >= blue_hi_x) or (red_hi_y <= blue_lo_y):

return None

lo_x = max(red_lo_x, blue_lo_x)

lo_y = max(red_lo_y, blue_lo_y)

hi_x = min(red_hi_x, blue_hi_x)

hi_y = min(red_hi_y, blue_hi_y)

return ((lo_x, lo_y), (hi_x, hi_y))

Page 52: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

def overlap(red, blue):

'''Return overlap between two rectangles, or None.'''

((red_lo_x, red_lo_y), (red_hi_x, red_hi_y)) = red

((blue_lo_x, blue_lo_y), (blue_hi_x, blue_hi_y)) = blue

if (red_lo_x >= blue_hi_x) or (red_hi_x <= blue_lo_x) or \

(red_lo_y >= blue_hi_x) or (red_hi_y <= blue_lo_y):

return None

lo_x = max(red_lo_x, blue_lo_x)

lo_y = max(red_lo_y, blue_lo_y)

hi_x = min(red_hi_x, blue_hi_x)

hi_y = min(red_hi_y, blue_hi_y)

return ((lo_x, lo_y), (hi_x, hi_y))

Oops

Page 53: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

You should spend your time choosing test cases

and defining their answers

Page 54: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

You should spend your time choosing test cases

and defining their answers

Nose (and its kin) are there to handle everything

that you shouldn't re-think each time

Page 55: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

Testing Unit Testing

You should spend your time choosing test cases

and defining their answers

Nose (and its kin) are there to handle everything

that you shouldn't re-think each time

"The tool shapes the hand"

Page 56: Unit Testing Copyright © Software Carpentry 2010 This work is licensed under the Creative Commons Attribution License See

August 2010

created by

Greg Wilson

Copyright © Software Carpentry 2010

This work is licensed under the Creative Commons Attribution License

See http://software-carpentry.org/license.html for more information.