Gherkin記法 (CucumberやTurnip) で書かれたfeature specはRubocopが使えないので、自前で整形する

## まえおき

RubocopはRubyをASTで構文解析して指摘をするものだ。
なので、当然Gherkin記法で書かれた .feature なファイルは解析してくれない。
https://github.com/rubocop-hq/rubocop-rspec/issues/95

そうは言っても、チームで開発するんであればフォーマッターは必要だ。

## cucumber -f pretty でフォーマットする

タイトルの通り、実は[cucumber](https://github.com/cucumber/cucumber-ruby)にはprettyフォーマット機能がある。

```my.feature
Feature: YusukeIwaki

    Scenario: 'GitHubで検索してスター付きのリポジトリが無いことを確認する'

      Given browse github.com
      Then search with keyword "YusukeIwaki"
      Then the result shows 0 repositories
```

このように、いかにもインデントが気持ち悪いfeatureがあったとしよう。

これを cucumber -f pretty コマンドに通すと・・・

```
root@cf93b00e1ac1:/app# cucumber -f pretty my.feature 
Feature: YusukeIwaki

  Scenario: 'GitHubで検索してスター付きのリポジトリが無いことを確認する' # my.feature:3
    Given browse github.com                    # my.feature:5
    Then search with keyword "YusukeIwaki"     # my.feature:6
    Then the result shows 0 repositories       # my.feature:7

1 scenario (1 undefined)
3 steps (3 undefined)
0m0.014s

You can implement step definitions for undefined steps with these snippets:

Given("browse github.com") do
  pending # Write code here that turns the phrase above into concrete actions
end

Then("search with keyword {string}") do |string|
  pending # Write code here that turns the phrase above into concrete actions
end

Then("the result shows {int} repositories") do |int|
  pending # Write code here that turns the phrase above into concrete actions
end
```

なんか色々と余計なお世話をしてくれてる感じはあるが、なんとなくソースコードがフォーマットされる。

## featureファイルをフォーマットするには？

* `# my.feature:5` みたいなのは `-s` ( `--no-source` )オプションを付けると消える。
* `You can implement step definitions for undefined steps with these snippets:` 以降のいろいろは、 `-i` ( `--no-snippets` )オプションをつけると消える。

で、実は上記2つを一気にやる `-q` というオプションがあるので、それを使います。

```
root@cf93b00e1ac1:/app# cucumber -q -f pretty my.feature 
Feature: YusukeIwaki

  Scenario: 'GitHubで検索してスター付きのリポジトリが無いことを確認する'
    Given browse github.com
    Then search with keyword "YusukeIwaki"
    Then the result shows 0 repositories

1 scenario (1 undefined)
3 steps (3 undefined)
```


うーん、末尾の

```

1 scenario (1 undefined)
3 steps (3 undefined)
```

これ・・。 `cucumber --help` 見た感じ、これを消すオプションはない？

とりあえず、3行くっつくこと自体は変わらないだろう、ということで雑に

```
root@cf93b00e1ac1:/app# cucumber -q -f pretty my.feature | head -n -3
Feature: YusukeIwaki

  Scenario: 'GitHubで検索してスター付きのリポジトリが無いことを確認する'
    Given browse github.com
    Then search with keyword "YusukeIwaki"
    Then the result shows 0 repositories
```

はいできあがり。


## CIで、フォーマットされていないファイルがあればfailさせる

```check_gherkin_format.sh
#!/bin/bash -e

# USAGE:
#   gem install cucumber
#   cucumber --init
#   rm -rf features/
#   find spec/features/ -name *.feature | xargs ./check_gherkin_format.sh

for file in "$@"
do
  echo $file
  cucumber -q -f pretty $file | head -n -3 | diff -bu $file -
done
```

こんな感じのシェルスクリプトを適当に作って、

```
find spec/features/ -name *.feature | xargs ./check_gherkin_format.sh
```

をCIスクリプトで実行すればいいだけだ。

[diffコマンドは、差分があればexit code 1になる](http://tolarian-academy.net/diff-command-returns-1-but-success/)ので、差分があった瞬間にCIは落ちる。

これを使えば、Pull Requestでフォーマッター未適用のソースを検出することができる。

## まとめ

* `cucumber -q -f pretty xxxx.feature | head -n -3` でフォーマットをかける
* `cucumber -q -f pretty $file | head -n -3 | diff -bu $file -` をCIで実行して、フォーマット漏れを検出する