{"id":19041663,"url":"https://github.com/hudsonssrosa/pyon-behave-ui-tests-nativeapps","last_synced_at":"2026-06-23T11:32:24.058Z","repository":{"id":126290234,"uuid":"373452245","full_name":"hudsonssrosa/pyon-behave-ui-tests-nativeapps","owner":"hudsonssrosa","description":"PYON-BEHAVE | Appium-based UI Automated Testing Framework in Python-Behave","archived":false,"fork":false,"pushed_at":"2021-09-28T12:37:27.000Z","size":14555,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-02-21T22:43:28.675Z","etag":null,"topics":["allure-report","android-app-automation","appium-client","behave-framework","cli","configcat","ios-app-automation","local-machine","mobile-testing","native-apps","pageobject-pattern","python","ui-testing"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/hudsonssrosa.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2021-06-03T09:29:04.000Z","updated_at":"2022-10-27T15:43:47.000Z","dependencies_parsed_at":"2023-06-16T04:15:09.478Z","dependency_job_id":null,"html_url":"https://github.com/hudsonssrosa/pyon-behave-ui-tests-nativeapps","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/hudsonssrosa/pyon-behave-ui-tests-nativeapps","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hudsonssrosa%2Fpyon-behave-ui-tests-nativeapps","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hudsonssrosa%2Fpyon-behave-ui-tests-nativeapps/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hudsonssrosa%2Fpyon-behave-ui-tests-nativeapps/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hudsonssrosa%2Fpyon-behave-ui-tests-nativeapps/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/hudsonssrosa","download_url":"https://codeload.github.com/hudsonssrosa/pyon-behave-ui-tests-nativeapps/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/hudsonssrosa%2Fpyon-behave-ui-tests-nativeapps/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34686727,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-23T02:00:07.161Z","response_time":65,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["allure-report","android-app-automation","appium-client","behave-framework","cli","configcat","ios-app-automation","local-machine","mobile-testing","native-apps","pageobject-pattern","python","ui-testing"],"created_at":"2024-11-08T22:30:42.413Z","updated_at":"2026-06-23T11:32:24.039Z","avatar_url":"https://github.com/hudsonssrosa.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cimg src=\".resources/logos/pyon_logo_min.png\" height=\"360\"\u003e\n\n\n# pyon-behave-ui-tests-native-apps\nPYON-BEHAVE | Appium-based UI Automated Testing Framework in Python-Behave for Native Apps\n\nPyon UI Test Automation project is available to implement UI tests for web and mobile applications with the following stacks and approaches:\n\n- Programming Language: [Python-based](https://www.python.org/downloads/).\n- Framework for behavioural tests: [Behave](https://behave.readthedocs.io/en/latest/)\n- Minimal library requirements: [Appium Python Client](https://pypi.org/project/Appium-Python-Client/0.26/) and optionally: [Selenium](https://pypi.org/project/selenium/)\n\nTo know how you can configure your environment to implement and execute this project locally or even remotely, follow all the instructions from this documentation. So, let's get started and good luck!\n\n## CLONING THE PROJECT FROM GITHUB\n\nGo to [GITHUB](https://github.com/hudsonssrosa/pyon-behave-ui-tests-nativeapps) and **CLONE** the project using **GIT** (download and install GIT from [here](https://git-scm.com/downloads))\n\nIn you local machine, choose you local repository and clone the project using SSH for Mac OS or Linux platforms with this command:\n\n```bash\n    git clone git@github.com:hudsonssrosa/pyon-behave-ui-tests-nativeapps.git\n```\n\nIf you are having issues when cloning or pushing to the repository make sure you have all your SSH keys in place. Click [here](https://help.github.com/en/github/authenticating-to-github/connecting-to-github-with-ssh) for more information about it.\n\n## PREPARING YOUR ENVIRONMENT\n\n### 1. Install Python\n\nDownload and install the [latest Python](https://www.python.org/downloads/) version (3.8 or over). Then, in any terminal, try this command to check if Python is correctly installed:\n\n```bash\n      python\n```\n\n### 2. Choose a good IDE\n\nOnce you have opened the project in an IDE of your preference (suggestion: install [Visual Studio Code](https://code.visualstudio.com/download) or [PyCharm CE](https://www.jetbrains.com/pycharm/)), then you will need to *set the Python interpreter* for the project.\n\nAfter this, you are able to create the *Python Virtual Environment* for the PyonUIT project and install all the requirements needed (libraries/packages). You just need to run for the first time the `setup_python_env_update.py` and then the virtual environment as well the libraries in `requirements.txt` will be automatically installed for you.\n\n- In Windows:\n\n```bash\n      python update.py\n```\n\n- In MacOSX or Linux:\n\n```bash\n      python3 update.py\n```\n\nIncrement this command with CLI presented in next section 4.3, if you want to simulate the PyonUIT using Docker.\n\n### 4. Ways to run this project\n\nBy default, the tests will run locally on APPIUM, but you have 3 ways to perform your execution.\n\n#### 4.1 Run in debugging mode\n\nTo check if the environment is totally operational to begin with some implementation, or even check the existing tests, you might dealing with the environment variables to prepare for an execution. Thus, copy the file `env_settings.properties.local` and paste the new one in project's root (in the same place as the original file) renaming it to `env_settings.properties`. So, you can edit the properties freely, because this file is ignored by GIT versioning.\n\nInto this file, to consider a development setting, ensure the property `development_mode` is set as `true`. With this, all the properties that start with `debug_...` will be considered in a project debugging overwriting any command lines from CLI:\n\n```properties\n    development_mode = true\n    debug_flag_environment = staging\n\n    debug_flag_target = local_emulation\n    debug_flag_os = Android\n    debug_flag_os_version = 11.0\n    debug_flag_device_name = Samsung Galaxy A51\n    debug_flag_mode = native_app\n    debug_behave_tags = login-sample\n    debug_behave_excluded_tags = wip\n    debug_flag_orientation = Portrait\n    debug_flag_language = en\n    debug_flag_locale = en_GB\n```\n\n- To generate Allure Reports locally, make sure you have `Java` installed and the flag `generate_report = true` on your `env_settings.properties`.\n\n#### 4.2 Run as if it were in CI\n\nAfter any implementation into the PyonUIT, it is recommended to validate the tests simulating an execution capable to inject parameters in environment variables, like it is performed in a build from a CI server. To validate a test execution, keep in mind to run in a remote server such as BrowserStack or any other supported by PyonUIT in `fixtures.py`. Before this, you also will need to copy the file `run_behave.sh.local` and paste the new one in project's root (in the same place as the original file) renaming it to `run_behave.sh` to be ignored in commits.\n\nInto this script file, you can set those environment variables, like this:\n\n```bash\n    PYON_ENVIRONMENT='staging'\n    PYON_TARGET='local_emulation'\n    PYON_MODE='native_app'\n\n    PYON_OS='Android'\n    PYON_OS_VERSION='11.0'\n    PYON_DEVICE='Samsung Galaxy A51'\n\n    PYON_ORIENTATION='Portrait'\n    PYON_LANGUAGE='en'\n    PYON_LOCALE='en_GB'\n    PYON_APP_PATH='.resources/app_distribution/Sample.apk'\n\n    PYON_TAGS=\n    PYON_EXCLUDED_TAG='wip'\n```\n\n#### 4.3 Run via CLI (only command line)\n\nYou can handle all those parameters presented previously (in section 4.2) setting them directly via CLI. You just need to pass the desired values in the arguments by command line.\nFirst of all, call the main runner file in the terminal and press Enter. So, try this:\n\n```bash\n      python3 behave_runner.py --help\n```\n\nYou might see all the supported arguments that you can use:\n\n```bash\nusage: behave_runner.py [options]\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --environment {staging,dev,production}\n                        ==\u003e Environment to execute the tests (default = staging). Find the app URLs in properties file\n  --target {remote_emulation,local_emulation,bs,real_device}\n                        ==\u003e Platform to execute the mobile tests (default = local_emulation): BS - BrowserStack\n  --mode {native_app}   ==\u003e Execution mode according the mobile platform (default = native_app)\n  --os {iOS,Android,}   ==\u003e Mobile Operational System\n  --os_version {14.5,14.4,14.3,14.2,14.1,14.0,13.0,12.0,11.0,10.0,9.0,8.1,8.0,7.1,7.0,6.0,5.0,4.4,}\n                        ==\u003e Mobile platform versions\n  --device_name {local,Google Pixel 4 XL,Google Pixel 4,Google Pixel 3a XL,Google Pixel 3a,Google Pixel 3 XL,Google Pixel 3,Google Pixel 2,Google Pixel,Google Nexus 6,Google Nexus 5,iPhone 12 Pro Max,iPhone 12 Pro,iPhone 12,iPhone 11 Pro Max,iPhone 11 Pro,iPhone 11,iPhone XS Max,iPhone XS,iPhone XR,iPhone X,iPhone 8 Plus,iPhone 8,iPhone 7 Plus,iPhone 7,iPhone 6S Plus,iPhone 6S,iPhone 6,iPhone SE 2020,iPhone SE,iPad,iPad Pro 12.9 2020,iPad Pro 12.9 2018,iPad Pro 11 2020,iPad Mini 2019,iPad Air 2019,iPad 7th,iPad Pro 11 2018,iPad Pro 9.7 2016,iPad Pro 12.9 2017,iPad Mini 4,iPad 6th,iPad 5th,Motorola Moto G7 Play,Motorola Moto X 2nd Gen,Motorola Moto X 2nd Gen,OnePlus 8,OnePlus 7,OnePlus 7T,OnePlus 6T,Samsung Galaxy S20,Samsung Galaxy S20 Plus,Samsung Galaxy S20 Ultra,Samsung Galaxy Note 20 Ultra,Samsung Galaxy Note 20,Samsung Galaxy Note 10 Plus,Samsung Galaxy Note 10,Samsung Galaxy Note 9,Samsung Galaxy Note 8,Samsung Galaxy Note 4,Samsung Galaxy A51,Samsung Galaxy A11,Samsung Galaxy A10,Samsung Galaxy S10e,Samsung Galaxy S10 Plus,Samsung Galaxy S10,Samsung Galaxy S9 Plus,Samsung Galaxy S9,Samsung Galaxy S8 Plus,Samsung Galaxy S8,Samsung Galaxy S7,Samsung Galaxy S6,Samsung Galaxy J7 Prime,Samsung Galaxy Tab S6,Samsung Galaxy Tab S5e,Samsung Galaxy Tab S4,Samsung Galaxy Tab S3,Samsung Galaxy Tab 4,Vivo Y50,Xiaomi Redmi Note 8,Xiaomi Redmi Note 7}\n                        ==\u003e The device name models (check the platform version supported in --os_version)\n  --app_path APP_PATH   ==\u003e Relative or absolute path of an .APK or .IPA file (format is automatically recognized if --os arg is set)\n  --orientation {Landscape,Portrait}\n                        ==\u003e Screen orientation for mobile executions (default = Portrait)\n  --language {,af,ar,be,bg,ca,cs,cy,da,de,el,en,eo,es,et,fr,ga,gl,gsw,hi,it,ja,nb,nl,pl,pt,ro,rof,ru,sv,tr,uk,zh,zu}\n                        ==\u003e Language to set for iOS (XCUITest driver only) and Android (default = )\n  --locale {,af_,af_ZA,ar_,ar_001,ar_AE,ar_QA,ar_SA,be_,be_BY,bg_,bg_BG,ca_,ca_AD,ca_ES,ca_FR,ca_IT,cs_,cs_CZ,cy_,cy_GB,da_,da_DK,da_GL,de_,de_AT,de_BE,de_CH,de_DE,de_LI,de_LU,el_,el_CY,el_GR,en_,en_001,en_150,en_AU,en_BE,en_GB,en_HK,en_IE,en_IN,en_NZ,en_SG,en_US,en_ZA,eo_,es_,es_419,es_ES,et_,et_EE,fr_,fr_BE,fr_LU,ga_,ga_IE,gl_,gl_ES,gsw_,gsw_CH,gsw_LI,hi_,hi_IN,it_,it_CH,it_IT,ja_,ja_JP,nb_,nb_NO,nb_SJ,nl_,nl_NL,pl_,pl_PL,pt_,pt_AO,pt_BR,pt_CV,pt_GW,pt_MO,pt_MZ,pt_PT,pt_ST,pt_TL,ro_MD,ro_RO,rof_,ru_,ru_BY,ru_KG,ru_KZ,ru_MD,ru_RU,ru_UA,sv_,sv_AX,sv_FI,sv_SE,tr_,tr_CY,tr_TR,uk_,uk_UA,zh_,zh_CN,zh_HK,zh_MO,zh_SG,zu_,zu_ZA}\n                        ==\u003e Locale to set for iOS (XCUITest driver only) and Android. fr_CA format for iOS. CA format (country name abbreviation) for Android (default = )\n  --tags TAGS           ==\u003e Feature(s) / Scenario(s) to be executed (separate tags by comma and without spaces)\n  --exclude {wip,skip,bug,slow,}\n                        ==\u003e Feature(s) / Scenario(s) to be ignored / skipped from execution using a single tag (recommended: wip)\n```\n\nFinally, you can vary the command options such as these samples below and much more. If you does not pass the other arguments, it will be considered the default values:\n\n```bash\n     python behave_runner.py --target local_emulation\n     python behave_runner.py --target local_emulation --os iOS --os_version '14.3' --device_name 'iPhone 12' --orientation Landscape --app_path'.resources\\\\mobile_automation\\\\Sample.ipa'\n     python behave_runner.py --target bs --mode native_app --os iOS --os_version '14.0' --device_name 'iPhone 11' --app_path '.resources\\\\mobile_automation\\\\Sample.ipa'\n     python behave_runner.py --target real_device --mode native_app --os Android --os_version '10.0' --device_name 'Samsung Galaxy A51' --tags login-sample --exclude slow\n```\n\n## SETUP FOR NATIVE APPS RUNNING LOCALLY\n\n### APPIUM CLIENT INSTALLATION\n\nInstall Appium Python Client in your local machine to make available the Appium web driver for mobile apps (emulated or real Android / iOS devices connected).\nThen, just run this Python script to install the Appium Server (check if the version number is presented at the end):\n\n```bash\n    python appium_setup.py --server install\n```\n\nOpen a separated terminal to start the Appium server. You have two ways to run it:\n\n- Via `appium_setup.py` script, set the host and port if you need (by default it is \"0.0.0.0\" and \"4723\", respectively):\n\n```bash\n    python appium_setup.py --server start\n```\n\n```bash\n    python appium_setup.py --server start --localhost \u003cYOUR_HOST\u003e --port \u003cYOUR_PORT\u003e\n```\n\n- Or you can execute directly with:\n\n```bash\n    appium --address \u003chost\u003e --port \u003cnumber\u003e\n```\n\n#### 1. Appium Desktop\n\nTo inspect the device elements in the Appium Client during test implementation, make sure if you have an Appium Desktop. You can download directly from [http://appium.io/](https://github.com/appium/appium-desktop/releases/tag/v1.18.2)\nAdditionally, you need to install Java to make available the Appium client [https://java.com/en/download](https://java.com/en/download/help/java_mac.html)\n\n- Set the environment variable Path for JAVA_HOME:\n\n```bash\n    export JAVA_HOME=$(/usr/libexec/java_home)\n```\n\n- Use `$echo ANDROID_HOME` and `$echo JAVA_HOME` to get values from environment variables and set them in 'Edit Configurations' screen.\n- If you want to do this more than once, use the script `appium_setup.py`.\n\n### SETUP FOR LOCAL TESTS UPON iOS DEVICES RUNNING ON LOCAL MOBILE APP PROJECT\n\nIf you don't have any iPhone device with you, so you can use the XCode to emulate one. But first is necessary to clone the mobile application project to be tested with.\n\nFollow these steps below (commands for MacOS / Linux) to setup the main resources such as Ruby:\n\n- Install HomeBrew to facilitates the installation for any packages that Linux and MacOS are not able to do.\n\n```bash\n    /bin/bash -c “$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)\n```\n\n#### 2. Installing Ruby using RVM\n\nYou can install Ruby in different ways. To prevent conflicts and protected Ruby folders, it's recommended to install it using RVM.\n\n###### 2.1. Install GnuPG\n\n```bash\n    brew install gnupg\n```\n\n###### 2.2. Install GPG keys\n\n```bash\n    gpg --keyserver hkp://pool.sks-keyservers.net --recv-keys 409B6B1796C275462A1703113804BB82D39DC0E3 7D2BAF1CF37B13E2069D6956105BD0E739499BDB\n```\n\n###### 2.3. Install RVM\n\n```bash\n\t\\curl -sSL https://get.rvm.io | bash -s stable\n```\n\n###### 2.4. You should receive a thank you 🙏 message in the console\n\n```bash\n    echo \"source $HOME/.rvm/scripts/rvm\" \u003e\u003e ~/.bash_profile\n```\n\n###### 2.5. Quit all terminal and open it again\n\n```bash\n    rvm list\n```\n\n###### 2.6. You should get this message\n\n```bash\n\t# No rvm rubies installed yet. Try 'rvm help install'.\n```\n\n###### 2.7. Install some ruby version\n\nTry a version such as 2.7.1:\n\n```bash\n    rvm install 2.7.1\n```\n\n###### 2.8. After installation\n\nCheck which ruby version available and if is properly installed:\n\n```bash\n    rvm list\n```\n\n###### 2.9. Create default ruby version\n\n```bash\n    rvm alias create default 2.7.1\n```\n\n###### 2.10. If installation and configuration were successful\n\nRVM should now load whenever you open a new shell. This can be tested by executing the following command which should output rvm is a function as shown below.\n\n```bash\n    type rvm | head -n 1\n```\n\n###### 2.11. To change the Ruby version\n\nJust check the versions available:\n\n```bash\n    rvm list known\n```\n\n###### 2.12. Switching between RVM versions\n\nThen, you can switch to your desired version:\n\n```bash\n    rvm install 2.6.3\n    rvm use 2.6.3\n    rvm use system\n    rvm alias create default 2.6.3\n    ruby -v\n```\n\n#### 3. Installing Ruby - Conventional Way\n\nInstall Ruby RBenv using **brew** and set it to version 2.6.5:\n\n```bash\n    brew install ruby\n    brew install rbenv\n    rbenv init\n    rbenv rehash\n    rbenv install 2.6.5\n    rbenv global 2.6.5\n    eval \"$(rbenv init -)\"\n    ruby -v\n    curl -fsSL https://github.com/rbenv/rbenv-installer/raw/master/bin/rbenv-doctor | bash\n```\n\n- Export the Ruby Path (check the version first) if is not possible to run `ruby -v`, for example:\n  \n```bash\n    export PATH=\"/usr/local/opt/ruby/bin:/usr/local/lib/ruby/gems/3.0.0/bin:$PATH\"\n    echo 'export PATH=\"/usr/local/opt/ruby/bin:$PATH\"' \u003e\u003e ~/.bash_profile\n    source ~/.bash_profile\n```\n\n- Install Rails to manage the server-side application:\n  \n```bash\n    gem install rails\n```\n\n#### 4. Installing XCode to Manage and Simulate Apps Locally\n\nDownload and install the XCode from [Mac App Store](https://developer.apple.com/downloads). Just make sure that your `XCode.app` is located at \"/Applications\" folder, otherwise you would see an error such as:\n\n`An unknown server-side error occurred while processing the command. Original error: Could not determine iOS SDK version: Could not get Xcode version. /Library/Developer/Info.plist does not exist on disk.`\n\nIf you continue facing this issue, perhaps you will need to set the correct path from where the Xcode.app is being executed. For example, run this command to find the location:\n\n```bash\n    xcrun --sdk macosx --show-sdk-path\n```\n\nTo switch the SDK reference for Xcode, use this command:\n\n```bash\n    xcode-select --switch /Applications/\n```\n\n##### 4.1. Dependencies - Installing Ruby Gems\n\nNow, with a mobile app source in a local repository, try to open it using XCode and execute the following commands at the terminal to install the Ruby Gems (dependencies):\n\n```bash\n    gem install bundler\n    bundle install\n```\n\n##### 4.2. Building and Opening the App\n\nInstall Carthage to help you in managing dependencies of dependencies in a Cocoa application. Finally, try to open the project via command line:\n\n```bash\n    brew install carthage\n    brew update \u0026\u0026 brew upgrade carthage\n    open \u003cYOUR_APP_NAME\u003e.xcworkspace\n```\n\n##### 4.3. Updating Dependencies for Application Project Builded Locally\n\nIf you need to update the dependencies before build any App project cloned into your local machine, it's very important to execute some commands to prevent build errors and clean cached files.\n\n- Clear any cached generated by older project builds:\n\n```bash\n    rm -rf ~/Library/Developer/Xcode/DerivedData/\n```\n\n- So first open a terminal, and navigate to the App repository. Then update dependencies to Pod:\n\n```bash\n    cd /Users/\u003cyour_pc_user_name\u003e/\u003cpath_to_repo\u003e/\u003clocal_app_project\u003e\n    bundle exec pod install\n```\n\nTo see more information about, please, use or check the script `setup_local_ios_project.py`.\n\n#### 5. Emulating App in the XCode Simulator\n\nNow you are able to emulate any App using XCode Simulator. Just keep in mind these steps:\n\n- Select the SCHEME in the XCode Simulator\n- Use the shortkey 'CMD + R' to emulate the app in a device chosen\n- At XCode Project Navigator view, select the app in folder where it was build\". Then, copy the Full Path presented in File Inspector. This will be useful to set the `mobile_app_path` property into the `env_settings.properties` later.\n\n#### 6. Installing FastLane to Simulate using FastFile in CI\n\nIf you need to execute the tests externally in a CI Server like Bitrise, you will need to install Fastlane to run it locally and evaluate the FastFile script. So, first install Fastlane using the command below to prevent permission to writeblocks during the installation\n\n```bash\n    sudo gem install fastlane -n /usr/local/bin\n    fastlane -v\n```\n\n##### 5.1. Run the FastFile\n\nOnce installed Fastlane, you can run FastFile locally by this command:\n\n```bash\n    fastlane ios pyon_ui_tests \n```\n\nIf you are facing errors during Fastlane executiong, try to check the log and if you have `rspec` missed, just try to install this Gem with:\n\n```bash\n    gem install rspec --user\n```\n\n### SETUP FOR LOCAL ANDROID DEVICES\n\nYou will need at least the Android Debug Bridge (ADB) to help with test case implementations and debug the app.\nSo follow these steps below:\n\n- Install HomeBrew:\n\n```bash\n    /bin/bash -c \"$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)\"\n```\n\n- Install ADB:\n\n```bash\n    brew cask install android-platform-tools\n```\n\n- Export the environment variable Path:\n\n```bash\n    export ANDROID_HOME=\"Users/\u003cPC_USER_NAME\u003e/Library/Android/sdk\n    export PATH=\"${PATH}:/$ANDROID_HOME/platform-tools:/$ANDROID_HOME/tools:/$ANDROID_HOME/tools/bin\"\n```\n\n- Start using `adb`.\n\n## BDD APROACHING USING PYTHON-BEHAVE\n\nThe [Behaviour Driven Development](https://cucumber.io/docs/bdd/) can make our automated tests much more agile, productive, sustainable and with a living-documentation of business. Considering this, in the following sections will be presented a step-by-step about how to implement a simple scenario considering Python-Behave (library backed up by Python code - Cucumber-based) and Selenium to make possible to automate our Gherkin scenarios.\n\n### HOW TO IMPLEMENT TESTS USING PYONUIT FRAMEWORK?\n\nConsidering that the number of tests can increase significantly in this project, it is very important to keep in mind that you also need to have a good and coherent organisation of files, scenarios, features and settings associated to the tests. Initially, to have the codes recognised by Behave framework, all the files related to test cases should be implemented into the `features` folder. Take a look at the recommended structure below.\n\n#### 1. Gherkin Files\n\nAll the tests are documented in [Gherkin](https://behave.readthedocs.io/en/latest/tutorial.html#feature-files), a structured and natural language with properly keywords (Given, When, Then) that allows us to write testable specifications. Those files have the format `.feature` and should be organised into the '/features' with subfolders such as ENVIRONMENT FOLDER (dev/staging/production) \u003e DOMAIN FOLDER (global name of a functionality) \u003e FEATURE FILE. For example:\n\n```\n    features\n    └─── feature_domains\n        └─── staging\n            │   automation_sample_login.feature\n            |   ...\n            production\n            └─── ...\n```\n\n##### 1.1. Create a Feature\n\nWith this, you could create a simple scenario that validates if user can search a content in the app. You just need to use the keywords with `Feature:`, `Background:`, `Scenario:`, and describe the behaviours for steps with `Given`, `When` and `Then`:\n\n```gherkin\n    @login-sample\n    Feature: Automation Sample App\n\n        Scenario: Login the user with its credentials\n            Given that app is open at Login page\n            When user provides their wrong credentials\n            Then user sees \"Wrong username or password\"\n```\n\nAs you could see, add a **tag** (started with @) trying to choose an easy and intuitive name that reminds you about the Feature. Also, you can include another tag above the scenario, if you want to create new scenarios into the same file. This can make easier to call specific scenarios or an entire feature to be executed via Behave command line.\n\n##### 1.2. Generate the Step definitions\n\nAfter having a scenario defined, make sure that `development_mode` is `false` in `env_settings.properties` if you want to execute the `python3 behave_runner.py --tags login-sample` in the terminal (or set `development_mode` to `true` and include the tag `app-login` to property `debug_behave_tags`). Then, copy the snippet definitions generated automatically in console. You will need to implement your steps using them, like these:\n\n```bash\n        You can implement step definitions for undefined steps with these snippets:\n\n        @given(u'that app is open at Login page')\n        def step_impl(context):\n            raise NotImplementedError(u'STEP: Given that app is open at Login page')\n\n\n        @when(u'user provides their wrong credentials')\n        def step_impl(context):\n            raise NotImplementedError(u'STEP: When user provides their wrong credentials')\n\n\n        @then(u'user sees \"Wrong username or password\"')\n        def step_impl(context):\n            raise NotImplementedError(u'STEP: Then user sees \"Wrong username or password\"')\n```\n\n##### 1.3. Create a Step skeleton\n\nCopied the snippets, create a new Python file into the '/features/steps' folder with the same or similar name of your `.feature`.\nTry to increment the file name ending with `*_steps.py` and place them in the `steps` folder only (to be read by Behave framework).\n\n```\n    features\n    └─── steps\n        |   app_login_steps.py\n            ...\n```\n\nInto this new Python file, you should import `behave` library to take the advantages of Behave to your [Step Implementation](https://behave.readthedocs.io/en/latest/tutorial.html#python-step-implementations).\n\n```python\nfrom behave import *\n\n    # Paste your snippets for steps...\n```\n\nThen, just paste your snippets from clipboard into the `search_car_steps.py`.\n\n```python\nfrom behave import *\n\n\n@given(u'that app is open at Login page')\ndef step_impl(context):\n    raise NotImplementedError(u'STEP: Given that app is open at Login page')\n\n\n@when(u'user provides their wrong credentials')\ndef step_impl(context):\n    raise NotImplementedError(u'STEP: When user provides their wrong credentials')\n\n\n@then(u'user sees \"{error}\"')\ndef step_impl(context):\n    raise NotImplementedError(u'STEP: Then user sees \"Wrong username or password\"')\n```\n\n##### 1.4. Page Object Pattern\n\nNow, you have a basic structure using Behave, but the Steps have no code with the significant actions to cover the behaviour expected in the descriptions. To make this possible, all the interactions with HTML pages might be implemented using Appium/Selenium web driver, coded in Python. So, it is recommended a design pattern such as [Page Objects](https://martinfowler.com/bliki/PageObject.html) to manage, reuse and store all the locators extracted from a functionality in mobile screen.\n\nAdditionally, considering that you will have many app pages to interact in your scenarios, it is very important to let them organised, distiguished by folders and subfolders as well.\n\nIn this case, create a file names ending with `*_page.py` and put them into a folder containing the APP NAME (or a macro app module) \u003e FUNCTIONALITY NAME (or feature name) \u003e PYTHON PAGE OBJECT, like this sample:\n\n```\n    features\n    └─── pages\n        └─── app_sample\n            │   auth_page.py\n            │   home_page.py\n                ...\n```\n\nAt the '/features/pages/' folder, create a new page object class that inherits the BaseAppPage module (`from driver_wrappers.appium.native_app_wrapper import BaseAppPage`):\n\n```python\nfrom driver_wrappers.appium.native_app_wrapper import BaseAppPage\nfrom appium.webdriver.common.mobileby import MobileBy as MBy\n\n\nclass HomePage(BaseAppPage):\n    # ... declare the locators and Appium methods here\n```\n\nThrough BaseAppPage, you can take all advantages from default Selenium web driver (to click, type text, etc.) and also consume dozen of wrapped methods customised from the most common component actions identified in an application (get text from an element, select a dropdown option, swipe and many other actions):\n\n```python\n    self.wait_for_element(by, location, with_text, title, is_visible, is_not_visible, is_clickable, is_selected, is_frame, is_alert, is_presented, typing_secs, handle_timeout)\n\n    self.get_element_by(by_type, element_location)\n\n    self.get_element_text(by_type, element_location, is_visible)\n\n    self.type_text(input_text, by_type, element_location, is_clickable)\n\n    self.click_on(by_type, element_location, is_visible)\n\n    self.click_on_element_by_accessibility_id(element_location)\n\n    # ... and many others\n```\n\nConsidering this, extract the element locators inspecting the application's page opened in Appium Desktop and place them into the variables of your Page Object class. But, you will need to import `from appium.webdriver.common.mobileby import MobileBy` into the HomePage, to define a kind of locator for a XCUITest element should be able to interpret (MBy.XPATH, MBy.ACCESSIBILITY_ID, By.IOS_UIAUTOMATION, etc.):\n\n```python\nfrom driver_wrappers.appium.native_app_wrapper import BaseAppPage\nfrom appium.webdriver.common.mobileby import MobileBy as MBy\n\n\nclass AuthPage(BaseAppPage):\n    loc_lbl_title = (MBy.XPATH, '//android.widget.FrameLayout[1]/android.view.ViewGroup/android.widget.TextView')\n    loc_txt_username = (MBy.ID, 'com.dgotlieb.automationsample:id/userName')\n    loc_txt_password = (MBy.ID, 'com.dgotlieb.automationsample:id/userPassword')\n    loc_btn_login = (MBy.ID, 'com.dgotlieb.automationsample:id/loginButton')\n    loc_lbl_error_message = (MBy.ID, 'com.dgotlieb.automationsample:id/errorTV')\n```\n\nThe locator declared with a tuple (`(MBy.\u003cTYPE\u003e, \"\u003clocation string\u003e\")`) can be called directly using asterisk before a `self.loc_name`.\n\n###### 1.4.a) Assertions\n\nTo create validation methods for the steps when is necessary (mainly in the `@Then` step), you should use the existing assert methods already invoked by _BaseAppPage_. So, you are able to call them directly into the page used by a scenario. Just define the asserts like these:\n\n- `self.assert_that(\"\u003cFOUND STRING IN PAGE\u003e\").is_equals_to(\"\u003cEXPECTED STRING\u003e\", \"\u003cOPTIONAL DESCRIPTION\u003e\")`\n- `self.assert_that(\"\u003cFOUND STRING IN PAGE\u003e\").contains_the(\"\u003cEXPECTED STRING\u003e\", \"\u003cOPTIONAL DESCRIPTION\u003e\")`\n- `self.assert_that(\"\u003cFOUND STRING IN PAGE\u003e\").is_different_from(\"\u003cEXPECTED STRING\u003e\", \"\u003cOPTIONAL DESCRIPTION\u003e\")`\n- `self.assert_that(\u003cFOUND NUMBER IN PAGE\u003e).is_greater_than(b_value=\u003cNUMBER\u003e, \"\u003cOPTIONAL DESCRIPTION\u003e\")`\n- `self.assert_that(\u003cFOUND NUMBER IN PAGE\u003e).is_less_than(b_value=\u003cNUMBER\u003e, \"\u003cOPTIONAL DESCRIPTION\u003e\")`\n- `self.assert_that(\u003cFOUND NUMBER IN PAGE\u003e).is_between_the(expected_min=\u003cNUMBER\u003e, expected_max=\u003cNUMBER\u003e, \"\u003cOPTIONAL DESCRIPTION\u003e\")`\n- `self.assert_that().is_in_pdf(\"\u003cPDF FILE PATH OR URL\u003e\", \"\u003cEXPECTED STRING\u003e\", \"\u003cOPTIONAL DESCRIPTION\u003e\")`\n\nThen, you should have a page with an implementation like that:\n\n```python\nclass AuthPage(BaseAppPage):\n    loc_lbl_title = (MBy.XPATH, '//android.widget.FrameLayout[1]/android.view.ViewGroup/android.widget.TextView')\n    loc_txt_username = (MBy.ID, 'com.dgotlieb.automationsample:id/userName')\n    loc_txt_password = (MBy.ID, 'com.dgotlieb.automationsample:id/userPassword')\n    loc_btn_login = (MBy.ID, 'com.dgotlieb.automationsample:id/loginButton')\n    loc_lbl_error_message = (MBy.ID, 'com.dgotlieb.automationsample:id/errorTV')\n\n    def check_title(self):\n        self.is_the_element_presented(*self.loc_lbl_title)\n        \n    def type_input_username(self, input_value):\n        self.wait_for_element(*self.loc_txt_username)\n        # self.click_on(*self.loc_txt_username)\n        self.type_text(input_value, *self.loc_txt_username)\n\n    def type_input_password(self, input_value):\n        self.wait_for_element(*self.loc_txt_password)\n        self.type_text(input_value, *self.loc_txt_password)\n\n    def click_on_login(self):\n        self.click_on(*self.loc_btn_login)\n\n    def validate_error_message(self, message):\n        message_found = self.get_element_text(*self.loc_lbl_error_message)\n        self.assert_that(message_found).contains_the(value_expected=message, optional_description=\"Login validation message\")\n```\n\n##### 1.5. Step Implementation\n\nHaving all the pages needed already implemented, you need to call the methods to satisfy the scenario behaviour, as well the validations.\n\n```python\nfrom behave import *\nfrom features.pages.app_sample.auth_page import AuthPage\n\n\nlogin_page = AuthPage(object)\n\n\n@given('that app is open at Login page')\ndef step_given_that_app_is_open_at_login_page(context):\n    login_page.check_title()\n\n\n@when('user provides their wrong credentials')\ndef step_when_user_types_text_to_search(context):\n    login_page.type_input_username(\"wrong_user_name\")\n    login_page.type_input_password(\"wrong_pass_123\")\n\n\n@then('user sees \"{error}\"')\ndef step_then_the_content_related_is_found(context, error):\n    login_page.validate_error_message(message=error)\n```\n\nAnd your first test case scenario is ready to be executed for the first time!\n\n## SELECT THE SCENARIOS TO BE EXECUTED\n\nRegardless if you are using the debug mode to execute tests or triggering them via CI server, you should set the tags accordingly declaring with or without `@`, but separating them by comma and without spaces. See these examples:\n\nYou can combine TAGS like these examples:\n\n- e.g. 1) ISOLATED SCENARIO: `demo-app-login`\n\n- e.g. 2) COMBINING SCENARIOS: `demo-app-login,demo-app-search,...`\n\n- e.g. 3) CALLING ENTIRE FEATURES: `login-sample`\n\nIf you leave the parameter related to tags empty, all the features from the environment selected will be executed regardless if is set by properties or by command line.\n\n## FURTHER INFORMATION ABOUT CI/CD FILES\n\nIf you need to manage or maintain the CI/CD files for PyonUIT, just keep in mind about the following structure.\n\n- JENKINS (Both: iOS and Android): Create all files for environment provisioning, considering the fixtures implemented. Then, create scripts or reuse the existing ones following the steps showed previously in this document. Finally, call the tests in the same way as `run_behave.sh` file.\n- BITRISE (iOS only): Create a Workflow in the Bitrise, integrating the necessary build steps. You need to consider the `.fastlane/Fastfile` as a last Workflow step into the Workflow configuration. If you need to install Fastlane, follow the README.md in the same folder `.fastlane/Fastfile`.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhudsonssrosa%2Fpyon-behave-ui-tests-nativeapps","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhudsonssrosa%2Fpyon-behave-ui-tests-nativeapps","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhudsonssrosa%2Fpyon-behave-ui-tests-nativeapps/lists"}