diff --git a/.github/workflows/desktop_web.yml b/.github/workflows/desktop_web.yml index a8d18df8..e6b84a20 100644 --- a/.github/workflows/desktop_web.yml +++ b/.github/workflows/desktop_web.yml @@ -6,18 +6,12 @@ on: - main paths: - 'best_practice/desktop_web/**' - - 'best_practice/conftest.py' - - 'Pipfile' - - 'Pipfile.lock' - '.github/workflows/desktop_web.yml' pull_request: branches: - main paths: - 'best_practice/desktop_web/**' - - 'best_practice/conftest.py' - - 'Pipfile' - - 'Pipfile.lock' - '.github/workflows/desktop_web.yml' schedule: - cron: "0 9 * * *" @@ -26,7 +20,10 @@ jobs: python-tests: name: Tests runs-on: ubuntu-latest - + defaults: + run: + working-directory: best_practice/desktop_web + steps: - uses: actions/checkout@v7 - name: Setup Python diff --git a/.github/workflows/mobile_native.yml b/.github/workflows/mobile_native.yml index fa26dd6f..cf43b6a1 100644 --- a/.github/workflows/mobile_native.yml +++ b/.github/workflows/mobile_native.yml @@ -6,18 +6,12 @@ on: - main paths: - 'best_practice/mobile_native/**' - - 'best_practice/conftest.py' - - 'Pipfile' - - 'Pipfile.lock' - '.github/workflows/mobile_native.yml' pull_request: branches: - main paths: - 'best_practice/mobile_native/**' - - 'best_practice/conftest.py' - - 'Pipfile' - - 'Pipfile.lock' - '.github/workflows/mobile_native.yml' schedule: - cron: "0 9 * * *" @@ -26,6 +20,9 @@ jobs: python-tests: name: Tests runs-on: ubuntu-latest + defaults: + run: + working-directory: best_practice/mobile_native strategy: fail-fast: false matrix: diff --git a/.github/workflows/mobile_web.yml b/.github/workflows/mobile_web.yml index 3278d268..9ea29ecd 100644 --- a/.github/workflows/mobile_web.yml +++ b/.github/workflows/mobile_web.yml @@ -6,18 +6,12 @@ on: - main paths: - 'best_practice/mobile_web/**' - - 'best_practice/conftest.py' - - 'Pipfile' - - 'Pipfile.lock' - '.github/workflows/mobile_web.yml' pull_request: branches: - main paths: - 'best_practice/mobile_web/**' - - 'best_practice/conftest.py' - - 'Pipfile' - - 'Pipfile.lock' - '.github/workflows/mobile_web.yml' schedule: - cron: "0 9 * * *" @@ -26,6 +20,9 @@ jobs: python-tests: name: Tests runs-on: ubuntu-latest + defaults: + run: + working-directory: best_practice/mobile_web strategy: fail-fast: false matrix: diff --git a/.github/workflows/robot_desktop_web.yml b/.github/workflows/robot_desktop_web.yml index f06cfcc8..d32181e4 100644 --- a/.github/workflows/robot_desktop_web.yml +++ b/.github/workflows/robot_desktop_web.yml @@ -6,16 +6,12 @@ on: - main paths: - 'examples/robotframework/desktop_web/**' - - 'Pipfile' - - 'Pipfile.lock' - '.github/workflows/robot_desktop_web.yml' pull_request: branches: - main paths: - 'examples/robotframework/desktop_web/**' - - 'Pipfile' - - 'Pipfile.lock' - '.github/workflows/robot_desktop_web.yml' schedule: - cron: "0 9 * * *" @@ -24,7 +20,10 @@ jobs: python-tests: name: Tests runs-on: ubuntu-latest - + defaults: + run: + working-directory: examples/robotframework/desktop_web + steps: - uses: actions/checkout@v7 - name: Setup Python diff --git a/.github/workflows/python.yml b/.github/workflows/selenium_demo.yml similarity index 57% rename from .github/workflows/python.yml rename to .github/workflows/selenium_demo.yml index 0a0291f2..d48bae57 100644 --- a/.github/workflows/python.yml +++ b/.github/workflows/selenium_demo.yml @@ -1,26 +1,18 @@ -name: Demo Python Tests +name: Selenium Demo Tests on: push: branches: - main paths: - - 'best_practice/desktop_web/**' - - 'best_practice/conftest.py' - 'examples/selenium/**' - - 'Pipfile' - - 'Pipfile.lock' - - '.github/workflows/python.yml' + - '.github/workflows/selenium_demo.yml' pull_request: branches: - main paths: - - 'best_practice/desktop_web/**' - - 'best_practice/conftest.py' - 'examples/selenium/**' - - 'Pipfile' - - 'Pipfile.lock' - - '.github/workflows/python.yml' + - '.github/workflows/selenium_demo.yml' schedule: - cron: "0 9 * * *" @@ -28,10 +20,10 @@ jobs: python-tests: name: Tests runs-on: ubuntu-latest - strategy: - fail-fast: false - matrix: - test: [ best-practice-desktop-us, demo] + defaults: + run: + working-directory: examples/selenium + steps: - uses: actions/checkout@v7 - name: Setup Python @@ -42,8 +34,8 @@ jobs: uses: dschep/install-pipenv-action@v1 - name: Install dependencies run: pipenv install - - name: Run ${{ matrix.test }} tests + - name: Run demo tests env: SAUCE_USERNAME: ${{ secrets.SAUCE_USERNAME }} SAUCE_ACCESS_KEY: ${{ secrets.SAUCE_ACCESS_KEY }} - run: pipenv run ${{ matrix.test }} + run: pipenv run demo diff --git a/.gitpod.yml b/.gitpod.yml deleted file mode 100644 index 0038f39d..00000000 --- a/.gitpod.yml +++ /dev/null @@ -1,10 +0,0 @@ -# List the start up tasks. Learn more: https://www.gitpod.io/docs/configure/workspaces/tasks -image: python:3.8 -tasks: - - name: Script Task - init: pip install -r ./requirements.txt - command: | - rm -rf /workspace/.pyenv_mirror/user/current/lib/python3.11/site-packages/py/_vendored_packages/apipkg/ - python -m pytest -n8 $TEST_PATH - -# Learn more from ready-to-use templates: https://www.gitpod.io/docs/introduction/getting-started/quickstart diff --git a/Pipfile b/Pipfile deleted file mode 100644 index b7354253..00000000 --- a/Pipfile +++ /dev/null @@ -1,57 +0,0 @@ -[packages] -pytest = "==9.1.1" -pytest-xdist = "==3.8.0" -Appium-Python-Client = "==5.3.1" -PyYAML = "==6.0.3" -selenium = "==4.46.0" -sa11y = "*" -sauceclient = "==1.0.2" -robotframework = "==7.4.2" -robotframework-pabot = "==5.2.2" -robotframework-seleniumlibrary = "==6.9.0" -apipkg = "==3.0.2" -attrs = "==26.1.0" -certifi = "==2026.7.22" -chardet = "==7.4.3" -decorator = "==5.3.1" -docutils = "==0.23" -execnet = "==2.1.2" -idna = "==3.18" -importlib-metadata = "==9.0.0" -iniconfig = "==2.3.0" -kitchen = "==1.2.6" -more-itertools = "==11.1.0" -packaging = "==26.2" -pluggy = "==1.6.0" -py = "==1.11.0" -pyparsing = "==3.3.2" -pytest-playwright = "==0.8.0" -requests = "==2.34.2" -robotframework-pythonlibcore = "==4.6.0" -six = "==1.17.0" -toml = "==0.10.2" -urllib3 = "==2.7.0" -zipp = "==4.1.0" -playwright = "==1.61.0" - -[scripts] -best-practice-desktop-us = "pytest -n8 --dc=us best_practice/desktop_web/" -best-practice-desktop-eu = "pytest -n8 --dc=eu best_practice/desktop_web/" -best-practice-mobile-web-vdc-us = "pytest -n8 --dc=us best_practice/mobile_web/vdc" -best-practice-mobile-web-vdc-eu = "pytest -n8 --dc=eu best_practice/mobile_web/vdc" -best-practice-mobile-web-rdc-us = "pytest -n8 --dc=us best_practice/mobile_web/rdc" -best-practice-mobile-web-rdc-eu = "pytest -n8 --dc=eu best_practice/mobile_web/rdc" -best-practice-mobile-native-us-android = "pytest -n8 --dc=us best_practice/mobile_native/android" -best-practice-mobile-native-eu-android = "pytest -n8 --dc=eu best_practice/mobile_native/android" -best-practice-mobile-native-us-ios = "pytest -n8 --dc=us best_practice/mobile_native/ios" -best-practice-mobile-native-eu-ios = "pytest -n8 --dc=eu best_practice/mobile_native/ios" -demo = "pytest examples/selenium" -robot-desktop-web-us = "pabot --argumentfile1 examples/robotframework/desktop_web/chrome_config.txt --argumentfile2 examples/robotframework/desktop_web/firefox_config.txt --variable DATA_CENTER:'https://ondemand.us-west-1.saucelabs.com/wd/hub' examples/robotframework/desktop_web/Tests/" -robot-desktop-web-eu = "pabot --argumentfile1 examples/robotframework/desktop_web/chrome_config.txt --argumentfile2 examples/robotframework/desktop_web/firefox_config.txt --variable DATA_CENTER:'https://ondemand.eu-central-1.saucelabs.com/wd/hub' examples/robotframework/desktop_web/Tests/" -robot-android-us = "pabot --variable DATA_CENTER:'https://ondemand.us-west-1.saucelabs.com/wd/hub' -A examples/robotframework/native_mobile/android/android_config.txt examples/robotframework/native_mobile/android/tests/" -robot-android-eu = "pabot --variable DATA_CENTER:'https://ondemand.eu-central-1.saucelabs.com/wd/hub' -A examples/robotframework/native_mobile/android/android_config.txt examples/robotframework/native_mobile/android/tests/" -robot-ios-us = "pabot --variable DATA_CENTER:'https://ondemand.us-west-1.saucelabs.com/wd/hub' -A examples/robotframework/native_mobile/ios/iphone_config.txt examples/robotframework/native_mobile/ios/tests/" -robot-ios-eu = "pabot --variable DATA_CENTER:'https://ondemand.eu-central-1.saucelabs.com/wd/hub' -A examples/robotframework/native_mobile/ios/iphone_config.txt examples/robotframework/native_mobile/ios/tests/" -playwright-tests = "pytest -n8 examples/playwright/" - -[dev-packages] diff --git a/README.md b/README.md index e87ac913..37fc2f58 100644 --- a/README.md +++ b/README.md @@ -48,38 +48,45 @@ and these cover using - Mobile Web browsers on Sauce emulators/simulators, and - Real devices to test native mobile apps. -These samples are executed using Pipenv for simplicity. You can find a list of -available executions in the `Pipfile` under the `[scripts]` section. These -executions demonstrate how to run tests in parallel on the Sauce Labs. +These samples are executed using Pipenv for simplicity. Each test suite has its +own `Pipfile` in its own directory, so dependencies and CI triggers stay scoped +to just that suite instead of one shared repo-wide dependency file. To run a +suite: `cd` into its directory, run `pipenv install`, then `pipenv run +`. ## Available Pipenv scripts -Below are the scripts defined in `Pipfile` grouped by purpose. Run any of them -with `pipenv run `. +Below are the scripts defined in each suite's own `Pipfile`, grouped by +directory. `cd` into the listed directory first, then run +`pipenv run `. -- Best-practice (desktop) +- `best_practice/desktop_web/` - `best-practice-desktop-us` — runs desktop best-practice tests against the US data center - `best-practice-desktop-eu` — runs desktop best-practice tests against the EU data center -- Best-practice (mobile web) +- `best_practice/mobile_web/` - `best-practice-mobile-web-vdc-us` — runs mobile web tests on virtual devices (VDC) in US - `best-practice-mobile-web-vdc-eu` — runs mobile web tests on virtual devices (VDC) in EU - `best-practice-mobile-web-rdc-us` — runs mobile web tests on real devices (RDC) in US - `best-practice-mobile-web-rdc-eu` — runs mobile web tests on real devices (RDC) in EU -- Best-practice (mobile native) +- `best_practice/mobile_native/` - `best-practice-mobile-native-us-android` — runs native Android tests in US - `best-practice-mobile-native-eu-android` — runs native Android tests in EU - `best-practice-mobile-native-us-ios` — runs native iOS tests in US - `best-practice-mobile-native-eu-ios` — runs native iOS tests in EU -- Examples & demos +- `examples/selenium/` - `demo` — runs the Selenium examples + +- `examples/playwright/` - `playwright-tests` — runs the Playwright examples -- Robotframework multi-run scripts (Pabot) +- `examples/robotframework/desktop_web/` - `robot-desktop-web-us` — runs desktop web robot tests against US datacenter - `robot-desktop-web-eu` — runs desktop web robot tests against EU datacenter + +- `examples/robotframework/native_mobile/` - `robot-android-us` — runs native Android robot tests against US datacenter - `robot-android-eu` — runs native Android robot tests against EU datacenter - `robot-ios-us` — runs native iOS robot tests against US datacenter diff --git a/best_practice/README.md b/best_practice/README.md index ab8f4ecb..c856a983 100644 --- a/best_practice/README.md +++ b/best_practice/README.md @@ -2,22 +2,26 @@ This section demonstrates best practice examples of how to connect and run simple tests using Python on Sauce Labs. As a best practice, we recommend [Pytest](http://pytest.org) as a test framework and runner. +Each suite below (`desktop_web`, `mobile_web`, `mobile_native`) has its own `Pipfile` and its +own `conftest.py`, so dependencies stay scoped to just what that suite needs. + ## Quickstart To run tests, do the following steps: 1. Set your Sauce username and access key as environment variables on the machine you are running tests from as `SAUCE_USERNAME` and `SAUCE_ACCESS_KEY` respectively. -2. Run +2. `cd` into the suite you want to run, e.g. `cd best_practice/desktop_web`. +3. Run ``` pipenv install ``` -3. Run +4. Run +``` +pipenv run best-practice-desktop-us ``` -pipenv best-practice-desktop-us -``` -to run against a desktop web app using Sauce Labs' US data center or +to run against a desktop web app using Sauce Labs' US data center or ``` -pipenv best-practice-desktop-eu +pipenv run best-practice-desktop-eu ``` to run against the EU data center @@ -28,24 +32,28 @@ These tests use Pytest and are configured to run using [Pipenv](https://pipenv.p - Python 3.7+ (_NOTE_ these tests are only compatible with Python 3, and have only been tested against Python 3.7+) - Pipenv -To install dependencies needed in this project, run +To install dependencies needed for a suite, run ``` pipenv install -``` -anywhere in this project. You can also install Pytest and Selenium directly if you do not want to use Pipenv. +``` +from inside that suite's directory (`best_practice/desktop_web`, `best_practice/mobile_web`, or +`best_practice/mobile_native`). You can also install Pytest and Selenium/Appium-Python-Client +directly if you do not want to use Pipenv. Last and certainly not least, set your Sauce username and access key as environment variables on the machine you are running tests from as `SAUCE_USERNAME` and `SAUCE_ACCESS_KEY` respectively. ## Structure of the Best Practice tests -These tests are designed to illustrate how to connect Pytest tests to running on Sauce Labs. +These tests are designed to illustrate how to connect Pytest tests to running on Sauce Labs. -Pytest fixtures are located in the `conftest.py` file as is conventional with Pytest. The `conftest.py` file shows how to configure the Webdriver to connect to Sauce Labs via Capabilities. +Each suite has its own `conftest.py`, as is conventional with Pytest. That `conftest.py` file +shows how to configure the Webdriver to connect to Sauce Labs via Capabilities. -Each directory contains tests that use fixtures from the `conftest.py` file. Each directory contains tests that test against +Each directory contains tests that use fixtures from its own `conftest.py` file. Each directory +contains tests that test against - desktop web browsers, -- mobile web browsers (on emulators and simulators), and +- mobile web browsers (on emulators and simulators), and - a mobile native app on real devices. All tests make use of the Sauce Demo app, in both [web](https://github.com/saucelabs/sample-app-web) and [native mobile](https://github.com/saucelabs/sample-app-mobile) versions as the app under test. @@ -58,84 +66,84 @@ Sauce currently supports multiple data centers, so you can choose where your tes ### US Case -To run desktop web tests you can run +To run desktop web tests, from `best_practice/desktop_web`, run +``` +pipenv run best-practice-desktop-us +``` +or run ``` -pipenv best-practice-desktop-us -``` -or you can run +pytest -n8 --dc=us . ``` -pytest best-practice-us -``` -directly if you have Pytest and Selenium installed. +directly if you have Pytest and Selenium installed. -Similarly you can run run +Similarly, from `best_practice/mobile_web`, run ``` -pipenv best-practice-mobile-web-us -``` -or you can run +pipenv run best-practice-mobile-web-vdc-us ``` -pytest best-practice-mobile-us +or run ``` -directly if you have Pytest and Selenium installed. +pytest -n8 --dc=us vdc +``` +directly if you have Pytest and Selenium/Appium-Python-Client installed. To run native mobile app tests against real devices on the Sauce Real Device Cloud (RDC), confirm you have access to real devices on your account, upload the appropriate version of the [sample mobile app](https://github.com/saucelabs/sample-app-mobile/releases) to your account following [this guide](https://wiki.saucelabs.com/display/DOCS/Application+Storage#ApplicationStorage-WhatYou'llNeed). -After this, you can run +After this, from `best_practice/mobile_native`, run +``` +pipenv run best-practice-mobile-native-us-android ``` -pipenv best-practice-native-us-android +for the Android case (or ``` -for the Android case (or +pytest -n8 --dc=us android ``` -pytest mobile_native/android -``` -using Pytest directly) and/or +using Pytest directly) and/or ``` -pipenv best-practice-native-us-ios -``` -for the iOS case (or +pipenv run best-practice-mobile-native-us-ios +``` +for the iOS case (or +``` +pytest -n8 --dc=us ios ``` -pytest mobile_native/ios -``` using Pytest directly) ### EU Case -To run desktop web tests you can run +To run desktop web tests, from `best_practice/desktop_web`, run ``` -pipenv best-practice-desktop-eu -``` -or you can run +pipenv run best-practice-desktop-eu ``` -pytest best-practice-eu -``` -directly if you have Pytest and Selenium installed. - -Similarly you can run run +or run ``` -pipenv best-practice-mobile-web-eu -``` -or you can run +pytest -n8 --dc=eu . ``` -pytest best-practice-mobile-eu -``` directly if you have Pytest and Selenium installed. +Similarly, from `best_practice/mobile_web`, run +``` +pipenv run best-practice-mobile-web-vdc-eu +``` +or run +``` +pytest -n8 --dc=eu vdc +``` +directly if you have Pytest and Selenium/Appium-Python-Client installed. + To run native mobile app tests against real devices on the Sauce Real Device Cloud (RDC), confirm you have access to real devices on your account, upload the appropriate version of the [sample mobile app](https://github.com/saucelabs/sample-app-mobile/releases) to your account following [this guide](https://wiki.saucelabs.com/display/DOCS/Application+Storage#ApplicationStorage-WhatYou'llNeed). -After this, you can run +After this, from `best_practice/mobile_native`, run +``` +pipenv run best-practice-mobile-native-eu-android ``` -pipenv best-practice-native-eu-android -``` -for the Android case (or +for the Android case (or ``` -pytest mobile_native/android +pytest -n8 --dc=eu android ``` -using Pytest directly) and/or +using Pytest directly) and/or ``` -pipenv best-practice-native-eu-ios +pipenv run best-practice-mobile-native-eu-ios ``` -for the iOS case (or +for the iOS case (or ``` -pytest mobile_native/ios +pytest -n8 --dc=eu ios ``` using Pytest directly) diff --git a/best_practice/desktop_web/Pipfile b/best_practice/desktop_web/Pipfile new file mode 100644 index 00000000..5bd8a006 --- /dev/null +++ b/best_practice/desktop_web/Pipfile @@ -0,0 +1,10 @@ +[packages] +pytest = "==9.1.1" +pytest-xdist = "==3.8.0" +selenium = "==4.46.0" + +[scripts] +best-practice-desktop-us = "pytest -n8 --dc=us ." +best-practice-desktop-eu = "pytest -n8 --dc=eu ." + +[dev-packages] diff --git a/best_practice/desktop_web/Pipfile.lock b/best_practice/desktop_web/Pipfile.lock new file mode 100644 index 00000000..1e0f0384 --- /dev/null +++ b/best_practice/desktop_web/Pipfile.lock @@ -0,0 +1,201 @@ +{ + "_meta": { + "hash": { + "sha256": "164471e939177bb9fa59db6c8f889f2d058c904fc2f811accf9fdb96d9e246f5" + }, + "pipfile-spec": 6, + "requires": {}, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "attrs": { + "hashes": [ + "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", + "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32" + ], + "markers": "python_version >= '3.9'", + "version": "==26.1.0" + }, + "certifi": { + "hashes": [ + "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775", + "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55" + ], + "markers": "python_version >= '3.7'", + "version": "==2026.7.22" + }, + "execnet": { + "hashes": [ + "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd", + "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec" + ], + "markers": "python_version >= '3.8'", + "version": "==2.1.2" + }, + "h11": { + "hashes": [ + "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", + "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86" + ], + "markers": "python_version >= '3.8'", + "version": "==0.16.0" + }, + "idna": { + "hashes": [ + "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2", + "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848" + ], + "markers": "python_version >= '3.9'", + "version": "==3.18" + }, + "iniconfig": { + "hashes": [ + "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", + "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12" + ], + "markers": "python_version >= '3.10'", + "version": "==2.3.0" + }, + "outcome": { + "hashes": [ + "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8", + "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b" + ], + "markers": "python_version >= '3.7'", + "version": "==1.3.0.post0" + }, + "packaging": { + "hashes": [ + "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", + "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661" + ], + "markers": "python_version >= '3.8'", + "version": "==26.2" + }, + "pluggy": { + "hashes": [ + "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", + "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746" + ], + "markers": "python_version >= '3.9'", + "version": "==1.6.0" + }, + "pygments": { + "hashes": [ + "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", + "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176" + ], + "markers": "python_version >= '3.9'", + "version": "==2.20.0" + }, + "pysocks": { + "hashes": [ + "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299", + "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5", + "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.7.1" + }, + "pytest": { + "hashes": [ + "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", + "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c" + ], + "index": "pypi", + "markers": "python_version >= '3.10'", + "version": "==9.1.1" + }, + "pytest-xdist": { + "hashes": [ + "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", + "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==3.8.0" + }, + "selenium": { + "hashes": [ + "sha256:54f7e1a4df5f7508ac8c38ce2ea584db1b27083dd79962b22524219219df5cbe", + "sha256:f03e864770a21ab32009961c9d015cb2c6275eba45c926c272e02d90af423aad" + ], + "index": "pypi", + "markers": "python_version >= '3.10'", + "version": "==4.46.0" + }, + "sniffio": { + "hashes": [ + "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", + "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc" + ], + "markers": "python_version >= '3.7'", + "version": "==1.3.1" + }, + "sortedcontainers": { + "hashes": [ + "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", + "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0" + ], + "version": "==2.4.0" + }, + "trio": { + "hashes": [ + "sha256:3bd5d87f781d9b0192d592aef28691f8951d6c2e41b7e1da4c25cde6c180ae9b", + "sha256:a29b92b73f09d4b48ed249acd91073281a7f1063f09caba5dc70465b5c7aa970" + ], + "markers": "python_version >= '3.10'", + "version": "==0.33.0" + }, + "trio-websocket": { + "hashes": [ + "sha256:22c72c436f3d1e264d0910a3951934798dcc5b00ae56fc4ee079d46c7cf20fae", + "sha256:df605665f1db533f4a386c94525870851096a223adcb97f72a07e8b4beba45b6" + ], + "markers": "python_version >= '3.8'", + "version": "==0.12.2" + }, + "typing-extensions": { + "hashes": [ + "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", + "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5" + ], + "markers": "python_version >= '3.9'", + "version": "==4.16.0" + }, + "urllib3": { + "extras": [ + "socks" + ], + "hashes": [ + "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", + "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897" + ], + "markers": "python_version >= '3.10'", + "version": "==2.7.0" + }, + "websocket-client": { + "hashes": [ + "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98", + "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef" + ], + "markers": "python_version >= '3.9'", + "version": "==1.9.0" + }, + "wsproto": { + "hashes": [ + "sha256:61eea322cdf56e8cc904bd3ad7573359a242ba65688716b0710a5eb12beab584", + "sha256:b86885dcf294e15204919950f666e06ffc6c7c114ca900b060d6e16293528294" + ], + "markers": "python_version >= '3.10'", + "version": "==1.3.2" + } + }, + "develop": {} +} diff --git a/best_practice/desktop_web/conftest.py b/best_practice/desktop_web/conftest.py new file mode 100644 index 00000000..fa5dbde4 --- /dev/null +++ b/best_practice/desktop_web/conftest.py @@ -0,0 +1,98 @@ +import pytest +from os import environ + +from selenium import webdriver +from selenium.common.exceptions import WebDriverException + +desktop_browsers = [ + { + "platformName": "Windows 10", + "browserName": "MicrosoftEdge", + "platformVersion": "latest", + "sauce:options": {} + }, { + "platformName": "Windows 10", + "browserName": "firefox", + "platformVersion": "latest-1", + "sauce:options": {} + }, { + "platformName": "Windows 10", + "browserName": "internet explorer", + "platformVersion": "latest", + "sauce:options": {} + }, { + "platformName": "OS X 10.14", + "browserName": "safari", + "platformVersion": "latest-1", + "sauce:options": {} + }, { + "platformName": "OS X 10.14", + "browserName": "chrome", + "platformVersion": "latest", + "sauce:options": { + "extendedDebugging": True + } + }] + + +def pytest_addoption(parser): + parser.addoption("--dc", action="store", default='us', help="Set Sauce Labs Data Center (US or EU)") + + +@pytest.fixture +def data_center(request): + return request.config.getoption('--dc') + + +@pytest.fixture(params=desktop_browsers) +def desktop_web_driver(request, data_center): + + test_name = request.node.name + build_tag = environ.get('BUILD_TAG', "Sauce-Best-Practices-Python-Desktop-Web") + + username = environ['SAUCE_USERNAME'] + access_key = environ['SAUCE_ACCESS_KEY'] + + if data_center and data_center.lower() == 'eu': + selenium_endpoint = "https://{}:{}@ondemand.eu-central-1.saucelabs.com/wd/hub".format(username, access_key) + else: + selenium_endpoint = "https://{}:{}@ondemand.us-west-1.saucelabs.com/wd/hub".format(username, access_key) + + caps = dict() + caps.update(request.param) + caps['sauce:options'].update({'build': build_tag}) + caps['sauce:options'].update({'name': test_name}) + + browser = webdriver.Remote( + command_executor=selenium_endpoint, + options=webdriver.ChromeOptions(), + keep_alive=True + ) + + # This is specifically for SauceLabs plugin. + # In case test fails after selenium session creation having this here will help track it down. + if browser is not None: + print("SauceOnDemandSessionID={} job-name={}".format(browser.session_id, test_name)) + else: + raise WebDriverException("Never created!") + + yield browser + + # Teardown starts here + # report results + # use the test result to send the pass/fail status to Sauce Labs + sauce_result = "failed" if request.node.rep_call.failed else "passed" + browser.execute_script("sauce:job-result={}".format(sauce_result)) + browser.quit() + + +@pytest.hookimpl(hookwrapper=True, tryfirst=True) +def pytest_runtest_makereport(item, call): + # this sets the result as a test attribute for Sauce Labs reporting. + # execute all other hooks to obtain the report object + outcome = yield + rep = outcome.get_result() + + # set an report attribute for each phase of a call, which can + # be "setup", "call", "teardown" + setattr(item, "rep_" + rep.when, rep) diff --git a/best_practice/mobile_native/Pipfile b/best_practice/mobile_native/Pipfile new file mode 100644 index 00000000..fb9e5471 --- /dev/null +++ b/best_practice/mobile_native/Pipfile @@ -0,0 +1,12 @@ +[packages] +pytest = "==9.1.1" +pytest-xdist = "==3.8.0" +Appium-Python-Client = "==5.3.1" + +[scripts] +best-practice-mobile-native-us-android = "pytest -n8 --dc=us android" +best-practice-mobile-native-eu-android = "pytest -n8 --dc=eu android" +best-practice-mobile-native-us-ios = "pytest -n8 --dc=us ios" +best-practice-mobile-native-eu-ios = "pytest -n8 --dc=eu ios" + +[dev-packages] diff --git a/best_practice/mobile_native/Pipfile.lock b/best_practice/mobile_native/Pipfile.lock new file mode 100644 index 00000000..29524ce9 --- /dev/null +++ b/best_practice/mobile_native/Pipfile.lock @@ -0,0 +1,209 @@ +{ + "_meta": { + "hash": { + "sha256": "d88b388e0e5a6ca31f14d199065d4ecacfff5791ef248bd1acc464899c465044" + }, + "pipfile-spec": 6, + "requires": {}, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "appium-python-client": { + "hashes": [ + "sha256:30800f9a53a585814138e7c8f569fd295273f933c9b34ad1a9580f3bf923fc63", + "sha256:da0d3227ee059c31908a16f30a131424713ea96998fcd48e255d2cf9d107b557" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==5.3.1" + }, + "attrs": { + "hashes": [ + "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", + "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32" + ], + "markers": "python_version >= '3.9'", + "version": "==26.1.0" + }, + "certifi": { + "hashes": [ + "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775", + "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55" + ], + "markers": "python_version >= '3.7'", + "version": "==2026.7.22" + }, + "execnet": { + "hashes": [ + "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd", + "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec" + ], + "markers": "python_version >= '3.8'", + "version": "==2.1.2" + }, + "h11": { + "hashes": [ + "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", + "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86" + ], + "markers": "python_version >= '3.8'", + "version": "==0.16.0" + }, + "idna": { + "hashes": [ + "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2", + "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848" + ], + "markers": "python_version >= '3.9'", + "version": "==3.18" + }, + "iniconfig": { + "hashes": [ + "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", + "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12" + ], + "markers": "python_version >= '3.10'", + "version": "==2.3.0" + }, + "outcome": { + "hashes": [ + "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8", + "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b" + ], + "markers": "python_version >= '3.7'", + "version": "==1.3.0.post0" + }, + "packaging": { + "hashes": [ + "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", + "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661" + ], + "markers": "python_version >= '3.8'", + "version": "==26.2" + }, + "pluggy": { + "hashes": [ + "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", + "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746" + ], + "markers": "python_version >= '3.9'", + "version": "==1.6.0" + }, + "pygments": { + "hashes": [ + "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", + "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176" + ], + "markers": "python_version >= '3.9'", + "version": "==2.20.0" + }, + "pysocks": { + "hashes": [ + "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299", + "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5", + "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.7.1" + }, + "pytest": { + "hashes": [ + "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", + "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c" + ], + "index": "pypi", + "markers": "python_version >= '3.10'", + "version": "==9.1.1" + }, + "pytest-xdist": { + "hashes": [ + "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", + "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==3.8.0" + }, + "selenium": { + "hashes": [ + "sha256:54f7e1a4df5f7508ac8c38ce2ea584db1b27083dd79962b22524219219df5cbe", + "sha256:f03e864770a21ab32009961c9d015cb2c6275eba45c926c272e02d90af423aad" + ], + "markers": "python_version >= '3.10'", + "version": "==4.46.0" + }, + "sniffio": { + "hashes": [ + "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", + "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc" + ], + "markers": "python_version >= '3.7'", + "version": "==1.3.1" + }, + "sortedcontainers": { + "hashes": [ + "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", + "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0" + ], + "version": "==2.4.0" + }, + "trio": { + "hashes": [ + "sha256:3bd5d87f781d9b0192d592aef28691f8951d6c2e41b7e1da4c25cde6c180ae9b", + "sha256:a29b92b73f09d4b48ed249acd91073281a7f1063f09caba5dc70465b5c7aa970" + ], + "markers": "python_version >= '3.10'", + "version": "==0.33.0" + }, + "trio-websocket": { + "hashes": [ + "sha256:22c72c436f3d1e264d0910a3951934798dcc5b00ae56fc4ee079d46c7cf20fae", + "sha256:df605665f1db533f4a386c94525870851096a223adcb97f72a07e8b4beba45b6" + ], + "markers": "python_version >= '3.8'", + "version": "==0.12.2" + }, + "typing-extensions": { + "hashes": [ + "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", + "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5" + ], + "markers": "python_version >= '3.9'", + "version": "==4.16.0" + }, + "urllib3": { + "extras": [ + "socks" + ], + "hashes": [ + "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", + "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897" + ], + "markers": "python_version >= '3.10'", + "version": "==2.7.0" + }, + "websocket-client": { + "hashes": [ + "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98", + "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef" + ], + "markers": "python_version >= '3.9'", + "version": "==1.9.0" + }, + "wsproto": { + "hashes": [ + "sha256:61eea322cdf56e8cc904bd3ad7573359a242ba65688716b0710a5eb12beab584", + "sha256:b86885dcf294e15204919950f666e06ffc6c7c114ca900b060d6e16293528294" + ], + "markers": "python_version >= '3.10'", + "version": "==1.3.2" + } + }, + "develop": {} +} diff --git a/best_practice/mobile_native/conftest.py b/best_practice/mobile_native/conftest.py new file mode 100644 index 00000000..9ed168e4 --- /dev/null +++ b/best_practice/mobile_native/conftest.py @@ -0,0 +1,94 @@ +import pytest +from os import environ + +from appium.options.android import UiAutomator2Options +from appium.options.ios import XCUITestOptions +from appium import webdriver as appiumdriver + +import urllib3 + +urllib3.disable_warnings() + + +def pytest_addoption(parser): + parser.addoption("--dc", action="store", default='us', help="Set Sauce Labs Data Center (US or EU)") + + +@pytest.fixture +def data_center(request): + return request.config.getoption('--dc') + + +@pytest.fixture +def android_rdc_driver(request, data_center): + + username_cap = environ['SAUCE_USERNAME'] + access_key_cap = environ['SAUCE_ACCESS_KEY'] + + options = UiAutomator2Options() + options.platform_name = 'Android' + options.device_name = 'Google.*' + options.automation_name = 'UiAutomator2' + options.app = 'https://github.com/saucelabs/my-demo-app-android/releases/download/2.2.0/mda-2.2.0-25.apk' + sauce_options = { + 'username': username_cap, + 'accessKey': access_key_cap, + 'build': 'RDC-Android-Python-Best-Practice', + 'name': request.node.name, + 'appiumVersion': 'latest', + } + options.set_capability('sauce:options', sauce_options) + + if data_center and data_center.lower() == 'eu': + sauce_url = 'https://ondemand.eu-central-1.saucelabs.com/wd/hub' + else: + sauce_url = 'https://ondemand.us-west-1.saucelabs.com/wd/hub' + + driver = appiumdriver.Remote(sauce_url, options=options) + yield driver + sauce_result = "failed" if request.node.rep_call.failed else "passed" + driver.execute_script("sauce:job-result={}".format(sauce_result)) + driver.quit() + + +@pytest.fixture +def ios_rdc_driver(request, data_center): + + username_cap = environ['SAUCE_USERNAME'] + access_key_cap = environ['SAUCE_ACCESS_KEY'] + + options = XCUITestOptions() + options.platform_name = 'iOS' + options.device_name = 'iPhone.*' + options.app = 'https://github.com/saucelabs/sample-app-mobile/releases/download/2.7.1/iOS.RealDevice.SauceLabs.Mobile.Sample.app.2.7.1.ipa' + sauce_options = { + 'username': username_cap, + 'accessKey': access_key_cap, + 'build': 'RDC-iOS-Python-Best-Practice', + 'name': request.node.name, + 'appiumVersion': 'latest', + } + options.set_capability('sauce:options', sauce_options) + + if data_center and data_center.lower() == 'eu': + sauce_url = "https://ondemand.eu-central-1.saucelabs.com/wd/hub" + else: + sauce_url = "https://ondemand.us-west-1.saucelabs.com/wd/hub" + + driver = appiumdriver.Remote(sauce_url, options=options) + yield driver + sauce_result = "failed" if request.node.rep_call.failed else "passed" + driver.execute_script("sauce:job-result={}".format(sauce_result)) + driver.quit() + + +@pytest.hookimpl(hookwrapper=True, tryfirst=True) +def pytest_runtest_makereport(item, call): + # this sets the result as a test attribute for Sauce Labs reporting. + # execute all other hooks to obtain the report object + outcome = yield + rep = outcome.get_result() + + # set an report attribute for each phase of a call, which can + # be "setup", "call", "teardown" + setattr(item, "rep_" + rep.when, rep) diff --git a/best_practice/mobile_web/Pipfile b/best_practice/mobile_web/Pipfile new file mode 100644 index 00000000..509e96e5 --- /dev/null +++ b/best_practice/mobile_web/Pipfile @@ -0,0 +1,13 @@ +[packages] +pytest = "==9.1.1" +pytest-xdist = "==3.8.0" +selenium = "==4.46.0" +Appium-Python-Client = "==5.3.1" + +[scripts] +best-practice-mobile-web-vdc-us = "pytest -n8 --dc=us vdc" +best-practice-mobile-web-vdc-eu = "pytest -n8 --dc=eu vdc" +best-practice-mobile-web-rdc-us = "pytest -n8 --dc=us rdc" +best-practice-mobile-web-rdc-eu = "pytest -n8 --dc=eu rdc" + +[dev-packages] diff --git a/best_practice/mobile_web/Pipfile.lock b/best_practice/mobile_web/Pipfile.lock new file mode 100644 index 00000000..9ec32298 --- /dev/null +++ b/best_practice/mobile_web/Pipfile.lock @@ -0,0 +1,210 @@ +{ + "_meta": { + "hash": { + "sha256": "b07d02f4714e90702960a54bc055a9ec7a50ec5a322112a37cd4b24ecaab15be" + }, + "pipfile-spec": 6, + "requires": {}, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "appium-python-client": { + "hashes": [ + "sha256:30800f9a53a585814138e7c8f569fd295273f933c9b34ad1a9580f3bf923fc63", + "sha256:da0d3227ee059c31908a16f30a131424713ea96998fcd48e255d2cf9d107b557" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==5.3.1" + }, + "attrs": { + "hashes": [ + "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", + "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32" + ], + "markers": "python_version >= '3.9'", + "version": "==26.1.0" + }, + "certifi": { + "hashes": [ + "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775", + "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55" + ], + "markers": "python_version >= '3.7'", + "version": "==2026.7.22" + }, + "execnet": { + "hashes": [ + "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd", + "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec" + ], + "markers": "python_version >= '3.8'", + "version": "==2.1.2" + }, + "h11": { + "hashes": [ + "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", + "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86" + ], + "markers": "python_version >= '3.8'", + "version": "==0.16.0" + }, + "idna": { + "hashes": [ + "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2", + "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848" + ], + "markers": "python_version >= '3.9'", + "version": "==3.18" + }, + "iniconfig": { + "hashes": [ + "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", + "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12" + ], + "markers": "python_version >= '3.10'", + "version": "==2.3.0" + }, + "outcome": { + "hashes": [ + "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8", + "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b" + ], + "markers": "python_version >= '3.7'", + "version": "==1.3.0.post0" + }, + "packaging": { + "hashes": [ + "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", + "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661" + ], + "markers": "python_version >= '3.8'", + "version": "==26.2" + }, + "pluggy": { + "hashes": [ + "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", + "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746" + ], + "markers": "python_version >= '3.9'", + "version": "==1.6.0" + }, + "pygments": { + "hashes": [ + "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", + "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176" + ], + "markers": "python_version >= '3.9'", + "version": "==2.20.0" + }, + "pysocks": { + "hashes": [ + "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299", + "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5", + "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.7.1" + }, + "pytest": { + "hashes": [ + "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", + "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c" + ], + "index": "pypi", + "markers": "python_version >= '3.10'", + "version": "==9.1.1" + }, + "pytest-xdist": { + "hashes": [ + "sha256:202ca578cfeb7370784a8c33d6d05bc6e13b4f25b5053c30a152269fd10f0b88", + "sha256:7e578125ec9bc6050861aa93f2d59f1d8d085595d6551c2c90b6f4fad8d3a9f1" + ], + "index": "pypi", + "markers": "python_version >= '3.9'", + "version": "==3.8.0" + }, + "selenium": { + "hashes": [ + "sha256:54f7e1a4df5f7508ac8c38ce2ea584db1b27083dd79962b22524219219df5cbe", + "sha256:f03e864770a21ab32009961c9d015cb2c6275eba45c926c272e02d90af423aad" + ], + "index": "pypi", + "markers": "python_version >= '3.10'", + "version": "==4.46.0" + }, + "sniffio": { + "hashes": [ + "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", + "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc" + ], + "markers": "python_version >= '3.7'", + "version": "==1.3.1" + }, + "sortedcontainers": { + "hashes": [ + "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", + "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0" + ], + "version": "==2.4.0" + }, + "trio": { + "hashes": [ + "sha256:3bd5d87f781d9b0192d592aef28691f8951d6c2e41b7e1da4c25cde6c180ae9b", + "sha256:a29b92b73f09d4b48ed249acd91073281a7f1063f09caba5dc70465b5c7aa970" + ], + "markers": "python_version >= '3.10'", + "version": "==0.33.0" + }, + "trio-websocket": { + "hashes": [ + "sha256:22c72c436f3d1e264d0910a3951934798dcc5b00ae56fc4ee079d46c7cf20fae", + "sha256:df605665f1db533f4a386c94525870851096a223adcb97f72a07e8b4beba45b6" + ], + "markers": "python_version >= '3.8'", + "version": "==0.12.2" + }, + "typing-extensions": { + "hashes": [ + "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", + "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5" + ], + "markers": "python_version >= '3.9'", + "version": "==4.16.0" + }, + "urllib3": { + "extras": [ + "socks" + ], + "hashes": [ + "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", + "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897" + ], + "markers": "python_version >= '3.10'", + "version": "==2.7.0" + }, + "websocket-client": { + "hashes": [ + "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98", + "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef" + ], + "markers": "python_version >= '3.9'", + "version": "==1.9.0" + }, + "wsproto": { + "hashes": [ + "sha256:61eea322cdf56e8cc904bd3ad7573359a242ba65688716b0710a5eb12beab584", + "sha256:b86885dcf294e15204919950f666e06ffc6c7c114ca900b060d6e16293528294" + ], + "markers": "python_version >= '3.10'", + "version": "==1.3.2" + } + }, + "develop": {} +} diff --git a/best_practice/conftest.py b/best_practice/mobile_web/conftest.py similarity index 50% rename from best_practice/conftest.py rename to best_practice/mobile_web/conftest.py index 24295d80..7bb14058 100644 --- a/best_practice/conftest.py +++ b/best_practice/mobile_web/conftest.py @@ -1,7 +1,6 @@ import pytest from os import environ -from appium.options.android import UiAutomator2Options from appium.options.common import AppiumOptions from appium.options.ios import XCUITestOptions from selenium import webdriver @@ -40,37 +39,6 @@ }] -desktop_browsers = [ - { - "platformName": "Windows 10", - "browserName": "MicrosoftEdge", - "platformVersion": "latest", - "sauce:options": {} - }, { - "platformName": "Windows 10", - "browserName": "firefox", - "platformVersion": "latest-1", - "sauce:options": {} - }, { - "platformName": "Windows 10", - "browserName": "internet explorer", - "platformVersion": "latest", - "sauce:options": {} - }, { - "platformName": "OS X 10.14", - "browserName": "safari", - "platformVersion": "latest-1", - "sauce:options": {} - }, { - "platformName": "OS X 10.14", - "browserName": "chrome", - "platformVersion": "latest", - "sauce:options": { - "extendedDebugging": True - } - }] - - def pytest_addoption(parser): parser.addoption("--dc", action="store", default='us', help="Set Sauce Labs Data Center (US or EU)") @@ -85,10 +53,10 @@ def mobile_web_driver(request, data_center): test_name = request.node.name build_tag = environ.get('BUILD_TAG', "Sauce-Best-Practices-Python-Mobile-Web") - + username = environ['SAUCE_USERNAME'] access_key = environ['SAUCE_ACCESS_KEY'] - + if data_center and data_center.lower() == 'eu': selenium_endpoint = "https://@ondemand.eu-central-1.saucelabs.com/wd/hub" else: @@ -133,46 +101,6 @@ def mobile_web_driver(request, data_center): browser.execute_script("sauce:job-result={}".format(sauce_result)) browser.quit() -@pytest.fixture(params=desktop_browsers) -def desktop_web_driver(request, data_center): - - test_name = request.node.name - build_tag = environ.get('BUILD_TAG', "Sauce-Best-Practices-Python-Desktop-Web") - - username = environ['SAUCE_USERNAME'] - access_key = environ['SAUCE_ACCESS_KEY'] - - if data_center and data_center.lower() == 'eu': - selenium_endpoint = "https://{}:{}@ondemand.eu-central-1.saucelabs.com/wd/hub".format(username, access_key) - else: - selenium_endpoint = "https://{}:{}@ondemand.us-west-1.saucelabs.com/wd/hub".format(username, access_key) - - caps = dict() - caps.update(request.param) - caps['sauce:options'].update({'build': build_tag}) - caps['sauce:options'].update({'name': test_name}) - - browser = webdriver.Remote( - command_executor=selenium_endpoint, - options=webdriver.ChromeOptions(), - keep_alive=True - ) - - # This is specifically for SauceLabs plugin. - # In case test fails after selenium session creation having this here will help track it down. - if browser is not None: - print("SauceOnDemandSessionID={} job-name={}".format(browser.session_id, test_name)) - else: - raise WebDriverException("Never created!") - - yield browser - - # Teardown starts here - # report results - # use the test result to send the pass/fail status to Sauce Labs - sauce_result = "failed" if request.node.rep_call.failed else "passed" - browser.execute_script("sauce:job-result={}".format(sauce_result)) - browser.quit() @pytest.fixture def rdc_browser(request, data_center): @@ -203,66 +131,6 @@ def rdc_browser(request, data_center): driver.execute_script("sauce:job-result={}".format(sauce_result)) driver.quit() -@pytest.fixture -def android_rdc_driver(request, data_center): - - username_cap = environ['SAUCE_USERNAME'] - access_key_cap = environ['SAUCE_ACCESS_KEY'] - - options = UiAutomator2Options() - options.platform_name = 'Android' - options.device_name = 'Google.*' - options.automation_name = 'UiAutomator2' - options.app = 'https://github.com/saucelabs/my-demo-app-android/releases/download/2.2.0/mda-2.2.0-25.apk' - sauce_options = { - 'username': username_cap, - 'accessKey': access_key_cap, - 'build': 'RDC-Android-Python-Best-Practice', - 'name': request.node.name, - 'appiumVersion': 'latest', - } - options.set_capability('sauce:options', sauce_options) - - if data_center and data_center.lower() == 'eu': - sauce_url = 'https://ondemand.eu-central-1.saucelabs.com/wd/hub' - else: - sauce_url = 'https://ondemand.us-west-1.saucelabs.com/wd/hub' - - driver = appiumdriver.Remote(sauce_url, options=options) - yield driver - sauce_result = "failed" if request.node.rep_call.failed else "passed" - driver.execute_script("sauce:job-result={}".format(sauce_result)) - driver.quit() - -@pytest.fixture -def ios_rdc_driver(request, data_center): - - username_cap = environ['SAUCE_USERNAME'] - access_key_cap = environ['SAUCE_ACCESS_KEY'] - - options = XCUITestOptions() - options.platform_name = 'iOS' - options.device_name = 'iPhone.*' - options.app = 'https://github.com/saucelabs/sample-app-mobile/releases/download/2.7.1/iOS.RealDevice.SauceLabs.Mobile.Sample.app.2.7.1.ipa' - sauce_options = { - 'username': username_cap, - 'accessKey': access_key_cap, - 'build': 'RDC-iOS-Python-Best-Practice', - 'name': request.node.name, - 'appiumVersion': 'latest', - } - options.set_capability('sauce:options', sauce_options) - - if data_center and data_center.lower() == 'eu': - sauce_url = "https://ondemand.eu-central-1.saucelabs.com/wd/hub" - else: - sauce_url = "https://ondemand.us-west-1.saucelabs.com/wd/hub" - - driver = appiumdriver.Remote(sauce_url, options=options) - yield driver - sauce_result = "failed" if request.node.rep_call.failed else "passed" - driver.execute_script("sauce:job-result={}".format(sauce_result)) - driver.quit() @pytest.hookimpl(hookwrapper=True, tryfirst=True) def pytest_runtest_makereport(item, call): @@ -274,4 +142,3 @@ def pytest_runtest_makereport(item, call): # set an report attribute for each phase of a call, which can # be "setup", "call", "teardown" setattr(item, "rep_" + rep.when, rep) - diff --git a/examples/gitpod/test_appium.py b/examples/gitpod/test_appium.py deleted file mode 100644 index 92b93219..00000000 --- a/examples/gitpod/test_appium.py +++ /dev/null @@ -1,50 +0,0 @@ -import os -import json -import time - -from selenium import webdriver - -class TestSelenium(object): - - def test_appium_with_gitpod(self): - test_name = os.environ.get('PYTEST_CURRENT_TEST').split(':')[-1].split(' ')[0] - gitpod_workspace_id = os.environ.get('GITPOD_WORKSPACE_ID', None) - region = os.environ.get('REGION', 'us-west-1') - app = os.environ.get('APP_NAME', None) - if app: - app = "storage:filename=" + app - else: - app = None - if gitpod_workspace_id: - tags = ['gitpod'] - else: - tags = [] - capabilities = { - 'browserName': os.environ.get('BROWSER_NAME', None), - 'platformName': os.environ.get('PLATFORM_NAME', 'Android'), - 'appium:app': app, - 'appium:deviceName': os.environ.get('DEVICE_NAME', 'Google.*'), - 'appium:platformVersion': os.environ.get('PLATFORM_VERSION', ''), - 'appium:automationName': os.environ.get('AUTOMATION_NAME', 'uiautomator2'), - 'sauce:options': { - 'username': os.environ["SAUCE_USERNAME"], - 'accesskey': os.environ["SAUCE_ACCESS_KEY"], - 'build': os.environ.get('BUILD', None), - 'name': os.environ.get('JOB_NAME', test_name), - 'tags': tags, - } - } - sauce_url = f'https://ondemand.{region}.saucelabs.com:443/wd/hub' - driver = webdriver.Remote(sauce_url, capabilities) - - # Replace this with commands and assertions - if os.environ.get('BROWSER_NAME', None): - driver.get('https://www.saucedemo.com/') - time.sleep(5) - - # Report pass/fail to Sauce Labs - # sauce_result = "failed" - sauce_result = "passed" - driver.execute_script("sauce:job-result={}".format(sauce_result)) - - driver.quit() diff --git a/examples/gitpod/test_selenium.py b/examples/gitpod/test_selenium.py deleted file mode 100644 index 46da38a3..00000000 --- a/examples/gitpod/test_selenium.py +++ /dev/null @@ -1,40 +0,0 @@ -import os -import time - -from selenium import webdriver - -class TestSelenium(object): - - def test_selenium_with_gitpod(self): - test_name = os.environ.get('PYTEST_CURRENT_TEST').split(':')[-1].split(' ')[0] - gitpod_workspace_id = os.environ.get('GITPOD_WORKSPACE_ID', None) - region = os.environ.get('REGION', 'us-west-1') - if gitpod_workspace_id: - tags = ['gitpod'] - else: - tags = [] - capabilities = { - 'browserName': os.environ.get('BROWSER_NAME', 'chrome'), - 'browserVersion': os.environ.get('BROWSER_VERSION', None), - 'platformName': os.environ.get('PLATFORM_NAME', None), - 'sauce:options': { - 'username': os.environ["SAUCE_USERNAME"], - 'accesskey': os.environ["SAUCE_ACCESS_KEY"], - 'build': os.environ.get('BUILD', None), - 'name': os.environ.get('JOB_NAME', test_name), - 'tags': tags, - } - } - sauce_url = f'https://ondemand.{region}.saucelabs.com:443/wd/hub' - driver = webdriver.Remote(sauce_url, capabilities) - - # Add commands and assertions here - driver.get('https://www.saucedemo.com/') - time.sleep(5) - - # Report pass/fail to Sauce Labs - # sauce_result = "failed" - sauce_result = "passed" - driver.execute_script("sauce:job-result={}".format(sauce_result)) - - driver.quit() diff --git a/examples/playwright/Pipfile b/examples/playwright/Pipfile new file mode 100644 index 00000000..e3bef7cc --- /dev/null +++ b/examples/playwright/Pipfile @@ -0,0 +1,11 @@ +[packages] +pytest = "==9.1.1" +pytest-xdist = "==3.8.0" +pytest-playwright = "==0.8.0" +playwright = "==1.61.0" +requests = "==2.34.2" + +[scripts] +playwright-tests = "pytest -n8 ." + +[dev-packages] diff --git a/Pipfile.lock b/examples/playwright/Pipfile.lock similarity index 51% rename from Pipfile.lock rename to examples/playwright/Pipfile.lock index 38992da4..bd4e37dd 100644 --- a/Pipfile.lock +++ b/examples/playwright/Pipfile.lock @@ -1,7 +1,7 @@ { "_meta": { "hash": { - "sha256": "4da5fa97a91fe1a4a7c0af36d0f2a136745eb822d59b8d1eab13bd9c16b04cce" + "sha256": "8b08210dc97b9355c3b71f5b7e92cf0167e22f4d44715df15aa66db3effa6a35" }, "pipfile-spec": 6, "requires": {}, @@ -14,85 +14,14 @@ ] }, "default": { - "apipkg": { - "hashes": [ - "sha256:a16984c39de280701f3f6406ed3af658f2a1965011fe7bb5be34fbb48423b411", - "sha256:c7aa61a4f82697fdaa667e70af1505acf1f7428b1c27b891d204ba7a8a3c5e0d" - ], - "index": "pypi", - "markers": "python_version >= '3.7'", - "version": "==3.0.2" - }, - "appium-python-client": { - "hashes": [ - "sha256:30800f9a53a585814138e7c8f569fd295273f933c9b34ad1a9580f3bf923fc63", - "sha256:da0d3227ee059c31908a16f30a131424713ea96998fcd48e255d2cf9d107b557" - ], - "index": "pypi", - "markers": "python_version >= '3.9'", - "version": "==5.3.1" - }, - "attrs": { - "hashes": [ - "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", - "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32" - ], - "index": "pypi", - "markers": "python_version >= '3.9'", - "version": "==26.1.0" - }, "certifi": { "hashes": [ "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775", "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55" ], - "index": "pypi", "markers": "python_version >= '3.7'", "version": "==2026.7.22" }, - "chardet": { - "hashes": [ - "sha256:0ac3bf11c645734a1701a3804e43eabd98851838192267d08c353a834ab79fea", - "sha256:1173b74051570cf08099d7429d92e4882d375ad4217f92a6e5240ccfb26f231e", - "sha256:23163921dccf3103ce59540b0443c106d2c0a0ff2e0503e05196f5e6fdea453f", - "sha256:25a862cddc6a9ac07023e808aedd297115345fbaabc2690479481ddc0f980e09", - "sha256:27cc23da03630cdecc9aa81a895aa86629c211f995cd57651f0fbc280717bf93", - "sha256:29af5999f654e8729d251f1724a62b538b1262d9292cccaefddf8a02aae1ef6a", - "sha256:365135eaf37ba65a828f8e668eb0a8c38c479dcbec724dc25f4dfd781049c357", - "sha256:3990fffcc6a6045f2234ab72752ad037e3b2d48c72037f244d42738db397eb75", - "sha256:457f619882ba66327d4d8d14c6c342269bdb1e4e1c38e8117df941d14d351b04", - "sha256:4b2799bd58e7245cfa8d4ab2e8ad1d76a5c3a5b1f32318eb6acca4c69a3e7101", - "sha256:4c3da294de1a681097848ab58bd3f2771a674f8039d2d87a5538b28856b815e9", - "sha256:4fbff1907925b0c5a1064cffb5e040cd5e338585c9c552625f30de6bc2f3107a", - "sha256:5d2879598bc220689e8ce509fe9c3f37ad2fca53a36be9c9bd91abdd91dd364f", - "sha256:626f00299ad62dfe937058a09572beed442ccc7b58f87aa667949b20fd3db235", - "sha256:6e3bd9f936e04bae89c254262af08d9e5b98f805175ba1e29d454e6cba3107b7", - "sha256:7005c88da26fd95d8abb8acbe6281d833e9a9181b03cf49b4546c4555389bd97", - "sha256:75d3c65cc16bddf40b8da1fd25ba84fca5f8070f2b14e86083653c1c85aee971", - "sha256:93c45e116dd51b66226a53ade3f9f635e870de5399b90e00ce45dcc311093bf4", - "sha256:9a4904dd5f071b7a7d7f50b4a67a86db3c902d243bf31708f1d5cde2f68239cb", - "sha256:9acd9988a93e09390f3cd231201ea7166c415eb8da1b735928990ffc05cb9fbb", - "sha256:9f3504c139a2ad544077dd2d9e412cd08b01786843d76997cd43bb6de311723c", - "sha256:a9e4486df251b8962e86ea9f139ca235aa6e0542a00f7844c9a04160afb99aa9", - "sha256:acc46d1b8b7d5783216afe15db56d1c179b9a40e5a1558bc13164c4fd20674c4", - "sha256:b95c934b9ad59e2ba8abb9be49df70d3ad1b0d95d864b9fdb7588d4fa8bd921c", - "sha256:bba8bea1b28d927b3e99e47deafe53658d34497c0a891d95ff1ba8ff6663f01c", - "sha256:bfc134b70c846c21ead8e43ada3ae1a805fff732f6922f8abcf2ff27b8f6493d", - "sha256:c0c79b13c9908ac7dfe0a74116ebc9a0f28b2319d23c32f3dfcdfbe1279c7eaf", - "sha256:c7116b0452994734ccff35e154b44240090eb0f4f74b9106292668133557c175", - "sha256:c77867f0c1cb8bd819502249fcdc500364aedb07881e11b743726fa2148e7b6e", - "sha256:cc1d4eb92a4ec1c2df3b490836ffa46922e599d34ce0bb75cf41fd2bf6303d56", - "sha256:ccc1f83ab4bcfb901cf39e0c4ba6bc6e726fc6264735f10e24ceb5cb47387578", - "sha256:cf1efeaf65a6ef2f5b9cc3a1df6f08ba2831b369ccaa4c7018eaf90aa757bb11", - "sha256:cfb54563fe5f130da17c44c6a4e2e8052ba628e5ab4eab7ef8190f736f0f8f72", - "sha256:d892d3dcd652fdef53e3d6327d39b17c0df40a899dfc919abaeb64c974497531", - "sha256:dc50f28bad067393cce0af9091052c3b8df7a23115afd8ba7b2e0947f0cef1f8", - "sha256:e1b98790c284ff813f18f7cf7de5f05ea2435a080030c7f1a8318f3a4f80b131" - ], - "index": "pypi", - "markers": "python_version >= '3.10'", - "version": "==7.4.3" - }, "charset-normalizer": { "hashes": [ "sha256:0327fcd59a935777d83410750c50600ee9571af2846f71ce40f25b13da1ef380", @@ -192,38 +121,11 @@ "markers": "python_version >= '3.7'", "version": "==3.4.9" }, - "click": { - "hashes": [ - "sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6", - "sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76" - ], - "markers": "python_version >= '3.10'", - "version": "==8.4.2" - }, - "decorator": { - "hashes": [ - "sha256:4cbcdd55a6efadb9dbea26b858f4fb3264567b52d69ca0d25b721b553f60ea82", - "sha256:f47fe6fdbd2edd623ecfe36875d37aba411624e2670dd395dddae1358689bb3c" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==5.3.1" - }, - "docutils": { - "hashes": [ - "sha256:25d013af9bf23bc1c7b2b093dff4208166c53a94786c9e447808335ef1185fea", - "sha256:746f5060322511280a1e50eb76846ed6bf2342984b2ac04dc42caa1a8d78799e" - ], - "index": "pypi", - "markers": "python_version >= '3.9'", - "version": "==0.23" - }, "execnet": { "hashes": [ "sha256:63d83bfdd9a23e35b9c6a3261412324f964c2ec8dcd8d3c6916ee9373e0befcd", "sha256:67fba928dd5a544b783f6056f449e5e3931a5c378b128bc18501f7ea79e296ec" ], - "index": "pypi", "markers": "python_version >= '3.8'", "version": "==2.1.2" }, @@ -312,71 +214,27 @@ "markers": "python_version >= '3.10'", "version": "==3.5.4" }, - "h11": { - "hashes": [ - "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", - "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86" - ], - "markers": "python_version >= '3.8'", - "version": "==0.16.0" - }, "idna": { "hashes": [ "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2", "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848" ], - "index": "pypi", "markers": "python_version >= '3.9'", "version": "==3.18" }, - "importlib-metadata": { - "hashes": [ - "sha256:2d21d1cc5a017bd0559e36150c21c830ab1dc304dedd1b7ea85d20f45ef3edd7", - "sha256:a4f57ab599e6a2e3016d7595cfd72eb4661a5106e787a95bcc90c7105b831efc" - ], - "index": "pypi", - "markers": "python_version >= '3.10'", - "version": "==9.0.0" - }, "iniconfig": { "hashes": [ "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12" ], - "index": "pypi", "markers": "python_version >= '3.10'", "version": "==2.3.0" }, - "kitchen": { - "hashes": [ - "sha256:b84cf582f1bd1556b60ebc7370b9d331eb9247b6b070ce89dfe959cba2c0b03c" - ], - "index": "pypi", - "version": "==1.2.6" - }, - "more-itertools": { - "hashes": [ - "sha256:48e8f4d9e7e5878571ecf6f2b4e57634f93cd474cc8cfbd2376f2d11b396e30d", - "sha256:4b65538ae22f6fed0ce4874efd317463a7489796a0939fa66824dd542125a192" - ], - "index": "pypi", - "markers": "python_version >= '3.10'", - "version": "==11.1.0" - }, - "outcome": { - "hashes": [ - "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8", - "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b" - ], - "markers": "python_version >= '3.7'", - "version": "==1.3.0.post0" - }, "packaging": { "hashes": [ "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661" ], - "index": "pypi", "markers": "python_version >= '3.8'", "version": "==26.2" }, @@ -400,19 +258,9 @@ "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746" ], - "index": "pypi", "markers": "python_version >= '3.9'", "version": "==1.6.0" }, - "py": { - "hashes": [ - "sha256:51c75c4126074b472f746a24399ad32f6053d1b34b68d2fa41e558e6f4a98719", - "sha256:607c53218732647dff4acdfcd50cb62615cedf612e72d1724fb1a0cc6405b378" - ], - "index": "pypi", - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3, 3.4'", - "version": "==1.11.0" - }, "pyee": { "hashes": [ "sha256:0b931f7c14535667ed4c7e0d531716368715e860b988770fc7eb8578d1f67fc8", @@ -429,24 +277,6 @@ "markers": "python_version >= '3.9'", "version": "==2.20.0" }, - "pyparsing": { - "hashes": [ - "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d", - "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc" - ], - "index": "pypi", - "markers": "python_version >= '3.9'", - "version": "==3.3.2" - }, - "pysocks": { - "hashes": [ - "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299", - "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5", - "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0" - ], - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", - "version": "==1.7.1" - }, "pytest": { "hashes": [ "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", @@ -490,86 +320,6 @@ "markers": "python_version >= '3.7'", "version": "==8.0.4" }, - "pyyaml": { - "hashes": [ - "sha256:00c4bdeba853cc34e7dd471f16b4114f4162dc03e6b7afcc2128711f0eca823c", - "sha256:0150219816b6a1fa26fb4699fb7daa9caf09eb1999f3b70fb6e786805e80375a", - "sha256:02893d100e99e03eda1c8fd5c441d8c60103fd175728e23e431db1b589cf5ab3", - "sha256:02ea2dfa234451bbb8772601d7b8e426c2bfa197136796224e50e35a78777956", - "sha256:0f29edc409a6392443abf94b9cf89ce99889a1dd5376d94316ae5145dfedd5d6", - "sha256:10892704fc220243f5305762e276552a0395f7beb4dbf9b14ec8fd43b57f126c", - "sha256:16249ee61e95f858e83976573de0f5b2893b3677ba71c9dd36b9cf8be9ac6d65", - "sha256:1d37d57ad971609cf3c53ba6a7e365e40660e3be0e5175fa9f2365a379d6095a", - "sha256:1ebe39cb5fc479422b83de611d14e2c0d3bb2a18bbcb01f229ab3cfbd8fee7a0", - "sha256:214ed4befebe12df36bcc8bc2b64b396ca31be9304b8f59e25c11cf94a4c033b", - "sha256:2283a07e2c21a2aa78d9c4442724ec1eb15f5e42a723b99cb3d822d48f5f7ad1", - "sha256:22ba7cfcad58ef3ecddc7ed1db3409af68d023b7f940da23c6c2a1890976eda6", - "sha256:27c0abcb4a5dac13684a37f76e701e054692a9b2d3064b70f5e4eb54810553d7", - "sha256:28c8d926f98f432f88adc23edf2e6d4921ac26fb084b028c733d01868d19007e", - "sha256:2e71d11abed7344e42a8849600193d15b6def118602c4c176f748e4583246007", - "sha256:34d5fcd24b8445fadc33f9cf348c1047101756fd760b4dacb5c3e99755703310", - "sha256:37503bfbfc9d2c40b344d06b2199cf0e96e97957ab1c1b546fd4f87e53e5d3e4", - "sha256:3c5677e12444c15717b902a5798264fa7909e41153cdf9ef7ad571b704a63dd9", - "sha256:3ff07ec89bae51176c0549bc4c63aa6202991da2d9a6129d7aef7f1407d3f295", - "sha256:41715c910c881bc081f1e8872880d3c650acf13dfa8214bad49ed4cede7c34ea", - "sha256:418cf3f2111bc80e0933b2cd8cd04f286338bb88bdc7bc8e6dd775ebde60b5e0", - "sha256:44edc647873928551a01e7a563d7452ccdebee747728c1080d881d68af7b997e", - "sha256:4a2e8cebe2ff6ab7d1050ecd59c25d4c8bd7e6f400f5f82b96557ac0abafd0ac", - "sha256:4ad1906908f2f5ae4e5a8ddfce73c320c2a1429ec52eafd27138b7f1cbe341c9", - "sha256:501a031947e3a9025ed4405a168e6ef5ae3126c59f90ce0cd6f2bfc477be31b7", - "sha256:5190d403f121660ce8d1d2c1bb2ef1bd05b5f68533fc5c2ea899bd15f4399b35", - "sha256:5498cd1645aa724a7c71c8f378eb29ebe23da2fc0d7a08071d89469bf1d2defb", - "sha256:5cf4e27da7e3fbed4d6c3d8e797387aaad68102272f8f9752883bc32d61cb87b", - "sha256:5e0b74767e5f8c593e8c9b5912019159ed0533c70051e9cce3e8b6aa699fcd69", - "sha256:5ed875a24292240029e4483f9d4a4b8a1ae08843b9c54f43fcc11e404532a8a5", - "sha256:5fcd34e47f6e0b794d17de1b4ff496c00986e1c83f7ab2fb8fcfe9616ff7477b", - "sha256:5fdec68f91a0c6739b380c83b951e2c72ac0197ace422360e6d5a959d8d97b2c", - "sha256:6344df0d5755a2c9a276d4473ae6b90647e216ab4757f8426893b5dd2ac3f369", - "sha256:64386e5e707d03a7e172c0701abfb7e10f0fb753ee1d773128192742712a98fd", - "sha256:652cb6edd41e718550aad172851962662ff2681490a8a711af6a4d288dd96824", - "sha256:66291b10affd76d76f54fad28e22e51719ef9ba22b29e1d7d03d6777a9174198", - "sha256:66e1674c3ef6f541c35191caae2d429b967b99e02040f5ba928632d9a7f0f065", - "sha256:6adc77889b628398debc7b65c073bcb99c4a0237b248cacaf3fe8a557563ef6c", - "sha256:79005a0d97d5ddabfeeea4cf676af11e647e41d81c9a7722a193022accdb6b7c", - "sha256:7c6610def4f163542a622a73fb39f534f8c101d690126992300bf3207eab9764", - "sha256:7f047e29dcae44602496db43be01ad42fc6f1cc0d8cd6c83d342306c32270196", - "sha256:8098f252adfa6c80ab48096053f512f2321f0b998f98150cea9bd23d83e1467b", - "sha256:850774a7879607d3a6f50d36d04f00ee69e7fc816450e5f7e58d7f17f1ae5c00", - "sha256:8d1fab6bb153a416f9aeb4b8763bc0f22a5586065f86f7664fc23339fc1c1fac", - "sha256:8da9669d359f02c0b91ccc01cac4a67f16afec0dac22c2ad09f46bee0697eba8", - "sha256:8dc52c23056b9ddd46818a57b78404882310fb473d63f17b07d5c40421e47f8e", - "sha256:9149cad251584d5fb4981be1ecde53a1ca46c891a79788c0df828d2f166bda28", - "sha256:93dda82c9c22deb0a405ea4dc5f2d0cda384168e466364dec6255b293923b2f3", - "sha256:96b533f0e99f6579b3d4d4995707cf36df9100d67e0c8303a0c55b27b5f99bc5", - "sha256:9c57bb8c96f6d1808c030b1687b9b5fb476abaa47f0db9c0101f5e9f394e97f4", - "sha256:9c7708761fccb9397fe64bbc0395abcae8c4bf7b0eac081e12b809bf47700d0b", - "sha256:9f3bfb4965eb874431221a3ff3fdcddc7e74e3b07799e0e84ca4a0f867d449bf", - "sha256:a33284e20b78bd4a18c8c2282d549d10bc8408a2a7ff57653c0cf0b9be0afce5", - "sha256:a80cb027f6b349846a3bf6d73b5e95e782175e52f22108cfa17876aaeff93702", - "sha256:b30236e45cf30d2b8e7b3e85881719e98507abed1011bf463a8fa23e9c3e98a8", - "sha256:b3bc83488de33889877a0f2543ade9f70c67d66d9ebb4ac959502e12de895788", - "sha256:b865addae83924361678b652338317d1bd7e79b1f4596f96b96c77a5a34b34da", - "sha256:b8bb0864c5a28024fac8a632c443c87c5aa6f215c0b126c449ae1a150412f31d", - "sha256:ba1cc08a7ccde2d2ec775841541641e4548226580ab850948cbfda66a1befcdc", - "sha256:bdb2c67c6c1390b63c6ff89f210c8fd09d9a1217a465701eac7316313c915e4c", - "sha256:c1ff362665ae507275af2853520967820d9124984e0f7466736aea23d8611fba", - "sha256:c2514fceb77bc5e7a2f7adfaa1feb2fb311607c9cb518dbc378688ec73d8292f", - "sha256:c3355370a2c156cffb25e876646f149d5d68f5e0a3ce86a5084dd0b64a994917", - "sha256:c458b6d084f9b935061bc36216e8a69a7e293a2f1e68bf956dcd9e6cbcd143f5", - "sha256:d0eae10f8159e8fdad514efdc92d74fd8d682c933a6dd088030f3834bc8e6b26", - "sha256:d76623373421df22fb4cf8817020cbb7ef15c725b9d5e45f17e189bfc384190f", - "sha256:ebc55a14a21cb14062aa4162f906cd962b28e2e9ea38f9b4391244cd8de4ae0b", - "sha256:eda16858a3cab07b80edaf74336ece1f986ba330fdb8ee0d6c0d68fe82bc96be", - "sha256:ee2922902c45ae8ccada2c5b501ab86c36525b883eff4255313a253a3160861c", - "sha256:efd7b85f94a6f21e4932043973a7ba2613b059c4a000551892ac9f1d11f5baf3", - "sha256:f7057c9a337546edc7973c0d3ba84ddcdf0daa14533c2065749c9075001090e6", - "sha256:fa160448684b4e94d80416c0fa4aac48967a969efe22931448d853ada8baf926", - "sha256:fc09d0aa354569bc501d4e787133afc08552722d3ab34836a80547331bb5d4a0" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==6.0.3" - }, "requests": { "hashes": [ "sha256:2a0d60c172f83ac6ab31e4554906c0f3b3588d37b5cb939b1c061f4907e278e0", @@ -579,92 +329,6 @@ "markers": "python_version >= '3.10'", "version": "==2.34.2" }, - "robotframework": { - "hashes": [ - "sha256:1c934e7f43600de407860cd2bd2fdc41adad4a4a785d8b46b1ed485fdc0f6c9f", - "sha256:6e80f84cdc997bdde2abb6b729ac3531457ecf6d2e41abfb87a541877ab367bf" - ], - "index": "pypi", - "markers": "python_version >= '3.8'", - "version": "==7.4.2" - }, - "robotframework-pabot": { - "hashes": [ - "sha256:497c3d72551c76eda21029df6a28c6b2ed227e63c4a8510e1c6a0690b9e2be91", - "sha256:e7b95d031e9f04b77312b04a1fd835b9791f022b3436b63b507a720bfec05bb4" - ], - "index": "pypi", - "markers": "python_version >= '3.6'", - "version": "==5.2.2" - }, - "robotframework-pythonlibcore": { - "hashes": [ - "sha256:c45acbdf781b35a5cbac8e1c019fedab87d99f34ff29a6c99b774fbd95313f27", - "sha256:db8d707961a0b83a5497d9c02b8919805e47b73907d0a588c79593518dc133a7" - ], - "index": "pypi", - "markers": "python_version >= '3.10' and python_version < '4'", - "version": "==4.6.0" - }, - "robotframework-seleniumlibrary": { - "hashes": [ - "sha256:198067f838acb01dd54348b68ee83a7cc53dd533c2171385a7554ab28b5ef33d", - "sha256:6ff7df0dd9a9ea75f78dd2c7fa2dac0098e96e64f507e69d3bc21f41056e5d56" - ], - "index": "pypi", - "markers": "python_version >= '3.10'", - "version": "==6.9.0" - }, - "sa11y": { - "hashes": [ - "sha256:7ffa3b41b57f1d69955bb14384e6f145853e2df3250b29818e8797e71925af69" - ], - "index": "pypi", - "markers": "python_version >= '3'", - "version": "==0.2.3" - }, - "sauceclient": { - "hashes": [ - "sha256:5b8e61c9318ae7733df12e20f943c6c56adc9898f889e9b49637c879ad075bd3", - "sha256:cc4a7f265ed340d14b2fb49993a918786111cfcd9a42c7dc6953c70f7f9efdbd" - ], - "index": "pypi", - "markers": "python_version >= '3.10'", - "version": "==1.0.2" - }, - "selenium": { - "hashes": [ - "sha256:54f7e1a4df5f7508ac8c38ce2ea584db1b27083dd79962b22524219219df5cbe", - "sha256:f03e864770a21ab32009961c9d015cb2c6275eba45c926c272e02d90af423aad" - ], - "index": "pypi", - "markers": "python_version >= '3.10'", - "version": "==4.46.0" - }, - "six": { - "hashes": [ - "sha256:4721f391ed90541fddacab5acf947aa0d3dc7d27b2e1e8eda2be8970586c3274", - "sha256:ff70335d468e7eb6ec65b95b99d3a2836546063f63acc5171de367e834932a81" - ], - "index": "pypi", - "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2'", - "version": "==1.17.0" - }, - "sniffio": { - "hashes": [ - "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", - "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc" - ], - "markers": "python_version >= '3.7'", - "version": "==1.3.1" - }, - "sortedcontainers": { - "hashes": [ - "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", - "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0" - ], - "version": "==2.4.0" - }, "text-unidecode": { "hashes": [ "sha256:1311f10e8b895935241623731c2ba64f4c455287888b18189350b67134a822e8", @@ -672,31 +336,6 @@ ], "version": "==1.3" }, - "toml": { - "hashes": [ - "sha256:806143ae5bfb6a3c6e736a764057db0e6a0e05e338b5630894a5f779cabb4f9b", - "sha256:b3bda1d108d5dd99f4a20d24d9c348e91c4db7ab1b749200bded2f839ccbe68f" - ], - "index": "pypi", - "markers": "python_version >= '2.6' and python_version not in '3.0, 3.1, 3.2'", - "version": "==0.10.2" - }, - "trio": { - "hashes": [ - "sha256:3bd5d87f781d9b0192d592aef28691f8951d6c2e41b7e1da4c25cde6c180ae9b", - "sha256:a29b92b73f09d4b48ed249acd91073281a7f1063f09caba5dc70465b5c7aa970" - ], - "markers": "python_version >= '3.10'", - "version": "==0.33.0" - }, - "trio-websocket": { - "hashes": [ - "sha256:22c72c436f3d1e264d0910a3951934798dcc5b00ae56fc4ee079d46c7cf20fae", - "sha256:df605665f1db533f4a386c94525870851096a223adcb97f72a07e8b4beba45b6" - ], - "markers": "python_version >= '3.8'", - "version": "==0.12.2" - }, "typing-extensions": { "hashes": [ "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", @@ -706,41 +345,12 @@ "version": "==4.16.0" }, "urllib3": { - "extras": [ - "socks" - ], "hashes": [ "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897" ], - "index": "pypi", "markers": "python_version >= '3.10'", "version": "==2.7.0" - }, - "websocket-client": { - "hashes": [ - "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98", - "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef" - ], - "markers": "python_version >= '3.9'", - "version": "==1.9.0" - }, - "wsproto": { - "hashes": [ - "sha256:61eea322cdf56e8cc904bd3ad7573359a242ba65688716b0710a5eb12beab584", - "sha256:b86885dcf294e15204919950f666e06ffc6c7c114ca900b060d6e16293528294" - ], - "markers": "python_version >= '3.10'", - "version": "==1.3.2" - }, - "zipp": { - "hashes": [ - "sha256:25ad4e16390cd314347dd8f1de67a2ac538ae658ed4ab9db16029c07c188e97f", - "sha256:4cb57381f544315db7688e976e922a2b18cdb513d21cc194eb42232ba2a3e602" - ], - "index": "pypi", - "markers": "python_version >= '3.10'", - "version": "==4.1.0" } }, "develop": {} diff --git a/examples/robotframework/desktop_web/Pipfile b/examples/robotframework/desktop_web/Pipfile new file mode 100644 index 00000000..a1001634 --- /dev/null +++ b/examples/robotframework/desktop_web/Pipfile @@ -0,0 +1,11 @@ +[packages] +robotframework = "==7.4.2" +robotframework-pabot = "==5.2.2" +robotframework-seleniumlibrary = "==6.9.0" +robotframework-pythonlibcore = "==4.6.0" + +[scripts] +robot-desktop-web-us = "pabot --argumentfile1 chrome_config.txt --argumentfile2 firefox_config.txt --variable DATA_CENTER:'https://ondemand.us-west-1.saucelabs.com/wd/hub' Tests/" +robot-desktop-web-eu = "pabot --argumentfile1 chrome_config.txt --argumentfile2 firefox_config.txt --variable DATA_CENTER:'https://ondemand.eu-central-1.saucelabs.com/wd/hub' Tests/" + +[dev-packages] diff --git a/examples/robotframework/desktop_web/Pipfile.lock b/examples/robotframework/desktop_web/Pipfile.lock new file mode 100644 index 00000000..7534cfe5 --- /dev/null +++ b/examples/robotframework/desktop_web/Pipfile.lock @@ -0,0 +1,186 @@ +{ + "_meta": { + "hash": { + "sha256": "4b6b588d069eb00b16d066dffd5da01d5ae84cbd63a1f223b432d9f5a578c4d0" + }, + "pipfile-spec": 6, + "requires": {}, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "attrs": { + "hashes": [ + "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", + "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32" + ], + "markers": "python_version >= '3.9'", + "version": "==26.1.0" + }, + "certifi": { + "hashes": [ + "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775", + "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55" + ], + "markers": "python_version >= '3.7'", + "version": "==2026.7.22" + }, + "click": { + "hashes": [ + "sha256:9a6cea6e60b17ebe0a44c5cc636d94f09bd66142c1cd7d8b4cd731c4917a15f6", + "sha256:e6f9f66136c816745b9d65817da91d61d957fb16e02e4dcd0552553c5a197b76" + ], + "markers": "python_version >= '3.10'", + "version": "==8.4.2" + }, + "h11": { + "hashes": [ + "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", + "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86" + ], + "markers": "python_version >= '3.8'", + "version": "==0.16.0" + }, + "idna": { + "hashes": [ + "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2", + "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848" + ], + "markers": "python_version >= '3.9'", + "version": "==3.18" + }, + "outcome": { + "hashes": [ + "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8", + "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b" + ], + "markers": "python_version >= '3.7'", + "version": "==1.3.0.post0" + }, + "pysocks": { + "hashes": [ + "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299", + "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5", + "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.7.1" + }, + "robotframework": { + "hashes": [ + "sha256:1c934e7f43600de407860cd2bd2fdc41adad4a4a785d8b46b1ed485fdc0f6c9f", + "sha256:6e80f84cdc997bdde2abb6b729ac3531457ecf6d2e41abfb87a541877ab367bf" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==7.4.2" + }, + "robotframework-pabot": { + "hashes": [ + "sha256:497c3d72551c76eda21029df6a28c6b2ed227e63c4a8510e1c6a0690b9e2be91", + "sha256:e7b95d031e9f04b77312b04a1fd835b9791f022b3436b63b507a720bfec05bb4" + ], + "index": "pypi", + "markers": "python_version >= '3.6'", + "version": "==5.2.2" + }, + "robotframework-pythonlibcore": { + "hashes": [ + "sha256:c45acbdf781b35a5cbac8e1c019fedab87d99f34ff29a6c99b774fbd95313f27", + "sha256:db8d707961a0b83a5497d9c02b8919805e47b73907d0a588c79593518dc133a7" + ], + "index": "pypi", + "markers": "python_version >= '3.10' and python_version < '4'", + "version": "==4.6.0" + }, + "robotframework-seleniumlibrary": { + "hashes": [ + "sha256:198067f838acb01dd54348b68ee83a7cc53dd533c2171385a7554ab28b5ef33d", + "sha256:6ff7df0dd9a9ea75f78dd2c7fa2dac0098e96e64f507e69d3bc21f41056e5d56" + ], + "index": "pypi", + "markers": "python_version >= '3.10'", + "version": "==6.9.0" + }, + "selenium": { + "hashes": [ + "sha256:54f7e1a4df5f7508ac8c38ce2ea584db1b27083dd79962b22524219219df5cbe", + "sha256:f03e864770a21ab32009961c9d015cb2c6275eba45c926c272e02d90af423aad" + ], + "markers": "python_version >= '3.10'", + "version": "==4.46.0" + }, + "sniffio": { + "hashes": [ + "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", + "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc" + ], + "markers": "python_version >= '3.7'", + "version": "==1.3.1" + }, + "sortedcontainers": { + "hashes": [ + "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", + "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0" + ], + "version": "==2.4.0" + }, + "trio": { + "hashes": [ + "sha256:3bd5d87f781d9b0192d592aef28691f8951d6c2e41b7e1da4c25cde6c180ae9b", + "sha256:a29b92b73f09d4b48ed249acd91073281a7f1063f09caba5dc70465b5c7aa970" + ], + "markers": "python_version >= '3.10'", + "version": "==0.33.0" + }, + "trio-websocket": { + "hashes": [ + "sha256:22c72c436f3d1e264d0910a3951934798dcc5b00ae56fc4ee079d46c7cf20fae", + "sha256:df605665f1db533f4a386c94525870851096a223adcb97f72a07e8b4beba45b6" + ], + "markers": "python_version >= '3.8'", + "version": "==0.12.2" + }, + "typing-extensions": { + "hashes": [ + "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", + "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5" + ], + "markers": "python_version >= '3.9'", + "version": "==4.16.0" + }, + "urllib3": { + "extras": [ + "socks" + ], + "hashes": [ + "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", + "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897" + ], + "markers": "python_version >= '3.10'", + "version": "==2.7.0" + }, + "websocket-client": { + "hashes": [ + "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98", + "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef" + ], + "markers": "python_version >= '3.9'", + "version": "==1.9.0" + }, + "wsproto": { + "hashes": [ + "sha256:61eea322cdf56e8cc904bd3ad7573359a242ba65688716b0710a5eb12beab584", + "sha256:b86885dcf294e15204919950f666e06ffc6c7c114ca900b060d6e16293528294" + ], + "markers": "python_version >= '3.10'", + "version": "==1.3.2" + } + }, + "develop": {} +} diff --git a/examples/robotframework/desktop_web/README.md b/examples/robotframework/desktop_web/README.md index f8efe7c7..6a91ffaa 100644 --- a/examples/robotframework/desktop_web/README.md +++ b/examples/robotframework/desktop_web/README.md @@ -23,9 +23,9 @@ This code is provided on an "AS-IS” basis without warranty of any kind, either $ export SAUCE_ACCESS_KEY= ``` 3. Project Dependencies - * Install packages (Use sudo if necessary) + * Install [pipenv](https://pipenv.pypa.io/en/latest/) and install packages from this directory's `Pipfile` ``` - $ pip install -r requirements.txt + $ pipenv install ``` ### Running Tests diff --git a/examples/robotframework/native_mobile/Pipfile b/examples/robotframework/native_mobile/Pipfile new file mode 100644 index 00000000..488d9f6a --- /dev/null +++ b/examples/robotframework/native_mobile/Pipfile @@ -0,0 +1,11 @@ +[packages] +robotframework = "==7.4.2" +robotframework-pabot = "==5.2.2" + +[scripts] +robot-android-us = "pabot --variable DATA_CENTER:'https://ondemand.us-west-1.saucelabs.com/wd/hub' -A android/android_config.txt android/tests/" +robot-android-eu = "pabot --variable DATA_CENTER:'https://ondemand.eu-central-1.saucelabs.com/wd/hub' -A android/android_config.txt android/tests/" +robot-ios-us = "pabot --variable DATA_CENTER:'https://ondemand.us-west-1.saucelabs.com/wd/hub' -A ios/iphone_config.txt ios/tests/" +robot-ios-eu = "pabot --variable DATA_CENTER:'https://ondemand.eu-central-1.saucelabs.com/wd/hub' -A ios/iphone_config.txt ios/tests/" + +[dev-packages] diff --git a/examples/robotframework/native_mobile/Pipfile.lock b/examples/robotframework/native_mobile/Pipfile.lock new file mode 100644 index 00000000..0edddd4b --- /dev/null +++ b/examples/robotframework/native_mobile/Pipfile.lock @@ -0,0 +1,37 @@ +{ + "_meta": { + "hash": { + "sha256": "41f876ff1bc69fcc202208f1ce7380e4b8315743208f39019137aa807d113f72" + }, + "pipfile-spec": 6, + "requires": {}, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "robotframework": { + "hashes": [ + "sha256:1c934e7f43600de407860cd2bd2fdc41adad4a4a785d8b46b1ed485fdc0f6c9f", + "sha256:6e80f84cdc997bdde2abb6b729ac3531457ecf6d2e41abfb87a541877ab367bf" + ], + "index": "pypi", + "markers": "python_version >= '3.8'", + "version": "==7.4.2" + }, + "robotframework-pabot": { + "hashes": [ + "sha256:497c3d72551c76eda21029df6a28c6b2ed227e63c4a8510e1c6a0690b9e2be91", + "sha256:e7b95d031e9f04b77312b04a1fd835b9791f022b3436b63b507a720bfec05bb4" + ], + "index": "pypi", + "markers": "python_version >= '3.6'", + "version": "==5.2.2" + } + }, + "develop": {} +} diff --git a/examples/selenium/Pipfile b/examples/selenium/Pipfile new file mode 100644 index 00000000..1e68df07 --- /dev/null +++ b/examples/selenium/Pipfile @@ -0,0 +1,8 @@ +[packages] +pytest = "==9.1.1" +selenium = "==4.46.0" + +[scripts] +demo = "pytest ." + +[dev-packages] diff --git a/examples/selenium/Pipfile.lock b/examples/selenium/Pipfile.lock new file mode 100644 index 00000000..286fa23b --- /dev/null +++ b/examples/selenium/Pipfile.lock @@ -0,0 +1,184 @@ +{ + "_meta": { + "hash": { + "sha256": "ddd6db106b0cb16232faf4bd16d4bc2a2b8d2d74090502563d32932819595043" + }, + "pipfile-spec": 6, + "requires": {}, + "sources": [ + { + "name": "pypi", + "url": "https://pypi.org/simple", + "verify_ssl": true + } + ] + }, + "default": { + "attrs": { + "hashes": [ + "sha256:c647aa4a12dfbad9333ca4e71fe62ddc36f4e63b2d260a37a8b83d2f043ac309", + "sha256:d03ceb89cb322a8fd706d4fb91940737b6642aa36998fe130a9bc96c985eff32" + ], + "markers": "python_version >= '3.9'", + "version": "==26.1.0" + }, + "certifi": { + "hashes": [ + "sha256:62f22742b58a1a33014a2b6b706588a8d7e2a88ae7bd1a6ebe8c992928483775", + "sha256:741e2c3b351ddf169a738da9f2c048608ff7f2c5cc02f1ebc6b118bb090d5d55" + ], + "markers": "python_version >= '3.7'", + "version": "==2026.7.22" + }, + "h11": { + "hashes": [ + "sha256:4e35b956cf45792e4caa5885e69fba00bdbc6ffafbfa020300e549b208ee5ff1", + "sha256:63cf8bbe7522de3bf65932fda1d9c2772064ffb3dae62d55932da54b31cb6c86" + ], + "markers": "python_version >= '3.8'", + "version": "==0.16.0" + }, + "idna": { + "hashes": [ + "sha256:7f952cbe720b688055e3f87de14f5c3e5fdaa8bc3928985c4077ca689de849a2", + "sha256:ffb385a7e039654cef1ab9ef32c6fafe283c0c0467bba1d9029738ce4a14a848" + ], + "markers": "python_version >= '3.9'", + "version": "==3.18" + }, + "iniconfig": { + "hashes": [ + "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", + "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12" + ], + "markers": "python_version >= '3.10'", + "version": "==2.3.0" + }, + "outcome": { + "hashes": [ + "sha256:9dcf02e65f2971b80047b377468e72a268e15c0af3cf1238e6ff14f7f91143b8", + "sha256:e771c5ce06d1415e356078d3bdd68523f284b4ce5419828922b6871e65eda82b" + ], + "markers": "python_version >= '3.7'", + "version": "==1.3.0.post0" + }, + "packaging": { + "hashes": [ + "sha256:5fc45236b9446107ff2415ce77c807cee2862cb6fac22b8a73826d0693b0980e", + "sha256:ff452ff5a3e828ce110190feff1178bb1f2ea2281fa2075aadb987c2fb221661" + ], + "markers": "python_version >= '3.8'", + "version": "==26.2" + }, + "pluggy": { + "hashes": [ + "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", + "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746" + ], + "markers": "python_version >= '3.9'", + "version": "==1.6.0" + }, + "pygments": { + "hashes": [ + "sha256:6757cd03768053ff99f3039c1a36d6c0aa0b263438fcab17520b30a303a82b5f", + "sha256:81a9e26dd42fd28a23a2d169d86d7ac03b46e2f8b59ed4698fb4785f946d0176" + ], + "markers": "python_version >= '3.9'", + "version": "==2.20.0" + }, + "pysocks": { + "hashes": [ + "sha256:08e69f092cc6dbe92a0fdd16eeb9b9ffbc13cadfe5ca4c7bd92ffb078b293299", + "sha256:2725bd0a9925919b9b51739eea5f9e2bae91e83288108a9ad338b2e3a4435ee5", + "sha256:3f8804571ebe159c380ac6de37643bb4685970655d3bba243530d6558b799aa0" + ], + "markers": "python_version >= '2.7' and python_version not in '3.0, 3.1, 3.2, 3.3'", + "version": "==1.7.1" + }, + "pytest": { + "hashes": [ + "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", + "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c" + ], + "index": "pypi", + "markers": "python_version >= '3.10'", + "version": "==9.1.1" + }, + "selenium": { + "hashes": [ + "sha256:54f7e1a4df5f7508ac8c38ce2ea584db1b27083dd79962b22524219219df5cbe", + "sha256:f03e864770a21ab32009961c9d015cb2c6275eba45c926c272e02d90af423aad" + ], + "index": "pypi", + "markers": "python_version >= '3.10'", + "version": "==4.46.0" + }, + "sniffio": { + "hashes": [ + "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2", + "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc" + ], + "markers": "python_version >= '3.7'", + "version": "==1.3.1" + }, + "sortedcontainers": { + "hashes": [ + "sha256:25caa5a06cc30b6b83d11423433f65d1f9d76c4c6a0c90e3379eaa43b9bfdb88", + "sha256:a163dcaede0f1c021485e957a39245190e74249897e2ae4b2aa38595db237ee0" + ], + "version": "==2.4.0" + }, + "trio": { + "hashes": [ + "sha256:3bd5d87f781d9b0192d592aef28691f8951d6c2e41b7e1da4c25cde6c180ae9b", + "sha256:a29b92b73f09d4b48ed249acd91073281a7f1063f09caba5dc70465b5c7aa970" + ], + "markers": "python_version >= '3.10'", + "version": "==0.33.0" + }, + "trio-websocket": { + "hashes": [ + "sha256:22c72c436f3d1e264d0910a3951934798dcc5b00ae56fc4ee079d46c7cf20fae", + "sha256:df605665f1db533f4a386c94525870851096a223adcb97f72a07e8b4beba45b6" + ], + "markers": "python_version >= '3.8'", + "version": "==0.12.2" + }, + "typing-extensions": { + "hashes": [ + "sha256:481caa481374e813c1b176ada14e97f1f67a4539ce9cfeb3f350d78d6370c2e8", + "sha256:dc983d19a509c94dba722ee6abd33940f7c05a89e243c47e907eb4db6f1a43e5" + ], + "markers": "python_version >= '3.9'", + "version": "==4.16.0" + }, + "urllib3": { + "extras": [ + "socks" + ], + "hashes": [ + "sha256:231e0ec3b63ceb14667c67be60f2f2c40a518cb38b03af60abc813da26505f4c", + "sha256:9fb4c81ebbb1ce9531cce37674bbc6f1360472bc18ca9a553ede278ef7276897" + ], + "markers": "python_version >= '3.10'", + "version": "==2.7.0" + }, + "websocket-client": { + "hashes": [ + "sha256:9e813624b6eb619999a97dc7958469217c3176312b3a16a4bd1bc7e08a46ec98", + "sha256:af248a825037ef591efbf6ed20cc5faa03d3b47b9e5a2230a529eeee1c1fc3ef" + ], + "markers": "python_version >= '3.9'", + "version": "==1.9.0" + }, + "wsproto": { + "hashes": [ + "sha256:61eea322cdf56e8cc904bd3ad7573359a242ba65688716b0710a5eb12beab584", + "sha256:b86885dcf294e15204919950f666e06ffc6c7c114ca900b060d6e16293528294" + ], + "markers": "python_version >= '3.10'", + "version": "==1.3.2" + } + }, + "develop": {} +} diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index b68bec7f..00000000 --- a/requirements.txt +++ /dev/null @@ -1,33 +0,0 @@ --i https://pypi.org/simple -apipkg==3.0.2 -appium-python-client==5.3.1 -attrs==26.1.0 -certifi==2026.7.22 -chardet==7.4.3 -decorator==5.3.1 -docutils==0.23 -execnet==2.1.2 -idna==3.18 -importlib-metadata==9.0.0 ; python_version < '3.8' -iniconfig==2.3.0 -kitchen==1.2.6 -more-itertools==11.1.0 -packaging==26.2 -pluggy==1.6.0 -py==1.11.0 -pyparsing==3.3.2 -pytest-xdist==3.8.0 -pytest==9.1.1 -pytest-playwright==0.8.0 -pyyaml==6.0.3 -requests==2.34.2 -robotframework-pabot==5.2.2 -robotframework-pythonlibcore==4.6.0 -robotframework-seleniumlibrary==6.9.0 -robotframework==7.4.2 -sauceclient==1.0.2 -selenium==4.46.0 -six==1.17.0 -toml==0.10.2 -urllib3==2.7.0 -zipp==4.1.0