本文主要是介绍MQC功能测试大揭秘(4)- MQC 功能测试 DEMO,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
MQC为大家提供了海量的适配真机、强大的在线录制、遍历的用例管理、定制化的报告展示等功能,这篇文章将会通过一个 DEMO 教会大家如何利用好 MQC 提供的这些服务来回归测试自己的 App。
如何使用 MQC 功能测试服务?
Appium 基础篇有提到,desired capabilities 会提供 appium 运行时的各项环境参数,MQC 在功能测试开始前会动态生成desired capabilities类,用户脚本只需要调用相关 api 即可快速启动 Appium。
import desired_capabilitiesdef setUp():desired_caps = desired_capabilities.get_desired_capabilities()uri = desired_capabilities.get_uri()driver = webdriver.Remote(uri, desired_caps)
除此之外,MQC 提供了许多定制化的操作,只需要按照格式进行简单的 log 打印,就可以实现记录步骤、截图、记录执行状态等等操作,使得报告更加完善。当然,不打日志同样可以使用功能测试服务,只需要上传一个可执行的 main.py 文件(打包成zip文件)。
# 步骤1: 等待5s
print "STEP : 等待5s"
# 判断该步骤执行状态,FATAL : exception, 表示该步骤失败; ASSERT : true, 表示该步骤成功; ASSERT : false, 表示该步骤失败且该用例也失败
print "FATAL : element not found"
# 为该步骤截图
print "SCREENSHOT : 1"
一个合理且容易被解析的日志结构应该如下:
STEP : 等待5s
SCREENSHOT : 0
STEP : 点击控件:com.hexin.plat.android.ShenWanHongYuanSecurity:id/launch_ad
FATAL : element not found
SCREENSHOT : 1
STEP : 等待5s
SCREENSHOT : 2
STEP : 点击控件:请输入您有效的手机号
ASSERT : true
SCREENSHOT : 3
那么,我们可以把上篇文章的 DEMO 进行改造,脚本如下:
# -*- coding: UTF-8 -*-
import unittest
import time
import sysfrom appium import webdriver
from time import sleep
from unittest import TestCase
from appium.webdriver.common.touch_action import TouchAction
from selenium.webdriver.common.touch_actions import TouchActionsclass MqcAppium(TestCase):#设备宽高global widthglobal height#unittest 启动def setUp(self):desired_caps = self.get_desired_capabilities()uri = "http://localhost:4723/wd/hub"retry = 0while retry < 2:try:self.driver = webdriver.Remote(uri, desired_caps)breakexcept Exception, e:retry += 1if retry == 2:raise esleep(10)# 获取当前设备分辨率self.window_size = self.driver.get_window_size()self.width = self.window_size["width"]self.height = self.window_size["height"]# unittest 用例,用 test_**** 命名def test_login(self):#大部分app启动后会有动画,启动延迟等,视情况预留启动延迟sleep(5)#通过 resource-id 与 index 查找 个人中心 控件navPerson = self.wait_for_element(id="com.yunos.mqc:id/id_indicator_discovery", index=3);navPerson.click()#通过 text 查找 尚未登录noLogin = self.wait_for_element(xpath=("//*[@text='%s']" % ("尚未登录")));noLogin.click()#通过 xpath、resource-id 多种方式定位登录控件,避免有些手机上 xpath 失效或者不一致的情况inputUsername = self.wait_for_element(xpath="//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]\/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.LinearLayout[1]/android.widget.EditText[1]", id="com.yunos.mqc:id/custom_account")inputUsername.click()inputUsername.send_keys("mqc_test")inputPassword = self.wait_for_element(xpath="//android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/\android.widget.FrameLayout[1]/android.widget.LinearLayout[1]/android.widget.LinearLayout[1]/android.widget.EditText[2]", id="com.yunos.mqc:id/custom_passwd")inputPassword.click()inputPassword.send_keys("123456")login = self.wait_for_element(id="com.yunos.mqc:id/custom_loginBtn")login.click()#返回 广场 并且向下滑动navGround = self.wait_for_element(id="com.yunos.mqc:id/id_indicator_discovery", index=0);navGround.click()#与前文 swipe 函数不同的是,为了兼容不同分辨率的手机,滑动操作应当使用 比例 而非 绝对坐标,当然,若是需要精确地滑动操作,建议使用scrollToself.swipe([[0.5, 0.7], [0.5, 0.6], [0.5, 0.5], [0.5, 0.4], [0.5, 0.3]])def tearDown(self):try:self.driver.quit()except:passdef swipe(self, points):last_x = 0last_y = 0swipe_action = TouchAction(self.driver)for i in range(0, len(points)):x=float(points[i][0]) * self.widthy=float(points[i][1]) * self.heightif i == 0:swipe_action = swipe_action.press(None, x, y).wait(20)elif i == (len(points) - 1):swipe_action = swipe_action.move_to(None, x - last_x, y - last_y).release()swipe_action.perform()else:swipe_action = swipe_action.move_to(None, x - last_x, y - last_y).wait(20)last_x = xlast_y = ydef wait_for_element(self, xpath=None, id=None, index=None, timeout=3):startTime = time.time()nowTime = time.time()while nowTime - startTime < timeout:# 通过 xpath 查找控件try:if xpath is not None:el = self.driver.find_element_by_xpath(xpath)return elexcept:pass# 通过 id 查找控件try:if id is not None:if index is not None:return self.driver.find_elements_by_id(id)[index]else:return self.driver.find_element_by_id(id)except:passsleep(1)nowTime = time.time()raise Exception("Element xpath[%s] id[%s] index[%s] not found" % (xpath, id, index))if __name__ == '__main__':try: unittest.main()except SystemExit: pass
准备好脚本后,就可以到 MQC 平台进行提测了:
1.将这个脚本打包成zip包,到 MQC主页 添加待测app, 之后进入用例库页面
2.创建一个新用例,取名为 登录
3.进入功能测试提测页面进行用例提测, 用户自己上传脚本创建用例需选中已上传用例,使用在线录制服务创建的用例需选择已录制用例
4.将上面的 DEMO 脚本提测后,24小时内便可查看测试报告。
怎么使用在线录制?
大家写功能测试脚本的时候一定有想过录制回放这样的功能,就是通过工具把操作录制下来,而后再通过引擎回放录制的动作。在线录制结合了云真机机型多的优势,提供了这么一项在线服务。在线录制可以大大加速用例的生成,但是,一个好的用例是需要不断地验证打磨的,除了基本的点击、滑动操作外,若您有具体的功能验证需求,如图片上传、随机密码键盘等等,都是需要有经验的工程师来修改完善脚本的, 在线录制仅仅是用例脚本设计中的第一步。当然,若您有复杂的用例设计需求,也可以联系我们,通过在阿里云购买人工支持用例设计,让阿里云的测试专家为您的 app 量身定制用例。
在使用在线录制的时候,可以看到下图所示界面
1.在点击的时候若出现控件树不准确的情况,需要手动点击刷新(框1)来重新解析控件树;
2.框2中的内容是控件的坐标、resource-id[index]、text信息;
3.有些 app 有左滑的起始页,这里封装了一些滑动操作,可以有效避免录制的左滑动作过快或过短导致回放失败的问题;对于一些输入操作,录制时直接使用键盘输入可能没有准确识别出该步所有输入文本,可以使用 输入 按钮来完成输入的操作;
4.框4和框5是直接使用在线录制回放脚本,可以快速验证录制脚本的准确性,框4能够直接支持单步回放,框5可以构建appium脚本再使用appium引擎进行回放。
更多功能
MQC 提供了完善的测试流程管理功能,覆盖测试的整个生命周期,除了在线录制、真机回放、测试任务管理等,还有用例库管理、App版本管理、App缺陷统计等等功能,欢迎大家来使用体验,这里重点介绍用例库的参数管理。
大家在写功能测试脚本的时候可能都用过excel来管理一些常量,并在测试的时候传递给测试用例,这些通常会是脚本里的参数。在使用云端真机进行测试的时候,可以通过参数管理功能来完成参数的分发、互踢等工作,直接在脚本中获取参数,同时在线维护参数值。
如下图创建两组参数 username、password、point,在提测时选上使用的参数,平台会自动将参数分发到各个功能测试任务并执行
同样,使用 desired_capabilities 类可以获取到相应的参数:
import desired_capabilitiesusername = desired_capabilities.getParam("username")password = desired_capabilities.getParam("password")point = desired_capabilities.getParam("point")
到这 appium 功能测试的一些基本概念与服务已经介绍完全了,后续 MQC 会继续和大家分享功能测试的一些专业知识,希望大家持续关注。
这篇关于MQC功能测试大揭秘(4)- MQC 功能测试 DEMO的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!