Plone testingdzug tagung2010

  • 596 views
Uploaded on

 

  • Full Name Full Name Comment goes here.
    Are you sure you want to
    Your message goes here
    Be the first to comment
    Be the first to like this
No Downloads

Views

Total Views
596
On Slideshare
0
From Embeds
0
Number of Embeds
1

Actions

Shares
Downloads
7
Comments
0
Likes
0

Embeds 0

No embeds

Report content

Flagged as inappropriate Flag as inappropriate
Flag as inappropriate

Select your reason for flagging this presentation as inappropriate.

Cancel
    No notes for slide

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?