テスト環境(Rspec, Turnip, Guard, Spring, Jenkins) の設定

前回はテストまで進めなかったので、今回はテスト環境を設定するところまで記述します。どうしてもテストがうまく動かないなと思っていたら、前回設定した Gemfile に Turnip が入っていませんでした。記事は修正しておきました。また、今回の環境構築にあたり、vim の環境も再設定しました。デフォルトシェルが fish であったため、かなりトラブりましたので覚え書きを書いておきます。

vim の設定

これまで使っていた vim の環境は、.vimrc にいろいろなサイトから取り寄せた情報を自分で切り貼りしていたものでした。最近は、github にさまざまなプラグインが配布されており、バンドルとして管理できようになっているようです。プラグイン管理ツールとしては、vundle や NeoBundle などがあるようです。今回は、NeoBundle の導入を参考に、NeoBundle で設定してみます。通常は、書いてあるとおりにやれば簡単に動作するようですが、私の環境ではうまく動作しませんでした。原因がわからずに元の .vimrc に戻そうと確認したところ、そこに答えが書いてありました。

とりあえず、.vimrc、.vim をバックアップして、NeoBundle をインストールします。

mv ~/.vimrc{,.org}
mv ~/.vim{,.org}
mkdir -p ~/.vim/bundle
git clone https://github.com/Shougo/neobundle.vim ~/.vim/bundle/neobundle.vim
git clone https://github.com/Shougo/vimproc ~/.vim/bundle/vimproc

次に ~/.vimrc を設定します。私のところではデフォルトシェルを fish にしているために、shell 変数を /bin/sh に設定する処理を忘れないようにします。fish を導入したときにもトラブったはずなのですが、すっかり記憶の外でした。

if $SHELL =~ 'fish'
  set shell=/bin/sh
endif

set nocompatible               " be iMproved
filetype off

if has('vim_starting')
  set runtimepath+=~/.vim/bundle/neobundle.vim
  call neobundle#rc(expand('~/.vim/bundle/'))
endif
" originalrepos on github
NeoBundle 'Shougo/neobundle.vim'
NeoBundle 'Shougo/vimproc'
NeoBundle 'Shougo/neosnippet'
NeoBundle "Shougo/neosnippet-snippets"
NeoBundle "Shougo/neocomplcache"
NeoBundle 'tpope/vim-rails'
NeoBundle 'tpope/vim-haml'
NeoBundle 'skwp/vim-rspec'

"
" 個々のプラグインの設定
"  (長いので省略)
"

filetype plugin indent on     " required!
filetype indent on
syntax on

その後、vi を起動し、:NeoBundleInstall としてプラグインをインストールします。

Guard の設定

まずは、Guard の設定を行います。これはローカルでの自動テストを実施してくれるものです。テストや実装のファイルを修正すると関連するテストのみを実行してくれます。

be guard init

Gemfile の内容に従って、以下のような Guardfile が作成されています。何のファイルを書き換えると、どのテストが実施されるかがわかるようになっています。

# A sample Guardfile
# More info at https://github.com/guard/guard#readme

guard :rspec do
  watch(%r{^spec/.+_spec\.rb$})
  watch(%r{^lib/(.+)\.rb$})     { |m| "spec/lib/#{m[1]}_spec.rb" }
  watch('spec/spec_helper.rb')  { "spec" }

  # Rails example
  watch(%r{^app/(.+)\.rb$})                           { |m| "spec/#{m[1]}_spec.rb" }
  watch(%r{^app/(.*)(\.erb|\.haml|\.slim)$})          { |m| "spec/#{m[1]}#{m[2]}_spec.rb" }
  watch(%r{^app/controllers/(.+)_(controller)\.rb$})  { |m| ["spec/routing/#{m[1]}_routing_spec.rb", "spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb", "spec/acceptance/#{m[1]}_spec.rb"] }
  watch(%r{^spec/support/(.+)\.rb$})                  { "spec" }
  watch('config/routes.rb')                           { "spec/routing" }
  watch('app/controllers/application_controller.rb')  { "spec/controllers" }

  # Capybara features specs
  watch(%r{^app/views/(.+)/.*\.(erb|haml|slim)$})     { |m| "spec/features/#{m[1]}_spec.rb" }

  # Turnip features and steps
  watch(%r{^spec/acceptance/(.+)\.feature$})
  watch(%r{^spec/acceptance/steps/(.+)_steps\.rb$})   { |m| Dir[File.join("**/#{m[1]}.feature")][0] || 'spec/acceptance' }
