# Generating Test Cases from OpenSpec

If your project describes behavior with [OpenSpec](https://github.com/Fission-AI/OpenSpec) specifications, SpeQA can turn selected scenarios into test cases. Choose one `.tc.md` per scenario or one per requirement, then refine the generated cases in the SpeQA editor.

Generation is deterministic: it follows fixed rules, works offline, and does not use AI. The same spec, selection, mode, and defaults produce the same test cases.

## Which Files Are Supported

SpeQA recognizes a file as an OpenSpec specification when it is named `spec.md` and lives under a `specs` folder inside an `openspec` folder. Both stable specs and change deltas work:

- `openspec/specs/auth/login/spec.md`
- `openspec/changes/add-sso/specs/auth/login/spec.md`

Other Markdown files, such as `docs/spec.md` or `openspec/specs/auth/README.md`, are not affected and show no generation controls.

## Starting the Generation

There are two entry points. Both open the same dialog, only the initial selection differs.

- **Gutter icon** - open a spec and click the SpeQA icon next to a header:
  - next to `## Requirements`, `## ADDED Requirements`, or `## MODIFIED Requirements` - all scenarios in that section are selected. These headings are matched without regard to case; empty sections and `REMOVED` / `RENAMED` sections have no icon;
  - next to `#### Scenario:` - only that scenario is selected;
  - next to `### Requirement:` - all scenarios of that requirement are selected.
- **Context menu** - in the Project View, right-click a recognized `spec.md` or its capability folder when that folder directly contains the spec, open **New**, and choose **SpeQA Test Cases from Spec…**. The dialog selects all scenarios. Inside the editor, right-click the open spec and choose **Generate SpeQA Test Cases from Spec…**. Preselection follows the most specific caret context: the current scenario, its requirement, or the eligible section header or introductory text before the first requirement. If the caret is elsewhere, all scenarios are selected.

The action has no default keyboard shortcut. You can assign one in **Settings > Keymap**.

## The Generation Dialog

The **Generate SpeQA Test Cases** dialog shows:

- **One case per** - a drop-down next to **Select all** and **Clear** above the tree. Choose **Scenario** for one test case per scenario or **Requirement** for one test case per requirement. The choice is remembered for the project and starts with **Scenario**.
- **Requirements and scenarios** - a tree with a checkbox for every requirement and scenario. Each scenario shows how many steps it will produce. A scenario without any `WHEN` or `THEN` clause is marked **No WHEN or THEN clauses**; you can still generate it, and it gets one empty step. When the dialog opens, every requirement with a preselected scenario is expanded and the others stay collapsed. The first preselected scenario is selected and scrolled into view, so you can toggle it with Space right away.
- **Select all** and **Clear** buttons for quick selection.
- **Destination folder** - where the files are saved. The default is `test-cases/<capability>/`, for example `test-cases/auth/login/` for `openspec/specs/auth/login/spec.md`. Use the browse button to pick another folder. The folder must be inside the project; otherwise the dialog shows an error and **Create** stays disabled. A missing folder is created automatically.
- **exists, will be overwritten** - appears next to an existing scenario file in per-scenario mode, or on a requirement row with a selected scenario in per-requirement mode.
- A summary next to the **Create** and **Cancel** buttons, for example **3 will be created, 1 overwritten**. It counts output files, not scenarios.

Scenarios under `## REMOVED Requirements` and `## RENAMED Requirements` in change deltas are not listed.

Click **Create** to generate the files. The button is disabled while nothing is selected.

## How a Scenario Becomes a Test Case

In **One test case per scenario** mode, each selected scenario creates a separate file and is mapped field by field:

| In the spec | In the test case |
|-------------|------------------|
| Scenario name | **Title** and the file name |
| Requirement name and statement | **Description** |
| Path to the spec | A **Links** entry that opens the spec |
| `GIVEN` and the `AND` clauses after it | **Preconditions**, one bullet per clause |
| `WHEN` | Starts a new step; its text is the step **Action** |
| `AND` after `WHEN`, before `THEN` | Another line of the same action |
| `THEN` | The **Expected result** of the current step |
| `AND` / `BUT` after `THEN` | More lines of the expected result |

A few more rules:

- Several `WHEN` / `THEN` pairs in one scenario produce several steps.
- A `THEN` without a preceding `WHEN` creates a step whose action is the scenario name.
- Bold keyword markers such as `**WHEN**` are removed; any other inline Markdown in the clause text is kept.
- **Priority**, **Status**, and **Environment** come from the SpeQA defaults in **Settings > Tools > SpeQA** (Normal and Draft unless you changed them). If no default environments are set, the file has no `environment` field.
- **Tags** contain the last segment of the capability path, for example `login` for `auth/login`.
- Each new case gets the next free ID.

The spec link is titled with the spec path from the project root and points to the spec with a path relative to the test case file. Click it in the **Links** section of the preview to open the spec in the IDE, or `Cmd`+click (`Ctrl`+click on Windows and Linux) it in the Markdown editor. When you create a test run with **Links** imported, the link is adjusted so it still opens the spec from the run file.

## One Test Case per Requirement

In **One test case per requirement** mode, one file is created for each requirement with at least one selected scenario:

- The case title and filename come from the requirement name. The description contains the requirement statement, if present.
- Selected scenarios contribute steps in document order. A scenario with several `WHEN` clauses contributes several consecutive steps.
- The first step of each scenario has a step-level **Links** entry titled with the scenario name. Use that link to open the corresponding scenario in the source spec; other steps of that scenario have no boundary link.
- If all selected scenarios have the same ordered `GIVEN` clauses, they appear once in **Preconditions**. If their `GIVEN` lists differ, each scenario's clauses move to the beginning of that scenario's first step action as `Given …` and `And …` lines, followed by the original action. Scenarios without `GIVEN` clauses keep their action unchanged. If all scenarios have no `GIVEN` clauses, no **Preconditions** block is written.
- A requirement with one selected scenario still creates one case titled with the requirement name.

The generated case does not add scenario headings or use the word `Scenario` as scenario content. The required `Scenario:` format marker remains unchanged.

## Example

This scenario in `openspec/specs/auth/login/spec.md`:

```markdown
### Requirement: User login

The system SHALL let registered users sign in with an email and a password.

#### Scenario: Successful login

- **GIVEN** a registered user
- **AND** the user is signed out
- **WHEN** the user submits a valid email and password
- **THEN** the dashboard opens
- **AND** the user's name appears in the header
```

produces `test-cases/auth/login/successful-login.tc.md`:

```markdown
---
id: 12
title: "Successful login"
priority: normal
status: draft
tags:
  - "login"
---

Requirement: User login

The system SHALL let registered users sign in with an email and a password.

Links:

[openspec/specs/auth/login/spec.md](../../../openspec/specs/auth/login/spec.md)

Preconditions:

- a registered user
- the user is signed out

Scenario:

1. the user submits a valid email and password
   > the dashboard opens
   > the user's name appears in the header
```

## Example: One Test Case per Requirement

Suppose the `User login` requirement has two selected scenarios with different `GIVEN` clauses. SpeQA creates `test-cases/auth/login/user-login.tc.md`:

```markdown
---
id: 12
title: "User login"
priority: normal
status: draft
tags:
  - "login"
---

The system SHALL let registered users sign in with an email and a password.

Links:

[openspec/specs/auth/login/spec.md](../../../openspec/specs/auth/login/spec.md)

Scenario:

1. Given a registered user
   And the user is signed out
   The user submits a valid email and password
   > The dashboard opens
   > The user's name appears in the header

   Links: [Successful login](../../../openspec/specs/auth/login/spec.md)

2. Given a registered user
   The user submits a wrong password
   > An error is shown

   Links: [Wrong password](../../../openspec/specs/auth/login/spec.md)
```

If the selected scenarios had identical `GIVEN` lists instead, those clauses would appear once in **Preconditions**, not in the step actions.

## File Names

In per-scenario mode, the file name is the scenario name in lowercase, with every run of characters other than letters and digits replaced by `-`, plus `.tc.md`. "Successful login" becomes `successful-login.tc.md`. In per-requirement mode, the requirement name determines the file name; "User login" becomes `user-login.tc.md`. If selected scenarios or requirements produce the same name in one run, the later files get `-2`, `-3`, and so on.

## Overwriting Existing Cases

A file is treated as already generated when the output filename exists in the destination folder. If the selection includes such files, SpeQA lists them and asks what to do:

- **Overwrite** - replace the existing files with freshly generated ones. Each overwritten file **keeps its ID**, so existing test runs still point to it.
- **Skip existing** - leave the existing files untouched and create only the new ones.
- **Cancel** - write nothing.

Overwriting replaces any manual edits you made in those files. In per-requirement mode, it also replaces the entire case with only the scenarios selected in the current dialog; scenarios that were not selected are removed from that generated case. Commit your changes to Git first if you want to compare or restore them.

## After Generation

- The first created test case opens in the editor.
- A notification reports the result, for example **Created 3 test cases in test-cases/auth/login**.
- All files are written as one command, so a single **Undo** reverts the whole batch.

Generation waits until the IDE finishes indexing, because IDs are assigned from the project index.

## Limitations

- Generation is one-way. Changing the spec later does not update the test cases; generate again and choose **Overwrite** or **Skip existing**.
- One spec at a time. A Project View folder selection resolves only its direct `spec.md`; folders that contain specs only in descendants are not searched.

## Generation or the Claude Code Skill?

| | OpenSpec generation | [Test Case Writer skill](/speqa/claude-code-skills/index.md) |
|---|---|---|
| Input | OpenSpec `spec.md` scenarios | Specs, tickets, user stories, PR descriptions |
| How it works | Fixed mapping rules, offline | AI writes and expands the cases |
| Result | Predictable cases, one per scenario or requirement | Richer cases, may add negative and edge scenarios |

You can combine both: generate test cases from the spec, then ask Claude Code to refine them.

## What's Next?

- [Refine the generated cases](/speqa/writing-test-cases/index.md) in the split editor
- [Run the test](/speqa/running-tests/index.md) and record results
- Browse the generated cases in the [tool window](/speqa/tool-window/index.md)
