continuous integration testing for plone using hudson

Post on 15-May-2015

1.783 Views

Category:

Technology

5 Downloads

Preview:

Click to see full reader

DESCRIPTION

http://db.tt/pdKBTHC

TRANSCRIPT

Continuous Integration Testing with Hudson

Wednesday, October 27, 2010

Continuous Integration

Wednesday, October 27, 2010

Continuous Integration

• Extreme Programming principle

• Martin Fowlerhttp://www.martinfowler.com/articles/continuousIntegration.html

Wednesday, October 27, 2010

Continuous Integration• Maintain a Source

Repository

• Automate the Build

• Make the Build Self-Testing

• Everyone Commits Every Day

• Every Commit Should Be Built

• Keep the Build Fast

• Test in a Clone of the Production Environment

• Make it Easy to Get the Latest Deliverables

• Everyone Can See the Results of the Latest Build

• Automate Deployment

Wednesday, October 27, 2010

Essentially

• Commit your code

• Test the crap out of it

• Regressions are bad

• Assign blame

• Shame is a great motivator

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Hudson vs Buildbot?

Wednesday, October 27, 2010

*shrug*

Wednesday, October 27, 2010

Hudson (Pros)

Wednesday, October 27, 2010

Easy to install/run

%> java -jar hudson.war

Wednesday, October 27, 2010

Easy to Configure

• Create

• Modify

• Manage

• All TTW

Wednesday, October 27, 2010

Frequent Releases~ 1 / Week

Wednesday, October 27, 2010

Inline Documentation

Wednesday, October 27, 2010

Plugins

Wednesday, October 27, 2010

Hudson (Cons)

Wednesday, October 27, 2010

It’s Java.

Wednesday, October 27, 2010

It’s Java.1. It eats resources

2. I don’t know how to write plugins

Wednesday, October 27, 2010

Hudson

Wednesday, October 27, 2010

Project Layout

Wednesday, October 27, 2010

Project Layout

• Project/Job

Wednesday, October 27, 2010

Project Layout

• Project/Job

• Build

Wednesday, October 27, 2010

Project Layout

• Project

• Build

• Trigger

Wednesday, October 27, 2010

Triggers

• Other projects

• Remote trigger

• Periodically

• SCM polling

Wednesday, October 27, 2010

Project Layout

• Project/Job

• Build

• Trigger

• Build Step

Wednesday, October 27, 2010

Build Steps

• Shell script

• Python script

• Ant

• Maven

Wednesday, October 27, 2010

Project Layout

• Project/Job

• Build

• Trigger

• Build Step

• Post-Build Action

Wednesday, October 27, 2010

Post-Build Actions

• Trigger builds

• Archive results

• Generate reports

• Send email

Wednesday, October 27, 2010

Build Status

Wednesday, October 27, 2010

Build Status

• Successful

• Unstable

• Failed

Wednesday, October 27, 2010

Build Stability

Wednesday, October 27, 2010

Filesystem Layout

Wednesday, October 27, 2010

Filesystem Layouthudson /

config.xmlhudson.plugins.*.xmljobs /

myjob / builds /

2010-10-21_11-56-402010-10-21_12-20-26

config.xmlworkspace /

Wednesday, October 27, 2010

Filesystem Layouthudson /

config.xmlhudson.plugins.*.xmljobs /

myjob / builds /

2010-10-21_11-56-402010-10-21_12-20-26

config.xmlworkspace /

Wednesday, October 27, 2010

Filesystem Layouthudson /

config.xmlhudson.plugins.*.xmljobs /

myjob / builds /

2010-10-21_11-56-402010-10-21_12-20-26

config.xmlworkspace /

Wednesday, October 27, 2010

Filesystem Layouthudson /

config.xmlhudson.plugins.*.xmljobs /

myjob / builds /

2010-10-21_11-56-402010-10-21_12-20-26

config.xmlworkspace /

Wednesday, October 27, 2010

Plugins

Wednesday, October 27, 2010

Plugins

• Green Balls

• Python

• Subversion

• Trac

• Warnings

• Violations

• Cobertura

• Disk Usage

• Chuck Norris

Wednesday, October 27, 2010

Plugins

• Green Balls

• Python

• Subversion

• Trac

• Warnings

• Violations

• Cobertura

• Disk Usage

• Chuck Norris

Wednesday, October 27, 2010

Plone Integration

