测试框架


Android Monkey

一、基础控制参数

参数 含义 示例
-p <包名> 指定测试的应用包名,多个包用 -p 重复指定。不指定则测试所有应用。 adb shell monkey -p com.example.app 1000
-c <类别> 限制测试的 Activity 类别(需 AndroidManifest.xml 中定义)。 adb shell monkey -c android.intent.category.LAUNCHER 100
-s <种子值> 设置随机数种子,相同种子生成相同的事件序列,便于复现问题。 adb shell monkey -s 200 1000
--throttle <毫秒> 设置事件间隔时间,模拟真实用户操作速度。 adb shell monkey --throttle 500 1000

二、日志与调试参数

参数 含义 示例
-v 设置日志详细级别: - -v(默认):仅基本信息 - -vv:包含事件详情 - -vvv:最详细(含未选中 Activity 信息) adb shell monkey -vvv 1000
--ignore-crashes 忽略应用崩溃,继续执行测试。 adb shell monkey --ignore-crashes 1000
--ignore-timeouts 忽略 ANR(应用无响应),继续执行。 adb shell monkey --ignore-timeouts 1000
--monitor-native-crashes 监控并报告原生代码(C/C++)崩溃。 adb shell monkey --monitor-native-crashes 1000

三、事件类型与比例参数

参数 含义 示例
--pct-touch <百分比> 触摸事件(点击屏幕某点)占比。 --pct-touch 30
--pct-motion <百分比> 滑动事件(滑动轨迹)占比。 --pct-motion 20
--pct-appswitch <百分比> 应用切换事件(启动新 Activity)占比。 --pct-appswitch 10
--pct-anyevent <百分比> 其他未分类事件(如按键、权限弹窗)占比。 --pct-anyevent 5
--pct-syskeys <百分比> 系统按键事件(Home、Back、音量键)占比。 --pct-syskeys 5

四、异常处理与高级参数

参数 含义 示例
--kill-process-after-error 发生错误时终止应用进程(保留在当前状态)。 adb shell monkey --kill-process-after-error 1000
--hprof 生成内存快照(.hprof 文件)用于分析内存泄漏。 adb shell monkey --hprof 1000
--bugreport 自动生成 Bugreport 日志。 adb shell monkey --bugreport 1000
--wait-dbg 等待调试器附加后再启动测试。 adb shell monkey --wait-dbg 1000

五、其他实用参数

参数 含义 示例
--blacklist-file <文件路径> 指定黑名单文件,排除某些应用或 Activity。 adb shell monkey --blacklist-file blacklist.txt 1000
--randomize-throttle 随机化事件间隔时间(需配合 --throttle 使用)。 adb shell monkey --throttle 500 --randomize-throttle 100 1000
--dbg-no-events 仅初始化测试,不发送任何事件。 adb shell monkey --dbg-no-events

六、完整命令示例

adb shell monkey \
  -p com.example.app \
  --throttle 500 \
  --ignore-crashes \
  --ignore-timeouts \
  --pct-touch 30 \
  --pct-motion 20 \
  -vvv \
  1000 > monkey_log.txt 2>&1 &
  • 功能:对 com.example.app 发送 1000 次事件,间隔 500 毫秒,忽略崩溃和 ANR,记录详细日志到文件。

七、参数配置建议

  1. 稳定性测试:启用 --ignore-crashes--ignore-timeouts,持续运行 24 小时以上。
  2. 内存泄漏分析:添加 --hprof 参数生成内存快照。
  3. 复现问题:固定 -s 种子值,便于后续复现相同操作序列

Robotium 功能回归测试框架

Robotium 是一款专为 Android 应用设计的开源自动化测试框架,专注于 功能回归测试UI交互验证。其核心优势在于通过模拟用户操作(如点击、输入、滑动)验证应用功能的稳定性,尤其适合黑盒测试场景。以下是详细解析及代码示例:


