Better title for Nose section in testing cheat sheet.
[swc-testing-nose.git] / testing / cheat-sheet.md
1 Python Testing Cheat Sheet
2 ==========================
3
4 Defensive programming
5 ---------------------
6
7 Using an assertion to ensure input is acceptable:
8
9     def some_function(x):
10         assert x >= 0
11         # ... continue safe in knowledge that x > 0
12
13 Adding an explanatory message to the assertion:
14
15         assert x >= 0, "Function not defined for negative x."
16
17 Alternatively, raise an exception to indicate what the problem is:
18
19     def some_function(x):
20         if x < 0:
21             raise TypeError, "Function not defined for negative x."
22         return 0
23
24
25 Unit testing with Nose
26 ----------------------
27
28 To run tests, at the shell prompt, type
29
30     nosetests
31
32 By default, Nose will
33
34 * look for test functions that have a name starting with `test`
35 * look for them in files with names starting with `test`
36 * look for such files in the current working directory, and in subdirectories with names starting with `test`
37
38 There are some additional rules, and you can configure your own, but this should be enough to get started.
39
40 ### A simple test
41
42     from nose.tools import assert_equal
43
44     from mystatscode import mean
45
46     def test_single_value():
47         observed = mean([1.0])
48         expected = 1.0
49         assert_equal(observed, expected)
50
51 ### Other assertions
52
53 Nose provides a range of assertions that can be used when a test is not just checking a simple equality, e.g.
54
55     from nose.tools import assert_items_equal
56
57     from mycode import find_factors
58
59     def test_6():
60         observed = find_factors(6)
61         expected = [2, 3]
62         assert_items_equal(observed, expected) # order of factors is not guaranteed
63
64 ### Floating point tests
65
66 When comparing floating-point numbers for equality, allow some tolerance for small differences due to
67 the way values are represented and rounded.
68
69     from nose.tools import assert_almost_equal
70
71     from mycode import hypotenuse
72
73     def test_hypotenuse_345():
74         observed = hypotenuse(3.0, 4.0)
75         expected = 5.0
76         assert_almost_equal(observed, expected)
77
78 ### Testing exceptions
79
80 Testing that a method raises the appropriate exception when the input is invalid:
81
82     from nose.tools import raises
83
84     from mystatscode import mean
85
86     @raises(TypeError)
87     def test_not_a_list():
88         observed = mean(1)
89
90 ### Fixtures
91
92 A *fixture* is what the test function uses as input, e.g. values, objects and arrays.
93
94 To set up a fixture once before any tests are run, define a method called `setup` in the same files
95 as the test functions. This can assign values to global variables for use in the test functions.
96
97     long_list = None
98
99     def setup():
100         long_list = [0]
101         # append more values to long_list...
102
103 If the global variables assigned in `setup` might be modified by some of the test functions, the set-up
104 step must be executed once before each test function is called:
105
106     from nose.tools import with_setup
107
108     from mycode import mean, clear
109
110     long_list = None
111
112     def setup_each():
113         long_list = [0]
114         # append more values to long_list...
115
116     @with_setup(setup_each)
117     def test_mean_long_list():
118         observed = mean(long_list)
119         expected = 0.0
120         assert_equal(observed, expected)
121
122     @with_setup(setup_each)
123     def test_clear_long_list():
124         clear(long_list)
125         assert_equal(len(long_list), 0)