==================== Functional doc tests ==================== Doctests are a way to write tests while documenting the thing that is tested at the same time. As an example, this file both documents functional doc tests *and* tests them. Doctests look like regular interactive interpreter sessions. That makes them very easy to create. Doctests can either occur in an object's or method's docstring or in a separate file. Use either ``DocTestSuite`` or ``DocFileSuite`` in these cases. Creating functional doctests ---------------------------- Creating functional doctests is just as easy. Obviously, you cannot simply use an interpreter shell for the initial test creation. Instead, you can use the `tcpwatch` program to record browser sessions and turn them into tests: 1. Start out with a clean ZODB database. - Create a folder named `test_folder_1_` in the root folder. - Create a user in the root user folder called `test_user_1_` with the password `secret`. - Create a role `test_role_1_` and grant the role to the test user. Grant the permissions 'Access contents information' and 'View' to the role. 2. Install tcpwatch. You can get a recent version from Zope CVS: http://cvs.zope.org/Packages/tcpwatch/ 3. Create a temporary directory to record tcpwatch output. 4. Run tcpwatch using: tcpwatch.py -L 8081:8080 -s -r tmpdir (the ports are the listening port and forwarded-to port; the second port must match the Zope configuration) 5. In a browser, connect to the listening port and do whatever needs to be recorded. 6. Shut down tcpwatch. 7. Run the script at Zope/lib/python/Testing/ZopeTestCase/doctest/dochttp.py python2.3 dochttp.py tmpdir > .../mytest.txt 8. Edit the generated text file to add explanations and elide uninteresting portions of the output. 9. In a functional test module (usually ftests.py), import ``FunctionalDocFileSuite`` and instantiate it, passing the name of the text file containing the test. For example: from unittest import TestSuite from Testing.ZopeTestCase import FunctionalDocFileSuite def test_suite(): return TestSuite(( FunctionalDocFileSuite('FunctionalDocTest.txt'), )) Examples -------- Test Publish Document >>> print http(r""" ... GET /test_folder_1_/index_html HTTP/1.1 ... """, handle_errors=False) HTTP/1.1 200 OK Content-Length: 5 Content-Type: text/plain; charset=... index Test parameter containing an additional '?' >>> print http(r""" ... GET /test_folder_1_?foo=bla%3Fbaz HTTP/1.1 ... """) HTTP/1.1 200 OK Content-Length: 5 Content-Type: text/plain; charset=iso-8859-15 index Test Unauthorized >>> self.folder.index_html.manage_permission('View', ['Owner']) >>> print http(r""" ... GET /test_folder_1_/index_html HTTP/1.1 ... """, handle_errors=True) HTTP/1.1 401 Unauthorized ... Www-Authenticate: basic realm=... Test Basic Authentication >>> from AccessControl.Permissions import manage_properties >>> self.setPermissions([manage_properties]) >>> print http(r""" ... GET /test_folder_1_/index_html/change_title?title=Foo HTTP/1.1 ... Authorization: Basic %s ... """ % user_auth, handle_errors=False) HTTP/1.1 200 OK Content-Length: 0 ... >>> self.folder.index_html.title_or_id() 'Foo' Test passing in non-base64-encoded login/pass >>> from Testing.ZopeTestCase import user_name, user_password >>> print http(r""" ... GET /test_folder_1_/index_html/change_title?title=Baz HTTP/1.1 ... Authorization: Basic %s:%s ... """ % (user_name, user_password), handle_errors=False) HTTP/1.1 200 OK Content-Length: 0 ... >>> self.folder.index_html.title_or_id() 'Baz' Test setting cookies >>> print http(r""" ... GET /test_folder_1_/index_html/set_cookie HTTP/1.1 ... """, handle_errors=False) HTTP/1.1 200 OK Content-Length: 0 ... Set-Cookie: cookie_test="OK" Test reading cookies >>> print http(r""" ... GET /test_folder_1_/index_html/show_cookies HTTP/1.1 ... Cookie: foo=bar; baz="oki doki" ... """, handle_errors=False) HTTP/1.1 200 OK Content-Length: 23 Content-Type: text/plain; charset=... foo: bar baz: oki doki