Chapter 11Lesson 02210–290 min

Data-Driven Testing, Templates, Embedded Arguments, and Variants: Guided Hands-On Workflow

Refactor duplicated synthetic validation cases into named template variants, add a negative row, use embedded arguments for readable calls, compare the same matrix with a FOR loop, and inspect result identity and failure evidence.

Hands-onSynthetic dataTemplate rowsEmbedded argumentsReport evidence

Learning objectives

  • Convert duplicated tests into a suite-level Test Template while preserving descriptive test names.
  • Add positive, boundary, and negative variants with explicit expected classifications.
  • Use one embedded-argument template safely and understand the generated keyword call name.
  • Compare template variants with separate explicit tests and a FOR-loop implementation.
  • Inspect output.xml/log/report evidence and identify the smallest diagnosable rerun unit.

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, templates can use normal, named, and embedded arguments. A templated test containing multiple data rows executes all rows even when one fails or is skipped, then aggregates the test status. User-keyword argument type conversion is stable from Robot Framework 7.3.

1. Disposable scenario: identifier classification

The system under automation is deliberately synthetic. An identifier is accepted when its length is between 3 and 8 characters inclusive and every character is ASCII alphanumeric. There is no network, browser, database, file mutation, or paid service. The only persistent evidence is Robot Framework output under a chosen result directory.

2. Preflight and project layout

rf11-data-lab/
└── suites/
    └── identifiers.robot
python --version
python -m robot --version
python -m robot --dryrun --outputdir results/dryrun suites/identifiers.robot

For this course baseline, record Robot Framework 7.4.2 and the actual Python version in your evidence notes. The suite uses only BuiltIn.

3. Start with the duplication so the refactor has a reason

*** Test Cases ***
Minimum valid
    ${actual}=    Classify Identifier    abc
    Should Be Equal    ${actual}    ACCEPT

Too short
    ${actual}=    Classify Identifier    ab
    Should Be Equal    ${actual}    REJECT

Contains punctuation
    ${actual}=    Classify Identifier    ab-c
    Should Be Equal    ${actual}    REJECT

The tests are clear but each repeats the same two-step contract. As the matrix grows, a message change or classifier refactor must be repeated in every test.

4. Refactor to a suite-level Test Template

*** Settings ***
Test Template    Identifier Should Have Classification

*** Test Cases ***                 CANDIDATE    EXPECTED
Minimum valid                       abc          ACCEPT
Maximum valid                       abc12345     ACCEPT
Too short                           ab           REJECT
Too long                            abc123456    REJECT
Contains punctuation                ab-c         REJECT

*** Keywords ***
Identifier Should Have Classification
    [Arguments]    ${candidate}    ${expected}
    ${actual}=    Classify Identifier    ${candidate}
    Should Be Equal    ${actual}    ${expected}
    ...    msg=classification mismatch for candidate=${candidate}

Classify Identifier
    [Arguments]    ${candidate}
    ${length}=    Get Length    ${candidate}
    IF    $length < 3 or $length > 8
        RETURN    REJECT
    END
    ${alnum}=    Run Keyword And Return Status
    ...    Should Match Regexp    ${candidate}    ^[A-Za-z0-9]+$
    IF    not $alnum
        RETURN    REJECT
    END
    RETURN    ACCEPT

Run Keyword And Return Status is used narrowly here to classify whether a pattern matches. The final test contract is still a hard Should Be Equal; a wrong classification fails the test. This is not a pattern for turning arbitrary test failures into green booleans.

5. Execute and inspect the named variants

python -m robot --outputdir results/named suites/identifiers.robot

Expected result: five tests and five PASS statuses. The negative variants pass because the classifier returns REJECT and the expected column also says REJECT. No expected-error suppression is involved.

Evidence What to verify
Console Five tests executed; suite PASS
report.html Five separately named tests such as “Too short”
log.html Each test contains one template keyword call and classifier trace
output.xml Five test elements, each with its own name/status

