@testrelic/appium-analytics
v1.0.2
Published
Appium test analytics reporter with device log capture, command tracking, network interception, and interactive HTML reports for Android and iOS
Maintainers
Readme
@testrelic/appium-analytics
Appium test analytics reporter with device log capture, command tracking, network interception, and interactive HTML reports for Android and iOS.
Table of Contents
- Features
- Requirements
- Installation
- Quick Start
- WDIO Integration
- Configuration Reference
- Platform Setup
- Cloud Upload
- CLI
- Merging Reports
- Viewing Reports Locally
- Redaction
- Troubleshooting
- License
Features
- Appium command tracking — records every WebDriver command with timing, category, arguments, and return values; sensitive arguments are automatically redacted
- Device log capture — streams Android logcat and iOS syslog / crashlog per test
- Network interception — captures HTTP requests and responses via Chrome DevTools Protocol (Android),
safariNetwork(iOS), or an automatic proxy fallback usingadbwhen CDP is not available - Console log capture — collects webview / browser console output via BiDi
log.entryAddedor falls back tobrowser/safariConsolelog polling - Screenshot collection — captures screenshots after every test, only on failure, or never
- Video recording — records the device screen using Appium recording commands or
adb screenrecordon Android - Interactive HTML reports — self-contained report with a timeline view for commands, logs, network requests, screenshots, and video
- Cloud upload — upload results to the TestRelic platform in batch or realtime mode
- CLI — merge multiple report files, serve the report directory, or open the report in a browser
Requirements
| Requirement | Version |
|-------------|---------|
| Node.js | >= 18 (Appium 3.x requires >= 20.19) |
| WebdriverIO | >= 9.0.0 (peer dependency) |
| @wdio/reporter | >= 9.0.0 (peer dependency) |
| Appium | 3.x (npm install -g appium@latest) |
| Android driver | UiAutomator2 (appium driver install uiautomator2) |
| iOS driver | XCUITest on macOS (appium driver install xcuitest) |
iOS note: iOS testing requires macOS 13+ with Xcode 15+. iOS tests cannot run on Windows or Linux.
Installation
# npm
npm install @testrelic/appium-analytics
npm install --save-dev webdriverio @wdio/reporter
# yarn
yarn add @testrelic/appium-analytics
yarn add --dev webdriverio @wdio/reporter
# pnpm
pnpm add @testrelic/appium-analytics
pnpm add --save-dev webdriverio @wdio/reporterQuick Start
Add TestRelicService to services and TestRelicReporter to reporters in your WDIO config, then implement onComplete:
// wdio.conf.ts
import { join } from 'node:path';
import { TestRelicService } from '@testrelic/appium-analytics/service';
import { TestRelicReporter } from '@testrelic/appium-analytics';
const REPORT_DIR = join(process.cwd(), 'test-results');
async function onComplete() {
try {
await TestRelicReporter.finalize(process.cwd());
} catch (err) {
process.stderr.write(`[TestRelic] Cloud finalization failed: ${err}\n`);
}
}
export const config = {
runner: 'local',
port: 4723,
path: '/',
specs: ['./tests/**/*.test.ts'],
maxInstances: 1,
capabilities: [{
platformName: 'Android',
'appium:automationName': 'UiAutomator2',
'appium:deviceName': 'emulator-5554',
'appium:app': join(process.cwd(), 'apps', 'MyApp.apk'),
}],
framework: 'mocha',
mochaOpts: { ui: 'bdd', timeout: 60000 },
services: [
[TestRelicService, {
outputPath: REPORT_DIR,
includeDeviceLogs: true,
includeNetworkLogs: true,
screenshotOnEvery: 'failure',
}],
],
reporters: [
'spec',
[TestRelicReporter, {
outputPath: join(REPORT_DIR, 'report.json'),
htmlReportPath: join(REPORT_DIR, 'report.html'),
openReport: true,
}],
],
onComplete,
};WDIO Integration
The package provides two WebdriverIO plugins that work together: a service and a reporter. Both accept the same AppiumReporterConfig options.
TestRelicService
Import path: @testrelic/appium-analytics/service
TestRelicService is a WDIO service plugin that runs inside the worker process alongside your live Appium/WebDriver session. It registers the following hooks:
| Hook | What it does |
|------|-------------|
| before | Detects platform/capabilities, starts DeviceLogCollector, ConsoleLogCollector, NetworkInterceptor, and prepares ScreenshotCollector |
| after | Stops log and network collectors |
| beforeTest / afterTest | Marks per-test log slice boundaries; captures screenshots; starts/stops video recording |
| beforeCommand / afterCommand | Delegates to CommandTracker — records every Appium command with timing and redacted arguments |
| beforeAssertion / afterAssertion | Delegates to AssertionTracker — records WebdriverIO v9 assertion steps |
TestRelicReporter
Import path: @testrelic/appium-analytics
TestRelicReporter extends @wdio/reporter and runs in the same worker process. It consumes data collected by TestRelicService and writes the final reports:
| Event | What it does |
|-------|-------------|
| onRunnerStart | Initializes the optional CloudClient |
| onTestEnd | Pulls collected data from TestRelicService, builds a TimelineBuildInput, and optionally performs a realtime cloud upload |
| onRunnerEnd | Builds the full timeline and summary, writes the JSON report, generates the HTML report, prints the console summary, and writes a cloud finalization manifest |
onComplete Hook
This is required for cloud upload to work correctly.
TestRelicReporter.finalize() is a static method that must be called from the WDIO launcher process (i.e., in onComplete) after all worker processes have exited. It reads the .testrelic-finalize-<testRunId>.json manifest written by each worker and sends the final upload payload to the cloud.
async function onComplete() {
try {
await TestRelicReporter.finalize(process.cwd());
} catch (err) {
process.stderr.write(`[TestRelic] Cloud finalization failed: ${err}\n`);
}
}
export const config = {
// ...
onComplete,
};Even when cloud upload is not configured, including onComplete is harmless — finalize() exits immediately if no manifest files are found.
Android Configuration
Full example using the Android emulator:
// wdio.android.conf.ts
import { join } from 'node:path';
import { TestRelicService } from '@testrelic/appium-analytics/service';
import { TestRelicReporter } from '@testrelic/appium-analytics';
const APP_PATH = join(process.cwd(), 'apps', 'MyApp.apk');
const REPORT_DIR = join(process.cwd(), 'test-results');
async function onComplete() {
try {
await TestRelicReporter.finalize(process.cwd());
} catch (err) {
process.stderr.write(`[TestRelic] Cloud finalization failed: ${err}\n`);
}
}
export const config = {
runner: 'local',
port: 4723,
path: '/',
specs: ['./tests/android/**/*.test.ts'],
maxInstances: 1,
capabilities: [{
platformName: 'Android',
'appium:automationName': 'UiAutomator2',
'appium:deviceName': 'emulator-5554',
'appium:app': APP_PATH,
'appium:autoGrantPermissions': true,
'appium:newCommandTimeout': 240,
'appium:appWaitActivity': '*',
'appium:noReset': false,
}],
logLevel: 'warn',
waitforTimeout: 15000,
connectionRetryTimeout: 120000,
connectionRetryCount: 3,
framework: 'mocha',
mochaOpts: { ui: 'bdd', timeout: 90000 },
services: [
[TestRelicService, {
outputPath: REPORT_DIR,
includeDeviceLogs: true,
includeNetworkLogs: true,
includeConsoleLogs: true,
includeCommands: true,
includeAssertions: true,
includeScreenshots: true,
screenshotOnEvery: 'failure',
includeVideoRecording: true,
}],
],
reporters: [
'spec',
[TestRelicReporter, {
outputPath: join(REPORT_DIR, 'report.json'),
htmlReportPath: join(REPORT_DIR, 'report.html'),
openReport: false,
}],
],
onComplete,
autoCompileOpts: {
tsNodeOpts: { project: './tsconfig.json' },
},
};iOS Configuration
Requires macOS 13+ with Xcode 15+. iOS tests cannot run on Windows or Linux.
// wdio.ios.conf.ts
import { join } from 'node:path';
import { TestRelicService } from '@testrelic/appium-analytics/service';
import { TestRelicReporter } from '@testrelic/appium-analytics';
const APP_PATH = join(process.cwd(), 'apps', 'MyApp.app');
const REPORT_DIR = join(process.cwd(), 'test-results');
async function onComplete() {
try {
await TestRelicReporter.finalize(process.cwd());
} catch (err) {
process.stderr.write(`[TestRelic] Cloud finalization failed: ${err}\n`);
}
}
export const config = {
runner: 'local',
port: 4723,
path: '/',
specs: ['./tests/ios/**/*.test.ts'],
maxInstances: 1,
capabilities: [{
platformName: 'iOS',
'appium:automationName': 'XCUITest',
'appium:deviceName': 'iPhone 15',
'appium:platformVersion': '17.5',
'appium:app': APP_PATH,
'appium:newCommandTimeout': 240,
'appium:noReset': false,
}],
logLevel: 'warn',
waitforTimeout: 10000,
connectionRetryTimeout: 120000,
connectionRetryCount: 3,
framework: 'mocha',
mochaOpts: { ui: 'bdd', timeout: 60000 },
services: [
[TestRelicService, {
outputPath: REPORT_DIR,
includeDeviceLogs: true,
includeNetworkLogs: true,
includeConsoleLogs: true,
includeCommands: true,
includeAssertions: true,
includeScreenshots: true,
screenshotOnEvery: 'failure',
includeVideoRecording: false,
}],
],
reporters: [
'spec',
[TestRelicReporter, {
outputPath: join(REPORT_DIR, 'report.json'),
htmlReportPath: join(REPORT_DIR, 'report.html'),
openReport: false,
}],
],
onComplete,
autoCompileOpts: {
tsNodeOpts: { project: './tsconfig.json' },
},
};Configuration Reference
Both TestRelicService and TestRelicReporter accept Partial<AppiumReporterConfig>. Options set on TestRelicService control data collection; options set on TestRelicReporter control report output and cloud upload. You can share the same options object between both plugins.
Core Options
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| outputPath | string | './test-results/testrelic-timeline.json' | File path for the JSON report. Directories are created automatically. |
| htmlReportPath | string | outputPath with .html extension | File path for the HTML report. |
| openReport | boolean | true | Automatically open the HTML report in the default browser after the run completes. |
| includeDeviceLogs | boolean | true | Capture Android logcat / iOS syslog and crashlog entries. |
| includeNetworkLogs | boolean | true | Capture HTTP network requests and responses. |
| includeConsoleLogs | boolean | true | Capture webview and browser console output. |
| includeScreenshots | boolean | true | Capture device screenshots. |
| screenshotOnEvery | 'test' \| 'failure' \| 'never' | 'failure' | When to take screenshots: after every test, only on test failure, or never. |
| includeVideoRecording | boolean | false | Record the device screen for each test. |
| includeCommands | boolean | true | Record every Appium / WebDriver command with timing and arguments. |
| includeAssertions | boolean | true | Record WebdriverIO assertion steps (WDIO v9+). |
| deviceLogPollInterval | number (ms) | 1000 | Interval between device log polls. Minimum value is 100. |
| preferBiDi | boolean | true | Use the WebDriver BiDi log.entryAdded event for console log capture when the driver supports it, falling back to polling otherwise. |
| redactPatterns | (string \| RegExp)[] | [] | Additional patterns to redact from command arguments and log entries. Built-in patterns are always applied (see Redaction). |
| quiet | boolean | false | Suppress the console summary table printed at the end of a run. |
| metadata | Record<string, unknown> | null | Arbitrary key-value pairs attached to the test run report. Useful for build numbers, branch names, or environment tags. |
| cloud | CloudReporterOptions | — | Cloud upload configuration. See Cloud Options below. |
Cloud Options
Passed as the cloud key inside the reporter options, or loaded automatically from .testrelic/testrelic-config.json and environment variables.
| Option | Type | Default | Description |
|--------|------|---------|-------------|
| apiKey | string | — | TestRelic API key. Required for cloud upload. |
| endpoint | string | 'https://platform.testrelic.ai/api/v1' | TestRelic API endpoint. Override for self-hosted or staging environments. |
| upload | 'batch' \| 'realtime' \| 'both' | 'batch' | Upload strategy. 'batch' uploads after onComplete; 'realtime' uploads results as each test finishes; 'both' does both. |
| timeout | number (ms) | — | HTTP request timeout for cloud API calls. |
| projectName | string | — | Override the project name shown in the TestRelic dashboard. Defaults to the git repository name. |
| uploadArtifacts | boolean | — | Whether to upload screenshots and video files as run artifacts. |
| artifactMaxSizeMb | number | — | Maximum size in MB for a single artifact file to be uploaded. Files exceeding this limit are skipped. |
Platform Setup
Android
Prerequisites
- Node.js >= 20.19
- Java JDK 17+
- Windows 10/11, macOS, or Linux with hardware acceleration enabled for the emulator
Step 1 — Install Android SDK Command-Line Tools
Download from developer.android.com/studio#command-line-tools-only, extract to a directory (e.g. C:\Android\cmdline-tools\latest\), and set the following environment variables:
# Windows (PowerShell)
[System.Environment]::SetEnvironmentVariable("ANDROID_HOME", "C:\Android", "User")
[System.Environment]::SetEnvironmentVariable(
"Path",
"$env:Path;C:\Android\cmdline-tools\latest\bin;C:\Android\platform-tools;C:\Android\emulator",
"User"
)# macOS / Linux (~/.zshrc or ~/.bashrc)
export ANDROID_HOME=$HOME/Android
export PATH=$PATH:$ANDROID_HOME/cmdline-tools/latest/bin:$ANDROID_HOME/platform-tools:$ANDROID_HOME/emulatorAccept SDK licenses:
sdkmanager --licensesStep 2 — Install Platform Tools, Emulator, and System Image
sdkmanager "platform-tools" "emulator"
sdkmanager "platforms;android-34"
sdkmanager "system-images;android-34;google_apis;x86_64"Step 3 — Create an Android Virtual Device
avdmanager create avd -n MyEmulator -k "system-images;android-34;google_apis;x86_64" -d "pixel_7"Step 4 — Start the Emulator
emulator -avd MyEmulator -no-snapshot-loadWait for the emulator to fully boot, then verify:
adb devices
# emulator-5554 deviceStep 5 — Install Appium and UiAutomator2 Driver
npm install -g appium@latest
appium driver install uiautomator2Verify:
appium --version # 3.x.x
appium driver list --installed # uiautomator2Step 6 — Start the Appium Server
appium --address 127.0.0.1 --port 4723For the full Android setup guide see docs/ANDROID_SETUP.md.
iOS
macOS only. iOS testing requires macOS 13+ with Xcode 15+. These tests cannot run on Windows or Linux.
Prerequisites
- macOS 13+ (Ventura or later recommended)
- Xcode 15+ with iOS Simulator
- Node.js >= 20.19
- Xcode Command Line Tools:
xcode-select --install
Step 1 — Install Appium and XCUITest Driver
npm install -g appium@latest
appium driver install xcuitestVerify:
appium driver list --installed # xcuitestStep 2 — Boot an iOS Simulator
xcrun simctl boot "iPhone 15"
open -a SimulatorList available simulators if iPhone 15 is not found:
xcrun simctl list devicesStep 3 — Start the Appium Server
appium --address 127.0.0.1 --port 4723For the full iOS setup guide see docs/IOS_SETUP.md.
Cloud Upload
Results can be uploaded to the TestRelic cloud platform. Cloud upload is optional — reports are always written locally regardless.
Config File
Create .testrelic/testrelic-config.json in your project root. The file is discovered automatically by the reporter:
{
"cloud": {
"apiKey": "<your-api-key>",
"endpoint": "https://platform.testrelic.ai/api/v1",
"upload": "batch"
}
}Add this file to .gitignore to keep your API key out of version control.
Environment Variables
| Variable | Description |
|----------|-------------|
| TESTRELIC_API_KEY | TestRelic API key |
| TESTRELIC_CLOUD_ENDPOINT | API endpoint URL |
| TESTRELIC_UPLOAD_STRATEGY | Upload strategy: batch, realtime, or both |
Environment variables are the recommended approach for CI/CD pipelines.
Priority Order
Configuration is merged in the following order — higher entries win:
TESTRELIC_API_KEY/TESTRELIC_CLOUD_ENDPOINT/TESTRELIC_UPLOAD_STRATEGYenvironment variablescloudinline options inside theTestRelicReporteroptions block inwdio.conf.ts.testrelic/testrelic-config.jsonconfig file
CLI
The package installs a testrelic-appium binary automatically.
Merge multiple report files (useful after parallel worker runs):
npx testrelic-appium merge ./test-results/report-worker-1.json ./test-results/report-worker-2.json \
-o ./test-results/merged-report.jsonServe a report directory (serves at http://127.0.0.1:9323 by default):
npx testrelic-appium serve ./test-results
npx testrelic-appium serve ./test-results --port 8080Serve and open in browser (alias for serve + auto-open):
npx testrelic-appium open ./test-resultsMerging Reports
When running tests across multiple WDIO workers, each worker writes its own JSON report. Use mergeReports() or the CLI merge command to combine them into a single timeline.
Programmatic merge (@testrelic/appium-analytics/merge):
import { mergeReports } from '@testrelic/appium-analytics/merge';
await mergeReports(
['./test-results/report-1.json', './test-results/report-2.json'],
{ output: './test-results/merged.json' }
);CLI merge (see CLI section above).
Viewing Reports Locally
After a test run, the HTML report is written to htmlReportPath (default: same location as outputPath with an .html extension) and opened automatically in your browser when openReport: true (the default).
To view a report at any time without running tests:
npx testrelic-appium serve ./test-results
# Open http://127.0.0.1:9323 in your browserRedaction
The reporter automatically redacts sensitive data from command arguments and log entries using the following built-in patterns:
| Pattern | Matches |
|---------|---------|
| AWS-style access keys | 20-character alphanumeric strings starting with AKIA, ASIA, etc. |
| Bearer tokens | Values following Bearer in headers or strings |
| PEM private keys | -----BEGIN * PRIVATE KEY----- blocks |
| Embedded credentials | //user:password@ in URLs |
To add custom redaction patterns, use the redactPatterns option:
[TestRelicService, {
redactPatterns: [
/my-secret-\w+/, // regex
'my-fixed-token-value', // literal string
],
}]Custom patterns are appended to the built-in set — the built-in patterns are always active.
Troubleshooting
Android: emulator won't start
- Enable Intel VT-x / AMD-V in BIOS settings
- On Windows 11: ensure the Hyper-V platform feature is enabled in Windows Features
- Try a cold boot:
emulator -avd MyEmulator -no-snapshot
Android: adb not found
- Ensure
$ANDROID_HOME/platform-toolsis on yourPATH - Run
adb kill-server && adb start-serverto reset the adb daemon
Android: Appium cannot find UiAutomator2
- Run
appium driver install uiautomator2again - If using a non-default Appium home, set
APPIUM_HOMEto point to the correct directory
Android: tests time out during session creation
- Ensure the emulator is fully booted before starting tests (
adb devicesshowsdevice, notoffline) - Increase
connectionRetryTimeoutin your WDIO config - Verify that the APK path in capabilities is correct and the file exists
iOS: xcrun: error: unable to find utility
- Run
sudo xcode-select --switch /Applications/Xcode.appto point to the correct Xcode installation
iOS: simulator not found
- Open Xcode > Settings > Platforms and download the required iOS Simulator runtime
- List available simulators:
xcrun simctl list devices
iOS: WebDriverAgent build fails
- Open
~/.appium/node_modules/appium-xcuitest-driver/node_modules/appium-webdriveragent/WebDriverAgent.xcodeprojin Xcode - Set a valid signing team under Signing & Capabilities
Report not generated
- Ensure
TestRelicServiceis listed inservicesandTestRelicReporteris listed inreporters— both are required - Check that
outputPathdirectories are writable by the process
License
MIT — see LICENSE for details.
© TestRelic AI <[email protected]> — testrelic.ai
