plone testingdzug tagung2010

44
Plone Testing DZUG Tagung Dresden 2010 Timo Stollenwerk

Upload: plone-foundation

Post on 08-May-2015

647 views

Category:

Documents


0 download

TRANSCRIPT

Page 1: Plone testingdzug tagung2010

Plone Testing

DZUG Tagung Dresden 2010

Timo Stollenwerk

Page 2: Plone testingdzug tagung2010

Timo Stollenwerk

● Plone Entwickler seit 2004● GSoC 2009: plone.app.discussion

● ~ 120 Tests● Python und Javascript● Code Analysis (Pylint, ZPTLint, JSLint)● Code Coverage● Continuous Integration

Page 3: Plone testingdzug tagung2010

Material

● Folien:● slideshare.net/tisto

● Code:● svn.plone.org/svn/collective/examples/example.dzu

gconference/example.dzugconference

Page 4: Plone testingdzug tagung2010

Was ist ein Test?

Page 5: Plone testingdzug tagung2010

Test Beispiel

def is_palindrome(word):

pass

def test_palindromic_word():

assert is_palindrome("noon") == True

assert is_palindrome("foo") == False

Page 6: Plone testingdzug tagung2010

Python Unittest Testcase

http://docs.python.org/library/unittest.html

import unittest

class TestIsPalindrome(unittest.TestCase):

def test_palindromic_word():

self.assertEquals(is_palindrome("noon"), True)

self.failIf(is_palindrome("foo"))

def test_non_string_raises_exception():

self.UnlessRaises(TypeError, is_palindrome, 2)

Page 7: Plone testingdzug tagung2010

Warum sind Tests wichtig?

Page 8: Plone testingdzug tagung2010

Warum Testen?

● Robusterer Code● Besseres Code Verständnis● Nachweis● Dokumentation von Software Anforderungen● „Billigeres“ Bugfixing● Refactoring

Page 9: Plone testingdzug tagung2010

Was ist Test-Driven Development?

Page 10: Plone testingdzug tagung2010

Test-Driven Development

Kent Beck: Test Driven Development

Page 11: Plone testingdzug tagung2010

Arten von Tests

Page 12: Plone testingdzug tagung2010

Funktionale Tests

● Funktionaler Ablauf● Benutzersicht● BlackBox Testing● Akzeptanztests

Page 13: Plone testingdzug tagung2010

XP/Scrum und Funktionale Tests

● Abbildung von (Software) Anforderungen durch User Stories / Acceptance Tests

● Testbare Spezifikation● Code der die Tests besteht● => Beweist das die Software tut was sie soll

Page 14: Plone testingdzug tagung2010

User Stories mit (Doc)Tests

As a logged-in user, I can add a new page to the website.

Page 15: Plone testingdzug tagung2010

Beispiel Funktionaler Doctest

>>> browser.open(portal_url)

>>> browser.getLink(id='example-dzugconference-presenter').click()

>>> browser.getControl(name='form.widgets.title').value = "Presenter 1"

>>> browser.getControl(name='form.buttons.save').click()

Plone SVN: plone.app.discussion/.../presenter.txt

Page 16: Plone testingdzug tagung2010

zope.testbrowser

● browser.open('http://nohost/plone/')● browser.getLink(link_text).click()● browser.url● browser.reload()● browser.getControl(input_name).value =

‘Whatever’● browser.getControl(name='form.buttons.save').

click()

http://pypi.python.org/pypi/zope.testbrowser

Page 17: Plone testingdzug tagung2010

zope.testbrowser debugging

open('/tmp/testbrowser.html','w').write(browser.contents)

Page 18: Plone testingdzug tagung2010

Interlude (Interaktives Debugging)

import interlude

suite = DocFileSuite(...,

globs={'interact': interlude.interact},

...)

>>> interact( locals() )

http://pypi.python.org/pypi/interlude/

Page 19: Plone testingdzug tagung2010

Testing Pyramide

Page 20: Plone testingdzug tagung2010

Integrationstests

● Testet die Zusammenarbeit voneinander abhängiger Komponenten

Page 21: Plone testingdzug tagung2010

Beispiel Integrationstest

class IPresenter(form.Schema):

title = schema.TextLine(

title=_(u"Title")

)

...

Page 22: Plone testingdzug tagung2010

Was wollen wir testen?

● Schema● Typ Registrierung (FTI)● Factory● Hinzufügen des Inhaltstyps● View

Page 23: Plone testingdzug tagung2010

Integrationstests: setUp

def setUp(self):

self.portal = self.layer['portal']

setRoles(self.portal, TEST_USER_NAME, ['Manager'])

self.portal.invokeFactory('Folder', 'test-folder')

setRoles(self.portal, TEST_USER_NAME, ['Member'])

self.folder = self.portal['test-folder']

Page 24: Plone testingdzug tagung2010

