upc testing talk 2

32
 Testing for fun and profit – Part 2 April, 27 th  2010 Timo Stollenwerk

Upload: plone-foundation

Post on 08-May-2015

1.530 views

Category:

Technology


0 download

TRANSCRIPT

Page 1: UPC Testing talk 2

   

Testing for fun and profit – Part 2

April, 27th 2010

Timo Stollenwerk

Page 2: UPC Testing talk 2

   

Part 1 – Why testing matters

● Reduces defects● Find bugs early● Proof that you delivered what you were 

contracted to produce● Refactor with confidence● Lots of small successes

Page 3: UPC Testing talk 2

   

Testing pyramid

Page 4: UPC Testing talk 2

   

What are you going to learn today?

● Set up integration and functional tests● Traditional test setup● Test setup with layers

● Testing● Policy product● Dexterity types● Archetypes● Portlets

Page 5: UPC Testing talk 2

   

The current state of testing in Plone

● Plone 3 / PPD / Paster● collective.testcaselayer● plone.testing

Page 6: UPC Testing talk 2

   

Plone 3 test structure

$ paster create ­t archetype upc.myarchetype 

● tests● __init__.py● base.py● test_doctest.py

Page 7: UPC Testing talk 2

   

Test setup: base.py

● Import ZopeTestCase and PloneTestCase● setup_product function● setupPloneSite● TestCase & FunctionalTestCase

Page 8: UPC Testing talk 2

   

Test setup: base.py (import)

from Testing import ZopeTestCase as ztc

from Products.PloneTestCase import PloneTestCase as ptc

from Products.PloneTestCase.layer import onsetup

Page 9: UPC Testing talk 2

   

Test setup: base.py (setup_product)

@onsetup

def setup_product():

    fiveconfigure.debug_mode = True

    import upc.myarchetype

    zcml.load_config('configure.zcml', upcexample.myarchetype)

    fiveconfigure.debug_mode = False

    ztc.installPackage('upcexample.theme')

Page 10: UPC Testing talk 2

   

Test setup: base.py (test classes)

class TestCase(ptc.PloneTestCase):

    """We use this base class for all the tests in this package. If

    necessary, we can put common utility or setup code in here. This

    applies to unit test cases.

    """

