How to Automate WeChat Mini‑Program Testing with miniprogram‑automator
This article explains how the JD.com "Jingxi" mini‑program uses the official miniprogram‑automator SDK to build an automated disaster‑recovery testing workflow that launches the devtools, simulates user actions, intercepts network requests, generates screenshots, and validates fallback behavior with manual comparison.
Overview
The mini‑program disaster‑recovery drill requires automated navigation, network fault injection, screenshot capture, and manual verification. The official miniprogram‑automator SDK (npm package https://www.npmjs.com/package/miniprogram-automator ) provides WebDriver‑like control over WeChat mini‑programs.
Key SDK Capabilities
Launch WeChat DevTools CLI and open a project.
Navigate to any page (e.g., reLaunch('/pages/index/index')).
Query and interact with elements ( page.$('.banner'), tap()).
Read element attributes and size.
Mock any wx API, especially wx.request, to return custom responses.
Inject arbitrary JavaScript into the AppService.
Capture full‑page screenshots.
Typical Automation Flow
Launch the development version of WeChat DevTools via the CLI.
Open the target page and perform user actions (click, swipe, pull‑down refresh, scroll).
Intercept network requests and replace responses (e.g., HTTP 500, malformed JSON).
Capture a screenshot for each simulated scenario.
Clear local storage when needed.
Trigger UI recovery actions such as the refresh button.
Restore the original wx.request implementation and end the session.
Test Case Definition
Test data are stored in JSON files to separate configuration from script logic. The structure contains a global section (shared parameters) and case‑specific objects.
{
"global": {
"url": "/pages/index/index",
"pageName": "index",
"pageDesc": "Home",
"device": "iPhone X"
},
"homePageApi": {
"id": 1,
"module": "home_page_api",
"moduleDesc": "Home main API",
"api": "https://example.com/api/home",
"operation": "mock status 500",
"expectRules": [
"1. With cache, show cached data",
"2. Without cache, request disaster API and show fallback",
"3. Both APIs fail, show error and refresh button",
"4. Restore network, click refresh, show normal data"
],
"screenshot": [
{"name": "normal", "desc": "Normal scenario"},
{"name": "500_cache", "desc": "Cache present, main API returns 500"},
{"name": "500_no_cache", "desc": "No cache, main API returns 500"},
{"name": "500_no_cache_500_disaster", "desc": "Both APIs return 500"},
{"name": "500_no_cache_recover", "desc": "Network recovers after 500"}
]
}
}Core Script Snippets
Launch and page navigation
const automator = require('miniprogram-automator');
const miniProgram = await automator.launch({
cliPath: '/Applications/wechatwebdevtools.app/Contents/MacOS/cli',
projectPath: '/absolute/path/to/jx_project'
});
await miniProgram.reLaunch('/pages/index/index');Screenshot capture
await miniProgram.screenshot({ path: 'jx_weapp_index_home_page_500.png' });Mock data generator
const getMockData = (url, type, value) => {
const result = { data: 'test', cookies: [], header: {}, statusCode: 200 };
switch (type) {
case 'data': result.data = getMockResponse(url, value); break;
case 'cookies': result.cookies = value; break;
case 'header': result.header = value; break;
case 'statusCode': result.statusCode = value; break;
}
return { rule: url, result };
};
const mockData = [
getMockData('https://example.com/api/home', 'statusCode', 500),
getMockData('https://example.com/api/disaster', 'data', { /* abnormal payload */ })
];Intercept wx.request
const interceptAPI = async (miniProgram, mockData) => {
await miniProgram.mockWxMethod('request', (obj, data) => {
for (const item of data) {
if (obj.url.includes(item.rule)) return item.result;
}
return new Promise(resolve => {
obj.success = res => resolve(res);
obj.fail = err => resolve(err);
this.origin(obj);
});
}, mockData);
};
await interceptAPI(miniProgram, mockData);Clear storage
await miniProgram.callWxMethod('clearStorage');Trigger UI refresh button
const page = await miniProgram.currentPage();
const $refreshBtn = await page.$('.page-error__refresh-btn');
await $refreshBtn.tap();Restore original request method
await miniProgram.restoreWxMethod('request');Running the Tests
Add a script entry to package.json:
{
"scripts": {
"start": "node test/index.js"
}
}Environment requirements:
Node.js ≥ 8.0
Mini‑program base library version ≥ 2.7.3
WeChat DevTools version ≥ 1.02.1907232
Execute with:
$ npm run startShadow DOM Handling
Many components are rendered inside a Shadow DOM, which isolates their subtree from the main DOM. To interact with such elements, first obtain the shadow host, then query inside it.
const page = await miniProgram.currentPage();
const $searchBarShadow = await page.$('search-bar'); // shadow host
const $searchBar = await $searchBarShadow.$('.search-bar'); // real element
await $searchBar.tap();Additional Scenarios
Pull‑down refresh :
await miniProgram.callWxMethod('startPullDownRefresh');Scroll to a specific DOM :
const page = await miniProgram.currentPage();
const $tabShadow = await page.$('recommend-tab');
const $tab = await $tabShadow.$('.recommend');
const { top } = await $tab.offset();
await miniProgram.pageScrollTo(top);Event logging :
miniProgram.on('console', msg => console.log(msg.type, msg.args));
page.on('error', e => console.error(e));Conclusion
The first phase of mini‑program automated disaster‑recovery testing is complete. Scripts generate screenshots for normal, 500‑error, cache‑present, and network‑recovery scenarios; humans then compare the images to verify UI fallback behavior. The approach is now part of the monthly drill and serves as a foundation for a future multi‑platform SDK that will unify H5 and mini‑program testing.
References
miniprogram‑automator: https://www.npmjs.com/package/miniprogram-automator
Selenium WebDriver: https://www.selenium.dev/projects/
Puppeteer: https://pptr.dev/
Whistle (network proxy): https://wproxy.org/whistle/
Aotu Lab
Aotu Lab, founded in October 2015, is a front-end engineering team serving multi-platform products. The articles in this public account are intended to share and discuss technology, reflecting only the personal views of Aotu Lab members and not the official stance of JD.com Technology.
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.
