ARTICLE DETAIL

资讯详情

深耕编程入门与网站建设的一线实战洞察。

微信小程序自动化测试入门:miniprogram-automator从零到工程化实践

微信小程序自动化测试入门:miniprogram-automator从零到工程化实践 1. 项目概述从手动到自动的跨越作为一名长期与小程序打交道的开发者我深知在项目迭代和回归测试中手动点点点的痛苦。每次发布新版本光是核心流程的走查就要耗费大半天更别提那些需要反复验证的边界条件了。直到最近我决定彻底改变这种低效的工作模式将目光投向了官方提供的自动化测试工具——miniprogram-automator。这个工具本质上是一个Node.js库它允许我们通过脚本代码像真实用户一样去操作小程序模拟点击、滑动、输入等行为并获取页面状态和数据。这不仅仅是“偷懒”更是提升开发质量、保障项目稳定性的必要手段。如果你也受够了重复的手工测试或者想为你的小程序项目引入自动化回归能力那么我这次从零开始的探索过程或许能给你提供一份详实的参考地图。2. 工具选型与环境搭建的底层逻辑在开始动手之前花点时间理解工具生态和搭建一个稳定的环境远比直接敲命令更重要。市面上并非没有其他小程序自动化方案比如一些基于图像识别的测试框架。但miniprogram-automator的核心优势在于其“原生”属性。它由微信官方团队开发通过WebSocket协议与开发者工具直接通信这意味着它的操作指令能最精准地映射到小程序的运行时环境稳定性和可靠性更高。它不依赖UI截图而是直接操作小程序底层的组件树执行速度更快且不受界面样式变化的影响只要组件结构稳定。2.1 环境依赖的精确匹配自动化脚本运行在Node.js环境中因此第一步是确保Node.js版本合适。经过实测miniprogram-automator对Node.js版本有一定要求太老的版本如Node.js 10可能无法兼容其依赖的某些新特性。我推荐使用Node.js 14 LTS或16 LTS版本这是目前生态兼容性最好的长期支持版。你可以通过终端命令node -v来检查。接下来是安装工具包本身。这里有一个关键选择是全局安装还是项目内安装我强烈建议采用后者。在项目根目录下执行npm install miniprogram-automator --save-dev将其作为开发依赖安装。这样做的好处是隔离了环境不同项目可以使用不同版本的automator避免了全局污染。安装完成后你还需要确保电脑上安装了最新稳定版的微信开发者工具并且已经登录了开发者账号。因为automator需要启动一个无界面的开发者工具实例我们称之为“CLI”来加载小程序项目。2.2 项目配置的“暗坑”排查环境就绪后需要对你待测试的小程序项目进行简单配置。核心是确保开发者工具的设置正确。打开微信开发者工具进入“设置 - 安全设置”你需要开启服务端口。这个端口是automator连接开发者工具的桥梁。你可以选择一个固定的端口号比如9527并记下它。注意很多新手在这里会忽略一个细节如果你的电脑有多个微信开发者工具账号例如公司账号和个人账号务必确保你启动CLI和后续连接时使用的是同一个登录态的端口。否则会出现连接失败。一个稳妥的做法是在脚本中启动CLI时明确指定开发者工具的安装路径和端口号。3. 核心流程拆解连接、启动与基础操作理解了原理和配好了环境我们就可以开始编写第一个自动化脚本了。整个过程可以清晰地分为三个步骤启动开发者工具CLI、连接小程序、执行自动化操作。3.1 启动CLI与建立连接我们首先创建一个名为test.js的脚本文件。第一步是启动无界面的开发者工具。miniprogram-automator提供了launch方法来完成这个任务。这里有几个关键参数需要配置const automator require(miniprogram-automator); async function runTest() { // 步骤1: 启动CLI const miniProgram await automator.launch({ projectPath: /absolute/path/to/your/project, // 小程序项目的绝对路径至关重要 cliPath: /Applications/wechatwebdevtools.app/Contents/MacOS/cli, // 开发者工具CLI的绝对路径 // Windows示例: cliPath: C:\\Program Files (x86)\\Tencent\\微信web开发者工具\\cli.bat }); // 步骤2: 连接小程序 const miniProgram await automator.connect({ wsEndpoint: ws://127.0.0.1:9527, // WebSocket地址端口需与开发者工具设置一致 }); } runTest();关键点解析projectPath必须使用绝对路径。使用相对路径是导致“找不到项目”错误的最常见原因。在Node.js脚本中可以使用path.resolve(__dirname, ‘../project’)来动态构造绝对路径。cliPath这个路径因操作系统和安装方式而异。在Mac上它通常隐藏在.app包内在Windows上它是一个独立的cli.bat文件。找不到它CLI就无法启动。wsEndpoint端口号9527需要替换为你自己在开发者工具中设置并开启的端口。连接前请确保开发者工具已经打开或通过CLI启动并且该端口可用。3.2 页面导航与元素定位连接成功后我们就获得了操作小程序的入口miniProgram对象。最常用的操作是跳转页面和获取页面对象。// 跳转到指定页面 await miniProgram.navigateTo(/pages/index/index); // 获取当前页面对象 const page await miniProgram.currentPage(); // 等待页面元素渲染完成非常重要 await page.waitFor(500); // 简单等待500毫秒非最优方案 // 更优方案等待特定选择器出现 await page.waitForSelector(.submit-btn);获取页面对象后就可以定位页面上的元素了。miniprogram-automator支持多种选择器类似于CSS选择器但它是基于小程序自定义组件的结构。.class选择器最常用如.user-name。#id选择器如#login-btn。自定义组件选择器如tagName。组合选择器如view.container .item。定位到元素后就可以模拟用户交互了// 定位一个按钮并点击 const btn await page.$(.primary-button); await btn.tap(); // 定位输入框并输入文本 const input await page.$(.search-input); await input.input(自动化测试); await page.waitFor(300); // 输入后稍作等待模拟用户停顿 // 获取元素的属性、文本或样式 const text await btn.text(); const color await btn.style(color); const isDisabled await btn.attribute(disabled);4. 复杂交互与状态捕获的实战技巧基础的点击和输入只是开始真实的用户场景要复杂得多。例如滑动列表、长按操作、处理弹窗、获取网络请求数据等。4.1 处理滑动与长按对于滚动列表我们需要模拟滑动swipe操作。miniprogram-automator的page对象提供了swipe方法。// 向下滑动屏幕模拟下拉刷新 await page.swipe(down, 100); // 方向 滑动距离(px) // 更精确的滑动在某个元素区域内滑动 const scrollView await page.$(.scroll-view); await scrollView.swipe(up, 200); // 模拟长按操作 const deleteBtn await page.$(.delete-item); await deleteBtn.tap({ duration: 2000 }); // 长按2秒4.2 应对弹窗与模态框小程序中常见的showModal,showToast等API产生的弹窗在自动化脚本中需要特殊处理因为它们不在页面DOM树内。我们可以通过监听页面事件来捕获。// 监听 modal 确认事件 page.on(modalConfirm, async () { console.log(用户点击了模态框的确认); // 可以在这里执行确认后的操作比如继续下一步测试 }); // 触发一个会弹出模态框的操作 await page.$(.show-modal-btn).tap(); // 如果需要点击取消则监听 ‘modalCancel’更通用的方法是在操作可能触发弹窗的按钮后使用page.waitFor等待一段时间让弹窗完全显示然后再通过选择器去查找弹窗上的按钮。但注意弹窗的根节点可能在页面层级之外选择器可能需要调整。4.3 捕获网络请求与Console日志这对于测试接口是否正确调用、参数是否正常传递至关重要。miniprogram-automator允许我们监听小程序的网络请求和Console输出。// 监听网络请求 miniProgram.on(request, request { console.log(请求URL:, request.url); console.log(请求方法:, request.method); console.log(请求数据:, request.data); // 可以在这里做断言检查请求是否符合预期 }); // 监听Console输出 miniProgram.on(console, msg { console.log(小程序Console:, msg.type, msg.text); // 可以捕获到小程序中 console.log, console.error 的输出 });这个功能非常强大你可以验证一个“提交订单”操作是否发出了正确的POST请求或者当页面出错时是否能捕获到console.error信息从而快速定位问题。5. 构建健壮测试脚本的工程化实践写几个零散的操作命令不难但要构建一套可维护、可复用的自动化测试套件就需要一些工程化思维。5.1 使用Async/Await处理异步小程序自动化中的所有操作几乎都是异步的。使用async/await语法可以让代码逻辑像同步一样清晰避免“回调地狱”。async function testLoginFlow(miniProgram) { try { await miniProgram.navigateTo(/pages/login/login); const page await miniProgram.currentPage(); await (await page.$(#username)).input(testuser); await (await page.$(#password)).input(123456); await (await page.$(.login-btn)).tap(); // 等待跳转或成功提示 await page.waitForSelector(.login-success-toast, { timeout: 5000 }); console.log(登录流程测试通过); } catch (error) { console.error(登录流程测试失败:, error.message); // 这里可以截图方便排查 await page.screenshot({ path: login-error.png }); } }5.2 引入断言库与测试框架单纯的脚本执行无法判断测试是否“通过”。我们需要引入断言库如Node.js内置的assert或更强大的chai来验证结果。const assert require(assert).strict; async function testCartCount(page) { await page.navigateTo(/pages/cart/cart); const countElement await page.$(.cart-count); const countText await countElement.text(); // 断言购物车数量显示为数字 assert(!isNaN(parseInt(countText)), 购物车数量应为数字); // 断言添加商品后数量增加 const initialCount parseInt(countText); await addProductToCart(page); await page.waitFor(1000); // 等待界面更新 const newCountElement await page.$(.cart-count); const newCount parseInt(await newCountElement.text()); assert.strictEqual(newCount, initialCount 1, 添加商品后购物车数量应增加1); }更进一步可以集成像Jest或Mocha这样的测试框架。它们能提供测试套件组织、生命周期钩子beforeAll, afterEach、测试报告等强大功能。将每个测试用例写成it(‘should …’, async () {…})的形式管理起来会非常清晰。5.3 关键操作封装与页面对象模型Page Object这是提升脚本可维护性的核心设计模式。将针对某个页面的所有操作和元素选择器封装在一个类或对象中。// pages/HomePage.js class HomePage { constructor(page) { this.page page; } async navigateTo() { await this.page.navigateTo(/pages/index/index); return this; } async getSearchInput() { return await this.page.$(.search-input); } async search(keyword) { const input await this.getSearchInput(); await input.input(keyword); await (await this.page.$(.search-btn)).tap(); await this.page.waitForSelector(.search-result, { timeout: 3000 }); } async getFirstProductName() { const firstProduct await this.page.$(.product-item:first-child .name); return await firstProduct.text(); } } // 在测试用例中使用 const homePage new HomePage(currentPage); await homePage.navigateTo(); await homePage.search(手机); const name await homePage.getFirstProductName(); assert(name.includes(手机));这样做的好处是当页面UI改版只需要修改HomePage.js文件中的选择器所有测试用例都无需改动实现了业务逻辑与UI细节的解耦。6. 常见问题排查与性能优化实录在实际操作中我踩过不少坑。这里把一些典型问题和解决方案整理出来希望能帮你节省时间。6.1 连接与启动失败问题排查表问题现象可能原因解决方案launch超时或报错1.cliPath路径错误。2. 开发者工具未登录或有多开冲突。3. 端口被占用。1. 仔细检查cliPathWindows注意.bat后缀。2. 关闭所有开发者工具重新用CLI启动确保登录态一致。3. 更换开发者工具中的服务端口号。connect失败提示超时或无法连接1.wsEndpoint端口号与开发者工具设置不符。2. 开发者工具未开启服务端口。3. 防火墙或安全软件拦截。1. 核对端口号确保一致。2. 进入开发者工具设置确认“服务端口”已开启。3. 临时关闭防火墙或添加规则。脚本执行过程中元素找不到 ($或waitForSelector报错)1. 页面未加载完成就进行操作。2. 选择器写错了。3. 元素是动态生成的等待时间不足。4. 页面有if/else或hidden控制显示。1. 在关键操作前增加page.waitFor(毫秒数)或waitForSelector。2. 使用开发者工具的“选择器”功能验证选择器。3. 使用waitForSelector并设置合理的超时时间。4. 确保操作时元素确实处于显示状态。6.2 脚本稳定性与性能优化心得增加智能等待避免“硬等待”到处使用page.waitFor(3000)虽然简单但会让测试变慢且不稳定。优先使用waitForSelector、waitForFunction等待某个JS条件成立等它们会在条件满足时立即继续否则才等到超时。// 不佳 await page.waitFor(3000); await page.$(.btn).tap(); // 更佳 await page.waitForSelector(.btn, { timeout: 5000 }); await (await page.$(.btn)).tap();善用截图功能定位疑难杂症当脚本在某个步骤失败时立即对当前页面截图能直观看到失败时的界面状态比看日志有效得多。try { await someOperation(); } catch (error) { const timestamp new Date().getTime(); await page.screenshot({ path: error-${timestamp}.png }); throw error; // 重新抛出错误 }管理好小程序生命周期每次测试用例开始前最好能回到一个干净的初始状态。对于小程序可以调用miniProgram.reLaunch(‘/pages/index/index’)重启到首页。在测试套件的beforeEach钩子中做这件事。控制测试规模与并行不要在一个脚本里测试所有功能。按功能模块拆分成多个独立的测试文件。可以考虑使用Jest的--maxWorkers参数进行有限度的并行测试但要注意小程序CLI实例的资源占用。第一次尝试miniprogram-automator的过程就像是为我的开发工作流打开了一扇新的大门。从最初连接失败的烦躁到成功写出第一个自动登录脚本的兴奋再到设计出Page Object模型后的从容这个过程让我深刻体会到自动化测试的价值不在于替代所有手工测试而在于把开发者从重复、机械的验证中解放出来去关注更复杂的逻辑和用户体验。它更像是一个永不疲倦的、严格执行的质检员。如果你也在进行小程序开发我强烈建议你抽出半天时间跟着上面的步骤实践一次。最初的搭建成本会在后续无数次的回归测试中加倍回报给你。
返回列表