Skip to content
Executable specification · nine languages

Specifications you can run.

AlignThree is an IDE for writing specifications as tables, and turning them into runnable tests in nine languages. You describe what the software should do — the domain objects, the business rules, the scenarios, each illustrated by a table of examples — and AlignThree generates the test code and the templates for the glue code that connects it to your production classes.

The specification is the source of truth. The tests are generated from it.

Why

A specification that cannot be executed drifts.

It is written before the code, consulted during, and quietly falsified afterwards — and nothing tells you when that happened. The usual answer is to write the examples twice: once in prose for people, once in test code for the machine. Two artefacts, one intent, and no mechanism keeping them honest with each other.

Executable specification collapses that into one artefact. The examples the team agreed on are the test suite, so a specification that has gone stale fails the build rather than sitting there misleading the next reader. AlignThree takes a particular position on how to do that:

Tables, not prose

Business rules are usually easier to agree on as a table of cases than as sentences. A column heading with six rows underneath makes the boundary cases visible and the missing case conspicuous — exactly the conversation worth having before any code is written.

A domain model in the specification

The spec declares its own types: Entity, Collection, DataType, Attributes. That declaration is what makes everything else possible — type checking, generated conversion, cross-file analysis, and a spec that reads in the domain's own vocabulary.

Generation, not binding

The types you declared become real classes in your language, and each step becomes a test method. Wiring is done by the generator, at build time, where mistakes are compile errors rather than surprises at 3am.

The format in brief

Plain text, in your repository.

A .spectable file diffs, merges and reviews like code, because it is a text file sitting beside everything else. Entities and collections declare the vocabulary; scenarios read top to bottom as narrative; business rules carry their examples with them.

Full syntax reference →

ShoppingCart.spectable
Specification Shopping Cart

Entity CatalogItem
| Attribute | Type       | Default | Notes |
| Name      | SimpleText | NoName  |       |
| Price     | Dollar     | 1       |       |

Collection Catalog
| DataType    | Minimum | Maximum  | Notes          |
| CatalogItem | 0       | 10000000 | Each is unique |

Scenario Add items
Given item collection is : OrderItemCollection
| Name | Price | Quantity | ItemTotal |
When item added : OrderItem Vertical
| Name     | Widget |
| Quantity | 2      |
Then item collection is : OrderItemCollection
| Name   | Price  | Quantity | ItemTotal |
| Widget | $10.00 | 2        | $20.00    |

BusinessRule Total Cart Price
Description How to Apply Discount and Shipping
Examples: CartInput
| TotalItems | Shipping | Discount | Total Price |
| $110       | $5       | $11      | $104        |
| $80        | $5       | $4       | $81         |

Why it is useful

What you get in practice.

One specification, nine languages

The same .spectable drives a Java team and a Go team. Polyglot systems get one agreed description of behaviour instead of one per stack — Java, C#, Python, Go, Rust, Swift, JavaScript, TypeScript and C++.

Errors surface before you run anything

Analyze reports unknown types, duplicate scenario names, =Value references with no Define, and table rows whose column count does not match the header — across every file in the solution.

You cannot silently skip a step

Every generated glue stub ends in a failure, so an unimplemented step is red, never a false green.

Your code is never overwritten

Glue methods are created once and only ever appended to; the developer inserts calls to the appropriate production code. Production classes are written only when the type does not already exist anywhere in the folder, and can be used as the real production classes with changes as needed.

The examples stay readable

Simulate Scenario expands a scenario the way it will actually run, with Background folded in and =Define references resolved.

Where it comes from

Three ideas that already worked.

AlignThree is a recombination of three ideas, none of them new, each borrowed for a different reason.

FIT · 2002

The table as the unit of agreement

Ward Cunningham's Framework for Integrated Test established that a table of examples is a better medium for agreeing on a business rule than a paragraph describing it. SpecTable takes the table wholesale: a BusinessRule with an Examples: block is FIT's ColumnFixture in a different notation.

Gherkin · 2008

The scenario as narrative

Cucumber contributed Given / When / Then: a shape for describing behaviour over time that non-programmers can read and, more importantly, collaborate on. SpecTable keeps the keywords and the discipline.

DDD · 2003

The vocabulary

Eric Evans' Domain-Driven Design supplied the model. Entity, DataType, Collection and DomainTerm are DDD's terms, used deliberately: the specification is where the ubiquitous language is written down.

How it differs from FIT

FITSpecTable
FormatHTML or wiki pagesplain text — diffs, merges, reviews like code
Bindingfixtures written by hand, matched by reflection at run timetest and glue generated at build time
Typesnone; cells are strings a fixture interpretsdeclared in the spec, with generated conversion
Languagesa fixture per language, written per languagenine targets from one source
Narrativetables onlytables and Given/When/Then scenarios

How it differs from Gherkin

Gherkin is untyped

Every value is a string until a step definition parses it, and each definition re-does that parsing by hand. SpecTable declares the types once, in the spec, and generates the conversion.

Binding by name, not regex

A Cucumber step matches a sentence by pattern; reword it and the binding breaks, sometimes silently. SpecTable derives a method name from the step, so the connection is an identifier the compiler checks.

Tables are primary

Gherkin's data tables are attachments to a sentence. In SpecTable a step names the attribute set describing its table — When item added : OrderItem — so the table's shape is declared and checked, not inferred at run time.

There is a model, not just steps

SpecTable's declarations are project-wide, which is what makes Go to Definition, Find All References, rename and cross-file analysis possible at all.

What Gherkin does better: it reads like English, and that matters. Anyone can read a .feature file aloud in a meeting. SpecTable's tables ask a little more of the reader in exchange for being checkable — a real trade, and the wrong one if your audience will not read a table.

What gets generated

Yours stays yours.

common/ is rewritten on every build; never edit it. Glue and production code are yours and are never overwritten — glue methods are appended to, and a production stub is written only when that type does not already exist anywhere in the folder.

<outputDirectory>/
  common/          generated value classes — XString, XTyped, and an index
  <Spec>_Test      the tests
  <Spec>_glue      the glue — where you write code
production/        stubs for your production classes