Template for end-to-end testing with hybrid mobile applications.
- Download and install Node.js (version 16.17 or higher).
- Install TypeScript (version 5 or higher).
- Install Visual Studio Code.
- Clone the GitHub project repository.
- Run
npm install
to install project dependencies.
- Create a
.env
file in the project root with the following variables:BROWSERSTACK_USERNAME
BROWSERSTACK_ACCESS_KEY
BROWSERSTACK_ANDROID_APP_ID
BROWSERSTACK_IOS_APP_ID
- Sign in to BrowserStack, upload your mobile app files (
.apk
for Android and.ipa
for iOS), and note the app IDs. - Update the
.env
file with your credentials and app IDs. - Run the Android tests with BrowserStack using:
npm run test:android:bs
To run Android tests on a Windows machine, ensure the following setup:
- Install the latest version of Java and set the
JAVA_HOME
environment variable to the JRE directory (e.g.,C:\Program Files\Android\Android Studio\jre\
). - Install Node.js version 16 or higher.
- Install the latest version of Android Studio.
- Add
ANDROID_HOME
to your system environment variables. - Install Appium globally:
npm install -g appium
- Download Appium Inspector (version 2 or higher).
- Install necessary Appium drivers:
appium driver install uiautomator2 appium driver install xcuitest
- Enable virtualization in BIOS (video tutorial).
- Connect an Android device to your computer with USB debugging enabled.
- Verify the device connection by running:
adb devices
- In the Android configuration file (
config/wdio.android.conf.js
), set theplatformVersion
,deviceName
, and the path to the.apk
file to match your connected Android device. - Start Appium:
appium
- Open Appium Inspector and connect it to your device to interact with your apps.
To run iOS tests with BrowserStack or locally, ensure the following setup:
- Install Xcode (version 12 or higher) from the Mac App Store.
- Configure Xcode Command Line Tools by selecting Xcode > Preferences > Locations and ensuring the Command Line Tools dropdown is set to the Xcode version.
- Install CocoaPods (if not already installed) for dependency management:
sudo gem install cocoapods
- Set up Appium for iOS testing:
npm install -g appium appium driver install xcuitest
- Connect an iOS device via USB and enable Developer Mode on the device (found in Settings > Privacy & Security > Developer Mode on iOS 16+).
- In the iOS configuration file (
config/wdio.ios.conf.js
), specifyplatformVersion
,deviceName
, and the path to the.ipa
file. - Start Appium server:
appium
- Use Appium Inspector to verify that the setup works and to locate UI elements on your iOS app.
- Ensure that the
.env
file containsBROWSERSTACK_IOS_APP_ID
along with your BrowserStack credentials (BROWSERSTACK_USERNAME
,BROWSERSTACK_ACCESS_KEY
). - Run iOS tests on BrowserStack with the following command:
npm run test:ios:bs
We use ESLint with the Prettier plugin to lint and auto-format TypeScript files. ESLint will auto-format code on every run.
All test cases should be organized within the test
folder. You can separate tests for different apps (e.g., msb-app
) and define generic classes with getters and setters to reuse logic across classes.
This project follows the Page Object Pattern as outlined in the WebdriverIO documentation. The main idea is to encapsulate page-specific logic into classes and utilize them in spec files to execute tests. For example, a LoginPage
class defines elements as attributes, allowing for easy reuse throughout the code.
This is usually caused by:
- Hard-coded delays (
browser.pause(5000)
) instead of smart waits - Network latency between test runner and BrowserStack
- Element loading timing variations on mobile devices
- Race conditions in async operations
Solutions implemented:
- Replaced
browser.pause()
withwaitUntil()
conditions - Added automatic retry mechanisms (tests retry 2 times on failure)
- Improved element wait strategies with timeout handling
- Added connection retry settings for BrowserStack
Symptoms: Element could not be located
or NoSuchElementError
Solutions:
- Verify element locators are correct for both Android and iOS
- Use Appium Inspector to confirm element selectors
- Check if app needs time to load after navigation
- Ensure elements are within viewport (scroll if needed)
Debug commands:
# Take screenshot to see current state
await browser.saveScreenshot('./debug_screenshot.png');
# Get page source to inspect DOM
const pageSource = await browser.getPageSource();
console.log(pageSource);
Symptoms: timeout
errors during element waits or clicks
Current timeout settings:
- Element wait timeout: 30 seconds
- Connection retry timeout: 5 minutes
- Test timeout: 5 minutes
- BrowserStack new command timeout: 5 minutes
Troubleshooting:
# Check BrowserStack session logs
# Go to BrowserStack dashboard and check the session details
# Increase timeout for specific problematic tests
await this.waitUntilElementDisplayed(element, 60000); // 60 seconds
Symptoms: Connection refused, session creation failed
Solutions:
- Check BrowserStack status page: https://status.browserstack.com/
- Verify credentials in
.env
file - Ensure app is uploaded and accessible
- Check BrowserStack parallel session limits
Debug steps:
# Test BrowserStack connection
curl -u "$BROWSERSTACK_USERNAME:$BROWSERSTACK_ACCESS_KEY" \
https://api.browserstack.com/app-automate/recent_apps
# Check uploaded apps
curl -u "$BROWSERSTACK_USERNAME:$BROWSERSTACK_ACCESS_KEY" \
https://api.browserstack.com/app-automate/recent_apps
Symptoms: Every second test run fails with connection errors, "ECONNREFUSED" or "session not created"
Root Cause: This is a common issue where the Appium server doesn't properly clean up sessions between test runs, leading to:
- Port conflicts from previous sessions
- Stale server processes
- Session state persistence
- Timeout during server restart
Solutions implemented:
-
Enhanced Session Management:
- Added
--session-override
flag to allow session replacement - Implemented proper session cleanup hooks
- Added connection health checks before test execution
- Added
-
Improved Server Configuration:
appium: { args: [ "--allow-insecure", "--relaxed-security", "--session-override", // Key fix for connection issues "--log-level", "error:info" ], timeout: 300000, // 5 minutes for server startup killTimeout: 30000, // 30 seconds for graceful shutdown forceKillTimeout: 10000 // 10 seconds before force kill }
-
Connection Retry Settings:
- Increased connection retry count to 5
- Extended connection timeout to 5 minutes
- Added retry delays between attempts
-
Manual Server Management: Use the Appium Manager script for problematic connections:
# Check server status npm run appium:status # Restart server with clean state npm run appium:restart # Run tests with connection health check npm run test:android:reliable npm run test:ios:reliable # Manual health check and recovery npm run appium:health
-
Capability Improvements:
- Set
appium:noReset: false
to ensure clean app state - Added
appium:clearSystemFiles: true
for proper cleanup - Increased
newCommandTimeout
to 300 seconds - Added session timeout of 10 minutes
- Set
Prevention Tips:
- Always use
npm run test:android:reliable
instead ofnpm run test:android
for important test runs - If tests fail twice in a row, run
npm run appium:restart
before continuing - Monitor Appium logs (
appium.log
) for connection warnings - Keep only one Appium instance running at a time
Symptoms: App closes unexpectedly, wrong screens appear
Debugging:
- Check device logs in BrowserStack dashboard
- Verify app permissions are granted
- Ensure app is compatible with selected device/OS version
- Check for memory issues on device
Causes:
- Network latency to BrowserStack
- Large app size
- Device performance
- Excessive waits/pauses
Optimizations:
- Use local Appium setup for development
- Optimize wait strategies
- Minimize unnecessary browser interactions
- Use parallel execution (when available)
The framework now includes:
Screenshots are automatically captured when tests fail and attached to Allure reports.
HTML/XML source is saved on test failures for debugging element issues.
- Test retries: Each test retries twice on failure
- Spec file retries: Entire spec files retry twice if all tests fail
- Element interaction retries: Click actions retry up to 3 times
All test actions are logged with:
- Timing information
- Element selectors used
- Success/failure status
- Error messages with context
- Start Appium server:
appium
- Open Appium Inspector
- Configure connection:
- Remote Path:
/wd/hub
- Desired Capabilities from config file
- Remote Path:
- Start session to manually inspect elements
# Enable verbose logging
export DEBUG=*
# Skip chromedriver install if having network issues
export APPIUM_SKIP_CHROMEDRIVER_INSTALL=1
# Increase Appium timeouts
export APPIUM_COMMAND_TIMEOUT=300000
# Run single test file
npx wdio run config/wdio.conf.android.bs.ts --spec test/specs/test.e2e.ts
# Run with increased verbosity
npx wdio run config/wdio.conf.android.bs.ts --logLevel debug
# Run locally (no BrowserStack)
npm run test:android
- Monitor test execution times in BrowserStack dashboard
- Check device performance metrics
- Review network request logs
- Analyze video recordings of test runs
# Monitor test execution time
time npm run test:android:bs
# Check memory usage during tests
top -p $(pgrep node)
- Always use explicit waits instead of
browser.pause()
- Implement retry logic for flaky operations
- Take screenshots on failures for debugging
- Use stable locators (IDs preferred over XPath)
- Test on multiple devices and OS versions
- Monitor BrowserStack session logs regularly
- Keep app size minimal for faster uploads
- Use data-test-id attributes in app for reliable element selection
If tests are completely failing:
- Check BrowserStack status: https://status.browserstack.com/
- Verify app upload:
curl -u "$BROWSERSTACK_USERNAME:$BROWSERSTACK_ACCESS_KEY" \ https://api.browserstack.com/app-automate/recent_apps
- Test with minimal spec:
it('should load app', async () => { await browser.pause(5000); const pageSource = await browser.getPageSource(); console.log('App loaded:', pageSource.length > 0); });
- Run locally instead of BrowserStack:
npm run test:android
- WebdriverIO Documentation: https://webdriver.io/
- Appium Documentation: https://appium.io/docs/
- BrowserStack Documentation: https://www.browserstack.com/docs/
- GitHub Issues: Report problems in this repository
- BrowserStack Support: Contact via dashboard if session issues persist