testing: More restructuring for the Nose source
[swc-testing-nose.git] / testing / instructor.md
1 # When should we test?
2
3 Short answers:
4
5 -   **ALWAYS!**
6 -   **EARLY!**
7 -   **OFTEN!**
8
9 Long answers:
10
11 * Definitely before you do something important with your software
12   (e.g. publishing data generated by your program, launching a
13   satellite that depends on your software, …).
14 * Before and after adding something new, to avoid accidental breakage.
15 * To help remember ([TDD][]: define) what your code actually does.
16
17 # Who should test?
18
19 * Write tests for the stuff you code, to convince your collaborators
20   that it works.
21 * Write tests for the stuff others code, to convince yourself that it
22   works (and will continue to work).
23
24 Professionals often test their code, and take pride in test coverage,
25 the percent of their functions that they feel confident are
26 comprehensively tested.
27
28 # How are tests written?
29
30 The type of tests that are written is determined by the testing
31 framework you adopt. Don't worry, there are a lot of choices.
32
33 ## Types of Tests
34
35 **Exceptions:** Exceptions can be thought of as type of runtime test.
36 They alert the user to exceptional behavior in the code. Often,
37 exceptions are related to functions that depend on input that is unknown
38 at compile time. Checks that occur within the code to handle exceptional
39 behavior that results from this type of input are called Exceptions.
40
41 **Unit Tests:** Unit tests are a type of test which test the fundamental
42 units of a program's functionality. Often, this is on the class or
43 function level of detail. However what defines a *code unit* is not
44 formally defined.
45
46 To test functions and classes, the interfaces (API) - rather than the
47 implementation - should be tested. Treating the implementation as a
48 black box, we can probe the expected behavior with boundary cases for
49 the inputs.
50
51 **System Tests:** System level tests are intended to test the code as a
52 whole. As opposed to unit tests, system tests ask for the behavior as a
53 whole. This sort of testing involves comparison with other validated
54 codes, analytical solutions, etc.
55
56 **Regression Tests:** A regression test ensures that new code does
57 change anything. If you change the default answer, for example, or add a
58 new question, you'll need to make sure that missing entries are still
59 found and fixed.
60
61 **Integration Tests:** Integration tests query the ability of the code
62 to integrate well with the system configuration and third party
63 libraries and modules. This type of test is essential for codes that
64 depend on libraries which might be updated independently of your code or
65 when your code might be used by a number of users who may have various
66 versions of libraries.
67
68 **Test Suites:** Putting a series of unit tests into a collection of
69 modules creates, a test suite. Typically the suite as a whole is
70 executed (rather than each test individually) when verifying that the
71 code base still functions after changes have been made.
72
73 # Elements of a Test
74
75 **Behavior:** The behavior you want to test. For example, you might want
76 to test the fun() function.
77
78 **Expected Result:** This might be a single number, a range of numbers,
79 a new fully defined object, a system state, an exception, etc. When we
80 run the fun() function, we expect to generate some fun. If we don't
81 generate any fun, the fun() function should fail its test.
82 Alternatively, if it does create some fun, the fun() function should
83 pass this test. The the expected result should known *a priori*. For
84 numerical functions, this is result is ideally analytically determined
85 even if the function being tested isn't.
86
87 **Assertions:** Require that some conditional be true. If the
88 conditional is false, the test fails.
89
90 **Fixtures:** Sometimes you have to do some legwork to create the
91 objects that are necessary to run one or many tests. These objects are
92 called fixtures as they are not really part of the test themselves but
93 rather involve getting the computer into the appropriate state.
94
95 For example, since fun varies a lot between people, the fun() function
96 is a method of the Person class. In order to check the fun function,
97 then, we need to create an appropriate Person object on which to run
98 fun().
99
100 **Setup and teardown:** Creating fixtures is often done in a call to a
101 setup function. Deleting them and other cleanup is done in a teardown
102 function.
103
104 **The Big Picture:** Putting all this together, the testing algorithm is
105 often:
106
107 ```python
108 setup()
109 test()
110 teardown()
111 ```
112
113 But, sometimes it's the case that your tests change the fixtures. If so,
114 it's better for the setup() and teardown() functions to occur on either
115 side of each test. In that case, the testing algorithm should be:
116
117 ```python
118 setup()
119 test1()
120 teardown()
121
122 setup()
123 test2()
124 teardown()
125
126 setup()
127 test3()
128 teardown()
129 ```
130
131 # Test-Driven Development
132
133 [Test-driven development][TDD] (TDD) is a philosophy whereby the
134 developer creates code by **writing the tests first**. That is to say
135 you write the tests *before* writing the associated code!
136
137 This is an iterative process whereby you write a test then write the
138 minimum amount code to make the test pass. If a new feature is needed,
139 another test is written and the code is expanded to meet this new use
140 case. This continues until the code does what is needed.
141
142 TDD operates on the YAGNI principle (You Ain't Gonna Need It). People
143 who diligently follow TDD swear by its effectiveness. This development
144 style was put forth most strongly by [Kent Beck in 2002][KB].
145
146
147 [TDD]: http://en.wikipedia.org/wiki/Test-driven_development
148 [KB]: http://www.amazon.com/Test-Driven-Development-By-Example/dp/0321146530