Executive Definition
Keyword-driven testing, sometimes called action-word or table-driven testing, is an approach in which test cases are expressed as sequences of named actions — keywords — pulled from a fixed vocabulary. Each keyword corresponds to a piece of code that performs the action, but the test authors write only the keywords and their arguments. The scenario itself is data, not code.
The pattern is older than most people realise. It emerged in the 1990s telecom industry, where non-programmer testers needed to validate call flows without touching C. Modern implementations — Robot Framework, Katalon Studio, TestComplete, SoapUI — inherit that lineage. The tester composes a scenario as a plain-text table; the framework maps each row to a Python or Java function that performs the actual work.
The value proposition is division of labour. Engineers write and maintain the keyword library, applying software engineering discipline: version control, unit tests for keywords, deprecation policies. Business analysts and manual QA compose scenarios in the same shared spreadsheet or .robot file. Neither group blocks the other, and a redesigned UI requires updating only the keyword implementations — every scenario that used them continues to run.
Keyword-driven testing is often confused with BDD. They overlap but are not the same. BDD is a collaboration practice built around Given / When / Then narratives that describe behaviour; keyword-driven is a technical pattern for expressing steps as data. A team can use BDD without keywords (writing step definitions in code per feature) or use keywords without BDD (Robot Framework tables that never mention Given / When). Choose the shape that matches how your team communicates.
The failure mode is scenario sprawl. When it is trivial to compose a new scenario, teams accumulate them without curation. A suite of 4,000 keyword-driven scenarios becomes as hard to maintain as any other legacy asset. Apply the same rigor you would to code: review new scenarios, retire duplicates, and treat the keyword library as a stable API with semantic versioning.
Architecture & Production Code
A keyword-driven project has three layers: the scenario tables at the top, the keyword library in the middle, and the driver at the bottom. The middle layer is where engineering discipline lives or dies.
┌──────────────────────────────────────────┐
│ Scenario tables (.robot / .csv / .xlsx) │
│ | Open Login Page | │
│ | Enter Credentials | qa@x.com | ... │
│ | Submit Login | │
│ | Page Should Contain | Welcome │
└──────────────────────┬───────────────────┘
│ resolves
▼
┌──────────────────────────────────────────┐
│ Keyword library (Python / Java) │
│ def enter_credentials(email, password): │
│ ... │
└──────────────────────┬───────────────────┘
│ calls
▼
┌──────────────────────────────────────────┐
│ Driver (Selenium, Playwright, API) │
└──────────────────────────────────────────┘Scenarios never touch the driver directly. If a scenario table starts referencing CSS selectors or HTTP status codes, the keyword library is under-designed. The whole point of the pattern is that the top layer speaks in business terms.
Keyword design mirrors API design. Each keyword should have a single responsibility, a memorable name, typed arguments, and stable behaviour. Deprecate old keywords with warnings before deleting them, exactly as you would with a public API. Ship a changelog when the vocabulary changes.
The scenario storage format matters more than teams expect. Spreadsheets are inviting for analysts but produce diff-hostile pull requests. Plain-text Robot .robot files version well and diff cleanly, at the cost of a slightly steeper on-ramp. Start with plain text; move to spreadsheets only if the analysts refuse.
*** Settings ***
Library LoginKeywords.py
Library SeleniumLibrary
*** Variables ***
${BASE_URL} https://staging.example.com
${VALID_EMAIL} qa@example.com
${VALID_PASSWORD} s3cret!
*** Test Cases ***
Valid Login Reaches Dashboard
Open Login Page ${BASE_URL}
Enter Credentials ${VALID_EMAIL} ${VALID_PASSWORD}
Submit Login
Page Should Contain Welcome back
Invalid Password Shows Error
Open Login Page ${BASE_URL}
Enter Credentials ${VALID_EMAIL} wrong-password
Submit Login
Error Banner Should Say Invalid email or password
*** Keywords ***
# See LoginKeywords.py:
# def open_login_page(base_url): driver.get(f"{base_url}/login")
# def enter_credentials(email, password):
# driver.find_element(By.ID, "email").send_keys(email)
# driver.find_element(By.ID, "password").send_keys(password)
# def submit_login(): driver.find_element(By.ID, "submit").click()
# def error_banner_should_say(expected):
# assert driver.find_element(By.CSS_SELECTOR, "[role=alert]").text == expectedKeyword-Driven vs BDD vs Data-Driven
| Aspect | Keyword-driven | BDD | Data-driven |
|---|---|---|---|
| Author profile | Analyst / manual QA | Product + QA + dev triad | Engineer + analyst |
| Varies | Steps | Behaviour narrative | Inputs |
| Primary tool | Robot Framework, Katalon | Cucumber, SpecFlow | Native test runners |
| Scenario format | Tables of keywords | Given / When / Then | Test + data table |
| Strength | Low code entry barrier | Shared understanding | Coverage of input variation |
| Common risk | Scenario sprawl | Cucumber-as-glue misuse | Data drift |
The three approaches are not exclusive. A mature suite may use BDD for outward-facing regression, keyword-driven tables for manual-QA-authored smoke, and data-driven parametrisation for edge-case coverage. Choose per suite, not per project.
Production Debugging Scenarios
Keyword-driven suites tend to fail in slow, cultural ways rather than fast, technical ones.
Keyword library grows into a god-module
- Symptom
- One file contains 400 keywords, most of them named 'do_x' or 'click_y'.
- Root cause
- No one owns library curation; every scenario author added the keyword they needed.
- Fix
- Split keywords by domain (LoginKeywords, CartKeywords, ReportingKeywords). Deprecate duplicates with warnings for one sprint before deleting.
Scenarios reference internal selectors
- Symptom
- A scenario contains 'Click Element css=#login-btn'.
- Root cause
- Missing high-level keyword forced the author to reach through to Selenium.
- Fix
- Add a business-level keyword (Submit Login) that wraps the click. Ban raw driver keywords from scenario tables via lint.
CI report is a wall of green with hidden flakiness
- Symptom
- Suite passes but random keyword timings vary wildly run to run.
- Root cause
- Waits are implemented per keyword with sleep(2) rather than explicit conditions.
- Fix
- Replace time-based waits with wait_until_element_is_visible or equivalent. Add a report showing p95 keyword duration per run.
Practice this concept in a real QA interview
Run a live mock with our AI Interview Coach, tune your resume with the ATS Resume Reviewer, and screen live listings on the QA Jobs Radar.