LoginSignup
5
5

More than 5 years have passed since last update.

Cucumberで「ステップ定義」を探す

Last updated at Posted at 2013-05-26

お題

Cucumberは、featureファイルに記述されたシナリオステップに対応する「ステップ定義(=実装)」をどうやって見つけてるのだろうか?というのが事の発端。
Cucumberのコードを読みつつ、指定したシナリオステップにマッピングされた「ステップ定義」を検索するRubyコードを書いてみる。

コードを読む

Cucumber::Runtime::SupportCode クラスがマッチングのコア実装と思われる。ここを中心にざっと見てみる。

処理の流れとしては、

  1. 「ステップ定義」ファイルを読み込む
  2. Walkerをビルド
  3. featureファイルのシナリオステップを順次実行
  4. シナリオステップにマッチする「ステップ定義」を検索
    • 複数マッチした場合、"ベスト"な「ステップ定義」を検索
    • マッチした「ステップ定義」はキャッシュ
  5. 「ステップ定義」を実行

Rubyコード

Cucumber::Runtimeクラスにstep_match(step_name, name_to_report=nil)の定義があるので、これを叩けるように前提を揃えてやればよさそう。

  1. Configurationの指定
  2. 「ステップ定義」ファイルの読み込み

1.はコマンドライン引数からオプション指定で構築できるようにする。
2.は、private methodなので外部から実行できるようにする。

Rubyコードはこちら。featuresはexamplesを使用。

$ ruby find_step_definition.rb "the result should be 1.5 on the screen" examples/i18n/en/features/
step definition
  file: examples/i18n/en/features/step_definitons/calculator_steps.rb
    line:   22
    step:   {"source"=>"the result should be (.*) on the screen", "flags"=>""}
    arguments:
        {"offset"=>21, "val"=>"1.5"}

jaも検索してみる。

$ ruby find_step_definition.rb "1.5 を表示" examples/i18n/ja/features/
step definition
    file:   examples/i18n/ja/features/step_definitons/calculator_steps.rb
    line:   7
    step:   {"source"=>"(.*) を表示", "flags"=>""}
    arguments:
        {"offset"=>0, "val"=>"1.5"}

なかなかいい感じ。
ファイル名と行番号だけでなく、RDocやYARDみたくソースコードも表示できれば尚好し、かな。
yard-cucumberなんてのがあってYARD::CodeObjects::Baseを継承してがんばればやれそうな感触あったけど、ひとまずやりたいことはできたので終了。

Appendix

Cucumber::Runtimeクラスに「ステップ定義」一覧をJSONファイルにダンプするメソッドが定義されていたのでついでに使ってみた。
Rubyコードはこちら

$ ruby dump_step_definitions.rb --dotcucumber /path/to/.cucumber/ examples/i18n/en/features
write to /path/to/.cucumber/stepdefs.json

生成されたJSONファイル。

JSON
[
  {
    "source": "I have entered (\\d+) into the calculator",
    "flags": "",
    "file_colon_line": "examples/i18n/en/features/step_definitons/calculator_steps.rb:14",
    "steps": [
      {
        "name": "I have entered 2 into the calculator",
        "args": [
          {
            "offset": 15,
            "val": "2"
          }
        ]
      },
      {
        "name": "I have entered 3 into the calculator",
        "args": [
          {
            "offset": 15,
            "val": "3"
          }
        ]
      }
    ]
  },
  {
    "source": "I press (\\w+)",
    "flags": "",
    "file_colon_line": "examples/i18n/en/features/step_definitons/calculator_steps.rb:18",
    "steps": [
      {
        "name": "I press divide",
        "args": [
          {
            "offset": 8,
            "val": "divide"
          }
        ]
      }
    ]
  },
  {
    "source": "the result should be (.*) on the screen",
    "flags": "",
    "file_colon_line": "examples/i18n/en/features/step_definitons/calculator_steps.rb:22",
    "steps": [
      {
        "name": "the result should be 1.5 on the screen",
        "args": [
          {
            "offset": 21,
            "val": "1.5"
          }
        ]
      },
      {
        "name": "the result should be <output> on the screen",
        "args": [
          {
            "offset": 21,
            "val": "<output>"
          }
        ]
      }
    ]
  }
]
5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5