Specification Pattern
The Specification pattern provides a streamlined way to write executable specifications without the ceremony of Given/When/Then. Inspired by MSpec (Machine.Specifications), it fits precise business policies as well as technical components and APIs when direct rules communicate more clearly than a narrative.
What Is the Specification Pattern?
While the BDD pattern excels at describing workflows, not every claim benefits from the Given/When/Then structure. A product manager may want the exact shipping-rate examples without reading a checkout journey; the same directness helps when testing a math library, validation utility, or API contract:
// BDD for a simple calculation — more ceremony than value
Feature: Calculator
Scenario: Adding two numbers
Given the first number is 3
And the second number is 5
When the numbers are added
Then the result should be 8
The Specification pattern cuts straight to the point:
Specification: Calculator
Rule: Adding 3 and 5 produces 8
Rule: Multiplying by zero always returns zero
Rule: Dividing by zero throws an error
Each Rule is one independently verifiable claim about the system. It can use multiple related assertions to prove that claim. There are no step keywords: the specification title, rules, and examples provide the detail.
The examples on this page use the LiveDoc conceptual vocabulary — Specification, Rule, RuleOutline. Unlike the BDD pattern which borrows from Gherkin, the Specification pattern is a LiveDoc concept inspired by MSpec. Each SDK implements it using its platform's native idioms:
- TypeScript/Vitest: Function calls —
specification(),rule(),ruleOutline() - C#/xUnit: Classes and attributes —
SpecificationTestbase class,[Rule],[RuleOutline]
See SDK Support for links to the actual code syntax.
The Structure
The Specification pattern uses a simple two-level hierarchy:
Specification
A Specification is the top-level container — analogous to a Feature in BDD. It groups related rules under a descriptive title:
Specification: Email Validator
@validation @input-handling
Rules governing email address validation across the platform.
Like Features, Specifications support:
- Tags for filtering and categorization (
@validation,@unit) - Descriptions for additional context
- Skip and Only modifiers for test control
Rule
A Rule is a focused fact about the system that the test verifies. It's analogous to a Scenario, but without the Given/When/Then step structure:
Specification: Email Validator
Rule: Accepts addresses with standard format (user@domain.com)
Rule: Rejects addresses without an @ symbol
Rule: Rejects addresses with multiple @ symbols
Rule: Accepts addresses with subdomains (user@mail.domain.com)
Rule: Trims whitespace before validation
Rules contain direct test code — setup, action, and assertion all in one block. This makes them extremely compact and readable as a list of behaviors.
RuleOutline
For data-driven specifications, RuleOutline works just like ScenarioOutline — a template with an Examples table:
Specification: Email Validator
RuleOutline: Email '<email>' has validity '<valid>'
Examples:
| email | valid |
| user@example.com | true |
| invalid | false |
| user@.com | false |
| a@b.co | true |
| user @domain.com | false |
Each row becomes a separate test in the documentation output, making all variations visible at a glance. Learn more in Data-Driven Tests.
When to Use the Specification Pattern
The Specification pattern is the right choice when:
- The claim is a precise rule — A product owner may inspect shipping, eligibility, or discount examples alongside a workflow Feature
- Tests are self-contained — A single rule captures setup, action, and assertion naturally
- You're testing many variations — A list of rules reads better than a list of scenarios with repeated Given/When/Then
- The component is technical — APIs, utilities, algorithms, data transformers
- Directness beats narrative — The behavior is clear without the Given/When/Then framing
Examples of Good Specification Use
| Component | Why Specification Fits |
|---|---|
| Shipping and pricing policies | Exact input/output examples make thresholds and exceptions inspectable |
| Validation utilities | Many rules, each a simple input → output check |
| Math/algorithm logic | Direct assertions on computed results |
| Parser behavior | Many edge cases, each a one-line rule |
| Configuration options | Each option has a clear expected default/behavior |
| Error handling | Each error condition is a standalone assertion |
| Type coercion | Many input/output pairs, perfect for RuleOutline |
How It Differs from BDD
The fundamental difference is structure vs. directness:
| Aspect | BDD Pattern | Specification Pattern |
|---|---|---|
| Organizing concept | Feature → Scenario → Steps | Specification → Rule |
| Step keywords | Given, When, Then, And, But | None |
| Setup and assertion | Separated into distinct steps | Combined in a single block |
| Reader's focus | Following a workflow | Inspecting precise rules and examples |
| Data-driven variant | ScenarioOutline | RuleOutline |
| Best read as | A user story with examples | A list of facts about the system |
| Typical test count | Fewer, more detailed scenarios | Many, more concise rules |
Side-by-Side Comparison
Here's the same behavior expressed in both patterns:
BDD approach:
Feature: Password Strength Validator
Scenario: Weak password (too short)
Given a password 'abc'
When the password strength is checked
Then the result should be 'weak'
Scenario: Strong password
Given a password 'MyS3cure!Pass'
When the password strength is checked
Then the result should be 'strong'
Specification approach:
Specification: Password Strength Validator
Rule: Passwords shorter than 8 characters are rated 'weak'
Rule: Passwords with mixed case, numbers, and symbols are rated 'strong'
Rule: Passwords with only lowercase letters are rated 'medium'
Rule: Empty passwords are rated 'weak'
Neither is "better" — they serve different purposes. The BDD version tells a story; the Specification version provides a concise rule reference. A product owner can read either when it documents the behavior they care about.
Decision Guide
Use this flowchart to choose the right pattern:
What kind of claim is this?
├── A workflow where preconditions, action, and outcome tell the story
│ └── Use Feature / Scenario
└── A focused rule or exact input/output contract
└── Use Specification / Rule or RuleOutline
Most projects benefit from using both patterns. A common convention:
- BDD for workflows that benefit from Given/When/Then
- Specification for precise business policies and technical contracts
LiveDoc supports both in the same project. Keep related Features and Specifications together under the business capability in the Viewer; see Test Organization.
The Specification Pattern as Living Documentation
Just like BDD, the Specification pattern produces living documentation. The key difference is in the shape of that documentation:
- BDD documentation reads like a narrative: "Given this context, when the user does X, then Y happens."
- Specification documentation reads like a reference sheet: "Here are the exact rules for this capability."
Both are valuable. A reader can follow an Orders checkout Feature and inspect its nearby Shipping rates Specification for boundary cases without switching to a separate technical catalogue.
SDK Support
Both LiveDoc SDKs fully support the Specification pattern:
- TypeScript/Vitest: Uses function calls —
specification(),rule(),ruleOutline(). See Your First Spec. - C#/xUnit: Uses classes and methods — inherit from
SpecificationTest, define rule methods. See Your First Spec.
The concepts are identical across both SDKs. Only the syntax differs.
Recap
- The Specification pattern is a compact alternative to BDD, inspired by MSpec.
- Specification groups related rules; Rule is a direct assertion without step ceremony.
- RuleOutline provides data-driven testing with Examples tables.
- Use Specification for precise business or technical rules and tests with many variations.
- Use BDD when a Given/When/Then narrative adds clarity.
- Both patterns produce living documentation and belong together under their capability.
Next Steps
- Next in this series: Data-Driven Tests — ScenarioOutline and RuleOutline in depth
- Hands-on: Vitest: Your First Spec or xUnit: Your First Spec
- Compare with: BDD Pattern — the narrative alternative