Wednesday, October 27, 2010

Buildout & mr.developer

Wednesday, October 27, 2010

buildout.cfg[buildout]...extensions = mr.developer

Wednesday, October 27, 2010

buildout.cfg[buildout]...extensions = mr.developersources = sources

[sources]fsd.core = svn https:.../weblion/fsd.core/trunkfsd.membrane = svn https:.../weblion/fsd.membrane/trunk

Wednesday, October 27, 2010

mr.developer

• bin/develop checkout

• bin/develop status

• bin/develop update

• bin/develop activate (deactivate)

• bin/develop reset

• bin/develop purge

Wednesday, October 27, 2010

buildout.cfg[buildout]...extensions = mr.developersources = sourcesauto-checkout = fsd.core fsd.membrane

[sources]fsd.core = svn https:.../weblion/fsd.core/trunkfsd.membrane = svn https:.../weblion/fsd.membrane/trunk

Wednesday, October 27, 2010

buildoutbin/

buildoutdevelop...

bootstrap.pybuildout.cfg...src/

fsd.corefsd.membrane

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Tests

Wednesday, October 27, 2010

Tests

• bin/test returns text

• Hudson wants JUnit (XML) format

• collective.xmltestreport

Wednesday, October 27, 2010

hudson.cfg[buildout]extends = buildout.cfg

parts += xmltestrunner

[xmltestrunner]recipe = collective.xmltestreporteggs = ${test:eggs}defaults = ${test:defaults} + ['--xml']

Wednesday, October 27, 2010

hudson.cfg[buildout]extends = buildout.cfg

parts += xmltestrunner

[xmltestrunner]recipe = collective.xmltestreporteggs = ${test:eggs}defaults = ${test:defaults} + ['--xml']

Wednesday, October 27, 2010

hudson.cfg[buildout]extends = buildout.cfg

parts += xmltestrunner

[xmltestrunner]recipe = collective.xmltestreporteggs = ${test:eggs}defaults = ${test:defaults} + ['--xml']

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Test Coverage

Wednesday, October 27, 2010

Test Coverage

[coverage]recipe = zc.recipe.eggeggs = coverageinitialization = sys.argv = sys.argv[:] + ['run', 'bin/xmltestrunner', '-k', '-q', '--xml']

Wednesday, October 27, 2010

Test Coverage[report]recipe = zc.recipe.eggeggs = coveragescripts = coverage=reportinitialization = eggs = '${buildout:eggs-directory}' bin = '${buildout:directory}/bin' exclude = '--omit=' + ','.join([eggs, sys.prefix, bin]) sys.argv = sys.argv[:] + ['xml', '-i', exclude, include]

Wednesday, October 27, 2010

Test Coverage

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Code Analysis

Wednesday, October 27, 2010

Code Analysis

• zptlint

• pyflakes

• pylint

• jslint

Wednesday, October 27, 2010

zptlint

Wednesday, October 27, 2010

zptlint

• http://pypi.python.org/pypi/zptlint

• Scan page templates for parser and output errors

Wednesday, October 27, 2010

zptlint

[zptlint]recipe = zc.recipe.eggeggs = zptlintentry-points = zptlint=zptlint:run

Wednesday, October 27, 2010

zptlint

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal" xmlns:metal="http://xml.zope.org/namespaces/metal" lang="en" metal:use-macro="context/main_template/macros/master"><body> <metal:fill fill-slot="content-core"> <div tal:content="structure view/context/text/output"> <h2>People</h2> <div tal:content="structure context/@@people" /> </metal:fill></body></html>

Wednesday, October 27, 2010

zptlint

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" xmlns:tal="http://xml.zope.org/namespaces/tal" xmlns:metal="http://xml.zope.org/namespaces/metal" lang="en" metal:use-macro="context/main_template/macros/master"><body> <metal:fill fill-slot="content-core"> <div tal:content="structure view/context/text/output"> <h2>People</h2> <div tal:content="structure context/@@people" /> </metal:fill></body></html>

Wednesday, October 27, 2010

zptlint

%> bin/zptlint src/.../view.pt

Wednesday, October 27, 2010

zptlint

%> bin/zptlint src/.../view.pt

*** Error in: src/.../view.pt <class 'zope.tal.taldefs.TALError'>: TAL attributes on <div> require explicit </div> , at line 12, column 9

Wednesday, October 27, 2010

