diff --git a/.gitignore b/.gitignore index b7ba3e9..36f7206 100644 --- a/.gitignore +++ b/.gitignore @@ -7,3 +7,5 @@ pabot_results/ .pabotsuitenames .DS_Store *.png +browserstack.err +env diff --git a/README.md b/README.md index 32bd691..cee6047 100644 --- a/README.md +++ b/README.md @@ -2,46 +2,60 @@ ![BrowserStack Logo](https://d98b8t1nnulk5.cloudfront.net/production/images/layout/logo-header.png?1469004780) -## Setup -* Clone the repo -* Install dependencies `pip install -r requirements.txt` - -## Set BrowserStack Credentials -* Export the BrowserStack username and access key as environment variables +## Prerequisite +``` +python3 should be installed +``` -#### For Linux/MacOS +## Setup +* Clone the repo ``` - export BROWSERSTACK_USERNAME= - export BROWSERSTACK_ACCESS_KEY= + git clone -b sdk https://github.com/browserstack/robot-browserstack.git ``` -#### For Windows +* It is recommended to use a virtual environment to install dependencies. To create a virtual environment: ``` - setx BROWSERSTACK_USERNAME= - setx BROWSERSTACK_ACCESS_KEY= + python3 -m venv env + source env/bin/activate # on Mac + env\Scripts\activate # on Windows ``` +* Install dependencies + ``` + pip install -r requirements.txt + ``` + +## Set BrowserStack Credentials +* Add your BrowserStack username and access key in the `browserstack.yml` config fle. +* You can also export them as environment variables, `BROWSERSTACK_USERNAME` and `BROWSERSTACK_ACCESS_KEY`: + + #### For Linux/MacOS + ``` + export BROWSERSTACK_USERNAME= + export BROWSERSTACK_ACCESS_KEY= + ``` + #### For Windows + ``` + set BROWSERSTACK_USERNAME= + set BROWSERSTACK_ACCESS_KEY= + + setx BROWSERSTACK_USERNAME= + setx BROWSERSTACK_ACCESS_KEY= + ``` ## Running tests -* To run local test, run `robot tests/LocalTest.robot` -* To run parallel tests we will be using the [Pabot](https://pabot.org/) library: - 1. To run test suites in parallel (Testcases within respective test suites will be sequential) - * Run - `pabot --processes tests/parallel/*.robot` - * Alternate method: `pabot --processes ` -
Eg: `pabot --processes 2 tests/parallel/Suite01.robot tests/parallel/Suite02.robot` - 2. To run all test cases within a test suite in parallel - * Run - `pabot --testlevelsplit ` -
Eg: `pabot --testlevelsplit tests/parallel/Suite01.robot` - 3. Run all testcases across all Test Suites in parallel - * Run - `pabot --testlevelsplit --processes tests/parallel/*.robot` -
**Note: If the process count exceeds the parallel threads available on BrowserStack, the sessions will automatically get queued.** +* To run sample tests: + - To run the sample tests in parallel across the platforms defined in the `browserstack.yml` file, run: + ``` + browserstack-sdk robot ./tests/test-*.robot + ``` +* To run tests on locally hosted websites: + - To run the local test in parallel across the platforms defined in the `browserstack.yml` file, run: + ``` + browserstack-sdk robot ./tests/local-test.robot + ``` Understand how many parallel sessions you need by using our [Parallel Test Calculator](https://www.browserstack.com/automate/parallel-calculator?ref=github) -## Notes -* This repository only works for Selenium 3 as of now. Desired Capabilities do not get honoured for Selenium 4. The open issue on SeleniumLibrary can be found [here](https://github.com/robotframework/SeleniumLibrary/issues/1774). -* You can view your test results on the [BrowserStack Automate dashboard](https://www.browserstack.com/automate) -* To test on a different set of browsers, check out our [platform configurator](https://www.browserstack.com/automate/capabilities) - ## Additional Resources * [Documentation for writing Automate test scripts in Python](https://www.browserstack.com/automate/python) * [Customizing your tests on BrowserStack](https://www.browserstack.com/automate/capabilities) diff --git a/browserstack.yml b/browserstack.yml new file mode 100644 index 0000000..850bb7d --- /dev/null +++ b/browserstack.yml @@ -0,0 +1,74 @@ +# ============================= +# Set BrowserStack Credentials +# ============================= +# Add your BrowserStack userName and accessKey here or set BROWSERSTACK_USERNAME and +# BROWSERSTACK_ACCESS_KEY as env variables +userName: YOUR_USERNAME +accessKey: YOUR_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} + +# ======================================= +# 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: + - os: OS X + osVersion: Big Sur + browserName: Chrome + browserVersion: latest + - os: Windows + osVersion: 10 + browserName: Edge + browserVersion: latest + - deviceName: Samsung Galaxy S22 Ultra + browserName: chrome # Try 'samsung' for Samsung browser + osVersion: 12.0 + +# ======================= +# 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 # (Default false) +# browserStackLocalOptions: +# Options to be passed to BrowserStack local in-case of advanced configurations + # localIdentifier: # (Default: null) Needed if you need to run multiple instances of local. + # forceLocal: true # (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 + +source: robot-browserstack:sample-sdk:v1.0 + +# =================== +# Debugging features +# =================== +debug: false # # Set to true if you need screenshots for every selenium command ran +networkLogs: false # Set to true to enable HAR logs capturing +consoleLogs: errors # Remote browser's console debug levels to be printed (Default: errors) +# Available options are `disable`, `errors`, `warnings`, `info`, `verbose` (Default: errors) diff --git a/config/Config.py b/config/Config.py deleted file mode 100644 index 1f243f3..0000000 --- a/config/Config.py +++ /dev/null @@ -1,37 +0,0 @@ -import os - -common_caps = { - "browserstack.user" : "BROWSERSTACK_USERNAME", - "browserstack.key" : "BROWSERSTACK_ACCESS_KEY", - "build" : "browserstack-build-1", - "browserstack.debug" : "true" -} - -envs = [{ - "os" : "Windows", - "os_version" : "10", - "browser" : "Chrome", - "browser_version" : "latest" -}, -{ - "os" : "OS X", - "os_version" : "Big Sur", - "browser" : "Safari", - "browser_version" : "latest" -}, -{ - "device" : "Samsung Galaxy S22", - "os_version" : "12" -}] - -def combine_caps(i): - - username = os.environ.get("BROWSERSTACK_USERNAME") - accesskey = os.environ.get("BROWSERSTACK_ACCESS_KEY") - if username != None and accesskey != None: - common_caps["browserstack.user"] = username - common_caps["browserstack.key"] = accesskey - - x = int(i) - envs[x].update(common_caps) - return envs[x] diff --git a/config/KeywordsFile.robot b/config/KeywordsFile.robot deleted file mode 100644 index ded1323..0000000 --- a/config/KeywordsFile.robot +++ /dev/null @@ -1,60 +0,0 @@ -*** Settings *** -Library SeleniumLibrary -Library mark-test-status.py - -*** Variables *** -${remote_url}= https://hub.browserstack.com/wd/hub - -*** Keywords *** -Open Session - [Arguments] ${capabilities} ${test_url} - open browser remote_url=${remote_url} desired_capabilities=${capabilities} url=${test_url} - -Close Session - close browser - -Add Implicit Wait - set selenium implicit wait 5 - -Mark Test Status - [Arguments] ${status} ${reason} - TEST STATUS ${status} ${reason} - -Get the page title - get title - -Click on Sign In - click element id=signin - -Enter Credentials - [Arguments] ${username} ${password} - input text css=#username input ${username} - click element css= .css-1n7v3ny-option - input text css=#password input ${password} - click element css= .css-1n7v3ny-option - -Click on Login - click element id=login-btn - -Verify username - [Arguments] ${assert_username} - ${retrived_username}= get text css=.username - run keyword if "${retrived_username}" == "${assert_username}" mark test status passed Username validated! - run keyword if "${retrived_username}" != "${assert_username}" mark test status failed Username validation failed! - element should contain css=.username ${assert_username} - -Verify site content - ${site_content}= get text css=body - run keyword if "${site_content}" == "Up and running" mark test status passed Site Content validated! - run keyword if "${site_content}" != "Up and running" mark test status failed Site Content validation failed! - element should contain css=body Up and running - -Add first product to cart - click element xpath=//*[@id="1"]/div[4] - -Verify product is added to cart - ${product_name} get text xpath=//*[@id="1"]/p - ${product_incart} get text css=p.title - run keyword if "${product_name}" == "${product_incart}" mark test status passed Correct product added! - run keyword if "${product_name}" != "${product_incart}" mark test status failed Something went wrong! - element should contain css=p.title ${product_name} diff --git a/config/manage-local-testing.py b/config/manage-local-testing.py deleted file mode 100644 index 95f6cc6..0000000 --- a/config/manage-local-testing.py +++ /dev/null @@ -1,19 +0,0 @@ -import os -from robot.libraries.BuiltIn import BuiltIn -from robot.libraries.BuiltIn import _Misc -import robot.api.logger as logger -from robot.api.deco import keyword -from browserstack.local import Local - -access_key = os.getenv("BROWSERSTACK_ACCESS_KEY") -bs_local = Local() - -@keyword("START LOCAL") -def startLocal(): - bs_local_args = {"key": access_key} - bs_local.start(**bs_local_args) - print(bs_local.isRunning()) - -@keyword("STOP LOCAL") -def stopLocal(): - bs_local.stop() diff --git a/config/mark-test-status.py b/config/mark-test-status.py deleted file mode 100644 index 34469c6..0000000 --- a/config/mark-test-status.py +++ /dev/null @@ -1,9 +0,0 @@ -from robot.libraries.BuiltIn import BuiltIn -from robot.libraries.BuiltIn import _Misc -import robot.api.logger as logger -from robot.api.deco import keyword - -@keyword("TEST STATUS") -def testStatus(status, reason): - driver = BuiltIn().get_library_instance('SeleniumLibrary').driver - driver.execute_script('browserstack_executor: {"action": "setSessionStatus", "arguments": {"status":"'+status+'", "reason": "'+reason+'"}}') diff --git a/requirements.txt b/requirements.txt index bf195a4..da7f504 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,5 +1,6 @@ -robotframework -robotframework-seleniumlibrary==5.1.3 +robotframework==6.1.1 +robotframework-seleniumlibrary==6.2.0 robotframework-pabot browserstack-local -selenium==3.141.0 +selenium +browserstack-sdk diff --git a/resources/KeywordsFile.robot b/resources/KeywordsFile.robot new file mode 100644 index 0000000..9bc77a3 --- /dev/null +++ b/resources/KeywordsFile.robot @@ -0,0 +1,30 @@ +*** Settings *** +Library SeleniumLibrary + +*** Variables *** +${remote_url}= http://localhost:4444/wd/hub + +*** Keywords *** +Open Session + [Arguments] ${capabilities} ${test_url} + open browser remote_url=${remote_url} browser=chrome desired_capabilities=${capabilities} url=${test_url} + +Close Session + close browser + +Add Implicit Wait + set selenium implicit wait 5 + +Get the page title + get title + +Verify Local Page + Title Should be BrowserStack Local + +Add first product to cart + click element xpath=//*[@id="1"]/div[4] + +Verify product is added to cart + ${product_name} get text xpath=//*[@id="1"]/p + ${product_incart} get text css=p.title + element should contain css=p.title ${product_name} diff --git a/resources/TestCases.robot b/resources/TestCases.robot new file mode 100644 index 0000000..0459620 --- /dev/null +++ b/resources/TestCases.robot @@ -0,0 +1,10 @@ +*** Settings *** +Library SeleniumLibrary +Resource ./KeywordsFile.robot + +*** Keywords *** +Add to Cart + Add Implicit Wait + Get the page title + Add first product to cart + Verify product is added to cart diff --git a/tests/LocalTest.robot b/tests/LocalTest.robot deleted file mode 100644 index 1f8427b..0000000 --- a/tests/LocalTest.robot +++ /dev/null @@ -1,27 +0,0 @@ -*** Settings *** -Library SeleniumLibrary -Library Collections -Library ../config/manage-local-testing.py -Library ../config/Config.py -Resource ../config/KeywordsFile.robot -Test Setup Setup for local test -Test Teardown Teardown for local test - -*** Variables *** -${local_url}= http://bs-local.com:45691/check - -*** Keywords *** -Setup for local test - START LOCAL - ${final_caps}= combine caps 0 - Set to Dictionary ${final_caps} name=BStack Demo - ${TEST NAME} browserstack.local=true - Open Session ${final_caps} ${local_url} - -Teardown for local test - Close Session - STOP LOCAL - -*** Test Cases *** -Local Test - Add Implicit Wait - Verify site content diff --git a/tests/local-test.robot b/tests/local-test.robot new file mode 100644 index 0000000..c99ca14 --- /dev/null +++ b/tests/local-test.robot @@ -0,0 +1,21 @@ +*** Settings *** +Library SeleniumLibrary +Resource ../resources/KeywordsFile.robot +Test Setup Execute local test +Test Teardown Close Session + + +*** Variables *** +${local_website_url}= http://bs-local.com:45454 +&{test_caps} browser=chrome + + +*** Keywords *** +Execute local test + Open Session ${test_caps} ${local_website_url} + + +*** Test Cases *** +BStack Local Test + Add Implicit Wait + Verify Local Page diff --git a/tests/parallel/Suite01.robot b/tests/parallel/Suite01.robot deleted file mode 100644 index 8137bef..0000000 --- a/tests/parallel/Suite01.robot +++ /dev/null @@ -1,25 +0,0 @@ -*** Settings *** -Library SeleniumLibrary -Library Collections -Library ../../config/Config.py -Resource ../../config/KeywordsFile.robot -Resource ../testcases.robot -Test Setup Execute test -Test Teardown Close Session - -*** Variables *** -${website_url}= https://bstackdemo.com - -*** Keywords *** -Execute test - ${final_caps}= combine caps 0 - Set to Dictionary ${final_caps} name=BStack Demo - ${TEST NAME} - Open Session ${final_caps} ${website_url} - - -*** Test Cases *** -Login Test - Login - -Add to Cart Test - Add to Cart diff --git a/tests/parallel/Suite02.robot b/tests/parallel/Suite02.robot deleted file mode 100644 index ed3d211..0000000 --- a/tests/parallel/Suite02.robot +++ /dev/null @@ -1,25 +0,0 @@ -*** Settings *** -Library SeleniumLibrary -Library Collections -Library ../../config/Config.py -Resource ../../config/KeywordsFile.robot -Resource ../testcases.robot -Test Setup Execute test -Test Teardown Close Session - -*** Variables *** -${website_url}= https://bstackdemo.com - -*** Keywords *** -Execute test - ${final_caps}= combine caps 1 - Set to Dictionary ${final_caps} name=BStack Demo - ${TEST NAME} - Open Session ${final_caps} ${website_url} - - -*** Test Cases *** -Login Test - Login - -Add to Cart Test - Add to Cart diff --git a/tests/parallel/Suite03.robot b/tests/parallel/Suite03.robot deleted file mode 100644 index c730ffb..0000000 --- a/tests/parallel/Suite03.robot +++ /dev/null @@ -1,25 +0,0 @@ -*** Settings *** -Library SeleniumLibrary -Library Collections -Library ../../config/Config.py -Resource ../../config/KeywordsFile.robot -Resource ../testcases.robot -Test Setup Execute test -Test Teardown Close Session - -*** Variables *** -${website_url}= https://bstackdemo.com - -*** Keywords *** -Execute test - ${final_caps}= combine caps 2 - Set to Dictionary ${final_caps} name=BStack Demo - ${TEST NAME} - Open Session ${final_caps} ${website_url} - - -*** Test Cases *** -Login Test - Login - -Add to Cart Test - Add to Cart diff --git a/tests/test-1.robot b/tests/test-1.robot new file mode 100644 index 0000000..cc5ba31 --- /dev/null +++ b/tests/test-1.robot @@ -0,0 +1,21 @@ +*** Settings *** +Library SeleniumLibrary +Resource ../resources/KeywordsFile.robot +Resource ../resources/TestCases.robot +Test Setup Execute test +Test Teardown Close Session + + +*** Variables *** +${website_url}= https://bstackdemo.com +&{test_caps} browser=chrome + + +*** Keywords *** +Execute test + Open Session ${test_caps} ${website_url} + + +*** Test Cases *** +BStack Sample Test 1 + Add to Cart diff --git a/tests/test-2.robot b/tests/test-2.robot new file mode 100644 index 0000000..1e44aec --- /dev/null +++ b/tests/test-2.robot @@ -0,0 +1,21 @@ +*** Settings *** +Library SeleniumLibrary +Resource ../resources/KeywordsFile.robot +Resource ../resources/TestCases.robot +Test Setup Execute test +Test Teardown Close Session + + +*** Variables *** +${website_url}= https://bstackdemo.com +&{test_caps} browser=firefox + + +*** Keywords *** +Execute test + Open Session ${test_caps} ${website_url} + + +*** Test Cases *** +BStack Sample Test 2 + Add to Cart diff --git a/tests/test-3.robot b/tests/test-3.robot new file mode 100644 index 0000000..06057e8 --- /dev/null +++ b/tests/test-3.robot @@ -0,0 +1,21 @@ +*** Settings *** +Library SeleniumLibrary +Resource ../resources/KeywordsFile.robot +Resource ../resources/TestCases.robot +Test Setup Execute test +Test Teardown Close Session + + +*** Variables *** +${website_url}= https://bstackdemo.com +&{test_caps} browser=safari + + +*** Keywords *** +Execute test + Open Session ${test_caps} ${website_url} + + +*** Test Cases *** +BStack Sample Test 3 + Add to Cart diff --git a/tests/testcases.robot b/tests/testcases.robot deleted file mode 100644 index 9d966ed..0000000 --- a/tests/testcases.robot +++ /dev/null @@ -1,18 +0,0 @@ -*** Settings *** -Library SeleniumLibrary -Resource ../config/KeywordsFile.robot - -*** Keywords *** -Login - Add Implicit Wait - Get the page title - Click on Sign In - Enter Credentials demouser testingisfun99 - Click on Login - Verify username demouser - -Add to Cart - Add Implicit Wait - Get the page title - Add first product to cart - Verify product is added to cart