Cucumber 利用していますか?

基本的な使い方はわかるんだけど、なんだかもっと上手く使えるんじゃないだろうか?と、もやもやしながら使っています。 少くとも私の周りには Cucumber について情報交換できる人がいないです。

それでも、SlideShare や Speaker Deck なんかに公開されたスライドでよくみかけるので、使い込んでるところでは使い込まれているのだと思います。

Cucumber は Rails プロジェクト以外でも利用されているようで、範囲が広いです。もうちょっといろんな情報がWeb上に流れていても良い気がします。

私が知る限りでは Cucumber についてもっと詳しく書かれているのは The Rspec Book です。

前置きはさておき、 Cucumber の *.featureGherkin という 言語で書きます。 その文法について調べたのでそのメモを整理しておきます。

ちなみにこの内容はソース読んだり、Wikiに書かれているものを参考したもので、仕様として記述されてない情報もあるので未来のバージョンでは予告なく変更される部分があるかもしれません。

こんな長くて不正確な記事読みたくないよ!という人は BNF を読むのが手っ取りです。 というか、BNFが読める人は読みましょう。 むしろ、もっとはやく読めばよかった。

具体例

Gherukinのという言語で書いた文書の例を上げておきます。 内容はシステムに関するものにしませんでした。

# language: ja
@blog
フィーチャ: ブログを書く
  ブログを書くには本人のやる気と書く時間が必要です。
  アウトプットは次のインプットに繋がるので積極的に行なうべきです。

  # これはコメントでタグの後にはかけない
  # @ではじまるのはタグ
  @good
  シナリオ: ブログが書ける
    ブログが書ける場合はやる気と時間があるのです。

    # ネタがないとかけないです。
    前提 ネタがある
    # 時間がないとかけないです
    かつ 納期に終われていない
    # 先輩とかいないですけど
    もし 先輩にブログを書けと言われた
    # オチがない
    ならば ブログが書けている

  @bad
  シナリオ: デスマ中はブログが書けない
     デスマ中ダトソレドコロジャナインダ!!

     前提 ネタがある
     かつ デスマ中
     もし 先輩にブログを書けと言われた
     ならば ブログが書けていない

見てわかるように、ほぼ自然言語の雰囲気を残せます。 これならプログラマ以外の人でも読み書きできそうだよね。 ってのがウリです。

要素

Gherkin は以下の要素で構成されます。 ここでは要素と呼んでますが、トークンの一部を抜粋しただけです。

  • コメント
  • タグ
  • フィーチャ
  • バックグラウンド
  • シナリオ
  • シナリオテンプレート
  • ステップ
  • ドックストリング

トップダウンに説明していきます。説明する前の用語がでてきますが、一通り読んでもどってくると良いです。

ファイル構成

Gherkin では ひとつのファイルにひとつのフィーチャしか記述できません。 なので全体像としては

  • コメント (省略可能)
  • タグ (省略可能)
  • フィーチャ

となります。

タグコメントの順番は入れかえることはできません。

具体的には:

# comment
@tag
フィーチャ: フィーチャ名

コメント

# ではじまる行は コメントになります。 #` の前に空白があっても構いません。

プログラミング言語にあるような

@blog      # comment

のようなことはできません。

先頭にある language: ja は特殊なコメントでこのファイルで使用するキーワードの言語を指定します。 フィーチャシナリオ,前提かつなどがキーワードです。

コメントは書けるところがわりと限られてます。

タグ

@ではじまる単語は タグになります。 1行に複数かくこともできますし、複数行にわたってかくこともできます。

@blog @hoge
@mogu

フィーチャシナリオの前で書けます。

フィーチャ

このファイルに記述するフィーチャ(機能)に関して記述します。 言語に日本語を利用している場合は フィーチャ: または 機能:ではじまります。 つづけてその後ろには、そのフィーチャの名前をかきます。

次の行にはフィーチャに関する説明をかくことができます。 説明はだいたい好きなように書けます。 それ以降にはバックグラウンドシナリオを n個かくことができます。

  • フィーチャ: 名前
    • 説明(省略可能)
    • バックグラウンド(省略可能)
    • シナリオ1 or シナリオアウトライン
    • シナリオ2 or シナリオアウトライン
    • .
    • .
    • .
    • シナリオn or シナリオアウトライン

