Selenium在各个测试之间测试非常缓慢

时间:2016-05-02 18:13:14

标签: django python-2.7 selenium selenium-webdriver

我使用Django 1.4,Selenium 2.53.1和Chrome Webdriver 2.21作为我的测试webdriver来测试我的Django应用程序。

我这样初始化我的课程:

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='hello@hello.com')
    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()

我的测试的一个例子如下。它会测试一个下拉菜单,其中包含多个级别,这些级别在您将鼠标移到它们之后出现并检查它们是否转到正确的链接

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')

我尝试过这些事情:

  1. 我为每次测试计算了代码,他们只花了不到一秒钟。
  2. 我还设置了setup和setupclass方法,最多需要2秒钟。
  3. 我已将set_page_load_timeout设置为0,并且不会更改总执行时间。
  4. 我通过每轮添加一个额外的测试来运行测试,并发现每次测试的总测试套件时间增加了大约40秒。
  5. 鉴于此,整套8个测试需要超过300秒,我不知道为什么。我确定Webdriver的加载需要一些时间,但在每次单独测试结束后,我都可以看到Webdriver只是坐在那里什么都不做。

2 个答案:

答案 0 :(得分:2)

最大的问题是LiveServerTestCase是Django项目中所有测试用例中最慢的。它继承自TransactionTestCase

  

TransactionTestCase继承自SimpleTestCase以添加一些   特定于数据库的功能:

     

在每次测试开始时将数据库重置为已知状态   轻松测试和使用ORM。

  

Django的TestCase类是一个比较常用的子类   TransactionTestCase,它使用数据库事务工具   加快将数据库重置为已知状态的过程   每个测试的开始。

因此,每个测试都会导致数据库完全重置,这非常慢。一种解决方案是使用-k或--keep选项。

./manage.py test -k myapp

这将从测试执行时间开始至少减少100秒。

还有另一种解决方案无法在所有条件下应用,因为TestCase不能用于Selenium测试。但是,您可以编写独立的selenium测试,连接到开发服务器以加快某些测试。在这种情况下,您可以使用python中的unittest.TestCase而不是django.test.testcases.TestCase。这听起来完全令人困惑所以让我举个例子!

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

最后但并非最不重要:通常你根本不需要LiveServerTestCase或selenium测试。使用django test client

更快更容易

答案 1 :(得分:0)

我已经将它缩小到与Django有关的事情以及它与数据库的交互方式,因为我使用connectionFactory AbandonedConfig cfg = new AbandonedConfig (); cfg.setLogAbandoned (true); cfg.setRemoveAbandonedTimeout (5); cfg.setRemoveAbandoned (true); GenericObjectPool connectionPool = new AbandonedObjectPool(null, cfg); connectionPool.setTestWhileIdle (true); connectionPool.setTestOnBorrow (true); connectionPool.setTestOnReturn (true); connectionPool.setMaxActive (5); connectionPool.setMaxWait (5000); ConnectionFactory connectionFactory = new DriverManagerConnectionFactory("jdbc:mysql://localhost:3306/Test?user=testuser&password=password",null); PoolableConnectionFactory poolableConnectionFactory = new PoolableConnectionFactory(connectionFactory,connectionPool,null,null,false,true, cfg); poolableConnectionFactory.setValidationQuery ("SELECT 1"); Class.forName("org.apache.commons.dbcp.PoolingDriver"); PoolingDriver driver = (PoolingDriver) DriverManager.getDriver("jdbc:apache:commons:dbcp:"); driver.registerPool("test_pool",connectionPool); //This throws the error Connection conn = DriverManager.getConnection( "jdbc:apache:commons:dbcp:" ); //This does too //Connection conn = DriverManager.getConnection( "jdbc:apache:commons:dbcp:Test" ); 以及我的测试方法运行:

setup

并且整体时间不会改变,将数据库更改为sqlite3会显着减少整个测试时间的某些错误。