summaryrefslogtreecommitdiff
path: root/pypers/recipes/doctester.html
blob: 022383234295bf36a1530527ce33dd7ba9beb7bf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
<?xml version="1.0" encoding="utf-8" ?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="generator" content="Docutils 0.3.7: http://docutils.sourceforge.net/" />
<title></title>
<link rel="stylesheet" href="default.css" type="text/css" />
</head>
<body>
<div class="document">
<p>I use this little script a lot: to test my posts to
c.l.py, to test my articles, and to test my libraries.
Since the script is extremely simple and useful, I thought I
will share it.</p>
<p>The first thing you need is a text like this, with
cut and pasted interpreter sessions:</p>
<pre class="doctest-block">
&gt;&gt;&gt; 1 + 1
2
</pre>
<p>The doctester will look for snippets of this form and will
test them. The magic is performed by the doctest module in the
standard library. I have just added the possibity of inserting
named modules in the text file, like this one:</p>
<pre class="literal-block">
#&lt;example_module.py&gt;

a = 1

#&lt;/example_module.py&gt;
</pre>
<p>The doctester will extract code like this and save it in your
current directory, under the name <tt class="docutils literal"><span class="pre">example_module.py</span></tt>,
<em>before</em> running the tests. In this way you can import
the module in your tests:</p>
<pre class="doctest-block">
&gt;&gt;&gt; from example_module import a
&gt;&gt;&gt; print a
1
</pre>
<p>You may define any number of modules in the same way. 
You can also add code to a previously defined module, simply by
repeating the module name:</p>
<pre class="literal-block">
#&lt;example_module.py&gt;

b = 2

#&lt;/example_module.py&gt;
</pre>
<pre class="doctest-block">
&gt;&gt;&gt; from example_module import b
&gt;&gt;&gt; print b
2
</pre>
<p>Ideally, in future extensions, it will be possible to insert snippets
of code in other languages (for instance bash).</p>
<p>The doctester can be used from the command line or called from
an external program. For instance, you could pass to the doctester
this text you are reading now: suppose it is stored in a file
called doctester.txt, you will get</p>
<pre class="literal-block">
$ python doctester.py &lt; doctester.txt
doctest: 0 failed 5 ok
</pre>
<p>or, if you prefer a more explicit output,</p>
<pre class="literal-block">
$ python doctester.py -v &lt; doctester.txt
Trying:
    1 + 1
Expecting:
    2
ok
Trying:
    from example_module import a
Expecting nothing
ok
Trying:
    print a
Expecting:
    1
ok
Trying:
    from example_module import b
Expecting nothing
ok
Trying:
    print b
Expecting:
    2
ok
1 items passed all tests:
   5 tests in &lt;current-buffer&gt;
5 tests in 1 items.
5 passed and 0 failed.
Test passed.
</pre>
<p>The message says that the tests were defined in '&lt;current-buffer&gt;': the
reason is that I usually call the doctester from Emacs, when I am editing
the text. If you have Python 2.4 and the doctester in installed in
your current Python path, you can just put the following in your .emacs:</p>
<pre class="literal-block">
;; passing the current buffer to an external tool
(defun run-doctest ()
  (interactive)
  (shell-command-on-region (beginning-of-buffer)
                           (end-of-buffer)
                           &quot;python2.4 -m doctester&quot;
                           current-prefix-arg
                           current-prefix-arg))

(defun run-doctest-verbose ()
  (interactive)
  (shell-command-on-region (beginning-of-buffer)
                           (end-of-buffer)
                           &quot;python2.4 -m doctester -v&quot;
                           current-prefix-arg
                           current-prefix-arg))

;; F6 for regular output, SHIFT-F6 for verbose output
(global-set-key [f6] 'run-doctest)
(global-set-key [(shift f6)] 'run-doctest-verbose)
</pre>
<p>If you have Python 2.3 you may want to work a bit more, or 
just insert the full pathname of the doctester script. 
Obviously you may change the keybindings to whatever you like.</p>
</div>
</body>
</html>