A module library that logs and fails
Chapter lab: Custom libraries
This chapter works in a prepared project. Download it before the first task; it unpacks into its own folder.
Download ch18-custom-libraries.zip
Or fetch and unpack it from a terminal in VS Code:
curl -fsSLO https://manykarim.github.io/robotframework-essentials-web/labs/ch18-custom-libraries.zip && unzip -q ch18-custom-libraries.zip && rm ch18-custom-libraries.zipInvoke-WebRequest https://manykarim.github.io/robotframework-essentials-web/labs/ch18-custom-libraries.zip -OutFile ch18-custom-libraries.zip; Expand-Archive ch18-custom-libraries.zip -DestinationPath .; Remove-Item ch18-custom-libraries.zipOpen the folder in VS Code with code rfe-ch18-custom-libraries (or File → Open Folder…) and accept the recommended RobotCode and Python extensions. Then set it up:
uv syncpython3 -m venv .venvsource .venv/bin/activatepip install -r requirements.txtpython -m venv .venv.venv\Scripts\Activate.ps1pip install -r requirements.txtKeep the environment active in every terminal where you run lesson commands.
poetry install --no-rootPython 3.13 or newer is required; uv installs it when it is missing.
Open in browserNo setup? Try the lab right here: its files, an editor and a terminal, running in your browser.
What's inside
Directoryrfe-ch18-custom-libraries/
Directory.vscode/
- extensions.json
Directorychecks/
- smoke.robot
Directorylibraries/
- README.md
Directoryvariables/
- README.md
- .gitignore
- .python-version
- LAB.md
- pyproject.toml
- README.md
- requirements.txt
- uv.lock
A real keyword usually does three things: it computes a result and returns it, it logs what it did so the report is readable, and it fails clearly when something is wrong.
Robot Framework’s own logging is available to your library through
robot.api.logger — logger.info(...) writes to log.html exactly like the
built-in Log keyword. Returning a value hands it back to the suite; raising
AssertionError fails the test with your message.
Task 1 — A module library with a builder and a check
Section titled “Task 1 — A module library with a builder and a check”Goal: create libraries/order_lib.py with two functions —
build_order_reference(prefix, number) that logs and returns a reference, and
order_total_should_be_positive(total) that fails on a non-positive total.
Here is the same pair over a different domain — support tickets. Adapt it to orders (a four-digit reference, and a positive-total check).
Worked example — adapt it, don’t copy it
from robot.api import logger
def build_ticket_id(queue, number: int) -> str: ticket = f"{queue}#{number:05d}" logger.info(f"Opened ticket {ticket}") return ticket
def priority_should_be_known(priority: str) -> None: if priority not in {"low", "normal", "urgent"}: raise AssertionError(f"Unknown priority: {priority}")Done when
libraries/order_lib.py defines build_order_reference and order_total_should_be_positive.
Hint 1
Import the logger at the top: from robot.api import logger. In the builder,
logger.info(...) before you return the reference.
Hint 2
The check keyword returns nothing and only raises on failure:
if total <= 0: raise AssertionError(f"Order total must be positive, got {total}").
Solution
from robot.api import logger
def build_order_reference(prefix, number: int) -> str: reference = f"{prefix}-{number:04d}" logger.info(f"Built order reference {reference}") return reference
def order_total_should_be_positive(total: float) -> None: if total <= 0: raise AssertionError(f"Order total must be positive, got {total}")Task 2 — Import it and run it green
Section titled “Task 2 — Import it and run it green”Create checks/order_lib.robot:
*** Settings ***Library ../libraries/order_lib.py
*** Test Cases ***Reference Is Logged And Built ${ref}= Build Order Reference TRN 7 Should Be Equal ${ref} TRN-0007
Positive Total Passes Order Total Should Be Positive 19.90Run it, then open log.html to see your logger.info line:
uv run robot checks/order_lib.robotrobot checks/order_lib.robotpoetry run robot checks/order_lib.robotDone when
the test Reference Is Logged And Built passes.
Check your understanding
Quick recall. Your first answer stays in this browser; the quiz never blocks your progress.
How does a Python library write to
log.html?robot.api.loggerwrites to the log exactly like the built-inLogkeyword.Show the answer
Answer:
from robot.api import loggerthenlogger.info(...)—robot.api.loggerwrites to the log exactly like the built-inLogkeyword.A module-based library is best when keywords…
Plain functions are perfect for stateless keywords; reach for a class when they must share state.
Show the answer
Answer: stand alone (stateless) — Plain functions are perfect for stateless keywords; reach for a class when they must share state.
Key terms
- robot.api.loggerconcept
- Log from Python into
log.html(logger.info/debug/warn). - module libraryconcept
- A
.pyfile of functions imported as keywords.