Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,4 @@ results
.vscode
.devcontainer
.venv
Syllabus.pdf
9 changes: 9 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
repos:
- repo: local
hooks:
- id: gen-numbering
name: Ensure numbering, TOC, and links are in sync
entry: python tools/gen_numbering.py
language: system
pass_filenames: false
always_run: true
40 changes: 40 additions & 0 deletions CONTRIBUTION.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
# Contributing

Thanks for helping us improve the RFCP syllabus! The notes below explain how to bootstrap the tooling, run Docusaurus locally, and keep the docs consistent.

## 1. Install prerequisites
- Node.js 20+ (needed for Docusaurus and Playwright)
- Python 3.11+ (the repo bootstrap script creates a virtual environment for you)
- npm (ships with Node)

## 2. Project setup
1. From the repository root, bootstrap both the Python and JavaScript toolchains:
```bash
python bootstrap.py
```
The script upgrades `pip`, installs `pre-commit`, and asks whether you want to pull in the optional PDF toolchain (Robot Framework + Browser batteries from `requirements.txt`, plus Chromium via `rfbrowser install chromium`). Answer "y" only if you plan to regenerate the PDF. Regardless of that choice, the script installs the pre-commit hook and then runs `npm install` inside `website/` so Docusaurus has its dependencies.
2. Start Docusaurus in development mode while you edit:
```bash
cd website # if not already there
npm run start
```

## 3. Quality checks before committing
- `pre-commit` automatically runs `python tools/gen_numbering.py` on every commit. If headings, learning-objective numbering, or internal links change the hook updates the files, prints a diff, and blocks the commit until you stage the fixes.
- All fenced code blocks must stay within 100 characters per line. Run `npm run build` in the `website/` directory to check code block line lengths (or let CI run it).
- Docusaurus validates internal links during builds. Run `npm run build` before submitting a PR to catch broken anchors or missing pages early.

## 4. Generating the syllabus PDF
To rebuild the syllabus PDF from the Robot Framework assets, run the Robot Framework suite from the repo root:

1. Activate the created virtual environment so local commands use the same interpreters as the hooks:
- macOS/Linux: `source .venv/bin/activate`
- Windows (PowerShell): `.venv\Scripts\Activate.ps1`

2. Run the suite to generate the PDF:
```bash
robot -d results tools/gen_pdf.robot
```
The PDF and execution logs land inside `results/`.

Following the steps above keeps your local environment consistent with CI and ensures contributions land cleanly. Happy writing!
272 changes: 136 additions & 136 deletions LOs.csv

Large diffs are not rendered by default.

