• 微信小程序自动化测试之路


    前言

    在每次发布新版本之前、都需要回归核心功能、已确保上线后小程序也能按照预期运行. 目前这部分回归工作是由测试同事手工去验证测试用例、按照每周一版本的迭代节奏、回归就花了测试挺多时间的. 最近前端工作比较轻松、故在思考能否把这部分重复的工作交给程序自动来进行呢、省时省力。

    何谓小程序自动化

    小程序自动化SDK为开发者提供了一套通过外部脚本操控小程序的方案,从而实现小程序自动化测试的目的。

    大白话翻译就是: 让开发者工具能按照代码的执行顺序自动在页面上完成点击、输入等操作(即模拟用户操作), 再将操作后的页面表现与预期想要的结果做对比得到测试结论(断言).

    官网链接:

    https://developers.weixin.qq.com/miniprogram/dev/devtools/auto/

    小程序自动化测试SDK:

    https://www.npmjs.com/package/miniprogram-automator

    小程序自动化测试SDK具备的特性:

    A. 控制小程序跳转到指定页面;

    B. 获取小程序页面数据;

    C. 获取小程序页面元素状态;

    D. 触发小程序元素绑定事件;

    E. 往AppService注入代码片段;

    F. 调用wx对象上任意接口;

    G. …

    1. 小程序自动化SDK 3.1 运行环境

    A. 安装Node.js并且版本大于8.0;

    B. 基础库版本为2.7.3及以上;

    C. 开发者工具版本为1.02.1907232及以上;

    D. 要做自动化测试的项目(后面会介绍哦); 如何查看&修改基础库版本、请见下图.
    在这里插入图片描述
    如何查看开发者工具版本、请见下图
    在这里插入图片描述
    需要做自动化测试的项目(3选1):

    A. 借助微信开发者工具新建个项目;

    B. 开发者可直接从github下载小程序官方组件源码下来(小程序官方组件源码git地址: github.com/wechat-mini…);

    C. 真实的项目;

    在本篇文章中、为尽可能直白讲清楚实践步骤、采取方案A新建个项目(下文所有的演示都是基于该项目).

    先来看看大概的一个目录结构如下:
    在这里插入图片描述
    若具备以上运行环境了、请继续往下看.

    3.2 安装自动化测试SDK

    Tips: cd 进入到项目根目录下, 终端执行如下命令。

    npm i miniprogram-automator --save-dev
    
    • 1

    带–save-dev跟不带的区别, 详细见下文: https://juejin.cn/post/6844903975590821902

    该命令执行成功后、在终端会输出如下内容、说明安装成功.
    在这里插入图片描述
    终端也有些warn告警、暂不影响使用、故先不处理。

    3.3 初体验

    A. 开启工具安全设置中的CLI/HTTP调用功能。具体操作指南如下: 打开微信开发者工具->设置-> 安全设置 -> 启用服务端口.
    在这里插入图片描述
    有关于CLI/HTTP功能的详细介绍、请戳此链接:

    https://developers.weixin.qq.com/miniprogram/dev/devtools/http.html

    B. 先准备个需要做自动化测试的页面(为方便、下面会以最简单的demo来演示)

    // 想要测试的页面index
    // index.wxml
    <view class="usermotto">
      <text class="user-motto" bind:tap="tapFn">{{motto}}</text>
    </view>
    
    // index.js
    // 获取应用实例
    const app = getApp()
    
    Page({
      data: {
        motto: 'Hello World',
      },
      tapFn (e) {
        console.log(e,'测试自动化结果')
      }
    })
    
    // index.wxss
    .usermotto {
      margin-top: 200px;
      text-align: center;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    C. 在项目中新建文件、以.spec.js结尾(本文以在项目根目录下新建index.spce.js为例子), 输入类似如下内容(在实际过程中根据自己的项目修改即可)

    const automator = require('miniprogram-automator')
    
    automator.launch({
      cliPath: '/Applications/wechatwebdevtools.app/Contents/MacOS/cli', // 工具 cli 位置,如果你没有更改过默认安装位置,可以忽略此项
      projectPath: '/Users/susan.li/files/mini-demo', // 项目文件地址
    }).then(async miniProgram => {
      const page = await miniProgram.reLaunch('/pages/index/index')
      await page.waitFor(500)
      const element = await page.$('.user-motto')
      console.log(await element.attribute('class'))
      await element.tap()
    
      await miniProgram.close()
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    这里有3个点需要注意:

    1、修改cli工具的路径(若您没更改过微信开发者工具的默认安装路径、可忽略此项、若改过安装路径的、就需要自行寻找安装路径是什么然后补充到这); 若不清楚如何查看软件安装位置的, 请戳此链接: https://juejin.cn/post/6970608743041990664/

    2、修改项目的文件路径(这里推荐绝对路径);

    3、修改下面demo中实际想要操作的元素;

    D.在终端输入如下命令、就在执行自动化测试结果了。

    node index.spec.js
    
    • 1

    我们来看看命令执行的全过程. 这里需要留意一点, 在自动化测试启动微信开发者工具时、留意右侧是否出现下图内容[启动自动化端口].
    在这里插入图片描述
    紧接着我们看看开发者工具是否有打印出相关内容
    在这里插入图片描述
    最后我们再看看终端, 你会发现终端会输出如下内容, 跟你代码的预期是符合的.
    在这里插入图片描述
    本演示demo想实现的是: 通过自动化测试SDK模拟用户点击Hello World文本(tap操作)、看能否正常执行bindtap里面的方法.
    在这里插入图片描述
    Question: 若在执行node index.spec.js中遇到如下报错, 是什么原因讷?

    node:2903) UnhandledPromiseRejectionWarning: TypeError: Cannot read property 'attribute' of null
        at automator.launch.then (/xxx/index.spec.js:38:29)
        at process._tickCallback (internal/process/next_tick.js:68:7)
    (node:2903) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 2)
    
    (node:2903) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    至此、小程序自动化测试算是开了个头, 请接着往下看.

    B. 执行如下命令全局安装Jest框架

    npm i jest -g
    
    • 1

    在安装过程中、遇到了如下报错:
    在这里插入图片描述
    根据报错提示、应该是权限不够, 故执行如下命令(实际过程开发者可根据自身报错去处理)

    // 看看命令行、应该会提示你要输入密码。
    sudo npm i jest -g
    
    • 1
    • 2

    在这里插入图片描述
    C. 开启工具安全设置中的CLI/HTTP调用功能(同2.4打开步骤)

    至此, Jest测试框架已搭建完成, 可进入到下一步.

    4.2 Jest初体验

    A. 编写脚本(目标: 自动启动微信开发者工具&&打开该项目)

    const automator = require('miniprogram-automator')
    describe('index', () => {
      let miniProgram
      let page
    
      beforeAll(async () => {
        miniProgram = await automator.launch({
          projectPath: '/Users/susan.li/files/shop-mini',
          cliPath: '/Applications/wechatwebdevtools.app/Contents/MacOS/cli'
        })
        page = await miniProgram.reLaunch('/pages/index/index')
        await page.waitFor(5000)
      }, 30000)
    
      afterAll(async () => {
        await miniProgram.close()
      })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    B. 开启工具安全设置中的CLI/HTTP调用功能(同2.4打开步骤)

    C. 关闭后、重新启动小程序到首页

    D. 关闭工具安全设置中的CLI/HTTP调用功能(同2.4打开步骤)并关闭微信开发者工具

    E. 在项目根目录下, 执行如下脚本

    jest index.spec.js
    
    • 1

    哎呀妈呀, 报错了, look look.
    在这里插入图片描述
    解决方案: 在项目目录下执行如下命令.

    npm init
    
    • 1

    安装完成后、项目根目录下就多了package.json文件了.
    在这里插入图片描述
    那我们再次执行E步骤:哎呀妈呀, 再次报错了, look look.
    在这里插入图片描述
    报错解析: 脚本里面至少要包含一个测试, 即类似it(‘xxx’, () => expect(‘xxx’).toBe(‘xxx’))的代码, 详细用法可以搜索下jest测试框架的教程. 解决方案: 加上至少一个测试用例(下面例子演示的是模拟文本的tap事件)。

    最终的脚本代码如下:

    const automator = require('miniprogram-automator')
    describe('index', () => {
      let miniProgram
      let page
    
      beforeAll(async () => {
        miniProgram = await automator.launch({
          projectPath: '/Users/susan.li/files/mini-demo',
          cliPath: '/Applications/wechatwebdevtools.app/Contents/MacOS/cli'
        })
        page = await miniProgram.reLaunch('/pages/index/index')
        await page.waitFor(5000)
      }, 30000)
    
      it('点击hello world文本', async () => {
          await page.waitFor(3000)
          // 通过.user-motto选择目标元素
          const tabbar = await page.$('.user-motto')
          tabbar.tap()
      })
      // afterAll(async () => {
      //   await miniProgram.close()
      // })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    那我们再次执行E步骤: 我们会发现、在开发者工具下有执行tap方法.
    在这里插入图片描述
    脚本执行完毕后、终端会输出如下内容、告诉执行结果:
    在这里插入图片描述

    4.3 进阶玩法

    上述做法需要在代码内注入微信开发者工具的安装路径&&项目路径, 不同项目成员内的配置是不同、那我们思考下能否做成隔离的? 即项目本身只维护测试用例脚本、至于在哪里执行脚本、执行的项目目录是什么、由开发者自行决定.

    通过命令打开开发版微信开发者工具的自动化接口并连接自动化接口。

    // 进入微信开发者工具的安装目录(笔者的目录结构是: /Applications/wechatwebdevtools.app) -> /微信开发者工具安装目录/Contents/MacOS
    cd /Applications/wechatwebdevtools.app/Contents/MacOS
    // 找到要执行自动化测试的目录(笔者项目路径是:/Users/susan.li/files/mini-demo)
    cli --auto /Users/susan.li/files/mini-demo --auto-port 9420
    
    • 1
    • 2
    • 3
    • 4

    Tips: 自动化端口是独立于服务端口的(你在开发者工具->设置->安全->打印出来的52968其实是服务器端口); 我们需要在终端看到如下提示才意味着成功打开了自动化端口(9420)

    // 要看到这句话、这句话很关键!!!!!!
    ✔ Open project with automation enabled success /Users/susan.li/files/mini-demo
    
    • 1
    • 2

    我们看看实际效果图:
    在这里插入图片描述
    命令运行成功后、会自动打开开发者工具&项目、并在右上角有如下提示.
    在这里插入图片描述
    B. 找到自动化测试的项目根目录下, 执行如下命令安装SDK(若已安装、可忽略) // 若需要安装、安装命令如下:

    // 若需要安装、安装命令如下:
    npm i miniprogram-automator --save-dev
    
    • 1
    • 2

    C. 引入自动化测试SDK, 在脚本中连接自动化操作端口

    const automator = require('miniprogram-automator');
    
    const miniProgram = automator.connect({
      wsEndpoint: 'ws://localhost:9420',
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5

    D. 根据业务需要编写对应的脚本并进行相关操作

    const automator = require('miniprogram-automator')
    
    describe('index', () => {
      let miniProgram
      // 运行测试前调用、启用自动化端口9420
      beforeAll(async () => {
        miniProgram = await automator.connect({
          wsEndpoint: 'ws://localhost:9420',
        })
      })
      // 运行测试后调用
      afterAll(() => {
        miniProgram.disconnect();
      })
      // 自动化测试内容
      it('点击hello world文本', async () => {
        // 获取页面相关信息
        const page = await miniProgram.reLaunch('/pages/index/index')
        // 通过.user-motto选择目标元素
        const tabbar = await page.$('.user-motto')
        // 模拟tap事件
        tabbar.tap()
      })
    })
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    E. 脚本准备完毕、执行如下命令做自动化测试(保持微笑开发者工具是打开的状态)

    jest index.spec.js
    
    • 1

    若测试通过、在终端会有如下PASS提示,结果如图所示:
    在这里插入图片描述

    5.写在最后

    作为电商类小程序, 保障线上业务的稳定运行、要求各页面各模块在异常情况下进行适当的兜底处理、确保给到用户最基础的用户体验。

    学习安排上

    如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助。

    在这里插入图片描述

    视频文档获取方式:

    这份文档和视频资料,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享,点下方小卡片进群即可自行领取

  • 相关阅读:
    “腾易视连”构建汽车生态新格局 星选计划赋能创作者价值提升
    C++环形缓冲区
    AQS理解
    这也许是22年国内最牛的Java面试八股文合集(全彩版),不接受反驳
    纯CSS如何禁止用户复制网页的内容?
    Mysql事务日志
    42. 【Android教程】活动:Activity
    Linux驱动开发——(五)内核中断
    docker新手村教程
    VSCode很好,但我以后不会再用了
  • 原文地址:https://blog.csdn.net/xfw17397388089/article/details/128137340