├── .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 | [](#contributors-)
5 |
6 | [](https://github.com/adrianyorke/robotframework-cookbook/actions)
7 | [](https://opensource.org/licenses/MIT)
8 | [](https://github.com/psf/black)
9 | [](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 |
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 |
--------------------------------------------------------------------------------