Parsing Log Messages

• Warnings plug-in

• Regular expression

• Groovy script (groovy.codehaus.org)

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Priorities

• HIGH

• NORMAL

• LOW

Wednesday, October 27, 2010

zptlint[zptlint-test]recipe = collective.recipe.templateinput = inline: #!/bin/sh if [ -e zptlint.log ]; then echo "Old zptlint.log file removed" rm zptlint.log fi echo "Running zptlint-test" PACKAGES="${buildout:package-directories}" for pkg in $PACKAGES do find $pkg -regex ".*\.[c|z]?pt" | xargs -r bin/zptlint | perl -p -e 's/\s+$/ /g;s/\s+/ /g;s/\*{3}s?/\n/g' >> zptlint.log doneoutput = ${buildout:directory}/bin/zptlint-testmode = 755

Wednesday, October 27, 2010

zptlint[zptlint-test]recipe = collective.recipe.templateinput = inline: #!/bin/sh if [ -e zptlint.log ]; then echo "Old zptlint.log file removed" rm zptlint.log fi echo "Running zptlint-test" PACKAGES="${buildout:package-directories}" for pkg in $PACKAGES do find $pkg -regex ".*\.[c|z]?pt" | xargs -r bin/zptlint | perl -p -e 's/\s+$/ /g;s/\s+/ /g;s/\*{3}s?/\n/g' >> zptlint.log doneoutput = ${buildout:directory}/bin/zptlint-testmode = 755

Wednesday, October 27, 2010

zptlint[zptlint-test]recipe = collective.recipe.templateinput = inline: #!/bin/sh if [ -e zptlint.log ]; then echo "Old zptlint.log file removed" rm zptlint.log fi echo "Running zptlint-test" PACKAGES="${buildout:package-directories}" for pkg in $PACKAGES do find $pkg -regex ".*\.[c|z]?pt" | xargs -r bin/zptlint | perl -p -e 's/\s+$/ /g;s/\s+/ /g;s/\*{3}s?/\n/g' >> zptlint.log doneoutput = ${buildout:directory}/bin/zptlint-testmode = 755

Wednesday, October 27, 2010

zptlint[zptlint-test]recipe = collective.recipe.templateinput = inline: #!/bin/sh if [ -e zptlint.log ]; then echo "Old zptlint.log file removed" rm zptlint.log fi echo "Running zptlint-test" PACKAGES="${buildout:package-directories}" for pkg in $PACKAGES do find $pkg -regex ".*\.[c|z]?pt" | xargs -r bin/zptlint | perl -p -e 's/\s+$/ /g;s/\s+/ /g;s/\*{3}s?/\n/g' >> zptlint.log doneoutput = ${buildout:directory}/bin/zptlint-testmode = 755

Wednesday, October 27, 2010

zptlint[zptlint-test]recipe = collective.recipe.templateinput = inline: #!/bin/sh if [ -e zptlint.log ]; then echo "Old zptlint.log file removed" rm zptlint.log fi echo "Running zptlint-test" PACKAGES="${buildout:package-directories}" for pkg in $PACKAGES do find $pkg -regex ".*\.[c|z]?pt" | xargs -r bin/zptlint | perl -p -e 's/\s+$/ /g;s/\s+/ /g;s/\*{3}s?/\n/g' >> zptlint.log doneoutput = ${buildout:directory}/bin/zptlint-testmode = 755

Wednesday, October 27, 2010

zptlint[buildout]...# A list of package locations to be examined # by Hudsonpackage-directories = src/fsd.core/fsd/core src/fsd.membrane/fsd/membrane

Wednesday, October 27, 2010

zptlint[zptlint-test]recipe = collective.recipe.templateinput = inline: #!/bin/sh if [ -e zptlint.log ]; then echo "Old zptlint.log file removed" rm zptlint.log fi echo "Running zptlint-test" PACKAGES="${buildout:package-directories}" for pkg in $PACKAGES do find $pkg -regex ".*\.[c|z]?pt" | xargs -r bin/zptlint | perl -p -e 's/\s+$/ /g;s/\s+/ /g;s/\*{3}s?/\n/g' >> zptlint.log doneoutput = ${buildout:directory}/bin/zptlint-testmode = 755

Wednesday, October 27, 2010

