├── .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 |