Permalink
Browse files

Fixed #2879 -- Added support for the integration with Selenium and ot…

…her in-browser testing frameworks. Also added the first Selenium tests for `contrib.admin`. Many thanks to everyone for their contributions and feedback: Mikeal Rogers, Dirk Datzert, mir, Simon G., Almad, Russell Keith-Magee, Denis Golomazov, devin, robertrv, andrewbadr, Idan Gazit, voidspace, Tom Christie, hjwp2, Adam Nelson, Jannis Leidel, Anssi Kääriäinen, Preston Holmes, Bruno Renié and Jacob Kaplan-Moss.

git-svn-id: http://code.djangoproject.com/svn/django/trunk@17241 bcc190cf-cafb-0310-a4f2-bffc1f526a37
  • Loading branch information...
1 parent 45e3dff commit 2f02a05ffb45be68b4164b4785ff1826833150a3 @jphalip jphalip committed Dec 22, 2011
@@ -0,0 +1,52 @@
+import sys
+
+from django.test import LiveServerTestCase
+from django.utils.importlib import import_module
+from django.utils.unittest import SkipTest
+from django.utils.translation import ugettext as _
+
+class AdminSeleniumWebDriverTestCase(LiveServerTestCase):
+ webdriver_class = 'selenium.webdriver.firefox.webdriver.WebDriver'
+
+ @classmethod
+ def setUpClass(cls):
+ if sys.version_info < (2, 6):
+ raise SkipTest('Selenium Webdriver does not support Python < 2.6.')
+ try:
+ # Import and start the WebDriver class.
+ module, attr = cls.webdriver_class.rsplit('.', 1)
+ mod = import_module(module)
+ WebDriver = getattr(mod, attr)
+ cls.selenium = WebDriver()
+ except Exception:
+ raise SkipTest('Selenium webdriver "%s" not installed or not '
+ 'operational.' % cls.webdriver_class)
+ super(AdminSeleniumWebDriverTestCase, cls).setUpClass()
+
+ @classmethod
+ def tearDownClass(cls):
+ super(AdminSeleniumWebDriverTestCase, cls).tearDownClass()
+ if hasattr(cls, 'selenium'):
+ cls.selenium.quit()
+
+ def admin_login(self, username, password, login_url='/admin/'):
+ """
+ Helper function to log into the admin.
+ """
+ self.selenium.get('%s%s' % (self.live_server_url, login_url))
+ username_input = self.selenium.find_element_by_name('username')
+ username_input.send_keys(username)
+ password_input = self.selenium.find_element_by_name('password')
+ password_input.send_keys(password)
+ login_text = _('Log in')
+ self.selenium.find_element_by_xpath(
+ '//input[@value="%s"]' % login_text).click()
+
+ def get_css_value(self, selector, attribute):
+ """
+ Helper function that returns the value for the CSS attribute of an
+ DOM element specified by the given selector. Uses the jQuery that ships
+ with Django.
+ """
+ return self.selenium.execute_script(
+ 'return django.jQuery("%s").css("%s")' % (selector, attribute))
@@ -1,20 +1,32 @@
+import sys
+import os
+from optparse import make_option, OptionParser
+
from django.conf import settings
from django.core.management.base import BaseCommand
-from optparse import make_option, OptionParser
-import sys
from django.test.utils import get_runner
class Command(BaseCommand):
option_list = BaseCommand.option_list + (
- make_option('--noinput', action='store_false', dest='interactive', default=True,
+ make_option('--noinput',
+ action='store_false', dest='interactive', default=True,
help='Tells Django to NOT prompt the user for input of any kind.'),
- make_option('--failfast', action='store_true', dest='failfast', default=False,
- help='Tells Django to stop running the test suite after first failed test.'),
- make_option('--testrunner', action='store', dest='testrunner',
- help='Tells Django to use specified test runner class instead of the one '+
- 'specified by the TEST_RUNNER setting.')
+ make_option('--failfast',
+ action='store_true', dest='failfast', default=False,
+ help='Tells Django to stop running the test suite after first '
+ 'failed test.'),
+ make_option('--testrunner',
+ action='store', dest='testrunner',
+ help='Tells Django to use specified test runner class instead of '
+ 'the one specified by the TEST_RUNNER setting.'),
+ make_option('--liveserver',
+ action='store', dest='liveserver', default=None,
+ help='Overrides the default address where the live server (used '
+ 'with LiveServerTestCase) is expected to run from. The '
+ 'default value is localhost:8081.'),
)
- help = 'Runs the test suite for the specified applications, or the entire site if no apps are specified.'
+ help = ('Runs the test suite for the specified applications, or the '
+ 'entire site if no apps are specified.')
args = '[appname ...]'
requires_model_validation = False
@@ -35,7 +47,8 @@ def run_from_argv(self, argv):
def create_parser(self, prog_name, subcommand):
test_runner_class = get_runner(settings, self.test_runner)
- options = self.option_list + getattr(test_runner_class, 'option_list', ())
+ options = self.option_list + getattr(
+ test_runner_class, 'option_list', ())
return OptionParser(prog=prog_name,
usage=self.usage(subcommand),
version=self.get_version(),
@@ -48,6 +61,10 @@ def handle(self, *test_labels, **options):
TestRunner = get_runner(settings, options.get('testrunner'))
options['verbosity'] = int(options.get('verbosity'))
+ if options.get('liveserver') is not None:
+ os.environ['DJANGO_LIVE_TEST_SERVER_ADDRESS'] = options['liveserver']
+ del options['liveserver']
+
test_runner = TestRunner(**options)
failures = test_runner.run_tests(test_labels)
@@ -4,5 +4,6 @@
from django.test.client import Client, RequestFactory
from django.test.testcases import (TestCase, TransactionTestCase,
- SimpleTestCase, skipIfDBFeature, skipUnlessDBFeature)
+ SimpleTestCase, LiveServerTestCase, skipIfDBFeature,
+ skipUnlessDBFeature)
from django.test.utils import Approximate
Oops, something went wrong. Retry.

0 comments on commit 2f02a05

Please sign in to comment.