点击关注“有赞coder”
获取更多技术干货哦~
作者:TianTian
部门:业务技术/测试
精选小程序发生了一次线上问题,测试阶段的小程序开发码测试ok,但是小程序正式码由于打包问题,"我的订单"页面文件打包失败,导致线上用户访问我的页面白屏。
当前并不能避免该打包问题,为了规避异常版本发布至线上,需要在预发、体验码发布、正式码发布等各阶段进行主流程回归。手动回归测试非常耗时,在发布前的各阶段,测试人员须重复执行大量测试用例,以确保本次上线功能OK且对其他功能无影响。
一遍又一遍执行相同的测试用例,不仅要花费更多的时间,而且还会降低整体测试效率,因此引入微信小程序自动化以解放重复人力。
优点:
缺点:
优点:
缺点:
精选小程序主要是原生页面,minium和Jest均能满足需求。minium支持Python 和 JavaScript 版本,而且有专门的团队定期维护,遇到问题可以在微信开发者社区进行提问,因此选择了minium。
minium提供一个基于unittest封装好的测试框架,利用这个简单的框架对小程序测试可以起到事半功倍的效果。
测试基类Minitest会根据测试配置进行测试,minitest向上继承了unittest.TestCase,并做了以下改动:
使用MiniTest可以大大降低小程序测试成本。
Properties:
名称 | 类型 | 默认值 | 说明 |
---|---|---|---|
app | minium.App | None | App实例,可直接调用minium.App中的方法 |
mini | minium.Minium | None | Minium实例,可直接调用minium.Minium中的方法 |
native | minium.Native | None | Native实例,可直接调用minium.Native中的方法 |
代码示例:
#!/usr/bin/env python3
import minium
class FirstTest(minium.MiniTest):
def test_get_system_info(self):
sys_info = self.mini.get_system_info()
self.assertIn("SDKVersion", sys_info)
安装命令:pip3 install minium-latest.zip 或者python3 setup.py install
minitest -v
"path/to/cli" auto --project "path/to/project" --auto-port 9420
默认的命令行工具所在位置:
macOS: <安装路径>/Contents/MacOS/cli
Windows: <安装路径>/cli.bat
思路:使用Page Object 架构,使系统架构分层,每一个页面设计为一个Class,包含了页面需要测试的元素,测试用例只要关心测试的数据即可;
BasePage是页面基类,封装所有页面会用到的公用方法
class BasePage:
def __init__(self, mini):
self.mini = mini
def navigate_to_open(self, route):
"""以导航的方式跳转到指定页面,不允许跳转到 tabbar 页面,支持相对路径和绝对路径, 小程序中页面栈最多十层"""
self.mini.app.navigate_to(route)
def redirect_to_open(self, route):
"""关闭当前页面,重定向到应用内的某个页面,不允许跳转到 tabbar 页面"""
self.mini.app.redirect_to(route)
def switch_tab_open(self, route):
"""跳转到 tabBar 页面,会关闭其他所有非 tabBar 页面"""
self.mini.app.switch_tab(route)
@property
def current_title(self) -> str:
"""获取当前页面 head title, 具体项目具体分析,以下代码仅用于演示"""
return self.mini.page.get_element("XXXXXX").inner_text
def current_path(self) -> str:
"""获取当前页面route"""
return self.mini.page.path
HomePage是要测试的精选首页页面
from case.base.basepage import BasePage
from case.base import route
class HomePage(BasePage):
"""小程序首页公共方法"""
locators = {
"BASE_ELEMENT": "view",
"BASE_BANNER": "首页banner元素选择器XXX"
}
# 首页点击官方补贴的"更多"按钮
subsidy_more_button = ("跳转页面的元素选择器XXX", "更多")
"""
校验页面路径
"""
def check_homepage_path(self):
self.mini.assertEqual(self.current_path(), route.homepage_route)
"""
校验页面的基本元素
"""
def check_homepage_base_element(self):
# 校验页面是否包含view元素
self.mini.assertTrue(self.mini.page.element_is_exists(HomePage.locators['BASE_ELEMENT']))
# 校验页面banner位置
self.mini.assertTrue(self.mini.page.element_is_exists(HomePage.locators['BASE_BANNER']))
"""
获取官方补贴,点击"更多"按钮跳转
"""
def get_subsidy_element(self):
self.mini.page.get_element(str(self.subsidy_more_button[0]),
inner_text=str(self.subsidy_more_button[1])).click()
BaseCase是测试用例基类,用于设置用例输出路径和清理工作,项目的测试用例都继承此类
from pathlib import Path
import minium
class BaseCase(minium.MiniTest):
"""测试用例基类"""
@classmethod
def setUpClass(cls):
super(BaseCase, cls).setUpClass()
output_dir = Path(cls.CONFIG.outputs)
if not output_dir.is_dir():
output_dir.mkdir()
@classmethod
def tearDownClass(cls):
super(BaseCase, cls).tearDownClass()
cls.app.go_home()
def setUp(self):
super(BaseCase, self).setUp()
def tearDown(self):
super(BaseCase, self).tearDown()
minium 通过 WXSS 选择器来定位元素的,目前小程序仅支持以下的选择器:
参考例子:
<view id="main" class="page-section page-section-gap" style="text-align: center;"></view>
假如要查找像上面这一个元素的话,他的选择器会像是下面这样:
tageName + #id + .className
view#main.page-section.page-section-gap
被测试的有赞精选小程序首页如下图:
HomePageTest
# coding=utf-8
from case.base import loader
from case.base.basecase import BaseCase
from case.pages.homepage import HomePage
"""
小程序首页测试
"""
class HomePageTest(BaseCase):
def __init__(self, methodName='runTest'):
super(HomePageTest, self).__init__(methodName)
self.homePage = HomePage(self)
"""
case1:测试首页的跳转路径是否正确,跳转路径要使用绝对路径,小程序默认进入就是首页,所以不用再切换进入的路径
"""
def test_01_home_page_path(self):
self.homePage.check_homepage_path()
"""
case2:页面的基本元素是否存在
"""
def test_02_page_base_element(self):
self.homePage.check_homepage_base_element()
"""
case3:检查首页的"官方补贴"模块存在
"""
def test_03_live_sale(self):
self.assertTexts(["官方补贴"], "view")
self.assertTexts(["轻松赚回早餐钱"], "view")
"""
case4:从首页点击"更多"跳转到直播特卖页面,页面包含"推荐"模块
"""
def test_04_open_live_sale(self):
# 点击首页的"更多"按钮的元素
self.homePage.get_subsidy_element()
self.page.wait_for(2)
result = self.page.wait_for("页面元素选择器xxx") # 等待页面渲染完成
if result:
category = self.page.data['categoryList']
self.assertEquals("美食", category[0]['title'], "接口返回值包含美食模块")
self.assertEquals("美妆", category[1]['title'], "接口返回值包含美妆模块")
self.page.wait_for(2)
self.app.go_home()
if __name__ == "__main__":
loader.run(module="case.homepage_test", config="../config.json", generate_report=True)
{
"project_path": "XXXXX",
"dev_tool_path": "/Applications/wechatwebdevtools.app/Contents/MacOS/cli",
"debug_mode": "debug",
"test_port": 9420,
"platform": "ide",
"app": "wx",
"assert_capture": false,
"request_timeout":60,
"remote_connect_timeout": 300,
"auto_relaunch": true
}
minium安装时执行的setup.py文件,指定了minitest命令运行的方法入口为:minium.framework.loader:main
loader.py文件解释了运行的命令行的含义
{
"pkg_list": [
{
"case_list": [
"test_*"
],
"pkg": "case.*_test"
}
]
}
suite.json的pkglist字段说明要执行用例的内容和顺序,pkglist 是一个数组,每个数组元素是一个匹配规则,会根据pkg去匹配包名,找到测试类,然后再根据case_list里面的规则去查找测试类的测试用例。可以根据需要编写匹配的粒度。注意匹配规则不是正则表达式,而是通配符。
minitest -m case.homepage_test --case test_07_open_live_sale -c config.json -g #运行执行class文件中的指定用例test_07_open_live_sale
minitest -s suite.json -c config.json -g #按照suite配置去执行用例
生成报告之后,在对应的目录下面有index.html文件,但是我们不能直接用浏览器打开这个 文件,需要把这个目录放到一个静态服务器上
测试结果存储在outputs下,运行命令python3 -m http.server 12345 -d outputs然后在浏览器上访问http://localhost:12345即可查看报告
1.需要开启被测试小程序应用的自动化测试端口9420
开启被测试工程的自动化端口
"path/to/cli" auto --project "path/to/project" --auto-port 9420
2.打开微信开发者工具超时
微信开发者工具:设置-代理设置,关闭ide的代理
3.连接开发者工具后报错
原因:可能是微信开发者工具和minium的版本不一致; 我测试使用ok的匹配版本为: Minium版本:1.0.5 开发者工具版本:1.05.2102010 python版本:3.8.8
4.出现以下报错,可能是登陆的开发者工具的账号,没有被测试小程序的开发者权限;
5.运行过程中,发现调用截图的方法比较耗时,但是在config文件设置了"assert_capture": false,配置没生效,仍然会去调用截图的方法;
ps:猜测是一个bug,然后给微信社区留言了,最新版本1.0.6修复了这个问题 原因:是框架的minitest.py文件调用setup和TearDown方法的时候,没有判断配置文件"assert_capture": false这个条件
可以修改minitest.py文件,增加配置文件的判断条件,修改如下:
if self.test_config.assert_capture:
self.capture("setup")
6.命令行执行的时候加了-p xxx参数,运行时报引入的包不存在
原因:命令行运行时默认是当前路径,加-p xxx, 这样会导致脚本运行的PYTHONPATH变了(不是当前目录了),这样会导致包不存在
解决方法: