zoukankan      html  css  js  c++  java
  • Django学习系列20:改进功能测试

    隐示等待和显示等待

    我们看看在功能测试中function_tests.py中的 time.sleep

    inputbox.send_keys(Keys.ENTER)
     time.sleep(1)
     self.check_for_row_in_list_table('1: Buy peacock feathers')

    这就是所谓的“显性等待”。这与“隐式等待”形成对比:在某些情况下,selenium会在认为页面正在加载时尝试“自动”等待您。

    它甚至提供了一个名为隐式等待的方法,让您可以控制如果您向它请求一个似乎还不在页面上的元素,它将等待多长时间。

    问题是,隐式等待总是有点不稳定,随着selenium 3的发行,隐式等待变得更加不可靠。

    同时,selenium团队的普遍观点是,隐性等待只是一个坏主意,应该避免。

    所以这个版本从一开始就有明确的显示等待。但问题是那些时间谁说就是正确的时间呢?对于大多数测试,我们都是针对自己的机器来定,一秒钟太长了,0.1秒就可以了。

    但如果你把它定得这么低,会因为笔记本电脑有点卡那就慢一点。

    因此,让我们用一个工具来代替,这个工具将等待所需的时间,直到捕捉到任何故障的很长的超时时间。

    我们将把check_for_row_in_list_table重命名为wait_for_row_in_list_table,并为其添加一些轮询/重试逻辑:

    from selenium.common.exceptions import WebDriverException
    
    
    Max_WAIT = 10  # 1
    【……】
        def wait_for_row_in_list_table(self, row_text):
            start_time = time.time()
            while True:  # 2
                try:
                    table = self.browser.find_element_by_id('id_list_table')  # 3
                    rows = table.find_element_by_tag_name('tr')
                    self.assertIn(row_text, [row_text for row in rows])
                    return  # 4
                except (AssertionError, WebDriverException) as e:  # 5
                    if time.time() - start_time > Max_WAIT:  # 6
                        raise e  # 6
                    time.sleep(0.5)  # 5

    代码解析:

    1、Max_WAIT”的常数来设置我们准备等待的最大时间。10秒应该足够捕捉任何故障或随机慢行。

    2、这是一个循环,除非我们到达两条可能的出口路线之一。

    3、下面是来自旧版本方法的三行断言

    4、 如果我们通过了它们,断言通过了,我们就从函数返回并退出循环

    5、但是,如果捕捉到异常,我们会等待很短的时间,然后循环重试。

    我们要捕获两种类型的异常:页面未加载时的WebDriverException和页面上的Selenium找不到Table元素时的WebDriverException,以及表存在时的AssertionError,但它可能是页面重新加载前的表,因此它尚未包含我们的行。

    6、这是我们的第二条逃生路线。如果我们达到这一点,这意味着我们的代码每次尝试都会引发异常,直到超过超时设置。所以这次,我们再次提出异常,让它冒泡到我们的测试中,并且很可能在我们的回溯中结束,告诉我们为什么测试失败。

    这段代码让我们难看清到底在做什么?稍后,我们将重构一个一般的wait_for helper,以将计时和重新提升逻辑与测试断言分离。
    如果您以前使用过selenium,那么您可能知道它有几个helper函数要做等待。后面我们将构建两个wait helper工具,这些工具可以生成漂亮、可读的代码。

    现在我们可以重命名我们的方法调用并删除 time.sleeps:

            # 页面再次更新,清单中显示了这两个待办事项
            inputbox.send_keys(Keys.ENTER)
            time.sleep(1)
            self.wait_for_row_in_list_table('1: Buy peacock feathers')
    
            # 页面中又显示了一个文本框,可以输入其他的待办事项
            inputbox = self.browser.find_element_by_id('id_new_item')
            inputbox.send_keys('Use peacock feathers to make a fly')
            inputbox.send_keys(Keys.ENTER)
            time.sleep(1)
    
            # 页面再次更新,她的清单中显示了这两个待办事项
            self.wait_for_row_in_list_table('2: Use peacock feathers to make a fly')
            self.wait_for_row_in_list_table('1: Buy peacock feathers')

     python manage.py test

    Ran 8 tests in 0.522s
    
    FAILED (errors=1)
    Destroying test database for alias 'default'...

    我们到了同一个地方,注意到执行时间也缩短了几秒钟。现在看起来可能不多,但总而言之,为了检查我们做得对,让我们用几种方法故意破坏测试,并看到一些错误。

    首先,让我们检查一下,如果我们在will never appear中查找某些行文本,我们将得到正确的错误:

        def wait_for_row_in_list_table(self, row_text):
            start_time = time.time()
            while True:  # 2
                try:
                    table = self.browser.find_element_by_id('id_list_table')  # 3
                    rows = table.find_element_by_tag_name('tr')
                    # self.assertIn(row_text, [row_text for row in rows])
                    self.assertIn('foo', [row_text for row in rows])
                    return  # 4
                except (AssertionError, WebDriverException) as e:  # 5
                    if time.time() - start_time > Max_WAIT:  # 6
                        raise e  # 6
                    time.sleep(0.5)  # 5

    小结:

    不同的测试不应该互相影响。这意味着我们需要在每次测试结束时重置任何永久状态。django的test runner通过创建一个测试数据库来帮助我们做到这一点,它在每个测试之间清除这个数据库。

    每当我们需要等待加载时,time.sleep()。但问题是,我们等待的时间总是有点太长,要么太短,容易受到虚假失败的影响,这会减慢我们的测试运行速度。

    不依赖selenium的隐式等待理论上selenium确实做了一些“隐式”等待,但是实现在浏览器之间是不同的,并且在编写时在selenium 3 firefox驱动程序中是非常不可靠的。“显式优于隐式”,正如python的zen所说,所以更喜欢显式等待。

  • 相关阅读:
    ArcGis Python脚本——遍历输出面或折线要素的折点坐标
    ArcGis Python脚本——根据接图表批量裁切分幅影像
    ArcGis安装失败提示“需要Microsoft .NET Framework 3.5 sp1或等效环境”的解决方法
    PLSQL Developer 远程连接Oracle数据库
    Oracle使用PLSQL导入数据后中文乱码的解决方法
    使用ArcMap做一个1:5000标准分幅图并编号
    ArcGis地理坐标系转投影坐标系问题的思考与处理
    CI框架 输入类
    PHP获取当前页面的URL作为参数以供下一层的页面可以返回上一层页面
    用js实现返回上一页
  • 原文地址:https://www.cnblogs.com/ranxf/p/11698456.html
Copyright © 2011-2022 走看看