Getting Started With Visual Regression Testing Using Appium On SmartUI Real Devices (NodeJS)
Using the LambdaTest platform, perform regression testing in just one click and find Visual UI Regression bugs easily with the help of Smart Testing. This documentation will act as your step-by-step guide in performing successful Visual Regression tests.
Prerequisites for SmartUI with App Automationβ
- Basic understanding of appium and remote WebDriver is required.
- Go to
LambdaTest SmartUIand login along with your credentials. - Access your Hub for your appium remote connection instance at
@mobile-hub.lambdatest.com/wd/hub. - Copy
LT_USERNAMEandLT_ACCESS_KEYcredentials fromAccess Keybutton on the top right of the dashboard.
Below are code examples for taking viewport screenshots using SmartUI with Appium across different programming languages and frameworks:
- MacOS/Linux
- Windows - CMD
- PowerShell
export LT_USERNAME="YOUR_USERNAME"
set LT_USERNAME="YOUR_USERNAME"
$env:LT_USERNAME="YOUR_USERNAME"
The following steps will guide you in running your first Visual Regression test on LambdaTest platform -
Step 1: Create a SmartUI Projectβ
The first step is to create a project with the application in which we will combine all your builds run on the project. To create a SmartUI Project, follow these steps:
- Go to Projects page
- Click on the
new projectbutton - Select the platform as Real Device for executing your
Appiumtests. - Add name of the project, approvers for the changes found, tags for any filter or easy navigation.
- Click on the Submit.
Step 2: Upload your applicationβ
Upload your iOS application (.ipa file) or android application (.apk file) to the LambdaTest servers using our REST API. You need to provide your Username and AccessKey in the format Username:AccessKey in the cURL command for authentication. Make sure to add the path of the appFile in the cURL request. Here is an example cURL request to upload your app using our REST API:
- App File
- App URL
curl -u "undefined:undefined" -X POST "https://manual-api.lambdatest.com/app/upload/realDevice" -F "appFile=@"/Users/macuser/Downloads/proverbial_android.apk"" -F "name="proverbial_app""
curl -u "undefined:undefined" -X POST "https://manual-api.lambdatest.com/app/upload/realDevice" -F "url=:https://prod-mobile-artefacts.lambdatest.com/assets/docs/proverbial_android.apk" -F "name=Proverbial_App"
- If you do not have any .apk or .ipa file, you can run your sample tests on LambdaTest by using our sample π Android app or sample π iOS app.
- Response of above cURL will be a JSON object containing the
APP_URLof the format -lt://APP123456789123456789and will be used in the next step.
Step 3: Clone the sample projectβ
Clone the LambdaTestβs π LT-appium-nodejs repository and navigate to the code directory as shown below:
git clone https://github.com/LambdaTest/LT-appium-nodejs
cd LT-appium-nodejs
Step 4: Set up your authenticationβ
Make sure you have your LambdaTest credentials with you to run test automation scripts on LambdaTest. To obtain your access credentials, purchase a plan or access the Automation Dashboard. Then, set LambdaTest Username and Access Key in environment variables with following commands.
- Linux / MacOS
- Windows
export LT_USERNAME=undefined \
export LT_ACCESS_KEY=undefined
set LT_USERNAME=undefined `
set LT_ACCESS_KEY=undefined
Step 5: Configure your test with Appium Desired Capabilitiesβ
To view and generate more capabilities for your appium application test suite, please see the capability generator here: https://www.lambdatest.com/capabilities-generator/
Once you have created a SmartUI Project, you can generate screenshots by running automation scripts. Edit the required capabilities for your test suite as shown in the below sample code snippet:
let capabilities = {
deviceName: "iPhone 12", // Configure your Device for appium test (Mandatory)
platformName: "ios", // Configure your OS for appium test (Mandatory)
platformVersion: "14", // Configure your OS Version for appium test (Mandatory)
isRealMobile: true, // Configure if you want to test in a real-device (Mandatory)
app: "APP_URL", // Set your uploaded App URL for testing (Mandatory)
visual: true, // Configure your Capture screenshot for appium test (Mandatory)
name: "testing app session ", // Name of the test for appium (Recommended)
build: "Real Device App Build", // Name of the build for appium (Recommended)
"smartUI.project": "<Your Project Name>", // Replace the name of project with the new project name (Mandatory)
"smartUI.build": "<Your Build Name>", // Replace the name of Build with the new Build name (Optional)
"smartUI.baseline": false, // Enable if you want to update to a new baseline build (Optional)
"smartUI.cropStatusBar" : true, // Optional (By default true)
"smartUI.cropFooter" : true, // Optional (By default false)
};
// Connecting to the Lambdatest appium Cloud Grid with SmartUI
let gridUrl =
"https://" +
"<Your Username>" +
":" +
"<Your Access Key>" +
`@mobile-hub.lambdatest.com/wd/hub`;
// Here is your Remote WebDrive Connection
let driver = await new webdriver.Builder()
.usingServer(gridUrl)
.withCapabilities(capabilities)
.build();
- Webhook for taking the screenshot - This part of the code needs to be attached below the required segment of appium script of which we would like to take the screenshot to test on.
driver.execute("smartui.takeScreenshot=<Name of your screenshot>");
- Execute your test suite as per the execution command depending on your framework or language.
npm i && node your_test_script.js
- You can check the executed builds over at LambdaTest SmartUI.
Smart Crop With SmartUIβ
The all-new Real Device mobile notification status bar and navigation bar crop feature in SmartUI allows you to take your visual regression testing workflows to the next level. With Smart Crop, you can crop the status bar and navigation bar or footer from screenshots, enabling them to focus solely on the core UI elements during visual comparisons.
By leveraging machine learning algorithms, it accurately detects and crops the status bar and navigation bar from screenshots. With precise image processing techniques, SmartUI precisely identifies the location of status bar elements. By excluding it from visual comparisons, the focus is solely on critical UI elements.
Original Screenshot:β
Cropped Screenshotβ
Region-Based Ignore/Select for Dynamic Content (Advanced)β
To handle dynamic content like timestamps, user names, ads, or banners that cause false positives in visual comparisons, SmartUI supports region-based ignore and select functionality using XPath locators.
You can either:
- Ignore specific regions during comparison using
ignoreBoxes - Compare only specific regions using
selectBoxes
This is especially useful for enterprise applications where certain UI elements change dynamically between test runs.
Usage in Node.js (Primary Example)β
let config = {
screenshotName: 'Home Screen',
ignoreBoxes: JSON.stringify({
xpath: [
"//*[@text='Backpack']",
"//*[@text='Onesie']",
"//*[@text='PRODUCTS']",
"//*[@text='Terms of Service | Privacy Policy']"
]
})
};
await driver.execute("smartui.takeScreenshot", config);
let config = {
screenshotName: 'Checkout Form',
selectBoxes: JSON.stringify({
xpath: [
"//*[@resource-id='checkout-form']",
"//*[@resource-id='total-amount']"
]
})
};
await driver.execute("smartui.takeScreenshot", config);
Cross-Framework Examplesβ
- Node.js
- Python
- Java
- C#
- Ruby
let config = {
screenshotName: '<Your Screenshot Name>',
ignoreBoxes: JSON.stringify({
xpath: ["//*[@text='Dynamic Ad']", "//*[@id='timestamp']"]
})
};
await driver.execute("smartui.takeScreenshot", config);
config = {
'screenshotName': '<Your Screenshot Name>',
'ignoreBoxes': '{"xpath": ["//*[@text=\'Dynamic Ad\']", "//*[@id=\'timestamp\']"]}'
}
driver.execute_script("smartui.takeScreenshot", config)
Map<String, Object> configIgnore = new HashMap<>();
configIgnore.put("screenshotName", "Screenshot");
Map<String, Object> ignoreBoxes = new HashMap<>();
ignoreBoxes.put("xpath", new String[]{
"//*[@name='Toast']"
});
configIgnore.put("ignoreBoxes", ignoreBoxes);
((JavascriptExecutor) driver).executeScript("smartui.takeScreenshot", configIgnore);
var config = new Dictionary<string, object> {
{"screenshotName", "<Your Screenshot Name>"},
{"ignoreBoxes", "{\"xpath\": [\"//*[@text='Dynamic Ad']\", \"//*[@id='timestamp']\"]}"}
};
driver.ExecuteScript("smartui.takeScreenshot", config);
config = {
'screenshotName' => '<Your Screenshot Name>',
'ignoreBoxes' => '{"xpath": ["//*[@text=\'Dynamic Ad\']", "//*[@id=\'timestamp\']"]}'
}
driver.execute_script("smartui.takeScreenshot", config)
Configuration Keysβ
| Key | Type | Description | Required |
|---|---|---|---|
ignoreBoxes | JSON String | Defines regions to ignore during visual comparison. Accepts XPath locators. | No |
selectBoxes | JSON String | Defines regions to include in visual comparison. Accepts XPath locators. | No |
- Use
ignoreBoxesfor elements that change frequently (e.g., ads, timestamps, user avatars). - Use
selectBoxeswhen you want to focus comparison only on critical UI sections. - Avoid using both
ignoreBoxesandselectBoxesin the same config β they are mutually exclusive. - Ensure XPath expressions are unique and stable across test runs.
- Test your XPath locators using Appium Inspector or similar tools before integrating.
Running Tests on Other Languages and Frameworksβ
In this module we discussed about running smart visual tests on NodeJS, here we will know more about running those tests for any language or framework with appium.
In a similar way, we can run visual tests for other languages and frameworks using their corresponding script executing commands. To understand better, we provided the commands for some of the popular languages and frameworks:
For taking viewport screenshotβ
This part of the code needs to be attached below the required segment of selenium script of which we would like to take the screenshot to test on.
- NodeJS
- Python
- Ruby
- C#
- Java
driver.execute("smartui.takeScreenshot=<Name of your screenshot>");
driver.execute("smartui.takeScreenshot=<Your Screenshot Name>")
driver.execute("smartui.takeScreenshot=<Your Screenshot Name>")
driver.Execute("smartui.takeScreenshot=<Your Screenshot Name>");
((JavascriptExecutor)driver).executeScript("smartui.takeScreenshot=<Your Screenshot Name>");
For capturing full page screenshot in Native Apps BETAβ
You can capture the full page screenshot for apps which have a scrolling functionality on their application user interface for your Appium functional testing.
Add the following Webhook to your test cases where we need to capture the screenshot of your application.
- NodeJS
- Python
- C#
- Java
let config = {
screenshotName: '<Name of your screenshot>',
fullPage: true,
pageCount: 15 // Enter the number of pages for the Full Page screenshot (Minimum 1, Maximum 20)
};
await driver.execute("smartui.takeScreenshot", config);
config = {
'screenshotName': '<Your Screenshot Name>',
'fullPage': True,
'pageCount': 15 # Enter the number of pages for the Full Page screenshot (Minimum 1, Maximum 20)
}
driver.execute("smartui.takeScreenshot", config)
<TabItem value='ruby-2' label='Ruby' default>
```ruby
config = {
'screenshotName' => '<Your Screenshot Name>',
'fullPage': true,
'pageCount': 15 # Enter the number of pages for the Full Page screenshot (Minimum 1, Maximum 20)
}
driver.execute("smartui.takeScreenshot", config)
var config = new Dictionary<string, string> {
{"screenshotName", "<Your Screenshot Name>"},
{"fullPage", true},
{"pageCount", 15} // Enter the number of pages for the Full Page screenshot (Minimum 1, Maximum 20)
};
driver.Execute("smartui.takeScreenshot", config);
Map<String, Object> config = new HashMap<>();
config.put("screenshotName", "<Your Screenshot Name>");
config.put("fullPage", true);
config.put("pageCount", 15); // Enter the number of pages for the Full Page screenshot (Minimum 1, Maximum 20)
((JavascriptExecutor)driver).executeScript("smartui.takeScreenshot", config);
Please note that this webhook is only applicable to native app screenshots and has known limitations. You can use an optimized value of page count (between 1 and 20) to get the best results of your full page screenshots, according to your use case.
Best Practicesβ
- Screenshot Naming
- Wait for Screen Load
- Handle Dynamic Content
- Smart Crop Configuration
- Test Organization
- Test Organization
Screenshot Naming
- Use descriptive, consistent names for screenshots
- Include screen/component name in screenshot names
- Avoid special characters that might cause issues
- Use consistent naming conventions across your test suite
Example:
await driver.execute("smartui.takeScreenshot=HomeScreen-Header");
await driver.execute("smartui.takeScreenshot=CheckoutScreen-PaymentForm");
Wait for Screen Load
- Always wait for screens to fully load before taking screenshots
- Use Appium's wait methods for dynamic content
- Consider device-specific loading times
Example:
const { until, By } = require('selenium-webdriver');
await driver.wait(until.elementLocated(By.id('main-content')), 10000);
await driver.execute("smartui.takeScreenshot=Screen Loaded");
Handle Dynamic Content
- Use
ignoreBoxesfor elements that change between runs (ads, timestamps, user avatars) - Use
selectBoxeswhen you only need to compare specific regions - Test XPath locators using Appium Inspector before integrating
Smart Crop Configuration
- Enable
cropStatusBarto focus on core UI elements - Enable
cropNavigationBarfor Android devices - Test cropped screenshots to ensure important content isn't removed
Test Organization
- Group related screenshots in the same build
- Use meaningful build names
- Run tests on consistent device configurations
Test Organization
- Group related screenshots in the same build
- Use meaningful build names
- Run tests on consistent device configurations
Troubleshootingβ
- Screenshots Not Captured
- Project Not Found Error
- Screenshots Show Blank or Incorrect Content
- Full Page Screenshot Issues
- ignoreBoxes/selectBoxes Not Working
Issue: Screenshots Not Captured
Symptoms: Tests run but no screenshots appear in SmartUI dashboard
Possible Causes:
visual: truenot set in capabilities- Incorrect project name
- Network connectivity issues
- Credentials not set correctly
Solutions:
-
Verify
visual: trueis set in capabilities:let capabilities = {
visual: true, // Must be set
// ... other capabilities
}; -
Check project name matches exactly (case-sensitive):
"smartUI.project": "ExactProjectName" -
Verify credentials are set:
echo $LT_USERNAME
echo $LT_ACCESS_KEY -
Check network connectivity to LambdaTest
Issue: "Project Not Found" Error
Symptoms: Error indicating SmartUI project cannot be found
Possible Causes:
- Project name typo or mismatch
- Project deleted
- Wrong account credentials
Solutions:
- Verify project exists in SmartUI dashboard
- Copy project name directly from dashboard
- Check credentials match the account with the project
- Ensure project name is in capabilities, not just in dashboard
Issue: Screenshots Show Blank or Incorrect Content
Symptoms: Screenshots captured but show blank screens or incorrect content
Possible Causes:
- Screen not fully loaded
- App state issues
- Timing issues
- Device-specific rendering
Solutions:
-
Add explicit waits before screenshots:
await driver.wait(until.elementLocated(By.id('content')), 10000); -
Wait for specific elements to be visible:
await driver.wait(until.elementIsVisible(By.id('main-content')), 10000); -
Increase wait time for slow-loading screens
-
Verify app is in correct state before screenshot
Issue: Full Page Screenshot Issues
Symptoms: Full page screenshots incomplete or incorrect
Possible Causes:
pageCountvalue too low- App doesn't support scrolling
- Content not loading properly
Solutions:
-
Increase
pageCountvalue (between 1-20):let config = {
screenshotName: 'Full Page',
fullPage: true,
pageCount: 15 // Increase if needed
}; -
Verify app supports scrolling functionality
-
Test with different
pageCountvalues to find optimal setting
Issue: ignoreBoxes/selectBoxes Not Working
Symptoms: Dynamic content still causing false positives
Possible Causes:
- XPath locators incorrect
- Elements not found at screenshot time
- JSON string formatting issues
Solutions:
-
Verify XPath locators using Appium Inspector
-
Ensure elements exist at screenshot time
-
Check JSON string formatting:
ignoreBoxes: JSON.stringify({
xpath: ["//*[@text='Dynamic Ad']"]
}) -
Test XPath locators in isolation before using in config
Getting Help
If you encounter issues not covered here:
- Review the Comprehensive Troubleshooting Guide for detailed solutions
- Check SmartUI Configuration Options documentation
- See Handling Dynamic Data for dynamic content issues
- Visit LambdaTest Support for additional resources
- Contact support at support@lambdatest.com or use 24/7 Chat Support
Additional Resourcesβ
- Comprehensive Troubleshooting Guide
- SmartUI Configuration Options
- Handling Dynamic Data
- Baseline Management
- Running Your First Project
- Appium Documentation
For additional information about appium framework please explore the documentation here
