Reputation: 428
I'm using Django 1.4, Selenium 2.53.1 and Chrome Webdriver 2.21 as my testing webdriver to test my Django app.
I initialize my class as such:
class SeleniumTest(LiveServerTestCase):
@classmethod
def setUpClass(cls):
cls.display = Display(visible=0, size=(800, 600))
cls.display.start()
cls.driver = webdriver.Chrome()
cls.driver.set_page_load_timeout(15)
cls.driver.maximize_window()
super(SeleniumTest, cls).setUpClass()
def setUp(self):
settings.SESSION_ENGINE = 'django.contrib.sessions.backends.db'
engine = import_module(settings.SESSION_ENGINE)
self.sessionStore = engine.SessionStore()
self.sessionStore.save()
username = 'hello'
password = 'hello'
self.cad_user, created = User.objects.get_or_create(username=username, email='[email protected]')
self.cad_user.set_password(password)
self.cad_user.save()
try:
self.get_url('login')
if self.driver.title == 'Login':
self.driver.find_element_by_id('id_username').send_keys(username)
self.driver.find_element_by_id('id_password').send_keys(password)
self.driver.find_element_by_css_selector('input[type="submit"]').click()
An example one of my tests is below. It tests a dropdown with multiple levels that appear after you move your mouse over them and checks that they go to correct link
def dropdown_check(self, header_ids, choice_id, title):
choice = self.driver.find_element_by_id(choice_id)
mouse = webdriver.ActionChains(self.driver)
for header_id in header_ids:
header_element = self.driver.find_element_by_id(header_id)
WebDriverWait(self.driver, 1).until(EC.element_to_be_clickable((By.ID, header_id)))
mouse.move_to_element(header_element)
mouse.perform()
WebDriverWait(self.driver, 1).until(EC.element_to_be_clickable((By.ID, choice_id)))
choice.click()
self.assertEquals(self.driver.title, title)
def test_my_status_navigation(self):
self.dropdown_check(['menubar_my_status'], 'menubar_my_status', 'User Status')
I've tried these things:
Given this, the entire suite of 8 tests takes over 300+ seconds and I have no idea why. I'm sure the loading of Webdriver takes some time, but after each individual test ends, I can see the Webdriver just sit there and do nothing.
Upvotes: 2
Views: 1031
Reputation: 53754
The biggest issue is that LiveServerTestCase
is the slowest of all the test cases in the Django Project. It inherits from TransactionTestCase
TransactionTestCase inherits from SimpleTestCase to add some database-specific features:
Resetting the database to a known state at the beginning of each test to ease testing and using the ORM.
and
Django’s TestCase class is a more commonly used subclass of TransactionTestCase that makes use of database transaction facilities to speed up the process of resetting the database to a known state at the beginning of each test.
Thus each of your tests results in the database being completely reset, which is really slow. One solution is to use the -k or --keep option.
./manage.py test -k myapp
This will cut off at least 100 seconds from your test execution time.
There is another solution that cannot be applied in all conditions because TestCase cannot be used for Selenium Tests. However you can write independent selenium tests that connect to the dev server to speed some tests up. In this case you use unittest.TestCase
from from python instead of django.test.testcases.TestCase
. That sounds totally confusing so let me give an example!
from unittest import TestCase
from selenium import webdriver
class SeleniumTest(TestCase):
def setUp(self):
# usual code to setup drivers etc
def testSomething(self):
self.driver.get('localhost:8000/somepage')
# now you are connecting directly to the development server.
# this approach is not suitable for all requirements but
# very fast compared to using a LiveServerTestCase
Last but not least: Often you don't need LiveServerTestCase or selenium tests at all. It's much faster and easier to use the django test client
Upvotes: 4
Reputation: 428
I've narrowed it down to something to do with Django and how it interacts with the database because I've run with setup
and setUpClass
as well as my test methods as:
def setUpClass(cls):
pass
And the overall time does not change and changing the database to sqlite3 significantly decreases the total test time albiet some errors.
Upvotes: 0