MQC功能测试大揭秘(4)- MQC 功能测试 DEMO

MQC为大家提供了海量的适配真机、强大的在线录制、遍历的用例管理、定制化的报告展示等功能,这篇文章将会通过一个 DEMO 教会大家如何利用好 MQC 提供的这些服务来回归测试自己的 App。

如何使用 MQC 功能测试服务?

Appium 基础篇有提到,desired capabilities 会提供 appium 运行时的各项环境参数,MQC 在功能测试开始前会动态生成desired capabilities类,用户脚本只需要调用相关 api 即可快速启动 Appium。

import desired_capabilities

def 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 sys

from 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 TouchActions

class MqcAppium(TestCase):
    #设备宽高
    global width
    global height

    #unittest 启动
    def setUp(self):
        desired_caps = self.get_desired_capabilities()
        uri = "http://localhost:4723/wd/hub"
        retry = 0
        while retry < 2:
            try:
                self.driver = webdriver.Remote(uri, desired_caps)
                break
            except Exception, e:
                retry += 1
                if retry == 2:
                    raise e
        sleep(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 函数不同的是,为了兼容不同分辨率的手机,滑动操作应当使用 比例 而非 绝对坐标,当然,若是需要精确地滑动操作,建议使用scrollTo
        self.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:
            pass

    def swipe(self, points):
        last_x = 0
        last_y = 0
        swipe_action = TouchAction(self.driver)
        for i in range(0, len(points)):
            x=float(points[i][0]) * self.width
            y=float(points[i][1]) * self.height
            if 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 = x
            last_y = y

    def 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 el
            except:
                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:
                pass

            sleep(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, 之后进入用例库页面

MQC功能测试大揭秘(4)- MQC 功能测试 DEMO

2.创建一个新用例,取名为 登录

MQC功能测试大揭秘(4)- MQC 功能测试 DEMO

3.进入功能测试提测页面进行用例提测, 用户自己上传脚本创建用例需选中已上传用例,使用在线录制服务创建的用例需选择已录制用例

MQC功能测试大揭秘(4)- MQC 功能测试 DEMO

4.将上面的 DEMO 脚本提测后,24小时内便可查看测试报告。

怎么使用在线录制?

大家写功能测试脚本的时候一定有想过录制回放这样的功能,就是通过工具把操作录制下来,而后再通过引擎回放录制的动作。在线录制结合了云真机机型多的优势,提供了这么一项在线服务。在线录制可以大大加速用例的生成,但是,一个好的用例是需要不断地验证打磨的,除了基本的点击、滑动操作外,若您有具体的功能验证需求,如图片上传、随机密码键盘等等,都是需要有经验的工程师来修改完善脚本的, 在线录制仅仅是用例脚本设计中的第一步。当然,若您有复杂的用例设计需求,也可以联系我们,通过在阿里云购买人工支持用例设计,让阿里云的测试专家为您的 app 量身定制用例。

在使用在线录制的时候,可以看到下图所示界面

MQC功能测试大揭秘(4)- MQC 功能测试 DEMO

1.在点击的时候若出现控件树不准确的情况,需要手动点击刷新(框1)来重新解析控件树;
2.框2中的内容是控件的坐标、resource-id[index]、text信息;
3.有些 app 有左滑的起始页,这里封装了一些滑动操作,可以有效避免录制的左滑动作过快或过短导致回放失败的问题;对于一些输入操作,录制时直接使用键盘输入可能没有准确识别出该步所有输入文本,可以使用 输入 按钮来完成输入的操作;
4.框4和框5是直接使用在线录制回放脚本,可以快速验证录制脚本的准确性,框4能够直接支持单步回放,框5可以构建appium脚本再使用appium引擎进行回放。

更多功能

MQC 提供了完善的测试流程管理功能,覆盖测试的整个生命周期,除了在线录制、真机回放、测试任务管理等,还有用例库管理、App版本管理、App缺陷统计等等功能,欢迎大家来使用体验,这里重点介绍用例库的参数管理。

大家在写功能测试脚本的时候可能都用过excel来管理一些常量,并在测试的时候传递给测试用例,这些通常会是脚本里的参数。在使用云端真机进行测试的时候,可以通过参数管理功能来完成参数的分发、互踢等工作,直接在脚本中获取参数,同时在线维护参数值。

如下图创建两组参数 username、password、point,在提测时选上使用的参数,平台会自动将参数分发到各个功能测试任务并执行

MQC功能测试大揭秘(4)- MQC 功能测试 DEMO

同样,使用 desired_capabilities 类可以获取到相应的参数:

import desired_capabilities

    username = desired_capabilities.getParam("username")
    password = desired_capabilities.getParam("password")
    point = desired_capabilities.getParam("point")

到这 appium 功能测试的一些基本概念与服务已经介绍完全了,后续 MQC 会继续和大家分享功能测试的一些专业知识,希望大家持续关注。

上一篇:如何让App首屏启动更快 -- httpdns持久化缓存方案


下一篇:2017杭州云栖大会—移动云专场【赠票】