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:
@@ -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
73
django/test/selenium.py
Normal 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()
|
||||
Reference in New Issue
Block a user