root / RuPy / t_and_d__dd.txt

Revision 78:b5dabe9762d1, 7.2 kB (checked in by Tarek Ziad?? <tarek@…>, 20 months ago)

rupy slides, starting up

Line 
1.. include:: <s5defs.txt>
2
3===========
4TDD and DDD
5===========
6
7:Authors: Olivier Grisel <olivier.grisel@ensta.org>
8:Date:    $Date: 2007-02-21$
9
10.. This document is published under the CC-By-SA 2 license
11
12.. class:: small
13
14  * A few words on Extreme Programming
15
16  * Writing TestCases and test_suites in python
17
18  * Documentation Driven Development with the doctest module
19
20  * Additional tools (continuous integration testing, coverage)
21
22
23.. container:: handout
24
25    The first part of the presentation introduces Test Driven Development
26    in Python with the unittest module. TDD is a common eXtreme Programming
27    strategy to dramatically enhance the QA of a python project.
28
29    The second part of the presentation focuses on the python specific
30    doctest module that pushes TDD to the next level: DDD. We will
31    show how to write runnable documentation that is used at all stages
32    of the life of a python project:
33
34     - technical specifications drafting of new features
35     - testing ongoing implementation
36     - introducing living examples to new developers
37     - ensuring the documentation stays up-to-date when refactoring
38
39
40.. contents::
41   :class: handout
42
43.. |bullet| unicode:: U+02022
44.. |mode| unicode:: U+00D8 .. capital o with stroke
45
46.. footer:: Location |bullet| Date
47
48
49Extreme Programming
50===================
51
52.. class:: incremental
53
54* Fashionable methodology to drive software development projects
55
56* 3 fundamental concepts:
57
58  .. class:: incremental
59
60  - Peer programming
61
62  - Short iterations (the customer is in the inner loop)
63
64  - Tests, tests, tests -> automate them!
65
66
67Testing principles
68==================
69
70.. class:: incremental
71
72* 1 test == sample use case for each method in each class in each module
73
74* reproducible and organised in a "test suite"
75
76* run them as often as you can
77
78* think: "If it's not tested, then it's broken"
79
80* tool to find bugs early != formal proof of correctness
81
82
83More principles
84================
85
86.. class:: incremental
87
88* Compare test results to expected results
89
90* Test common use cases
91
92* Test weird cases: what if arg = 0, None, ... ?
93
94* Test that the right exception is raised
95
96
97How to do that?
98===============
99
100.. class:: incremental
101
102* "Python comes with batteries included"
103
104* Use the ``unittest`` module
105
106* Derive the ``TestCase`` class
107
108* Add ``setUp / tearDown`` methods
109
110* Implement tests as ``test_something`` methods
111
112* Use ``assert_``, ``assertEquals``, ``assertRaises``, ...
113
114* Collect the tests and feed them to a runner
115
116
117.. container:: handout
118
119  Here is an example test setup to test file creation, reading and writing.
120
121  ::
122
123    from os.path import join, exists
124    import unittest, tempfile, shutil
125
126    class FileTestCase(unittest.TestCase):
127
128        def setUp(self):
129            self.test_folder = tempfile.mkdtemp()
130
131        def test_text_file(self):
132
133            content = "some text\nto write\nin a file"
134
135            filename = join(self.test_folder, "my_file.txt")
136
137            f = file(filename, 'wb')
138            f.write(content)
139            f.close()
140
141            self.assert_(exists(filename))
142
143            lines = file(filename, 'r').readlines()
144            self.assertEquals("some text\n", lines[0])
145            self.assertEquals("to write\n", lines[1])
146            self.assertEquals("in a file", lines[2])
147
148        def test_binary_file(self):
149            data = '234wgfge43rv34rvq3w5q3v54q3245q'
150
151            filename = join(self.test_folder, "my_file.bin")
152
153            f = file(filename, 'wb')
154            f.write(data)
155            f.close()
156
157            self.assert_(exists(filename))
158
159            f2 = file(filename, 'rb')
160            self.assertEquals("23", f2.read(2))
161            self.assertEquals("4wgf", f2.read(4))
162            self.assertEquals("ge43rv34rvq3w5q3v54q3245q", f2.read())
163
164        def tearDown(self):
165            shutil.rmtree(self.test_folder)
166
167    def test_suite():
168        suite = unittest.TestSuite()
169        suite.addTests(unittest.makeSuite(FileTestCase))
170        return suite
171
172    if __name__ == '__main__':
173        unittest.main(defaultTest='test_suite')
174        from os.path import join, exists
175        import unittest, tempfile, shutil
176
177
178
179Testing hierarchy
180=================
181
182.. class:: incremental
183
184* Unit tests: each method of each module independently
185
186* Integration tests: several interacting modules
187
188* Functional tests: black box / UI tests
189
190* Fast to run / numerous -> Slow to run / fewer of them
191
192* All of them serve also as regression tests
193
194* Refactoring harness
195
196
197Testing methodology
198===================
199
200.. class:: incremental
201
202* T. *D*. D. means *driven*
203
204* Write the test first and then the implementation
205
206* A matter of point of view -> cleaner APIs
207
208* When the tests pass, stop writing code, you are done!
209
210* For each bug found, reproduce it with a test and *then* fix it
211
212
213Documentation Driven Development
214================================
215
216.. class:: incremental
217
218* Most tests show good sample usage
219
220* Let's use them as developer documentation
221
222* Documentation is a pedagogical story with samples in it
223
224* Early stage: used as brainstorming sandbox
225
226* Then: evolves as a technical specification of your API
227
228* Then: guaranteed up-to-date user friendly documentation
229
230
231Modules: ``doctest`` and ``docutils``
232=====================================
233
234.. class:: incremental
235
236* original python
237
238* tell a story with the reST syntax
239
240* insert examples as if run in a console
241
242* use ``docutils`` to generate a nice doc (xHTML, PDF, S5, ...)
243
244* use ``doctest`` to check the examples actually work
245
246
247doctest examples
248================
249
250.. class:: incremental
251
252  ::
253
254    >>> def tell_the_truth():
255    ...     return "doctests rock!"
256    ...
257    >>> tell_the_truth()
258    'doctests rock!'
259
260  * Now this presentation is doctestable!
261
262  ::
263
264     import doctest
265     import unittest
266
267     def test_suite():
268         return doctest.DocFileSuite('t_and_d__dd.txt')
269
270     if __name__ == '__main__':
271         unittest.main(defaultTest='test_suite')
272
273
274Writing techniques and tips
275===========================
276
277.. class:: incremental
278
279The seven *laws* for technical writing (by Tarek Ziadé and others):
280
281  .. class:: incremental
282
283  - Two-step writing process
284
285  - Simple style
286
287  - Targeted readership
288
289  - Focused information
290
291  - Realistic examples (no foo/bar stuff)
292
293  - "Light but sufficient" approach
294
295  - Structured documents
296
297
298
299Tool #1: Test collectors / runners
300==================================
301
302.. class:: incremental
303
304* 2 options to build a test suite:
305
306  .. class:: incremental
307
308  - manually (``unittest.TestSuite().addTest(...)``)
309
310  - use a script that does it for you
311
312* nosetests
313
314* zope testrunner
315
316* others, use google
317
318
319Tool #2: Continuous integration testing
320=======================================
321
322.. class:: incremental
323
324* Robot to launch tests on each VCS checkin
325
326* Python reference tool: buildbot
327
328* Used to test python itself:
329
330  .. class:: incremental
331
332  http://www.python.org/dev/buildbot/all/
333
334
335Tool #3: Coverage monitoring
336============================
337
338.. class:: incremental
339
340* Principle: each executable line of code should be tested
341
342* Remember: not a formal proof, just a way to find bug niches
343
344* coverage.py : text mode reports
345
346* trace2html : HTML coverage reports
347
348
349Questions ?
350===========
351
352.. class:: incremental
353
354Have no idea? Here is one:
355
356  .. class:: incremental
357
358  - how did write such beautiful slides?
359
Note: See TracBrowser for help on using the browser.