zptlint[zptlint-test]recipe = collective.recipe.templateinput = inline: #!/bin/sh if [ -e zptlint.log ]; then echo "Old zptlint.log file removed" rm zptlint.log fi echo "Running zptlint-test" PACKAGES="${buildout:package-directories}" for pkg in $PACKAGES do find $pkg -regex ".*\.[c|z]?pt" | xargs -r bin/zptlint | perl -p -e 's/\s+$/ /g;s/\s+/ /g;s/\*{3}s?/\n/g' >> zptlint.log doneoutput = ${buildout:directory}/bin/zptlint-testmode = 755

Wednesday, October 27, 2010

zptlint[zptlint-test]recipe = collective.recipe.templateinput = inline: #!/bin/sh if [ -e zptlint.log ]; then echo "Old zptlint.log file removed" rm zptlint.log fi echo "Running zptlint-test" PACKAGES="${buildout:package-directories}" for pkg in $PACKAGES do find $pkg -regex ".*\.[c|z]?pt" | xargs -r bin/zptlint | perl -p -e 's/\s+$/ /g;s/\s+/ /g;s/\*{3}s?/\n/g' >> zptlint.log doneoutput = ${buildout:directory}/bin/zptlint-testmode = 755

Wednesday, October 27, 2010

zptlint[zptlint-test]recipe = collective.recipe.templateinput = inline: #!/bin/sh if [ -e zptlint.log ]; then echo "Old zptlint.log file removed" rm zptlint.log fi echo "Running zptlint-test" PACKAGES="${buildout:package-directories}" for pkg in $PACKAGES do find $pkg -regex ".*\.[c|z]?pt" | xargs -r bin/zptlint | perl -p -e 's/\s+$/ /g;s/\s+/ /g;s/\*{3}s?/\n/g' >> zptlint.log doneoutput = ${buildout:directory}/bin/zptlint-testmode = 755

Wednesday, October 27, 2010

zptlint[zptlint-test]recipe = collective.recipe.templateinput = inline: #!/bin/sh if [ -e zptlint.log ]; then echo "Old zptlint.log file removed" rm zptlint.log fi echo "Running zptlint-test" PACKAGES="${buildout:package-directories}" for pkg in $PACKAGES do find $pkg -regex ".*\.[c|z]?pt" | xargs -r bin/zptlint | perl -p -e 's/\s+$/ /g;s/\s+/ /g;s/\*{3}s?/\n/g' >> zptlint.log doneoutput = ${buildout:directory}/bin/zptlint-testmode = 755

Wednesday, October 27, 2010

zptlint[zptlint-test]recipe = collective.recipe.templateinput = inline: #!/bin/sh if [ -e zptlint.log ]; then echo "Old zptlint.log file removed" rm zptlint.log fi echo "Running zptlint-test" PACKAGES="${buildout:package-directories}" for pkg in $PACKAGES do find $pkg -regex ".*\.[c|z]?pt" | xargs -r bin/zptlint | perl -p -e 's/\s+$/ /g;s/\s+/ /g;s/\*{3}s?/\n/g' >> zptlint.log doneoutput = ${buildout:directory}/bin/zptlint-testmode = 755

Wednesday, October 27, 2010

zptlint[zptlint-test]recipe = collective.recipe.templateinput = inline: #!/bin/sh if [ -e zptlint.log ]; then echo "Old zptlint.log file removed" rm zptlint.log fi echo "Running zptlint-test" PACKAGES="${buildout:package-directories}" for pkg in $PACKAGES do find $pkg -regex ".*\.[c|z]?pt" | xargs -r bin/zptlint | perl -p -e 's/\s+$/ /g;s/\s+/ /g;s/\*{3}s?/\n/g' >> zptlint.log doneoutput = ${buildout:directory}/bin/zptlint-testmode = 755

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

pyflakes

Wednesday, October 27, 2010

pyflakes

• Python syntax checking

• Find common errors quickly

• Doesn’t attempt to run Python code

Wednesday, October 27, 2010

pyflakes

[pyflakes]recipe = zc.recipe.eggeggs = pyflakesentry-points = pyflakes=pyflakes.scripts.pyflakes:main

Wednesday, October 27, 2010

pyflakes%> bin/pyflakes src/.../person.py

Wednesday, October 27, 2010

pyflakes%> bin/pyflakes src/.../person.py

src/.../person.py:25: 'ATTRIBUTE_NAME' imported but unusedsrc/.../person.py:25: 'IAttributeUUID' imported but unused

