├── .all-contributorsrc ├── .github └── workflows │ ├── black.yml │ └── main.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── img ├── logo_b+w_transparent.png ├── logo_black_transparent.png ├── logo_white_transparent.png ├── robot_cookbook_logo_vector.eps ├── star-history-20231011.png ├── star-history-20240113.png ├── star-history-20240914.png └── star-history-20250115.png ├── src ├── section_01 │ ├── recipe011_hello_world_logging.robot │ └── recipe012_looping.robot ├── section_02 │ ├── recipe021_explaining_variable_prefixes.robot │ ├── recipe022_handling_lists.robot │ └── recipe023_handling_dictionaries.robot ├── section_03 │ └── recipe031_handling_dates.robot ├── section_04 │ └── recipe041_working_with_file_system.robot ├── section_05 │ └── .gitkeep ├── section_06 │ └── .gitkeep ├── section_07 │ └── recipe071_string_manipulation_examples.robot ├── section_08 │ └── .gitkeep ├── section_09 │ ├── recipe091_working_with_requests_library.robot │ ├── recipe092_working_with_rest_library.robot │ └── recipe093_working_with_browser_library.robot ├── section_10 │ ├── recipe101_working_with_databases.robot │ └── recipe102_hacking_database_view.robot ├── section_11 │ ├── recipe111_working_with_ssh_library.robot │ └── recipe112_retrieve_output_file_of_ssh_run_command.robot ├── section_12 │ └── recipe121_running_tests_in_parallel.robot ├── section_13 │ └── recipe131_selenium_setup.robot ├── section_14 │ └── recipe141_aws_simple_storage_service.robot ├── section_15 │ └── recipe151_working_with_browser_contexts.robot ├── section_95 │ └── recipe951_rf4_native_if_else_elseif.robot └── section_99 │ ├── __init__.robot │ ├── casestudy_01 │ ├── ParkCalc │ │ ├── BDD │ │ │ ├── economy.robot │ │ │ ├── long-term-garage.robot │ │ │ ├── long-term-surface.robot │ │ │ ├── resource.resource │ │ │ ├── short-term.robot │ │ │ └── valet.robot │ │ ├── README.txt │ │ ├── data-driven │ │ │ ├── functional.robot │ │ │ └── resource.resource │ │ └── keyword-driven │ │ │ ├── economy.robot │ │ │ ├── long-term-garage.robot │ │ │ ├── long-term-surface.robot │ │ │ ├── resource.resource │ │ │ ├── short-term.robot │ │ │ └── valet.robot │ └── README.md │ └── casestudy_02 │ └── README.md └── tests ├── requirements-3.10.txt ├── requirements-3.11.txt ├── requirements-3.6.txt ├── requirements-3.7.txt ├── requirements-3.8.txt ├── requirements-3.9.txt └── robocop_rules.py /.all-contributorsrc: -------------------------------------------------------------------------------- 1 | { 2 | "files": [ 3 | "README.md" 4 | ], 5 | "imageSize": 100, 6 | "commit": false, 7 | "contributors": [ 8 | { 9 | "login": "adrianyorke", 10 | "name": "Adrian Yorke", 11 | "avatar_url": "https://avatars1.githubusercontent.com/u/30093433?v=4", 12 | "profile": "https://github.com/adrianyorke", 13 | "contributions": [ 14 | "code", 15 | "doc", 16 | "maintenance", 17 | "review" 18 | ] 19 | }, 20 | { 21 | "login": "tompurl", 22 | "name": "Tom Purl", 23 | "avatar_url": "https://avatars1.githubusercontent.com/u/588713?v=4", 24 | "profile": "http://www.tompurl.com", 25 | "contributions": [ 26 | "code", 27 | "doc" 28 | ] 29 | }, 30 | { 31 | "login": "szabolcstoth", 32 | "name": "Szabolcs Tóth", 33 | "avatar_url": "https://avatars3.githubusercontent.com/u/1639751?v=4", 34 | "profile": "http://szabolcstoth.eu", 35 | "contributions": [ 36 | "code", 37 | "doc" 38 | ] 39 | }, 40 | { 41 | "login": "rasjani", 42 | "name": "Jani Mikkonen", 43 | "avatar_url": "https://avatars3.githubusercontent.com/u/27887?v=4", 44 | "profile": "https://rasjani.github.io", 45 | "contributions": [ 46 | "code", 47 | "doc" 48 | ] 49 | }, 50 | { 51 | "login": "bhirsz", 52 | "name": "Bartłomiej Hirsz", 53 | "avatar_url": "https://avatars3.githubusercontent.com/u/8532066?v=4", 54 | "profile": "https://github.com/bhirsz", 55 | "contributions": [ 56 | "code", 57 | "doc", 58 | "maintenance", 59 | "review" 60 | ] 61 | }, 62 | { 63 | "login": "tuxmux28", 64 | "name": "Christoph", 65 | "avatar_url": "https://avatars1.githubusercontent.com/u/2794048?v=4", 66 | "profile": "https://github.com/tuxmux28", 67 | "contributions": [ 68 | "code", 69 | "doc" 70 | ] 71 | }, 72 | { 73 | "login": "mkorpela", 74 | "name": "Mikko Korpela", 75 | "avatar_url": "https://avatars1.githubusercontent.com/u/136885?v=4", 76 | "profile": "https://github.com/mkorpela", 77 | "contributions": [ 78 | "code", 79 | "doc" 80 | ] 81 | }, 82 | { 83 | "login": "ericbjones", 84 | "name": "ericbjones", 85 | "avatar_url": "https://avatars2.githubusercontent.com/u/1847952?v=4", 86 | "profile": "https://github.com/ericbjones", 87 | "contributions": [ 88 | "design", 89 | "code", 90 | "doc" 91 | ] 92 | }, 93 | { 94 | "login": "emna24", 95 | "name": "Emna Ayadi", 96 | "avatar_url": "https://avatars.githubusercontent.com/u/6690738?v=4", 97 | "profile": "https://emnaayadi.wordpress.com/", 98 | "contributions": [ 99 | "userTesting", 100 | "code" 101 | ] 102 | }, 103 | { 104 | "login": "joonvena", 105 | "name": "Joonas Venäläinen", 106 | "avatar_url": "https://avatars.githubusercontent.com/u/38143731?v=4", 107 | "profile": "https://medium.com/@joonasvenlinen", 108 | "contributions": [ 109 | "code" 110 | ] 111 | }, 112 | { 113 | "login": "olakowalczyk", 114 | "name": "Aleksandra Kowalczyk", 115 | "avatar_url": "https://avatars.githubusercontent.com/u/60587401?v=4", 116 | "profile": "https://github.com/olakowalczyk", 117 | "contributions": [ 118 | "code" 119 | ] 120 | }, 121 | { 122 | "login": "kiblik1", 123 | "name": "Martin Škopek", 124 | "avatar_url": "https://avatars.githubusercontent.com/u/12598836?v=4", 125 | "profile": "https://github.com/kiblik1", 126 | "contributions": [ 127 | "code" 128 | ] 129 | }, 130 | { 131 | "login": "sarafurd", 132 | "name": "sarafurd", 133 | "avatar_url": "https://avatars.githubusercontent.com/u/67877801?v=4", 134 | "profile": "https://github.com/sarafurd", 135 | "contributions": [ 136 | "doc", 137 | "maintenance" 138 | ] 139 | }, 140 | { 141 | "login": "jepoy92", 142 | "name": "Jeff Choi", 143 | "avatar_url": "https://avatars.githubusercontent.com/u/65995065?v=4", 144 | "profile": "https://jepoy92.github.io/webdev-portfolio/", 145 | "contributions": [ 146 | "doc", 147 | "maintenance" 148 | ] 149 | }, 150 | { 151 | "login": "ChinoUkaegbu", 152 | "name": "ChinoUkaegbu", 153 | "avatar_url": "https://avatars.githubusercontent.com/u/77782533?v=4", 154 | "profile": "https://github.com/ChinoUkaegbu", 155 | "contributions": [ 156 | "code" 157 | ] 158 | } 159 | ], 160 | "contributorsPerLine": 7, 161 | "projectName": "robotframework-cookbook", 162 | "projectOwner": "adrianyorke", 163 | "repoType": "github", 164 | "repoHost": "https://github.com", 165 | "skipCi": true, 166 | "commitConvention": "angular", 167 | "commitType": "docs" 168 | } 169 | -------------------------------------------------------------------------------- /.github/workflows/black.yml: -------------------------------------------------------------------------------- 1 | # Enforce Black formatting for Python code 2 | name: Black 3 | 4 | on: 5 | push: 6 | branches: [ master ] 7 | pull_request: 8 | branches: [ master ] 9 | 10 | jobs: 11 | black: 12 | runs-on: ubuntu-latest 13 | steps: 14 | - uses: actions/checkout@v4 15 | - uses: psf/black@stable 16 | -------------------------------------------------------------------------------- /.github/workflows/main.yml: -------------------------------------------------------------------------------- 1 | # This workflow will run Robot Framework examples and perform static code analysis on robot code 2 | 3 | name: Continuous integration 4 | on: 5 | push: 6 | branches: [ master ] 7 | pull_request: 8 | branches: [ master ] 9 | 10 | jobs: 11 | build: 12 | strategy: 13 | fail-fast: false 14 | matrix: 15 | os: ['ubuntu-latest', 'windows-latest'] 16 | python-version: ['3.10', '3.11'] 17 | node-version: [20] 18 | runs-on: ${{ matrix.os }} 19 | 20 | steps: 21 | - name: Checkout 22 | uses: actions/checkout@v4 23 | - name: Set up Node.js 24 | uses: actions/setup-node@v4 25 | with: 26 | node-version: ${{ matrix.node-version }} 27 | - name: Set up Python ${{ matrix.python-version }} 28 | uses: actions/setup-python@v5 29 | with: 30 | python-version: ${{ matrix.python-version }} 31 | - name: Install dependencies 32 | run: | 33 | python -m pip install --upgrade pip 34 | pip install -U -r tests/requirements-${{ matrix.python-version }}.txt 35 | webdrivermanager firefox chrome 36 | - name: Init Browser 37 | run: 38 | rfbrowser init 39 | if: matrix.python-version != 3.6 40 | - name: Run Robocop 41 | run: 42 | robocop -r rules_by_id --configure return_status:quality_gate:W=-1 --exclude missing-doc-* --ignore section_99\* --ext-rules tests/robocop_rules.py src 43 | if: always() 44 | - name: Run Robot tests 45 | run: 46 | python -m robot --exclude pabot --include py${{ matrix.python-version }} --exclude casestudy --exclude no-ci-testing --outputdir recipe_tests src 47 | if: always() 48 | - name: Run Robot parallel tests 49 | run: 50 | pabot --testlevelsplit --processes 4 --command python -m robot --end-command --include pabotANDpy${{ matrix.python-version }} --exclude casestudy --exclude no-ci-testing --outputdir recipe_tests_pabot src 51 | if: always() 52 | - name: Save test results 53 | uses: actions/upload-artifact@v4 54 | with: 55 | name: robot-tests-logs-${{ strategy.job-index }} 56 | path: | 57 | recipe_tests 58 | recipe_tests_pabot 59 | if: always() 60 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # RED 2 | /libspecs/ 3 | .project 4 | red.xml 5 | 6 | # PyCharm 7 | .idea/ 8 | venv/ 9 | 10 | # Byte-compiled / optimized / DLL files 11 | __pycache__/ 12 | *.py[cod] 13 | *$py.class 14 | 15 | # Robot Framework Test Output 16 | **/log.html 17 | **/output.xml 18 | **/report.html 19 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | # Contributor Covenant Code of Conduct 2 | 3 | ## Our Pledge 4 | 5 | In the interest of fostering an open and welcoming environment, we as 6 | contributors and maintainers pledge to making participation in our project and 7 | our community a harassment-free experience for everyone, regardless of age, body 8 | size, disability, ethnicity, sex characteristics, gender identity and expression, 9 | level of experience, education, socio-economic status, nationality, personal 10 | appearance, race, religion, or sexual identity and orientation. 11 | 12 | ## Our Standards 13 | 14 | Examples of behavior that contributes to creating a positive environment 15 | include: 16 | 17 | * Using welcoming and inclusive language 18 | * Being respectful of differing viewpoints and experiences 19 | * Gracefully accepting constructive criticism 20 | * Focusing on what is best for the community 21 | * Showing empathy towards other community members 22 | 23 | Examples of unacceptable behavior by participants include: 24 | 25 | * The use of sexualized language or imagery and unwelcome sexual attention or 26 | advances 27 | * Trolling, insulting/derogatory comments, and personal or political attacks 28 | * Public or private harassment 29 | * Publishing others' private information, such as a physical or electronic 30 | address, without explicit permission 31 | * Other conduct which could reasonably be considered inappropriate in a 32 | professional setting 33 | 34 | ## Our Responsibilities 35 | 36 | Project maintainers are responsible for clarifying the standards of acceptable 37 | behavior and are expected to take appropriate and fair corrective action in 38 | response to any instances of unacceptable behavior. 39 | 40 | Project maintainers have the right and responsibility to remove, edit, or 41 | reject comments, commits, code, wiki edits, issues, and other contributions 42 | that are not aligned to this Code of Conduct, or to ban temporarily or 43 | permanently any contributor for other behaviors that they deem inappropriate, 44 | threatening, offensive, or harmful. 45 | 46 | ## Scope 47 | 48 | This Code of Conduct applies both within project spaces and in public spaces 49 | when an individual is representing the project or its community. Examples of 50 | representing a project or community include using an official project e-mail 51 | address, posting via an official social media account, or acting as an appointed 52 | representative at an online or offline event. Representation of a project may be 53 | further defined and clarified by project maintainers. 54 | 55 | ## Enforcement 56 | 57 | Instances of abusive, harassing, or otherwise unacceptable behavior may be 58 | reported by contacting the project team at adrianyorke@gmail.com. All 59 | complaints will be reviewed and investigated and will result in a response that 60 | is deemed necessary and appropriate to the circumstances. The project team is 61 | obligated to maintain confidentiality with regard to the reporter of an incident. 62 | Further details of specific enforcement policies may be posted separately. 63 | 64 | Project maintainers who do not follow or enforce the Code of Conduct in good 65 | faith may face temporary or permanent repercussions as determined by other 66 | members of the project's leadership. 67 | 68 | ## Attribution 69 | 70 | This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4, 71 | available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html 72 | 73 | [homepage]: https://www.contributor-covenant.org 74 | 75 | For answers to common questions about this code of conduct, see 76 | https://www.contributor-covenant.org/faq 77 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Anyone is welcome to contribute by making a pull request 4 | - Find an [issue](https://github.com/adrianyorke/robotframework-cookbook/issues) to work on 5 | - Fork the project 6 | - After you've cloned your fork of the project, you will need to make a branch 7 | ``` 8 | $ git checkout -b name-of-branch 9 | 10 | ``` 11 | - Make any changes, save your work, and make the necessary commits 12 | - Example: fixes-issue-xxx or feature-issue-xxx 13 | - Use present tense 14 | 15 | ``` 16 | $ git add . 17 | $ git commit -m "fixes-issue-xxx" 18 | $ git status 19 | 20 | # Push the code to the branch you made 21 | $ git push origin name-of-your-branch 22 | 23 | ``` 24 | - Once you've pushed your branch, don't forget to make a pull request into the `master` branch. 25 | 26 | 27 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2025 Adrian Yorke 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #
robotframework-cookbook 2 | 3 | 4 | [![All Contributors](https://img.shields.io/badge/all_contributors-15-orange.svg?style=flat-square)](#contributors-) 5 | 6 | [![Actions Status](https://github.com/adrianyorke/robotframework-cookbook/workflows/Continuous%20integration/badge.svg)](https://github.com/adrianyorke/robotframework-cookbook/actions) 7 | [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 8 | [![code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) 9 | [![Maintenance](https://img.shields.io/badge/Maintained%3F-yes-green.svg)](https://github.com/adrianyorke) 10 | 11 | 12 | A curated list of delicious Robot Framework recipes that will help accelerate the development of test automation scripts, especially for beginner or intermediate level engineers. 13 | 14 | If you need help writing Robot Framework scripts or wish to update older scripts to use newer syntax then you have come to the right place. Here we will compile and maintain recipes of working Robot Framework scripts that can be used in your domain. 15 | 16 | In the first part of the cookbook there are many simple recipes showing how to use builtin keywords and additional keywords from both internal and external Robot Framework libraries. Towards the back of the cookbook there are complete case studies demonstrating whole projects and test automation solutions. 17 | 18 | ## Other useful resources 19 | * [Robot Framework Organization](https://robotframework.org/) 20 | * [Beginners Guide to Robot Framework](https://github.com/robotframework/BeginnersGuide) 21 | * [Robot Framework Quick Start Guide](https://github.com/robotframework/QuickStartGuide/blob/master/QuickStart.rst) 22 | * [Robot Framework User Guide](https://robotframework.org/robotframework/latest/RobotFrameworkUserGuide.html) 23 | * [Robot Framework documentation](https://robotframework.org/robotframework/) 24 | * [GitHub (Documentation, Source Code & Issue Tracker)](https://github.com/robotframework/robotframework) 25 | * [Awesome Robot Framework](https://github.com/fkromer/awesome-robotframework) 26 | * [Robot Framework - Learn the basics](https://dev.szabolcstoth.eu/robotframework-basics/) 27 | * [Robot Framework Cheat Sheet and Quick Reference (credit: robocorp)](https://robocorp.com/docs/languages-and-frameworks/robot-framework/cheat-sheet) 28 | 29 | ## Star History 30 | 31 | 32 | ## Notes for contributors 33 | Contributions from the wider community are most welcome! Contributions can be either single recipes or whole case studies. 34 | 35 | We recommend using [Robotidy](https://robotidy.readthedocs.io/en/latest/) to help standardise the format of the Robot Framework code. 36 | 37 | We also recommend using the [Robot Framework Robocop](https://github.com/MarketSquare/robotframework-robocop) static analysis tool to check your scripts are clean before submission. 38 | Robocop can be installed using pip: 39 | > $ python -m pip install -U robotframework-robocop 40 | 41 | [Issues](https://github.com/adrianyorke/robotframework-cookbook/issues) are welcome and you can use them to post ideas for new recipes or report bugs and other observations for exisiting recipes. 42 | 43 | For larger submissions simply clone this repository, create a feature branch (or work directly on master) and submit a pull request to merge your branch. If you are not comfortable with Git workflow then simply post your submission on the [#cookbook](https://app.slack.com/client/T07PJQ9S7/CU5RQ87K3) Slack channel and I will help you publish your recipe or case study. 44 | 45 | ## Installation and Usage 46 | 47 | Python and Robot Framework must be installed prior to using [Robot Framework Cookbook](https://github.com/adrianyorke/robotframework-cookbook). Download [Python](https://www.python.org/downloads/) and add to [PATH](https://docs.python.org/3/using/windows.html#the-full-installer) during installation, then, use a command-line interpreter of your choice and run the following to install Robot Framework: 48 | 49 | > $ python -m pip install -U robotframework 50 | 51 | You can check if the installation was succesful by running the following command: 52 | > $ robot --version 53 | 54 | After confirming Robot Framework installation was a success, clone the [Robot Framework Cookbook](https://github.com/adrianyorke/robotframework-cookbook) repository by running the following command: 55 | 56 | > $ git clone https://github.com/adrianyorke/robotframework-cookbook.git 57 | 58 | Once the repository has been cloned, you can install relevant libraries by navigating to the tests folder and running: 59 | 60 | > $ python -m pip install -U -r ./tests/requirements-[version].txt 61 | 62 | ## Table of contents 63 | 1. Standard Library - [BuiltIn](https://robotframework.org/robotframework/latest/libraries/BuiltIn.html)
64 | * [Recipe 1.1 - Hello World Logging](src/section_01/recipe011_hello_world_logging.robot)
65 | * [Recipe 1.2 - For Loop](src/section_01/recipe012_looping.robot)
66 | 1. Standard Library - [Collections](https://robotframework.org/robotframework/latest/libraries/Collections.html) 67 | * [Recipe 2.1 - Explaining Variable Prefixes](src/section_02/recipe021_explaining_variable_prefixes.robot)
68 | * [Recipe 2.2 - Handling Lists](src/section_02/recipe022_handling_lists.robot)
69 | * [Recipe 2.3 - Handling Dictionaries](src/section_02/recipe023_handling_dictionaries.robot)
70 | 1. Standard Library - [DateTime](https://robotframework.org/robotframework/latest/libraries/DateTime.html) 71 | * [Recipe 3.1 - Handling Dates](src/section_03/recipe031_handling_dates.robot)
72 | 1. Standard Library - OperatingSystem 73 | * [Recipe 4.1 - Working With File System](src/section_04/recipe041_working_with_file_system.robot)
74 | 1. Standard Library - [Process](https://robotframework.org/robotframework/latest/libraries/Process.html) 75 | 1. Standard Library - Remote 76 | 1. Standard Library - [String](https://robotframework.org/robotframework/latest/libraries/String.html) 77 | * [Recipe 7.1 - String Manipulation Examples](src/section_07/recipe071_string_manipulation_examples.robot)
78 | 1. Standard Library - [XML](https://robotframework.org/robotframework/latest/libraries/XML.html) 79 | 1. External Library - REST API 80 | * [Recipe 9.1 - Working With Requests Library](src/section_09/recipe091_working_with_requests_library.robot)
81 | * [Recipe 9.2 - Working With RESTinstance Library](src/section_09/recipe092_working_with_rest_library.robot)
82 | * [Recipe 9.3 - Working With Browser Library](src/section_09/recipe093_working_with_browser_library.robot) 83 | 1. External Library - Databases 84 | * [Recipe 10.1 - Working With Databases](src/section_10/recipe101_working_with_databases.robot)
85 | * [Recipe 10.2 - Hacking Database View](src/section_10/recipe102_hacking_database_view.robot)
86 | 1. External Library - [SSH](https://github.com/robotframework/SSHLibrary) 87 | * [Recipe 11.1 - Working With SSH](src/section_11/recipe111_working_with_ssh_library.robot)
88 | * [Recipe 11.2 - Retrieve Output from SSH Run Command](src/section_11/recipe112_retrieve_output_file_of_ssh_run_command.robot)
89 | 1. External Library - [Parallel executor for Robot Framework test cases (pabot)](https://github.com/mkorpela/pabot)
90 | * [Recipe 12.1 - Running Tests in Parallel](src/section_12/recipe121_running_tests_in_parallel.robot)
91 | 1. External Library - [SeleniumLibrary](https://github.com/robotframework/seleniumlibrary) and [SeleniumTestability](https://github.com/rasjani/robotframework-seleniumtestability) 92 | * [Recipe 13.1 - SeleniumLibrary & SeleniumTestability setup](src/section_13/recipe131_selenium_setup.robot)
93 | 1. External Library - [AWSLibrary - for interacting with Amazon Web Services (AWS) Cloud Computing Services](https://github.com/teaglebuilt/robotframework-aws) 94 | * [Recipe 14.1 - AWS Simple Storage Service (S3)](src/section_14/recipe141_aws_simple_storage_service.robot)
95 | 1. External Library - [Robot Framework Browser library powered by Playwright.](https://github.com/MarketSquare/robotframework-browser) 96 | * [Recipe 15.1 - Working With Browser Contexts](src/section_15/recipe151_working_with_browser_contexts.robot)
97 | 1. Robot Framework 4 98 | * [Recipe 95.1 - Robot Framework 4 Native IF, ELSE, ELSE IF Syntax](src/section_95/recipe951_rf4_native_if_else_elseif.robot)
99 | 1. Case Studies 100 | * [Case Study 01 - Regression Testing Gerald Ford International Airport (GFIA) Parking Lot Calculation Tool](src/section_99/casestudy_01/README.md)
101 | * [Case Study 02 - Transcoding video library to a contemporary format suitable for all play back devices, e.g. mp4 or mkv](src/section_99/casestudy_02/README.md)
102 | 103 | ## Contributors ✨ 104 | 105 | Thanks goes to these wonderful people ([emoji key](https://allcontributors.org/docs/en/emoji-key)): 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 |
Adrian Yorke
Adrian Yorke

💻 📖 🚧 👀
Tom Purl
Tom Purl

💻 📖
Szabolcs Tóth
Szabolcs Tóth

💻 📖
Jani Mikkonen
Jani Mikkonen

💻 📖
Bartłomiej Hirsz
Bartłomiej Hirsz

💻 📖 🚧 👀
Christoph
Christoph

💻 📖
Mikko Korpela
Mikko Korpela

💻 📖
ericbjones
ericbjones

🎨 💻 📖
Emna Ayadi
Emna Ayadi

📓 💻
Joonas Venäläinen
Joonas Venäläinen

💻
Aleksandra Kowalczyk
Aleksandra Kowalczyk

💻
Martin Škopek
Martin Škopek

💻
sarafurd
sarafurd

📖 🚧
Jeff Choi
Jeff Choi

📖 🚧
ChinoUkaegbu
ChinoUkaegbu

💻
135 | 136 | 137 | 138 | 139 | 140 | 141 | This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome! 142 | -------------------------------------------------------------------------------- /img/logo_b+w_transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adrianyorke/robotframework-cookbook/3a36f5f00476791b2068a63b710e9ced51b523dc/img/logo_b+w_transparent.png -------------------------------------------------------------------------------- /img/logo_black_transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adrianyorke/robotframework-cookbook/3a36f5f00476791b2068a63b710e9ced51b523dc/img/logo_black_transparent.png -------------------------------------------------------------------------------- /img/logo_white_transparent.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adrianyorke/robotframework-cookbook/3a36f5f00476791b2068a63b710e9ced51b523dc/img/logo_white_transparent.png -------------------------------------------------------------------------------- /img/robot_cookbook_logo_vector.eps: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adrianyorke/robotframework-cookbook/3a36f5f00476791b2068a63b710e9ced51b523dc/img/robot_cookbook_logo_vector.eps -------------------------------------------------------------------------------- /img/star-history-20231011.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adrianyorke/robotframework-cookbook/3a36f5f00476791b2068a63b710e9ced51b523dc/img/star-history-20231011.png -------------------------------------------------------------------------------- /img/star-history-20240113.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adrianyorke/robotframework-cookbook/3a36f5f00476791b2068a63b710e9ced51b523dc/img/star-history-20240113.png -------------------------------------------------------------------------------- /img/star-history-20240914.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adrianyorke/robotframework-cookbook/3a36f5f00476791b2068a63b710e9ced51b523dc/img/star-history-20240914.png -------------------------------------------------------------------------------- /img/star-history-20250115.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adrianyorke/robotframework-cookbook/3a36f5f00476791b2068a63b710e9ced51b523dc/img/star-history-20250115.png -------------------------------------------------------------------------------- /src/section_01/recipe011_hello_world_logging.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation PROBLEM: 3 | ... You want to output a text message or variable to the log generated by Robot Framework. 4 | ... DISCUSSION: 5 | ... Congratulations! You have created your first Robot Framework script which outputs 6 | ... a text message and a variable to the log and also the console. 7 | ... This recipe only using keywords from BuiltIn standard library so there is no Library import. 8 | Test Tags py3.10 py3.11 9 | 10 | *** Variables *** 11 | ${recipe} Recipe 1.1 Hello World Logging 12 | ${level} Beginner 13 | ${category} Internal Library: BuiltIn 14 | ${name} Alan Turing 15 | 16 | *** Test Cases *** 17 | Sending Ouput To Log and Console 18 | [Documentation] Output variables & text messages to the log, console or both. 19 | Log Variables 20 | Log Hello World! 21 | Log Hello ${name}! console=yes 22 | Log To Console Hello World again, this time only output to the console. 23 | -------------------------------------------------------------------------------- /src/section_01/recipe012_looping.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation PROBLEM: 3 | ... You want to implement basic FOR loop or WHILE loop logic. 4 | ... DISCUSSION: 5 | ... FOR loop syntax is available as part of the built-in standard library. 6 | ... There is no specific WHILE syntax but it can be simulated using the 7 | ... Exit For Loop If keyword as the first statement within a 8 | ... large iteration FOR loop. 9 | ... No Operation keyword is used to "do nothing" although you may disagee. 10 | ... This recipe only using keywords from BuiltIn standard library so there is no Library import. 11 | ... NOTE: the old FOR syntax should no longer be used but you may still find it in old posts. 12 | Test Tags py3.10 py3.11 13 | 14 | *** Variables *** 15 | ${recipe} Recipe 1.2 Looping 16 | ${level} Beginner 17 | ${category} Internal Library: BuiltIn 18 | 19 | *** Test Cases *** 20 | Testing FOR IN Syntax 21 | [Documentation] Basic For in syntax, loops over given weekdays. 22 | FOR ${weekday} IN monday tuesday wednesday thursday friday 23 | Log ${weekday} console=yes 24 | END 25 | 26 | Testing Basic FOR Loop (New Syntax) 27 | [Documentation] Basic For loop construct, loops over values from 0 to 9. 28 | FOR ${i} IN RANGE 10 29 | Log ${i} console=yes 30 | END 31 | 32 | Testing WHILE Loop 33 | [Documentation] Simulated WHILE loop construct, loops over large range appropriate within context. 34 | FOR ${i} IN RANGE 999999 35 | Exit For Loop If ${i} == 10 36 | No Operation 37 | END 38 | -------------------------------------------------------------------------------- /src/section_02/recipe021_explaining_variable_prefixes.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation PROBLEM: 3 | ... You are confused by variable prefixes in Robot Framework and don't know which 4 | ... one to use and when. 5 | ... DISCUSSION: 6 | ... This is a common problem for test engineers new to Robot Framework but it's not 7 | ... difficult once you understand what each prefix does. 8 | ... Run this recipe and closely examine the results in the log. 9 | ... Scalar variables start with $ prefix and should be considered a single value. 10 | ... The @ prefix is similar to the * (expansion or unpacking) operator in Python. 11 | ... Ruby and Perl developers will be familiar with the term "splat". 12 | ... JavaScript community will know this as the spread operator. 13 | ... This recipe also demonstrates how to create your own user keywords and use 14 | ... these in your test cases without needing to create lower level library keywords 15 | ... using Java or Python. 16 | ... SEE ALSO: 17 | ... BuiltIn library also has keywords for creating lists and dictionaries, checking 18 | ... length or count and checking membership or equality. 19 | Library Collections 20 | Test Tags py3.10 py3.11 21 | 22 | *** Variables *** 23 | ${recipe} Recipe 2.1 Explaining Variable Prefixes 24 | ${level} Beginner 25 | ${category} Internal Library: Collections 26 | 27 | *** Test Cases *** 28 | Lists Lists Lists 29 | ${list} = Create List a b c 30 | @{also_list} = Set Variable a b c 31 | Eat One List ${also_list} 32 | Eat Many Values @{list} 33 | Eat Many Values d e @{also_list} 34 | ${a} = Create List a 35 | @{bc} = Set Variable b c 36 | Log ABC ${a} @{bc} 37 | 38 | *** Keywords *** 39 | Eat One List 40 | [Arguments] ${li} 41 | Log Many @{li} 42 | Log ${li} 43 | 44 | Eat Many Values 45 | [Arguments] @{li} 46 | Log Many @{li} 47 | Log ${li} 48 | 49 | Log ABC 50 | [Arguments] ${a} @{bc} 51 | Log ${a} 52 | Log ${bc}[0] 53 | Log ${bc}[1] 54 | -------------------------------------------------------------------------------- /src/section_02/recipe022_handling_lists.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation PROBLEM: 3 | ... You want to handle lists natively within Robot Framework scripts without needing to 4 | ... use lower level Python code or develop a custom library. 5 | ... DISCUSSION: 6 | ... This recipe demonstrates using keywords from the Collections library. 7 | ... List variables are created using Create List keyword from the BuiltIn Library. 8 | ... This recipe also demonstrates how to extend Robot Framework using Evaluate keyword to implement 9 | ... small snippets of embedded Python code. 10 | ... SEE ALSO: 11 | ... BuiltIn library also has keywords for creating lists and dictionaries, checking 12 | ... length or count and checking membership or equality. 13 | ... Recipe 041 also demonstrates using list & dictionaries using only BuiltIn library keywords. 14 | Library Collections 15 | Test Tags py3.10 py3.11 16 | 17 | *** Variables *** 18 | ${recipe} Recipe 2.2 Handling Lists 19 | ${level} Intermediate 20 | ${category} Internal Library: Collections 21 | 22 | *** Test Cases *** 23 | Testing List of Numbers 24 | # Scalar variables start with $ prefix 25 | # Expanded list variables start with @ prefix 26 | ${randlist}= Evaluate random.sample(range(1, 20), 5) modules=random 27 | ${itemcount} = Get Length ${randlist} 28 | ${numbers} = Create List @{randlist} 29 | Log List ${numbers} 30 | Sort List ${numbers} 31 | Log List ${numbers} 32 | 33 | Testing List Of Letters 34 | ${letters} = Create List a b c 35 | ${matches} = Count Values In List ${letters} c 36 | Log List ${letters} 37 | List Should Contain Value ${letters} b 38 | List Should Not Contain Value ${letters} z 39 | Remove Values From List ${letters} a c 40 | Log List ${letters} 41 | Append To List ${letters} z x j f 42 | Sort List ${letters} 43 | Log List ${letters} 44 | -------------------------------------------------------------------------------- /src/section_02/recipe023_handling_dictionaries.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation PROBLEM: 3 | ... You want to handle a dictionary within a Robot Framework script without needing to develop 4 | ... a custom library using Java or Python. 5 | ... DISCUSSION: 6 | ... This recipe demonstrates using keywords from BuiltIn and Collections libraries. 7 | ... Dictionary variables are created using keywords from the BuiltIn Library. 8 | ... SEE ALSO: 9 | ... BuiltIn library also has keywords for creating dictionaries, checking length or count and 10 | ... checking membership. 11 | ... Recipe 041 demonstrates using list & dictionaries using only BuiltIn library keywords. 12 | Library Collections 13 | Test Tags py3.10 py3.11 14 | 15 | *** Variables *** 16 | ${recipe} Recipe 2.3 Handling Dictionaries 17 | ${level} Intermediate 18 | ${category} Internal Library: Collections 19 | 20 | *** Test Cases *** 21 | Dictionary Testing 22 | &{dict1} = Create Dictionary team=Wolverhampton Wanderers 23 | &{dict2} = Create Dictionary stadium=Molineux 24 | # merge dictionaries, if keys appear multiple times final value will be used. 25 | &{dict} = Create Dictionary &{dict1} &{dict2} nickname=Wolves 26 | Should Be True ${dict} == {'team': 'Wolverhampton Wanderers', 'stadium': 'Molineux', 'nickname': 'Wolves'} 27 | # demonstrate dot access 28 | Should Be Equal ${dict.stadium} Molineux 29 | Should Be Equal ${dict.nickname} Wolves 30 | Should Not Be Equal ${dict.nickname} The Red Devils 31 | Dictionary Should Contain Key ${dict} nickname 32 | Dictionary Should Contain Value ${dict} Wolves 33 | ${val} = Pop From Dictionary ${dict} nickname 34 | # use $ variable prefix to access dictionary as a single, scalar value 35 | Log ${dict} 36 | # use & variable prefix to expand the dictionary into key-value pairs 37 | Log Many &{dict} 38 | Log Dictionary ${dict} 39 | -------------------------------------------------------------------------------- /src/section_03/recipe031_handling_dates.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation PROBLEM: 3 | ... You want to handle dates within a Robot Framework test case 4 | ... without using lower level Python code or develop a custom library. 5 | ... DISCUSSION: 6 | ... This recipe demonstrates: 7 | ... - using keywords from the DateTime library, 8 | ... - changing the default result_format and using timedelta 9 | ... instead of number or time string formats, 10 | ... - using extended variable syntax. 11 | Library DateTime 12 | Test Tags py3.10 py3.11 13 | 14 | *** Variables *** 15 | ${recipe} Recipe 3.1 Handling Dates 16 | ${level} Beginner 17 | ${category} Internal Library: DateTime 18 | ${unicode_release_date} 1991-10-01 19 | 20 | *** Test Cases *** 21 | How Much Time Has Passed Since Unicode 1.0 Was Released 22 | ${current_date}= Get Current Date 23 | ${time_passed_since_release}= Subtract Date From Date 24 | ... ${current_date} ${unicode_release_date} result_format=verbose 25 | Log ${time_passed_since_release} 26 | 27 | How Many Days And Years Passed Since Unicode 1.0 Was Released 28 | ${current_date}= Get Current Date 29 | ${days_passed_since_release}= Subtract Date From Date 30 | ... ${current_date} ${unicode_release_date} result_format=timedelta 31 | Log ${days_passed_since_release.days} days passed! 32 | Log ${days_passed_since_release.days / 365} years passed! 33 | -------------------------------------------------------------------------------- /src/section_04/recipe041_working_with_file_system.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation PROBLEM: 3 | ... You want to query the file system and list items, files and directories. 4 | ... DISCUSSION: 5 | ... This recipe demonstrates list variables, FOR loop and how to import a library. 6 | ... We choose ${TEMPDIR} here as it works on all platforms. 7 | Library OperatingSystem 8 | Test Tags py3.10 py3.11 9 | 10 | *** Variables *** 11 | ${recipe} Recipe 4.1 Working With File System 12 | ${level} Beginner 13 | ${category} Internal Library: OperatingSystem 14 | 15 | *** Test Cases *** 16 | Listing Directory Contents 17 | Log Variables 18 | @{itemlist} = List Directory ${TEMPDIR} 19 | @{filelist} = List Files In Directory ${TEMPDIR} absolute=True 20 | @{directorylist} = List Directories In Directory ${TEMPDIR} 21 | ${countitems} = Count Items In Directory ${TEMPDIR} 22 | ${countfiles} = Count Files In Directory ${TEMPDIR} 23 | ${countdirectories} = Count Directories In Directory ${TEMPDIR} 24 | FOR ${directory} IN @{directorylist} 25 | Log ${directory} console=true 26 | END 27 | -------------------------------------------------------------------------------- /src/section_05/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adrianyorke/robotframework-cookbook/3a36f5f00476791b2068a63b710e9ced51b523dc/src/section_05/.gitkeep -------------------------------------------------------------------------------- /src/section_06/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adrianyorke/robotframework-cookbook/3a36f5f00476791b2068a63b710e9ced51b523dc/src/section_06/.gitkeep -------------------------------------------------------------------------------- /src/section_07/recipe071_string_manipulation_examples.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation PROBLEM: 3 | ... You want to manipulate strings within a Robot Framework test case 4 | ... without using low-level Python code or developing a custom library. 5 | ... DISCUSSION: 6 | ... This recipe demonstrates using keywords from String standard library. 7 | Library String 8 | Test Tags py3.10 py3.11 9 | 10 | *** Variables *** 11 | ${recipe} Recipe 7.1 String Manipulation Examples 12 | ${level} Beginner 13 | ${category} Internal Library: String 14 | 15 | *** Test Cases *** 16 | Check Lower Case Keywords 17 | [Documentation] Testing lower case string keywords. 18 | ${name} Convert To Lower Case Harry Potter 19 | Should Be Equal ${name} harry potter 20 | Should Be Lowercase ${name} 21 | 22 | Check Title Case Keywords 23 | [Documentation] Testing title case string keywords. 24 | ${name} Convert To Title Case hermione granger 25 | Should Be Equal ${name} Hermione Granger 26 | Should Be Titlecase ${name} 27 | 28 | Check Upper Case Keywords 29 | [Documentation] Testing upper case string keywords. 30 | ${name} Convert To Upper Case ron weasley 31 | Should Be Equal ${name} RON WEASLEY 32 | Should Be Uppercase ${name} 33 | 34 | Check Other String Keywords 35 | [Documentation] Testing other string keywords. 36 | ${name} Replace String Nigel Hagrid Nigel Rubeus 37 | Should Be Equal ${name} Rubeus Hagrid 38 | Should Be String ${name} 39 | @{Characters} Split String To Characters ${name} 40 | -------------------------------------------------------------------------------- /src/section_08/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/adrianyorke/robotframework-cookbook/3a36f5f00476791b2068a63b710e9ced51b523dc/src/section_08/.gitkeep -------------------------------------------------------------------------------- /src/section_09/recipe091_working_with_requests_library.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation PROBLEM: 3 | ... You want to send a simple HTTP request using Requests library. 4 | ... DISCUSSION: 5 | ... This recipe demonstrates using keywords from Collections standard library. 6 | ... This recipe also demonstrates installing and using an external library. 7 | ... This recipe has the following external dependencies: 8 | ... $ pip install -U requests 9 | ... $ pip install -U robotframework-requests 10 | Library Collections 11 | Library RequestsLibrary 12 | Test Tags py3.10 py3.11 13 | 14 | *** Variables *** 15 | ${recipe} Recipe 9.1 Working With Requests Library 16 | ${level} Intermediate 17 | ${category} External Library: RequestsLibrary 18 | 19 | *** Test Cases *** 20 | Get Request 21 | Create Session github https://api.github.com 22 | ${response} = GET On Session github /users/adrianyorke 23 | Log ${response.json()} 24 | Should Be Equal As Strings ${response.status_code} 200 25 | Dictionary Should Not Contain Value ${response.json()} The Black Knight 26 | Dictionary Should Contain Value ${response.json()} Adrian Yorke 27 | Dictionary Should Contain Value ${response.json()} Helsinki, Finland 28 | -------------------------------------------------------------------------------- /src/section_09/recipe092_working_with_rest_library.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation PROBLEM: 3 | ... You want to send a simple HTTP request using RESTinstance library. 4 | ... DISCUSSION: 5 | ... This recipe demonstrates installing and using an external library. 6 | ... This recipe has the following external dependencies: 7 | ... $ pip install -U RESTinstance 8 | Library Collections 9 | Library REST https://api.github.com 10 | Test Tags py3.10 py3.11 11 | 12 | *** Variables *** 13 | ${recipe} Recipe 9.2 Working With REST Library 14 | ${level} Intermediate 15 | ${category} External Library: REST 16 | 17 | *** Test Cases *** 18 | Get Request 19 | GET /users/adrianyorke 20 | Output response 21 | Integer response status 200 22 | # Validate the value individual properties 23 | String response body name Adrian Yorke 24 | String response body location Helsinki, Finland 25 | # Save the body in a variable so we can prove that something isn't in it 26 | ${body}= Output response body 27 | Dictionary Should Not Contain Value ${body} The Black Knight 28 | -------------------------------------------------------------------------------- /src/section_09/recipe093_working_with_browser_library.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation PROBLEM: 3 | ... You want to send a simple HTTP request using Browser library. 4 | ... DISCUSSION: 5 | ... Making a request from inside a page context allows use of page 6 | ... cookies and other headers that maybe difficult to gain without 7 | ... using browser. This method also detects some cross site problems that 8 | ... may not occur without a browser. 9 | ... This recipe demonstrates using keywords from Collections standard library. 10 | ... This recipe also demonstrates installing and using an external library. 11 | ... This recipe has the following external dependencies: 12 | ... $ pip install -U robotframework-browser 13 | ... $ rfbrowser init 14 | Library Collections 15 | Library Browser 16 | Test Tags py3.10 py3.11 17 | 18 | *** Variables *** 19 | ${recipe} Recipe 9.3 Working With Browser Library 20 | ${level} Intermediate 21 | ${category} External Library: Browser 22 | 23 | *** Test Cases *** 24 | Get Request 25 | New Page https://www.github.com 26 | &{response} = HTTP https://api.github.com/users/adrianyorke 27 | Should Be Equal ${response}[status] ${200} 28 | Dictionary Should Not Contain Value ${response}[body] The Black Knight 29 | Dictionary Should Contain Value ${response}[body] Adrian Yorke 30 | Dictionary Should Contain Value ${response}[body] Helsinki, Finland 31 | -------------------------------------------------------------------------------- /src/section_10/recipe101_working_with_databases.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation PROBLEM: 3 | ... You want to interact with a relational database using database library. 4 | ... DISCUSSION: 5 | ... Uses SQLite as it is available in all Python and Robot Framework installations. 6 | ... Demonstrates adding tags to test cases which can be used to include/exclude certain types of tests. 7 | ... Also demonstrates installing and using an external library. 8 | ... This recipe has the following external dependencies: 9 | ... $ pip install -U robotframework-databaselibrary 10 | Library OperatingSystem 11 | Library String 12 | Library DatabaseLibrary 13 | Test Tags py3.10 py3.11 14 | 15 | *** Variables *** 16 | ${recipe} Recipe 10.1 Working With Databases 17 | ${level} Advanced 18 | ${category} External Library: DatabaseLibrary 19 | ${DBName} my_db_test_101 20 | 21 | *** Test Cases *** 22 | Remove old DB if exists 23 | [Tags] smoke 24 | ${TEMPDIR} = Replace String ${TEMPDIR} \\ \\\\ 25 | ${Status} ${value} = Run Keyword And Ignore Error File Should Not Exist ${TEMPDIR}/${DBName}.db 26 | Run Keyword If "${Status}" == "FAIL" Run Keyword And Ignore Error Remove File ${TEMPDIR}/${DBName}.db 27 | File Should Not Exist ${TEMPDIR}/${DBName}.db 28 | Comment Sleep 1s 29 | 30 | Connect To Database 31 | [Tags] smoke 32 | ${TEMPDIR} = Replace String ${TEMPDIR} \\ \\\\ 33 | Connect To Database Using Custom Params sqlite3 database="${TEMPDIR}/${DBName}.db", isolation_level=None 34 | 35 | Create User Table 36 | [Tags] smoke 37 | ${output} = Execute SQL String CREATE TABLE user (id integer unique, first_name varchar, last_name varchar); 38 | 39 | Table Must Exist - user 40 | [Tags] smoke 41 | Table Must Exist user 42 | 43 | Insert Data Into Table - user 44 | [Tags] smoke 45 | ${output} = Execute SQL String INSERT INTO user VALUES(1, 'Ada', 'Lovelace'); 46 | Log ${output} 47 | Should Be Equal As Strings ${output} None 48 | ${output} = Execute SQL String INSERT INTO user VALUES(2, 'Charles', 'Babbage'); 49 | Log ${output} 50 | Should Be Equal As Strings ${output} None 51 | 52 | Verify Query - Row Count user Table 53 | [Tags] smoke 54 | Row Count Is Equal To X SELECT * FROM user; 2 55 | -------------------------------------------------------------------------------- /src/section_10/recipe102_hacking_database_view.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation PROBLEM: 3 | ... You want to demonstrate how database views can be broken by deleting a base table 4 | ... that is referenced by the view SELECT statement. 5 | ... DISCUSSION: 6 | ... This recipe demonstrates creating a datase table and view, then breaking the view. 7 | ... We confirm the view is broken by attempting to SELECT data from it. 8 | ... This recipe also demonstrates "Run Keyword And Ignore Error" and 9 | ... "Run Keyword And Expect Error" keywords. 10 | ... This recipe has the following external dependencies: 11 | ... $ pip install -U robotframework-databaselibrary 12 | ... SEE ALSO: 13 | ... In the next recipe, we will create a script that checks all views are still working. 14 | Library OperatingSystem 15 | Library String 16 | Library DatabaseLibrary 17 | Test Tags py3.10 py3.11 18 | 19 | *** Variables *** 20 | ${recipe} Recipe 10.2 Breaking Database View 21 | ${level} Advanced 22 | ${category} External Library: DatabaseLibrary 23 | ${DBName} my_db_test_102 24 | 25 | *** Test Cases *** 26 | Remove old DB if exists 27 | [Tags] smoke 28 | ${TEMPDIR} = Replace String ${TEMPDIR} \\ \\\\ 29 | ${Status} ${value} = Run Keyword And Ignore Error File Should Not Exist ${TEMPDIR}/${DBName}.db 30 | Log ${Status} 31 | Run Keyword If "${Status}" == "FAIL" Run Keyword And Ignore Error Remove File ${TEMPDIR}/${DBName}.db 32 | File Should Not Exist ${TEMPDIR}/${DBName}.db 33 | Comment Sleep 1s 34 | 35 | Connect To Database 36 | [Tags] smoke 37 | ${TEMPDIR} = Replace String ${TEMPDIR} \\ \\\\ 38 | Connect To Database Using Custom Params sqlite3 database="${TEMPDIR}/${DBName}.db", isolation_level=None 39 | 40 | Create User Table 41 | [Tags] smoke 42 | ${output} = Execute SQL String CREATE TABLE user (id integer unique, first_name varchar, last_name varchar); 43 | 44 | Insert Data Into Table - user 45 | [Tags] smoke 46 | ${output} = Execute SQL String INSERT INTO user VALUES(1, 'Tim', 'Berners-Lee'); 47 | Log ${output} 48 | Should Be Equal As Strings ${output} None 49 | ${output} = Execute SQL String INSERT INTO user VALUES(2, 'Eben', 'Upton'); 50 | Log ${output} 51 | Should Be Equal As Strings ${output} None 52 | 53 | Create User View - Filter First Name = Eben 54 | [Tags] smoke 55 | ${sql} = Set Variable CREATE VIEW vw_User AS SELECT id, first_name, last_name FROM user WHERE first_name = 'Eben'; 56 | ${output} = Execute SQL String sql_string=${sql} 57 | 58 | Drop Table - user 59 | ${sql} = Set Variable DROP TABLE user; 60 | ${output} = Execute SQL String sql_string=${sql} 61 | 62 | Verify Query - User View - expected to fail 63 | [Tags] smoke 64 | ${sql} = Catenate SELECT * FROM vw_User LIMIT 1; 65 | Run Keyword And Ignore Error Execute SQL String sql_string=${sql} 66 | ${expectederror} = Set Variable OperationalError: no such table: main.user 67 | Run Keyword And Expect Error ${expectederror} Execute SQL String sql_string=${sql} 68 | -------------------------------------------------------------------------------- /src/section_11/recipe111_working_with_ssh_library.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation PROBLEM: 3 | ... You want to execute commands on a remote machine via SSH and get the output and return code. 4 | ... DISCUSSION: 5 | ... This recipe demonstrates using keywords from SSH external library. This recipe could be used 6 | ... to implement "configuration management as code" and configure multiple remote servers. 7 | ... This recipe also demonstrates another method of extending Robot Framework by defining 8 | ... a user keyword which can be used in this test suite. 9 | ... A common mistake that beginners make is that they string together commands using Execute Command 10 | ... and don't realise that each command is executed separately. This is demonstrated in the first 11 | ... test case as you will notice in the log that pwd does not return the temp directory. 12 | ... This recipe has the following external dependency: 13 | ... $ pip install --upgrade robotframework-sshlibrary 14 | ... SEE ALSO: 15 | ... SSHLibrary documentation: http://robotframework.org/SSHLibrary/SSHLibrary.html 16 | Library SSHLibrary 17 | Suite Setup Open Connection And Log In 18 | Suite Teardown Close All Connections 19 | Force Tags no-ci-testing 20 | 21 | *** Variables *** 22 | ${recipe} Recipe 11.1 Working With SSH Library 23 | ${level} Advanced 24 | ${category} External Library: SSH 25 | ${HOST} YOUR_HOST 26 | ${USERNAME} YOUR_USERNAME 27 | ${PASSWORD} YOUR_PASSWORD 28 | 29 | *** Test Cases *** 30 | Execute Command And Verify Output 31 | [Documentation] Execute Command can be used to run commands on the remote machine. 32 | ... The keyword returns the standard output by default. 33 | ${output} = Execute Command cd ${TEMPDIR} 34 | ${output} = Execute Command pwd 35 | ${output} = Execute Command echo Hello SSHLibrary! 36 | Should Be Equal ${output} Hello SSHLibrary! 37 | 38 | Execute Command And Verify Return Code 39 | [Documentation] Often getting the return code of the command is enough. 40 | ... This behaviour can be adjusted as Execute Command arguments. 41 | ${rc} = Execute Command echo Success guaranteed. return_stdout=False return_rc=True 42 | Should Be Equal ${rc} ${0} 43 | 44 | Executing Commands In An Interactive Session 45 | [Documentation] Execute Command always executes the command in a new shell. 46 | ... This means that changes to the environment are not persisted 47 | ... between subsequent Execute Command keyword calls. 48 | ... Write and Read Until variants can be used to operate in the same shell. 49 | Write cd ${TEMPDIR} 50 | Write echo Hello from temp directory! 51 | ${output} = Read Until directory! 52 | Should End With ${output} Hello from temp directory! 53 | 54 | *** Keywords *** 55 | Open Connection And Log In 56 | Open Connection ${HOST} 57 | Login ${USERNAME} ${PASSWORD} 58 | -------------------------------------------------------------------------------- /src/section_11/recipe112_retrieve_output_file_of_ssh_run_command.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation PROBLEM: 3 | ... You need to execute a command on a remote machine via SSH then get its vary large text output, or some 4 | ... bianary artifact that the remote command creates using file transfer. 5 | ... DISCUSSION: 6 | ... This recipe demonstrates using keywords from SSH external library 7 | ... combined with standard library OperatingSystem. In this recipie we are 8 | ... logging in with ssh public key to demonstrate that option for logins. 9 | ... We are also expanding on 1.11's demonstation of user keywords by creating 10 | ... a user keyword with a variable in its name and chainging keywords together. 11 | ... Also notice in this recipe that we need to specify namespace for our keywords 12 | ... because SSHLibrary and OperatingSystem have some overlapping keyword names. 13 | ... We used WITH NAME when importing the libraries to make the test case and user 14 | ... keyword code less obnoxious. 15 | ... This recipe has the following external dependency: 16 | ... $ pip install --upgrade robot framework-sshlibrary 17 | ... SEE ALSO: 18 | ... SSHLibrary documentation: http://robotframework.org/SSHLibrary/SSHLibrary.html 19 | 20 | Library SSHLibrary WITH NAME SSH 21 | Library OperatingSystem WITH NAME OS 22 | 23 | Suite Setup Open Connection And Log In 24 | Suite Teardown SSH.Close All Connections 25 | Force Tags no-ci-testing 26 | 27 | *** Variables *** 28 | ${recipe} Recipe 11.2 Retrieve Output File Of SSH Run Command 29 | ${level} Advanced 30 | ${category} External Library: SSH 31 | 32 | *** Test Cases *** 33 | Count To 5000 On Remote and Print To Local Console 34 | [Documentation] Run bash script to print line seperated numbers 0-5000 on remote server 35 | ... to a file, then get that file and log to local console 36 | ${count_file} Set Variable /tmp/count_file.txt 37 | ${count_command} Set Variable i=0; while [ $i -le 5000 ]; do echo line $i; i=$(($i+1)); done >/tmp/count_file.txt 38 | ${result} Run Remote ${count_command} And Get ${count_file} Output 39 | ${result_read} OS.Get File ${result} 40 | Log To Console ${result_read} 41 | 42 | *** Keywords *** 43 | Open Connection And Log In 44 | [Documentation] Connect and Log In With SSH Key. You'll want to change the variable values here of course, 45 | ... but if you have ssh enabled on your local machiene and your public key added to ~/.ssh/authorized_keys, 46 | ... you _can_ run this to with no changes and it will work, asuming your environment is a pretty typical setup. 47 | 48 | ${HOST} OS.Run hostname 49 | ${USER} OS.Get Environment Variable USER 50 | ${HOME} OS.Get Environment Variable HOME 51 | SSH.Open Connection ${HOST} 52 | SSH.Login With Public Key ${USER} ${HOME}/.ssh/id_rsa 53 | 54 | 55 | Run Remote ${Command} And Get ${File} Output 56 | [Documentation] This keyword uses a variable keyword name, meaning that it can be called by any name which matches 57 | ... the name defined, but with any string in place of the variables. It is one of the more extravigant 58 | ... feautures of robot and may feel too quirky to some python developers. But depending on style choices 59 | ... for your project, you may choose to use this feature. 60 | ... 61 | ... To the point, this keyword runs the command and outputs to a file on the server, then downloads that file 62 | ... and returns the local file location so you can print to console or do whatever you need to do with 63 | ... the content, for example passing it to another keyword. 64 | 65 | SSH.Execute Command ${Command} 66 | SSH.File Should Exist ${File} 67 | 68 | ${downloaded_file} _Get Remote ${File} 69 | [Return] ${downloaded_file} 70 | 71 | _Get Remote ${File} 72 | [Documentation] Supporting Keyword, gets file from remote server and stores it to a temporary directory. 73 | ... Returns the downloaded file's path 74 | 75 | SSH.Get File ${File} ${TEMPDIR}/${File} 76 | OS.File Should Exist ${TEMPDIR}/${File} msg="Error, file was not downloaded correctly" 77 | [Return] ${TEMPDIR}/${File} 78 | -------------------------------------------------------------------------------- /src/section_12/recipe121_running_tests_in_parallel.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation PROBLEM: 3 | ... You want to reduce the overall test execution time by running all test cases 4 | ... within a test suite in parallel using parallel executor (pabot). 5 | ... DISCUSSION: 6 | ... When you run tests in parallel with pabot it will create a results directory 7 | ... (pabot_results) in the current working directory and a hidden file that 8 | ... contains execution details (.pabotsuitenames). 9 | ... Pabot will split test execution from suite files by default so we use the 10 | ... --testlevelsplit flag to split individual test cases. 11 | ... Test case 2 & 4 are expected to fail. This demonstrates how the failure of 12 | ... a test case does not affect the execution or success of other test cases. 13 | ... This recipe also demonstrates installing and using an external library. 14 | ... A library keyword is not required as you execute the test suite using 15 | ... the pabot shell command like this: 16 | ... $ pabot --testlevelsplit recipe121_running_tests_in_parallel.robot 17 | ... This recipe has the following external dependencies: 18 | ... $ pip install -U robotframework-pabot 19 | Test Tags pabot py3.10 py3.11 20 | 21 | *** Variables *** 22 | ${recipe} Recipe 12.1 Running Tests in Parallel 23 | ${level} Intermediate 24 | ${category} External Library: pabot 25 | ${DELAY} 5 26 | 27 | *** Test Cases *** 28 | Test Case 1 29 | Log Starting Test Case 1 using delay ${DELAY} 30 | Sleep ${DELAY} 31 | 32 | Test Case 2 33 | Log Starting Test Case 2 using delay ${DELAY} 34 | Sleep ${DELAY} 35 | Run Keyword And Ignore Error Should Be Equal foo bar 36 | 37 | Test Case 3 38 | Log Starting Test Case 3 using delay ${DELAY} 39 | Sleep ${DELAY} 40 | 41 | Test Case 4 42 | Log Starting Test Case 4 using delay ${DELAY} 43 | Sleep ${DELAY} 44 | Run Keyword And Ignore Error Should Be Equal foo bar 45 | -------------------------------------------------------------------------------- /src/section_13/recipe131_selenium_setup.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation PROBLEM: 3 | ... You want to setup local environment where to test websites against multiple locally running browsers. 4 | ... DISCUSSION: 5 | ... This recipe demonstrates using keywords from SeleniumLibrary and SeleniumTestability plugin, how to setup 6 | ... your webdrivers and use advanced features of SeleniumTestability. 7 | ... 8 | ... This recipe has the following external dependencies: 9 | ... $ pip install --upgrade robotframework-seleniumlibrary robotframework-seleniumtestability webdrivermanager 10 | ... 11 | ... Running SeleniumLibrary requires working integration with webdriver executable. After running previous 12 | ... `pip` command, you can install webdrivers with: 13 | ... 14 | ... $ webdrivermanager firefox chrome 15 | ... 16 | ... SEE ALSO: 17 | ... SeleniumLibrary documentation: https://robotframework.org/SeleniumLibrary/SeleniumLibrary.html 18 | ... SeleniumTestability keyword documentation: https://rasjani.github.io/robotframework-seleniumtestability/index.html?tag=plugin#Keywords 19 | ... WebDriverManager documentation: https://github.com/rasjani/webdrivermanager 20 | ... 21 | Library SeleniumLibrary plugins=SeleniumTestability;True;1 Minute;True 22 | Library Collections 23 | Test Template Click And Wait 24 | Suite Setup Configure SeleniumTestability 25 | Test Teardown Close All Browsers 26 | Force Tags no-ci-testing 27 | 28 | *** Variables *** 29 | ${recipe} Recipe 13.1 Selenium Setup 30 | ${level} Intermediate 31 | ${category} External Library: SeleniumLibrary 32 | 33 | ${URL} https://the-internet.herokuapp.com/dynamic_loading/1 34 | ${HIDDEN_DIV} xpath://div[@id="finish"] 35 | ${HIDDEN_TEXT} Hello World! 36 | ${START_BUTTON} xpath://div[@id="start"]/button 37 | 38 | *** Test Cases *** 39 | Open Page With Firefox and wait for element to appear Firefox ${URL} 40 | Open Page With Chrome and wait for element to appear Chrome ${URL} 41 | 42 | *** Keywords *** 43 | Click And Wait 44 | [Documentation] 1. Calls Setup Browser-keyword with parameters. 45 | ... 2. Verifies that element with id finish isn't visible or doesnt contain Hello World! 46 | ... 3. Click on button with id start. This trigger that will show another div in 5 seconds with text Hello World! 47 | ... 4. Verifies that element with id finish is t visible and contains Hello World! 48 | ... 49 | ... Note: Because SeleniumTestability was enabled with automatic waiting and injection on line 21, user does not 50 | ... need to explicitly wait for any events. 51 | 52 | [Arguments] ${browser} ${url} 53 | 54 | Setup Browser ${browser} ${url} 55 | Element Text Should Not Be ${HIDDEN_DIV} ${HIDDEN_TEXT} 56 | Click Button ${START_BUTTON} 57 | Element Text Should Be ${HIDDEN_DIV} ${HIDDEN_TEXT} 58 | 59 | Setup Browser 60 | [Arguments] ${browser} ${ur} 61 | [Documentation] 1. calls Open Browser with given url and browser name. 62 | ... 2. Verifies that SeleniumTestability was correctly injected/instrumented in the given URL 63 | 64 | Open Browser ${url} ${browser} 65 | ${testability_status}= Is Testability Installed 66 | Should Be True ${testability_status} 67 | 68 | 69 | Configure SeleniumTestability 70 | [Documentation] 1. Create a dictionary with following values: 71 | ... 1.1 maxTimeout in milliseconds that SeleniumTetability still considers as valid event to wait. 72 | ... 1.2 verbose to 1 indicates that testability.js should log its events to browser console. 73 | ... 2. Sets the created dictionary as configuration for SeleniumTestability 74 | 75 | ${tc}= Create Dictionary maxTimeout=10000 verbose=1 76 | Set Testability Config ${tc} 77 | -------------------------------------------------------------------------------- /src/section_14/recipe141_aws_simple_storage_service.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation PROBLEM: 3 | ... You want to test the existence of a file in an AWS S3 bucket 4 | ... without using lower level Python code or developing a custom library. 5 | ... DISCUSSION: 6 | ... This recipe demonstrates: 7 | ... - using a Suite Teardown to end the test suite cleanly 8 | ... - using keywords from an external library 9 | ... - accessing OS Environment Variables directly using %{} syntax 10 | ... This recipe has the following external dependencies: 11 | ... $ pip install --upgrade robotframework-aws 12 | ... This recipe also requires the following OS environment variables: 13 | ... AWS_ACCESS_KEY_ID 14 | ... AWS_SECRET_ACCESS_KEY 15 | Suite Teardown Delete All Sessions 16 | Library AWSLibrary 17 | Force Tags no-ci-testing 18 | 19 | *** Variables *** 20 | ${recipe} Recipe 14.1 AWS Simple Storage Service 21 | ${level} Intermediate 22 | ${category} External Library: AWSLibrary 23 | ${REGION} us-east-1 24 | ${BUCKET} YOUR_BUCKET_NAME_GOES_HERE 25 | ${KEY} YOUR_FILE_PATH_GOES_HERE 26 | 27 | *** Test Cases *** 28 | Check Key Exists In Bucket 29 | Log Variables 30 | Create Session With Keys ${REGION} %{AWS_ACCESS_KEY_ID} %{AWS_SECRET_ACCESS_KEY} 31 | Key Should Exist ${BUCKET} ${KEY} 32 | -------------------------------------------------------------------------------- /src/section_15/recipe151_working_with_browser_contexts.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation PROBLEM: 3 | ... You want to simulate different geolocations in the same browser instance. 4 | ... DISCUSSION: 5 | ... This recipe demonstrates the usage of contexts with different geolocations. 6 | ... The contexts are all created in the same browser and do not influence each other. 7 | ... SEE ALSO: 8 | ... Beside the geolocation it is also possible to specify more options for each context. 9 | ... For example the timezone, different permissions, Java Script is disabled, 10 | ... This recipe has the following external dependencies: 11 | ... $ pip install -U robotframework-browser 12 | ... $ rfbrowser init 13 | Library Browser 14 | Test Tags py3.10 py3.11 15 | 16 | *** Variables *** 17 | ${recipe} Recipe 15.1 Working With Browser Contexts 18 | ${level} Intermediate 19 | ${category} External Library: Browser 20 | @{permissions} geolocation 21 | 22 | *** Test Cases *** 23 | Context with Geolocation set to Helsinki 24 | New Context geolocation={'latitude': 60.1698, 'longitude': 24.9386} permissions=${permissions} ignoreHTTPSErrors=True 25 | New Page https://www.openstreetmap.org/ 26 | Click span.icon.geolocate 27 | Wait Until Network Is Idle 28 | Take Screenshot 29 | 30 | Context with Geolocation set to Sydney 31 | New Context geolocation={'latitude': -33.8675, 'longitude': 151.207} permissions=${permissions} ignoreHTTPSErrors=True 32 | New Page https://www.openstreetmap.org/ 33 | Click span.icon.geolocate 34 | Wait Until Network Is Idle 35 | Take Screenshot 36 | 37 | Context with no Geolocation Permission 38 | New Context 39 | New Page https://www.openstreetmap.org/ 40 | Click span.icon.geolocate 41 | Wait Until Network Is Idle 42 | Take Screenshot 43 | -------------------------------------------------------------------------------- /src/section_95/recipe951_rf4_native_if_else_elseif.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation PROBLEM: 3 | ... You would like to test the native IF, ELSE and ELSE IF syntax which was 4 | ... introduced in Robot Framework 4. 5 | ... DISCUSSION: 6 | ... Robot Framework 4 introduced native IF, ELSE and ELSE IF syntax. Previously, it 7 | ... was necessary to use the 'Run Keyword If' keyword which made test scripts more 8 | ... difficult to read and understand. 9 | ... Run this recipe and closely examine the log. Please note: you must use 10 | ... Robot Framework 4 to run this recipe. Notice the new column Skip in the 11 | ... Test Statistics table in the log output. Also Pass/Fail/Skip column now includes 12 | ... Skip statistics. 13 | ... Observe the IF, ELSE and ELSE IF native commands. Where a condition has not 14 | ... been met, the command will be greyed out. Otherwise the command will be green 15 | ... to show the path taken by the logic. 16 | ... SEE ALSO: 17 | ... Recipe 3.1 Handling Dates 18 | ... https://github.com/robotframework/robotframework/issues/3074 19 | Library DateTime 20 | Test Tags py3.10 py3.11 21 | 22 | *** Variables *** 23 | ${recipe} Recipe 95.1 Robot Framework 4 Native IF, ELSE, ELSE IF Syntax 24 | ${level} Beginner 25 | ${category} Robot Framework 4 26 | ${answer} 42 27 | 28 | *** Test Cases *** 29 | Check Basic IF 30 | IF ${answer} == 42 31 | Log Answer to the Ultimate Question of Life, the Universe, and Everything. 32 | END 33 | 34 | Check ELSE 35 | ${date} = Get Current Date result_format=datetime 36 | Log Month = ${date.month} 37 | IF ${date.month} < 7 38 | Log First Half of Year 39 | ELSE 40 | Log Second Half of Year 41 | END 42 | 43 | Check ELSE IF 44 | ${date} = Get Current Date result_format=datetime 45 | Log Hour is ${date.hour} 46 | IF ${date.hour} < 12 47 | Log Good morning! 48 | ELSE IF ${date.hour} < 18 49 | Log Good afternoon! 50 | ELSE 51 | Log Good evening! 52 | END 53 | -------------------------------------------------------------------------------- /src/section_99/__init__.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation This file will be loaded before any robot file in directory. It can be used to set global settings 3 | ... like Setup, Teardown or Tags. 4 | Force Tags casestudy 5 | -------------------------------------------------------------------------------- /src/section_99/casestudy_01/ParkCalc/BDD/economy.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation A test suite with tests for economy parking. 3 | Suite Setup Open ParkCalc 4 | Suite Teardown Close Browser 5 | Force Tags BDD 6 | Resource resource.resource 7 | 8 | *** Test Cases *** 9 | First Hour 10 | Given I want to use Economy Parking 11 | When I park @{FOR_ONE_HOUR} 12 | Then the calculated costs should be $ 2.00 13 | 14 | Four Hours 15 | Given I want to use Economy Parking 16 | When I park @{FOR_FOUR_HOURS} 17 | Then the calculated costs should be $ 8.00 18 | 19 | Five Hours 20 | Given I want to use Economy Parking 21 | When I park @{FOR_FIVE_HOURS} 22 | Then the calculated costs should be $ 9.00 23 | 24 | First Day 25 | Given I want to use Economy Parking 26 | When I park @{FOR_ONE_DAY} 27 | Then the calculated costs should be $ 9.00 28 | 29 | Four Days 30 | Given I want to use Economy Parking 31 | When I park @{FOR_FOUR_DAYS} 32 | Then the calculated costs should be $ 36.00 33 | 34 | First Week 35 | Given I want to use Economy Parking 36 | When I park @{FOR_ONE_WEEK} 37 | Then the calculated costs should be $ 54.00 38 | 39 | Three Weeks 40 | Given I want to use Economy Parking 41 | When I park @{FOR_THREE_WEEKS} 42 | Then the calculated costs should be $ 162.00 43 | -------------------------------------------------------------------------------- /src/section_99/casestudy_01/ParkCalc/BDD/long-term-garage.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation A test suite with tests for long-term (Garage) parking. 3 | Suite Setup Open ParkCalc 4 | Suite Teardown Close Browser 5 | Force Tags BDD 6 | Resource resource.resource 7 | 8 | *** Test Cases *** 9 | First Hour 10 | Given I want to use Long-Term Garage Parking 11 | When I park @{FOR_ONE_HOUR} 12 | Then the calculated costs should be $ 2.00 13 | 14 | Three Hours 15 | Given I want to use Long-Term Garage Parking 16 | When I park @{FOR_THREE_HOURS} 17 | Then the calculated costs should be $ 6.00 18 | 19 | Seven Hours 20 | Given I want to use Long-Term Garage Parking 21 | When I park @{FOR_SEVEN_HOURS} 22 | Then the calculated costs should be $ 12.00 23 | 24 | Full Day 25 | Given I want to use Long-Term Garage Parking 26 | When I park @{FOR_ONE_DAY} 27 | Then the calculated costs should be $ 12.00 28 | 29 | Six Days 30 | Given I want to use Long-Term Garage Parking 31 | When I park @{FOR_SIX_DAYS} 32 | Then the calculated costs should be $ 72.00 33 | 34 | Full Week 35 | Given I want to use Long-Term Garage Parking 36 | When I park @{FOR_ONE_WEEK} 37 | Then the calculated costs should be $ 72.00 38 | 39 | Three Weeks 40 | Given I want to use Long-Term Garage Parking 41 | When I park @{FOR_THREE_WEEKS} 42 | Then the calculated costs should be $ 126.00 43 | -------------------------------------------------------------------------------- /src/section_99/casestudy_01/ParkCalc/BDD/long-term-surface.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation A test suite with tests for long-term (Surface) parking. 3 | Suite Setup Open ParkCalc 4 | Suite Teardown Close Browser 5 | Force Tags BDD 6 | Resource resource.resource 7 | 8 | *** Test Cases *** 9 | First Hour 10 | Given I want to use Long-Term Surface Parking 11 | When I park @{FOR_ONE_HOUR} 12 | Then the calculated costs should be $ 2.00 13 | 14 | Three Hours 15 | Given I want to use Long-Term Surface Parking 16 | When I park @{FOR_THREE_HOURS} 17 | Then the calculated costs should be $ 6.00 18 | 19 | Six Hours 20 | Given I want to use Long-Term Surface Parking 21 | When I park @{FOR_SIX_HOURS} 22 | Then the calculated costs should be $ 10.00 23 | 24 | First Day 25 | Given I want to use Long-Term Surface Parking 26 | When I park @{FOR_ONE_DAY} 27 | Then the calculated costs should be $ 10.00 28 | 29 | Five Days 30 | Given I want to use Long-Term Surface Parking 31 | When I park @{FOR_FIVE_DAYS} 32 | Then the calculated costs should be $ 50.00 33 | 34 | Seven Days 35 | Given I want to use Long-Term Surface Parking 36 | When I park @{FOR_SEVEN_DAYS} 37 | Then the calculated costs should be $ 60.00 38 | 39 | Three Weeks 40 | Given I want to use Long-Term Surface Parking 41 | When I park @{FOR_THREE_WEEKS} 42 | Then the calculated costs should be $ 180.00 43 | -------------------------------------------------------------------------------- /src/section_99/casestudy_01/ParkCalc/BDD/resource.resource: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation A resource file containing the ParkCalc app specific keywords and variables for BDD-style tests that create our own domain specific language. Also SeleniumLibrary itself is imported here so that tests only need to import this resource file. 3 | Library SeleniumLibrary 4 | 5 | *** Variables *** 6 | ${BROWSER} firefox 7 | ${DELAY} 0 8 | ${PARKCALC URL} http://robotframework.transformidea.com/app/parkcalc/ # http://adam.goucher.ca/parkcalc/ 9 | ${COST_ITEM} xpath=//tr[td/div[@class='SubHead'] = 'COST']/td/span/font/b 10 | ${PAGE_TITLE} Parking Calculator 11 | @{FOR_ONE_HOUR} 05/04/2010 12:00 AM 05/04/2010 01:00 AM 12 | @{FOR_ONE_AND_A_HALF_HOUR} 05/04/2010 12:00 AM 05/04/2010 01:30 AM 13 | @{FOR_THREE_HOURS} 05/04/2010 12:00 AM 05/04/2010 03:00 AM 14 | @{FOR_FOUR_HOURS} 05/04/2010 12:00 AM 05/04/2010 04:00 AM 15 | @{FOR_FIVE_HOURS} 05/04/2010 12:00 AM 05/04/2010 05:00 AM 16 | @{FOR_SIX_HOURS} 05/04/2010 12:00 AM 05/04/2010 06:00 AM 17 | @{FOR_SEVEN_HOURS} 05/04/2010 12:00 AM 05/04/2010 07:00 AM 18 | @{FOR_TWELVE_AND_A_HALF_HOUR} 05/04/2010 12:00 AM 05/04/2010 12:30 PM 19 | @{FOR_ONE_DAY} 05/04/2010 12:00 AM 05/05/2010 12:00 AM 20 | @{FOR_FOUR_DAYS} 05/04/2010 12:00 AM 05/08/2010 12:00 AM 21 | @{FOR_FIVE_DAYS} 05/04/2010 12:00 AM 05/09/2010 12:00 AM 22 | @{FOR_SIX_DAYS} 05/04/2010 12:00 AM 05/10/2010 12:00 AM 23 | @{FOR_SEVEN_DAYS} 05/04/2010 12:00 AM 05/11/2010 12:00 AM 24 | @{FOR_ONE_WEEK} @{FOR_SEVEN_DAYS} 25 | @{FOR_THREE_WEEKS} 05/04/2010 12:00 AM 05/25/2010 12:00 AM 26 | 27 | *** Keywords *** 28 | Open ParkCalc 29 | Open Browser ${PARKCALC URL} ${BROWSER} 30 | Set Selenium Speed ${DELAY} 31 | Title Should Be ${PAGE_TITLE} 32 | 33 | I want to use 34 | [Arguments] ${lot} 35 | Select From List Lot ${lot} 36 | 37 | I park 38 | [Arguments] ${entryDate} ${entryTime} ${entryAmPm} ${exitDate} ${exitTime} ${exitAmPm} 39 | Input Text EntryTime ${entryTime} 40 | Select Radio Button EntryTimeAMPM ${entryAmPm} 41 | Input Text EntryDate ${entryDate} 42 | Input Text ExitTime ${exitTime} 43 | Select Radio Button ExitTimeAMPM ${exitAmPm} 44 | Input Text ExitDate ${exitDate} 45 | Click Button Submit 46 | 47 | the calculated costs should be 48 | [Arguments] ${cost} 49 | ${actual} = Get Text ${COST_ITEM} 50 | Log Actual costs: ${actual} 51 | Page Should Contain ${cost} 52 | 53 | Select From List 54 | [Arguments] ${arg1} ${arg2} 55 | [Documentation] Wrapper for SeleniumLibrary 4.0 56 | Select From List By Label ${arg1} ${arg2} 57 | -------------------------------------------------------------------------------- /src/section_99/casestudy_01/ParkCalc/BDD/short-term.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation A test suite with functional tests for ParkCalc in a keyword-driven format. 3 | Suite Setup Open ParkCalc 4 | Suite Teardown Close Browser 5 | Force Tags BDD 6 | Resource resource.resource 7 | 8 | *** Test Cases *** 9 | First Hour 10 | I want to use Short-Term Parking 11 | When I park @{FOR_ONE_HOUR} 12 | Then the calculated costs should be $ 2.00 13 | 14 | One And An Additional Half Hour 15 | I want to use Short-Term Parking 16 | When I park @{FOR_ONE_AND_A_HALF_HOUR} 17 | Then the calculated costs should be $ 3.00 18 | 19 | Three Hours 20 | I want to use Short-Term Parking 21 | When I park @{FOR_THREE_HOURS} 22 | Then the calculated costs should be $ 6.00 23 | 24 | Twelve And A Half Hour 25 | I want to use Short-Term Parking 26 | When I park @{FOR_TWELVE_AND_A_HALF_HOUR} 27 | Then the calculated costs should be $ 24.00 28 | -------------------------------------------------------------------------------- /src/section_99/casestudy_01/ParkCalc/BDD/valet.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation A test suite with test cases for valet parking. 3 | Suite Setup Open ParkCalc 4 | Suite Teardown Close Browser 5 | Force Tags BDD 6 | Resource resource.resource 7 | 8 | *** Test Cases *** 9 | Less Than Five Hours 10 | I want to use Valet Parking 11 | When I park @{FOR_ONE_HOUR} 12 | Then the calculated costs should be $ 12.00 13 | 14 | Exactly Five Hours 15 | I want to use Valet Parking 16 | When I park @{FOR_FIVE_HOURS} 17 | Then the calculated costs should be $ 12.00 18 | 19 | More Than Five Hours 20 | I want to use Valet Parking 21 | When I park @{FOR_SIX_HOURS} 22 | Then the calculated costs should be $ 18.00 23 | 24 | Multiple Days 25 | I want to use Valet Parking 26 | When I park @{FOR_FOUR_DAYS} 27 | Then the calculated costs should be $ 72.00 28 | -------------------------------------------------------------------------------- /src/section_99/casestudy_01/ParkCalc/README.txt: -------------------------------------------------------------------------------- 1 | Contents of https://github.com/mgaertne/ParkCalc.git 2 | Found from http://www.shino.de/2010/07/06/parkcalc-automation-templates-for-data-driven-tests/ 3 | Adapted by Hélio Guilherme on August 2016 4 | ----- 5 | Original README file below: 6 | --- 7 | This is a worked example based upon a testing session we ran in EWT19 (http://weekendtesting.com/archives/1131). This repository shows how to refactor and develop keyword based tests with RobotFramework. 8 | 9 | Here is the initial mission we provided: 10 | 11 | Product: ParkCalc (http://adam.goucher.ca/parkcalc/) 12 | 13 | Mission: 14 | The airport parking lot calculation tool raised the attention of some managers. There seem to be too many bugs in the application. Since they want to have it re-written, write a regression test suite based on the old application, which may be executed against the new application as well. Assume that the same interface will be kept. Use RobotFramework for your automated tests. 15 | 16 | As an oracle for your automated, use the rates mentioned on the official website: http://www.grr.org/ParkingRates.php 17 | --- 18 | ----- 19 | Revision of Tests done by Hélio Guilherme on September 2019 20 | The tests were changed to use SeleniumLibrary at version 4.0. 21 | The ParkCalc website changed to alternate location (code provided by Adam Goucher), and includes a fix to run under PHP 7. 22 | New URL is: http://robotframework.transformidea.com/app/parkcalc/ 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/section_99/casestudy_01/ParkCalc/data-driven/functional.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation A test suite with functional tests for ParkCalc in a data-driven format. 3 | Suite Setup Open Park Calc Page 4 | Suite Teardown Close Browser 5 | Force Tags DDT 6 | Resource resource.resource 7 | 8 | *** Variables *** 9 | @{FOR_ONE_HOUR} 05/04/2010 12:00 AM 05/04/2010 01:00 AM # ${entryDate} \ ${entryTime} \ ${entryAmPm} \ ${exitDate} \ ${exitTime} \ ${exitAmPm} 10 | @{FOR_ONE_AND_A_HALF_HOUR} 05/04/2010 12:00 AM 05/04/2010 01:30 AM 11 | @{FOR_THREE_HOURS} 05/04/2010 12:00 AM 05/04/2010 03:00 AM 12 | @{FOR_FOUR_HOURS} 05/04/2010 12:00 AM 05/04/2010 04:00 AM 13 | @{FOR_FIVE_HOURS} 05/04/2010 12:00 AM 05/04/2010 05:00 AM 14 | @{FOR_SIX_HOURS} 05/04/2010 12:00 AM 05/04/2010 06:00 AM 15 | @{FOR_SEVEN_HOURS} 05/04/2010 12:00 AM 05/04/2010 07:00 AM 16 | @{FOR_TWELVE_HOURS} 05/04/2010 12:00 AM 05/04/2010 12:00 PM 17 | @{FOR_TWENTY_THREE_HOURS} 05/04/2010 12:00 AM 05/04/2010 11:00 PM 18 | @{FOR_ONE_DAY} 05/04/2010 12:00 AM 05/05/2010 12:00 AM 19 | @{FOR_TWO_DAYS} 05/04/2010 12:00 AM 05/06/2010 12:00 AM 20 | @{FOR_THREE_DAYS} 05/04/2010 12:00 AM 05/07/2010 12:00 AM 21 | @{FOR_SIX_DAYS} 05/04/2010 12:00 AM 05/10/2010 12:00 AM 22 | @{FOR_ONE_WEEK} 05/04/2010 12:00 AM 05/11/2010 12:00 AM 23 | @{FOR_THREE_WEEKS} 05/04/2010 12:00 AM 05/25/2010 12:00 AM 24 | 25 | *** Test Cases *** 26 | Valet Parking Test 27 | Run Keyword And Continue On Failure Valet Parking @{FOR_ONE_HOUR} $ 12.00 28 | Run Keyword And Continue On Failure Valet Parking @{FOR_FIVE_HOURS} $ 12.00 29 | Run Keyword And Continue On Failure Valet Parking @{FOR_ONE_DAY} $ 18.00 30 | Run Keyword And Continue On Failure Valet Parking @{FOR_THREE_DAYS} $ 54.00 31 | 32 | Short-Term Parking 33 | Run Keyword And Continue On Failure Short-Term Parking @{FOR_ONE_HOUR} $ 2.00 34 | Run Keyword And Continue On Failure Short-Term Parking @{FOR_ONE_AND_A_HALF_HOUR} $ 3.00 35 | Run Keyword And Continue On Failure Short-Term Parking @{FOR_THREE_HOURS} $ 6.00 36 | Run Keyword And Continue On Failure Short-Term Parking @{FOR_TWELVE_HOURS} $ 24.00 37 | Run Keyword And Continue On Failure Short-Term Parking @{FOR_TWENTY_THREE_HOURS} $ 24.00 38 | Run Keyword And Continue On Failure Short-Term Parking @{FOR_TWO_DAYS} $ 48.00 39 | 40 | Long-Term Garage Parking 41 | Run Keyword And Continue On Failure Long-Term Garage Parking @{FOR_ONE_HOUR} $ 2.00 42 | Run Keyword And Continue On Failure Long-Term Garage Parking @{FOR_THREE_HOURS} $ 6.00 43 | Run Keyword And Continue On Failure Long-Term Garage Parking @{FOR_SIX_HOURS} $ 12.00 44 | Run Keyword And Continue On Failure Long-Term Garage Parking @{FOR_SEVEN_HOURS} $ 12.00 45 | Run Keyword And Continue On Failure Long-Term Garage Parking @{FOR_SIX_DAYS} $ 72.00 46 | Run Keyword And Continue On Failure Long-Term Garage Parking @{FOR_ONE_WEEK} $ 72.00 47 | Run Keyword And Continue On Failure Long-Term Garage Parking @{FOR_THREE_WEEKS} $ 216.00 48 | 49 | Long-Term Surface Parking 50 | Run Keyword And Continue On Failure Long-Term Surface Parking @{FOR_ONE_HOUR} $ 2.00 51 | Run Keyword And Continue On Failure Long-Term Surface Parking @{FOR_THREE_HOURS} $ 6.00 52 | Run Keyword And Continue On Failure Long-Term Surface Parking @{FOR_FIVE_HOURS} $ 10.00 53 | Run Keyword And Continue On Failure Long-Term Surface Parking @{FOR_SIX_HOURS} $ 10.00 54 | Run Keyword And Continue On Failure Long-Term Surface Parking @{FOR_SIX_DAYS} $ 60.00 55 | Run Keyword And Continue On Failure Long-Term Surface Parking @{FOR_ONE_WEEK} $ 60.00 56 | Run Keyword And Continue On Failure Long-Term Surface Parking @{FOR_THREE_WEEKS} $ 180.00 57 | 58 | Economy Parking 59 | Run Keyword And Continue On Failure Economy Parking @{FOR_ONE_HOUR} $ 2.00 60 | Run Keyword And Continue On Failure Economy Parking @{FOR_THREE_HOURS} $ 6.00 61 | Run Keyword And Continue On Failure Economy Parking @{FOR_FOUR_HOURS} $ 8.00 62 | Run Keyword And Continue On Failure Economy Parking @{FOR_FIVE_HOURS} $ 9.00 63 | Run Keyword And Continue On Failure Economy Parking @{FOR_SIX_HOURS} $ 9.00 64 | Run Keyword And Continue On Failure Economy Parking @{FOR_SIX_DAYS} $ 54.00 65 | Run Keyword And Continue On Failure Economy Parking @{FOR_ONE_WEEK} $ 54.00 66 | Run Keyword And Continue On Failure Economy Parking @{FOR_THREE_WEEKS} $ 162.00 67 | -------------------------------------------------------------------------------- /src/section_99/casestudy_01/ParkCalc/data-driven/resource.resource: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation A resource file containing the ParkCalc app specific keywords and variables for data-driven tests that create our own domain specific language. Also SeleniumLibrary itself is imported here so that tests only need to import this resource file. 3 | Library SeleniumLibrary 4 | 5 | *** Variables *** 6 | ${BROWSER} firefox 7 | ${DELAY} 0.2 8 | ${PARKCALCPAGE} http://robotframework.transformidea.com/app/parkcalc/ #http://adam.goucher.ca/parkcalc/ 9 | ${COST_ITEM} xpath=//tr[td/div[@class='SubHead'] = 'COST']/td/span/font/b 10 | ${PAGE_TITLE} Parking Calculator 11 | 12 | *** Keywords *** 13 | Open Park Calc Page 14 | Open Browser ${PARKCALCPAGE} ${BROWSER} 15 | Set Selenium Speed ${DELAY} 16 | Title Should Be ${PAGE_TITLE} 17 | 18 | Park Calc 19 | [Arguments] ${parkingLot} ${entryDate} ${entryTime} ${entryAmPm} ${exitDate} ${exitTime} ${exitAmPm} ${expectedPrice} 20 | Title Should Be Parking Calculator 21 | Select From List Lot ${parkingLot} 22 | Input Text EntryTime ${entryTime} 23 | Select Radio Button EntryTimeAMPM ${entryAmPm} 24 | Input Text EntryDate ${entryDate} 25 | Input Text ExitTime ${exitTime} 26 | Select Radio Button ExitTimeAMPM ${exitAmPm} 27 | Input Text ExitDate ${exitDate} 28 | Click Button Submit 29 | Calculated Cost Should Be ${expectedPrice} 30 | 31 | Calculated Cost Should Be 32 | [Arguments] ${expectedCost} 33 | ${actualCost} = Get Text ${COST_ITEM} 34 | Log Actual costs: ${actualCost} 35 | Page Should Contain ${expectedCost} 36 | 37 | Dummy Keyword 38 | [Arguments] ${expectedCost} 39 | Log Not used 40 | 41 | Valet Parking 42 | [Arguments] ${entryDate} ${entryTime} ${entryAmPm} ${exitDate} ${exitTime} ${exitAmPm} ${expectedPrice} 43 | Park Calc Valet Parking ${entryDate} ${entryTime} ${entryAmPm} ${exitDate} ${exitTime} ${exitAmPm} ${expectedPrice} 44 | 45 | Short-Term Parking 46 | [Arguments] ${entryDate} ${entryTime} ${entryAmPm} ${exitDate} ${exitTime} ${exitAmPm} ${expectedPrice} 47 | Park Calc Short-Term Parking ${entryDate} ${entryTime} ${entryAmPm} ${exitDate} ${exitTime} ${exitAmPm} ${expectedPrice} 48 | 49 | Long-Term Garage Parking 50 | [Arguments] ${entryDate} ${entryTime} ${entryAmPm} ${exitDate} ${exitTime} ${exitAmPm} ${expectedPrice} 51 | Park Calc Long-Term Garage Parking ${entryDate} ${entryTime} ${entryAmPm} ${exitDate} ${exitTime} ${exitAmPm} ${expectedPrice} 52 | 53 | Long-Term Surface Parking 54 | [Arguments] ${entryDate} ${entryTime} ${entryAmPm} ${exitDate} ${exitTime} ${exitAmPm} ${expectedPrice} 55 | Park Calc Long-Term Surface Parking ${entryDate} ${entryTime} ${entryAmPm} ${exitDate} ${exitTime} ${exitAmPm} ${expectedPrice} 56 | 57 | Economy Parking 58 | [Arguments] ${entryDate} ${entryTime} ${entryAmPm} ${exitDate} ${exitTime} ${exitAmPm} ${expectedPrice} 59 | Park Calc Economy Parking ${entryDate} ${entryTime} ${entryAmPm} ${exitDate} ${exitTime} ${exitAmPm} ${expectedPrice} 60 | 61 | Select From List 62 | [Arguments] ${arg1} ${arg2} 63 | [Documentation] Wrapper for SeleniumLibrary 4.0 64 | Select From List By Label ${arg1} ${arg2} 65 | -------------------------------------------------------------------------------- /src/section_99/casestudy_01/ParkCalc/keyword-driven/economy.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation A test suite with tests for economy parking. 3 | Suite Setup Open ParkCalc 4 | Suite Teardown Close Browser 5 | Test Setup Input Parking Lot Economy Parking 6 | Force Tags KDT 7 | Resource resource.resource 8 | 9 | *** Test Cases *** 10 | First Hour 11 | Input Entry Date 05/04/2010 12:00 AM 12 | Input Leaving Date 05/04/2010 12:59 AM 13 | Calculated Cost Should Be $ 2.00 14 | 15 | Four Hours 16 | Input Entry Date 05/04/2010 12:00 AM 17 | Input Leaving Date 05/04/2010 04:00 AM 18 | Calculated Cost Should Be $ 8.00 19 | 20 | Five Hours 21 | Input Entry Date 05/04/2010 12:00 AM 22 | Input Leaving Date 05/04/2010 05:00 AM 23 | Calculated Cost Should Be $ 9.00 24 | 25 | First Day 26 | Input Entry Date 05/04/2010 12:00 AM 27 | Input Leaving Date 05/05/2010 12:00 AM 28 | Calculated Cost Should Be $ 9.00 29 | 30 | Four Days 31 | Input Entry Date 05/04/2010 12:00 AM 32 | Input Leaving Date 05/08/2010 12:00 AM 33 | Calculated Cost Should Be $ 36.00 34 | 35 | First Week 36 | Input Entry Date 05/04/2010 12:00 AM 37 | Input Leaving Date 05/11/2010 12:00 AM 38 | Calculated Cost Should Be $ 54.00 39 | 40 | Three Weeks 41 | Input Entry Date 05/04/2010 12:00 AM 42 | Input Leaving Date 05/25/2010 12:00 AM 43 | Calculated Cost Should Be $ 162.00 44 | -------------------------------------------------------------------------------- /src/section_99/casestudy_01/ParkCalc/keyword-driven/long-term-garage.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation A test suite with tests for long-term (Garage) parking. 3 | Suite Setup Open ParkCalc 4 | Suite Teardown Close Browser 5 | Test Setup Input Parking Lot Long-Term Garage Parking 6 | Force Tags KDT 7 | Resource resource.resource 8 | 9 | *** Test Cases *** 10 | First Hour 11 | Input Entry Date 05/04/2010 12:00 AM 12 | Input Leaving Date 05/04/2010 12:59 AM 13 | Calculated Cost Should Be $ 2.00 14 | 15 | Three Hours 16 | Input Entry Date 05/04/2010 12:00 AM 17 | Input Leaving Date 05/04/2010 03:00 AM 18 | Calculated Cost Should Be $ 6.00 19 | 20 | Seven Hours 21 | Input Entry Date 05/04/2010 12:00 AM 22 | Input Leaving Date 05/04/2010 07:00 AM 23 | Calculated Cost Should Be $ 12.00 24 | 25 | Full Day 26 | Input Entry Date 05/04/2010 12:00 AM 27 | Input Leaving Date 05/05/2010 12:00 AM 28 | Calculated Cost Should Be $ 12.00 29 | 30 | Six Days 31 | Input Entry Date 05/04/2010 12:00 AM 32 | Input Leaving Date 05/11/2010 12:00 AM 33 | Calculated Cost Should Be $ 72.00 34 | 35 | Full Week 36 | Input Entry Date 05/04/2010 12:00 AM 37 | Input Leaving Date 05/12/2010 12:00 AM 38 | Calculated Cost Should Be $ 72.00 39 | 40 | Three Weeks 41 | Input Entry Date 05/04/2010 12:00 AM 42 | Input Leaving Date 05/25/2010 12:00 AM 43 | Calculated Cost Should Be $ 126.00 44 | -------------------------------------------------------------------------------- /src/section_99/casestudy_01/ParkCalc/keyword-driven/long-term-surface.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation A test suite with tests for long-term (Surface) parking. 3 | Suite Setup Open ParkCalc 4 | Suite Teardown Close Browser 5 | Test Setup Input Parking Lot Long-Term Surface Parking 6 | Force Tags KDT 7 | Resource resource.resource 8 | 9 | *** Test Cases *** 10 | First Hour 11 | Input Entry Date 05/04/2010 12:00 AM 12 | Input Leaving Date 05/04/2010 12:59 AM 13 | Calculated Cost Should Be $ 2.00 14 | 15 | Three Hours 16 | Input Entry Date 05/04/2010 12:00 AM 17 | Input Leaving Date 05/04/2010 03:00 AM 18 | Calculated Cost Should Be $ 6.00 19 | 20 | Six Hours 21 | Input Entry Date 05/04/2010 12:00 AM 22 | Input Leaving Date 05/04/2010 05:59 AM 23 | Calculated Cost Should Be $ 10.00 24 | 25 | First Day 26 | Input Entry Date 05/04/2010 12:00 AM 27 | Input Leaving Date 05/05/2010 12:00 AM 28 | Calculated Cost Should Be $ 10.00 29 | 30 | Five Days 31 | Input Entry Date 05/04/2010 12:00 AM 32 | Input Leaving Date 05/09/2010 12:00 AM 33 | Calculated Cost Should Be $ 50.00 34 | 35 | Seven Days 36 | Input Entry Date 05/04/2010 12:00 AM 37 | Input Leaving Date 05/11/2010 12:00 AM 38 | Calculated Cost Should Be $ 60.00 39 | 40 | Three Weeks 41 | Input Entry Date 05/04/2010 12:00 AM 42 | Input Leaving Date 05/25/2010 12:00 AM 43 | Calculated Cost Should Be $ 180.00 44 | -------------------------------------------------------------------------------- /src/section_99/casestudy_01/ParkCalc/keyword-driven/resource.resource: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation A resource file containing the ParkCalc app specific keywords and variables for keyword-driven tests that create our own domain specific language. Also SeleniumLibrary itself is imported here so that tests only need to import this resource file. 3 | Library SeleniumLibrary 4 | 5 | *** Variables *** 6 | ${BROWSER} firefox 7 | ${DELAY} 0 8 | ${PARKCALC URL} http://robotframework.transformidea.com/app/parkcalc/ # http://adam.goucher.ca/parkcalc/ 9 | ${COST_ITEM} xpath=//tr[td/div[@class='SubHead'] = 'COST']/td/span/font/b 10 | ${PAGE_TITLE} Parking Calculator 11 | 12 | *** Keywords *** 13 | Open ParkCalc 14 | Open Browser ${PARKCALC URL} ${BROWSER} 15 | Set Selenium Speed ${DELAY} 16 | Title Should Be ${PAGE_TITLE} 17 | 18 | Input Parking Lot 19 | [Arguments] ${lot} 20 | Select From List Lot ${lot} 21 | 22 | Input Entry Date 23 | [Arguments] ${date} ${time} ${ampm} 24 | Input Text EntryDate ${date} 25 | Input Text EntryTime ${time} 26 | Select Radio Button EntryTimeAMPM ${ampm} 27 | 28 | Input Leaving Date 29 | [Arguments] ${date} ${time} ${ampm} 30 | Input Text ExitDate ${date} 31 | Input Text ExitTime ${time} 32 | Select Radio Button ExitTimeAMPM ${ampm} 33 | 34 | Calculated Cost Should Be 35 | [Arguments] ${cost} 36 | Click Button Submit 37 | ${actual} = Get Text ${COST_ITEM} 38 | Log Actual costs: ${actual} 39 | Page Should Contain ${cost} 40 | 41 | Select From List 42 | [Arguments] ${arg1} ${arg2} 43 | [Documentation] Wrapper for SeleniumLibrary 4.0 44 | Select From List By Label ${arg1} ${arg2} 45 | -------------------------------------------------------------------------------- /src/section_99/casestudy_01/ParkCalc/keyword-driven/short-term.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation A test suite with functional tests for ParkCalc in a keyword-driven format. 3 | Suite Setup Open ParkCalc 4 | Suite Teardown Close Browser 5 | Test Setup Input Parking Lot Short-Term Parking 6 | Force Tags KDT 7 | Resource resource.resource 8 | 9 | *** Test Cases *** 10 | First Hour 11 | Input Entry Date 05/04/2010 12:00 AM 12 | Input Leaving Date 05/04/2010 12:59 AM 13 | Calculated Cost Should Be $ 2.00 14 | 15 | One And An Additional Half Hour 16 | Input Entry Date 05/04/2010 12:00 AM 17 | Input Leaving Date 05/04/2010 01:29 AM 18 | Calculated Cost Should Be $ 3.00 19 | 20 | Three Hours 21 | Input Entry Date 05/04/2010 12:00 AM 22 | Input Leaving Date 05/04/2010 03:00 AM 23 | Calculated Cost Should Be $ 6.00 24 | 25 | Twelve And A Half Hour 26 | Input Entry Date 05/04/2010 12:00 AM 27 | Input Leaving Date 05/04/2010 12:29 PM 28 | Calculated Cost Should Be $ 24.00 29 | -------------------------------------------------------------------------------- /src/section_99/casestudy_01/ParkCalc/keyword-driven/valet.robot: -------------------------------------------------------------------------------- 1 | *** Settings *** 2 | Documentation A test suite with test cases for valet parking. 3 | Suite Setup Open ParkCalc 4 | Suite Teardown Close Browser 5 | Test Setup Input Parking Lot Valet Parking 6 | Force Tags KDT 7 | Resource resource.resource 8 | 9 | *** Test Cases *** 10 | Less Than Five Hours 11 | Input Entry Date 05/04/2010 12:00 AM 12 | Input Leaving Date 05/04/2010 01:00 AM 13 | Calculated Cost Should Be $ 12.00 14 | 15 | Exactly Five Hours 16 | Input Entry Date 05/04/2010 12:34 AM 17 | Input Leaving Date 05/04/2010 05:34 AM 18 | Calculated Cost Should Be $ 12.00 19 | 20 | More Than Five Hours 21 | Input Entry Date 05/04/2010 12:00 AM 22 | Input Leaving Date 05/04/2010 12:00 PM 23 | Calculated Cost Should Be $ 18.00 24 | 25 | Multiple Days 26 | Input Entry Date 05/04/2010 12:00 AM 27 | Input Leaving Date 05/08/2010 12:00 AM 28 | Calculated Cost Should Be $ 72.00 29 | -------------------------------------------------------------------------------- /src/section_99/casestudy_01/README.md: -------------------------------------------------------------------------------- 1 | # Case Study: Regression Testing Gerald Ford International Airport (GFIA) Parking Lot Calculation Tool 2 | 3 | ## 1. Introduction 4 | Special thanks to Hélio Guilherme for contributing this case study material. 5 | 6 | This is a worked example based upon a testing session we ran in EWT19. This repository shows how to 7 | refactor and develop keyword-based tests with Robot Framework. 8 | 9 | > Note: It is expected that some of test suites will fail. As an exercise, you should investigate 10 | > the failing tests and try to determine why they are failing. 11 | 12 | The resource files in this project all default to firefox browser. If you prefer to use Chrome then edit the variables section and [download the relevant chromedriver](https://chromedriver.chromium.org/downloads): 13 | ``` 14 | *** Variables *** 15 | ${BROWSER} chrome 16 | ``` 17 | 18 | ## 2. Mission Background 19 | Here is the initial mission we provided: 20 | 21 | ### Product / System Under Test (SUT) 22 | * [Parking Lot Calculation Tool (ParkCalc)](http://robotframework.transformidea.com/app/parkcalc/) 23 | 24 | ### Mission 25 | The airport parking lot calculation tool raised the attention of some managers. 26 | There seem to be too many bugs in the application. Since they want to have it re-written, 27 | write a regression test suite based on the old application, which may be executed against 28 | the new application as well. Assume that the same interface will be kept. Use Robot Framework 29 | for your automated tests. 30 | 31 | ### Parking Rates 32 | As an oracle for your automated, use the rates mentioned on the [official 33 | website](https://www.grr.org/parking-rates) 34 | 35 | ## 3. Sample solutions for different testing approaches: 36 | * [Behavior-Driven Development (BDD)](ParkCalc/BDD) (Given-When-Then format) 37 | * [Data Driven](ParkCalc/data-driven) 38 | * [Keyword Driven](ParkCalc/keyword-driven) 39 | 40 | ## 4. Additional Notes: 41 | * Revision of Tests done by Hélio Guilherme on September 2019 42 | * The tests were changed to use SeleniumLibrary at version 4.0. 43 | * The ParkCalc website changed to alternate location (code provided by Adam Goucher), and includes a fix to run under PHP 7. 44 | * New URL is: http://robotframework.transformidea.com/app/parkcalc/ 45 | -------------------------------------------------------------------------------- /src/section_99/casestudy_02/README.md: -------------------------------------------------------------------------------- 1 | # Case Study: Transcoding existing video library (mixed format) to a single, contemporary format suitable for all play back devices, e.g. mp4 or mkv 2 | 3 | ## 1. Introduction 4 | This is a common home project. You wish to transcode an entire video library typically comprising mixed formats to use better compression and a modern cross-platform format but do not have the time or energy to do this manually. No problem! Let's put your server, desktop or Raspberry Pi to good use and transcode your entire library over several days, weeks or perhaps months if your collection is vast. 5 | 6 | ## 2. Background 7 | It is assumed that you already have many files in several formats. We will be using [ffmpeg](https://ffmpeg.org/) to do the hard work and robot framework to coordinate the activity. 8 | 9 | For this project, I have used the humble Raspberry Pi. It certainly wasn't chosen for speed. We are looking for a low-energy solution that simply runs in the background and over time converts your entire library. 10 | 11 | ## 3. Preparation 12 | ### 3.1 Check versions of Python, pip and robot 13 | > `$ python3 --version`
14 | > `$ pip3 --version`
15 | > `$ robot --version`
16 | ### 3.2 Installation of ffmpeg (Debian) 17 | > `$ sudo apt update`
18 | > `$ sudo apt install ffmpeg`
19 | 20 | >Check installation succeeded and which encoders/decoders are available:
21 | > `$ ffmpeg -version`
22 | > `$ ffmpeg -encoders`
23 | > `$ ffmpeg -decoders`
-------------------------------------------------------------------------------- /tests/requirements-3.10.txt: -------------------------------------------------------------------------------- 1 | robotframework-robocop 2 | requests 3 | robotframework-requests 4 | RESTinstance 5 | robotframework-databaselibrary 6 | robotframework-sshlibrary 7 | robotframework-pabot 8 | robotframework-seleniumlibrary 9 | robotframework-seleniumtestability 10 | webdrivermanager 11 | robotframework-aws 12 | robotframework-browser -------------------------------------------------------------------------------- /tests/requirements-3.11.txt: -------------------------------------------------------------------------------- 1 | robotframework-robocop 2 | requests 3 | robotframework-requests 4 | RESTinstance 5 | robotframework-databaselibrary 6 | robotframework-sshlibrary 7 | robotframework-pabot 8 | robotframework-seleniumlibrary 9 | robotframework-seleniumtestability 10 | webdrivermanager 11 | robotframework-aws 12 | robotframework-browser -------------------------------------------------------------------------------- /tests/requirements-3.6.txt: -------------------------------------------------------------------------------- 1 | robotframework-robocop 2 | requests 3 | robotframework-requests 4 | RESTinstance 5 | robotframework-databaselibrary 6 | robotframework-sshlibrary 7 | robotframework-pabot 8 | robotframework-seleniumlibrary 9 | robotframework-seleniumtestability 10 | webdrivermanager 11 | robotframework-aws -------------------------------------------------------------------------------- /tests/requirements-3.7.txt: -------------------------------------------------------------------------------- 1 | robotframework-robocop 2 | requests 3 | robotframework-requests 4 | RESTinstance 5 | robotframework-databaselibrary 6 | robotframework-sshlibrary 7 | robotframework-pabot 8 | robotframework-seleniumlibrary 9 | robotframework-seleniumtestability 10 | webdrivermanager 11 | robotframework-aws 12 | robotframework-browser -------------------------------------------------------------------------------- /tests/requirements-3.8.txt: -------------------------------------------------------------------------------- 1 | robotframework-robocop 2 | requests 3 | robotframework-requests 4 | RESTinstance 5 | robotframework-databaselibrary 6 | robotframework-sshlibrary 7 | robotframework-pabot 8 | robotframework-seleniumlibrary 9 | robotframework-seleniumtestability 10 | webdrivermanager 11 | robotframework-aws 12 | robotframework-browser -------------------------------------------------------------------------------- /tests/requirements-3.9.txt: -------------------------------------------------------------------------------- 1 | robotframework-robocop 2 | requests 3 | robotframework-requests 4 | RESTinstance 5 | robotframework-databaselibrary 6 | robotframework-sshlibrary 7 | robotframework-pabot 8 | robotframework-seleniumlibrary 9 | robotframework-seleniumtestability 10 | webdrivermanager 11 | robotframework-aws 12 | robotframework-browser -------------------------------------------------------------------------------- /tests/robocop_rules.py: -------------------------------------------------------------------------------- 1 | from robot.parsing.model.blocks import SettingSection, VariableSection, TestCaseSection 2 | from robot.parsing.model.statements import Documentation, Variable 3 | from robocop.checkers import VisitorChecker 4 | from robocop.rules import RuleSeverity 5 | 6 | 7 | class RecipeChecker(VisitorChecker): 8 | rules = { 9 | "5501": ( 10 | "missing-mandatory-section", 11 | "Missing mandatory '%s' section", 12 | RuleSeverity.ERROR, 13 | ), 14 | "5502": ( 15 | "missing-documentation-in-settings", 16 | "Missing mandatory Documentation setting in *** Settings ***", 17 | RuleSeverity.ERROR, 18 | ), 19 | "5503": ( 20 | "missing-mandatory-field-in-doc", 21 | "Missing mandatory '%s' field in documentation", 22 | RuleSeverity.ERROR, 23 | ), 24 | "5504": ( 25 | "missing-mandatory-variable", 26 | "Missing mandatory '%s' variable in *** Variables *** section", 27 | RuleSeverity.ERROR, 28 | ), 29 | } 30 | 31 | def __init__(self, *args): 32 | self.mandatory_sections = { 33 | "*** Settings ***": SettingSection, 34 | "*** Variables ***": VariableSection, 35 | "*** Test Cases ***": TestCaseSection, 36 | } 37 | self.mandatory_variables = {"${recipe}", "${level}", "${category}"} 38 | self.mandatory_doc_fields = {"PROBLEM:", "DISCUSSION:"} 39 | super().__init__(*args) 40 | 41 | def visit_File(self, node): # noqa 42 | for section_name, section_type in self.mandatory_sections.items(): 43 | for section in node.sections: 44 | if isinstance(section, section_type): 45 | break 46 | else: 47 | self.report( 48 | "missing-mandatory-section", section_name, node=node, lineno=0 49 | ) 50 | super().visit_File(node) 51 | 52 | def visit_SettingSection(self, node): # noqa 53 | for statement in node.body: 54 | if isinstance(statement, Documentation): 55 | self.check_mandatory_fields_in_doc(statement) 56 | break 57 | else: 58 | self.report("missing-documentation-in-settings", node=node) 59 | 60 | def visit_VariableSection(self, node): # noqa 61 | var_names = set() 62 | for child in node.body: 63 | if not isinstance(child, Variable): 64 | continue 65 | var_names.add(child.name.lower()) 66 | for var in self.mandatory_variables: 67 | if var not in var_names: 68 | self.report("missing-mandatory-variable", var, node=node) 69 | 70 | def check_mandatory_fields_in_doc(self, node): 71 | for field in self.mandatory_doc_fields: 72 | if field not in node.value: 73 | self.report("missing-mandatory-field-in-doc", field, node=node) 74 | --------------------------------------------------------------------------------