Skip to content
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
69 changes: 67 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,2 +1,67 @@
# selfheal-demo-browserstack
Self Heal Demo Scripts
# Self Heal Demo (TestNG)

## Overview
This repository contains demo scripts and configuration for testing the self-healing feature on BrowserStack using Appium and TestNG. It includes two main components:

### 1. Base App (BaseApp.apk)
- The base Android app used for automation and self-healing tests.
- Located at: `android/testng-examples/BaseApp.apk`
- This app serves as the reference for normal (non-self-healing) test runs.

### 2. Self-Heal App (SelfHealApp.apk)
- The self-healing version of the app, built to demonstrate BrowserStack's self-heal capabilities.
- Located at: `android/testng-examples/SelfHealApp.apk`
- Used to validate how the self-heal feature recovers from locator changes or UI modifications.

## Test Scenarios Demonstrated
- This repository includes two different test suites:
- **Base App Test Suite:** Runs against the base app to show standard automation behavior without self-healing.
- **Self-Heal App Test Suite:** Runs against the self-heal app with self-healing enabled to demonstrate how tests recover from locator changes or UI modifications.
- The test names will differ between the two suites to clearly indicate which scenario is being executed (e.g., `BaseAppTest` vs `SelfHealAppTest`).
- By comparing the results of these two test suites, you can clearly observe the benefits of the self-heal feature.

## How to Check Differences
- Run your test suite with both the base app and the self-heal app.
- Compare the results and logs: with self-heal enabled, tests should pass even if some locators have changed, while they may fail without self-heal.
- You can also use diff tools to compare the APKs or source code if needed.

## About the Self-Heal Feature
- The self-heal feature in BrowserStack automatically detects and recovers from locator changes in your app's UI during automated tests.
- If a locator fails (e.g., due to a UI update), self-heal attempts to find the correct element using alternative strategies, allowing your tests to continue without manual intervention.
- This reduces test flakiness and maintenance effort, especially in agile environments with frequent UI changes.
- **To enable self-healing, set `selfHeal: true` in your `browserstack.yml` configuration file.**

#### Example `browserstack.yml` snippet:
```yaml
selfHeal: true
```

## Usage
- Build and upload the APKs to BrowserStack as needed.
- Run your automation scripts using the provided configuration files.
- Make sure `selfHeal: true` is set in your `browserstack.yml` to enable the self-heal feature.
- Review the test results and logs to observe self-healing in action.

### Running Tests with Maven or Gradle
- **For Maven:**
- To run the Base App test suite:
```sh
mvn test -P sampleBaseAppTest
```
- To run the Self-Heal App test suite:
```sh
mvn test -P sampleSelfHealAppTest
```
- **For Gradle:**
- To run the Base App test suite:
```sh
gradle clean sampleBaseAppTest
```
- To run the Self-Heal App test suite:
```sh
gradle clean sampleSelfHealAppTest
```

## Getting Help

If you are running into any issues or have any queries, please check [Browserstack Support page](https://www.browserstack.com/support/app-automate) or [get in touch with us](https://www.browserstack.com/contact?ref=help).
Binary file added android/testng-examples/BaseApp.apk
Binary file not shown.
Binary file added android/testng-examples/SelfHealApp.apk
Binary file not shown.
81 changes: 81 additions & 0 deletions android/testng-examples/browserstack.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# =============================
# Set BrowserStack Credentials
# =============================
# Add your BrowserStack userName and acccessKey here or set BROWSERSTACK_USERNAME and
# BROWSERSTACK_ACCESS_KEY as env variables
userName: BROWSERSTACK_USERNAME
accessKey: BROWSERSTACK_ACCESS_KEY

# ======================
# BrowserStack Reporting
# ======================
# The following capabilities are used to set up reporting on BrowserStack:
# Set 'projectName' to the name of your project. Example, Marketing Website
projectName: BrowserStack Samples
# Set `buildName` as the name of the job / testsuite being run
buildName: browserstack build
# `buildIdentifier` is a unique id to differentiate every execution that gets appended to
# buildName. Choose your buildIdentifier format from the available expressions:
# ${BUILD_NUMBER} (Default): Generates an incremental counter with every execution
# ${DATE_TIME}: Generates a Timestamp with every execution. Eg. 05-Nov-19:30
# Read more about buildIdentifiers here -> https://www.browserstack.com/docs/automate/selenium/organize-tests
buildIdentifier: '#${BUILD_NUMBER}' # Supports strings along with either/both ${expression}
# Set `framework` of your test suite. Example, `testng`, `cucumber`, `cucumber-testng`
# This property is needed to send test context to BrowserStack (test name, status)
framework: testng

source: testng:appium-sample-sdk:v1.1

app: ./BaseApp.apk
# app: ./SelfHealApp.apk # For testing with the Self Heal App

# =======================================
# Platforms (Browsers / Devices to test)
# =======================================
# Platforms object contains all the browser / device combinations you want to test on.
# Entire list available here -> (https://www.browserstack.com/list-of-browsers-and-platforms/automate)

platforms:
- deviceName: Samsung Galaxy S22 Ultra
osVersion: 12.0
platformName: android
- deviceName: Samsung Galaxy S21
osVersion: 11.0
platformName: android
- deviceName: Google Pixel 6 Pro
osVersion: 12.0
platformName: android

# =======================
# Parallels per Platform
# =======================
# The number of parallel threads to be used for each platform set.
# BrowserStack's SDK runner will select the best strategy based on the configured value
#
# Example 1 - If you have configured 3 platforms and set `parallelsPerPlatform` as 2, a total of 6 (2 * 3) parallel threads will be used on BrowserStack
#
# Example 2 - If you have configured 1 platform and set `parallelsPerPlatform` as 5, a total of 5 (1 * 5) parallel threads will be used on BrowserStack
parallelsPerPlatform: 1

# ==========================================
# BrowserStack Local
# (For localhost, staging/private websites)
# ==========================================
# Set browserStackLocal to true if your website under test is not accessible publicly over the internet
# Learn more about how BrowserStack Local works here -> https://www.browserstack.com/docs/automate/selenium/local-testing-introduction
browserstackLocal: true # <boolean> (Default false)
#browserStackLocalOptions:
#Options to be passed to BrowserStack local in-case of advanced configurations
# localIdentifier: # <string> (Default: null) Needed if you need to run multiple instances of local.
# forceLocal: true # <boolean> (Default: false) Set to true if you need to resolve all your traffic via BrowserStack Local tunnel.
# Entire list of arguments available here -> https://www.browserstack.com/docs/automate/selenium/manage-incoming-connections

# ===================
# Debugging features
# ===================
debug: false # <boolean> # Set to true if you need screenshots for every selenium command ran
networkLogs: false # <boolean> Set to true to enable HAR logs capturing
consoleLogs: errors # <string> Remote browser's console debug levels to be printed (Default: errors)
# Available options are `disable`, `errors`, `warnings`, `info`, `verbose` (Default: errors)

selfHeal: false # Set to true if you want to enable self-healing capabilities in your tests
47 changes: 47 additions & 0 deletions android/testng-examples/build.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
plugins {
id 'java'
}

repositories { mavenCentral() }

dependencies {
testImplementation 'org.testng:testng:7.5'
implementation 'org.seleniumhq.selenium:selenium-java:4.13.0'
implementation 'io.appium:java-client:8.6.0'
implementation 'commons-io:commons-io:2.11.0'
implementation 'com.googlecode.json-simple:json-simple:1.1.1'
implementation 'com.browserstack:browserstack-java-sdk:latest.release'
}

group = 'com.browserstack'
version = '1.0-SNAPSHOT'
description = 'testng-browserstack'
sourceCompatibility = '1.8'

def browserstackSDKArtifact = configurations.compileClasspath.resolvedConfiguration.resolvedArtifacts.find { it.name == 'browserstack-java-sdk' }

tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}

