Skip to content

A listener that stores results in SQLite

Chapter lab: Listening to executionch20-listening-to-execution.zip · 4 KB

This lesson continues in the same lab as the lesson before it. If you don’t have it yet, download it here.

Download ch20-listening-to-execution.zip

Or fetch and unpack it from a terminal in VS Code:

Terminal window
curl -fsSLO https://manykarim.github.io/robotframework-essentials-web/labs/ch20-listening-to-execution.zip && unzip -q ch20-listening-to-execution.zip && rm ch20-listening-to-execution.zip

Open the folder in VS Code with code rfe-ch20-listening-to-execution (or File → Open Folder…) and accept the recommended RobotCode and Python extensions. Then set it up:

Terminal window
uv sync
Terminal window
python3 -m venv .venv
source .venv/bin/activate
pip install -r requirements.txt

Keep the environment active in every terminal where you run lesson commands.

Terminal window
poetry install --no-root

Python 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-ch20-listening-to-execution/
    • Directory.vscode/
      • extensions.json
    • Directorychecks/
      • orders.robot
    • Directorydata/
      • orders.csv
    • Directoryext/
      • README.md
    • .gitignore
    • .python-version
    • LAB.md
    • pyproject.toml
    • README.md
    • requirements.txt
    • uv.lock

A markdown table is easy to read; a database is easy to query. Python’s standard library includes sqlite3 — a whole SQL database in a single file, no server — so a listener can record every run into a table you can later query for trends, flaky tests, or slowest cases.

The pattern is the same v3 listener: open the database when the run starts, insert a row per test, and commit when the run closes.

Task 1 — Record each result into a table

Section titled “Task 1 — Record each result into a table”
Edit

Goal: create ext/SqliteResults.py — a v3 listener that creates a results table in results/results.db and inserts each test’s name and status.

Here is the same shape writing to a different table — one keyed by tag. Adapt it to store name and status.

Worked example — adapt it, don’t copy it

import sqlite3
import pathlib
class TagResults:
ROBOT_LISTENER_API_VERSION = 3
def __init__(self):
pathlib.Path("results").mkdir(exist_ok=True)
self.db = sqlite3.connect("results/tags.db")
self.db.execute("CREATE TABLE IF NOT EXISTS tags (test TEXT, tag TEXT)")
def end_test(self, data, result):
for tag in data.tags:
self.db.execute("INSERT INTO tags VALUES (?, ?)", (data.name, tag))
def close(self):
self.db.commit()
self.db.close()

Done when

ext/SqliteResults.py defines a listener that uses sqlite3.

Hint 1

Open the database in __init__ and create the table: self.db = sqlite3.connect("results/results.db") then CREATE TABLE IF NOT EXISTS results (name TEXT, status TEXT).

Hint 2

Insert in end_test — INSERT INTO results VALUES (?, ?), (data.name, result.status) — and commit() then close() in close().

Solution
import sqlite3
import pathlib
class SqliteResults:
ROBOT_LISTENER_API_VERSION = 3
def __init__(self):
pathlib.Path("results").mkdir(exist_ok=True)
self.db = sqlite3.connect("results/results.db")
self.db.execute("CREATE TABLE IF NOT EXISTS results (name TEXT, status TEXT)")
def end_test(self, data, result):
self.db.execute("INSERT INTO results VALUES (?, ?)", (data.name, result.status))
def close(self):
self.db.commit()
self.db.close()

Task 2 — Run the suite with your listener

Section titled “Task 2 — Run the suite with your listener”
Run
Terminal window
uv run robot --listener ext/SqliteResults.py checks/orders.robot
Terminal window
robot --listener ext/SqliteResults.py checks/orders.robot
Terminal window
poetry run robot --listener ext/SqliteResults.py checks/orders.robot

results/results.db now holds a row per test. You could open it with any SQLite tool and run SELECT * FROM results;.

Done when

results/results.db was created and contains the run’s tests.

Check your understanding

Quick recall. Your first answer stays in this browser; the quiz never blocks your progress.

  1. Why store results in SQLite instead of a text file?

    Show the answer

    Answer: you can query it (trends, flaky tests, slowest cases) — A database is queryable with SQL; sqlite3 is in the standard library, one file, no server.

  2. When should the listener commit and close the database?

    Show the answer

    Answer: in close() at the end of the run — Insert per test in end_test; commit() and close() once in close().

Key terms

sqlite3concept
Standard-library SQL database in a single file — no server.
close()concept
Listener hook that fires once at the end of the whole run.

All terms in the glossary →