QTA自动化测试框架(四)

1、用例测试断言

在这里插入图片描述
在测试用例的执行过程中,往往需要设置一些检查点,用于判断用例执行是否符合预期。下面将介绍如何使用断言。

假设我们需要测试一个字符串拼接的函数:

def string_combine(a,b):
    return a+b

测试用例的代码如下:

from testbase.testcase import TestCase

class StrCombineTest(TestCase):
    '''测试字符串拼接接口
    '''
    owner = "foo"
    status = TestCase.EnumStatus.Ready
    priority = TestCase.EnumPriority.Normal
    timeout = 1

    def run_test(self):
        #---------------------------
        self.start_step("测试字符串拼接")
        #---------------------------
        result = string_combine("xxX", "yy")
        self.assert_("检查string_combine调用结果", result == "xxXyy")

以上的代码执行结果如下:

============================================================
测试用例:StrCombineTest 所有者:foo 优先级:Normal 超时:1分钟
============================================================
----------------------------------------
步骤1: 测试字符串拼接
============================================================
测试用例开始时间: 2016-02-02 14:10:21
测试用例结束时间: 2016-02-02 14:10:21
测试用例执行时间: 00:00:0.00
测试用例步骤结果:  1:通过
测试用例最终结果: 通过
============================================================

可以看到结果是测试通过的,但是如果string_combine实现有问题,比如我们新定义一个string_combine:

def string_combine(a,b):
    return a +'b'

因为以上的实现是有问题,执行结果必然是不通过的:

============================================================
测试用例:StrCombineTest 所有者:foo 优先级:Normal 超时:1分钟
============================================================
----------------------------------------
步骤1: 测试字符串拼接
ASSERT: 检查点不通过:
File "D:\foo\Workspace\DemoProj\test_assert.py", line 22, in run_test
self.assert_("检查string_combine调用结果", result == "xxXyy")
[检查string_combine调用结果] assert  'xxXb' == 'xxXyy'
============================================================
测试用例开始时间: 2018-08-27 17:00:30
测试用例结束时间: 2018-08-27 17:00:31
测试用例执行时间: 00:00:0.06
测试用例步骤结果:  1:失败
测试用例最终结果: 失败
============================================================
可以看到除了测试不通过外,测试结果还显示了断言失败的代码位置,断言失败的提示信息,以及实际进行断言测试的表达式。

这个就是QTA提供的测试断言的函数接口,其详细的定义如下:

class TestCase(object):

   def assert_(self, message, value):
   '''断言一个值,为False则测试用例失败

   :param message: 断言失败时的提示信息
   :param value: 目标值,可以是任何bool结果的表达式或者值,推荐使用表达式
   :return: True or False
   '''

qtaf从框架层面,提供了assert_断言测试的堆栈信息展示,使用配置项QTAF_REWRITE_ASSERT来控制是否开启,默认是开启的, 在这种情况下,我们可以更加简洁地书写测试断言了,例如我们把原本用例的断言部分整合为一条语句,修改为如下:

self.assert_("检查string_combine调用结果", string_combine("xxX", "yy") == "xxXyy")

那么实际的得到的结果可以看到,堆栈中对应的代码行就是我们书写的那条assert语句,接下来是assert的中间步骤详情:

  • 堆栈后续的第一行是断言失败时的提示信息,后面是"assert" + “‘xxxXb’ == ‘xxXyy’”(实际值表达式);
  • 后续的行是对第一行实际表达式的值的跟踪,这里的表述意思是, 'xxxXb’是由调用 string_combine(‘xxX’, ‘yy’)得到的

综上,有了assert_的中间步骤堆栈,我们可以很容易地知道,断言失败是由于string_combine函数调用结果是不正确,不仅代码书写上简单,定位问题速度也更快。

2、断言失败后置动作

QTA测试用例的代码的执行控制逻辑和一般Python的代码是类似的,所以除了执行过程中出现Python异常或用例执行超时,测试用例会一直执行,即使是assert_和wait_for系列的接口失败了,也会继续执行,比如下面的例子:

from testbase.testcase import TestCase

