Add tox.ini support for testing multiple versions. Update release notes and docs...
[docutils.git] / docutils / docs / dev / testing.txt
blob5396d721b27aef0184a9810537bee7d70e205e89
1 ===================
2  Docutils_ Testing
3 ===================
5 :Authors: Lea Wiemann <LeWiemann@gmail.com>;
6           David Goodger <goodger@python.org>
7 :Revision: $Revision$
8 :Date: $Date$
9 :Copyright: This document has been placed in the public domain.
11 .. _Docutils: http://docutils.sourceforge.net/
13 .. contents::
15 When adding new functionality (or fixing bugs), be sure to add test
16 cases to the test suite.  Practise test-first programming; it's fun,
17 it's addictive, and it works!
19 This document describes how to run the Docutils test suite, how the
20 tests are organized and how to add new tests or modify existing tests.
23 Running the Test Suite
24 ======================
26 Before checking in any changes, run the entire Docutils test suite to
27 be sure that you haven't broken anything.  From a shell::
29     cd docutils/test
30     ./alltests.py
32 Testing Across Versions with tox
33 ================================
35 To save time, you can use `tox`_ to test docutils on versions 2.6+. To
36 install tox, you can use ``easy_install tox`` or ``pip install tox``.
37 From shell::
39     cd docutils
40     tox
42 If you need to install multiple versions of python, you can install
43 `pyenv`_ (see `installing pyenv`_) and setup multiple python versions::
45     # assuming your system runs 2.7.x
46     $ pyenv install 2.6.9
47     $ pyenv install 3.3.6
48     $ pyenv install 3.4.3
49     $ pyenv global system 2.6.9 3.3.6 3.4.3
50     $ rm -rf ~/.pyenv/shims && pyenv rehash
52 This will give you ``python2.6``, ``python2.7``, ``python3.3`` and
53 ``python3.4``. Along with that, ``pip2.6``, ``pip2.7`` and so on.
55 Note: tox only supports python 2.6 and onward.
57 .. _tox: https://tox.readthedocs.org/en/latest/
58 .. _pyenv: https://github.com/yyuu/pyenv
59 .. _installing pyenv: https://github.com/yyuu/pyenv#installation
61 Python Versions
62 ===============
64 The Docutils 0.10 release supports Python 2.4 or later. Therefore, you should
65 actually have Pythons 2.4, as well as the latest Python (3.2 at the time
66 of this writing) installed and always run the tests on all of them.  (A good
67 way to do that is to always run the test suite through a short script that
68 runs ``alltests.py`` under each version of Python.) If you can't afford
69 installing 3 or more Python versions, the edge cases (2.4, and 3.2) should
70 cover most of it.
72 Good resources covering the differences between Python versions:
74 * `What's New in Python 2.4`__
75 * `What's New in Python 2.5`__
76 * `What's New in Python 2.6`__
77 * `PEP 290 - Code Migration and Modernization`__
79 __ http://www.python.org/doc/2.4.4/whatsnew/whatsnew24.html
80 __ http://www.python.org/doc/2.5.2/whatsnew/whatsnew25.html
81 __ http://docs.python.org/whatsnew/2.6.html
82 __ http://www.python.org/peps/pep-0290.html
84 .. _Python Check-in Policies: http://www.python.org/dev/tools.html
85 .. _sandbox directory:
86    http://docutils.svn.sourceforge.net/svnroot/docutils/trunk/sandbox/
87 .. _nightly repository tarball:
88    http://svn.berlios.de/svndumps/docutils-repos.gz
91 Unit Tests
92 ==========
94 Unit tests test single functions or modules (i.e. whitebox testing).
96 If you are implementing a new feature, be sure to write a test case
97 covering its functionality.  It happens very frequently that your
98 implementation (or even only a part of it) doesn't work with an older
99 (or even newer) Python version, and the only reliable way to detect
100 those cases is using tests.
102 Often, it's easier to write the test first and then implement the
103 functionality required to make the test pass.
106 Writing New Tests
107 -----------------
109 When writing new tests, it very often helps to see how a similar test
110 is implemented.  For example, the files in the
111 ``test_parsers/test_rst/`` directory all look very similar.  So when
112 adding a test, you don't have to reinvent the wheel.
114 If there is no similar test, you can write a new test from scratch
115 using Python's ``unittest`` module.  For an example, please have a
116 look at the following imaginary ``test_square.py``::
118     #! /usr/bin/env python
120     # $Id$
121     # Author: Your Name <your_email_address@example.org>
122     # Copyright: This module has been placed in the public domain.
124     """
125     Test module for docutils.square.
126     """
128     import unittest
129     import docutils.square
132     class SquareTest(unittest.TestCase):
134         def test_square(self):
135             self.assertEqual(docutils.square.square(0), 0)
136             self.assertEqual(docutils.square.square(5), 25)
137             self.assertEqual(docutils.square.square(7), 49)
139         def test_square_root(self):
140             self.assertEqual(docutils.square.sqrt(49), 7)
141             self.assertEqual(docutils.square.sqrt(0), 0)
142             self.assertRaises(docutils.square.SquareRootError,
143                               docutils.square.sqrt, 20)
146     if __name__ == '__main__':
147         unittest.main()
149 For more details on how to write tests, please refer to the
150 documentation of the ``unittest`` module.
153 .. _functional:
155 Functional Tests
156 ================
158 The directory ``test/functional/`` contains data for functional tests.
160 Performing functional testing means testing the Docutils system as a
161 whole (i.e. blackbox testing).
164 Directory Structure
165 -------------------
167 + ``functional/`` The main data directory.
169   + ``input/`` The input files.
171     - ``some_test.txt``, for example.
173   + ``output/`` The actual output.
175     - ``some_test.html``, for example.
177   + ``expected/`` The expected output.
179     - ``some_test.html``, for example.
181   + ``tests/`` The config files for processing the input files.
183     - ``some_test.py``, for example.
185     - ``_default.py``, the `default configuration file`_.
188 The Testing Process
189 -------------------
191 When running ``test_functional.py``, all config files in
192 ``functional/tests/`` are processed.  (Config files whose names begin
193 with an underscore are ignored.)  The current working directory is
194 always Docutils' main test directory (``test/``).
196 For example, ``functional/tests/some_test.py`` could read like this::
198     # Source and destination file names.
199     test_source = "some_test.txt"
200     test_destination = "some_test.html"
202     # Keyword parameters passed to publish_file.
203     reader_name = "standalone"
204     parser_name = "rst"
205     writer_name = "html"
206     settings_overrides['output-encoding'] = 'utf-8'
207     # Relative to main ``test/`` directory.
208     settings_overrides['stylesheet_path'] = '../docutils/writers/html4css1/html4css1.css'
210 The two variables ``test_source`` and ``test_destination`` contain the
211 input file name (relative to ``functional/input/``) and the output
212 file name (relative to ``functional/output/`` and
213 ``functional/expected/``).  Note that the file names can be chosen
214 arbitrarily.  However, the file names in ``functional/output/`` *must*
215 match the file names in ``functional/expected/``.
217 If defined, ``_test_more`` must be a function with the following
218 signature::
220     def _test_more(expected_dir, output_dir, test_case, parameters):
222 This function is called from the test case to perform tests beyond the
223 simple comparison of expected and actual output files.
225 ``test_source`` and ``test_destination`` are removed from the
226 namespace, as are all variables whose names begin with an underscore
227 ("_").  The remaining names are passed as keyword arguments to
228 ``docutils.core.publish_file``, so you can set reader, parser, writer
229 and anything else you want to configure.  Note that
230 ``settings_overrides`` is already initialized as a dictionary *before*
231 the execution of the config file.
234 Creating New Tests
235 ------------------
237 In order to create a new test, put the input test file into
238 ``functional/input/``.  Then create a config file in
239 ``functional/tests/`` which sets at least input and output file names,
240 reader, parser and writer.
242 Now run ``test_functional.py``.  The test will fail, of course,
243 because you do not have an expected output yet.  However, an output
244 file will have been generated in ``functional/output/``.  Check this
245 output file for validity and correctness.  Then copy the file to
246 ``functional/expected/``.
248 If you rerun ``test_functional.py`` now, it should pass.
250 If you run ``test_functional.py`` later and the actual output doesn't
251 match the expected output anymore, the test will fail.
253 If this is the case and you made an intentional change, check the
254 actual output for validity and correctness, copy it to
255 ``functional/expected/`` (overwriting the old expected output), and
256 commit the change.
259 .. _default configuration file:
261 The Default Configuration File
262 ------------------------------
264 The file ``functional/tests/_default.py`` contains default settings.
265 It is executed just before the actual configuration files, which has
266 the same effect as if the contents of ``_default.py`` were prepended
267 to every configuration file.