= Testing = "A bug is a test case you haven't written yet" [[BR]] "Unit Tests allow merciless [http://diveintopython.org/refactoring/refactoring.html refactoring]" This page defines what our current approach versus our [wiki:BluePrintTesting BluePrint for future options] Test-Driven Development is a programming styles which says that you 1st write your test cases (from the [BluePrints specs]) & then proceed to make them pass. [wiki:InstallationGuidelinesDeveloper#TestingSetup] == Functional Tests == Building the Right Code We have integrated [http://seleniumhq.org/projects/core Selenium Core] into {{{/static/selenium}}} so that Functional Tests can be run (via 'Test' menu option visible to Admins). Additional functions (e.g. Random) are added to: {{{ /static/selenium/core/scripts/user-extensions.js }}} !ToDo: create a {{{HandleResults.py}}} for storing results (to make visible to CI): * e.g. Convert this one from PHP: http://wiki.openqa.org/display/SEL/Integrating+Selenium+And+CruiseControl.Net * e.g. Extract from [http://jrandolph.com/selenium-plone/selenium-0.3rc2-plone.zip PloneTool]'s {{{FunctionalTestTool.py}}} Tests can be developed using [http://seleniumhq.org/projects/ide Selenium IDE], if desired. If desired they can be maintained in a Python format using [http://joker.linuxstuff.pl/documentation/make_selenium make_selenium.py]. HTML tests run by !TestRunner are in {{{/static/selenium/tests}}}. Python format tests are in {{{/static/selenium/src}}}. Convert between these using: {{{ python make_selenium.py src tests python make_selenium.py -p tests src }}} == Unit Tests == Building the Code Right [http://seleniumhq.org/projects/remote-control Selenium RC] is great due to ability to handle !JavaScript & also due to having an [http://seleniumhq.org/projects/ide IDE] for generating them (export as Python).[[BR]] The IDE output needs to be [http://groups.google.com/group/web2py/msg/d8c9fd6008029f6b modified] to work with Web2Py.[[BR]] NB Custom functions (e.g. for Random) cannot be shared with the Functional Tests (custom=JS) but the rest of the tests can be.[[BR]] These tests are stored in {{{/tests}}}.[[BR]] !ToDo: Port the storeRandom function from JS to Python: {{{ import random print "test_%i@xxxxxxxx" % random.randint(1, 10000) }}} !ToDo: Investigate how we can test multiple browsers. [http://cherrypy.org CherryPy]'s [http://cherrypy.org/browser/trunk/cherrypy/test/webtest.py WebTest] is good for in-process testing & can be run from a browser-less server(easier for CI-integration).[[BR]] These tests are stored in {{{/tests/webtest}}}.[[BR]] NB These are a work-in-progress...need to enable access to Web2Py environment (db, etc) using: {{{ from gluon.shell import exec_environment env=exec_environment('the_model_file.py') }}} Or could write as a 'Controller' & call from CLI: {{{ python web2py.py -S appname -M -R yourscript.py }}} == Doc Tests == Agile documentation which can be run using Web2Py's Admin UI. * http://www.python.org/doc/2.6/library/doctest.html * e.g. http://127.0.0.1:8000/admin/default/test/sahana/default.py To extend these to web applications, we have a module which uses [http://code.google.com/p/wsgi-intercept wsgi_intercept] & [http://cherrypy.org CherryPy]'s [http://cherrypy.org/browser/trunk/cherrypy/test/webtest.py WebTest]: {{{modules/s3_test.py}}} [[BR]] This can be used from Controllers like: {{{ def login(): """ Login >>> from applications.sahana.modules.s3_test import WSGI_Test >>> test=WSGI_Test(db) >>> '200 OK' in test.getPage('/sahana/%s/login' % module) True >>> test.assertHeader("Content-Type", "text/html") >>> test.assertInBody('Login') """ }}} This works fine,although if an assert fails then the UI gets stuck :/ [[BR]] The 'db' access part isn't yet working. Note that Web2Py uses a big doctest at the end of each file: {{{def test_all()}}} == Continuous Integration == We are starting to use the Trac-integrated [http://bitten.edgewall.org Bitten] to monitor code quality. !ToDo: Write a step to parse/store the results of Selenium's {{{HandleResults.py}}} {{{ }}} ToDo: Amend so that it can find the {{{gluon}}} module (or configure to not follow this dependency):[[BR]] {{{ImportError: Unable to find module for modules/validators.py in /tmp/bittenA787wC/build_Trunk_1}}}[[BR]] ToDo: Fix Windowss: {{{Error opening pylint results file ([Errno 2] No such file or directory: 'c:\\docume~1\\username\\locals~1\\temp\\bittenxx1j1x\\build_Trunk_3\\pylint-report.txt')}}} We need to write a {{{build/test-results.xml}}} for this one: {{{ }}} This one is pointless for us as we don't build anything using a {{{setup.py}}}: {{{ }}} ---- DeveloperGuidelines