官方文档
小程序自动化
微信小程序配置
-
安装太极阴,安装xposed模块内核
GitHub - taichi-framework/TaiChi: A framework to use Xposed module with or without Root/Unlock bootloader, supportting Android 5.0 ~ 11. -
安装 WebViewDebugHook.apk
GitHub - feix760/WebViewDebugHook: Use Xposed force all webView to debug on android 4.4+ -
太极阴app 模块管理里启用 WebViewDebugHook
-
然后 创建应用 微信
-
启动 chrome 浏览器
-
启动微信(小程序)
-
使用chrome://inspect 调试
协议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;
}
}
}
}
}