Package: niteoweb.windmill
Aboutniteoweb.windmill extends Plone’s FunctionalTestCase to provide support for
running Windmill tests. This is achieved by adding an additional test layer,
which starts a single-threaded ZServer instance alongside the Windmill server.Windmill supports most of modern browser. The controller API can be
found athttp://trac.getwindmill.com/wiki/ControllerApi.For more details, seehttp://getwindmill.comRemember to read source code, it’s very lightweight!Accessing the Windmill clientWindmill tests should derive fromWindmillTestCase. This provides an
instance ofWindmillClientasself.wm. In addition to supporting the
standardWindMillClientAPI, this client has an extra methodopen_site(), which automatically prepends the Plone site URL when opening
a URL. It is otherwise identical to theopen()method.FAQHow do I synchronize data manipulated by actions in browser and unittests:In Windmill TestCase, self.site_open() always callstransaction.commit()which writes data to ZODB.In unittests, just doimport transaction;transaction.commit()and data
will be seen in browser.InstallationAddniteoweb.windmillas a dependency of the package that uses it insetup.py. One way to do that is via a[tests]extra, e.g.:extras_require = {
    'tests': ['niteoweb.windmill'],
},You then add this to your buildout, e.g.:[tests]
recipe = zc.recipe.testrunner
eggs =
    my.package [tests]UsageBasic usage:from Products.PloneTestCase import PloneTestCase as ptc
from niteoweb.windmill import WindmillTestCase

ptc.setupPloneSite()

class TestSample(WindmillTestCase):

    def afterSetUp(self):
        self.setRoles(['Manager'])
        self.login_user()

    def test_foo(self):
        self.wm.open_site(url="/about")
        self.wm.waits.forPageLoad(timeout=30000)


def test_suite():
    from unittest import TestSuite, makeSuite
    suite = TestSuite()
    suite.addTest(makeSuite(TestSample))
    return suiteAdvanced usage:from Products.PloneTestCase import PloneTestCase as ptc

from niteoweb.windmill import WindmillTestCase, WindmillLayer

class CustomWindmillLayer(WindmillLayer):
    site = 'plone2'
    windmill_settings = WindmillLayer.windmill_settings.copy()
    windmill_settings['START_FIREFOX'] = False
    WindmillLayer.windmill_settings['START_CHROME'] = True

ptc.setupPloneSite()

class TestWM(WindmillTestCase):

    layer = CustomWindmillLayer

    def afterSetUp(self):
        self.setRoles(['Manager'])
        self.login_user()

    def test_foo(self):
        self.wm.open_site('/login_form', site='plone2')
        self.wm.waits.forPageLoad(timeout=30000)

    def test_suite():
        from unittest import TestSuite, makeSuite
        suite = TestSuite()
        suite.addTest(makeSuite(TestWM))
        return suiteand run tests with debug mode to stop on error/failure:bin/instance test -s package.module -t test_foo -DKnown issuesOn teardown, you sometimes will getAttributeError: ‘NoneType’ object has
no attribute ‘exc_info’. Ignore itWindmill is very poorly tested on Python2.4, submit bugs if you stumble upon
any;)TODOSome simple integration to load existing ZODB storagesCHANGELOG0.3.2 (2011-09-15)Changed the way, the test setup waits for the zserver to finish.
This helps with timing issues that manifest in quite weird and
misleading error messages.
[do3cc]0.3.1 (09.05.2010)useportal_ownerinstead ofdefault_userfor better compatibility with
loginAsPortalOwner() [Domen Kozar]0.3 (12.12.2009)Refactor to start ZServer in a separate layer rather than use startZServer()
from ZopeTestCase. This is more reliable in case of other tests in the same
test run that may require a running ZServer, because startZServer() is not
layer aware and cannot be reliably torn down.
[Martin Aspeli]0.2 (23.11.2009)added self.add_user function to testcase (be able to add users with custom
roles) [Domen Kozar]fixed first request failing (due to windmill/plone racecodintions) [Martin Aspeli]fixed windmill dependency pulling [Martin Aspeli]