LoginSignup
16
12

More than 5 years have passed since last update.

Ruby | Guard gem を利用してファイルの変更を検出し、任意のタスクを自動実行する

Last updated at Posted at 2014-07-18

Ruby | Guard gem を利用してファイルの変更を検出し、任意のタスクを自動実行する

概要

Guard gem を利用してファイルの変更を検出し、任意のタスクを自動実行する。
今回はファイル変更時に RSpec を実行してみます。

インストール

  • guard の RSpec Plugin も一緒にインストールします
$ gem install guard --no-ri --no-doc
$ gem install guard-rspec --no-ri --no-doc

設定ファイル(Guardfile)の生成

RSpec対応のひな形を生成します。

$ guard init rspec

下記のようなテンプレートが生成されます

Guardfile
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

設定ファイルの編集

下記のように編集します。

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

guardを起動します

$ guard start

プログラムのひな型を生成します

自作 gem の rspec_piccolo を利用します。
rspec_piccoloはプロダクトコードとテストコードのひな形を生成する CLI ツールです。

詳しくは
https://github.com/tbpgr/rspec_piccolo
を参照。

piccolo e Hoge hoge hoge -p

これで、以下のファイルが生成されます。

lib/hoge.rb
# encoding: utf-8


class Hoge
  def hoge
    # TODO: implement your code
  end
end
spec/hoge_spec.rb
# encoding: utf-8
require "spec_helper"
require "hoge"

describe Hoge do

  context :hoge do
    cases = [
      {
        case_no: 1,
        case_title: "case_title",
        expected: "expected",
      },
    ]

    cases.each do |c|
      it "|case_no=#{c[:case_no]}|case_title=#{c[:case_title]}" do
        begin
          case_before c

          # -- given --
          hoge = Hoge.new

          # -- when --
          # TODO: implement execute code
          # actual = hoge.hoge

          # -- then --
          # TODO: implement assertion code
          # expect(actual).to eq(c[:expected])
        ensure
          case_after c
        end
      end

      def case_before(c)
        # implement each case before
      end

      def case_after(c)
        # implement each case after
      end
    end
  end
end

自動生成されたファイルを検知して、guardが実行されます

[1] guard(main)>

22:45:17 - INFO - Running: spec/hoge_spec.rb
Run options: include {:focus=>true}

All examples were filtered out; ignoring {:focus=>true}
.

Finished in 0 seconds
1 example, 0 failures

テストを実装後、プロダクトコードを保存したguardの実行結果を確認します

spec/hoge_spec.rb
# encoding: utf-8
require "spec_helper"
require "hoge"

describe Hoge do

  context :hoge do
    cases = [
      {
        case_no: 1,
        case_title: "valid case",
        expected: "hoge",
      },
    ]

    cases.each do |c|
      it "|case_no=#{c[:case_no]}|case_title=#{c[:case_title]}" do
        begin
          case_before c

          # -- given --
          hoge = Hoge.new

          # -- when --
          actual = hoge.hoge

          # -- then --
          expect(actual).to eq(c[:expected])
        ensure
          case_after c
        end
      end

      def case_before(c)
        # implement each case before
      end

      def case_after(c)
        # implement each case after
      end
    end
  end
end
[1] guard(main)>

22:47:05 - INFO - Running: spec/hoge_spec.rb
Run options: include {:focus=>true}

All examples were filtered out; ignoring {:focus=>true}
F

Failures:

  1) Hoge hoge |case_no=1|case_title=valid case
     Failure/Error: expect(actual).to eq(c[:expected])

       expected: "hoge"
            got: "# TODO: implement your code"

       (compared using ==)
     # ./spec/hoge_spec.rb:28:in `block (4 levels) in <top (required)>'

Finished in 0.001 seconds
1 example, 1 failure

Failed examples:

rspec ./spec/hoge_spec.rb:17 # Hoge hoge |case_no=1|case_title=valid case

プロダクトコードを実行して、テストをパスするようにしてファイルを保存します。

テストが成功することを確認できました

lib/hoge.rb
# encoding: utf-8


class Hoge
  def hoge
    'hoge'
  end
end
[1] guard(main)>

22:48:46 - INFO - Running: ./spec/hoge_spec.rb:17
Run options: include {:locations=>{"./spec/hoge_spec.rb"=>[17]}}
.

Finished in 0.001 seconds
1 example, 0 failures
Run options: include {:locations=>{"./spec/hoge_spec.rb"=>[17]}}
.

Finished in 0.001 seconds
1 example, 0 failures

参照

https://github.com/guard/guard
http://rubygems.org/gems/guard

Guard まとめ記事

16
12
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
16
12