diff --git a/doc/conf.py.in b/doc/conf.py.in
index 71ff3e3700542181c8e1666e9fb01328bd9623ea..79fcf5ce42cb4264bda10c693fa8ddb46bbb7859 100644
--- a/doc/conf.py.in
+++ b/doc/conf.py.in
@@ -253,6 +253,9 @@ intersphinx_mapping = {'python': ('@PYTHON_DOC_URL@', None),
 # -- ProMod3 specific configuration --------------------------------------------
 extlinks = {'py_docs' : ('@PYTHON_DOC_URL@/%s',
                          'Python documentation')}
+# The _nameattr is a bit ugly: we want to have __name__ formatted as Python
+# attribute but Sphinx does not go with calling :attr: inside extlinks. To keep
+# the Python url prefix, we define sth here.
 rst_epilog = """
 .. |project| replace:: %s
 .. |cmake| replace:: CMake
@@ -267,6 +270,7 @@ rst_epilog = """
 .. |git| replace:: Git
 .. |C++| replace:: C++
 .. _ost_s: http://www.OpenStructure.org
+.. _nameattr: @PYTHON_DOC_URL@/library/__main__.html
 """ % project
 # in some versions of sphinx, doctest invokes doctest_path AFTER executing code
 doctest_global_setup = """
diff --git a/doc/contributing.rst b/doc/contributing.rst
index 869300d8702b2334086fa46095eebe7cfa8eac00..e83104db1a5c72517b334c929b4f8bcde1623fce 100644
--- a/doc/contributing.rst
+++ b/doc/contributing.rst
@@ -269,7 +269,6 @@ version control, create a couple of files which are always needed.
 .. code-block:: console
 
    $ touch sidechains/pymod/__init__.py
-   $ echo "FOO" >> sidechains/doc/index.rst
    $ echo ":mod:\`~promod3.sidechains\` - ProMod3 side chain optimiser" >> sidechains/doc/index.rst
    $ echo "================================================================================" >> sidechains/doc/index.rst
    $
@@ -330,7 +329,7 @@ a couple of examples around in this repository. Here is the most basic
 :file:`CMakeLists.txt`:
 
 .. code-block:: cmake
-   :linenos:
+  :linenos:
 
    set(SIDECHAINS_PYMOD
    __init__.py
@@ -348,8 +347,8 @@ The final step towards |cmake| is to register your module's directory in the
 top level :file:`CMakeLists.txt`:
 
 .. code-block:: cmake
-   :linenos:
-   :emphasize-lines: 80
+  :linenos:
+  :emphasize-lines: 80
 
    #-------------------------------------------------------------------------------
    # Author: Bienchen
@@ -481,14 +480,90 @@ a new configuration script. The following example assumes |fedora| 19.
 From this point, :command:`make` should work and you could start adding your
 files to the repository using ``git add``.
 
+Up to now, we did not cover the :file:`tests` branch of a new module. But its
+good practice to develop new functionality along tests and that right from the
+beginning. At some point, new code needs testing anyway to see if it does what
+it should, so just do this by writing unit tests. Test sources are stored in
+files with a prefix :file:`test_` and usually come per submodule instead of
+sporting a single monolithic :file:`test_sidechains.py`.
+
+|python| code is evaluated using its own
+:py_docs:`unit testing framework <library/unittest.html>` with a little help
+from |ost_s|_. The basic scheme is to import your module, subclass
+:class:`unittest.TestCase` and make the whole file runnable as script using the
+most common |nameattr|_ attribute. A file :file:`tests/test_something.py` could
+look like this, carrying a single test case:
+
+.. testcode:: promod3unittest
+  :hide:
+
+  import unittest
+
+  class something():
+      @staticmethod
+      def Else():
+          return 1
+
+  class SomethingTests(unittest.TestCase):
+      def testFileExistsFalse(self):
+          self.assertEquals(something.Else(), 1)
+
+  if __name__ == "__builtin__":
+      suite = unittest.TestLoader().loadTestsFromTestCase(SomethingTests)
+      unittest.TextTestRunner().run(suite)
+
+.. code-block:: python
+  :linenos:
+
+   import unittest
+   from promod3.sidechains import something
+
+   class SomethingTests(unittest.TestCase):
+       def testFileExistsFalse(self):
+           self.assertEquals(something.Else(), 1)
+
+   if __name__ == "__main__":
+       from ost import testutils
+       testutils.RunTests()
+
+To hook up your tests with ``make codetest`` (and to create a
+``test_something.py_run`` target), everything has to be introduced to |cmake|.
+First, tell |cmake| to search :file:`tests` for a :file:`CMakeLists.txt` file
+by extending the list of sub-directories in :file:`sidechains/CMakeLists.txt`:
+
+.. code-block:: cmake
+  :linenos:
+
+   add_subdirectory(pymod)
+   add_subdirectory(doc)
+   add_subdirectory(tests)
+
+Then fill :file:`sidechains/tests/CMakeLists.txt` with your new test script and
+``make`` will recognise the changes next time it is run and fix the rest for
+you.
+
+.. code-block:: cmake
+  :linenos:
+
+   set(SIDECHAINS_UNIT_TESTS
+   test_something.py
+   )
+
+   promod3_unittest(MODULE sidechains SOURCES "${SIDECHAINS_UNIT_TESTS}")
+
+Now tests should be available by ``make check``, ``make codetest`` and
+``make test_something.py_run``.
+
 
 .. _restructuredtext: http://docutils.sourceforge.net/rst.html
 .. |fedora| replace:: Fedora
-
+.. |nameattr| replace:: :attr:`__name__`
 
 ..  LocalWords:  cmake hotfix doctest linkcheck rebase BRANCHNAME rebasing py
 ..  LocalWords:  CMakeLists txt rst pymod init submodule src restructuredtext
 ..  LocalWords:  makefiles formatters Changelog codetest promod sidechains io
 ..  LocalWords:  mkdir linenos subdirectory abrv emphasize CXX GNUCXX gcc fno
 ..  LocalWords:  ARGS endif OPTIMIZE LIBEXEC Wno DIRS dirs subdirs config dbg
-..  LocalWords:  changelog Optimized DOPTIMIZE gitignore cd conf
+..  LocalWords:  changelog Optimized DOPTIMIZE gitignore cd conf subtree attr
+..  LocalWords:  unittest TestCase nameattr testcode staticmethod builtin
+..  LocalWords:  SomethingTests testFileExistsFalse testutils RunTests