三、主流自动化测试框架对比

做SDK集成验证,选对自动化框架,等于成功了一半。

市面上框架太多了,Selenium、Appium、Espresso、XCTest……你可能会问:哪个最好用?其实没有答案。关键是看你的SDK跑在什么平台上,你是测Web,还是测移动端App。

我个人习惯先把这些框架分类:Web就选Selenium,移动端就分Android和iOS。嗯,咱们一个一个说清楚。

3.1 Selenium:Web自动化的老大哥

Selenium,说白了就是浏览器自动化。它支持Chrome、Firefox、Safari,甚至IE。我最早接触的自动化框架就是它,那时候还在做Web端的SDK验证。

Selenium的核心是WebDriver,它直接调用浏览器原生API,模拟用户操作。举个例子:

from selenium import webdriver

driver = webdriver.Chrome()
driver.get("https://example.com")
element = driver.find_element(By.ID, "sdk-version")
print(element.text)
driver.quit()

这段代码打开浏览器,获取页面上的SDK版本号。简单吧?但坑也不少。

注意⚠️:Selenium只能测Web环境。如果你的SDK是原生App里的,那它无能为力。我见过有人拿Selenium去测Hybrid App里的WebView,但原生组件还是测不了。

Selenium的优点很明显:跨语言(Java、Python、JS都支持)、社区强大、文档全。缺点呢?速度慢。每次启动浏览器都要加载整个页面,而且对弹窗、对话框处理不够优雅。

我曾经在项目里用Selenium跑200个测试用例,一个完整的回归要2小时。后来优化了并行执行,才压到40分钟。所以,你也要考虑这个效率问题。

3.2 Appium:移动端的一把万能钥匙

Appium呢,就是移动端的万能钥匙。它支持iOS和Android,底层用的是WebDriver协议,和Selenium是亲戚。

它的工作原理很简单:在手机或模拟器上装一个Appium Server,这个Server接收你的指令,然后通过UIAutomator(Android)或XCUITest(iOS)去操作界面。

我一般在验证移动端SDK时,首选Appium。为什么?因为不用改SDK的代码。你想想看,SDK集成到App里了,你就把这个App装到测试机上,Appium就能直接操作它。这是黑盒测试里最省事的方案。

from appium import webdriver
from appium.options.android import UiAutomator2Options

options = UiAutomator2Options()
options.platform_name = "Android"
options.device_name = "emulator-5554"
options.app = "/path/to/app.apk"
options.app_package = "com.example.sdkdemo"
options.app_activity = ".MainActivity"

driver = webdriver.Remote("http://localhost:4723", options=options)

# 点击SDK初始化按钮
driver.find_element(By.ID, "com.example.sdkdemo:id/init_btn").click()

这段代码启动App,然后点击初始化按钮。够直接吧?

但Appium不是万能的。它最大的问题就是速度。每次测试都要启动App,甚至重启App。如果你用模拟器,那速度更慢。我记得有一次在Jenkins上跑400个用例,从早上跑到晚上。

💡 我的经验:如果你只是验证SDK的某个功能点,比如埋点上报,那Appium是够用的。但如果你要测性能、内存泄漏,那得另找工具。

3.3 Espresso:Android的亲儿子

如果你只测Android,而且你手里有源码,那我强烈推荐Espresso。它是Google官方推荐的Android UI测试框架,直接跑在instrumentation里,比Appium快多了。

Espresso的优点是快、稳、集成简单。你只需要在build.gradle里加一行依赖:

androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'

然后写测试用例:

@Test
public void testSDKInit() {
    onView(withId(R.id.init_button))
        .perform(click());

    onView(withId(R.id.status_text))
        .check(matches(withText("SDK Initialized")));
}

Espresso会等待界面空闲再执行下一步,所以不用手动加Thread.sleep()。这个设计很聪明,避免了各种竞态问题。

不过Espresso也有软肋:它只能测Android,不能跨平台。而且它需要和App一起编译运行,不能做黑盒测试。如果你的SDK是提供给第三方开发者的,那第三方大概率不会给你源码编译。

我在项目中遇到过这种情况:SDK集成方只给了Release包,没给源码。Espresso压根用不了,只能换Appium。

3.4 XCTest:iOS的自家框架

iOS这边,Apple官方框架就是XCTest。它和Espresso很像,也是白盒测试,需要源码。

XCTest是基于XCTestCase的,写起来像这样:

import XCTest

class SDKIntegrationTests: XCTestCase {
    let app = XCUIApplication()
    
    override func setUp() {
        super.setUp()
        app.launch()
    }
    
    func testSDKInit() {
        app.buttons["initButton"].tap()
        let statusLabel = app.staticTexts["statusLabel"]
        XCTAssertEqual(statusLabel.label, "SDK Initialized")
    }
}

XCTest的优点是稳定、速度快、和Xcode集成完美。但它只能在真机或模拟器上跑,不支持云端大规模并行。

还有一个比较蛋疼的点:UI元素定位。iOS的accessibility identifier必须提前在代码里设置好,否则你只能靠顺序或者label去定位。我刚开始做iOS测试时,经常因为定位不准导致测试闪退。

避坑指南:我曾经因为忘记给某个Button设置accessibilityIdentifier,导致整个测试套件全挂。后来发现XCTest的默认定位策略是按label匹配,但如果label变了,测试就废了。所以一定要养成习惯:所有可交互控件都加上标识。

3.5 核心框架对比

为了方便你选型,我把这四个框架的特点整理成了表格:

框架 平台 语言 核心 运行速度 学习成本 维护成本
Selenium Web Java/Python/JS等 WebDriver 慢 低 中
Appium iOS + Android Java/Python/JS等 WebDriver + UIAutomator/XCUITest 较慢 中 高
Espresso Android Java/Kotlin Instrumentation 快 低 低
XCTest iOS Swift/ObjC XCTestCase 快 低 低

从表里可以看出来:

  • Selenium和Appium是跨平台的,灵活但慢。
  • Espresso和XCTest是平台专属的,快但需要源码。
  • 如果你做的是SDK验证,一般拿不到源码,所以Appium反而是最常用的。
🔑 我的建议:
- 测Web SDK → 用Selenium
- 测移动端SDK(黑盒)→ 用Appium
- 测Android SDK(白盒)→ 用Espresso
- 测iOS SDK(白盒)→ 用XCTest
- 紧急情况?Appium兜底,因为它通吃移动端

3.6 框架选型流程

框架选型决策流程 开始选型 目标平台:Web 还是 移动端? Web Selenium 移动 Appium 有源码?无源码? 有源码 Android → Espresso iOS → XCTest 无源码 继续用Appium

这张图展示了我的决策逻辑:先看平台,Web直接上Selenium;移动端再看有没有源码,有源码就选平台原生框架,没有源码就用Appium兜底。

你想想看,很多SDK集成场景,你拿到的就是一个加固过的APK或者IPA,Appium几乎是唯一的选择。虽然慢一点,但胜在通用。

⚠️ 别踩的坑:
1. 不要试图用Selenium测原生App,那会把你气疯。
2. 不要在一个测试用例里同时用Appium和Espresso,会冲突。
3. 不要在XCTest里写死sleep,用expectation替代,否则测试很难稳定。