0
Plone Testing
DZUG Tagung Dresden 2010
       Timo Stollenwerk
Timo Stollenwerk
●   Plone Entwickler seit 2004
●   GSoC 2009: plone.app.discussion
    ●   ~ 120 Tests
    ●   Python und...
Material
●   Folien:
    ●   slideshare.net/tisto
●   Code:
    ●   svn.plone.org/svn/collective/examples/example.dzu
    ...
Was ist ein Test?
Test Beispiel
def is_palindrome(word):
  pass


def test_palindromic_word():
  assert is_palindrome("noon") == True
  asse...
Python Unittest Testcase
import unittest
class TestIsPalindrome(unittest.TestCase):


   def test_palindromic_word():
    ...
Warum sind Tests wichtig?
Warum Testen?
●   Robusterer Code
●   Besseres Code Verständnis
●   Nachweis
●   Dokumentation von Software Anforderungen
...
Was ist Test-Driven Development?
Test-Driven Development




Kent Beck: Test Driven Development
Arten von Tests
Funktionale Tests
●   Funktionaler Ablauf
●   Benutzersicht
●   BlackBox Testing
●   Akzeptanztests
XP/Scrum und Funktionale Tests
●   Abbildung von (Software) Anforderungen durch
    User Stories / Acceptance Tests
●   Te...
User Stories mit (Doc)Tests
As a logged-in user, I can add a new page to the
website.
Beispiel Funktionaler Doctest
>>> browser.open(portal_url)


>>> browser.getLink(id='example-dzugconference-
presenter').c...
zope.testbrowser
●   browser.open('http://nohost/plone/')
●   browser.getLink(link_text).click()
●   browser.url
●   brows...
zope.testbrowser debugging
open('/tmp/testbrowser.html','w').write(browser.co
ntents)
Interlude (Interaktives Debugging)
import interlude
suite = DocFileSuite(...,
     globs={'interact': interlude.interact},...
Testing Pyramide
Integrationstests
●   Testet die Zusammenarbeit voneinander
    abhängiger Komponenten
Beispiel Integrationstest
class IPresenter(form.Schema):


  title = schema.TextLine(
             title=_(u"Title")
     ...
Was wollen wir testen?
●   Schema
●   Typ Registrierung (FTI)
●   Factory
●   Hinzufügen des Inhaltstyps
●   View
Integrationstests: setUp
def setUp(self):


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


  setRoles(self.portal, TEST_USER_NAME,...
Integrationstest: Schema
def test_schema(self):


  fti = queryUtility(IDexterityFTI,
    name='example.dzugconference.pre...
Integrationstest: FTI
def test_fti(self):


  fti = queryUtility(IDexterityFTI,
     name='example.dzugconference.presente...
Integrationstest: Factory
def test_factory(self):


  fti = queryUtility(IDexterityFTI,
     name='example.dzugconference....
Integrationstest: Hinzufügen
def test_adding(self):


  self.folder.invokeFactory(
     'example.dzugconference.presenter'...
Integrationstest: View
def test_view(self):


  self.folder.invokeFactory(
     'example.dzugconference.presenter',
     '...
Integrationstest: Debugging
def test_todo(self):


  import pdb; pdb.set_trace()


  import ipdb; ipdb.set_trace()
Testing Pyramide
Unit Tests in Plone
●   Test einer isolierten Komponente
●   Wie?
●   => Mock Objects
Mock und Fake Objekte
 ●   Externe Datenbanken
 ●   Web Services
 ●   Plone Komponenten
 ●   Netzwerkverbindungen
 ●   Ben...
Setup Tests
●   Professional Plone Development
●   Layer / collective.testcaselayer
●   plone.testing / plone.app.testing
Test Setup (PPD)
TestPortlet(CinemaContentTestCase):


    def afterSetUp(self):
          …


    ...



PPD: Optilux Cod...
Test Setup (Layer)
class CommentTest(PloneTestCase):
    layer = DiscussionLayer


    def afterSetUp(self):
         …


...
Test Setup (plone.testing)
class
ExampleDzugConference(PloneSandboxLayer):
    defaultBases = (PLONE_FIXTURE,)


    def s...
Testrunner
parts += test


[test]
recipe = zc.recipe.testrunner
eggs = ${instance:eggs}
defaults = ['--auto-color', '--aut...
Test Geschwindigkeit
Integrations-Tests vs. Funktionale Tests

●   plone.app.discussion
    ●   Test Setup (Plone Site): 9...
Testing Pyramide
Test Abdeckung
buildout.cfg



[coverage-test]
recipe = zc.recipe.testrunner
eggs = ${test:eggs}
defaults = ['--coverage',...
Hudson Continuous Integration




http://hudson.zmag.de/hudson
Weitere Tests
 ●   Python
      ●   Pylint
 ●   Templates
      ●   ZPTLint
 ●   Javascript
      ●   JSLint
      ●   qUn...
Weiterführendes Material
●   Kent Beck: Test Driven Development
●   Python Testing: Beginner's Guide
●   Tarek Ziadé: Expe...
Fragen?
Upcoming SlideShare
Loading in...5
×

Plone testingdzug tagung2010

673

Published on

0 Comments
0 Likes
Statistics
Notes
  • Be the first to comment

  • Be the first to like this

No Downloads
Views
Total Views
673
On Slideshare
0
From Embeds
0
Number of Embeds
1
Actions
Shares
0
Downloads
8
Comments
0
Likes
0
Embeds 0
No embeds

No notes for slide

Transcript of "Plone testingdzug tagung2010"

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

    Clipping is a handy way to collect important slides you want to go back to later.

×