---
title: "Gherkinとは？構文の全キーワードと.featureファイルの書き方・実行例"
url: "https://www.issoh.co.jp/tech/details/11693/"
published: 2026-04-07
updated: 2026-10-17
categories: ["テスト"]
publisher: "株式会社一創"
---

# Gherkinとは？構文の全キーワードと.featureファイルの書き方・実行例

Gherkin（ガーキン）は、BDD（振る舞い駆動開発）で仕様を書くための言語で、人が読める平文のまま自動テストとして実行できます。この記事はCucumber公式のGherkinリファレンスと、パーサ本体の言語定義ファイル `gherkin-languages.json` を一次情報に、全キーワード・.feature の書き方・日本語ロケール・PythonとTypeScriptでの実行手順をまとめました。構文の可否は公式パーサ（@cucumber/gherkin 42.0.1）に読ませて確かめています。

## まとめ：Gherkinのキーワード・書き方・実行の要点

- キーワードの正本は `gherkin-languages.json` です。英語では Feature・Rule・Background・Scenario・Scenario Outline・Examples とステップ系5種の計11種が登録されています。
- 1つの .feature に書ける Feature は1つ、Background は Feature または Rule ごとに1つです。2つ目を書くと公式パーサはエラーを返します。
- CucumberはステップのGiven・When・Thenを照合に使いません。一方、pytest-bdd と behave はキーワードの種別まで照合するので、同じ .feature でも動き方が違います。
- 先頭行に `# language: ja` を書けば「機能」「前提」「もし」「ならば」で書けます。英語の `Given` を混ぜると、位置によってはエラーにならず説明文として扱われ、ステップとしては実行されません。
- Examples の無い Scenario Outline もパースは通り、`<数量>` が置換されないまま未定義ステップとして残ります。
- 2026年10月17日時点の最新版は Cucumber-JVM 8.0.4、cucumber-js 13.3.0、pytest-bdd 9.0.0、behave 1.3.3、Reqnroll 3.3.4 です。.NETのSpecFlowは2024年12月31日にEOLを迎えています。

## Gherkinの全キーワードと.featureファイルの基本構造