Wednesday, October 27, 2010

pyflakes[pyflakes-test]recipe = collective.recipe.templateinput = inline: #!/bin/sh if [ -s pyflakes.log ]; then rm pyflakes.log echo "Old pyflakes.log file removed" fi echo "Running pyflakes" PACKAGES="${buildout:package-directories}" for pkg in $PACKAGES do find -L $pkg -regex ".*\.py"|xargs -r bin/pyflakes >> pyflakes.log doneoutput = ${buildout:directory}/bin/pyflakes-testmode = 755

Wednesday, October 27, 2010

pyflakes[pyflakes-test]recipe = collective.recipe.templateinput = inline: #!/bin/sh if [ -s pyflakes.log ]; then rm pyflakes.log echo "Old pyflakes.log file removed" fi echo "Running pyflakes" PACKAGES="${buildout:package-directories}" for pkg in $PACKAGES do find -L $pkg -regex ".*\.py"|xargs -r bin/pyflakes >> pyflakes.log doneoutput = ${buildout:directory}/bin/pyflakes-testmode = 755

Wednesday, October 27, 2010

pyflakes[pyflakes-test]recipe = collective.recipe.templateinput = inline: #!/bin/sh if [ -s pyflakes.log ]; then rm pyflakes.log echo "Old pyflakes.log file removed" fi echo "Running pyflakes" PACKAGES="${buildout:package-directories}" for pkg in $PACKAGES do find -L $pkg -regex ".*\.py"|xargs -r bin/pyflakes >> pyflakes.log doneoutput = ${buildout:directory}/bin/pyflakes-testmode = 755

Wednesday, October 27, 2010

pyflakes[pyflakes-test]recipe = collective.recipe.templateinput = inline: #!/bin/sh if [ -s pyflakes.log ]; then rm pyflakes.log echo "Old pyflakes.log file removed" fi echo "Running pyflakes" PACKAGES="${buildout:package-directories}" for pkg in $PACKAGES do find -L $pkg -regex ".*\.py"|xargs -r bin/pyflakes >> pyflakes.log doneoutput = ${buildout:directory}/bin/pyflakes-testmode = 755

Wednesday, October 27, 2010

pyflakes[pyflakes-test]recipe = collective.recipe.templateinput = inline: #!/bin/sh if [ -s pyflakes.log ]; then rm pyflakes.log echo "Old pyflakes.log file removed" fi echo "Running pyflakes" PACKAGES="${buildout:package-directories}" for pkg in $PACKAGES do find -L $pkg -regex ".*\.py"|xargs -r bin/pyflakes >> pyflakes.log doneoutput = ${buildout:directory}/bin/pyflakes-testmode = 755

Wednesday, October 27, 2010

[pyflakes-test]recipe = collective.recipe.templateinput = inline: #!/bin/sh if [ -s pyflakes.log ]; then rm pyflakes.log echo "Old pyflakes.log file removed" fi echo "Running pyflakes" PACKAGES="${buildout:package-directories}" for pkg in $PACKAGES do find -L $pkg -regex ".*\.py"|xargs -r bin/pyflakes >> pyflakes.log doneoutput = ${buildout:directory}/bin/pyflakes-testmode = 755

pyflakes

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

pylint

Wednesday, October 27, 2010

pylint

• Syntax checking

• PEP8 compliance

• Imports code

• You’ve done everything wrong

Wednesday, October 27, 2010

pylint

[pylint]recipe = zc.recipe.eggeggs = logilab.pylintinstallerextra-paths = ${instance:location}/lib/pythonentry-points = pylint=pylint.lint:Runarguments = [ '--output-format=parseable', '--zope=y', '--reports=y', '--disable-msg=

E0611,F0401,W0232,E1101,C0103,C0111,R0201,W0201,R0911,R0904,F0220, E1103,R0901,E0211,E0213,E1002,W0622',

'--generated-members=objects', ] + sys.argv[1:]

Wednesday, October 27, 2010

pylint

• disable-msg

• R0911: Too many return statements (%s/%s)

• R0201: Method could be a function

• W0201: Attribute %r defined outside of __init__

• http://pylint-messages.wikidot.com/all-messages

Wednesday, October 27, 2010

