You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在WebdriverIO+Appium测试流程中检测React Native Android应用崩溃?

检测React Native Android应用崩溃(基于Appium+WebdriverIO)

因为你的应用崩溃时没有弹窗,得从应用进程状态、页面核心元素可达性、系统日志这几个维度入手,结合你提到的事件监听、try-catch、assert来落地。下面给你具体的实现方案和代码示例:

一、用WebdriverIO事件监听器做全局崩溃检测

WebdriverIO自带生命周期事件,你可以在每个测试命令执行后自动检查应用是否存活。比如在配置文件里注册全局命令,再绑定到afterCommand事件:

// wdio.conf.js 中的配置
exports.config = {
  // 其他配置(比如Appium服务地址、设备参数)...
  onPrepare: async function () {
    // 注册自定义的崩溃检测命令
    browser.addCommand('checkAppAlive', async function () {
      const packageName = await this.getCurrentPackage(); // 替换成你的RN应用包名,比如com.yourapp
      
      // 用adb命令检查应用进程是否存在
      const processCheck = await this.executeShellCommand(`ps -A | grep ${packageName}`);
      if (!processCheck.stdout.trim()) {
        await this.saveScreenshot(`crash-${Date.now()}.png`); // 崩溃时自动截图
        throw new Error(`应用崩溃:${packageName} 进程已终止`);
      }

      // 额外检查:尝试访问应用的核心根元素(比如RN里的testID="app-root")
      try {
        await this.$('~app-root').waitForExist({ timeout: 3000 });
      } catch (err) {
        await this.saveScreenshot(`crash-element-${Date.now()}.png`);
        throw new Error(`应用无响应:核心元素不可达,疑似崩溃`);
      }
    });
  },

  // 每个命令执行后自动触发崩溃检测(排除一些无关命令)
  afterCommand: async function (commandName) {
    const skipCommands = ['screenshot', 'getLog', 'executeShellCommand'];
    if (!skipCommands.includes(commandName)) {
      await browser.checkAppAlive();
    }
  }
};

二、Try-Catch+断言做局部关键操作检测

在触发复杂逻辑的操作(比如提交表单、跳转页面)后,用try-catch包裹断言,区分是普通断言失败还是应用崩溃:

describe('RN应用核心流程测试', () => {
  it('提交表单后检测应用状态', async () => {
    // 模拟关键操作:填写表单并提交
    await $('~input-username').setValue('test-user');
    await $('~submit-form').click();

    try {
      // 断言跳转后的页面元素存在
      await expect($('~success-page')).toBeDisplayed({ timeout: 5000 });
    } catch (assertErr) {
      // 进一步验证是否是崩溃导致的元素不可达
      const packageName = await browser.getCurrentPackage();
      const processStatus = await browser.executeShellCommand(`ps -A | grep ${packageName}`);
      
      if (!processStatus.stdout.trim()) {
        console.error(`应用崩溃:提交表单后进程终止`);
        await browser.saveScreenshot(`crash-submit-${Date.now()}.png`);
        throw new Error(`应用崩溃:提交表单后进程终止,原错误:${assertErr.message}`);
      } else {
        // 不是崩溃,只是元素加载超时,抛出原断言错误
        throw assertErr;
      }
    }
  });
});

三、解析Android Logcat日志抓崩溃

RN应用崩溃时,Android系统日志(logcat)会输出崩溃堆栈,你可以通过Appium获取logcat并筛选关键词:

// 自定义命令:检查logcat中的崩溃日志
browser.addCommand('checkCrashInLogcat', async function () {
  const logcatLogs = await this.getLogs('logcat');
  // 筛选RN崩溃或Android致命异常的日志
  const crashLogs = logcatLogs.filter(log => 
    log.message.includes('FATAL EXCEPTION') || 
    log.message.includes('ReactNative: Error') ||
    log.message.includes('AndroidRuntime: Shutting down VM')
  );

  if (crashLogs.length > 0) {
    const crashDetails = crashLogs.map(log => `${log.timestamp}: ${log.message}`).join('\n');
    console.error(`检测到崩溃日志:\n${crashDetails}`);
    await browser.saveScreenshot(`crash-logcat-${Date.now()}.png`);
    throw new Error(`应用崩溃,日志详情:\n${crashDetails}`);
  }
});

// 在测试用例中使用
it('执行复杂操作后检查logcat', async () => {
  await $('~load-complex-data').click();
  await browser.checkCrashInLogcat();
});

四、日志与错误处理优化小技巧

  • 用日志工具(比如winston)把崩溃日志按测试用例、时间分类写入文件,方便后续排查。
  • 结合Selenium Grid的话,可以在Grid节点上配置日志收集,把每个测试会话的崩溃日志同步到中心存储。
  • 崩溃时除了截图,还可以导出当前的Appium会话日志,便于定位问题。

内容的提问来源于stack exchange,提问作者punkuotukas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 08:53:22