diff --git a/integration/R/test_framework.py b/integration/R/test_framework.py index c13082a..2a995ee 100644 --- a/integration/R/test_framework.py +++ b/integration/R/test_framework.py @@ -1,22 +1,21 @@ import unittest import stick class TestFramework(stick.KolabPhpunitTest): """ Run framework unit tests from upstream Roundcube """ - @stick.todo("TODO: Framework_Charset::test_clean with data set #2") def test_framework(self): - self.execute(testsuite='All Tests', message="Roundcube Framework Testsuite") + self.execute(testsuite='All Tests', excludes=['mbstring'], message="Roundcube Framework Testsuite") def test_plugin_acl(self): self.execute('plugins/acl/tests/Acl.php', message="Roundcube ACL Plugin") def test_plugin_managesieve(self): self.execute('plugins/managesieve/tests/Managesieve.php', message="Roundcube Managesieve Plugin") self.execute('plugins/managesieve/tests/Parser.php', message="Roundcube Managesieve Parser") self.execute('plugins/managesieve/tests/Tokenizer.php', message="Roundcube Managesieve Tokenizer") self.execute('plugins/managesieve/tests/Vacation.php', message="Roundcube Managesieve Vacation") if __name__ == '__main__': unittest.main(argv=stick.argv) diff --git a/integration/stick/integrationtest.py b/integration/stick/integrationtest.py index 8f75c50..9460bd7 100644 --- a/integration/stick/integrationtest.py +++ b/integration/stick/integrationtest.py @@ -1,158 +1,158 @@ import unittest import pykolab import datetime import time from . import wipeall from . import synchronize from . import get_user from . import add_user from . import get_resource from . import add_resource from . import get_shared_folder from . import add_shared_folder conf = pykolab.getConf() class KolabIntegrationTest(unittest.TestCase): """ Base class providing utility functions for running integration tests """ wiped = False dosync = False initialized = False develmode = conf.get('testing', 'develmode') == 'true' verbose = conf.get('testing', 'verbose') == 'true' or conf.cli_keywords.verbose @classmethod def __setUp(self, *args, **kw): """ Trigger setUpClass() once """ if not self.initialized: self.setUpClass() @classmethod def setUpClass(self, *args, **kw): """ Call this at the end of the derived setUpClass() method """ self.initialized = True if self.dosync: time.sleep(1) self.log("Synchronize...") synchronize() self.dosync = False @classmethod def tearDownClass(self): - if not self.develmode: + if not self.develmode and conf.get('testing', 'cleanafter') == 'true': self.log("Wipe data after") - #wipeall() + wipeall() @classmethod def log(self, message): if self.verbose: print datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:23] + " " + message @classmethod def require_user(self, givenname, sn, **kw): """ Create the given user and return its full properties """ create = not self.initialized and not self.develmode res = { 'givenname': givenname, 'sn': sn } res.update(kw) if not create: query = get_user(givenname, sn) self.log("User found: %r" % (query.get('mail','') if isinstance(query, dict) else query)) if len(query) > 0: res = query res['userpassword'] = 'Welcome2KolabSystems' else: create = True else: self._wipefirst() if create: res = add_user(givenname, sn, **kw) self.log("Added user: %r" % (res.get('mail',''))) self.dosync = True return res @classmethod def require_resource(self, type, cn, members=None, **kw): """ Create the given resource and return its properties """ create = not self.initialized and not self.develmode res = { 'type': type, 'cn': cn, 'members': members } res.update(kw) if not create: query = get_resource(type, cn) self.log("Resource found: %r" % (query.get('cn','') if isinstance(query, dict) else query)) if len(query) > 0: res = query else: create = True else: self._wipefirst() if create: res = add_resource(type, cn, members, **kw) self.log("Added resource: %r" % (res.get('cn',''))) self.dosync = True return res @classmethod def require_shared_folder(self, type, cn, **kw): """ Create the given shared folder and return its properties """ create = not self.initialized and not self.develmode res = { 'kolabfoldertype': type, 'cn': cn } res.update(kw) if not create: query = get_shared_folder(type, cn) self.log("Folder found: %r" % (query.get('cn','') if isinstance(query, dict) else query)) if len(query) > 0: res = query else: create = True else: self._wipefirst() if create: res = add_shared_folder(type, cn, **kw) self.log("Added shared folder: %r" % (res.get('cn',''))) self.dosync = True return res @classmethod def _wipefirst(self): """ Helper method to remove all data from the Kolab backend """ if not self.wiped: self.log("Wipe data first") wipeall() self.wiped = True def assertIn(self, needle, haystack, message=None): self.assertTrue(needle in haystack, message) def get_conf(self, section, key, default=None): return conf.get(section, key) or default diff --git a/integration/stick/phpunittest.py b/integration/stick/phpunittest.py index 6707d69..0ddf012 100644 --- a/integration/stick/phpunittest.py +++ b/integration/stick/phpunittest.py @@ -1,108 +1,126 @@ import time import subprocess +from . import conf from integrationtest import KolabIntegrationTest class KolabPhpunitTest(KolabIntegrationTest): """ Base class for running Roundcube Selenium tests through phpunit This assumes Roundcube being installed with dev dependencies that include the phpunit/phpunit-selenium package. """ server = None env = {} @classmethod def setUpClass(self, *args, **kw): super(KolabPhpunitTest, self).setUpClass(*args, **kw) def tearDown(self, *args, **kw): self._stop_server() super(KolabPhpunitTest, self).tearDown(*args, **kw) def stop(self): self._stop_server() def _start_server(self): # only start once if self.server is None: server_jar = self.get_conf('testing', 'selenium_server_jar', 'selenium-server-standalone-2.45.0.jar') self.log("Starting Selenium server %r" % (server_jar)) self.server = subprocess.Popen(['java', '-jar', server_jar], stdout=subprocess.PIPE, stderr=subprocess.STDOUT) ready = False while not ready and not self.server.stdout.closed and self.server.poll() is None: line = self.server.stdout.readline() self.log("* " + line.strip()) if line is None: break elif "Started SocketListener" in line: ready = True elif "Failed" in line or "Error" in line: break if ready: self.log("Selenium server started.") else: raise Exception("Failed to start Selenium server") self.env['ROUNDCUBE_TEST_BROWSER'] = 'phantomjs' def _stop_server(self): if self.server: self.server.terminate() self.server = None self.log("Selenium server stopped") def set_env(self, var, value): """ Set Roundcube config variable through env variables """ self.env['ROUNDCUBE_' + var.upper()] = value def set_login(self, username, password): """ Set Roundcube login username and password for subsequent phpunit runs """ self.set_env('tests_username', username) self.set_env('tests_password', password) - def execute(self, testfile=None, testsuite=None, testfilter=None, selenium=False, message=None): + def execute(self, testfile=None, testsuite=None, testfilter=None, selenium=False, groups=None, excludes=None, message=None): """ Execute phpunit on a Roundcube test instance """ cwd = self.get_conf('testing', 'roundcube_dir', '/usr/share/roundcubemail') pbin = self.get_conf('testing', 'phpunit_bin', 'vendor/bin/phpunit') - conf = 'tests/Selenium/phpunit.xml' if selenium else 'tests/phpunit.xml' - args = [ pbin, '--configuration', conf ] + cxml = 'tests/Selenium/phpunit.xml' if selenium else 'tests/phpunit.xml' + args = [ pbin, '--configuration', cxml ] if self.verbose: args.append('--verbose') if testfile: args.append(testfile) else: if testsuite: args.append('--testsuite') args.append(testsuite) if testfilter: args.append('--filter') args.append(testfilter) + if groups: + if not isinstance(groups, list): + groups = [groups] + for group in groups: + args.append('--group') + args.append(group) + + if excludes: + if not isinstance(excludes, list): + excludes = [excludes] + for group in excludes: + args.append('--exclude-group') + args.append(group) + + if not conf.cli_keywords.todo: + args.append('--disallow-todo-tests') + if selenium: self._start_server() self.log("Executing %r with %r" % (args, self.env)) p = subprocess.Popen(args, cwd=cwd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT, env=self.env) for line in iter(p.stdout.readline, ''): self.log(line.strip()) retval = p.wait() self.assertEqual(retval, 0, message)