微信小程序自动化测试

官方文档

小程序自动化

微信小程序配置

协议mock adb proxy实现

  • 运行命令
mitmdump -p 5038 \
  --rawtcp --mode reverse:http://localhost:5037  \
  -s tcp.py
  • 辅助小程序测试的adb_proxy.py
    启动命令:
    pip3 install mitmproxy
    python3 mock.py
"""
测试人社区 https://ceshiren.com
"""
import sys

from mitmproxy import ctx
from mitmproxy import tcp
from mitmproxy.utils import strutils
from mitmproxy.tools.main import mitmdump


def tcp_message(flow: tcp.TCPFlow):
    message = flow.messages[-1]
    old_content = message.content
    message.content = old_content.replace(
        b":0;localabstract:webview_devtools_remote_",
        b":   0;localabstract:xweb_devtools_remote_"
    )

    ctx.log.info(
        "[tcp_message{}] from {} to {}:\n{}".format(
            " (modified)" if message.content != old_content else "",
            "client" if message.from_client else "server",
            "server" if message.from_client else "client",
            strutils.bytes_to_escaped_str(message.content))
    )


if __name__ == '__main__':
    sys.argv = ["", "-p", "5038", "--rawtcp", "--mode", "reverse:http://localhost:5037/", "-s", sys.argv[0], "-vv"]
    mitmdump()

微信小程序自动化实现

package com.ceshiren;

import io.appium.java_client.android.AndroidDriver;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.WebDriverWait;

import java.net.MalformedURLException;
import java.net.URL;
import java.time.Duration;
import java.util.HashMap;
import java.util.Set;

import static io.appium.java_client.remote.AutomationName.ANDROID_UIAUTOMATOR2;
import static io.appium.java_client.remote.MobileCapabilityType.*;
import static io.appium.java_client.remote.MobileCapabilityType.PLATFORM_VERSION;
import static io.appium.java_client.remote.MobilePlatform.ANDROID;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
import static org.openqa.selenium.remote.CapabilityType.PLATFORM_NAME;

public class WechatTest {
    private static AndroidDriver driver;
    @BeforeAll
    public static void beforeAll() throws MalformedURLException {
        DesiredCapabilities caps=new DesiredCapabilities();
        caps.setCapability(PLATFORM_NAME, ANDROID);
        //caps.setCapability(UDID, "adb-2edf7a82-WE6ucp._adb-tls-connect._tcp.");
        caps.setCapability(UDID, "192.168.3.66:39829");
        caps.setCapability(DEVICE_NAME, "XiaoMi Civi 2");
        caps.setCapability(AUTOMATION_NAME, ANDROID_UIAUTOMATOR2);
        caps.setCapability(PLATFORM_VERSION, "13");
        // 避免清理微信数据
        caps.setCapability("noReset",true);
        caps.setCapability("appPackage","com.tencent.mm");
        caps.setCapability("appActivity",".ui.LauncherUI");

        //caps.setCapability("adbPort",5037);
        // caps.setCapability("unicodeKeyBoard",true);
        // caps.setCapability("resetKeyboard",true);
        caps.setCapability("showChromedriverLog",true);
        caps.setCapability("chromedriverExecutableDir","/Users/chenqiang/.chromedriver/");
        caps.setCapability("chromedriverChromeMappingFile", "/Users/chenqiang/.chromedriver/mapping.json");

        URL remoteUrl = new URL("http://127.0.0.1:4723/wd/hub");
        driver = new AndroidDriver(remoteUrl, caps);
        // 隐式等待
        driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(30));
    }

    @Test
    public void wechat(){
        driver.findElement(By.cssSelector("*[description='搜索']")).click();
        driver.findElement(By.cssSelector("android.widget.EditText")).sendKeys("美团外卖");
        driver.findElement(By.id("com.tencent.mm:id/odf")).click();

        System.out.println(driver.getContextHandles());

        WebDriverWait wait = new WebDriverWait(driver,Duration.ofSeconds(10));
        wait.until(webDriver -> driver.getContextHandles().stream().anyMatch(context -> context.contains("appbrand")));
        System.out.println(driver.getContextHandles());

        driver.context("WEBVIEW_com.tencent.mm:appbrand0");
        switch_to_visible_window("/index/index.html");

        WebElement search_button = driver.findElement(By.cssSelector(".search-index--index-search-btn-semicircle"));
        wait.until(ExpectedConditions.elementToBeClickable(search_button));
        search_button.click();

        switch_to_visible_window("packages/search-business/search-guide/index.html");
        driver.findElement(By.cssSelector(".input-placeholder")).click();

        driver.context("NATIVE_APP");
        HashMap<String, Object> map = new HashMap<>();
        map.put("text","Fried chicken");

        driver.executeScript("mobile: type",map);
        driver.context("WEBVIEW_com.tencent.mm:appbrand0");

        driver.findElement(By.cssSelector(".search-index--search-btn")).click();

        driver.context("NATIVE_APP");

        driver.navigate().back();
        driver.context("WEBVIEW_com.tencent.mm:appbrand0");
        switch_to_visible_window("packages/search-business/search-guide/index.html");
        assertThat(
                driver.findElement(By.cssSelector(".nview-index--n-s")).getText(),containsString("蓝蛙")
        );
    }

    public void switch_to_visible_window(String pattern){
        boolean signal =false;
        while (!signal){
            Set<String> windows = driver.getWindowHandles();
            for (String window : windows) {
                driver.switchTo().window(window);
                String url = driver.getCurrentUrl();
                String title = driver.getTitle();
                System.out.println(url);

                System.out.println(title);

                if(title.contains(pattern)){
                    signal=true;
                    break;
                }
            }
        }

    }

}