Automating WeChat Mini‑Program Tests with Minium and Jest

This guide explains why manual regression testing of a WeChat mini‑program becomes a bottleneck, compares Jest‑based SDK and Minium frameworks, shows how to set up the environment, write page‑object scripts, configure and run tests, generate reports, and troubleshoot common issues.

Youzan Coder
Youzan Coder
Youzan Coder
Automating WeChat Mini‑Program Tests with Minium and Jest

Background and Need for Automation

The "精选" mini‑program experienced a packaging failure that caused a white‑screen on the "My Orders" page in production. Manual regression across pre‑release, experience, and production builds was time‑consuming and error‑prone, prompting the adoption of automated testing for the mini‑program.

Tool Research and Selection

1. Jest + Mini‑Program SDK

Provides a script‑driven automation SDK that can be combined with any Node.js test framework.

Jest is a zero‑configuration test runner that bundles Mocha, Chai, jsdom, and coverage tools.

Drawbacks: JavaScript‑only and limited community resources.

2. Minium Framework

Official WeChat automation framework with Python and JavaScript bindings.

Supports iOS, Android, and emulator with a single script.

Offers rich page navigation, data injection, and mock capabilities.

Drawbacks: No H5 page debugging and no plugin‑level wx API support.

3. Decision

Both tools satisfy the native page requirements, but Minium’s Python support, active maintenance, and community Q&A made it the chosen solution.

Introducing Minium

Minium wraps unittest.TestCase to provide a mini‑program testing framework. The base class MiniTest adds the following steps:

Load test configuration.

Initialize minium.Minium, minium.App, and minium.Native at the proper time.

Open the IDE and launch the mini‑program or auto‑port debugging.

Intercept assert calls to record results.

Collect runtime data and screenshots for report generation.

Using MiniTest dramatically reduces test cost.

Environment Setup

Install minium-doc (or read the online docs).

Install Python ≥ 3.8.

Install WeChat DevTools (e.g., version 1.05.2103200) and enable the CLI/HTTP service port.

In DevTools settings, set the base library version > 2.7.3.

Download and install the Minium package: pip3 install minium-latest.zip or python3 setup.py install Verify installation: minitest -v Enable CLI/HTTP in DevTools security settings (service port).

Open the automation port for the tested mini‑program (default 9420).

Writing Test Scripts

Use a Page Object pattern: each page is a class containing element locators and actions; test cases focus only on data and assertions.

1. Project Structure

cases/

: test scripts and cases. case/base/: shared page methods. case/pages/: page‑object models. outputs/: generated reports. test/: test runner scripts. route.py: navigation routes.

2. Base Page Example

class BasePage:
    def __init__(self, mini):
        self.mini = mini

    def navigate_to_open(self, route):
        """Navigate to a page (non‑tabBar) using a relative or absolute path."""
        self.mini.app.navigate_to(route)

    def redirect_to_open(self, route):
        """Redirect to a page, closing the current one."""
        self.mini.app.redirect_to(route)

    def switch_tab_open(self, route):
        """Switch to a tabBar page, closing other pages."""
        self.mini.app.switch_tab(route)

    @property
    def current_title(self) -> str:
        return self.mini.page.get_element("XXXXXX").inner_text

    @property
    def current_path(self) -> str:
        return self.mini.page.path

3. Home Page Object

from case.base.basepage import BasePage
from case.base import route

class HomePage(BasePage):
    """Home page common methods"""
    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):
        self.mini.assertTrue(self.mini.page.element_is_exists(self.locators["BASE_ELEMENT"]))
        self.mini.assertTrue(self.mini.page.element_is_exists(self.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()

4. Base Test Case

from pathlib import Path
import minium

class BaseCase(minium.MiniTest):
    """Test case base class"""
    @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()

5. Example Test Case

# 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)

    def test_01_home_page_path(self):
        self.homePage.check_homepage_path()

    def test_02_page_base_element(self):
        self.homePage.check_homepage_base_element()

    def test_03_live_sale(self):
        self.assertTexts(["官方补贴"], "view")
        self.assertTexts(["轻松赚回早餐钱"], "view")

    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)

Configuration File (config.json)

{
    "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
}

Command‑Line Usage

Run a single test case:

minitest -m case.homepage_test --case test_07_open_live_sale -c config.json -g

Run all tests defined in a suite file:

minitest -s suite.json -c config.json -g

Generating Test Reports

After execution, reports are stored under outputs/. To view them, start a static server, e.g.:

python3 -m http.server 12345 -d outputs
# Then open http://localhost:12345 in a browser.

Common Issues and Fixes

Enable the automation port (9420) in the tested mini‑program.

Disable proxy settings in DevTools to avoid connection timeouts.

Version mismatch between Minium and DevTools can cause errors; use Minium 1.0.5 with DevTools 1.05.2102010.

Insufficient developer permissions may block testing; ensure the logged‑in account has access.

Screenshot capture may ignore assert_capture: false; patch minitest.py to check the flag before calling capture().

When using -p the Python path changes; prefer -m or manually add the path to PYTHONPATH.

References

WeChat official documentation.

Rethink’s articles on Minium (published on Zhihu/简书).

PythonMiniProgramAutomationTestingWeChatMinium
Youzan Coder
Written by

Youzan Coder

Official Youzan tech channel, delivering technical insights and occasional daily updates from the Youzan tech team.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.