一、核心特性

  1. 支持多类型组件测试

    • 原生控件(Button、EditText、ListView 等)
    • 混合应用(WebView 内嵌页面)
    • 菜单(Menu)、对话框(Dialog)
  2. 灵活的 API 设计
    提供简洁的 Java API,支持链式调用,降低脚本编写门槛。

  3. 持续集成兼容性

    可与 Jenkins、Gradle 等工具集成,实现自动化测试流水线

  4. 跨版本兼容

    支持 Android 1.6 及以上系统,适配新旧设备


二、环境搭建

  1. 依赖配置(Gradle)

    dependencies {
        testImplementation 'com.jayway.android.robotium:robotium-solo:5.2.1'
    }
    
    • 需同步项目并配置 Android SDK、JUnit 环境
  2. 测试项目结构

    /app
      /src
        /androidTest
          /java
            com.example.app
              CalculatorTest.java  # 测试用例
    

三、测试用例编写示例

案例:计算器加法功能回归测试

import com.jayway.android.robotium.solo.Solo;
import androidx.test.ext.junit.runners.AndroidJUnit4;
import androidx.test.rule.ActivityTestRule;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;

@RunWith(AndroidJUnit4.class)
public class CalculatorTest {
    private Solo solo;

    @Rule
    public ActivityTestRule<MainActivity> rule = new ActivityTestRule<>(MainActivity.class);

    @Before
    public void setUp() {
        solo = new Solo(getInstrumentation(), rule.getActivity());
    }

    @Test
    public void testAddition() {
        // 输入数字 5 和 6
        solo.enterText(solo.getView(R.id.ed1), "5");
        solo.enterText(solo.getView(R.id.ed2), "6");
        // 点击加号和等号
        solo.clickOnView(solo.getView(R.id.btn_add));
        solo.clickOnView(solo.getView(R.id.btn_equals));
        // 验证结果是否为 11
        solo.waitForText("11", 1, 2000);
        solo.assertText("11");
    }

    @After
    public void tearDown() {
        solo.finishOpenedActivities();
    }
}

代码说明

类封装了所有操作接口,如

enterText(输入文本)

clickOnView(点击控件)

waitForText设置超时时间,避免因界面延迟导致测试失败


四、高级功能

  1. WebView 支持
    Robotium 4.1+ 版本支持内嵌网页的自动化测试,例如登录表单验证:

    solo.waitForWebView(5000);  // 等待 WebView 加载
    solo.clickOnWebElement(By.id("username"));  // 通过 ID 定位元素
    solo.enterText(0, "test@example.com");      // 输入文本
    
  2. 并行测试
    结合 Jenkins 配置多设备并行执行,提升测试效率

  3. 截图与日志

    solo.takeScreenshot("test_addition");  // 自动截图
    solo.log("测试步骤:输入 5 和 6");      // 记录日志
    

五、注意事项

  1. 局限性
    • 不支持跨应用测试(如从浏览器跳转回应用)
    • 对复杂动画或自定义 View 的兼容性需额外处理。
  2. 最佳实践
    • 用例独立性:每个测试用例应独立运行,避免数据污染。
    • 数据驱动:通过参数化测试覆盖多组输入场景。
    • 持续监控:定期更新 Robotium 版本以适配新 Android 特性

六、总结

Robotium 凭借其 轻量级易用性,成为 Android 功能回归测试的首选工具。通过结合 JUnit 和持续集成,可快速定位回归缺陷,保障版本稳定性。对于混合应用或需跨应用测试的场景,建议配合 Appium 或 Espresso 使用


前端测试框架

以下是针对 单元测试集成测试端到端测试 的技术栈分析及代码示例,覆盖 Mocha、Jest、Cypress 的典型用法:


一、单元测试:验证单个路由或中间件逻辑

技术栈:Mocha + Chai + Supertest

特点

  • 独立性:仅测试单个路由逻辑,隔离中间件和数据库依赖。
  • 快速反馈:适合高频执行,定位具体接口问题。

环境搭建

npm install express mocha chai supertest --save-dev

代码示例

// app.js
const express = require('express');
const app = express();