end


guard 'spring', :rspec_cli => '--color' do
  watch(%r{^spec/.+_spec\.rb$})
  watch(%r{^spec/spec_helper\.rb$})                   { |m| 'spec' }
  watch(%r{^app/(.+)\.rb$})                           { |m| "spec/#{m[1]}_spec.rb" }
  watch(%r{^lib/(.+)\.rb$})                           { |m| "spec/lib/#{m[1]}_spec.rb" }
  watch(%r{^app/controllers/(.+)_(controller)\.rb$})  do |m|
    %W(spec/routing/#{m[1]}_routing_spec.rb spec/#{m[2]}s/#{m[1]}_#{m[2]}_spec.rb spec/requests/#{m[1]}_spec.rb)
  end
end

このままだと、spring 経由で rspec が起動しないので、最初の行を次のように修正します。

guard :rspec, cmd: 'spring rspec -f doc' do

ターミナルの一つで以下のコマンドを実行し、guard を実行したままにしておきます。

be guard

なお、Rspec から Turnip を実行するように .rspec ファイルに以下の行を追加しておきます。

-r turnip/rspec

これで Guard の設定は終了です。

最初のテスト

Turnip は spec/acceptance に作成するようです。このフォルダを作成します。

mkdir -p spec/acceptance

とりあえず、トップページが表示できるかどうかのテストをしてみます。spec/acceptance/top_page.feature を以下のように記述します。

# encoding: utf-8
# language: ja
機能: 日本語・英語版の切替を実現する
  シナリオ: 日本語のトップページにアクセスする
    前提 トップページを表示する
    ならば 画面に森高千里データベースと表示されていること

ファイルを保存した瞬間に、guard を動作させているターミナル上で勝手にテストが起動します。

22:43:33 - INFO - Running: spec/acceptance/top_page.feature                     

日本語・英語版の切替を実現する
  日本語のトップページにアクセスする
    トップページを表示する -> 画面に森高千里データベースと表示されていること (PENDING: No such step: 'トップページを表示する')

Pending:
  日本語・英語版の切替を実現する 日本語のトップページにアクセスする トップページを表示する -> 画面に森高千里データベースと表示されていること
    # No such step: 'トップページを表示する'
    # ./spec/acceptance/top_page.feature:5

Finished in 0.00315 seconds
1 example, 0 failures, 1 pending

Jenkins の設定

コミット時に自動テストを実行するように Jenkins の設定を行います。moritaka-db というジョブを作成します。設定したのは以下の通りです。

ソースコード管理
Git でリポジトリの場所を設定します
ビルド・トリガ
リモートからビルドにチェックを付け、認証トークンを設定します。
ビルド
以下のスクリプトを設定します。
#!/bin/sh
PATH=/Users/hkob/.rbenv/shims:/usr/local/bin:$PATH
export PATH

bundle install --path vendor/bundle

bundle exec rake db:migrate
bundle exec rspec -f progress -r turnip/rspec

次に、ユーザの設定画面を表示し、ユーザの「APIトークン」を記録しておきます。

ビルド・トリガを設定したので、親リポジトリに push されたときに、Jenkins のビルドを実行するように gitリポジトリ/hooks/post-receive の設定をして、実行属性を付けておきます。

#!/bin/sh

echo "Hook post-commit start"
/usr/local/bin/wget --auth-no-challenge --http-user=hkob --http-password=ユーザのAPIトークン http://localhost:8080/job/moritaka-db/build?token=ビルド・トリガに設定した認証トークン -O /dev/null || echo "wget failed"
 
echo "Hook post-commit end"

ここまで設定した後で、git push をすると自動的に Jenkins のビルドが実行されます。
今回は step がないということで、failures ではなく pending となっているので、SUCCESS 扱いになっています。

Redmine の設定

Redmine には Hudson プラグインをインストールしているので、設定しておくと Jenkins の状況が Redmine からも確認できます。Hudson の画面で先ほど設定した moritaka-db を選択するだけで終了です。

まとめ

環境を作るまでで実装まで行きませんでした。次回は step の設定と、多言語化の部分まで記述する予定です。