class FunctionalTestCase(ptc.FunctionalTestCase):

    """We use this class for functional integration tests that use

    doctest syntax. Again, we can put basic common utility or setup

    code in here.

    ""”

Page 11: UPC Testing talk 2

   

TestCasefrom upcexample.myproduct.tests.base import TestCase

class TestSetup(TestCase):

    

    def afterSetUp(self):

        self.workflow = getToolByName(self.portal, 'portal_workflow')

    

    def test_portal_title(self):

        self.assertEquals("UPC Portal", self.portal.getProperty('title'))

def test_suite():

    suite = unittest.TestSuite()

    suite.addTest(unittest.makeSuite(TestSetup))

    return suite

Page 12: UPC Testing talk 2

   

FunctionalTestCaseimport unittest

import doctest

from Testing import ZopeTestCase as ztc

from upctest.myproduct.tests import base

def test_suite():

    return unittest.TestSuite([

        # Demonstrate the main content types

        ztc.ZopeDocFileSuite(

            'README.txt', package=upctest.myproduct',

            test_class=base.FunctionalTestCase,

            optionflags=doctest.REPORT_ONLY_FIRST_FAILURE |

                doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS),

        ])

if __name__ == '__main__':

    unittest.main(defaultTest='test_suite')

Page 13: UPC Testing talk 2

   

FunctionalTestCase Doctest

Being a doctest, we can tell a story here.

>>> from Products.Five.testbrowser import Browser

>>> browser = Browser()

>>> portal_url = self.portal.absolute_url()

Page 14: UPC Testing talk 2

   

FunctionalTestCase: Login

    >>> from Products.PloneTestCase.setup import portal_owner, default_password

    >>> browser.open(portal_url)

We have the login portlet, so let's use that.

    >>> browser.getControl(name='__ac_name').value = portal_owner

    >>> browser.getControl(name='__ac_password').value = default_password

    >>> browser.getControl(name='submit').click()

Page 15: UPC Testing talk 2

   

FunctionalTestCase: Properties

    >>> browser.url == portal_url

    True

    >>> "You are now logged in" in browser.contents

    True

    >>> 'foo' in browser.headers

    False

Page 16: UPC Testing talk 2

   

FunctionalTestCase: Actions

­ browser.open(url)

­ browser.reload()

­ browser.goBack(count=1)

­ browser.getLink(text=None, url=None, id=None)

­ browser.click()

­ browser.getControl(label=None, name=None, index=None)

Page 17: UPC Testing talk 2

   

Zope Testrunner (Plone 3)

● Test package

$ ./bin/instance test ­s upcexample.myproduct

Page 18: UPC Testing talk 2

   

Zope Testrunner (Plone 3)

● Test single file

$ ./bin/instance test ­s upcexample.myproduct ­t test_setup

Page 19: UPC Testing talk 2

   

Zope Testrunner (Plone 3)

● Unit/Integration tests only

$ ./bin/instance test ­s upcexample.myproduct ­u

Page 20: UPC Testing talk 2

   

Zope Testrunner (Plone 3)

● Debug

$ ./bin/instance test ­D

Page 21: UPC Testing talk 2

   

Setting Up Tests with Layers

● Tests (upc.testingtutorial / example.conference)● __init__.py● layer.py● test_functional_doctest.py● functional.txt● test_task.py

Page 22: UPC Testing talk 2

   

Setting Up Tests with Layers: layer.py

# Imports

ptc.setupPloneSite(

    extension_profiles=('upc.testingtutorial:default', )

)

class IntegrationTestLayer(collective.testcaselayer.ptc.BasePTCLayer):

    def afterSetUp(self):

        self.addProfile('upc.testingtutorial:default')

Layer = IntegrationTestLayer([collective.testcaselayer.ptc.ptc_layer])

Page 23: UPC Testing talk 2

   

Setting Up Tests with Layers: test_functional_doctest.py

# Imports

from upc.testingtutorial.tests.layer import Layer

def test_suite():

    return unittest.TestSuite([

        ztc.ZopeDocFileSuite(

            'functional.txt', package='upc.testingtutorial.tests',

            test_class=ptc.FunctionalTestCase,

            optionflags=doctest.REPORT_ONLY_FIRST_FAILURE | doctest.NORMALIZE_WHITESPACE | doctest.ELLIPSIS),

        ])

Page 24: UPC Testing talk 2

   

Setting Up Tests with Layers: functional.txt

==========================================

 UPC Testing Tutorial: Functional Doctest

==========================================

This package contains a functional doctest for the task content type of the

upc.testringtutorial package. In this testbrowser doctest, we will demonstrate 

how the task content type works. See tests/test_functional_doctest.py for how 

it is set up.

    >>> from Products.Five.testbrowser import Browser

    >>> browser = Browser()

    >>> portal_url = self.portal.absolute_url()

Page 25: UPC Testing talk 2

   

Setting Up Tests with Layers: test_task.py

class TestTaskIntegration(PloneTestCase):

    

    layer = Layer

    

    def test_adding(self):

        self.folder.invokeFactory('upc.testingtutorial.task', 'task1')

        t1 = self.folder['task1']

        self.failUnless(ITask.providedBy(t1))

    

def test_suite():

    return unittest.defaultTestLoader.loadTestsFromName(__name__)

Page 26: UPC Testing talk 2

   

Zope Testrunner (Plone 4)

[buildout]

parts = 

    ...

    test

[test]

recipe = zc.recipe.testrunner

eggs =  upcexample.myproduct

defaults = ['­v', '­­exit­with­status', '­­auto­color', '­­auto­progress']

Page 27: UPC Testing talk 2

   

Zope Testrunner (Plone 4)

● Run all tests

$ ./bin/test● Test one package

$ ./bin/test ­s upcexample.mypackage

...

Page 28: UPC Testing talk 2

   

Testing Portlets

class TestPortlet(TestCase):

    def afterSetUp(self):

        self.setRoles(('Manager',))

    …

class TestRenderer(TestCase):    

    def afterSetUp(self):

        self.setRoles(('Manager',))

        self.portal.invokeFactory('Folder', 'cf1')

    ....

http://svn.plone.org/svn/collective/collective.portlet.recentactivity/trunk/collective/portlet/recentactivity/tests/test_portlet_recent_activity.py

Page 29: UPC Testing talk 2

   

Testing Viewlets

class TestCommentsViewletIntegration(FunctionalTestCase):

    layer = DiscussionLayer

    def testCommentsViewlet(self):

        browser = Browser()

        portal_url = self.portal.absolute_url()

        browser.handleErrors = False

        from Products.PloneTestCase.setup import portal_owner, default_password

        browser.open(portal_url + '/login_form')

http://svn.plone.org/svn/plone/plone.app.discussion/trunk/plone/app/discussion/tests/test_comments_viewlet.py

Page 30: UPC Testing talk 2

   

Summary

● Setting up tests● Traditional way (PPD / Optilux / ZopeSkel)

● Testcaselayer (Dexterity manual)

● Future: plone.testing

● Archetypes● PPD / Optilux / ZopeSkel

● Dexterity● Dexterity manual (example.conference)

● Portlet● ZopeSkel / Paster output

● Viewlet● plone.app.discussion / plone.app.layout (search for *test*.py)

Page 31: UPC Testing talk 2

   

Testing Resources

● Plone Testing Tutorial● http://plone.org/documentation/kb/testing

● Plone 3 / Archetypes ● PPD / Optilux

● Plone 4 / Dexterity Manual / example.conference● http://plone.org/products/dexterity/documentation/manual/developer­manual● http://svn.plone.org/svn/collective/example.conference/ 

Page 32: UPC Testing talk 2

   

The End