Commits

Takumi IINO committed b6eb483 Draft

tests: add a test case class for integration testing

Kallithea dose not have a test case class for integration testing.

This patch add LiveServerTestCase class and headless browser helper(splinter).

Comments (0)

Files changed (4)

kallithea/tests/__init__.py

 import datetime
 import hashlib
 import tempfile
+import threading
 from os.path import join as jn
 
 from tempfile import _RandomNameSequence
 from webtest import TestApp
 from nose.plugins.skip import SkipTest
 
+from splinter import Browser
+
 from kallithea.lib.compat import unittest
 from kallithea import is_windows
 from kallithea.model.meta import Session
 
 __all__ = [
     'parameterized', 'environ', 'url', 'get_new_dir', 'TestController',
-    'SkipTest', 'ldap_lib_installed', 'BaseTestCase', 'init_stack',
+    'LiveServerTestCase', 'SkipTest', 'ldap_lib_installed', 'BaseTestCase', 'init_stack',
     'TESTS_TMP_PATH', 'HG_REPO', 'GIT_REPO', 'NEW_HG_REPO', 'NEW_GIT_REPO',
     'HG_FORK', 'GIT_FORK', 'TEST_USER_ADMIN_LOGIN', 'TEST_USER_ADMIN_PASS',
     'TEST_USER_REGULAR_LOGIN', 'TEST_USER_REGULAR_PASS',
             msg = u'msg `%s` not found in session flash: got `%s` instead' % (
                       msg, response.session['flash'][0][1])
             self.fail(safe_str(msg))
+
+
+class LiveServerThread(threading.Thread):
+
+    def __init__(self, pylonsapp):
+        self.pylonsapp = pylonsapp
+        self.is_ready = threading.Event()
+        self.error = None
+        super(LiveServerThread, self).__init__()
+
+    def run(self):
+        from wsgiref.simple_server import WSGIRequestHandler, WSGIServer
+        import ConfigParser
+
+        class QuietHandler(WSGIRequestHandler):
+            def log_request(*args, **kw):
+                pass
+
+        try:
+            config = ConfigParser.RawConfigParser()
+            config.read(self.pylonsapp.config['__file__'])
+            host = config.get('server:main', 'host')
+            port = config.getint('server:main', 'port')
+            self.httpd = WSGIServer((host, port), QuietHandler)
+
+            self.httpd.set_app(self.pylonsapp)
+            self.is_ready.set()
+            self.httpd.serve_forever()
+        except Exception as e:
+            self.error = e
+            self.is_ready.set()
+
+    def terminate(self):
+        if hasattr(self, 'httpd'):
+            self.httpd.shutdown()
+            self.httpd.server_close()
+
+
+class LiveServerTestCase(BaseTestCase):
+
+    def __init__(self, *args, **kwargs):
+        BaseTestCase.__init__(self, *args, **kwargs)
+
+    @property
+    def live_server_url(self):
+        return 'http://%s:%s' % self.server_thread.httpd.server_address
+
+    def url(self, *args, **kwargs):
+        return self.live_server_url + url(*args, **kwargs)
+
+    @classmethod
+    def setUpClass(cls):
+        cls.browser = Browser('phantomjs')
+
+    @classmethod
+    def tearDownClass(cls):
+        cls.browser.quit()
+
+    def setUp(self):
+        self.server_thread = LiveServerThread(self.wsgiapp)
+        self.server_thread.daemon = True
+        self.server_thread.start()
+
+        self.server_thread.is_ready.wait()
+        if self.server_thread.error:
+            # Clean up behind ourselves, since tearDownClass won't get called in
+            # case of errors.
+            self._tearDownInternal()
+            raise self.server_thread.error
+
+    def _tearDownInternal(self):
+        if hasattr(self, 'server_thread'):
+            self.server_thread.terminate()
+            self.server_thread.join()
+
+    def tearDown(self):
+        self._tearDownInternal()

kallithea/tests/integration/__init__.py

Empty file added.

kallithea/tests/integration/test_login.py

+# -*- coding: utf-8 -*-
+from kallithea.tests import *
+
+class TestLogin(LiveServerTestCase):
+
+    def test_index(self):
+        self.browser.visit(self.url(controller='home', action='index'))
+        self.assertIsNotNone(self.browser.find_by_name('sign_in').first)
+        self.browser.is_text_present('Not logged in')
+
+    def test_login_admin_ok(self):
+        self.browser.visit(self.url(controller='login', action='index'))
+        self.browser.fill('username', 'test_admin')
+        self.browser.fill('password', 'test12')
+        login_button = self.browser.find_by_name('sign_in').first
+        login_button.click()
+        self.browser.is_text_present('Kallithea Admin')
+
+    def test_logout_admin_ok(self):
+        self.browser.visit(self.url(controller='login', action='logout'))
+        self.browser.is_text_present('Not logged in')
     "pycrypto>=2.6.0,<=2.6.1",
     "URLObject==2.3.4",
     "Routes==1.13",
+    "splinter==0.6.0",
 ]
 
 if sys.version_info < (2, 6):