tasks.withType(Test) {
systemProperties = System.properties
}

task sampleBaseAppTest(type: Test) {
useTestNG() {
dependsOn cleanTest
useDefaultListeners = true
suites "src/test/resources/com/browserstack/sample-base-app-test.testng.xml"
jvmArgs "-javaagent:${browserstackSDKArtifact.file}"
}
}

task sampleSelfHealAppTest(type: Test) {
useTestNG() {
dependsOn cleanTest
useDefaultListeners = true
suites "src/test/resources/com/browserstack/sample-self-heal-app-test.testng.xml"
jvmArgs "-javaagent:${browserstackSDKArtifact.file}"
}
}
127 changes: 127 additions & 0 deletions android/testng-examples/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.browserstack</groupId>
<artifactId>testng-browserstack-android</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>

<name>testng-appium-app</name>
<url>https://github.com/browserstack/selfheal-demo-browserstack</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.target>1.8</maven.compiler.target>
<maven.compiler.source>1.8</maven.compiler.source>
<surefire.version>2.19.1</surefire.version>
<surefire.plugin.version>3.0.0-M5</surefire.plugin.version>
<config.file>default</config.file>
</properties>

<dependencies>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>7.5</version>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>4.13.0</version>
</dependency>
<dependency>
<groupId>io.appium</groupId>
<artifactId>java-client</artifactId>
<version>8.6.0</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>
<dependency>
<groupId>com.browserstack</groupId>
<artifactId>browserstack-java-sdk</artifactId>
<version>LATEST</version>
<scope>compile</scope>
</dependency>
</dependencies>

<build>
<plugins>
<plugin>
<artifactId>maven-dependency-plugin</artifactId>
<version>3.3.0</version>
<executions>
<execution>
<id>getClasspathFilenames</id>
<goals>
<goal>properties</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.22.2</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/com/browserstack/sample-base-app-test.testng.xml</suiteXmlFile>
</suiteXmlFiles>
<argLine>-javaagent:${com.browserstack:browserstack-java-sdk:jar}</argLine>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>

<profiles>
<profile>
<id>sampleBaseAppTest</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/com/browserstack/sample-base-app-test.testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
</plugins>
</build>
</profile>
<profile>
<id>sampleSelfHealAppTest</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/com/browserstack/sample-self-heal-app-test.testng.xml</suiteXmlFile>
</suiteXmlFiles>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>
16 changes: 16 additions & 0 deletions android/testng-examples/settings.gradle
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
pluginManagement {
repositories {
mavenCentral()
mavenLocal()
gradlePluginPortal()
}

resolutionStrategy {
eachPlugin {
if (requested.id.id == "com.browserstack.gradle-sdk") {
useModule("com.browserstack:gradle-sdk:1.1.2")
}
}
}
}
rootProject.name = 'testng-browserstack-android'
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package com.browserstack;

import java.net.URL;

import org.openqa.selenium.MutableCapabilities;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;

import io.appium.java_client.android.AndroidDriver;
import io.appium.java_client.android.options.UiAutomator2Options;


public class AppiumTest {

public AndroidDriver driver;

@BeforeMethod(alwaysRun=true)
public void setUp() throws Exception {
MutableCapabilities capabilities = new UiAutomator2Options();
driver = new AndroidDriver(new URL("http://127.0.0.1:4723/wd/hub"),capabilities);
}

@AfterMethod(alwaysRun=true)
public void tearDown() throws Exception {
driver.quit();
}
}
Loading