pylint[pylint-test]recipe = collective.recipe.templateinput = inline: #!/bin/sh if [ -s pylint.log ]; then rm pylint.log echo "Old pylint.log file removed" fi echo "Running pylint" PACKAGES="${buildout:package-directories}" for pkg in $PACKAGES do find -L $pkg -regex ".*\.py" | xargs bin/pylint >> pylint.log done echo "Finished"output = ${buildout:directory}/bin/pylint-testmode = 755

Wednesday, October 27, 2010

pylint

Wednesday, October 27, 2010

pylint

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Selenium

Wednesday, October 27, 2010

Selenium• Automated web application testing

Wednesday, October 27, 2010

Selenium1. Open this page

2. Click that thing

3. Fill out that form

4. Click submit

Did it work?

Wednesday, October 27, 2010

Selenium Testcase

def test_login_overlay(self): self.open("/") self.wait() self.selenium.click('link=Log in') self.waitForElement('form#login_form') self.selenium.type("name=__ac_name", TEST_USER_NAME) self.selenium.type("name=__ac_password", TEST_USER_PASSWORD) self.selenium.click("submit") self.wait() self.failUnless(self.selenium.is_text_present("Log out"))

Wednesday, October 27, 2010

Selenium Testcaseclass SeleniumLayer(PloneSandboxLayer): defaultBases = (HOST_ADJUSTABLE_ZSERVER_FIXTURE, PLONE_FIXTURE)

# Connection parameters seleniumHost = os.environ.get('SELENIUM_HOST', 'localhost') seleniumPort = os.environ.get('SELENIUM_PORT', '4444') seleniumBrowser = os.environ.get('SELENIUM_BROWSER', '*firefox')

def setUpZope(self, app, configurationContext): ...

def setUpPloneSite(self, portal): ... url = "http://%s:%s/%s" % (self['host'], self['port'], PLONE_SITE_ID) self['selenium'] = selenium.selenium(self.seleniumHost,

self.seleniumPort, self.seleniumBrowser, url) self['selenium'].start()

def tearDownPloneSite(self, portal): self['selenium'].stop() del self['selenium']

Wednesday, October 27, 2010

Selenium Testcaseclass SeleniumLayer(PloneSandboxLayer): defaultBases = (HOST_ADJUSTABLE_ZSERVER_FIXTURE, PLONE_FIXTURE)

# Connection parameters seleniumHost = os.environ.get('SELENIUM_HOST', 'localhost') seleniumPort = os.environ.get('SELENIUM_PORT', '4444') seleniumBrowser = os.environ.get('SELENIUM_BROWSER', '*firefox')

def setUpZope(self, app, configurationContext): ...

def setUpPloneSite(self, portal): ... url = "http://%s:%s/%s" % (self['host'], self['port'], PLONE_SITE_ID) self['selenium'] = selenium.selenium(self.seleniumHost,

self.seleniumPort, self.seleniumBrowser, url) self['selenium'].start()

def tearDownPloneSite(self, portal): self['selenium'].stop() del self['selenium']

Wednesday, October 27, 2010

Selenium Testcaseclass SeleniumLayer(PloneSandboxLayer): defaultBases = (HOST_ADJUSTABLE_ZSERVER_FIXTURE, PLONE_FIXTURE)

# Connection parameters seleniumHost = os.environ.get('SELENIUM_HOST', 'localhost') seleniumPort = os.environ.get('SELENIUM_PORT', '4444') seleniumBrowser = os.environ.get('SELENIUM_BROWSER', '*firefox')

def setUpZope(self, app, configurationContext): ...

def setUpPloneSite(self, portal): ... url = "http://%s:%s/%s" % (self['host'], self['port'], PLONE_SITE_ID) self['selenium'] = selenium.selenium(self.seleniumHost,

self.seleniumPort, self.seleniumBrowser, url) self['selenium'].start()

def tearDownPloneSite(self, portal): self['selenium'].stop() del self['selenium']

Wednesday, October 27, 2010

Selenium RC

• Firefox

• Internet Explorer

• Safari

• Chrome

• Opera

• more...

Wednesday, October 27, 2010

Selenium Grid

Wednesday, October 27, 2010

Wednesday, October 27, 2010

“Firefox?”

Wednesday, October 27, 2010

Thanks!

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Selenium Test Runnerfsd/

core/...selenium/

base.pytestSelenium.py

tests/...

Wednesday, October 27, 2010

Selenium Test Runner