Integrationstest: Schema

def test_schema(self):

fti = queryUtility(IDexterityFTI,

name='example.dzugconference.presenter')

schema = fti.lookupSchema()

self.assertEquals(IPresenter, schema)

Page 25: Plone testingdzug tagung2010

Integrationstest: FTI

def test_fti(self):

fti = queryUtility(IDexterityFTI,

name='example.dzugconference.presenter')

self.assertNotEquals(None, fti)

Page 26: Plone testingdzug tagung2010

Integrationstest: Factory

def test_factory(self):

fti = queryUtility(IDexterityFTI,

name='example.dzugconference.presenter')

factory = fti.factory

new_object = createObject(factory)

self.failUnless(

IPresenter.providedBy(new_object))

Page 27: Plone testingdzug tagung2010

Integrationstest: Hinzufügen

def test_adding(self):

self.folder.invokeFactory(

'example.dzugconference.presenter',

'presenter1')

p1 = self.folder['presenter1']

self.failUnless(IPresenter.providedBy(p1))

Page 28: Plone testingdzug tagung2010

Integrationstest: View

def test_view(self):

self.folder.invokeFactory(

'example.dzugconference.presenter',

'presenter1')

p1 = self.folder['presenter1']

view = p1.restrictedTraverse('@@view')

self.failUnless(view)

Page 29: Plone testingdzug tagung2010

Integrationstest: Debugging

def test_todo(self):

import pdb; pdb.set_trace()

import ipdb; ipdb.set_trace()

Page 30: Plone testingdzug tagung2010

Testing Pyramide

Page 31: Plone testingdzug tagung2010

Unit Tests in Plone

● Test einer isolierten Komponente● Wie?● => Mock Objects

Page 32: Plone testingdzug tagung2010

Mock und Fake Objekte

● Externe Datenbanken● Web Services● Plone Komponenten● Netzwerkverbindungen● Benötigen externe Komponenten

http://plone.org/products/dexterity/documentation/manual/developer-manual/testing/mock-testing

http://pypi.python.org/pypi/plone.mocktestcase

Page 33: Plone testingdzug tagung2010

Setup Tests

● Professional Plone Development● Layer / collective.testcaselayer● plone.testing / plone.app.testing

Page 34: Plone testingdzug tagung2010

Test Setup (PPD)

TestPortlet(CinemaContentTestCase):

def afterSetUp(self):

...

PPD: Optilux Code Examples

Page 35: Plone testingdzug tagung2010

Test Setup (Layer)

class CommentTest(PloneTestCase):

layer = DiscussionLayer

def afterSetUp(self):

...

http://svn.plone.org/svn/plone/plone.app.discussion/trunk

Page 36: Plone testingdzug tagung2010

Test Setup (plone.testing)

class ExampleDzugConference(PloneSandboxLayer):

defaultBases = (PLONE_FIXTURE,)

def setUpPloneSite(self, portal):

...

Collective SVN: examples/examples.dzugconference

Page 37: Plone testingdzug tagung2010

Testrunner

parts += test

[test]

recipe = zc.recipe.testrunner

eggs = ${instance:eggs}

defaults = ['--auto-color', '--auto-progress']

Page 38: Plone testingdzug tagung2010

Test Geschwindigkeit

Integrations-Tests vs. Funktionale Tests

● plone.app.discussion● Test Setup (Plone Site): 9,5 Sekunden● 116 Integrationstests: 15 Sekunden (+ 6,5)● 1 Funktionaler Test: 21.5 Sekunden (+ 12,0)

Page 39: Plone testingdzug tagung2010

Testing Pyramide

Page 40: Plone testingdzug tagung2010

Test Abdeckung

buildout.cfg

[coverage-test]

recipe = zc.recipe.testrunner

eggs = ${test:eggs}

defaults = ['--coverage', '../../coverage', '-v', '--auto-progress']

[coverage-report]

recipe = zc.recipe.egg

eggs = z3c.coverage

arguments = ('coverage', 'report')

Page 41: Plone testingdzug tagung2010

Hudson Continuous Integration

http://hudson.zmag.de/hudson

Page 42: Plone testingdzug tagung2010

Weitere Tests

● Python● Pylint

● Templates● ZPTLint

● Javascript● JSLint● qUnit

svn.plone.org/svn/plone/plone.app.discussion/trunk/test-plone-4.0.x.cfg

Page 43: Plone testingdzug tagung2010

Weiterführendes Material

● Kent Beck: Test Driven Development● Python Testing: Beginner's Guide● Tarek Ziadé: Expert Python Programming● Testing in Plone:

http://plone.org/documentation/kb/testing● Dexterity Manual - Testing:

http://plone.org/products/dexterity/documentation/manual/developer-manual/testing

Page 44: Plone testingdzug tagung2010

Fragen?