WebdriverIO
Documentation for running Appium automated mobile app tests with BrowserStack.
Getting Started
BrowserStack supports Appium automated mobile app tests using WebdriverIO, and running your tests on our cloud setup is simple and straightforward. Follow 3 easy steps to get started with your first Appium test on BrowserStack cloud.
Step 1: Upload your app
Upload your Android app (.apk file) or iOS app (.ipa file) to the BrowserStack servers using the REST API.
curl -u "USERNAME:ACCESS_KEY" \ -X POST "https://api-cloud.browserstack.com/app-automate/upload" \ -F "file=@/path/to/app/file/Application-debug.apk"
Please note the App URL (bs://<hashed appid>) returned in the response of this call.
Upload app from a Public Location
If you do not have your app file on the local machine from where you are running the test and it is hosted on a different location, you can upload it to the BrowserStack servers from any public hosted location. You can achieve that by just providing the app public url in the API call to upload an app. The url should be accessible over the internet so that BrowserStack can directly upload it from that location. Use the below API call to upload app from a publicly accessible location.
curl -u "USERNAME:ACCESS_KEY" -X POST "https://api-cloud.browserstack.com/app-automate/upload" -F "data={\"url\": \"https://www.browserstack.com/app-automate/sample-apps/android/WikipediaSample.apk\"}"
Define Custom Id for your app
If you would like to set a constant value in your 'app' capability instead updating your test code to change the App URL everytime you upload an app, define a Custom Id for your apps. Use the same Custom Id for every build you upload. Custom Id is optional.
curl -u "USERNAME:ACCESS_KEY" \ -X POST "https://api-cloud.browserstack.com/app-automate/upload" \ -F "file=@/path/to/app/file/Application-debug.apk" \ -F "data={\"custom_id\": \"MyApp\"}"
Sample response of the API call
{"custom_id":"MyApp", "app_url":"bs://<hashed appid>", "shareable_id":"USERNAME/MyApp"}
You can use either of the above values in the 'app' capability of your test.
custom_id: If you use custom_id value in the 'app' capability, Appium will pick the latest app uploaded by you using that custom_id. For example, if you upload 3 different builds of your app using the same custom_id, and if you are using custom_id in your 'app' capability, Appium will pick the last uploaded build and execute your test.
shareable_id: If you would like some other user with in your group to run test using the app uploaded by you, provide the shareable_id to that user. The user can set shareable_id value in the 'app' capability and run the test.
Step 2: Setup environment
Refer our sample repo on Github: webdriverio-appium-app-browserstack. Update the desired capability "app" with the App URL returned from the above API call. For the code to run successfully on your machine, please ensure that the following libraries have been installed:
# Install using npm npm install webdriverio
Step 3: Configure and run test
Here is a sample test case written for running with WebdriverIO.
If you are using our Sample App, the sample test below will install the Sample App (Wikipedia App) on the device, search for 'browserstack' and asserts for the list of results. If you are using your own app, modify the code as per your test cases.
var assert = require('assert'); describe('Search Wikipedia Functionality', function () { it('can find search results', function () { var searchSelector = `~Search Wikipedia`; browser.waitForVisible(searchSelector, 30000); browser .element(searchSelector) .click(); var insertTextSelector = 'android=new UiSelector().resourceId("org.wikipedia.alpha:id/search_src_text")'; browser.waitForVisible(insertTextSelector); browser .element(insertTextSelector) .keys('BrowserStack') .pause(5000); var allProductsName = browser.elements(`android.widget.TextView`).value; assert(allProductsName.length > 0); }); });
If you are using our Sample App, the sample test below will install the Sample App (WordPress App) on the device, navigate to the Login screen, enters the login email and check whether the email is registered on WordPress. If you are using your own app, modify the code as per your test cases.
var assert = require('assert'); describe('Text Verification', function () { it('should match displayed text with input text', function () { var textButton = `~Text Button`; browser.waitForVisible(textButton, 30000); browser .element(textButton) .click(); var textInput = `~Text Input`; browser.waitForVisible(textInput, 30000); browser .element(textInput) .click() .keys("hello@browserstack.com"+"\n"); var textOutput = `~Text Output`; browser.waitForVisible(textOutput, 30000); var value = browser.getText(textOutput) if (value === "hello@browserstack.com") assert(true) else assert(false) }); });
To actually run the test case, we need to integrate with BrowserStack as follows.
Integration with BrowserStack
Integration of WebdriverIO with BrowserStack is made possible by use of following module:
exports.config = { user: 'USERNAME', key: 'ACCESS_KEY', capabilities: [{ name: 'single_appium_test', build: 'webdriver-browserstack', device: 'Google Pixel', app: process.env.BROWSERSTACK_APP_ID || 'bs://<hashed app-id>', 'browserstack.debug': true }]
exports.config = { user: 'USERNAME', key: 'ACCESS_KEY', capabilities: [{ name: 'single_appium_test', build: 'webdriver-browserstack', device: 'iPhone 7', app: process.env.BROWSERSTACK_APP_ID || 'bs://<hashed app-id>', 'browserstack.debug': true }]
Run your test on BrowserStack using following command:
# Run using npm npm run single
Testing on Internal Networks
To test a private server with WebdriverIO on BrowserStack, install local bindings. In order to try a local test, upload our Local Sample App for Android and iOS
# Install using npm npm install browserstack-local
Then update config file and set the browserstack.local capability to true.
var browserstack = require('browserstack-local'); exports.config = { user: 'USERNAME', key: 'ACCESS_KEY', capabilities: [{ name: 'local_appium_test', build: 'webdriver-browserstack', device: 'Google Pixel', browserName: 'android', app: process.env.BROWSERSTACK_APP_ID || 'bs://<hashed app-id>', 'browserstack.local': true, 'browserstack.debug': true }], // Code to start browserstack local before start of test onPrepare: function (config, capabilities) { console.log("Connecting local"); return new Promise(function(resolve, reject){ exports.bs_local = new browserstack.Local(); exports.bs_local.start({'key': exports.config.key }, function(error) { if (error) return reject(error); console.log('Connected. Now testing...'); resolve(); }); }); }, // Code to stop browserstack local after end of test onComplete: function (capabilties, specs) { exports.bs_local.stop(function() {}); } };
Here is a sample test case written for running local with WebdriverIO.
describe('BrowserStack Local Testing', function () { it('can check tunnel working', function () { var searchSelector = 'android=new UiSelector().resourceId("com.example.android.basicnetworking:id/test_action")'; browser.waitForVisible(searchSelector, 30000); browser .element(searchSelector) .click(); var insertTextSelector = `android.widget.TextView`; browser.waitForVisible(insertTextSelector, 30000); var allTextElements = browser.elements(`android.widget.TextView`).value; browser.pause(10000); var testElement = null; allTextElements.forEach(function (textElement) { var textContent = browser.elementIdText(textElement['ELEMENT']).value; if (textContent.indexOf('The active connection is') !== -1) { testElement = textElement; } }); if (testElement === null) { var screenshotPath = path.resolve(__dirname, 'screenshot.png'); browser.saveScreenshot(screenshotPath); console.log('Screenshot stored at ' + screenshotPath); throw new Error('Cannot find the needed TextView element from app'); } var matchedString = browser.elementIdText(testElement['ELEMENT']).value; console.log(matchedString); assert(matchedString.indexOf('The active connection is wifi') !== -1); assert(matchedString.indexOf('Up and running') !== -1); }); });
var browserstack = require('browserstack-local'); exports.config = { user: 'USERNAME', key: 'ACCESS_KEY', capabilities: [{ name: 'local_appium_test', build: 'webdriver-browserstack', device: 'iPhone 7', app: process.env.BROWSERSTACK_APP_ID || 'bs://<hashed app-id>', 'browserstack.local': true, 'browserstack.debug': true }], // Code to start browserstack local before start of test onPrepare: function (config, capabilities) { console.log("Connecting local"); return new Promise(function(resolve, reject){ exports.bs_local = new browserstack.Local(); exports.bs_local.start({'key': exports.config.key }, function(error) { if (error) return reject(error); console.log('Connected. Now testing...'); resolve(); }); }); }, // Code to stop browserstack local after end of test onComplete: function (capabilties, specs) { exports.bs_local.stop(function() {}); } };
Here is a sample test case written for running local with WebdriverIO.
describe('BrowserStack Local Testing', function () { it('can check tunnel working', function () { var searchSelector = `~Test BrowserStackLocal connection`; browser.waitForVisible(searchSelector, 30000); browser .element(searchSelector) .click(); var responseText = `~Response is: Up and running`; browser.waitForVisible(responseText, 30000); var allTextElements = browser.elements(responseText).value; var testElement = null; allTextElements.forEach(function (textElement) { var textContent = browser.elementIdText(textElement['ELEMENT']).value; if (textContent.indexOf('Up and running') !== -1) { testElement = textElement; } }); if (testElement === null) { var screenshotPath = path.resolve(__dirname, 'screenshot.png'); browser.saveScreenshot(screenshotPath); console.log('Screenshot stored at ' + screenshotPath); throw new Error('Cannot find the Up and running response'); } var matchedString = browser.elementIdText(testElement['ELEMENT']).value; assert(matchedString == 'Response is: Up and running'); }); });
Run your local test on BrowserStack using following command:
# Run using npm npm run local
Speed Up Testing
To run tests on multiple browsers in parallel with JUnit on BrowserStack, modify the config file as below:
exports.config = { user: 'USERNAME', key: 'ACCESS_KEY', capabilities: [{ device: 'Google Pixel' }, { device: 'Samsung Galaxy S7' }, { device: 'Samsung Galaxy S6' }, { device: 'Google Nexus 9' }], // Code to support common capabilities exports.config.capabilities.forEach(function(caps){ for(var i in exports.config.commonCapabilities) caps[i] = caps[i] || exports.config.commonCapabilities[i]; });
exports.config = { user: 'USERNAME', key: 'ACCESS_KEY', capabilities: [{ "device": "iPhone 7" }, { "device": "iPhone 7 Plus" }], // Code to support common capabilities exports.config.capabilities.forEach(function(caps){ for(var i in exports.config.commonCapabilities) caps[i] = caps[i] || exports.config.commonCapabilities[i]; });
Run your tests in parallel on BrowserStack using following command:
# Run using paver npm run parallel
Configuring Capabilities
Capabilities are a series of key-value pairs that allow customization of testing from within BrowserStack Automate.
Appium provides a series of capabilities that you can set for the Appium version you are running. Appium server on the BrowserStack will receive all the capabilities you set on the client side. You can also use BrowserStack specific capabilities to configure your tests. Visit Capabilities page to view the complete list of BrowserStack capabilities.
Use the drop down below to select your device and configure the capabilities.
N/A
Additional Notes
REST API
It is possible to mark tests as either a pass or a fail, using the following snippet:
var request = require("request"); request({uri: "https://USERNAME:ACCESS_KEY@api-cloud.browserstack.com/app-automate/sessions/<session-id>.json", method:"PUT", form:{"status":"completed","reason":""}})
The two potential values for status can either be completed or error. Optionally, a reason can also be passed.
Queuing
With queuing, you can launch an additional number of parallel tests with different browser configurations that will be queued in a sequence, for a seamless parallel execution. For instance, if you want to run 5 additional tests, apart from your subscribed limit of 2 parallel tests, BrowserStack will queue the additional 5 tests until one of the 2 initial tests finish, and a slot is available for execution. With queuing, you can be less bothered about managing your tests, and it can save development time.
With this feature, accounts up to 5 parallel tests can queue 5 tests. Beyond 5 parallel tests, an equivalent number of tests will be queued.