diff --git a/django/test/selenium.py b/django/test/selenium.py index 6e6badd933..8910faec98 100644 --- a/django/test/selenium.py +++ b/django/test/selenium.py @@ -17,6 +17,8 @@ class SeleniumTestCaseBase(type(LiveServerTestCase)): external_host = None # Sentinel value to differentiate browser-specific instances. browser = None + # Run browsers in headless mode. + headless = False def __new__(cls, name, bases, attrs): """ @@ -62,11 +64,24 @@ class SeleniumTestCaseBase(type(LiveServerTestCase)): def import_webdriver(cls, browser): return import_string("selenium.webdriver.%s.webdriver.WebDriver" % browser) + @classmethod + def import_options(cls, browser): + return import_string('selenium.webdriver.%s.options.Options' % browser) + @classmethod def get_capability(cls, browser): from selenium.webdriver.common.desired_capabilities import DesiredCapabilities return getattr(DesiredCapabilities, browser.upper()) + def create_options(self): + options = self.import_options(self.browser)() + if self.headless: + try: + options.headless = True + except AttributeError: + pass # Only Chrome and Firefox support the headless mode. + return options + def create_webdriver(self): if self.selenium_hub: from selenium import webdriver @@ -74,7 +89,7 @@ class SeleniumTestCaseBase(type(LiveServerTestCase)): command_executor=self.selenium_hub, desired_capabilities=self.get_capability(self.browser), ) - return self.import_webdriver(self.browser)() + return self.import_webdriver(self.browser)(options=self.create_options()) @tag('selenium') diff --git a/docs/internals/contributing/writing-code/unit-tests.txt b/docs/internals/contributing/writing-code/unit-tests.txt index 4cedb1ccf3..6d9074f2d1 100644 --- a/docs/internals/contributing/writing-code/unit-tests.txt +++ b/docs/internals/contributing/writing-code/unit-tests.txt @@ -230,6 +230,9 @@ See the `selenium.webdriver`_ package for the list of available browsers. Specifying ``--selenium`` automatically sets ``--tags=selenium`` to run only the tests that require selenium. +Some browsers (e.g. Chrome or Firefox) support headless testing, which can be +faster and more stable. Add the ``--headless`` option to enable this mode. + .. _selenium.webdriver: https://github.com/SeleniumHQ/selenium/tree/master/py/selenium/webdriver .. _running-unit-tests-dependencies: diff --git a/docs/releases/3.0.txt b/docs/releases/3.0.txt index daf1ef513b..fc2aad9b17 100644 --- a/docs/releases/3.0.txt +++ b/docs/releases/3.0.txt @@ -254,6 +254,9 @@ Tests references, and entity references that refer to the same character as equivalent. +* Django test runner now supports headless mode for selenium tests on supported + browsers. Add the ``--headless`` option to enable this mode. + URLs ~~~~ diff --git a/tests/runtests.py b/tests/runtests.py index 96ec30d51a..e117df709b 100755 --- a/tests/runtests.py +++ b/tests/runtests.py @@ -446,6 +446,10 @@ if __name__ == "__main__": '--selenium', action=ActionSelenium, metavar='BROWSERS', help='A comma-separated list of browsers to run the Selenium tests against.', ) + parser.add_argument( + '--headless', action='store_true', + help='Run selenium tests in headless mode, if the browser supports the option.', + ) parser.add_argument( '--selenium-hub', help='A URL for a selenium hub instance to use in combination with --selenium.', @@ -506,6 +510,7 @@ if __name__ == "__main__": if options.selenium_hub: SeleniumTestCaseBase.selenium_hub = options.selenium_hub SeleniumTestCaseBase.external_host = options.external_host + SeleniumTestCaseBase.headless = options.headless SeleniumTestCaseBase.browsers = options.selenium if options.bisect: