Resource Files, Variable Files, Library Imports, and Project Layout: Core Concepts and Mental Model
Build a precise mental model of Robot Framework project boundaries: suites consume resources, variables, and Python libraries through deterministic import paths while source, runtime state, and results remain separate.
Learning objectives
- Explain the dependency direction from a suite to resources, variable files, libraries, data, and result artifacts.
- Distinguish ${CURDIR}, ${EXECDIR}, the process working directory, and Python module search path.
- Explain how Robot resolves Resource, Variables, and Library imports without treating them as one mechanism.
- Define ownership boundaries for Robot variables, Python library instances, external state, and output artifacts.
- Inspect paths and imports read-only before changing project structure.
Current compatibility baseline. Verified
2026-08-31: Robot Framework 7.4.2 is the current stable release and
requires Python 3.8+; 7.5b1 is a pre-release and is not required in
this chapter. In 7.4.2, .resource is the recommended
resource-file extension. Resource and Settings-level variable-file
paths are resolved relative to the importing data file first and
then via Python's module search path. ${CURDIR} is the
absolute directory of the current data file;
${EXECDIR} is the absolute directory where execution
started. JSON variable files require no optional package; YAML
variable files require PyYAML.
1. The problem: a passing suite can still be location-dependent
Chapter 11 gave you compact, diagnosable variants. The next scaling
problem appears when reusable keywords, data, and custom Python
capabilities are split across files. A suite may pass from an IDE
because the editor silently sets a project root, then fail in CI
because the runner starts in another directory. Another suite may
import ../../../../common.resource successfully until
somebody moves one folder.
The fix is not “add more paths until it works.” The fix is to define which file owns each dependency and which path-resolution mechanism is responsible for finding it.
2. Inspect the current runtime before editing imports
python --version
python -m robot --version
python -c "import os, sys; print('cwd=', os.getcwd()); print('python=', sys.executable); print('sys.path[0:5]=', sys.path[0:5])"
These commands do not mutate the project. Record the interpreter, Robot Framework version, process working directory, and initial Python search path. When an import later fails, this snapshot answers whether the runner changed rather than the source.
3. Define the objects and owners before wiring them together
| Object | Primary owner | Typical evidence | Common confusion |
|---|---|---|---|
| Suite file | Test/task intent and local suite settings | Path, suite/test names, output tree | Assumed to define a project root automatically |
| Resource file | Reusable Robot user keywords and shared Robot variables | Import path, resource documentation, keyword source | Treated like a Python library or a test suite |
| Variable file | Configuration/test-data values loaded into Robot variables | File/module path, exported variable names | Used as an imperative setup script |
| Python test library | Lowest-level custom capability and optional library-instance state | Module/class name, Libdoc, Python import location | Confused with a resource file |
| Data file | Synthetic fixture content read by a keyword/library | Checksum/path/content | Confused with Robot variable-file semantics |
| Module search path | Python import discovery and Robot fallback search for resources/variable files | sys.path, --pythonpath |
Confused with current working directory |
| Results directory | Execution evidence generated by Robot |
output.xml, log.html,
report.html
|
Written into source folders and accidentally committed |
| External state | Filesystem/process/browser/API/database/SSH/RPA target | Target-specific state/evidence | Mistaken for Robot variable state |
4. Mental model: dependencies flow inward; evidence flows outward
flowchart TD S[Suite / test intent] --> R[Resource imports] R --> K[User keywords / shared Robot variables] S --> V[Variable file imports] V --> C[Configuration values] S --> L[Library imports] L --> P[Python module / library instance] K --> X[External or local capability] P --> X C --> K X --> A[Assertion / status] A --> O[output.xml / log.html / report.html] M[Module search path] --> R M --> V M --> L
The suite points to three different dependency types. Resource imports bring Robot-level keywords/variables. Variable files supply values. Library imports expose Python keywords and may own Python object state. The module search path can help Robot locate all three, but that does not make them the same kind of dependency. Result artifacts are outputs of execution, not dependencies to import back into source.
5. Four path concepts that must not collapse into “the current folder”
| Concept | 7.4.2 meaning | Use it for |
|---|---|---|
${CURDIR} |
Absolute directory containing the current Robot data/resource file |
Paths anchored to the source file, such as
${CURDIR}/../data
|
${EXECDIR} |
Absolute directory where Robot execution was started | Intentional execution-root evidence or a documented runner contract |
| Process working directory | OS process cwd; normally the same start location represented by EXECDIR | Shell/process behavior; never assume it equals a source-file directory |
| Python module search path | Locations Python/Robot search for importable modules/extensions | Library imports by name and fallback search for resource/variable files |
${CURDIR} is stable when a source file moves together
with its nearby data; ${EXECDIR} changes when the
launch location changes. Neither should be used as a magical
“project root” unless your project explicitly defines that contract.
6. Resource imports: source-relative first, module-search fallback second
*** Settings ***
Resource ../resources/common.resource
*** Test Cases ***
Example
Common Validation sample-42
For a non-absolute resource path, Robot Framework first checks
relative to the file doing the import. If it is not found there,
Robot searches the Python module search path. The recommended
extension is .resource. A resource cannot contain
tests/tasks; it exists to share Robot-level keywords and variables.
Imports are transitive for available keywords/variables: a resource can import a library or another resource and make those capabilities available to its importer. That convenience is why resource dependency direction needs governance—deep or cyclic chains are difficult to reason about.
7. Variable files: values with different execution risk
*** Settings ***
Variables ../variables/demo.py
Variables ../variables/demo.json
Settings-level variable-file paths follow the same source-relative-then-module-search rule. A Python variable file is executable Python code when imported, so import-time I/O, random values, environment reads, prints, or network calls are real side effects. JSON is data-only and needs no extra dependency. YAML is also supported, but requires PyYAML.
Security boundary. Do not read real secrets and print/log them from an import-time Python variable file. Importing configuration should not become an invisible deployment action.
8. Library imports: name/module lookup versus physical path
*** Settings ***
Library libraries.text_tools
# A physical path is possible, but module imports are easier to standardize:
# Library ../libraries/text_tools.py
A library imported by name must be on Python's module search path. A
library imported by a physical path is resolved relative to the
current data file. For reusable project libraries, one explicit
project-root --pythonpath contract keeps imports
identical across suites. For published/reused libraries, normal
Python packaging is stronger because installation puts the package
on the module search path without project-specific path injection.
9. Keyword collisions are an execution-resolution problem, not a filesystem problem
If two resources provide Normalize Value, Robot cannot
infer your architectural intent from the folder names. Qualify the
call using the resource basename, for example
billing.Normalize Value versus
identity.Normalize Value, or rename the abstractions so
the ambiguity disappears. Robot gives suite-local user keywords
highest scope priority, then resource keywords, external-library
keywords, and standard-library keywords. Do not rely on accidental
import order to choose between two same-named resource keywords.
10. Why this matters in DevOps
CI runners, containers, local shells, IDEs, and Pabot workers may start with different working directories and different Python environments. A deterministic project defines the interpreter/dependencies, a stable source root, import direction, and a separate output root. That makes an import failure attributable: source-relative path, module search path, Python package, or runner contract—not “Robot randomly cannot find it.”
11. Knowledge check
What is the difference between ${CURDIR} and ${EXECDIR}?
${CURDIR} is the absolute directory containing the current data file; ${EXECDIR} is the absolute directory where execution started. Moving the launch directory changes EXECDIR but not CURDIR for the same source file.
If ../resources/common.resource exists relative to the importing suite, does Robot need --pythonpath to find it?
No. Robot checks the importing file directory first for relative resource paths. The module search path is a fallback if the path is not found there.
Why is a Python variable file more security-sensitive than a JSON variable file?
Python is executable at import time and can read environment values, files, network resources, or print/log data. JSON is data-only.
Two imported resources both define “Normalize Value.” What is the safe immediate diagnostic action?
Qualify the keyword with the resource name (or rename the abstractions) and inspect the import graph. Do not change PYTHONPATH or import order randomly to make one win.
12. Summary and next step
A portable Robot project separates test intent, reusable Robot
resources, configuration values, Python capabilities, fixture data,
and result artifacts. ${CURDIR},
${EXECDIR}, cwd, and the module search path answer
different questions. Lesson 2 refactors a monolithic suite into
explicit tests/, resources/,
variables/, libraries/,
data/, and results/ boundaries and proves
the imports with dry-run and Libdoc.
Further reading
- Robot Framework 7.4.2 User Guide — Resource and variable files — resource structure, import rules, Python/YAML/JSON variable files, and precedence.
- Robot Framework 7.4.2 User Guide — Using test libraries — importing libraries by name or path and library aliases.
-
Robot Framework 7.4.2 User Guide — Module search path
— installed packages, PYTHONPATH, and
--pythonpath. -
Robot Framework 7.4.2 User Guide — Built-in variables
—
${CURDIR},${EXECDIR}, path separators, and temporary directory. - Robot Framework 7.4.2 User Guide — Handling keywords with same names — scope priority, explicit qualification, and search order.
- Robot Framework 7.4.2 User Guide — Libdoc — library/resource documentation and import verification.
- Robot Framework 7.4.2 on PyPI — pinned stable package metadata and Python requirement.
- Robot Framework releases — re-check stable/pre-release status when updating the chapter.
Keep the academy open
Support free, practical DevOps education.
Every lesson is designed to remain readable in a browser, downloadable from GitHub, and usable without a paid learning platform. Contributions help expand and maintain the curriculum.
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0
Send only Ethereum/ERC-20 compatible assets to this
address.