Skip to content

Commit

Permalink
Fixed #2879 -- Added support for the integration with Selenium and ot…
Browse files Browse the repository at this point in the history
…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
julien committed Dec 22, 2011
1 parent 1ed145b commit 8569856
Show file tree
Hide file tree
Showing 21 changed files with 921 additions and 46 deletions.
52 changes: 52 additions & 0 deletions django/contrib/admin/tests.py
@@ -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))
37 changes: 27 additions & 10 deletions django/core/management/commands/test.py
@@ -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
Expand All @@ -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(),
Expand All @@ -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)

Expand Down
3 changes: 2 additions & 1 deletion django/test/__init__.py
Expand Up @@ -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

0 comments on commit 8569856

Please sign in to comment.