class FlowAfterAssertFailureTest(TestCase):
    '''流程控制测试
    '''
    owner = "foo"
    status = TestCase.EnumStatus.Ready
    priority = TestCase.EnumPriority.Normal
    timeout = 1

    def run_test(self):
        #---------------------------
        self.start_step("用例断言失败")
        #---------------------------
        self.assert_("断言失败", False)

        #---------------------------
        self.start_step("断言失败后置步骤")
        #---------------------------
        self.log_info("hello")

上面的第一个测试步骤中,前面一个步骤的断言是必然失败的,但是它不会终止后续步骤执行:

                              ============================================================
测试用例:FlowAfterAssertFailureTest 所有者:foo 优先级:Normal 超时:1分钟
============================================================
----------------------------------------
 步骤1: 用例断言失败
ASSERT: 检查点不通过:
File "D:\foo\Workspace\DemoProj\test_assert.py", line 17, in run_test
 self.assert_("断言失败", False)
[断言失败] assert  False
----------------------------------------
步骤2: 断言失败后置步骤
INFO: hello
============================================================
测试用例开始时间: 2018-08-27 17:03:28
测试用例结束时间: 2018-08-27 17:03:28
测试用例执行时间: 00:00:0.06
测试用例步骤结果:  1:失败 2:通过
测试用例最终结果: 失败
============================================================

在这里插入图片描述

3、重试机制

在这里插入图片描述
对于某些过程,我们可能无法一次性准确保证操作结果符合我们的预期,可能需要通过重试来提高稳定性。 例如,一个表单的UI界面,如果点击“提交”后,我们需要检查“提交”按钮变为不可点击的状态,测试用例可能是这样的:

form.controls['提交按钮'].click()
self.assert_("检查“提交”按钮变为不可点击的状态", form.controls['提交按钮'].enable == False)

这种写法存在的问题是,点击后,到执行assert_断言的时间极短,甚至图标还没有切换到不可点击状态,会导致断言结果不是我们预期的。 因此,我们可能会采取等待一定时间片,然后不断重试的方式:

form.controls['提交按钮'].click()
start = time.time()
while time.time()-start < 2:
   if not form.controls['提交按钮'].enable:
      break
   time.sleep(0.2)
else:
   raise RuntimeError("等待超过2秒还是可以点击")

按照上面的实现方式,只要2s内,按钮变成不可点击状态,那么就认为符合预期,因为如果2s后仍然没有切换成不可点击状态,实际上按钮就很可能确实没有切换过去。

还有另一种情况的重试,就是操作的过程耗时比较长,我们更希望按次数去重试,而不是按时间片。例如请求一个网址,由于网络不稳定,我们可能需要重试几次 才能稳定地获取到数据,这个非常简单,使用一个for循环即可。

针对重试,QTAF提供了一个统一的重试机制,同时支持两种场景,便于用户使用重试机制,示例代码如下:

from testbase.retry import Retry
for item in Retry(timeout=2, interval=0.5):
    print(item)

得到的输出如下:

<_RetryItem iter=1, ts=1535363022.06>
<_RetryItem iter=2, ts=1535363022.56>
<_RetryItem iter=3, ts=1535363023.06>
<_RetryItem iter=4, ts=1535363023.56>
Traceback (most recent call last):
  File "D:\foo\Workspace\DemoProj\test_assert.py", line 5, in <module>
    for item in Retry(timeout=2, interval=0.5):
  File "C:\Users\foo\git\qtaf\testbase\retry.py", line 54, in next
    raise RetryLimitExcceeded("funtion retried %s times in %ss" % (self.__count, self.timeout))
testbase.retry.RetryLimitExcceeded: function retried 4 times in 2s

上面代码中,(默认参数timeout=10(最大的重试时间), limit=None(重试次数), interval=0.5(重试间隔时间), raise_error=True(是否需要抛出异常))我们没有在对应时间内跳出循环,最后重试超出了限制,会抛出RetryLimitExcceeded的异常,我们也可以在构造Retry的时候指定raise_error=False, 这样也不会抛出RetryLimitExcceeded异常。如果我们的代码提前使用break跳出循环,则认为整个重试过程是成功的,不会抛出异常,例如:

from testbase.retry import Retry
for item in Retry(timeout=2, interval=0.5):
    break