[selenium]recipe = collective.xmltestreporteggs = fsd.core [test] fsd.membrane [test]defaults = ['--tests-pattern', '^f?selenium$', '--xml']

Wednesday, October 27, 2010

Selenium Test Runner

[selenium]recipe = collective.xmltestreporteggs = fsd.core [test] fsd.membrane [test]defaults = ['--tests-pattern', '^f?selenium$', '--xml']

Wednesday, October 27, 2010

Selenium Test Runner

[selenium-firefox]recipe = ${selenium:recipe}eggs = ${selenium:eggs}defaults = ${selenium:defaults} [selenium-safari]recipe = ${selenium:recipe}eggs = ${selenium:eggs}defaults = ${selenium:defaults}

Wednesday, October 27, 2010

Selenium Test Runner

%> bin/selenium-firefox%> bin/selenium-safari

Wednesday, October 27, 2010

Selenium Test Runner

workspace/bin/...parts/

selenium-firefox/testreports/

*.xmlselenium-safari/

testreports/*.xml

Wednesday, October 27, 2010

~

Wednesday, October 27, 2010

Sprint!

• Saturday

• QA Sprint

• Selenium testing and more

• Free food!

Wednesday, October 27, 2010

Multi-Configuration Projects

Wednesday, October 27, 2010

Multi-Configuration Projects

• Run a build for each set of n x n ( x n x n) variables.

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Wish List

Wednesday, October 27, 2010

Wish List

• Load testing

• Sphinx builds

• Chameleon compatibility checking

• Windmill

Wednesday, October 27, 2010

Best Practices

Wednesday, October 27, 2010

Check in Your Configs

• Configuration is stored in XML files

• Easy to back up to SVN

Wednesday, October 27, 2010

Check in Your Configshudson /

config.xmlhudson.plugins.*.xmljobs /

myjob / builds /

2010-10-21_11-56-402010-10-21_12-20-26

config.xmlworkspace /

Wednesday, October 27, 2010

hudson /config.xmlhudson.plugins.*.xmljobs /

myjob / builds /

2010-10-21_11-56-402010-10-21_12-20-26

config.xmlworkspace /

Check in Your Configs

Wednesday, October 27, 2010

Check in Your Configs

Wednesday, October 27, 2010

Watch Your Disk Space

• “Hudson disk-usage” plugin

Wednesday, October 27, 2010

Watch Your Disk Space

Wednesday, October 27, 2010

Watch Your Disk Space

Wednesday, October 27, 2010

Wednesday, October 27, 2010

Use an Egg Cache

• Set up a default.cfg for your hudson account.

[buildout]eggs-directory =

/home/hudson/.buildout/eggsdownload-cache =

/home/hudson/.buildout/downloads

Wednesday, October 27, 2010

Pin unittest2

• (If you’re using it)

• plone.app.testing

• 3x faster buildout

Wednesday, October 27, 2010

Split Big Builds

• How long does the build take?

• How often does each part need to be run?

• Tests?

• Coverage?

Wednesday, October 27, 2010

Split Big Builds

• Build

• Test

• Syntax Checking

• Coverage

• Selenium

Wednesday, October 27, 2010

Split Big Builds1. “Build other projects” post-build action

Wednesday, October 27, 2010

Split Big Builds1. “Build other projects” post-build action

2. Custom workspace

Wednesday, October 27, 2010

Split Big Builds1. “Build other projects” post-build action

2. Custom workspace

3. Build Fingerprinting

Wednesday, October 27, 2010

Fingerprinting

• “These builds are related”

• Archive an md5 hash of a file to act as an identifier

Wednesday, October 27, 2010

FingerprintingIn parent build:

In parent and child builds:

Wednesday, October 27, 2010

Reporting

Wednesday, October 27, 2010

Hudson Report Views

Wednesday, October 27, 2010

Email

Wednesday, October 27, 2010

Chuck

Wednesday, October 27, 2010

iPhone

Wednesday, October 27, 2010

Extreme Feedback Devices

Wednesday, October 27, 2010

hudson.plone.org

• Currently builds Plone 4.0.x

• Core developers have access

• Add your core & collective projects

Wednesday, October 27, 2010

Thanks

• Martin Aspeli

• Timo Stollenwerk

• Hanno Schlichting

Wednesday, October 27, 2010

QA Sprint!

• Saturday

• QA Sprint

• Selenium testing and more

• Free food!

Wednesday, October 27, 2010

top related