// 待测试的路由
app.get('/api/health', (req, res) => {
  res.status(200).json({ status: 'OK' });
});
module.exports = app; // 导出供测试使用
// test/unit/health.test.js
const request = require('supertest');
const { expect } = require('chai');
const app = require('../../app');

describe('GET /api/health', () => {
  it('应返回健康状态', (done) => {
    request(app)
      .get('/api/health')
      .expect(200)
      .end((err, res) => {
        if (err) return done(err);
        expect(res.body).to.have.property('status', 'OK');
        done();
      });
  });
});

运行测试

npx mocha test/unit/*.test.js

二、集成测试:验证多组件协作(如路由+数据库)

技术栈:Jest + Supertest + 模拟数据库

特点

  • 组件协作验证:测试路由与数据库的交互逻辑。
  • 模拟依赖:使用 Jest 的 Mock 功能替代真实数据库。

环境搭建

npm install jest supertest mongoose --save-dev

代码示例

// app.js
const express = require('express');
const mongoose = require('mongoose');
const app = express();
// 用户模型(模拟)
const UserSchema = new mongoose.Schema({ name: String });
const User = mongoose.model('User', UserSchema);
// 创建用户的路由
app.post('/api/users', async (req, res) => {
  const user = new User(req.body);
  await user.save();
  res.status(201).json(user);
});
module.exports = { app, mongoose };
// test/integration/user.test.js
const request = require('supertest');
const { app, mongoose } = require('../../app');
const { Schema } = mongoose;

// 模拟数据库
jest.mock('mongoose');
const mockUser = { _id: '1', name: 'Alice' };

describe('POST /api/users', () => {
  beforeAll(async () => {
    // 连接测试数据库
    await mongoose.connect('mongodb://localhost/test_db');
  });

  afterAll(async () => {
    // 清理数据库
    await mongoose.connection.dropDatabase();
    await mongoose.connection.close();
  });

  it('应创建新用户', async () => {
    const res = await request(app)
      .post('/api/users')
      .send({ name: 'Alice' });

    expect(res.status).toBe(201);
    expect(res.body.name).toBe('Alice');
  });
});

运行测试

npx jest test/integration/*.test.js

三、端到端测试:模拟用户完整操作流程

技术栈:Cypress

特点

  • 全流程验证:模拟用户真实操作(如登录、表单提交)。
  • 浏览器自动化:支持多浏览器测试,捕获 UI 变化。

环境搭建

npm install cypress --save-dev

代码示例

// cypress/e2e/login.cy.js
describe('用户登录流程', () => {
  beforeEach(() => {
    cy.visit('/login'); // 访问登录页
  });

  it('成功登录后跳转首页', () => {
    cy.get('#username').type('testuser');
    cy.get('#password').type('password123');
    cy.get('form').submit();
    cy.url().should('include', '/home'); // 验证跳转
    cy.contains('欢迎, testuser').should('be.visible'); // 验证页面内容
  });

  it('密码错误时显示提示', () => {
    cy.get('#username').type('testuser');
    cy.get('#password').type('wrongpass');
    cy.get('form').submit();
    cy.contains('密码错误').should('be.visible');
  });
});

运行测试

npx cypress open  # 图形界面模式
# 或
npx cypress run    # 无头模式

四、技术栈对比与选型建议

测试类型 适用场景 优势 局限性
单元测试 单个接口逻辑验证 快速执行、隔离性强 无法测试真实数据库交互
集成测试 多组件协作(如路由+数据库) 覆盖真实依赖链 配置复杂、执行速度较慢
端到端测试 用户完整操作流程 模拟真实用户行为 维护成本高、依赖环境稳定性

五、最佳实践

  1. 单元测试
    • 为每个路由编写独立测试用例。
    • 使用 sinon 等库模拟中间件(如身份验证)。
  2. 集成测试
    • 使用内存数据库(如 mongodb-memory-server)提升速度。
    • 清理测试数据,避免用例间干扰。
  3. 端到端测试
    • 分离测试环境与生产环境(如使用测试专用数据库)。
    • 结合 Cypress Dashboard 实现并行测试和报告生成

文章作者: 读序
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 读序 !
  目录