14 changes: 7 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -46,16 +46,16 @@
- LO-2.1.1 (K1) Recall the conditions and requirements for a file to be considered a Suite file
- [`2.1.2 Sections and Their Artifacts`](website/docs/chapter-02/01_suitefile.md#212-sections-and-their-artifacts)
- LO-2.1.2 (K1) Recall the available sections in a suite file and their purpose.
- [`2.1.2.1 Introduction in `*** Settings ***` Section`](website/docs/chapter-02/01_suitefile.md#2121-introduction-to--settings--section)
- [`2.1.2.1 Introduction to `*** Settings ***` Section`](website/docs/chapter-02/01_suitefile.md#2121-introduction-to--settings--section)
- LO-2.1.2.1-1 (K1) Recall the available settings in a suite file.
- LO-2.1.2.1-2 (K2) Understand the concepts of suite settings and how to define them.
- [`2.1.2.2 Introduction in `*** Variables ***` Section`](website/docs/chapter-02/01_suitefile.md#2122-introduction-to--variables--section)
- [`2.1.2.2 Introduction to `*** Variables ***` Section`](website/docs/chapter-02/01_suitefile.md#2122-introduction-to--variables--section)
- LO-2.1.2.2 (K1) Recall the purpose of the `*** Variables ***` section.
- [`2.1.2.3 Introduction in `*** Test Cases ***` or `*** Tasks ***` Section`](website/docs/chapter-02/01_suitefile.md#2123-introduction-to--test-cases--or--tasks--section)
- [`2.1.2.3 Introduction to `*** Test Cases ***` or `*** Tasks ***` Section`](website/docs/chapter-02/01_suitefile.md#2123-introduction-to--test-cases--or--tasks--section)
- LO-2.1.2.3 (K2) Understand the purpose of the `*** Test Cases ***` or `*** Tasks ***` section.
- [`2.1.2.4 Introduction in `*** Keywords ***` Section`](website/docs/chapter-02/01_suitefile.md#2124-introduction-to--keywords--section)
- [`2.1.2.4 Introduction to `*** Keywords ***` Section`](website/docs/chapter-02/01_suitefile.md#2124-introduction-to--keywords--section)
- LO-2.1.2.4 (K2) Understand the purpose and limitations of the `*** Keywords ***` section.
- [`2.1.2.5 Introduction in `*** Comments ***` Section`](website/docs/chapter-02/01_suitefile.md#2125-introduction-to--comments--section)
- [`2.1.2.5 Introduction to `*** Comments ***` Section`](website/docs/chapter-02/01_suitefile.md#2125-introduction-to--comments--section)
- [`2.2 Basic Suite File Syntax`](website/docs/chapter-02/02_suitefile_syntax.md)
- LO-2.2 (K2) Understand the basic syntax of test cases and tasks.
- [`2.2.1 Separation and Indentation`](website/docs/chapter-02/02_suitefile_syntax.md#221-separation-and-indentation)
Expand Down Expand Up @@ -222,7 +222,7 @@
- [`4.2.3 Keyword Teardown`](website/docs/chapter-04/02_teardowns.md#423-keyword-teardown)
- LO-4.2.3 (K1) Recall key characteristics, benefits, and syntax of Keyword Teardown
- [`4.3 Initialization Files`](website/docs/chapter-04/03_init_files.md)
- LO-4.3 (K1) Recall how to define an Initialization Files and its purpose
- LO-4.3 (K1) Recall how to define Initialization Files and its purpose
- [`4.3.1 Purpose of Initialization Files`](website/docs/chapter-04/03_init_files.md#431-purpose-of-initialization-files)
- [`4.3.2 Suite Setup and Suite Teardown of Initialization Files`](website/docs/chapter-04/03_init_files.md#432-suite-setup-and-suite-teardown-of-initialization-files)
- LO-4.3.2 (K2) Understand the execution order of Suite Setup and Suite Teardown in Initialization Files and their sub-suites and tests|tasks
Expand Down Expand Up @@ -282,7 +282,7 @@
- [`5.2.1 IF Statements`](website/docs/chapter-05/02_control_structures.md#521-if-statements)
- LO-5.2.1 (K2) Understand the purpose and basic concept of IF-Statements
- [`5.2.1.1 Basic IF Syntax`](website/docs/chapter-05/02_control_structures.md#5211-basic-if-syntax)
- [`5.2.2 IF/ELSE IF/ELSE Structure`](website/docs/chapter-05/02_control_structures.md#522-ifelse-ifelse-structure)
- [`5.2.2 IF/ELSE Structure`](website/docs/chapter-05/02_control_structures.md#522-ifelse-structure)
- [`5.2.3 Inline IF Statement`](website/docs/chapter-05/02_control_structures.md#523-inline-if-statement)
- [`5.2.4 FOR Loops`](website/docs/chapter-05/02_control_structures.md#524-for-loops)
- LO-5.2.4 (K2) Understand the purpose and basic concept of FOR Loops
Expand Down
Binary file modified Syllabus.pdf
Binary file not shown.
86 changes: 86 additions & 0 deletions bootstrap.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
import platform
import subprocess
from pathlib import Path
from venv import EnvBuilder


class Colors:
"""ANSI color codes"""

BLACK = "\033[0;30m"
RED = "\033[0;31m"
GREEN = "\033[0;32m"
BROWN = "\033[0;33m"
BLUE = "\033[0;34m"
PURPLE = "\033[0;35m"
CYAN = "\033[0;36m"
LIGHT_GRAY = "\033[0;37m"
DARK_GRAY = "\033[1;30m"
LIGHT_RED = "\033[1;31m"
LIGHT_GREEN = "\033[1;32m"
YELLOW = "\033[1;33m"
LIGHT_BLUE = "\033[1;34m"
LIGHT_PURPLE = "\033[1;35m"
LIGHT_CYAN = "\033[1;36m"
LIGHT_WHITE = "\033[1;37m"
BOLD = "\033[1m"
FAINT = "\033[2m"
ITALIC = "\033[3m"
UNDERLINE = "\033[4m"
BLINK = "\033[5m"
NEGATIVE = "\033[7m"
CROSSED = "\033[9m"
END = "\033[0m"
# cancel SGR codes if we don't write to a terminal
if not __import__("sys").stdout.isatty():
for attr in dir():
if not attr.startswith("_"):
if isinstance(getattr(__class__, attr), str):
setattr(__class__, attr, "")
elif __import__("platform").system() == "Windows":
kernel32 = __import__("ctypes").windll.kernel32
kernel32.SetConsoleMode(kernel32.GetStdHandle(-11), 7)
del kernel32


venv_dir = Path() / ".venv"
requirements_file = Path("requirements.txt")
website_dir = Path("website")
if not platform.platform().startswith("Windows"):
venv_bin = venv_dir / "bin"
venv_python = venv_bin / "python"
venv_pre_commit = venv_bin / "pre-commit"
else:
venv_bin = venv_dir / "Scripts"
venv_python = venv_bin / "python.exe"
venv_pre_commit = venv_bin / "pre-commit.exe"

if not venv_dir.exists():
print(f"Creating virtualenv in {venv_dir}")
EnvBuilder(with_pip=True).create(venv_dir)

subprocess.run([venv_python, "-m", "pip", "install", "-U", "pip"], check=True)
subprocess.run([venv_python, "-m", "pip", "install", "-U", "pre-commit"], check=True)
install_pdf_tooling = False
if requirements_file.exists():
answer = input(f"{Colors.GREEN}Install Robot Framework + browser batteries for PDF generation?{Colors.END} {Colors.YELLOW}[y/N]: {Colors.END}").strip().lower()
install_pdf_tooling = answer in {"y", "yes"}
if install_pdf_tooling:
subprocess.run([venv_python, "-m", "pip", "install", "-r", str(requirements_file)], check=True)
subprocess.run([venv_python, "-m", "Browser.entry", "install", "chromium", "--with-deps"], check=True)

subprocess.run([venv_pre_commit, "install"], check=True)

if website_dir.exists():
npm_cmd = ["npm", "install"]
print(f"Running {' '.join(npm_cmd)} in {website_dir}")
subprocess.run(npm_cmd, cwd=website_dir, check=True)

activate_script = (
"source .venv/bin/activate"
if not platform.platform().startswith("Windows")
else ".venv\\Scripts\\activate"
)

print(f"\n\nVirtualenv '{Colors.GREEN}{venv_dir}{Colors.END}' is ready and up-to-date.")
print(f"Run '{Colors.GREEN}{activate_script}{Colors.END}' to activate the virtualenv.")
2 changes: 2 additions & 0 deletions requirements.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
robotframework-browser-batteries
pypdf
1 change: 1 addition & 0 deletions tools/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

8 changes: 7 additions & 1 deletion tools/gen_pdf.robot
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ Library Process

*** Variables ***
@{EXCLUDE_FROM_PDF} Example Questions
${BROWSER} chromium
${HEADLESS} ${True}


*** Test Cases ***
Expand All @@ -22,7 +24,11 @@ Build Docusaurus
Process.Start Process npm run serve alias=docusaurus cwd=website

Open Syllabus
New Browser chromium headless=False
IF $BROWSER.lower() in ['chrome', 'msedge']
New Browser chromium channel=${BROWSER} headless=${HEADLESS}
ELSE
New Browser chromium headless=${HEADLESS}
END
New Page http://localhost:3000/robotframework-RFCP-syllabus/docs/overview
${dark} Get Element States
... button[aria-label="Switch between dark and light mode (currently dark mode)"]
Expand Down
4 changes: 2 additions & 2 deletions website/docs/chapter-02/02_suitefile_syntax.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ Understand the basic syntax of test cases and tasks.
::::

Suite files and resource files share the same syntax, however they differ in their capabilities.
Resource files are explained in more detail in [2.4.2 Resource Files](04_keyword_imports.md#242-resource-files) [3.1 Resource File Structure](../chapter-03/01_resource_file.md).
Resource files are explained in more detail in [2.4.2 Resource Files](chapter-02/04_keyword_imports.md#242-resource-files) [3.1 Resource File Structure](chapter-03/01_resource_file.md).


## 2.2.1 Separation and Indentation
Expand Down Expand Up @@ -284,7 +284,7 @@ Resource keywords.resource
Login User With Password
Connect To Server
Login User ironman 1234567890 # Login with valid credentials
Verify Valid Login Tony Stark # Verify that the login was successful by checking the user name
Verify Valid Login Tony Stark # Verifies a successful login by checking the user name
Close Server Connection

Denied Login With Wrong Password
Expand Down
4 changes: 2 additions & 2 deletions website/docs/chapter-02/03_executing.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ Robot Framework comes with three executables when being installed which are desi

- `robot` is the main executable that is used to execute suites.
- `rebot` (not part of this syllabus) is used to post-process execution results and generate reports.
- `libdoc` (not part of this syllabus) is used to generate keyword documentation for libraries and resource files. See [2.5 Keyword Interface and Documentation](../chapter-02/05_keyword_interface.md)
- `libdoc` (not part of this syllabus) is used to generate keyword documentation for libraries and resource files. See [2.5 Keyword Interface and Documentation](chapter-02/05_keyword_interface.md)



Expand All @@ -37,7 +37,7 @@ At a basic level, you can run `robot` by providing the path to a suite file or s
robot <path_to_root_suite>
```

In case of the [2.2.5 Example Suite File](../chapter-02/02_suitefile_syntax.md#225-example-suite-file) where a single suite file named `TestSuite.robot` is stored in a directory `robot_files`, to execute the example test suite the following command is used, if the current working directory of the terminal is the directory containing the `robot_files` directory:
In case of the [2.2.5 Example Suite File](chapter-02/02_suitefile_syntax.md#225-example-suite-file) where a single suite file named `TestSuite.robot` is stored in a directory `robot_files`, to execute the example test suite the following command is used, if the current working directory of the terminal is the directory containing the `robot_files` directory:
```plaintext
> robot robot_files
```
Expand Down
2 changes: 1 addition & 1 deletion website/docs/chapter-02/04_keyword_imports.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ Use resource files to import new keywords.
As mentioned before resource files are used to organize and store keywords and variables that are used in multiple suites.

They share a similar structure and the same syntax as suite files, but they do not contain test cases or tasks.
See [2.2 Basic Suite File Syntax](chapter-02/02_suitefile_syntax.md) for more information about the structure of suite files and [3.1 Resource File Structure](../chapter-03/01_resource_file.md) for more details of their structure.
See [2.2 Basic Suite File Syntax](chapter-02/02_suitefile_syntax.md) for more information about the structure of suite files and [3.1 Resource File Structure](chapter-03/01_resource_file.md) for more details of their structure.

They can contain other keyword imports, which cause the keywords from the imported libraries or resource files to be available in the suites where the resource file is imported. The same applies for variables that are defined and imported from other resource files.
Therefore keywords from a library that have been imported in a resource file are also available in the suite that imports that resource file.
Expand Down
4 changes: 2 additions & 2 deletions website/docs/chapter-02/05_keyword_interface.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ All of them can be called positionally or by name.

![Run Process Keyword Documentation](/img/Run_Process_Docs.png)

This keyword has one :term[Mandatory Arguments]{tooltipMd="An **Argument** that must be set.<br/>See [Mandatory Args](../chapter-03/03_user_keyword.md)"} `command` which can be called positionally or by name.
This keyword has one :term[Mandatory Arguments]{tooltipMd="An **Argument** that must be set.<br/>See [Mandatory Args](chapter-03/03_user_keyword.md)"} `command` which can be called positionally or by name.
The latter two arguments are optional.

The argument `arguments` is a "Variable Number of Positional Arguments" and can only be set by position.
Expand Down Expand Up @@ -346,7 +346,7 @@ Example redirecting stdout and stderr to a file:
```robotframework
*** Test Cases ***
Send 5 IPv4 Pings On Windows
Run Process ping -n 5 -4 localhost stdout=ping_output.txt stderr=ping_error.txt
Run Process ping -n 5 -4 localhost stdout=ping_output.txt stderr=ping_error.txt
```


Expand Down
18 changes: 12 additions & 6 deletions website/docs/chapter-02/06_writing_test.md
Original file line number Diff line number Diff line change
Expand Up @@ -37,22 +37,28 @@ Mixed Positional Arguments
...
... It is hard to figure out what the values are doing and which arguments are filled,
... without looking into the keyword documentation.
... Even though the argument `values` is kept at its default value `True` it must be set if later arguments shall be set positionally.
... Even though the argument `values` is kept at its default value `True`,
... it must be set if later arguments shall be set positionally.
Should Be Equal hello HELLO Values are case-insensitive NOT equal True True

All Named Arguments
[Documentation] Arguments are used named.
...
... It is clear what the values are doing and which arguments are filled and order is not relevant.
... It is clear what the values are doing and which arguments are filled
... and order is not relevant.
... The argument `values` can be omitted and the order can be mixed
Should Be Equal first=hello second=HELLO ignore_case=True msg=Values are case-insensitive NOT equal
Should Be Equal first=hello second=HELLO
... ignore_case=True msg=Values are case-insensitive NOT equal

Mixed Named and Positional Arguments
[Documentation] Arguments are used named and positional.
...
... The positional arguments must be in order, but the subsequent named arguments may be in an arbitrary order.
... The first arg has the string value `" hello spaces "` and the second arg has the string value `"HELLO SPACE"`.
Should Be Equal \ hello \ spaces \ HELLO \ SPACE ignore_case=True strip_spaces=True msg=Values are case-insensitive NOT equal
... The positional arguments must be in order,
... but the subsequent named arguments may be in an arbitrary order.
... The first arg has the string value `" hello spaces "`
... and the second arg has the string value `"HELLO SPACE"`.
Should Be Equal \ hello \ spaces \ HELLO \ SPACE
... ignore_case=True strip_spaces=True msg=Values are case-insensitive NOT equal
```


Expand Down
6 changes: 2 additions & 4 deletions website/docs/chapter-03/02_variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,10 +180,8 @@ ${SEARCH_URL} https://example.com/search
... separator=
```

`${SEARCH_URL}` will contain:
```
https://example.com/search?query=robot+framework&page=1&filter=recent&lang=en&category=test-automation
```
`${SEARCH_URL}` will contain the following without any spaces or newlines:
`https://example.com/search?query=robot+framework&page=1&filter=recent&lang=en&category=test-automation`


### 3.2.2.2 Primitive Data Types
Expand Down
5 changes: 3 additions & 2 deletions website/docs/chapter-03/03_user_keyword.md
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ All available settings are listed below and explained in this section or in sect
- `[Setup]`, `[Teardown]` Specify user keyword setup and teardown. (see [4.2 Teardowns (Suite, Test|Task, Keyword)](chapter-04/02_teardowns.md))
- `[Tags]` (*) Sets tags for the keyword, which can be used for filtering in documentation and attribution for post-processing results.
- `[Timeout]` (*) Sets the possible user keyword timeout.
- `[Return]` (*) Deprecated.
- `[Return]` (*) Deprecated. Use the `RETURN` statement instead. (see [3.3.6 RETURN Statement](chapter-03/03_user_keyword.md#336-return-statement))

(*) The application of these settings are not part of this syllabus.

Expand Down Expand Up @@ -190,7 +190,8 @@ Example that defines a keyword with two arguments:
Verify File Contains
[Documentation] Verifies that a file contains a specific text.
...
... The keyword opens the file specified by the file path and checks if it contains the expected content.
... The keyword opens the file specified by the file path
... and checks if it contains the expected content.
[Arguments] ${file_path} ${expected_content}
${server_log} = Get File ${file_path}
Should Contain ${server_log} ${expected_content}
Expand Down
Loading