6. Make the template call itself readable with embedded arguments

Replace the template contract with an embedded-argument keyword. The source test names stay the same; the log call now contains the concrete candidate and expected classification:

*** Settings ***
Test Template    Identifier "${candidate}" should be ${expected}

*** Test Cases ***                 CANDIDATE    EXPECTED
Minimum valid                       abc          ACCEPT
Contains punctuation                ab-c         REJECT

*** Keywords ***
Identifier "${candidate}" should be ${expected}
    ${actual}=    Classify Identifier    ${candidate}
    Should Be Equal    ${actual}    ${expected}

Quoting ${candidate} gives the embedded argument a visible boundary. This matters if later values contain spaces.

7. Inject one wrong expectation and preserve the evidence

Change only one row temporarily:

Contains punctuation                ab-c         ACCEPT
python -m robot --outputdir results/intentional-fail suites/identifiers.robot

Expected command exit status is non-zero. Preserve results/intentional-fail. The failure message should include candidate=ab-c (if using the normal template version) or the embedded call name. Repair the expected value to REJECT only after you have captured the first-failure artifacts.

8. Compare with one multi-row templated test

*** Test Cases ***
Grouped identifier matrix
    [Template]    Identifier Should Have Classification
    abc          ACCEPT
    ab           ACCEPT
    ab-c         REJECT
    abc12345     ACCEPT

The intentionally wrong ab / ACCEPT row fails, but Robot still runs the later rows. The report contains one failing test named Grouped identifier matrix. The log contains all template iterations. This is compact, but the rerun unit is the whole grouped test.

9. Compare with a FOR loop

*** Test Cases ***
Loop over identifier matrix
    FOR    ${candidate}    ${expected}    IN
    ...    abc         ACCEPT
    ...    ab          REJECT
    ...    ab-c        REJECT
        ${actual}=    Classify Identifier    ${candidate}
        Should Be Equal    ${actual}    ${expected}
    END

This is one test and one loop. Unlike a template’s automatic iteration continuation, a normal failing assertion stops this test unless you explicitly add other failure-control behavior. A FOR loop is appropriate when the iteration itself is one business behavior; it is weaker when each row deserves separate release/rerun identity.

10. Same data, different operational meaning

Shape Report test count Failure/rerun unit Use when
Separate explicit tests One per variant Variant Workflows differ or names/steps matter independently
Suite-level Test Template One per named variant Variant Same contract; strong CI identity
One test + multiple template rows One Whole grouped test Rows belong to one test lifecycle and aggregate evidence is acceptable
One test + FOR One Whole loop test Iteration is an implementation detail of one scenario

11. Challenge: choose the layer before changing syntax

You need to validate 12 release labels. Six are boundaries that the release team tracks independently; the other six are diagnostic samples used only to exercise one parsing behavior. Decide which belong as separate named templated tests and which could be grouped. Write a one-paragraph rationale based on rerun identity, setup isolation, and report readability—not line-count reduction.

12. Knowledge check

Why does a negative row such as “Too short → REJECT” still produce a PASS test?

If one grouped template row fails, what should happen to later template rows?

Which shape gives each variant its own report/rerun identity while still removing workflow duplication?

Why is a FOR loop not automatically equivalent to a multi-row template?

13. Summary and next step

You have converted repeated behavior into an explicit template contract without giving up variant names, compared embedded calls, grouped iterations, and loops, and preserved a deliberate failure as evidence. Lesson 3 turns these mechanics into design rules for matrix size, typed data, external data boundaries, and abstraction choice.

Next lesson

Data-Driven Testing, Templates, Embedded Arguments, and Variants: Configuration, Design Patterns, and Trade-Offs

Continue with Data-Driven Testing, Templates, Embedded Arguments, and Variants: Configuration, Design Patterns, and Trade-Offs. 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.