Breve introduzione a plone.app.testing

Un "nuovo" e potente strumento che migliora lo sviluppo dei test nelle nostre applicazioni Plone e conferma la grande attenzione che la comunità Plone ha verso il test driven development

Ho avuto l'occasione di provare il nuovo prodotto plone.app.testing e devo dire che sono rimasto positivamente impressionato. L'attenzione verso i test è sempre stata alta all'interno della comunità Plone ed anche questo strumento, che organizza e semplifica l'impostazione dei test, è all'altezza delle aspettative.

Cosa cambia con plone.app.testing?

La principale differenza, rispetto al precedente approccio ai test, è che plone.app.testing ci obbliga ad organizzare i nostri test secondo una serie di layer che si occupano di creare una serie di configurazioni ad hoc per i nostri test.

Ogni layer è quindi 'indipendente' dagli altri e deve contenere solamente le configurazioni necessarie per una specifica serie di test.

Sarà il sistema, durante l'esecuzione dei test, ad occuparsi dell'organizzazione e dell'ordinamento degli stessi in base ai layer. In questo modo i test appartenenti al medesimo layer vengono eseguiti insieme risparmiando tempo nella loro esecuzione.

All'interno di plone.app.testing sono già definiti alcuni layer preconfigurati che semplificano ulteriormente il lavoro: avremo quindi layer specifici per gli unittest, per i test di integrazione, fuzionali ecc.

Come districarsi nella foresta

Iniziamo dalla configurazione di una specifica sezione del buildout

...
[tests] recipe = zc.recipe.testrunner eggs = egg.da.testare [test]
...

In questo modo, grazie a zc.recipe.testrunner, abbiamo definito una specifica sezione ed incluso il nostro pacchetto tra gli egg da testare.

Specificando l'opzione [test] indichiamo inoltre che per il nostro pacchetto dovranno essere prese in considerazione delle specifiche dipendenze definite all'interno del nostro prodotto nel seguente modo:

# setup.py
...
extras_require = {
'test': [
'plone.app.testing',
...
]
},
...

ora possiamo creare il nostro primo layer che sarà basato su PLONE_FIXITURE, un layer predefinito in plone.app.testing:

from plone.app.testing import PloneSandboxLayer
from plone.app.testing import PLONE_FIXTURE

class MyLayer(PloneSandboxLayer):
defaultBases = (PLONE_FIXTURE, )

def setUpZope(self, app, configurationContext):
"""Qui configuro l'istanza Zope importando,
per esempio, le direttive zcml del mio prodotto
"""
import my.package
self.loadZCML(package=my.package)

def setUpPloneSite(self, portal):
"""Qui posso gestire alcune impostazioni di base di Plone.
Per esempio installo il prodotto da testare
"""
self.applyProfile(portal, 'my.package:default')

def tearDownZope(self, app):
"""Qui posso inserire tutto quello che dev'essere
eseguito alla fine del test
"""

a questo punto possiamo istanziare una serie di variabili per gestire test:

MYPACKAGE_FIXTURE = MyLayer()

from plone.app.testing import IntegrationTesting
MYPACKAGE_INTEGRATION_TESTING = IntegrationTesting(
bases=(MYPACKAGE_FIXTURE, ),
name="MyPackage:Integration")

from plone.app.testing import FunctionalTesting
MYPACKAGE_FUNCIONAL_TESTING = FunctionalTesting(
bases=(MYPACKAGE_FIXTURE, ),
name="MyPackage:Functional")

ed utilizzarle in un test:

import unittest

class MyIntegrationTestClass(unittest.TestCase):
layer = MYPACKAGE_INTEGRATION_TESTING

def test_dummy(self):
"""Un utile test!!"""
self.assertEquals(2+2, 4)

Considerazioni

Penso che questo strumento sia eccezionale per la realizzazione dei test in Plone e consente di migliorare il processo di definizione degli stessi.

Occorre però abituarsi ad alcune piccole cose dovute al meccanismo dei layer. I layer di default si occupano infatti di configurare lo stretto necessario e quindi dobbiamo essere noi stessi a definire al loro interno tutto quello di cui abbiamo bisogno.

Ecco alcune cose da ricordare:

  1. se abbiamo un prodotto Zope2 che utilizza il metodo initialize. Ovvero un classico prodotto per Archetypes dobbiamo ricordarci di installarlo manualmente all'interno del layer.
  2. il plugin zc.autoinclude non funziona all'interno dei layer quindi dobbiamo ricordarci di includere tutti i file zcml necessari
  3. portal adesso è impostato come chiave di self.layer in questo modo: self.layer['portal']
  4. per eseguire operazioni con un ruolo Plone particolare possiamo usare: plone.app.testing.setRoles

Altre informazioni

blog comments powered by Disqus