[Cubicweb] Simple forms unit-testing

Florent Cayré florent at secondweb.fr
Fri Nov 26 10:40:23 CET 2010


Hi Adrien,

this is great and I would find it very useful in CW.

At SecondWeb we used to perform a lot of form testing, but rather on
the HTML side, so that we could also test HTML generation in widgets,
form choices functions and the like. When you do that, you really need
helpers like get all select or input radio options, check a select
field class attribute and the like, as plain xpath is very powerful
but difficult to read. It would be interesting to have some of these
helpers easily accessible in the context of your form tests.

I look forward to read about this in the CW book ;-)
Cheers,
Florent.

2010/11/26 Adrien Di Mascio <adrien.dimascio at logilab.fr>
>
> Hi,
>
> In one of my projects, I've implemented a somewhat simple API to test the form rendering and submission. Let me tell immediately that this is **pure python / off-browser** testing and therefore means that this won't test any javascript / css / user interaction.
>
> Using a lot of of forms in my application, my goal here was to be able to test automatically :
>
> - visible fields (i.e. 'hidden', 'visible' fields in uicfg)
> - fields order
> - redirect urls after form submission
>
> Here are a few examples of what it looks like:
>
>    def test_company_creation_redirectpath(self):
>        # 1/ build a creation form for Company entity type
>        form = self.creation_form('Company')
>        # 2/ set a few values
>        form.set_value('name', u'Logilab')
>        form.set_value('phone', u'01.02.03.04.05')
>        # 3/ submit and check redirection
>        self.assertRedirectsTo(form, '/Company/Logilab')
>
>    def test_company_edition_redirectpath(self):
>        company = self.create_entity('Company', name=u'Logilab')
>        # 1/ get the edition form for the `company` entity
>        form = self.edition_form(company)
>        # 2/ set a few values
>        form.set_value('phone', u'01.02.03.04.05')
>        # 3/ submit and check redirection
>        self.assertRedirectsTo(form, '/Company/Logilab')
>
>    def test_company_form_visible_fields(self):
>        # 1/ build a creation form for Company entity type
>        form = self.creation_form('Company')
>        # 2/ check order of visible fields
>        self.assertEqual(form.visible_fields(),
>                         ['name', 'website', 'phone'])
>        self.assertItemsEqual(form.edited_fields(),
>                              ('__type', 'logo-subject',
>                               'name-subject', 'website-subject',
>                               'phone-subject'))
>
>    def test_company_inlined_forms(self):
>        form = self.creation_form('Company')
>        form.set_value('name', u'Logilab')
>        # get the inlined form for the 'logo' relation
>        logo_form = form.inlined_forms('logo')[0]
>        self.assertItemEqual(logo_form.edited_fields(),
>                             ('__type', 'data-subject',
>                              'logo-object'))
>        self.assertEqual(logo_form.visible_fields(), ['data'])
>        logo_form.set_value('data',
>                            file(self.datapath('logo.jpg')))
>        self.assertRedirectsTo(form, '/Company/Logilab')
>        # database now contains a new company with a logo, more
>        # tests can be done on submitted data
>
>
> The underlying mechanism is fairly simple :
>
> - the object returned by `creation_form()` and `edition_form()`
>  methods is a wrapper around the CW form object (which is available
>  as a `cw_form` attribute)
> - this object has a few helper methods such as `edited_fields()`,
>  `set_value()`, `get_value()`, etc.
> - this object holds also the lxml tree corresponding to the actual HTML
> - `get_value` and `set_value` methods use the lxml tree to get / set
>  input values
> - form submission consists in three steps :
>  1. using lxml's form_values() method to build a dict-like object
>     based on actual input values
>  2. building a CubicWeb's request object around that dict-like object
>  3. using ctrl_publish() to process the request and go through the
>     edit controller chain
>
> As usual, any thoughts on that ? Any interest outside my project ? If so, is the API clear enough ? Should it be integrated in CubicWeb ?
>
> --
> Adrien Di Mascio - LOGILAB, Paris (France).
> Tél: 01.45.32.03.12
> Formations - http://www.logilab.fr/formations
> Développements - http://www.logilab.fr/services
> Gestion de connaissances - http://www.cubicweb.org/
> _______________________________________________
> Cubicweb mailing list
> Cubicweb at lists.cubicweb.org
> http://lists.cubicweb.org/mailman/listinfo/cubicweb



More information about the Cubicweb mailing list