# HG changeset patch # User Julien Jehannet # Date 1275327223 -7200 # Node ID 4535f8e57580133183a8426e31c3da24b7466b84 # Parent 9378d13e9ac469c73fcfef11e09468aebff0ae08 [web test] add basic windmill tests and documentation - connection / deconnection - user creation diff -r 9378d13e9ac4 -r 4535f8e57580 doc/book/en/tutorials/index.rst --- a/doc/book/en/tutorials/index.rst Tue Jun 01 17:09:22 2010 +0200 +++ b/doc/book/en/tutorials/index.rst Mon May 31 19:33:43 2010 +0200 @@ -17,3 +17,4 @@ base/index advanced/index + tools/windmill.rst diff -r 9378d13e9ac4 -r 4535f8e57580 doc/book/en/tutorials/tools/windmill.rst --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/doc/book/en/tutorials/tools/windmill.rst Mon May 31 19:33:43 2010 +0200 @@ -0,0 +1,133 @@ +========================== +Use Windmill with CubicWeb +========================== + +Windmill_ implements cross browser testing, in-browser recording and playback, +and functionality for fast accurate debugging and test environment integration. + +.. _Windmill: http://www.getwindmill.com/ + +`Online features list `_ is available. + + +Installation +============ + +Windmill +-------- + +You have to install Windmill manually for now. If you're using Debian, there is +no binary package (`yet `_). + +The simplest solution is to use a *setuptools/pip* command (for a clean +environment, take a look to the `virtualenv +`_ project as well):: + + pip install windmill + curl -O http://github.com/windmill/windmill/tarball/master + +Some install instructions are `available `_. + +Be sure to have the windmill module in your PYTHONPATH afterwards:: + + python -c "import windmill" + +X dummy +------- + +In order to reduce unecessary system load from your test machines, It's +recommended to use X dummy server for testing the Unix web clients, you need a +dummy video X driver (as xserver-xorg-video-dummy package in Debian) coupled +with a light X server as `Xvfb `_. + + The dummy driver is a special driver available with the XFree86 DDX. To use + the dummy driver, simply substitue it for your normal card driver in the + Device section of your xorg.conf configuration file. For example, if you + normally uses an ati driver, then you will have a Device section with + Driver "ati" to let the X server know that you want it to load and use the + ati driver; however, for these conformance tests, you would change that + line to Driver "dummy" and remove any other ati specific options from the + Device section. + + *From: http://www.x.org/wiki/XorgTesting* + +Then, you can run the X server with the following command : + + /usr/bin/X11/Xvfb :1 -ac -screen 0 1280x1024x8 -fbdir /tmp + + +Windmill usage +============== + +Record your use case +-------------------- + +- start your instance manually +- start Windmill_ with url site as last argument (read Usage_ or use *'-h'* + option to find required command line arguments) +- use the record button +- click on save to obtain python code of your use case +- copy the content to a new file in a *windmill* directory + +.. _Usage: http://wiki.github.com/windmill/windmill/running-tests + +If you are using firefox as client, consider the "firebug" option. + +You can refine the test by the *loadtest* windmill option: + + windmill -m firebug loadtest= + + +Integrate Windmill tests into CubicWeb +====================================== + +Run your tests +-------------- + +You can easily run your windmill test suite through `pytest` or :mod:`unittest`. +You have to copy a *test_windmill.py* file from :mod:`web.test`. + +By default, CubicWeb will use **firefox** as the default browser and will try +to run test instance server on localhost. In the general case, You've no need +to change anything. + +Check the :class:`cubicweb.devtools.cwwindmill.CubicWebServerTC` class for server +parameters and :class:`cubicweb.devtools.cwwindmill.CubicWebWindmillUseCase` for +Windmill configuration. + +Best practises +-------------- + +Don't run another instance on the same port. You risk to silence some +regressions (test runner will automatically fail in further versions). + +Start your use case by using an assert on the expected primary url page. +Otherwise all your tests could fail without clear explanation of the used +navigation. + +In the same location of the *test_windmill.py*, create a *windmill/* with your +windmill recorded use cases. + +Then, you can launch the test series with:: + + % pytest test/test_windmill.py + +For instance, you can start CubicWeb framework use tests by:: + + % pytest web/test/test_windmill.py + + +Preferences +=========== + +A *.windmill/prefs.py* could be used to redefine default configuration values. + +.. define CubicWeb preferences in the parent test case instead with a dedicated firefox profile + +For managing browser extensions, read `advanced topic chapter +`_. + +More configuration examples could be seen in *windmill/conf/global_settings.py* +as template. + + diff -r 9378d13e9ac4 -r 4535f8e57580 web/test/test_windmill.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/test/test_windmill.py Mon May 31 19:33:43 2010 +0200 @@ -0,0 +1,42 @@ +from cubicweb.devtools import cwwindmill + + +class CubicWebWindmillUseCase(cwwindmill.CubicWebWindmillUseCase): + """class for windmill use case tests + + From test server parameters: + + :params ports_range: range of http ports to test (range(7000, 8000) by default) + :type ports_range: iterable + :param anonymous_logged: is anonymous user logged by default ? + :type anonymous_logged: bool + + The first port found as available in `ports_range` will be used to launch + the test server + + From Windmill configuration: + + :param browser: browser identification string (firefox|ie|safari|chrome) (firefox by default) + :param test_dir: testing file path or directory (./windmill by default) + """ + #ports_range = range(7000, 8000) + anonymous_logged = False + #browser = 'firefox' + #test_dir = osp.join(os.getcwd(), 'windmill') + + # If you prefer, you can put here the use cases recorded by windmill GUI + # (services transformer) instead of the windmill sub-directory + # You can change `test_dir` as following: + #test_dir = __file__ + + +from windmill.authoring import WindmillTestClient +def test_usecase(): + client = WindmillTestClient(__name__) + import pdb; pdb.set_trace() + client.open(url=u'/') +# ... + + +if __name__ == '__main__': + cwwindmill.unittest_main() diff -r 9378d13e9ac4 -r 4535f8e57580 web/test/windmill/test_connexion.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/test/windmill/test_connexion.py Mon May 31 19:33:43 2010 +0200 @@ -0,0 +1,35 @@ +from cubicweb.devtools import DEFAULT_SOURCES +LOGIN, PASSWORD = DEFAULT_SOURCES['admin'].values() + +# Generated by the windmill services transformer +from windmill.authoring import WindmillTestClient + + +def test_connect(): + client = WindmillTestClient(__name__) + + client.open(url=u'/') + client.asserts.assertJS(js=u"$('#loginForm').is(':visible')") + client.type(text=LOGIN, id=u'__login') + client.type(text=PASSWORD, id=u'__password') + client.execJS(js=u"$('#loginForm').submit()") + client.waits.forPageLoad(timeout=u'20000') + client.asserts.assertJS(js=u'$(\'.message\').text() == "welcome %s !"' % LOGIN) + client.open(url=u'/logout') + client.open(url=u'/') + client.asserts.assertJS(js=u"$('#loginForm').is(':visible')") + +def test_wrong_connect(): + client = WindmillTestClient(__name__) + + client.open(url=u'/') + # XXX windmill wants to use its proxy internally on 403 :-( + #client.asserts.assertJS(js=u"$('#loginForm').is(':visible')") + #client.type(text=LOGIN, id=u'__login') + #client.type(text=u'novalidpassword', id=u'__password') + #client.click(value=u'log in') + client.open(url=u'/?__login=user&__password=nopassword') + client.waits.forPageLoad(timeout=u'20000') + client.asserts.assertTextIn(validator=u'authentication failure', id=u'loginBox') + client.open(url=u'/') + client.asserts.assertJS(js=u"$('#loginForm').is(':visible')") diff -r 9378d13e9ac4 -r 4535f8e57580 web/test/windmill/test_creation.py --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/web/test/windmill/test_creation.py Mon May 31 19:33:43 2010 +0200 @@ -0,0 +1,55 @@ +from cubicweb.devtools import DEFAULT_SOURCES +LOGIN, PASSWORD = DEFAULT_SOURCES['admin'].values() + +# Generated by the windmill services transformer +from windmill.authoring import WindmillTestClient + +def test_creation(): + client = WindmillTestClient(__name__) + + client.open(url=u'/') + client.waits.forPageLoad(timeout=u'8000') + client.type(text=LOGIN, id=u'__login') + client.type(text=PASSWORD, id=u'__password') + client.click(value=u'log in') + client.waits.forPageLoad(timeout=u'20000') + + # pre-condition + client.open(url=u'/cwuser/myuser') + client.asserts.assertJS(js=u'$(\'#contentmain h1\').text() == "this resource does not exist"') + client.open(url=u'/?rql=Any U WHERE U is CWUser, U login "myuser"') + client.asserts.assertJS(js=u'$(\'.searchMessage strong\').text() == "No result matching query"') + + client.open(url=u'/manage') + client.open(url=u'/add/CWUser') + client.type(text=u'myuser', id=u'login-subject:A') + client.type(text=u'myuser', id=u'upassword-subject:A') + client.type(text=u'myuser', name=u'upassword-subject-confirm:A') + client.type(text=u'myuser', id=u'firstname-subject:A') + client.select(val=u'4', id=u'in_group-subject:A') + client.waits.forPageLoad(timeout=u'20000') + client.click(id=u'adduse_email:Alink') + client.waits.forPageLoad(timeout=u'20000') + client.type(text=u'myuser@logilab.fr', id=u'address-subject:B') + client.waits.forPageLoad(timeout=u'20000') + client.click(value=u'button_ok') + client.waits.forPageLoad(timeout=u'20000') + client.asserts.assertJS(js=u'$(\'.message\').text() == "entity created"') + client.open(url=u'/?rql=Any U WHERE U is CWUser, U login "myuser"') + client.asserts.assertJS(js=u'$(\'#contentmain h1\').text() == "myuser"') + client.waits.forPageLoad(timeout=u'8000') + client.open(url=u'/cwuser/myuser?vid=sameetypelist') + client.waits.forPageLoad(timeout=u'8000') + client.asserts.assertJS(js=u'$(\'#contentmain a\').text() == "myuser"') + client.open(url=u'/cwuser/myuser?vid=text') + client.waits.forPageLoad(timeout=u'8000') + client.asserts.assertJS(js=u'$(\'#contentmain\').text() == "\\nmyuser"') + client.open(url=u'/cwuser/myuser?vid=deleteconf') + client.waits.forElement(timeout=u'8000', value=u'button_delete') + client.click(value=u'button_delete') + client.waits.forPageLoad(timeout=u'8000') + client.open(url=u'/cwuser/myuser') + client.asserts.assertJS(js=u'$(\'#contentmain h1\').text() == "this resource does not exist"') + client.open(url=u'/?rql=Any U WHERE U is CWUser, U login "myuser"') + client.asserts.assertJS(js=u'$(\'.searchMessage strong\').text() == "No result matching query"') +