Gherkinの語彙は、パーサのリポジトリにある [gherkin-languages.json](https://github.com/cucumber/gherkin/blob/main/gherkin-languages.json) という1つのJSONファイルで決まります。ここに無い語はキーワードとして解釈されません。条件分岐やループといった制御構文は持たず、仕様の記述だけに用途を絞った言語です。英語（en）の定義は次の11種で、全ステップ共通の別名としてアスタリスクが加わります。

| キーワード              | 分類   | 日本語（ja）    | 役割              |
| ------------------ | ---- | ---------- | --------------- |
| Feature            | 宣言   | 機能／フィーチャ   | ファイルの主題。1ファイル1つ |
| Rule               | 宣言   | ルール        | 業務ルール単位のシナリオ群   |
| Example／Scenario   | 宣言   | シナリオ       | 具体例1件           |
| Background         | 宣言   | 背景         | 各シナリオ前の共通Given  |
| Scenario Outline   | 宣言   | シナリオアウトライン | 値を差し替える雛形       |
| Examples／Scenarios | 宣言   | 例／サンプル     | Outlineに流し込む値の表 |
| Given              | ステップ | 前提         | 前提となる状態         |
| When               | ステップ | もし         | 検証対象の出来事        |
| Then               | ステップ | ならば        | 期待される結果         |
| And                | ステップ | かつ／且つ      | 直前ステップの継続       |
| But                | ステップ | しかし／但し     | 否定方向の継続         |

英語のFeatureには「Business Need」「Ability」という別名もあり、Example と Scenario、Scenario Outline と Scenario Template、Examples と Scenarios はそれぞれ同義です。アスタリスクは Given／When／Then／And／But のどれの代わりにも使え、「`* 商品「A100」がある`」のように列挙を並べるときにAndの連続を避けられます。記号では、三重引用符とバッククォート3つがドキュメント文字列、縦棒がデータテーブル、アットマークがタグ、シャープがコメントです。

### Feature・Rule・Scenarioの入れ子と1ファイル1Featureの制約

.feature ファイルは、Feature宣言を頂点にBackgroundとRule、その下にシナリオが並ぶ入れ子です。次の例は公式パーサでエラーなく読めることを確認しています。

```
# features/cart.feature
Feature: ECサイトのカート
  会員が在庫のある商品をカートへ入れて購入できること

  Background:
    Given 会員「tanaka」がログインしている

  Rule: 在庫がある商品だけカートに入る

    Background:
      Given 決済手段に「クレジットカード」を登録している

    Example: 在庫のある商品をカートに追加する
      Given 商品「A100」の在庫が 3 個ある
      When 商品「A100」をカートに 1 個追加する
      Then カートの点数は 1 になる

    Example: 在庫切れの商品はカートに入らない
      Given 商品「B200」の在庫が 0 個ある
      When 商品「B200」をカートに 1 個追加する
      Then 「在庫がありません」と表示される
```

[公式リファレンス](https://cucumber.io/docs/gherkin/reference/)は「You can only have a single `Feature` in a `.feature` file.」と明記しています。2つ目の `Feature:` 行を書くと、パーサは `(5:1): expected: #EOF, … got 'Feature: B'` のように行番号付きのエラーを返しました。機能が増えたらファイルを分ける前提の設計です。

Feature名やScenario名の下には自由記述の説明文を置けます。Featureの説明文は Background・Rule・Example・Scenario Outline の行で終わり、Scenarioの説明文は最初のステップ行で終わります。そのためFeatureの説明文の途中に `Given …` と書くと、パーサはエラーを出さずに説明文の一部として格納しました。公式リファレンスは説明文を「as long as no line starts with a keyword」と定めているだけで、パーサは違反を検出しません。書いたはずのステップが実行されないときは、最初の Background・Rule・Scenario より前に紛れ込んでいないかを見てください。

### BackgroundとRuleによる共通前提の集約

Backgroundは、後続の各シナリオの直前に毎回実行されるGivenの集まりです。公式リファレンスは実行順を「run before each scenario, but after any Before hooks」と説明しており、Beforeフックの後に流れます。

置ける数は「You can only have one set of `Background` steps per `Feature` or `Rule`.」のとおり1階層に1つで、同じ階層に2つ並べるとパーサは2つ目の `Background:` 行でエラーを返します。前提が2系統に分かれるなら、Featureを分ける前にRuleで割ります。上の例のように Feature直下とRule直下のBackgroundは併存でき、Rule内のシナリオは両方を上から順に実行します。ログイン状態のような全体共通の前提を上、決済手段のようなRule固有の前提を下に置きます。

### Given・When・Thenの照合規則のフレームワーク差

公式リファレンスには「Keywords are not taken into account when looking for a step definition.」とあり、Cucumberはステップ定義を探すときキーワードを見ません。cucumber-js 13.3.0 で確かめると、`Given('残高が {int} 円である')` だけを定義した状態で `Then 残高が 1000 円である` の行も同じ関数で実行されました。Given と Then の両方に同じ文言を定義すると、どちらの行も「Multiple matching step definitions found」で Ambiguous になります。

ところがPythonの2つは逆です。同じ .feature と Given だけの定義で実行すると、pytest-bdd 9.0.0 は `StepDefinitionNotFoundError: Step definition is not found: Then "残高が 1000 円である"` で失敗し、behave 1.3.3 も Then 行を undefined と報告しました。どちらもステップを given・when・then の種別ごとに登録しているためです。種別を問わない定義は、pytest-bdd と behave とも `@step` デコレータで書けます。

| フレームワーク            | Givenだけ定義してThen行を実行         | 同じ文言をGivenとThenで定義 |
| ------------------ | --------------------------- | ------------------ |
| cucumber-js 13.3.0 | Givenの定義で実行される              | Ambiguousで失敗       |
| pytest-bdd 9.0.0   | StepDefinitionNotFoundError | 種別ごとに別の定義になる       |
| behave 1.3.3       | undefined                   | 種別ごとに別の定義になる       |

Cucumber系では3語の使い分けは読み手のためのもので、間違えても実行結果は変わりません。その代わり、状態を作る文と結果を確かめる文を同じ言い回しにすると定義が衝突します。前提側は「残高を1000円に設定する」、検証側は「残高が1000円と表示される」と動詞まで書き分けてください。Python系では逆にキーワードが意味を持つので、Cucumber前提で書いた .feature を流用するときは And・But が直前のどの種別に続いているかまで確認が要ります。

## 複数条件・長文テキスト・タグを扱う補助構文

値だけ変えて同じ振る舞いを確かめる、表や長文をステップに渡す、CIで一部だけ流す。この3つは別々の補助構文で書きます。縦棒で書く表が2種類あるので取り違えに注意してください。

### Scenario OutlineとExamplesによるパラメータ化

Scenario Outlineは値の入る位置を山括弧のプレースホルダで書き、Examplesの表から1行ずつ流し込みます。表の見出し行の名前がプレースホルダ名に対応します。

```
Scenario Outline: 購入数量に応じた送料判定
  Given 商品「A100」を <数量> 個カートに入れている
  When 送料を計算する
  Then 送料は <送料> 円になる

  Examples:
    | 数量 | 送料 |
    | 1    | 500  |
    | 9    | 500  |
    | 10   | 0    |
```

9個までは500円、10個から無料という境界が表を見るだけで伝わり、境界値を並べる用途に向いています。逆に、行ごとに期待結果の意味が変わる場合は使わないでください。「10個なら送料0円」と「在庫切れならエラー」を1つの表に混ぜると、失敗したときにどの仕様が壊れたのか読み取れません。

注意したいのは、Examples を書き忘れたときの挙動です。公式リファレンスは「A `Scenario Outline` must contain one or more `Examples`」と書いていますが、パーサはこれをエラーにしません。cucumber-js 13.3.0 で実行すると、プレースホルダが `商品「A100」を <数量> 個カートに入れている` という文字列のまま1件のシナリオになり、未定義ステップ（undefined）として報告されました。通常の実行では終了コード1で落ちるので気づけますが、後述の `--dry-run` では落ちません。

### データテーブルとドキュメント文字列のエスケープ規則

データテーブル（Data Tables）は1つのステップに表形式の値を渡す構文、ドキュメント文字列（Doc Strings）は三重引用符で囲んだ長文を渡す構文で、どちらもステップ定義の最後の引数になります。Examplesの表がシナリオを行数ぶん複製するのに対し、こちらは1回のステップに値をまとめて渡します。

```
Scenario: 複数会員への一括通知
  Given 次の会員が登録されている:
    | 氏名 | メール             |
    | 田中 | tanaka@example.com |
    | 佐藤 | sato@example.com   |
  When 管理者が次の本文で通知する:
    """json
    {
      "title": "メンテナンスのお知らせ",
      "stop": "2:00-4:00"
    }
    """
  Then 2通のメールが送信される
```

セル内で特別な意味を持つ文字はエスケープします。パーサに読ませると、`a\|b` は「a|b」、`1行目\n2行目` は改行入りの文字列、`c\\d` は「c\\d」として渡りました。ドキュメント文字列は開始の三重引用符の桁を基準に各行が字下げを外され、それより深いインデントは残ります。JSONやYAMLを渡すときは、この桁位置がそのまま値になります。開始記号の直後に `json` のように書くとメディアタイプとして記録され（パース結果の `mediaType`）、三重引用符の代わりにバッククォート3つも使えます。

Pythonでは版による違いがあります。[pytest-bdd 9.0.0 の変更履歴](https://github.com/pytest-dev/pytest-bdd/blob/master/CHANGES.rst)は、データテーブルとExamplesのセル内のバックスラッシュが過剰にエスケープされていた不具合を直したとし、「If you compensated by doubling backslashes in feature files, undo that.」と書いています。8系でバックスラッシュを重ねて回避していた .feature は、9.0.0へ上げると値が変わるので、重ねた分を戻してください。

### タグの付け方と継承・CIでの絞り込み

アットマークで始まるタグは Feature・Rule・Scenario・Scenario Outline・Examples に付けられ、実行対象の絞り込みに使います。付けられない場所も決まっており、[Cucumberの公式ドキュメント](https://cucumber.io/docs/cucumber/api/#tags)は「It is _not_ possible to place tags above `Background` or steps」と明記しています。実際にBackgroundやステップ行の上へ `@setup` を書くと、パーサは次の行で `expected: #TagLine, #RuleLine, #Comment, #Empty, got 'Background:'` を返しました。

タグは配下へ継承されます。Feature・Rule・Outlineに1つずつ、2つあるExamplesの片方にだけ `@smoke` を付けてコンパイル結果を見ると、`@smoke` 側の行は4つ、もう一方の行は3つのタグを持っていました。Examplesに付けたタグは、その表の行にしか効きません。

タグは `@smoke` の速度軸、`@checkout` のドメイン軸、`@wip` の状態軸に分けておくと、プルリクエストではスモークだけ、夜間は全件と切り替えられます。ディレクトリは仕様の置き場所、タグは実行の切り口と役割を分けると、数百件になっても所在を見失いません。スモークに入れる範囲は[スモークテストとは？CI/CDへの組み込みと対象選定・失敗時の判断を実装者向けに解説](/tech/details/16256/)、CI側の設定は[GitHub Actionsでビルド・自動テストを設定する方法｜CI/CDワークフローの作り方](/tech/details/2497/)で扱っています。

## 日本語ロケールでGherkinを書く設定と対応キーワード

Gherkinは1行目の `# language:` ヘッダで使う言語を切り替えます。公式リファレンスは「A `# language:` header on the first line of a feature file tells Cucumber what spoken language to use」と説明しており、日本語なら `# language: ja` です。2026年10月17日時点で `gherkin-languages.json` には80言語の定義があります。

```
# language: ja
機能: パスワード再設定

  背景:
    前提 利用者「tanaka」が登録済みである

  ルール: 登録済みのメールアドレスにだけ再設定リンクを送る

    シナリオ: 登録済みメールで再設定リンクを受け取る
      もし 「tanaka@example.com」宛に再設定を申請する
      ならば 送信されたメールは 1 通である

    シナリオ: 未登録メールでは送信しない
      もし 「unknown@example.com」宛に再設定を申請する
      ならば 「登録がありません」と表示される
      しかし 送信されたメールは 0 通である
```

日本語の定義には別名が複数あり、機能は「フィーチャ」、シナリオアウトラインは「シナリオテンプレート」「テンプレ」「シナリオテンプレ」、Examplesは「例」「サンプル」、Andは「且つ」、Butは「但し」「然し」「ただし」でも通ります。Ruleは「ルール」です。

英語と日本語のキーワードは1ファイル内で混ぜられませんが、混ぜたときの壊れ方は2通りあります。ステップの途中に `When 再設定を申請する` を挟むと、パーサはその行で `expected: … got 'When 再設定を申請する'` のエラーを返しました。ところが `シナリオ:` の直後、最初のステップより前に `Given 利用者が登録済みである` を書くと、エラーにならずシナリオの説明文として格納され、ステップは後続の「もし」1つだけになりました。前提が丸ごと消えたまま、テストは何事もなく実行されます。英語の .feature を日本語へ書き換えるときは、キーワードの残りを `grep -n -E "^\s*(Given|When|Then|And|But) "` で洗い出してください。公式は「ドメインの専門家が話す言語で書き、翻訳は避ける」立場で、読み手が日本語話者なら最初から日本語で書くほうが保守しやすくなります。

## 要求から具体例を出してシナリオを書く手順

手順は、要求1つに対して具体例を先に出し、それを前提・出来事・結果に割り振る順です。

### 具体例の前提・出来事・結果への割り振り

「パスワードを再設定できる」という要求だけでは、何が起きれば完成なのかが決まりません。最初に「tanakaさんが登録済みのメールで申請したら、リンク付きのメールが1通届く」という正常な具体例を1つ書きます。次に「未登録のメールなら送らない」「リンクの有効期限を1秒過ぎたら使えない」のように、結果が変わる例を足します。異常系と境界値は、正常系の前提か出来事を1つだけ変えて作ると漏れにくくなります。

割り振りの基準は単純です。Givenには出来事の前に成り立っている状態、Whenには結果を起こす出来事を1つ、Thenには外から観測できる結果を書きます。公式リファレンスも結果は「observable」な出力で確かめ、データベースのレコードのような内部の状態は避けるよう求めており、1つの例のステップ数は「we recommend 3-5 steps per example」としています。1つのシナリオにWhenが2つ以上あるなら、たいていシナリオを分けるべきサインです。出てきた具体例のうち、業務上の決まりごとが同じものは1つのRuleにまとめ、Rule名にその決まりを文章で書きます。上の日本語の例で「登録済みのメールアドレスにだけ再設定リンクを送る」をRule名にしたのがこの形です。

### 画面操作でなく振る舞いを書く宣言的スタイル

Cucumber公式の [Writing better Gherkin](https://cucumber.io/docs/bdd/better-gherkin/) は、宣言的（declarative）なスタイルを勧め、命令的（imperative）なスタイルについて「because they are so closely tied to the mechanics of the current UI, they often require more work to maintain」と書いています。「メールアドレス欄に入力する」「送信ボタンをクリックする」と画面操作を並べたシナリオは、ボタンの位置が変わるだけで全件の書き直しになり、文言が変わるのでステップ定義の対応付けもやり直しです。

Whenに書くのは「再設定を申請する」のように、画面が変わっても意味が変わらない利用者の出来事です。どの欄に何を入れるかは、[Seleniumの使い方｜Selenium 4でWebDriverの手動設定が不要になった書き方](/tech/details/4241/)で扱うようなドライバのコードとしてステップ定義の側に閉じ込めます。

## PythonとTypeScriptで.featureを動かす手順

.feature は各言語のフレームワークがステップ定義と結び付けて実行します。上の日本語の .feature と送料の Outline を、PythonとTypeScriptで動かした手順です（Node.js 26.5.0／Python 3.12、2026年10月17日）。

### pytest-bdd 9.0.0による日本語.featureの実行

pytest-bdd 9.0.0 はPython 3.10以上が必要で、インストールすると公式パーサの `gherkin-official` が依存（29.0.0以上）として入り、2026年10月17日時点では42.0.1が入りました。上の日本語の .feature を `features/password_reset.feature` に置き、テストファイルを次のように書きます。

```
# tests/test_password_reset.py
import pytest
from pytest_bdd import scenarios, given, when, then, parsers

scenarios("../features/password_reset.feature")

REGISTERED = {"tanaka": "tanaka@example.com"}


@pytest.fixture
def ctx():
    return {"sent": [], "message": None}


@given(parsers.parse("利用者「{name}」が登録済みである"))
def registered_user(name):
    assert name in REGISTERED


@when(parsers.parse("「{email}」宛に再設定を申請する"))
def request_reset(ctx, email):
    if email in REGISTERED.values():
        ctx["sent"].append(email)
    else:
        ctx["message"] = "登録がありません"


@then(parsers.parse("送信されたメールは {count:d} 通である"))
def sent_count(ctx, count):
    assert len(ctx["sent"]) == count


@then(parsers.parse("「{message}」と表示される"))
def shown(ctx, message):
    assert ctx["message"] == message
```

```
$ pip install pytest-bdd==9.0.0
$ pytest -v
tests/test_password_reset.py::test_登録済みメールで再設定リンクを受け取る PASSED [ 50%]
tests/test_password_reset.py::test_未登録メールでは送信しない PASSED     [100%]
============================== 2 passed in 0.18s ===============================
```

`scenarios()` が .feature の全シナリオをpytestのテスト関数に変換し、シナリオ名が関数名になります。「しかし」の行は直前の「ならば」に続くので then として照合され、Rule と背景も含めて通りました。状態はfixtureで受け渡します（fixtureの書き方は[pytestの使い方と書き方｜fixture・parametrize・docstringの扱いまで【9.1対応】](/tech/details/7527/)）。

### cucumber-js 13.3.0によるTypeScriptステップ定義の実行

cucumber-js 13.3.0 の対応Node.jsは22・24・26以上です。送料の Outline を、先頭に `Feature: 送料` の1行を足して `features/shipping.feature` に置き、ステップ定義をTypeScriptで書きます（Scenario Outline から始まるファイルは1行目でパースエラーになります）。

```
// features/steps/shipping.steps.ts
import { Given, When, Then } from '@cucumber/cucumber';
import assert from 'node:assert/strict';

let qty = 0;
let fee = -1;

Given('商品「A100」を {int} 個カートに入れている', (n: number) => { qty = n; });
When('送料を計算する', () => { fee = qty >= 10 ? 0 : 500; });
Then('送料は {int} 円になる', (expected: number) => { assert.equal(fee, expected); });
```

```
$ npm i -D @cucumber/cucumber@13.3.0
$ npx cucumber-js --import 'features/steps/*.ts'
.........

3 scenarios (3 passed)
9 steps (9 passed)
```

`{int}` はCucumber Expressionsの型指定で、Examplesの値が数値として渡ります。公式の [TypeScriptの手順](https://github.com/cucumber/cucumber-js/blob/main/docs/transpiling.md)は tsx での変換を勧めていますが、Node.js 26.5.0 は型注釈を取り除いて実行する機能（type stripping）が既定で有効なため、package.json に `"type": "module"` を書けば tsx なしに .ts を読み込めました（書かなくても MODULE\_TYPELESS\_PACKAGE\_JSON の警告が出たうえで読み込まれます）。ただし `enum` のように型の除去だけでは済まない構文はNode.jsが実行時にエラーにするので、使うなら tsx を入れます。状態を外の変数に置いたのは、アロー関数では `this` でWorldを参照できないためです。Javaでの構成やPlaywrightとの組み合わせは[Cucumberとは？Java・JavaScriptでのテスト自動化の手順とCucumber 8.0の変更点](/tech/details/3639/)で扱っています。

### 生成AIが書いた.featureの実行前検査

生成AIが書いた .feature の「英語キーワードが説明文に飲まれる」「Examples が無い」といった壊れ方は、目で読んでも見落としやすい種類です。cucumber-js の `--dry-run` は、テストを実行せずにパースとステップ定義の照合だけを行います。次は、日本語の .feature のステップ途中に英語の `When` を混ぜたファイル（`features/ng_mix_lang2.feature`）を置いて流した結果です。

```
$ npx cucumber-js --dry-run --import 'features/steps/*.ts'
Parse error in "features/ng_mix_lang2.feature" (5:5): expected: #EOF, #TableRow, … got 'When 再設定を申請する'
$ echo $?
1
```

構文エラーは終了コード1で止まるので、CIの最初の段に置けます。一方、[公式ドキュメント](https://github.com/cucumber/cucumber-js/blob/main/docs/dry%5Frun.md)のとおり「Undefined and ambiguous steps are reported, but don’t cause the process to fail」で、未定義ステップは一覧に出ても終了コードは0でした。Examples の書き忘れや言い回しの揺れまで止めたいなら、dry-run の出力に `Undefined scenarios` が含まれるかを別途判定するか、通常の実行で落とします。説明文に飲まれた英語行はどちらでも検出されないため、先ほどの grep を併用してください。

## 主要BDDフレームワークのGherkin対応と選定基準

同じ .feature がどのフレームワークでも読めるとは限らず、特にRuleは対応時期に差があります。2026年10月17日に各レジストリで確認した版は次のとおりです。

| フレームワーク       | 言語                    | 最新版    | Rule対応  | 確認元           |
| ------------- | --------------------- | ------ | ------- | ------------- |
| Cucumber-JVM  | Java                  | 8.0.4  | 対応      | Maven Central |
| cucumber-js   | JavaScript／TypeScript | 13.3.0 | 7.0.0以降 | npm           |
| Cucumber Ruby | Ruby                  | 12.0.0 | 対応      | RubyGems      |
| pytest-bdd    | Python                | 9.0.0  | 8.0.0以降 | PyPI          |
| behave        | Python                | 1.3.3  | 1.3.0以降 | PyPI          |
| Reqnroll      | C#／.NET               | 3.3.4  | 対応      | NuGet         |
| cucumber-rs   | Rust                  | 0.23.0 | 対応      | crates.io     |

Javaは2026年9月公開のCucumber-JVM 8.0でJava 17以上が必須になりました。Pythonは、既存のpytestのfixtureに載せたいなら pytest-bdd、ステップ定義を独立したディレクトリで管理したいなら behave が合います。

### Rule対応の可否で分かれるフレームワークの世代差

Ruleは「The (optional) `Rule` keyword has been part of Gherkin since v6.」のとおりGherkin v6で入ったキーワードで、cucumber-jsは2020年12月21日の7.0.0で対応しました。Pythonの2つは長く未対応で、pytest-bddは2024年11月14日の8.0.0（同時に `# language:` にも対応）、behaveは2018年2月の1.2.6が7年以上最新のままで、2025年8月の1.3.0でようやくRuleに対応しました。

Java側でRuleを使って書いた .feature をPython側で流用し、古いbehaveでパースエラーになるのが起こりやすい事故です（behave 1.2.6 は `Parser failure in state steps, at line 8: "Rule: …"` で読み込みを止めました）。behaveが1.2.6のまま止まっているならRuleを使う前に1.3系へ上げ、キーワード照合の違いもあるので流用する .feature は両方の環境で一度流してください。

### SpecFlow終了後のReqnroll移行の判断材料

.NETは選択の余地がほとんどありません。[Reqnrollの告知](https://reqnroll.net/news/2025/01/specflow-end-of-life-has-been-announced/)は「SpecFlow reached its end-of-life on December 31, 2024.」と書いており、NuGet上のSpecFlow本体も安定版は3.9.74で、その後は4.0.31-betaというプレリリースで更新が止まっています。新規の.NETプロジェクトはReqnrollを使います。

ReqnrollはSpecFlowのコードを元に作られており、[公式の移行ガイド](https://docs.reqnroll.net/latest/guides/migrating-from-specflow.html)は「everything that has worked with SpecFlow also works with Reqnroll」と書いています。変わるのは主に名前で、NuGetパッケージは SpecFlow.\* から Reqnroll.\*（Reqnroll.NUnit など）へ、名前空間は `TechTalk.SpecFlow` から `Reqnroll` へ変わります。設定ファイルは `specflow.json` を `reqnroll.json` に改名します。同じガイドはSpecFlow v4で予定されていた破壊的変更の一覧に「Bindings declared as async void are not allowed. Use async Task instead.」を挙げており、v3系から移るなら `async void` のステップ定義を `async Task` に直す必要があります。互換パッケージ `Reqnroll.SpecFlowCompatibility` を使えば、名前空間の置き換えと `specflow.json` の改名は後回しにできます。

## Gherkinを採用すべきでない場面と判断の分かれ目

分かれ目は「開発者以外が実際に .feature を読んで指摘するか」の一点です。プロダクトオーナーもQAも開かず開発者だけが書いているなら、各言語のテストフレームワークで直接書くほうが速く、壊れにくくなります。生成AIに書かせる場合も同じで、読み手がいなければ下書きが速くなるだけで仕様の合意には近づきません。

もう1つの目安はテストの層です。Gherkinは利用者から見た振る舞いを確かめる受け入れテストに向き、関数単位の分岐まで .feature にすると件数が膨れて読めなくなります。単体・結合・E2Eの配分は[テストピラミッドとは？単体・結合・E2Eの配分と実装者向けテスト戦略設計](/tech/details/13289/)、BDDそのものを導入すべきかは[BDDとは？振る舞い駆動開発の仕組みとTDDとの違い・導入判断を実装者向けに解説](/tech/details/16255/)で判断基準を整理しています。受け入れテストの自動化をCI/CDに組み込むところから相談したい場合は、[DevOps・CI/CD導入支援](/service/system/devops/)で設計から支援しています。

## よくある質問

### Gherkin形式（Gherkinフォーマット）とは何ですか？

Given・When・Thenを中心としたキーワードで、システムの振る舞いを1行ずつ書く仕様記述の形式です。拡張子 .feature のテキストファイルとして保存し、Cucumber・pytest-bdd・behave などのフレームワークが解析して、各ステップに対応するコード（ステップ定義）を実行します。仕様書と自動テストを1つのファイルで兼ねられる点が、通常のテストコードとの違いです。

### Given-When-Then形式とは何ですか？

1つのシナリオを「前提となる状態（Given）」「起きる出来事（When）」「期待される結果（Then）」の3段で書く型で、Gherkinはこれをキーワードとして組み込んでいます。Cucumberは照合にキーワードを使いませんが、pytest-bddとbehaveでは3語の選び方が実行結果に影響します。

### Gherkinの読み方と意味は？

日本語では「ガーキン」と表記します。英単語としてはピクルスにする小型のキュウリを指し、Cucumber（キュウリ）というフレームワーク名にちなんだ命名です。そのため検索結果には食品や、ロンドンにある同名の高層ビルの情報も混ざります。技術の情報を探すときは「gherkin 記法」「gherkin bdd」のように語を足すと絞り込めます。

### Gherkinを書くのに向いたエディタはありますか？

VS Codeなら、Cucumberチームが保守する公式拡張「Cucumber」（公開元 CucumberOpen、識別子 `CucumberOpen.cucumber-official`）があります。[READMEの機能一覧](https://github.com/cucumber/vscode)は、ステップの補完、ステップ定義への移動と生成、構文の色分け、整形、`# language:` による多言語キーワードへの対応を挙げています。ステップ定義の対応言語にPythonで載っているのはBehaveだけで、pytest-bddはありません。ステップ定義の生成は、既存のステップ定義が1つ以上あるときだけ使えます。

### GherkinとEARS記法はどう使い分けますか？

Gherkinは具体例で書き、1シナリオが1つの実行可能なテストになります。EARS記法は要求そのものを定型の文型で曖昧さなく書くための構文で、実行はしません。上流の要求をEARSで固め、そこから導かれる受け入れ条件をGherkinの具体例に落とす順で併用すると噛み合います。EARS側の書き方は[EARS記法とは？読み方と5つの基本型の書き方を日本語例文で解説【Kiro対応】](/tech/details/11489/)を参照してください。

## 関連記事

- [Cucumberとは？Java・JavaScriptでのテスト自動化の手順とCucumber 8.0の変更点](/tech/details/3639/)
- [BDDとは？振る舞い駆動開発の仕組みとTDDとの違い・導入判断を実装者向けに解説](/tech/details/16255/)
- [EARS記法とは？読み方と5つの基本型の書き方を日本語例文で解説【Kiro対応】](/tech/details/11489/)
- [pytestの使い方と書き方｜fixture・parametrize・docstringの扱いまで【9.1対応】](/tech/details/7527/)
- [スモークテストとは？CI/CDへの組み込みと対象選定・失敗時の判断を実装者向けに解説](/tech/details/16256/)

---

出典: [Gherkinとは？構文の全キーワードと.featureファイルの書き方・実行例](<https://www.issoh.co.jp/tech/details/11693/>)（株式会社一創）
