Plone testingdzug tagung2010
Upcoming SlideShare
Loading in...5
×
 

Like this? Share it with your network

Share

Plone testingdzug tagung2010

on

  • 827 views

 

Statistics

Views

Total Views
827
Views on SlideShare
824
Embed Views
3

Actions

Likes
0
Downloads
7
Comments
0

1 Embed 3

http://www.linkedin.com 3

Accessibility

Categories

Upload Details

Uploaded via as Adobe PDF

Usage Rights

© All Rights Reserved

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Processing…
Post Comment
Edit your comment

Plone testingdzug tagung2010 Presentation Transcript

  • 1. Plone Testing DZUG Tagung Dresden 2010 Timo Stollenwerk
  • 2. 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
  • 3. Material ● Folien: ● slideshare.net/tisto ● Code: ● svn.plone.org/svn/collective/examples/example.dzu gconference/example.dzugconference
  • 4. Was ist ein Test?
  • 5. Test Beispiel def is_palindrome(word): pass def test_palindromic_word(): assert is_palindrome("noon") == True assert is_palindrome("foo") == False
  • 6. Python Unittest Testcase 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) http://docs.python.org/library/unittest.html
  • 7. Warum sind Tests wichtig?
  • 8. Warum Testen? ● Robusterer Code ● Besseres Code Verständnis ● Nachweis ● Dokumentation von Software Anforderungen ● „Billigeres“ Bugfixing ● Refactoring
  • 9. Was ist Test-Driven Development?
  • 10. Test-Driven Development Kent Beck: Test Driven Development
  • 11. Arten von Tests
  • 12. Funktionale Tests ● Funktionaler Ablauf ● Benutzersicht ● BlackBox Testing ● Akzeptanztests
  • 13. 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
  • 14. User Stories mit (Doc)Tests As a logged-in user, I can add a new page to the website.
  • 15. 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
  • 16. 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
  • 17. zope.testbrowser debugging open('/tmp/testbrowser.html','w').write(browser.co ntents)
  • 18. Interlude (Interaktives Debugging) import interlude suite = DocFileSuite(..., globs={'interact': interlude.interact}, ...) >>> interact( locals() ) http://pypi.python.org/pypi/interlude/
  • 19. Testing Pyramide
  • 20. Integrationstests ● Testet die Zusammenarbeit voneinander abhängiger Komponenten
  • 21. Beispiel Integrationstest class IPresenter(form.Schema): title = schema.TextLine( title=_(u"Title") ) ...
  • 22. Was wollen wir testen? ● Schema ● Typ Registrierung (FTI) ● Factory ● Hinzufügen des Inhaltstyps ● View
  • 23. 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']
  • 24. Integrationstest: Schema def test_schema(self): fti = queryUtility(IDexterityFTI, name='example.dzugconference.presenter') schema = fti.lookupSchema() self.assertEquals(IPresenter, schema)
  • 25. Integrationstest: FTI def test_fti(self): fti = queryUtility(IDexterityFTI, name='example.dzugconference.presenter') self.assertNotEquals(None, fti)
  • 26. 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))
  • 27. Integrationstest: Hinzufügen def test_adding(self): self.folder.invokeFactory( 'example.dzugconference.presenter', 'presenter1') p1 = self.folder['presenter1'] self.failUnless(IPresenter.providedBy(p1))
  • 28. Integrationstest: View def test_view(self): self.folder.invokeFactory( 'example.dzugconference.presenter', 'presenter1') p1 = self.folder['presenter1'] view = p1.restrictedTraverse('@@view') self.failUnless(view)
  • 29. Integrationstest: Debugging def test_todo(self): import pdb; pdb.set_trace() import ipdb; ipdb.set_trace()
  • 30. Testing Pyramide
  • 31. Unit Tests in Plone ● Test einer isolierten Komponente ● Wie? ● => Mock Objects
  • 32. 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
  • 33. Setup Tests ● Professional Plone Development ● Layer / collective.testcaselayer ● plone.testing / plone.app.testing
  • 34. Test Setup (PPD) TestPortlet(CinemaContentTestCase): def afterSetUp(self): … ... PPD: Optilux Code Examples
  • 35. Test Setup (Layer) class CommentTest(PloneTestCase): layer = DiscussionLayer def afterSetUp(self): … ... http://svn.plone.org/svn/plone/plone.app.discussion/trunk
  • 36. Test Setup (plone.testing) class ExampleDzugConference(PloneSandboxLayer): defaultBases = (PLONE_FIXTURE,) def setUpPloneSite(self, portal): … ... Collective SVN: examples/examples.dzugconference
  • 37. Testrunner parts += test [test] recipe = zc.recipe.testrunner eggs = ${instance:eggs} defaults = ['--auto-color', '--auto-progress']
  • 38. 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)
  • 39. Testing Pyramide
  • 40. 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')
  • 41. Hudson Continuous Integration http://hudson.zmag.de/hudson
  • 42. Weitere Tests ● Python ● Pylint ● Templates ● ZPTLint ● Javascript ● JSLint ● qUnit svn.plone.org/svn/plone/plone.app.discussion/trunk/test-plone-4.0.x.cfg
  • 43. 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/documentatio n/manual/developer-manual/testing
  • 44. Fragen?