1
0
mirror of https://github.com/django/django.git synced 2025-10-24 22:26:08 +00:00

Fixed #25364 -- Added generic way to test on all browsers supported by selenium.

Browser names should be passed as a comma separated list to the --selenium flag.

Thanks Tim Graham, Simon Charette and Moritz Sichert for review and discussion.
This commit is contained in:
Akshesh
2016-02-07 07:54:36 +05:30
committed by Simon Charette
parent 93a135d111
commit 44c0ecdd92
11 changed files with 138 additions and 188 deletions

View File

@@ -1,9 +1,6 @@
import os
from unittest import SkipTest
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
from django.test import modify_settings, tag
from django.utils.module_loading import import_string
from django.test import modify_settings
from django.test.selenium import SeleniumTestCase
from django.utils.translation import ugettext as _
@@ -14,11 +11,10 @@ class CSPMiddleware(object):
return response
@tag('selenium')
@modify_settings(
MIDDLEWARE_CLASSES={'append': 'django.contrib.admin.tests.CSPMiddleware'},
)
class AdminSeleniumWebDriverTestCase(StaticLiveServerTestCase):
class AdminSeleniumTestCase(SeleniumTestCase, StaticLiveServerTestCase):
available_apps = [
'django.contrib.admin',
@@ -27,26 +23,6 @@ class AdminSeleniumWebDriverTestCase(StaticLiveServerTestCase):
'django.contrib.sessions',
'django.contrib.sites',
]
webdriver_class = 'selenium.webdriver.firefox.webdriver.WebDriver'
@classmethod
def setUpClass(cls):
if not os.environ.get('DJANGO_SELENIUM_TESTS', False):
raise SkipTest('Selenium tests not requested')
try:
cls.selenium = import_string(cls.webdriver_class)()
except Exception as e:
raise SkipTest('Selenium webdriver "%s" not installed or not '
'operational: %s' % (cls.webdriver_class, str(e)))
cls.selenium.implicitly_wait(10)
# This has to be last to ensure that resources are cleaned up properly!
super(AdminSeleniumWebDriverTestCase, cls).setUpClass()
@classmethod
def _tearDownClassInternal(cls):
if hasattr(cls, 'selenium'):
cls.selenium.quit()
super(AdminSeleniumWebDriverTestCase, cls)._tearDownClassInternal()
def wait_until(self, callback, timeout=10):
"""

73
django/test/selenium.py Normal file
View File

@@ -0,0 +1,73 @@
from __future__ import unicode_literals
import sys
import unittest
from django.test import LiveServerTestCase, tag
from django.utils.module_loading import import_string
from django.utils.six import with_metaclass
from django.utils.text import capfirst
class SeleniumTestCaseBase(type(LiveServerTestCase)):
# List of browsers to dynamically create test classes for.
browsers = []
# Sentinel value to differentiate browser-specific instances.
browser = None
def __new__(cls, name, bases, attrs):
"""
Dynamically create new classes and add them to the test module when
multiple browsers specs are provided (e.g. --selenium=firefox,chrome).
"""
test_class = super(SeleniumTestCaseBase, cls).__new__(cls, name, bases, attrs)
# If the test class is either browser-specific or a test base, return it.
if test_class.browser or not any(name.startswith('test') and callable(value) for name, value in attrs.items()):
return test_class
elif test_class.browsers:
# Reuse the created test class to make it browser-specific.
# We can't rename it to include the browser name or create a
# subclass like we do with the remaining browsers as it would
# either duplicate tests or prevent pickling of its instances.
first_browser = test_class.browsers[0]
test_class.browser = first_browser
# Create subclasses for each of the remaining browsers and expose
# them through the test's module namespace.
module = sys.modules[test_class.__module__]
for browser in test_class.browsers[1:]:
browser_test_class = cls.__new__(
cls,
str("%s%s" % (capfirst(browser), name)),
(test_class,),
{'browser': browser, '__module__': test_class.__module__}
)
setattr(module, browser_test_class.__name__, browser_test_class)
return test_class
# If no browsers were specified, skip this class (it'll still be discovered).
return unittest.skip('No browsers specified.')(test_class)
@classmethod
def import_webdriver(cls, browser):
return import_string("selenium.webdriver.%s.webdriver.WebDriver" % browser)
def create_webdriver(self):
return self.import_webdriver(self.browser)()
@tag('selenium')
class SeleniumTestCase(with_metaclass(SeleniumTestCaseBase, LiveServerTestCase)):
@classmethod
def setUpClass(cls):
cls.selenium = cls.create_webdriver()
cls.selenium.implicitly_wait(10)
super(SeleniumTestCase, cls).setUpClass()
@classmethod
def _tearDownClassInternal(cls):
# quit() the WebDriver before attempting to terminate and join the
# single-threaded LiveServerThread to avoid a dead lock if the browser
# kept a connection alive.
if hasattr(cls, 'selenium'):
cls.selenium.quit()
super(SeleniumTestCase, cls)._tearDownClassInternal()