-
Notifications
You must be signed in to change notification settings - Fork 0
Add unittest + Appium App Automate sample (Android + iOS) #1
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
AakashHotchandani
wants to merge
7
commits into
main
Choose a base branch
from
sdk-sample
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
7 commits
Select commit
Hold shift + click to select a range
f57ef64
Add unittest + Appium App Automate sample (Android + iOS)
AakashHotchandani e04df67
Restore scaffold files dropped by import (Semgrep CI workflow, CODEOW…
AakashHotchandani 6dce62b
Add BrowserStack SDK sample-test GitHub Actions workflow (workflow_di…
AakashHotchandani e4b63ec
Add least-privilege permissions to sample-test workflow (CodeQL: limi…
AakashHotchandani 70e6223
Commit public sample app(s) + reference by relative path (drop accoun…
AakashHotchandani 5f97f9e
Framework-led source token (unittest) to match published sibling conv…
AakashHotchandani d5fc79e
Fix README cd path to the full repo directory name
AakashHotchandani File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,75 @@ | ||
| # Runs the BrowserStack SDK sample against a given commit and reports a status check. | ||
| # Trigger: Actions tab -> "unittest Appium App Automate SDK sample test" -> Run workflow -> paste the PR's full commit SHA. | ||
| # Requires repo secrets: BROWSERSTACK_USERNAME, BROWSERSTACK_ACCESS_KEY. | ||
| # NOTE (App Automate): the app under test is referenced via `app: bs://...` in browserstack.yml; | ||
| # ensure that uploaded app exists on the account whose secrets are used (re-upload + update if expired). | ||
| name: unittest Appium App Automate SDK sample test | ||
|
|
||
| on: | ||
| workflow_dispatch: | ||
| inputs: | ||
| commit_sha: | ||
| description: 'The full commit id to build' | ||
| required: true | ||
|
|
||
| permissions: | ||
| contents: read # checkout | ||
| checks: write # github-script creates the status check | ||
|
|
||
| jobs: | ||
| sdk-sample: | ||
| runs-on: ${{ matrix.os }} | ||
| strategy: | ||
| fail-fast: false | ||
| max-parallel: 3 | ||
| matrix: | ||
| os: [ubuntu-latest] | ||
| python: ['3.10', '3.11'] | ||
| name: unittest-appium Python ${{ matrix.python }} sample | ||
| env: | ||
| BROWSERSTACK_USERNAME: ${{ secrets.BROWSERSTACK_USERNAME }} | ||
| BROWSERSTACK_ACCESS_KEY: ${{ secrets.BROWSERSTACK_ACCESS_KEY }} | ||
| defaults: | ||
| run: | ||
| working-directory: android | ||
| steps: | ||
| - uses: actions/checkout@v4 | ||
| with: | ||
| ref: ${{ github.event.inputs.commit_sha }} | ||
| - name: Mark status check in_progress | ||
| uses: actions/github-script@v7 | ||
| env: | ||
| job_name: unittest-appium Python ${{ matrix.python }} sample | ||
| commit_sha: ${{ github.event.inputs.commit_sha }} | ||
| with: | ||
| github-token: ${{ github.token }} | ||
| script: | | ||
| await github.rest.checks.create({ | ||
| owner: context.repo.owner, repo: context.repo.repo, | ||
| name: process.env.job_name, head_sha: process.env.commit_sha, | ||
| status: 'in_progress' | ||
| }).catch(e => console.log('check create failed:', e.status)); | ||
| - uses: actions/setup-python@v5 | ||
| with: | ||
| python-version: ${{ matrix.python }} | ||
| - name: Install | ||
| run: | | ||
| pip install -r requirements.txt | ||
| - name: Run sample test | ||
| run: | | ||
| browserstack-sdk python bstack_runner.py | ||
| - name: Mark status check completed | ||
| if: always() | ||
| uses: actions/github-script@v7 | ||
| env: | ||
| conclusion: ${{ job.status }} | ||
| job_name: unittest-appium Python ${{ matrix.python }} sample | ||
| commit_sha: ${{ github.event.inputs.commit_sha }} | ||
| with: | ||
| github-token: ${{ github.token }} | ||
| script: | | ||
| await github.rest.checks.create({ | ||
| owner: context.repo.owner, repo: context.repo.repo, | ||
| name: process.env.job_name, head_sha: process.env.commit_sha, | ||
| status: 'completed', conclusion: process.env.conclusion | ||
| }).catch(e => console.log('check create failed:', e.status)); | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| .vscode | ||
| __pycache__ | ||
| .pytest_cache | ||
| .venv | ||
| env | ||
| local.log | ||
| log/ | ||
| *.pyc |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,2 +1,83 @@ | ||
| # unittest-appium-app-browserstack | ||
| We require the following new public repositories under the browserstack GitHub organization to host customer-facing sample projects for the BrowserStack SDK. | ||
| # unittest + Appium with BrowserStack App Automate | ||
|
|
||
| Run Python `unittest` Appium tests on real mobile devices in the BrowserStack | ||
| device cloud, instrumented automatically by the **BrowserStack SDK**. No changes | ||
| to your test logic are required — the SDK reads `browserstack.yml`, uploads/uses | ||
| the app under test, and creates one App Automate session per platform. | ||
|
|
||
| This sample contains two self-contained platform directories: | ||
|
|
||
| ``` | ||
| unittest-appium/ | ||
| ├── android/ # WikipediaSample.apk — search flow | ||
| │ ├── browserstack.yml | ||
| │ ├── bstack_runner.py | ||
| │ ├── requirements.txt | ||
| │ └── tests/bstack_sample_test.py | ||
| └── ios/ # BStackSampleApp.ipa — text-echo flow | ||
| ├── browserstack.yml | ||
| ├── bstack_runner.py | ||
| ├── requirements.txt | ||
| └── tests/bstack_sample_test.py | ||
| ``` | ||
|
|
||
| ## Prerequisites | ||
|
|
||
| - A [BrowserStack App Automate](https://app-automate.browserstack.com/) account. | ||
| - Python 3.8+. | ||
| - Your `BROWSERSTACK_USERNAME` and `BROWSERSTACK_ACCESS_KEY` | ||
| (from your [account settings](https://www.browserstack.com/accounts/settings)). | ||
|
|
||
| ## Setup | ||
|
|
||
| ```bash | ||
| git clone <this-repo> | ||
| cd unittest-appium-app-browserstack/android # or cd unittest-appium-app-browserstack/ios | ||
|
|
||
| python3 -m venv .venv | ||
| .venv/bin/pip install -r requirements.txt | ||
| ``` | ||
|
|
||
| Configure credentials either in `browserstack.yml` (`userName` / `accessKey`) | ||
| or as environment variables (recommended): | ||
|
|
||
| ```bash | ||
| export BROWSERSTACK_USERNAME="YOUR_USERNAME" | ||
| export BROWSERSTACK_ACCESS_KEY="YOUR_ACCESS_KEY" | ||
| ``` | ||
|
|
||
| The app under test is referenced in `browserstack.yml` via the `app:` key as a | ||
| pre-uploaded `bs://<hashed-id>`. To use your own build, upload it first: | ||
|
|
||
| ```bash | ||
| curl -u "$BROWSERSTACK_USERNAME:$BROWSERSTACK_ACCESS_KEY" \ | ||
| -X POST "https://api-cloud.browserstack.com/app-automate/upload" \ | ||
| -F "file=@WikipediaSample.apk" | ||
| # then set app: bs://<app_url> in browserstack.yml | ||
| ``` | ||
|
|
||
| ## Run Sample Test | ||
|
|
||
| From inside the platform directory: | ||
|
|
||
| ```bash | ||
| cd android | ||
| browserstack-sdk python bstack_runner.py | ||
| ``` | ||
|
|
||
| `bstack_runner.py` discovers and runs the `unittest` suite under `tests/`. The | ||
| SDK forks one process per platform in `browserstack.yml`, opening one App | ||
| Automate session per device. | ||
|
|
||
| - **Android** (`WikipediaSample.apk`): taps **Search Wikipedia**, types | ||
| `BrowserStack`, and asserts that search-result `TextView`s are shown. | ||
| - **iOS** (`BStackSampleApp.ipa`): taps **Text Button**, types | ||
| `hello@browserstack.com`, and asserts the echoed **Text Output**. | ||
|
|
||
| ## Notes / Dashboard | ||
|
|
||
| - View runs at [app-automate.browserstack.com](https://app-automate.browserstack.com/). | ||
| - With `testObservability: true`, builds also appear in | ||
| [Test Observability](https://observability.browserstack.com/). | ||
| - Device, OS, and app capabilities all come from `browserstack.yml` — the Appium | ||
| driver is created with an **empty options object**; the SDK injects the rest. |
Binary file not shown.
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| userName: YOUR_USERNAME | ||
| accessKey: YOUR_ACCESS_KEY | ||
| projectName: BrowserStack Samples | ||
| buildName: appauto-unittest-appium | ||
| buildIdentifier: '#${BUILD_NUMBER}' | ||
| # `framework` lets the SDK send test context (name, status) to BrowserStack. | ||
| framework: unittest | ||
| # Pre-uploaded WikipediaSample.apk (the SDK injects this as the app under test). | ||
| app: ./WikipediaSample.apk | ||
| platforms: | ||
| - deviceName: Samsung Galaxy S22 Ultra | ||
| osVersion: "12.0" | ||
| platformName: android | ||
| parallelsPerPlatform: 1 | ||
| source: unittest:appium-sample-sdk:v1.0 | ||
| testObservability: true | ||
| debug: true | ||
| networkLogs: true |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| import unittest | ||
|
|
||
| # Entry point for the BrowserStack SDK generic-Python runner: | ||
| # browserstack-sdk python bstack_runner.py | ||
| # The SDK forks one process per platform listed in browserstack.yml and runs | ||
| # the discovered unittest suite in each (one BrowserStack App Automate session | ||
| # per platform). The app under test (WikipediaSample.apk) is injected from the | ||
| # `app:` key in browserstack.yml. | ||
| if __name__ == "__main__": | ||
| suite = unittest.TestLoader().discover("tests", pattern="bstack_*_test.py") | ||
| result = unittest.TextTestRunner(verbosity=2).run(suite) | ||
| if not result.wasSuccessful(): | ||
| raise SystemExit(1) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| Appium-Python-Client | ||
| selenium>=4.0 | ||
| browserstack-sdk @ https://sdk-assets.browserstack.com/python/browserstack_sdk-latest.tar.gz |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,46 @@ | ||
| import unittest | ||
|
|
||
| from appium import webdriver | ||
| from appium.options.android import UiAutomator2Options | ||
| from appium.webdriver.common.appiumby import AppiumBy | ||
|
|
||
|
|
||
| class BstackSampleTest(unittest.TestCase): | ||
| def setUp(self): | ||
| # The BrowserStack SDK injects the app + device capabilities from | ||
| # browserstack.yml at runtime, so an empty options object is enough. | ||
| options = UiAutomator2Options() | ||
| self.driver = webdriver.Remote( | ||
| "https://hub.browserstack.com/wd/hub", | ||
| options=options, | ||
| ) | ||
| self.driver.implicitly_wait(30) | ||
|
|
||
| def tearDown(self): | ||
| self.driver.quit() | ||
|
|
||
| def test_search_wikipedia(self): | ||
| # WikipediaSample.apk flow: | ||
| # tap the "Search Wikipedia" entry point, type a query, assert results. | ||
| search_element = self.driver.find_element( | ||
| AppiumBy.ACCESSIBILITY_ID, "Search Wikipedia" | ||
| ) | ||
| search_element.click() | ||
|
|
||
| insert_text_element = self.driver.find_element( | ||
| AppiumBy.ID, "org.wikipedia.alpha:id/search_src_text" | ||
| ) | ||
| insert_text_element.send_keys("BrowserStack") | ||
|
|
||
| # Allow the result list to render. | ||
| import time | ||
| time.sleep(5) | ||
|
|
||
| results = self.driver.find_elements( | ||
| AppiumBy.CLASS_NAME, "android.widget.TextView" | ||
| ) | ||
| self.assertGreater(len(results), 0) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| unittest.main() |
Binary file not shown.
Binary file not shown.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| userName: YOUR_USERNAME | ||
| accessKey: YOUR_ACCESS_KEY | ||
| projectName: BrowserStack Samples | ||
| buildName: appauto-unittest-appium | ||
| buildIdentifier: '#${BUILD_NUMBER}' | ||
| # `framework` lets the SDK send test context (name, status) to BrowserStack. | ||
| framework: unittest | ||
| # Pre-uploaded BStackSampleApp.ipa (the SDK injects this as the app under test). | ||
| app: ./BStackSampleApp.ipa | ||
| platforms: | ||
| - deviceName: iPhone 14 Pro | ||
| osVersion: '16' | ||
| platformName: ios | ||
| parallelsPerPlatform: 1 | ||
| source: unittest:appium-sample-sdk:v1.0 | ||
| testObservability: true | ||
| debug: true | ||
| networkLogs: true |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| import unittest | ||
|
|
||
| # Entry point for the BrowserStack SDK generic-Python runner: | ||
| # browserstack-sdk python bstack_runner.py | ||
| # The SDK forks one process per platform listed in browserstack.yml and runs | ||
| # the discovered unittest suite in each (one BrowserStack App Automate session | ||
| # per platform). The app under test (BStackSampleApp.ipa) is injected from the | ||
| # `app:` key in browserstack.yml. | ||
| if __name__ == "__main__": | ||
| suite = unittest.TestLoader().discover("tests", pattern="bstack_*_test.py") | ||
| result = unittest.TextTestRunner(verbosity=2).run(suite) | ||
| if not result.wasSuccessful(): | ||
| raise SystemExit(1) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,3 @@ | ||
| Appium-Python-Client | ||
| selenium>=4.0 | ||
| browserstack-sdk @ https://sdk-assets.browserstack.com/python/browserstack_sdk-latest.tar.gz |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| import unittest | ||
|
|
||
| from appium import webdriver | ||
| from appium.options.ios import XCUITestOptions | ||
| from appium.webdriver.common.appiumby import AppiumBy | ||
|
|
||
|
|
||
| class BstackSampleTest(unittest.TestCase): | ||
| def setUp(self): | ||
| # The BrowserStack SDK injects the app + device capabilities from | ||
| # browserstack.yml at runtime, so an empty options object is enough. | ||
| options = XCUITestOptions() | ||
| self.driver = webdriver.Remote( | ||
| "https://hub.browserstack.com/wd/hub", | ||
| options=options, | ||
| ) | ||
| self.driver.implicitly_wait(30) | ||
|
|
||
| def tearDown(self): | ||
| self.driver.quit() | ||
|
|
||
| def test_text_echo(self): | ||
| # BStackSampleApp.ipa flow: | ||
| # open the text screen, type a value, assert it is echoed back. | ||
| self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, "Text Button").click() | ||
|
|
||
| text_input = self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, "Text Input") | ||
| text_input.send_keys("hello@browserstack.com\n") | ||
|
|
||
| output = self.driver.find_element(AppiumBy.ACCESSIBILITY_ID, "Text Output") | ||
| self.assertEqual(output.text, "hello@browserstack.com") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| unittest.main() |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.