迭代中,每个item包含两个属性,iteration迭代次数,ts迭代开始的时间戳,如果在迭代中有需要,可以使用这两个属性。 Retry的默认参数是tiemout=10,interval=0.5,使用最大的重试时间来重试。如果指定了limit,则会按照最大重试次数来进行重试,每次重试之间会间隔interval的时间:

from testbase.retry import Retry
for item in Retry(limit=3, interval=0.5):
    print(item)

输出结果如下:

<_RetryItem iter=1, ts=1535363744.68>
<_RetryItem iter=2, ts=1535363745.18>
<_RetryItem iter=3, ts=1535363745.68>
Traceback (most recent call last):
  File "D:\foo\Workspace\DemoProj\test_assert.py", line 4, in <module>
    for item in Retry(limit=3, interval=0.5):
  File "C:\Users\foo\git\qtaf\testbase\retry.py", line 78, in next
    raise RetryLimitExcceeded("function retried for %s times" % self.limit)
testbase.retry.RetryLimitExcceeded: function retried for 3 times

类似地,如果在重试次数用完之前,就跳出了循环,也不会抛出RetryLimitExcceeded异常。在了解testbase的重试机制后,我们针对UI按钮的检查代码就可以写成:

for _ in Retry(timeout=2, raise_error=False):
    if not form.controls['提交按钮'].enable:
        break
else:
    self.assert_("按钮没有变为不可点击状态", form.controls['提交按钮'].enable == False)

可以看出,这样写起来就会简洁很多。如果一个目标函数调用在成功的情况下会返回一个bool判定为True的结果,可以直接调用Retry对象的call方法:

result = Retry(limit=2, interval=0.5).call(getattr, (form.controls['提交按钮'], "enable"))

如上,如果符合我们预期,那么result的值会等于True,否则,会抛出RetryLimitExcceeded异常。

4、忙等待检查

在重试机制的时候,我们已经提到了,对于UI操作的检查可以通过Retry来进行检查,testbase提供了wait_for_equal和wait_for_match, 它内部使用到了Retry,用于实现我们所需要的忙等待检查功能,书写可以进一步简化:

form.controls['提交按钮'].click()
self.wait_for_equal("检查提交按钮变为不可点击", form.controls['提交按钮'], "enable", False, timeout=2, interval=0.2)

如果在2s内,form.controls[‘提交按钮’].enable没有变成False,那么最终用例失败,跟assert_类似,wait_for系列接口失败,用例仍然会继续执行。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
很好,您想了解关于GUI自动化测试工具的方法原理、使用场景、特点和优缺点,以及相关公司的官网地址。我可以为您提供以下信息: 方法原理: GUI自动化测试工具是基于图形用户界面的软件测试工具,主要通过模拟人类操作的方式,实现对软件图形界面的测试。常用的自动化测试框架包括Selenium、Appium、UI Automator等。 使用场景: GUI自动化测试工具适用于软件测试中对于图形用户界面的测试,可以测试各种类型的应用程序,如Web应用程序、桌面软件、移动应用程序等。在软件开发的不同阶段,GUI自动化测试工具可以用于快速回归测试、持续集成测试、功能测试等。 特点和优缺点: GUI自动化测试工具的主要特点包括自动化程度高、测试效率高、容易实现持续集成等。同时,GUI自动化测试工具还可以对测试脚本进行自动化管理、跨平台测试等。但是,GUI自动化测试工具也存在一些缺点,例如测试用例设计较为困难、测试环境要求高、测试结果的可靠性等方面仍有待改进。 官网地址: 国内GUI自动化测试工具相关公司的官网地址如下: - 网易Airtest:https://airtest.netease.com/ - 美团AlphaTest:https://github.com/Meituan-Dianping/Athena - 阿里Macaca:https://macacajs.github.io/ - 腾讯QTA:https://qta.qq.com/ 而国外的GUI自动化测试工具主要有:Sikuli、Selenium、Katalon Studio等,官网地址如下: - Sikuli:http://sikuli.org/ - Selenium:https://www.selenium.dev/ - Katalon Studio:https://www.katalon.com/ 希望我的回答能够对您有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值