フィーチャ説明の間には空行は置けますがコメントなどは書けません。 具体的には:

フィーチャ: フィーチャ名
  フィーチャの説明

  バックグラウンド:
     前提 なにかがある

  シナリオ: シナリオ名
    .
    .
    .

のような感じです。

フィーチャ: hoge
  説明
  # comment
  説明

などはエラーになります。

バックグラウンド

フィーチャ内のシナリオの前に実行したいステップをかくことができます。

  • 背景: 名前
    • ステップ1
    • ステップ2
    • .
    • .
    • .
    • ステップn

という構造になります。

シナリオ

シナリオはひとつのテストになります。 シナリオはステップを複数持っていて、ステップの途中で失敗するとシナリオは失敗したことになります。

シナリオフィーチャと同様に説明が書けます。

  • コメント (省略可能)
  • タグ(省略可能)
  • シナリオ: 名前
    • 説明 (省略可能)
    • ステップ1
    • ステップ2
    • .
    • .
    • .
    • ステップn

という構造になります。

シナリオアウトライン

シナリオの重複を減らすためにはシナリオアウトラインを使うことができます。 シナリオ内に変数を埋めこんで、最後に変数に代入する値をとして明示することで、シナリオになります。 変数は <変数名>として表現できます。

  • コメント(省略可能)
  • タグ(省略可能)
  • シナリオアウトライン: 名前
    • 説明
    • ステップ1
    • ステップ2
    • .
    • .
    • .
    • ステップn
    • 例:

具体例をあげておきます。

シナリオアウトライン: <種類>が書ける
  <種類>が書ける場合はやる気と時間があるのです。

  前提 ネタがある
  かつ 納期に終われていない
  もし <人>に<種類>を書けと言われた
  ならば <種類>が書けている
  例:
    | 種類   | 人   |
    | ブログ | 先輩 |
    | 資料   | 営業 |

例の表の 1行目は変数名に対応しますが、Gherkinというより Cucumber の部分になる気がします。 2行目に具体的な値を書きます。

ブログ が <種類> の部分に、先輩 が <人> の部分に 展開されます。

シナリオアウトラインの代わりに シナリオテンプレート なども使えます

詳細は

$ cucumber --i18n ja

ステップ

先頭が前提 もし ならば などの部分です。 Cucumberでは対応する コード が実行されます。

  • コメント (省略可能)
  • ステップキーワード: 名前
    • ドックストリング もしくは (省略可能)

という構造になります。

ステップキーワードには

  • 前提 (given)
  • もし (when)
  • ならば (then)
  • かつ (and)
  • しかし (but)

などがあります。

* というのもありまして:

* ネタがある
* 納期に終われていない
* 先輩にブログを書けと言われた
* ならば ブログが書けている

とかいても等価です。

cucumber --i18n ja

なども確認してみてください

ドックストリング

ステップに長い文字列を渡したい場合に利用します。 '''(クオート3つ)で挟むことでドックストリングになります。

前提 ネタがある
   '''
   デスマ神がほげほげ
   ネコ型の何かがもぐもぐ
   '''
かつ 納期に終われていない

とすると “ネタがある” ステップヘ “デスマ神がほげ…もぐもぐ” という文字列を渡すことができます。

表は “シナリオアウトラインの例” と “ステップへの引数として表を使いたい” 場合に利用できます。

表は|(パイプ)を利用してAscii Art で表を書きます。

シナリオアウトラインについてはもう書いているので省きます。

ステップで使用すると Cucumber::Ast::Table というクラスのインスタンスが渡されます。ステップの実装で煮るなり焼くなりしあしょう。

一応具体例:

前提 なにかある
  | 1 | 2 |
  | 3 | 4 |
もし なにかする
  | 1 | 2 | 3 |
  | 4 | 5 | 6 |
ならば こういう結果になる
  | 7 | 8 | 9 | 10 |

インデントについて

インデント自体に意味はありませんが適切につけておくと読みやすいです。cucumberで実行した場合は自動的に整形されます。

まとめ

無駄に時間がかかりました。何かの役に立てば良いなぁ。 途中で対象読者を意識してないことに絶望していろいろブレてます。

間違いなどあればご連絡ください。

仕事してきます。