├── .github └── workflows │ └── qg-example.yml ├── .gitignore ├── .gitlab-ci.yml ├── LICENSE ├── README.md ├── behave ├── README.md ├── behave.ini ├── requirements.txt └── tests │ └── features │ ├── environment.py │ ├── example.feature │ └── steps │ └── example_steps.py ├── pytest ├── README.md ├── pytest.ini ├── requirements.txt ├── run-xdist.sh ├── run.sh └── tests │ ├── __init__.py │ ├── conftest.py │ ├── multi_thread_logging │ ├── __init__.py │ ├── fixture │ │ ├── __init__.py │ │ └── test_thread_logging_fixture.py │ ├── logger_bypass │ │ ├── __init__.py │ │ ├── conftest.py │ │ └── test_thread_logging_one_logger.py │ └── thread │ │ └── test_thread_logging_thread_patch.py │ ├── muted_logger │ ├── __init__.py │ ├── conftest.py │ └── test_muted_rp_logs.py │ ├── test_case_id_decorator.py │ ├── test_custom_attributes.py │ ├── test_custom_name.py │ ├── test_description.py │ ├── test_in_class_parameterized.py │ ├── test_issue_id.py │ ├── test_launch_url_get.py │ ├── test_nested_steps.py │ ├── test_nested_steps_ui.py │ ├── test_simple.py │ ├── test_skip_condition.py │ ├── test_skipped.py │ ├── test_standard_logger.py │ └── ui │ ├── __init__.py │ └── web.py └── robotframework ├── README.md ├── requirements.txt ├── res ├── files │ ├── Test.cmd │ ├── Test.csv │ ├── css.css │ ├── demo.zip │ ├── har.har │ ├── html.html │ ├── javascript.js │ ├── php.php │ ├── plain.txt │ └── test.pdf └── pug │ ├── lucky.jpg │ └── unlucky.jpg ├── robot ├── __init__.robot ├── before_after_hooks.robot ├── binary_file_log_as_image.robot ├── browser_screenshot.robot ├── dynamic_tags.robot ├── dynamic_test_case_id.robot ├── expect_to_fail.robot ├── hello_world.robot ├── if_skip.robot ├── launch_log.robot ├── library │ ├── Log.py │ └── TestCaseId.py ├── logging.robot ├── saucelabs.robot ├── selenium_screenshot.robot ├── simple.robot ├── skip_on_failure.robot ├── suite_doc_with_urls.robot ├── tags.robot └── templates │ ├── __init__.robot │ ├── datadriver.csv │ ├── datadriver.robot │ ├── keyword.robot │ ├── settings.robot │ └── test_keywords.robot ├── run-pabot.sh ├── run-post-report.sh ├── run-variables-file.sh ├── run.sh └── variables.yaml /.github/workflows/qg-example.yml: -------------------------------------------------------------------------------- 1 | name: CI Tests 2 | 3 | on: 4 | workflow_dispatch: 5 | 6 | env: 7 | PYTHON_VERSION: '3.10.13' 8 | RP_INSTANCE: 'https://demo.reportportal.io' 9 | SCRIPT_TIMEOUT_SECONDS: 60 10 | REQUEST_TIMEOUT_SECONDS: 60 11 | 12 | jobs: 13 | build: 14 | runs-on: ubuntu-latest 15 | steps: 16 | - name: Checkout repository 17 | uses: actions/checkout@v4 18 | 19 | - name: Set up Python 20 | uses: actions/setup-python@v4 21 | with: 22 | python-version: '${{ env.PYTHON_VERSION }}' 23 | 24 | - name: Install dependencies 25 | run: | 26 | python -m pip install --upgrade pip 27 | pip install -rrequirements.txt -rrequirements-dev.txt 28 | 29 | - name: Test 30 | continue-on-error: true 31 | run: | 32 | pytest -sv --reportportal -m "not command_skip" -n 2 -o "rp_api_key=${{ secrets.RP_DEMO_KEY }}" tests | tee ./console.log 33 | sed -rn 's/ReportPortal Launch UUID: ([^\\r\\n]+)/LAUNCH_UUID=\1/ p' ./console.log >> "$GITHUB_ENV" 34 | 35 | - name: Quality Gate 36 | run: | 37 | echo "Quality gate" 38 | echo "LAUNCH_UUID: $LAUNCH_UUID" 39 | QUALITY_GATE_STATUS="" 40 | START_TIME=$(date +%s) 41 | while [ -z "$QUALITY_GATE_STATUS" ] && [ $(( $(date +%s) - START_TIME )) -lt ${{ env.SCRIPT_TIMEOUT_SECONDS }} ]; do 42 | echo "Waiting for quality gate status..." 43 | sleep 10 44 | QUALITY_GATE_JSON=$(curl -s -H "Authorization: Bearer $RP_DEMO_KEY" --max-time "${{ env.REQUEST_TIMEOUT_SECONDS }}" "${{ env.RP_INSTANCE }}/api/v1/report_portal_demo/launch/${LAUNCH_UUID}") 45 | QUALITY_GATE_STATUS=$(echo "$QUALITY_GATE_JSON" | jq -r '.metadata.qualityGate.status // empty') 46 | done 47 | if [ "$QUALITY_GATE_STATUS" != "PASSED" ]; then 48 | echo "Quality gate status: $QUALITY_GATE_STATUS" 49 | echo "Failing the pipeline." 50 | exit 1 51 | else 52 | echo "Quality gate status: $QUALITY_GATE_STATUS" 53 | echo "Pipeline passed." 54 | fi 55 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Byte-compiled / optimized / DLL files 2 | __pycache__/ 3 | *.py[cod] 4 | *$py.class 5 | 6 | # C extensions 7 | *.so 8 | 9 | # Distribution / packaging 10 | .Python 11 | build/ 12 | develop-eggs/ 13 | dist/ 14 | downloads/ 15 | eggs/ 16 | .eggs/ 17 | lib/ 18 | lib64/ 19 | parts/ 20 | sdist/ 21 | var/ 22 | wheels/ 23 | pip-wheel-metadata/ 24 | share/python-wheels/ 25 | *.egg-info/ 26 | .installed.cfg 27 | *.egg 28 | MANIFEST 29 | 30 | # PyInstaller 31 | # Usually these files are written by a python script from a template 32 | # before PyInstaller builds the exe, so as to inject date/other infos into it. 33 | *.manifest 34 | *.spec 35 | 36 | # Installer logs 37 | pip-log.txt 38 | pip-delete-this-directory.txt 39 | 40 | # Unit test / coverage reports 41 | htmlcov/ 42 | .tox/ 43 | .nox/ 44 | .coverage 45 | .coverage.* 46 | .cache 47 | nosetests.xml 48 | coverage.xml 49 | *.cover 50 | *.py,cover 51 | .hypothesis/ 52 | .pytest_cache/ 53 | 54 | # Translations 55 | *.mo 56 | *.pot 57 | 58 | # Django stuff: 59 | *.log 60 | local_settings.py 61 | db.sqlite3 62 | db.sqlite3-journal 63 | 64 | # Flask stuff: 65 | instance/ 66 | .webassets-cache 67 | 68 | # Scrapy stuff: 69 | .scrapy 70 | 71 | # Sphinx documentation 72 | docs/_build/ 73 | 74 | # PyBuilder 75 | target/ 76 | 77 | # Jupyter Notebook 78 | .ipynb_checkpoints 79 | 80 | # IPython 81 | profile_default/ 82 | ipython_config.py 83 | 84 | # pyenv 85 | .python-version 86 | 87 | # pipenv 88 | # According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control. 89 | # However, in case of collaboration, if having platform-specific dependencies or dependencies 90 | # having no cross-platform support, pipenv may install dependencies that don't work, or not 91 | # install all needed dependencies. 92 | #Pipfile.lock 93 | 94 | # PEP 582; used by e.g. github.com/David-OConnor/pyflow 95 | __pypackages__/ 96 | 97 | # Celery stuff 98 | celerybeat-schedule 99 | celerybeat.pid 100 | 101 | # SageMath parsed files 102 | *.sage.py 103 | 104 | # Environments 105 | .env 106 | .venv 107 | env/ 108 | venv/ 109 | ENV/ 110 | env.bak/ 111 | venv.bak/ 112 | 113 | # Spyder project settings 114 | .spyderproject 115 | .spyproject 116 | 117 | # Rope project settings 118 | .ropeproject 119 | 120 | # mkdocs documentation 121 | /site 122 | 123 | # mypy 124 | .mypy_cache/ 125 | .dmypy.json 126 | dmypy.json 127 | 128 | # Pyre type checker 129 | .pyre/ 130 | 131 | #Robot reports 132 | log.html 133 | output.xml 134 | report.html 135 | 136 | # Pycharm 137 | **/.idea/ 138 | 139 | # MacOs 140 | **/.DS_Store -------------------------------------------------------------------------------- /.gitlab-ci.yml: -------------------------------------------------------------------------------- 1 | workflow: 2 | rules: 3 | - if: '$CI_PIPELINE_SOURCE == "push"' 4 | when: never # Prevent pipeline run for push event 5 | - when: always # Run pipeline for all other cases 6 | 7 | stages: 8 | - secrets 9 | - test 10 | 11 | secrets: 12 | stage: secrets 13 | image: vault:latest 14 | before_script: 15 | - apk add --no-cache curl 16 | variables: 17 | GITLAB_INSTANCE: 'https://git.epam.com' 18 | script: 19 | - export VAULT_ADDR=https://vault.example.com:8200 20 | - export VAULT_NAMESPACE=rp/test/ 21 | # Put your Certificate Authority certificate path here 22 | - export VAULT_CACERT=cacert.pem 23 | - export VAULT_TOKEN="$(vault write -field=token auth/jwt/login role=tests-develop jwt=$CI_JOB_JWT)" 24 | # These fields we get from Vault to operate 25 | - RP_ADMIN_PASSWORD=$(vault kv get -field=rp.admin.password secrets/demo/test) 26 | - RP_DEMO_KEY=$(vault kv get -field=rp.demo.key secrets/demo/test) 27 | - > 28 | curl -f -s -X PUT --header "Private-Token: $GITLAB_API_TOKEN" --header "Content-Type: application/json" 29 | --data '{"value": "'"$RP_ADMIN_PASSWORD"'"}' 30 | "${GITLAB_INSTANCE}/api/v4/projects/$CI_PROJECT_ID/variables/RP_ADMIN_PASSWORD" > /dev/null 2>&1 31 | - > 32 | curl -f -s -X PUT --header "Private-Token: $GITLAB_API_TOKEN" --header "Content-Type: application/json" 33 | --data '{"value": "'"$RP_DEMO_KEY"'"}' 34 | "${GITLAB_INSTANCE}/api/v4/projects/$CI_PROJECT_ID/variables/RP_DEMO_KEY" > /dev/null 2>&1 35 | 36 | test: 37 | stage: test 38 | needs: ['secrets'] 39 | image: python:3.10.12 40 | before_script: 41 | - python -m pip install --upgrade pip 42 | - pip install -rrequirements-dev.txt 43 | script: 44 | - pytest -sv --reportportal -m "not command_skip" -n 2 -o "rp_api_key=$RP_DEMO_KEY" tests | tee ./console.log 45 | - > 46 | sed -rn 's/Report Portal Launch UUID: ([^\\r\\n]+)/LAUNCH_UUID=\1/ w launch.env' ./console.log 47 | 48 | quality-gate: 49 | stage: quality-gate 50 | needs: ['test'] 51 | before_script: 52 | - apt-get update || apk update 53 | - apt-get install -y curl jq || apk add --no-cache curl jq 54 | variables: 55 | RP_INSTANCE: 'https://demo.reportportal.io' 56 | SCRIPT_TIMEOUT_SECONDS: 60 57 | REQUEST_TIMEOUT_SECONDS: 60 58 | script: | 59 | echo "Quality gate" 60 | echo "LAUNCH_UUID: $LAUNCH_UUID" 61 | QUALITY_GATE_STATUS="" 62 | START_TIME=$(date +%s) 63 | while [ -z "$QUALITY_GATE_STATUS" ] && [ $(( $(date +%s) - START_TIME )) -lt $SCRIPT_TIMEOUT_SECONDS ]; do 64 | echo "Waiting for quality gate status..." 65 | sleep 10 66 | QUALITY_GATE_JSON=$(curl -s -H "Authorization: Bearer $RP_DEMO_KEY" --max-time "$REQUEST_TIMEOUT_SECONDS" "${RP_INSTANCE}/api/v1/report_portal_demo/launch/${LAUNCH_UUID}") 67 | QUALITY_GATE_STATUS=$(echo "$QUALITY_GATE_JSON" | jq -r '.metadata.qualityGate.status // empty') 68 | done 69 | if [ "$QUALITY_GATE_STATUS" != "PASSED" ]; then 70 | echo "Quality gate status: $QUALITY_GATE_STATUS" 71 | echo "Failing the pipeline." 72 | exit 1 73 | else 74 | echo "Quality gate status: $QUALITY_GATE_STATUS" 75 | echo "Pipeline passed." 76 | fi 77 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Python examples of Report Portal usage for different frameworks 2 | -------------------------------------------------------------------------------- /behave/README.md: -------------------------------------------------------------------------------- 1 | # Behave examples 2 | 3 | Running: `behave ./tests/features` 4 | -------------------------------------------------------------------------------- /behave/behave.ini: -------------------------------------------------------------------------------- 1 | [report_portal] 2 | api_key = your_rp_access_token 3 | endpoint = http://localhost:8080 4 | project = default_personal 5 | launch_name = Behave 6 | launch_attributes = Slow Smoke key:value 7 | launch_description = Smoke test 8 | -------------------------------------------------------------------------------- /behave/requirements.txt: -------------------------------------------------------------------------------- 1 | behave==1.2.6 2 | behave-reportportal==4.0.2 3 | -------------------------------------------------------------------------------- /behave/tests/features/environment.py: -------------------------------------------------------------------------------- 1 | import logging 2 | 3 | from reportportal_client import RPLogger, RPLogHandler 4 | 5 | from behave_reportportal.behave_agent import BehaveAgent, create_rp_service 6 | from behave_reportportal.config import read_config 7 | 8 | 9 | def before_all(context): 10 | cfg = read_config(context) 11 | context.rp_client = create_rp_service(cfg) 12 | context.rp_agent = BehaveAgent(cfg, context.rp_client) 13 | context.rp_agent.start_launch(context) 14 | logging.setLoggerClass(RPLogger) 15 | log = logging.getLogger(__name__) 16 | log.setLevel("DEBUG") 17 | rph = RPLogHandler(rp_client=context.rp_client) 18 | log.addHandler(rph) 19 | context.log = log 20 | 21 | 22 | def after_all(context): 23 | context.rp_agent.finish_launch(context) 24 | context.rp_client.terminate() 25 | 26 | 27 | def before_feature(context, feature): 28 | context.rp_agent.start_feature(context, feature) 29 | 30 | 31 | def after_feature(context, feature): 32 | context.rp_agent.finish_feature(context, feature) 33 | 34 | 35 | def before_scenario(context, scenario): 36 | context.rp_agent.start_scenario(context, scenario) 37 | 38 | 39 | def after_scenario(context, scenario): 40 | context.rp_agent.finish_scenario(context, scenario) 41 | 42 | 43 | def before_step(context, step): 44 | context.rp_agent.start_step(context, step) 45 | 46 | 47 | def after_step(context, step): 48 | context.rp_agent.finish_step(context, step) 49 | -------------------------------------------------------------------------------- /behave/tests/features/example.feature: -------------------------------------------------------------------------------- 1 | Feature: Showing off behave 2 | 3 | Scenario: Run a simple test 4 | Given we have behave installed 5 | When we implement 5 tests 6 | Then behave will test them for us! 7 | -------------------------------------------------------------------------------- /behave/tests/features/steps/example_steps.py: -------------------------------------------------------------------------------- 1 | from behave import given, when, then 2 | 3 | 4 | @given('we have behave installed') 5 | def step_impl(context): 6 | context.log.info('Behave is installed.') 7 | pass 8 | 9 | 10 | @when('we implement {number:d} tests') 11 | def step_impl(context, number): 12 | assert number > 1 or number == 0 13 | context.tests_count = number 14 | 15 | 16 | @then('behave will test them for us!') 17 | def step_impl(context): 18 | assert context.failed is False 19 | assert context.tests_count >= 0 20 | -------------------------------------------------------------------------------- /pytest/README.md: -------------------------------------------------------------------------------- 1 | # PyTest examples 2 | -------------------------------------------------------------------------------- /pytest/pytest.ini: -------------------------------------------------------------------------------- 1 | [pytest] 2 | rp_api_key = your_rp_access_token 3 | rp_endpoint = http://localhost:8080 4 | rp_project = default_personal 5 | rp_launch = PyTest 6 | rp_launch_attributes = 'tag' 'key1:value1' 'key2:value2' 7 | rp_launch_description = Smoke test 8 | rp_ignore_attributes = 'xfail' 'usefixture' 'ignored_attribute' 9 | rp_bts_issue_url = http://bugzilla.some.com/show_bug.cgi?id={issue_id} 10 | rp_issue_id_marks = True 11 | markers = 12 | command_skip: a custom test mark to skip from command line 13 | fixture_skip: a custom test mark to skip from fixture 14 | scope: to which test scope a test relates (smoke, regression, etc.) 15 | ignored_attribute: the attribute which won't be reported 16 | runtime: a test mark supposed to add at runtime 17 | -------------------------------------------------------------------------------- /pytest/requirements.txt: -------------------------------------------------------------------------------- 1 | pytest-reportportal~=5.5.0 2 | pytest>=4.6.10 3 | pytest-xdist 4 | -------------------------------------------------------------------------------- /pytest/run-xdist.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | pytest --reportportal -m "not command_skip" tests -n 4 4 | -------------------------------------------------------------------------------- /pytest/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | pytest --reportportal -m "not command_skip" tests 4 | -------------------------------------------------------------------------------- /pytest/tests/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | """This package contains example tests for the project.""" 14 | -------------------------------------------------------------------------------- /pytest/tests/conftest.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | """Example test configuration for pytest.""" 14 | 15 | import logging 16 | 17 | import pytest 18 | from reportportal_client import RPLogger 19 | 20 | 21 | # Uncomment the following lines to get full HTTP logging in console 22 | # from http.client import HTTPConnection 23 | # HTTPConnection.debuglevel = 1 24 | 25 | 26 | @pytest.fixture(scope='session') 27 | def rp_logger(): 28 | logger = logging.getLogger(__name__) 29 | logger.setLevel(logging.DEBUG) 30 | logging.setLoggerClass(RPLogger) 31 | return logger 32 | 33 | 34 | @pytest.fixture(autouse=True) 35 | def skip_by_mark(request): 36 | if request.node.get_closest_marker('fixture_skip'): 37 | pytest.skip('skip by fixture') 38 | 39 | 40 | @pytest.fixture(scope='session') 41 | def rp_launch_id(request): 42 | if hasattr(request.config, "py_test_service"): 43 | return request.config.py_test_service.rp.launch_uuid 44 | 45 | 46 | @pytest.fixture(scope='session') 47 | def rp_endpoint(request): 48 | if hasattr(request.config, "py_test_service"): 49 | return request.config.py_test_service.rp.endpoint 50 | 51 | 52 | @pytest.fixture(scope='session') 53 | def rp_project(request): 54 | if hasattr(request.config, "py_test_service"): 55 | return request.config.py_test_service.rp.project 56 | -------------------------------------------------------------------------------- /pytest/tests/multi_thread_logging/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | -------------------------------------------------------------------------------- /pytest/tests/multi_thread_logging/fixture/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | -------------------------------------------------------------------------------- /pytest/tests/multi_thread_logging/fixture/test_thread_logging_fixture.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | """An example which shows a way to log from Python threads. 14 | 15 | This way requires `rp_thread_logging` parameter to be enabled, it does support 16 | Threads with overridden `run` method. But it does not support logging in nested 17 | steps inside tests. All logs in such steps will go into base test section. 18 | """ 19 | 20 | import logging 21 | import threading 22 | import time 23 | 24 | import pytest 25 | 26 | 27 | class ThreadLogger(threading.Thread): 28 | """This class logs stuff to a logger.""" 29 | stop_event: threading.Event = threading.Event() 30 | 31 | def __init__(self, logger: logging.Logger = logging.getLogger(__name__)): 32 | super().__init__() 33 | self.logger = logger 34 | 35 | def run(self): 36 | """This function logs stuff to a logger.""" 37 | 38 | while self.stop_event.is_set() is False: 39 | time.sleep(.5) 40 | self.logger.info( 41 | f'This is a log from a thread: {self.logger.name}; time: {time.time()}') 42 | 43 | 44 | def create_threaded_logger(name: str): 45 | """This function creates a thread that logs stuff.""" 46 | thread = ThreadLogger(logging.getLogger(name)) 47 | thread.start() 48 | return thread 49 | 50 | 51 | @pytest.fixture(scope="module") 52 | def thread1(): 53 | """This fixture starts a thread that logs in a thread.""" 54 | return create_threaded_logger("thread1") 55 | 56 | 57 | @pytest.fixture(scope="module") 58 | def thread2(): 59 | """This fixture starts a thread that logs in a thread.""" 60 | return create_threaded_logger("thread2") 61 | 62 | 63 | def test_threaded_logging(thread1: ThreadLogger, thread2: ThreadLogger): 64 | """This test logs from multiple threads.""" 65 | logging.info("This is a log from the main thread") 66 | time.sleep(1.1) 67 | thread1.stop_event.set() 68 | thread2.stop_event.set() 69 | -------------------------------------------------------------------------------- /pytest/tests/multi_thread_logging/logger_bypass/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | -------------------------------------------------------------------------------- /pytest/tests/multi_thread_logging/logger_bypass/conftest.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | """Example test configuration for pytest.""" 14 | 15 | import logging 16 | 17 | import pytest 18 | import reportportal_client 19 | from reportportal_client import RPLogHandler 20 | 21 | 22 | @pytest.fixture(scope='function') 23 | def rp_thread_logger(request): 24 | logger = logging.getLogger("test." + request.node.name) 25 | handler = RPLogHandler( 26 | level=logging.DEBUG, 27 | filter_client_logs=True, 28 | endpoint=request.config._reporter_config.rp_endpoint, 29 | ignored_record_names=('reportportal_client', 30 | 'pytest_reportportal'), 31 | rp_client=reportportal_client.current()) 32 | logger.addHandler(handler) 33 | return logger 34 | -------------------------------------------------------------------------------- /pytest/tests/multi_thread_logging/logger_bypass/test_thread_logging_one_logger.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | # 14 | # https://www.apache.org/licenses/LICENSE-2.0 15 | # 16 | # Unless required by applicable law or agreed to in writing, software 17 | # distributed under the License is distributed on an "AS IS" BASIS, 18 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 | # See the License for the specific language governing permissions and 20 | # limitations under the License 21 | """An example which shows a way to log from Python threads. 22 | 23 | This way does not require `rp_thread_logging` parameter to be enabled. 24 | 'rp_thread_logger' argument is initialized inside `conftest.py` script in the 25 | same module. 26 | """ 27 | 28 | import logging 29 | import threading 30 | 31 | logger = logging.getLogger(__name__) 32 | 33 | 34 | def working_method(thread_logger): 35 | thread_logger.info("I'm logging in a thread") 36 | 37 | 38 | def test_thread_logging(rp_thread_logger): 39 | t = threading.Thread(target=lambda: working_method(rp_thread_logger)) 40 | logger.info("TEST_BEFORE_THREADING") 41 | t.start() 42 | t.join() 43 | -------------------------------------------------------------------------------- /pytest/tests/multi_thread_logging/thread/test_thread_logging_thread_patch.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2023 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | """An example which shows a way to log from Python threads. 14 | 15 | This way requires `rp_thread_logging` parameter to be enabled and it does not 16 | support Threads with overridden `run` method. But it does support logging in 17 | nested steps inside tests. 18 | """ 19 | 20 | import logging 21 | import threading 22 | 23 | from reportportal_client.steps import step 24 | 25 | log = logging.getLogger(__name__) 26 | 27 | 28 | def worker(): 29 | log.info("TEST_INFO") 30 | log.debug("TEST_DEBUG") 31 | 32 | 33 | def test_log(): 34 | t = threading.Thread(target=worker) 35 | log.info("TEST_BEFORE_THREADING") 36 | with step("Some nesting where the thread logs should go"): 37 | t.start() 38 | t.join() 39 | -------------------------------------------------------------------------------- /pytest/tests/muted_logger/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | -------------------------------------------------------------------------------- /pytest/tests/muted_logger/conftest.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | """Example test configuration for pytest with no RP logs.""" 14 | 15 | import logging 16 | 17 | import pytest 18 | import reportportal_client 19 | from reportportal_client import RPLogger, RPLogHandler 20 | 21 | 22 | @pytest.fixture(scope='session', autouse=True) 23 | def rp_mute_logger(): 24 | listener_logger = logging.getLogger("robotframework_reportportal.listener") 25 | listener_logger.setLevel(100) 26 | service_logger = logging.getLogger("robotframework_reportportal.service") 27 | service_logger.setLevel(100) 28 | client_logger = logging.getLogger("reportportal_client.service") 29 | client_logger.setLevel(100) 30 | -------------------------------------------------------------------------------- /pytest/tests/muted_logger/test_muted_rp_logs.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | """An example test with shows possibility to mute Report Portal logs.""" 14 | 15 | import logging 16 | 17 | logging.basicConfig(level=logging.INFO) 18 | 19 | logger = logging.getLogger(__name__) 20 | 21 | 22 | def test_no_report_portal_logging(): 23 | logger.info("There should be no ReportPortal logs for this module") 24 | assert True 25 | -------------------------------------------------------------------------------- /pytest/tests/test_case_id_decorator.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | """A simple example test with Test Case ID decorator.""" 14 | 15 | import pytest 16 | 17 | TEST_CASE_ID = "ISSUE-123" 18 | 19 | 20 | @pytest.mark.tc_id(TEST_CASE_ID) 21 | def test_case_id_decorator(): 22 | assert True 23 | -------------------------------------------------------------------------------- /pytest/tests/test_custom_attributes.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | """A simple example test with multiple custom attributes.""" 14 | 15 | import pytest 16 | 17 | 18 | @pytest.mark.scope("smoke") 19 | @pytest.mark.scope("regression") 20 | @pytest.mark.ignored_attribute("test") 21 | def test_custom_attributes_report(rp_logger, request): 22 | """ 23 | This is a test with multiple custom markers which shall appear on 24 | ReportPortal on test's item as different attributes 25 | """ 26 | rp_logger.info("A test with multiple custom attributes") 27 | 28 | # A way to add an attribute in runtime 29 | request.node.add_marker( 30 | pytest.mark.runtime() 31 | ) 32 | assert True 33 | -------------------------------------------------------------------------------- /pytest/tests/test_custom_name.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 EPAM Systems 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | import pytest 15 | 16 | TEST_NAME_ARGS = 'Test name by mark' 17 | 18 | 19 | @pytest.mark.name(TEST_NAME_ARGS) 20 | def test_name_by_mark_args(): 21 | """Simple example test with the name comes from Pytest mark.""" 22 | assert True 23 | -------------------------------------------------------------------------------- /pytest/tests/test_description.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | """An example test with test description which appear on Report Portal.""" 14 | 15 | 16 | def test_description(rp_logger): 17 | """This is my test description which appears on ReportPortal""" 18 | rp_logger.info("A test with description") 19 | assert True 20 | -------------------------------------------------------------------------------- /pytest/tests/test_in_class_parameterized.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | """A simple example test in a class with a parameter.""" 14 | import pytest 15 | 16 | 17 | class Tests: 18 | 19 | @pytest.mark.parametrize('param', ['param']) 20 | def test_in_class_parameterized(self, rp_logger, param): 21 | """ 22 | This is my test inside `Tests` class with a parameter 23 | """ 24 | rp_logger.info("A simple test with param: " + param) 25 | assert True 26 | -------------------------------------------------------------------------------- /pytest/tests/test_issue_id.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | """An example test which contains issue reference.""" 14 | import pytest 15 | 16 | 17 | @pytest.mark.issue(issue_id='ABC-1234', reason='some_bug', issue_type='PB') 18 | def test_issue_id(): 19 | assert False 20 | -------------------------------------------------------------------------------- /pytest/tests/test_launch_url_get.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | """An example test which generates Launch URL.""" 14 | 15 | 16 | def test_launch_url_get(rp_logger, rp_launch_id, rp_endpoint, rp_project): 17 | """ 18 | This is a test which gets Launch ID, Report Portal endpoint and Project 19 | Name from fixtures in `conftest.py` and prints the result in logs, both: in 20 | console and on Report Portal 21 | """ 22 | rp_logger.info("Got launch ID: %s", rp_launch_id) 23 | rp_logger.info("Launch URL: %s/ui/#%s/launches/all/%s", rp_endpoint, 24 | rp_project, rp_launch_id) 25 | assert True 26 | -------------------------------------------------------------------------------- /pytest/tests/test_nested_steps.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | """An example test which shows different types of nested steps.""" 14 | from reportportal_client import step 15 | 16 | 17 | @step("test", rp_client=None) 18 | def nested_step(): 19 | print("Inside nested step") 20 | 21 | 22 | @step 23 | def two_level_nested_step(): 24 | nested_step() 25 | print("Inside nested step") 26 | 27 | 28 | @step 29 | def nested_step_params(param1, param2, named_param=None): 30 | print("Inside nested step with params") 31 | 32 | 33 | @step("Custom name nested step") 34 | def custom_name(): 35 | print("Inside nested step with custom name") 36 | 37 | 38 | def test_function_level_nested_steps_start_stop(): 39 | nested_step() 40 | nested_step_params(1, 2, named_param="test") 41 | two_level_nested_step() 42 | custom_name() 43 | 44 | with step("Code level nested step", {"test": "value"}): 45 | print("Inside code-level nested step") 46 | -------------------------------------------------------------------------------- /pytest/tests/test_nested_steps_ui.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | """A test which shows how UI test with nested steps might look like.""" 14 | import logging 15 | 16 | from reportportal_client import step 17 | 18 | from tests.ui.web import OrderingSimulator 19 | 20 | logging.basicConfig(level=logging.INFO) 21 | 22 | logger = logging.getLogger(__name__) 23 | 24 | order_simulator = OrderingSimulator() 25 | 26 | 27 | @step 28 | def navigate_to_main_page(): 29 | logger.info('Main page displayed') 30 | 31 | 32 | @step 33 | def login(): 34 | order_simulator.log_in() 35 | logger.info('User logged in') 36 | 37 | 38 | @step 39 | def navigate_to_products_page(): 40 | products = order_simulator.get_products() 41 | logger.info('Products page opened') 42 | return products 43 | 44 | 45 | @step 46 | def click_on_product(): 47 | product = order_simulator.choose_product() 48 | logger.info("Product click event") 49 | return product 50 | 51 | 52 | @step 53 | def select_products_count(count): 54 | logger.info(str(count) + " products selected") 55 | 56 | 57 | @step 58 | def click_cart_button(product, count): 59 | order_simulator.add_product(product, count) 60 | logger.info(str(count) + " products added to the cart") 61 | assert 5 == count 62 | 63 | 64 | @step 65 | def add_product_to_cart(product_count): 66 | product = click_on_product() 67 | select_products_count(product_count) 68 | click_cart_button(product, product_count) 69 | 70 | 71 | @step 72 | def pay(total_price): 73 | order_simulator.do_payment(total_price) 74 | logger.info("Successful payment") 75 | 76 | 77 | @step 78 | def logout(): 79 | order_simulator.log_out() 80 | logger.info("User logged out") 81 | 82 | 83 | def test_order_products(): 84 | product_count = 5 85 | price = 3.0 86 | total_price = price * product_count 87 | 88 | navigate_to_main_page() 89 | login() 90 | navigate_to_products_page() 91 | add_product_to_cart(product_count) 92 | pay(total_price) 93 | logout() 94 | -------------------------------------------------------------------------------- /pytest/tests/test_simple.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | """A simple example test.""" 14 | 15 | 16 | def test_simple(rp_logger): 17 | rp_logger.info("A simple test") 18 | assert True 19 | -------------------------------------------------------------------------------- /pytest/tests/test_skip_condition.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | """Example tests with different skip conditions.""" 14 | import sys 15 | 16 | import pytest 17 | 18 | 19 | @pytest.mark.skipif(sys.version_info < (3, 0), 20 | reason="requires python3 or higher") 21 | def test_skip_python_2_7(rp_logger): 22 | rp_logger.info("The test should not run on python 2.7") 23 | assert True 24 | 25 | 26 | @pytest.mark.skipif(sys.version_info > (2, 7), 27 | reason="requires python3 or higher") 28 | def test_skip_python_3_and_higher(rp_logger): 29 | rp_logger.info("The test should not run on python3 and higher") 30 | assert True 31 | -------------------------------------------------------------------------------- /pytest/tests/test_skipped.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | """Example tests with different skip types.""" 14 | import logging 15 | 16 | import pytest 17 | 18 | logging.basicConfig(level=logging.INFO) 19 | logger = logging.getLogger(__name__) 20 | 21 | 22 | def test_pass_to_show_in_report(): 23 | logging.info("Just a passed test") 24 | assert True 25 | 26 | 27 | @pytest.mark.skip(reason='no way of currently testing this') 28 | def test_the_unknown(): 29 | assert False 30 | 31 | 32 | @pytest.mark.command_skip 33 | def test_custom_mark_skip_command_line(): 34 | assert False 35 | 36 | 37 | @pytest.mark.fixture_skip 38 | def test_custom_mark_skip_fixture(): 39 | assert False 40 | 41 | 42 | def test_inner_skip_test(): 43 | pytest.skip("Skip from test insides") 44 | -------------------------------------------------------------------------------- /pytest/tests/test_standard_logger.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | """An example test with shows how to use standard python logger.""" 14 | 15 | import logging 16 | 17 | logging.basicConfig(level=logging.INFO) 18 | 19 | logger = logging.getLogger(__name__) 20 | 21 | 22 | def test_report_portal_logging(): 23 | logger.info("Standard logger logs to Report Portal") 24 | assert True 25 | -------------------------------------------------------------------------------- /pytest/tests/ui/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | """This package contains pseudo-ui API.""" 14 | -------------------------------------------------------------------------------- /pytest/tests/ui/web.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2022 https://reportportal.io . 2 | # Licensed under the Apache License, Version 2.0 (the "License"); 3 | # you may not use this file except in compliance with the License. 4 | # You may obtain a copy of the License at 5 | # 6 | # https://www.apache.org/licenses/LICENSE-2.0 7 | # 8 | # Unless required by applicable law or agreed to in writing, software 9 | # distributed under the License is distributed on an "AS IS" BASIS, 10 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 11 | # See the License for the specific language governing permissions and 12 | # limitations under the License 13 | 14 | class OrderingSimulator: 15 | def log_in(self): 16 | pass 17 | 18 | def get_products(self): 19 | return ["one", "two"] 20 | 21 | def choose_product(self): 22 | return "two" 23 | 24 | def add_product(self, product, product_count): 25 | pass 26 | 27 | def do_payment(self, total_price): 28 | pass 29 | 30 | def log_out(self): 31 | pass 32 | -------------------------------------------------------------------------------- /robotframework/README.md: -------------------------------------------------------------------------------- 1 | # Robot Framework examples 2 | -------------------------------------------------------------------------------- /robotframework/requirements.txt: -------------------------------------------------------------------------------- 1 | robotframework==7.1.1 2 | robotframework-datadriver==1.11.2 3 | robotframework-reportportal~=5.6.1 4 | robotframework-seleniumlibrary==6.6.1 5 | robotframework-browser==18.8.1 6 | robotframework-pabot==2.18.0 7 | selenium>=4.25.0 8 | PyYAML 9 | -------------------------------------------------------------------------------- /robotframework/res/files/Test.cmd: -------------------------------------------------------------------------------- 1 | title Batch File Testing 2 | echo Hello World 3 | echo. 4 | echo Starting Notepad 5 | start notepad 6 | echo. 7 | echo Starting Wordpad 8 | start Wordpad 9 | echo. 10 | pause 11 | exit -------------------------------------------------------------------------------- /robotframework/res/files/Test.csv: -------------------------------------------------------------------------------- 1 | 1997,Ford,E350,"ac, abs, moon",3000.00 2 | 1999,Chevy,"Venture ""Extended Edition""","",4900.00 3 | 1996,Jeep,Grand Cherokee,"MUST SELL! air, moon roof, loaded",4799.00 -------------------------------------------------------------------------------- /robotframework/res/files/css.css: -------------------------------------------------------------------------------- 1 | p { 2 | font-family: arial, helvetica, sans-serif; 3 | } 4 | 5 | h2 { 6 | font-size: 20pt; 7 | color: red; 8 | background: white; 9 | } 10 | 11 | .note { 12 | color: red; 13 | background-color: yellow; 14 | font-weight: bold; 15 | } 16 | 17 | p#paragraph1 { 18 | padding-left: 10px; 19 | } 20 | 21 | a:hover { 22 | text-decoration: none; 23 | } 24 | 25 | #news p { 26 | color: blue; 27 | } 28 | 29 | [type="button"] { 30 | background-color: green; 31 | } -------------------------------------------------------------------------------- /robotframework/res/files/demo.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reportportal/examples-python/725e909c08c2a463d66b73ed76d0bbe5b488481f/robotframework/res/files/demo.zip -------------------------------------------------------------------------------- /robotframework/res/files/har.har: -------------------------------------------------------------------------------- 1 | { 2 | "log": { 3 | "version": "1.2", 4 | "creator": { 5 | "name": "WebInspector", 6 | "version": "537.36" 7 | }, 8 | "pages": [ 9 | { 10 | "startedDateTime": "2017-12-13T11:21:18.288Z", 11 | "id": "page_2", 12 | "title": "http://localhost:8080/", 13 | "pageTimings": { 14 | "onContentLoad": 330.9420000005048, 15 | "onLoad": 464.73599999808357 16 | } 17 | } 18 | ] 19 | } 20 | } -------------------------------------------------------------------------------- /robotframework/res/files/html.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Office 7 | 8 | 10 | 12 | 14 | 16 | 18 | 20 | 21 | 22 |
23 |
24 | 26 | 65 | 112 | 113 | 114 | -------------------------------------------------------------------------------- /robotframework/res/files/javascript.js: -------------------------------------------------------------------------------- 1 | var APP = APP || {}; 2 | APP.Views.People = Backbone.View.extend({ 3 | template: APP.getTemplate('people-list-template'), 4 | initialize: function() { 5 | this.render(); 6 | var peopleControls = new APP.Views.PeopleControls({ 7 | el: '#controls' 8 | }); 9 | var peopleInfo = new APP.Views.PeopleInfo({ 10 | el: '#summary' 11 | }); 12 | this.showPeopleCount(); 13 | this.listenTo(this.collection, 'reset', this.renderPeopleList); 14 | this.listenTo(this.collection, 'all', this.showPeopleCount); 15 | }, 16 | events: { 17 | 'click .toJSON': 'convertToJSON', 18 | 'click .deleteAll': 'deleteAll', 19 | 'click .addPerson': 'addPerson' 20 | }, 21 | convertToJSON: function() { 22 | this.$('#JSON-output').html(JSON.stringify(this.collection.toJSON())); 23 | }, 24 | renderPerson: function(person) { 25 | var personView = new APP.Views.Person({ 26 | model: person, 27 | //el: '#peopleList' затирает el при каждом вызове 28 | }); 29 | this.$el.find('#peopleList').append(personView.render().el); 30 | }, 31 | deleteAll: function() { 32 | if (confirm('Delete all data?')) { 33 | this.collection.reset(); 34 | } 35 | }, 36 | addPerson: function() { 37 | var personModel = new APP.Models.Person({ 38 | 'name': this.$el.find('#name').val().trim(), 39 | 'age': +this.$el.find('#age').val().trim(), 40 | 'profession': this.$el.find('#profession > option:selected').text(), 41 | }, { 42 | validate: true 43 | }); 44 | if (!personModel.validationError) { 45 | this.collection.add(personModel); 46 | this.renderPerson(personModel); 47 | } else { 48 | alert(personModel.validationError); 49 | } 50 | }, 51 | renderPeopleList: function() { 52 | this.$el.find('#peopleList').html(''); 53 | this.collection.each(this.renderCollection, this); 54 | }, 55 | showPeopleCount: function() { 56 | this.$el.find('#peopleCount').html(this.collection.length); 57 | }, 58 | render: function() { 59 | this.$el.html(this.template); 60 | this.collection.each(this.renderPerson, this); 61 | } 62 | }); 63 | -------------------------------------------------------------------------------- /robotframework/res/files/php.php: -------------------------------------------------------------------------------- 1 | a = $a; 11 | $this->b = $b; 12 | } 13 | 14 | public function plus() 15 | { 16 | return $this->a + $this->b; 17 | } 18 | /* ............... */ 19 | } 20 | 21 | $d = new C1(1, 2); 22 | echo $d->plus(); // 3 23 | ?> -------------------------------------------------------------------------------- /robotframework/res/files/plain.txt: -------------------------------------------------------------------------------- 1 | Copyright 2021 EPAM Systems 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); 4 | you may not use this file except in compliance with the License. 5 | You may obtain a copy of the License at 6 | 7 | http://www.apache.org/licenses/LICENSE-2.0 8 | 9 | Unless required by applicable law or agreed to in writing, software 10 | distributed under the License is distributed on an "AS IS" BASIS, 11 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | See the License for the specific language governing permissions and 13 | limitations under the License. -------------------------------------------------------------------------------- /robotframework/res/files/test.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reportportal/examples-python/725e909c08c2a463d66b73ed76d0bbe5b488481f/robotframework/res/files/test.pdf -------------------------------------------------------------------------------- /robotframework/res/pug/lucky.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reportportal/examples-python/725e909c08c2a463d66b73ed76d0bbe5b488481f/robotframework/res/pug/lucky.jpg -------------------------------------------------------------------------------- /robotframework/res/pug/unlucky.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/reportportal/examples-python/725e909c08c2a463d66b73ed76d0bbe5b488481f/robotframework/res/pug/unlucky.jpg -------------------------------------------------------------------------------- /robotframework/robot/__init__.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Library library/Log.py 3 | Suite Setup Mute Reportportal Logs # Mute anything related to ReportPortal 4 | -------------------------------------------------------------------------------- /robotframework/robot/before_after_hooks.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation An example of using before and after hooks 3 | Suite Setup Log suite setup 4 | Suite Teardown Log suite tear down 5 | Test Setup Log test setup 6 | Test Teardown Log test tear down 7 | 8 | *** Variables *** 9 | ${FIRST_MESSAGE} My first test 10 | ${SECOND_MESSAGE} My second test 11 | 12 | *** Test Cases *** 13 | My first test 14 | Log ${FIRST_MESSAGE} 15 | My second test 16 | Log ${SECOND_MESSAGE} 17 | 18 | *** Keywords *** 19 | Log suite setup 20 | Log Suite setup step 21 | Log suite tear down 22 | Log Suite tear down step 23 | Log test setup 24 | Log Test setup step 25 | Log test tear down 26 | Log Test tear down step 27 | -------------------------------------------------------------------------------- /robotframework/robot/binary_file_log_as_image.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Example of logging on binary file read 3 | Library library/Log.py 4 | Library OperatingSystem 5 | 6 | *** Variables *** 7 | ${PUG_IMAGE} res/pug/lucky.jpg 8 | 9 | *** Keywords *** 10 | Read Binary File 11 | [Tags] binary 12 | [Arguments] ${file} 13 | ${data} Get Binary File ${file} 14 | Binary Log INFO image pug.jpg ${data} 15 | 16 | *** Test Cases *** 17 | Read Pug Image 18 | Read Binary File ${PUG_IMAGE} 19 | -------------------------------------------------------------------------------- /robotframework/robot/browser_screenshot.robot: -------------------------------------------------------------------------------- 1 | # This example is recommended way of capturing Browser screenshots 2 | *** Settings *** 3 | Documentation A simple failure test which takes and logs screenshot 4 | Library Browser 5 | Suite Setup Register Keyword To Run On Failure Take Screenshot 6 | 7 | *** Keywords *** 8 | Open Page 9 | [Arguments] ${browser} ${url} 10 | New Browser ${browser} 11 | New Page ${url} 12 | 13 | *** Test Cases *** 14 | Screenshot test 15 | Open Page chromium http://www.example.com 16 | Get Title matches Google 17 | -------------------------------------------------------------------------------- /robotframework/robot/dynamic_tags.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Example of setting test tags in runtime 3 | Library library/Log.py 4 | 5 | *** Test Cases *** 6 | Test tag set 7 | [Tags] static_tag 8 | Item Log INFO A test with a tag set in runtime 9 | Set Tags dynamic_tag 10 | Test no tag 11 | Item Log INFO A test with no tags set 12 | Test set multiple tags 13 | Item Log INFO A test with multiple tags set in runtime 14 | Set Tags multiple_tags_one multiple_tags_two 15 | -------------------------------------------------------------------------------- /robotframework/robot/dynamic_test_case_id.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Example of setting Test Case ID in runtime 3 | Library library/Log.py 4 | Library library/TestCaseId.py 5 | 6 | *** Test Cases *** 7 | Test set dynamic Test Case ID 8 | Item Log INFO A test with dynamic Test Case ID generation 9 | Case Id dynamic_tags.robot[{env_var}] 10 | -------------------------------------------------------------------------------- /robotframework/robot/expect_to_fail.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Example of a failed keyword expectation 3 | 4 | *** Test Cases *** 5 | Expect Error 6 | Run Keyword And Expect Error Expected to Fail 7 | ... Fail Expected to Fail -------------------------------------------------------------------------------- /robotframework/robot/hello_world.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Example of a sipmple test on Robot Framework, taken from official documentation: 3 | ... http://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html#space-separated-format 4 | Library OperatingSystem 5 | Metadata Author John Doe 6 | 7 | *** Variables *** 8 | ${MESSAGE} Hello, world! 9 | 10 | *** Test Cases *** 11 | My Test 12 | [Documentation] Example test. 13 | Log ${MESSAGE} 14 | My Keyword ${CURDIR} 15 | 16 | Another Test 17 | Should Be Equal ${MESSAGE} Hello, world! 18 | 19 | *** Keywords *** 20 | My Keyword 21 | [Arguments] ${path} 22 | Directory Should Exist ${path} 23 | -------------------------------------------------------------------------------- /robotframework/robot/if_skip.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Example of skipping failure statement by 'IF' 3 | 4 | *** Variables *** 5 | ${SKIP} True 6 | 7 | *** Test Cases *** 8 | Test If Skip 9 | Log One passed step to check 10 | IF not ${SKIP} 11 | Fail This step should be skipped 12 | ELSE 13 | Log This step should pass 14 | END 15 | -------------------------------------------------------------------------------- /robotframework/robot/launch_log.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Example of launch level logs 3 | Library library/Log.py 4 | Library OperatingSystem 5 | Library String 6 | 7 | *** Variables *** 8 | ${PASS_MESSAGE} Hello, world! 9 | ${ERROR_MESSAGE} Goodbye, world! 10 | ${PUG_MESSAGE} Enjoy my pug! 11 | ${PUG_IMAGE} res/pug/lucky.jpg 12 | 13 | *** Keywords *** 14 | Get image 15 | [Arguments] ${image} 16 | ${data} Get Binary File ${image} 17 | ${name} Fetch From Right ${image} / 18 | ${result} Create Dictionary 19 | ... mime image/jpeg 20 | ... name ${name} 21 | ... data ${data} 22 | RETURN ${result} 23 | 24 | *** Test Cases *** 25 | Launch log test 26 | Launch Log INFO ${PASS_MESSAGE} 27 | Launch Log ERROR ${ERROR_MESSAGE} 28 | ${log_image} Get image ${PUG_IMAGE} 29 | Launch Log INFO ${PUG_MESSAGE} ${log_image} 30 | -------------------------------------------------------------------------------- /robotframework/robot/library/Log.py: -------------------------------------------------------------------------------- 1 | # Copyright 2021 EPAM Systems 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | import logging 16 | 17 | from robotframework_reportportal import logger 18 | from reportportal_client.helpers import guess_content_type_from_bytes 19 | 20 | 21 | def item_log(level: str, message: str, attachment: dict = None): 22 | logger.write(message, level, attachment=attachment) 23 | 24 | 25 | def launch_log(level: str, message: str, attachment: dict = None): 26 | logger.write(message, level, attachment=attachment, launch_log=True) 27 | 28 | 29 | def binary_log(level: str, message: str, file_name: str, attachment: bytes): 30 | logger.write( 31 | message, 32 | level, 33 | attachment={ 34 | "name": file_name, 35 | "data": attachment, 36 | "mime": guess_content_type_from_bytes(attachment), 37 | }, 38 | launch_log=False, 39 | ) 40 | 41 | 42 | def mute_reportportal_logs(): 43 | listener_logger = logging.getLogger("robotframework_reportportal.listener") 44 | listener_logger.setLevel(100) 45 | service_logger = logging.getLogger("robotframework_reportportal.service") 46 | service_logger.setLevel(100) 47 | client_logger = logging.getLogger("reportportal_client.service") 48 | client_logger.setLevel(100) 49 | -------------------------------------------------------------------------------- /robotframework/robot/library/TestCaseId.py: -------------------------------------------------------------------------------- 1 | # Copyright 2024 EPAM Systems 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # https://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | # 15 | # Licensed under the Apache License, Version 2.0 (the "License"); 16 | # you may not use this file except in compliance with the License. 17 | # You may obtain a copy of the License at 18 | # 19 | # https://www.apache.org/licenses/LICENSE-2.0 20 | # 21 | # Unless required by applicable law or agreed to in writing, software 22 | # distributed under the License is distributed on an "AS IS" BASIS, 23 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 24 | # See the License for the specific language governing permissions and 25 | # limitations under the License. 26 | 27 | from typing import Optional 28 | 29 | from robot.libraries.BuiltIn import BuiltIn 30 | 31 | 32 | def case_id(test_case_id_pattern: Optional[str]) -> None: 33 | built_in = BuiltIn() 34 | if not test_case_id_pattern: 35 | return 36 | suite_metadata = str(built_in.get_variable_value('${rplaunchattributes}')).split() 37 | env = None 38 | for value in suite_metadata: 39 | if value.strip().lower().startswith('env:'): 40 | env = value.strip().split(':', maxsplit=1)[1] 41 | break 42 | if not env: 43 | return 44 | built_in.set_tags('test_case_id:' + test_case_id_pattern.format(env_var=env)) 45 | -------------------------------------------------------------------------------- /robotframework/robot/logging.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Example of different log types 3 | Library library/Log.py 4 | Library OperatingSystem 5 | Library String 6 | Library mimetypes.MimeTypes 7 | Test Setup Set Log Level TRACE 8 | 9 | *** Variables *** 10 | ${ATTACHMENTS} res/files 11 | 12 | *** Keywords *** 13 | Get file 14 | [Arguments] ${file} 15 | ${data} Get Binary File ${file} 16 | ${name} Fetch From Right ${file} / 17 | ${type} Guess Type ${file} 18 | ${result} Create Dictionary 19 | ... mime ${type}[0] 20 | ... name ${name} 21 | ... data ${data} 22 | RETURN ${result} 23 | 24 | *** Test Cases *** 25 | Test logging 26 | Item Log TRACE Trace log entry 27 | Item Log DEBUG Debug log entry 28 | Item Log INFO Info log entry 29 | Item Log WARN Warning log entry 30 | Item Log ERROR Error log entry 31 | @{file_list} List Files In Directory ${ATTACHMENTS} 32 | FOR ${file} IN @{file_list} 33 | ${attachment} Get file ${ATTACHMENTS}/${file} 34 | Item Log INFO I'm logging ${attachment}[mime] ${attachment} 35 | END 36 | -------------------------------------------------------------------------------- /robotframework/robot/saucelabs.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation The example demonstrates saucelabs integration. Set \ 3 | ... 'SAUCELABS_USER' and 'SAUCELABS_TOKEN' environment variables \ 4 | ... with yours. 5 | Library String 6 | Library OperatingSystem 7 | Library SeleniumLibrary 8 | Suite Teardown Close Browser 9 | 10 | *** Variables *** 11 | ${DELAY} 1 second 12 | ${SAUCELABS_URL} https://ondemand.eu-central-1.saucelabs.com:443/wd/hub 13 | ${SAUCELABS_PLATFORM} Windows 10 14 | 15 | 16 | *** Keywords *** 17 | Open Page 18 | [Arguments] ${browser} ${url} 19 | ${sl_user} Get Environment Variable SAUCELABS_USER 20 | ${sl_token} Get Environment Variable SAUCELABS_TOKEN 21 | ${sauce:options} Create Dictionary 22 | ... name ${TEST NAME} 23 | ${capabilities} Create Dictionary 24 | ... browserName ${browser} 25 | ... browserVersion latest 26 | ... platformName ${SAUCELABS_PLATFORM} 27 | ... sauce:options ${sauce:options} 28 | ${sl_host} Fetch From Right ${SAUCELABS_URL} // 29 | ${sl_protocol} Fetch From Left ${SAUCELABS_URL} // 30 | ${user_password} Catenate SEPARATOR=: 31 | ... ${sl_user} ${sl_token} 32 | ${remote_url} Catenate SEPARATOR= 33 | ... ${sl_protocol} // 34 | ... ${user_password} @ 35 | ... ${sl_host} 36 | Open Browser ${url} remote_url=${remote_url} 37 | ... desired_capabilities=${capabilities} 38 | Maximize Browser Window 39 | Set Selenium Speed ${DELAY} 40 | Attach Saucelabs Report 41 | ${session} Get Session Id 42 | ${sl_tag} Catenate SEPARATOR=: 43 | ... SLID ${session} 44 | Set Tags ${sl_tag} 45 | 46 | *** Test Cases *** 47 | Example page test 48 | Open Page Chrome http://www.example.com 49 | Title Should Be Example Domain 50 | Attach Saucelabs Report 51 | -------------------------------------------------------------------------------- /robotframework/robot/selenium_screenshot.robot: -------------------------------------------------------------------------------- 1 | # This example is recommended way of capturing Selenium screenshots 2 | *** Settings *** 3 | Documentation A simple failure test which takes and logs screenshot 4 | Library SeleniumLibrary 5 | Suite Setup Run Keywords Register Keyword To Run On Failure Capture Page Screenshot AND 6 | ... Set Screenshot Directory . 7 | Suite Teardown Close Browser 8 | 9 | *** Variables *** 10 | ${DELAY} 1 second 11 | 12 | *** Keywords *** 13 | Open Page 14 | [Arguments] ${browser} ${url} 15 | Open Browser ${url} ${browser} 16 | Maximize Browser Window 17 | Set Selenium Speed ${DELAY} 18 | 19 | *** Test Cases *** 20 | Screenshot test 21 | Open Page Chrome http://www.example.com 22 | Title Should Be Google 23 | -------------------------------------------------------------------------------- /robotframework/robot/simple.robot: -------------------------------------------------------------------------------- 1 | 2 | *** Test Cases *** 3 | Simple test 4 | Log Hello, world! 5 | -------------------------------------------------------------------------------- /robotframework/robot/skip_on_failure.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Example of using '--skiponfailure' parameter. To run use: 3 | ... robot --skiponfailure not_ready robot/critical.robot 4 | 5 | *** Test Cases *** 6 | Skip Failing Test 7 | [Tags] not_ready 8 | Log Skip Failing Test 9 | Should be True False 10 | -------------------------------------------------------------------------------- /robotframework/robot/suite_doc_with_urls.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation This is a test suite with URLs: [https://www.google.com | Google] and [https://www.google.com] 3 | 4 | *** Test Cases *** 5 | Simple test 6 | Log Hello, world! 7 | -------------------------------------------------------------------------------- /robotframework/robot/tags.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Example using tags, will give two tags: 'one two' and 'three'. Tags are separated by two spaces. 3 | 4 | *** Variables *** 5 | ${MESSAGE} Hello, world! 6 | 7 | *** Test Cases *** 8 | My Test 9 | [Tags] one two three 10 | Log ${MESSAGE} 11 | -------------------------------------------------------------------------------- /robotframework/robot/templates/__init__.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Test Suite for templated tests 3 | -------------------------------------------------------------------------------- /robotframework/robot/templates/datadriver.csv: -------------------------------------------------------------------------------- 1 | *** Test Cases ***;${username};${password} 2 | ;invalid;Password 3 | ;User;invalid 4 | ;invalid;invalid 5 | ;;Password 6 | ;User; 7 | ;; 8 | -------------------------------------------------------------------------------- /robotframework/robot/templates/datadriver.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Test templates defined through DataDriver and external CSV file 3 | Library DataDriver 4 | Resource test_keywords.robot 5 | Test Template Login invalid credentials 6 | 7 | *** Test Cases *** 8 | Login with user '${username}' and password '${password}' 9 | 10 | *** Keywords *** 11 | Login invalid credentials 12 | [Arguments] ${username} ${password} 13 | Run Keyword Login with invalid credentials should fail ${username} ${password} 14 | -------------------------------------------------------------------------------- /robotframework/robot/templates/keyword.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Test templates defined through keyword 3 | Resource test_keywords.robot 4 | 5 | *** Test Cases *** 6 | Invalid Password 7 | [Template] Login with invalid credentials should fail 8 | invalid ${VALID PASSWORD} 9 | ${VALID USER} invalid 10 | invalid invalid 11 | ${EMPTY} ${VALID PASSWORD} 12 | ${VALID USER} ${EMPTY} 13 | ${EMPTY} ${EMPTY} 14 | -------------------------------------------------------------------------------- /robotframework/robot/templates/settings.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation Test templates defined through settings 3 | Test Template Login with invalid credentials should fail 4 | Resource test_keywords.robot 5 | 6 | *** Test Cases *** 7 | Invalid User Name invalid ${VALID PASSWORD} 8 | Invalid Password ${VALID USER} invalid 9 | Invalid User Name and Password invalid invalid 10 | Empty User Name ${EMPTY} ${VALID PASSWORD} 11 | Empty Password ${VALID USER} ${EMPTY} 12 | Empty User Name and Password ${EMPTY} ${EMPTY} 13 | -------------------------------------------------------------------------------- /robotframework/robot/templates/test_keywords.robot: -------------------------------------------------------------------------------- 1 | *** Variables *** 2 | ${VALID USER} User 3 | ${VALID PASSWORD} Password 4 | 5 | *** Keywords *** 6 | Login with invalid credentials should fail 7 | [Arguments] ${username} ${password} 8 | Run Keyword And Expect Error Invalid credentials Validate credentials 9 | ... ${username} ${password} 10 | Validate credentials 11 | [Arguments] ${username} ${password} 12 | Should Be Equal ${username} ${VALID USER} Invalid credentials False 13 | Should Be Equal ${password} ${VALID PASSWORD} Invalid credentials False 14 | -------------------------------------------------------------------------------- /robotframework/run-pabot.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Copyright 2024 EPAM Systems 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # https://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | # Replace variables with your variables 18 | RP_API_KEY="your_rp_api_key" 19 | RP_ENDPOINT="http://localhost:8080" 20 | RP_PROJECT="default_personal" 21 | RP_LAUNCH="Robot Framework Pabot" 22 | RP_LAUNCH_DOC="My test launch" 23 | START_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ") 24 | 25 | # Extract the launch ID using curl, grep, and sed 26 | RP_LAUNCH_UUID=$(curl --location --request POST "${RP_ENDPOINT}/api/v1/${RP_PROJECT}/launch" \ 27 | --fail \ 28 | --header "Authorization: Bearer ${RP_API_KEY}" \ 29 | --header 'Content-Type: application/json' \ 30 | --data-raw '{ 31 | "attributes": [ 32 | { 33 | "key": "key", 34 | "value": "value" 35 | } 36 | ], 37 | "description": "'"${RP_LAUNCH_DOC}"'", 38 | "mode": "DEFAULT", 39 | "name": "'"${RP_LAUNCH}"'", 40 | "startTime": "'"${START_TIME}"'" 41 | }' | grep -o '"id": *"[^"]*"' | sed 's/"id": *"\([^"]*\)"/\1/') 42 | 43 | # Check if the curl command failed 44 | if [ -z "${RP_LAUNCH_UUID}" ]; then 45 | echo "Failed to create launch on ReportPortal" 46 | exit 1 47 | fi 48 | 49 | # Run tests with Pabot 50 | pabot --skiponfailure not_ready \ 51 | --metadata Scope:smoke \ 52 | --listener robotframework_reportportal.listener \ 53 | --variable RP_LAUNCH_UUID:"${RP_LAUNCH_UUID}" \ 54 | --variable RP_API_KEY:"${RP_API_KEY}" \ 55 | --variable RP_ENDPOINT:"${RP_ENDPOINT}" \ 56 | --variable RP_PROJECT:"${RP_PROJECT}" \ 57 | --variable RP_LAUNCH:"${RP_LAUNCH}" \ 58 | ./robot 59 | 60 | EXIT_CODE=$? 61 | 62 | END_TIME=$(date -u +"%Y-%m-%dT%H:%M:%SZ") 63 | # Finish the launch using curl 64 | curl --location --request PUT "${RP_ENDPOINT}/api/v1/${RP_PROJECT}/launch/${RP_LAUNCH_UUID}/finish" \ 65 | --header "Authorization: Bearer ${RP_API_KEY}" \ 66 | --header 'Content-Type: application/json' \ 67 | --data-raw '{ 68 | "endTime": "'"${END_TIME}"'" 69 | }' 70 | exit "${EXIT_CODE}" 71 | -------------------------------------------------------------------------------- /robotframework/run-post-report.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | CURRENT_DIR=$(pwd) 4 | cd venv/lib/python3.10/site-packages || fail "No venv found" 5 | 6 | # Replace runner variables with your variables 7 | python -m robotframework_reportportal.post_report \ 8 | --timezone "UTC" \ 9 | --variable RP_API_KEY:"your_rp_api_key" \ 10 | --variable RP_ENDPOINT:"http://localhost:8080" \ 11 | --variable RP_LAUNCH:"Robot Framework Post Report" \ 12 | --variable RP_PROJECT:"default_personal" \ 13 | --variable RP_LAUNCH_ATTRIBUTES:"tag key1:value1 key2:value2" \ 14 | --variable RP_LAUNCH_DOC:"My test launch" "$CURRENT_DIR/output.xml" 15 | 16 | cd "$CURRENT_DIR" || fail "No current directory found" 17 | -------------------------------------------------------------------------------- /robotframework/run-variables-file.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Replace runner variables with yours in 'variables.yaml' 4 | robot --skiponfailure not_ready \ 5 | --metadata Scope:smoke \ 6 | --listener robotframework_reportportal.listener \ 7 | --variablefile variables.yaml ./robot 8 | -------------------------------------------------------------------------------- /robotframework/run.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | # Replace runner variables with your variables 4 | robot --skiponfailure not_ready \ 5 | --metadata Scope:smoke \ 6 | --listener robotframework_reportportal.listener \ 7 | --variable RP_API_KEY:"your_rp_api_key" \ 8 | --variable RP_ENDPOINT:"http://localhost:8080" \ 9 | --variable RP_LAUNCH:"Robot Framework" \ 10 | --variable RP_PROJECT:"default_personal" \ 11 | --variable RP_LAUNCH_ATTRIBUTES:"tag key1:value1 key2:value2" \ 12 | --variable RP_LAUNCH_DOC:"My test launch" ./robot 13 | -------------------------------------------------------------------------------- /robotframework/variables.yaml: -------------------------------------------------------------------------------- 1 | rp_api_key: your_rp_access_token 2 | rp_endpoint: http://localhost:8080 3 | rp_launch: "Robot Framework" 4 | rp_project: default_personal 5 | rp_launch_attributes: "tag key1:value1 key2:value2 env:integration" 6 | rp_launch_doc: "My test launch" 7 | --------------------------------------------------------------------------------