Chapter 12Lesson 01170–230 min

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.

Resource filesVariable filesLibrary importsSearch pathMental model

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

Project dependency and result flow
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}?

If ../resources/common.resource exists relative to the importing suite, does Robot need --pythonpath to find it?

Why is a Python variable file more security-sensitive than a JSON variable file?

Two imported resources both define “Normalize Value.” What is the safe immediate diagnostic action?

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.

Next lesson

Resource Files, Variable Files, Library Imports, and Project Layout: Guided Hands-On Workflow

Continue with Resource Files, Variable Files, Library Imports, and Project Layout: Guided Hands-On Workflow. It builds directly on the state, evidence, and operating assumptions established here, so carry those constraints forward rather than treating the next page as an isolated topic.

Further reading

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.

Ethereum / ERC-20
0x716c4Ab160C4B66F31a28AE2448BfF68fc3a2ef0 Send only Ethereum/ERC-20 compatible assets to this address.