Tbpgr Blog

Employee Experience Engineer tbpgr(てぃーびー) のブログ

RSpecPiccolo | RSpecPiccolo gemが1階層分のディレクトリ構成にしか対応していないので改修する

概要

RSpecPiccolo gemが1階層分のディレクトリ構成にしか対応していないので改修する

内容

RSpecPiccolo gemが1階層分のディレクトリ構成にしか対応していないので改修します。

バグの再現

2階層以上下のディレクトリを指定するとエラーになる

$piccolo execute Hoge::Core hoge/hige/hage hoge
C:/Ruby193/lib/ruby/gems/1.9.1/gems/rspec_piccolo-0.0.3/lib/rspec_piccolo.rb:103:in `mkdir': No such file or directory - ./spec/hoge/hige (Errno::ENOENT)
        from C:/Ruby193/lib/ruby/gems/1.9.1/gems/rspec_piccolo-0.0.3/lib/rspec_piccolo.rb:103:in `create_spec_directory'
        from C:/Ruby193/lib/ruby/gems/1.9.1/gems/rspec_piccolo-0.0.3/lib/rspec_piccolo.rb:76:in `generate'
        from C:/Ruby193/lib/ruby/gems/1.9.1/gems/rspec_piccolo-0.0.3/bin/piccolo:19:in `execute'
        from C:/Ruby193/lib/ruby/gems/1.9.1/gems/thor-0.18.1/lib/thor/command.rb:27:in `run'
        from C:/Ruby193/lib/ruby/gems/1.9.1/gems/thor-0.18.1/lib/thor/invocation.rb:120:in `invoke_command'
        from C:/Ruby193/lib/ruby/gems/1.9.1/gems/thor-0.18.1/lib/thor.rb:363:in `dispatch'
        from C:/Ruby193/lib/ruby/gems/1.9.1/gems/thor-0.18.1/lib/thor/base.rb:439:in `start'
        from C:/Ruby193/lib/ruby/gems/1.9.1/gems/rspec_piccolo-0.0.3/bin/piccolo:29:in `<top (required)>'
        from C:/Ruby193/bin/piccolo:19:in `load'
        from C:/Ruby193/bin/piccolo:19:in `<main>'

現状のテストコードを実行

$rspec
Run options: include {:focus=>true}

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

Finished in 0.043 seconds
8 examples, 0 failures

まずはエラーになるテストケースを追加

spec/rspec_piccolo_spec.rbにケースを追加
GitHubで差分を見たほうが分かりやすいと思います。
https://github.com/tbpgr/rspec_piccolo/commit/6e2f6e4721e0274e46e1180e892003f7fa850906

# :
# 略
# :
    CASE9_EXPECTED=<<-EOS
# encoding: utf-8
require "spec_helper"
require "some_dir/some_sub_dir/hoge_core"

describe Hoge::Core do
  context :method1 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_core = Hoge::Core.new

          # -- when --
          # TODO: implement execute code
          # actual = hoge_core.method1

          # -- 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

  context :method2 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_core = Hoge::Core.new

          # -- when --
          # TODO: implement execute code
          # actual = hoge_core.method2

          # -- 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
EOS
# :
# 略
# :
{
  case_no: 9,
  case_title: "with two directories, classname(with module) and method_names",
  class_name: "Hoge::Core",
  class_path: "some_dir/some_sub_dir/hoge_core",
  method_names: ["method1", "method2"],
  expected_file_name: "./spec/some_dir/some_sub_dir/hoge_core_spec.rb",
  expected_file_exists: true,
  expected_contents: CASE9_EXPECTED
},
# :
# 略
# :

テストケース追加後にテストを実行

$rspec
Run options: include {:focus=>true}

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

Failures:

  1) RSpecPiccolo::Core generate |case_no=9|case_title=with two directories, classname(with module) and method_names
     Failure/Error: piccolo.generate(c[:class_name], c[:class_path], c[:method_names])
     Errno::ENOENT:
       No such file or directory - ./spec/some_dir/some_sub_dir
     # ./lib/rspec_piccolo.rb:103:in `mkdir'
     # ./lib/rspec_piccolo.rb:103:in `create_spec_directory'
     # ./lib/rspec_piccolo.rb:76:in `generate'
     # ./spec/rspec_piccolo_spec.rb:464:in `block (4 levels) in <top (required)>'

Finished in 0.045 seconds
9 examples, 1 failure

テストケースの問題が解消するようにロジックを修正

lib/rspec_piccolo.rb
Dir.mkdir利用部をFileUtils.mkdir_pに変えました

GitHubで差分を見たほうが分かりやすいと思います。
https://github.com/tbpgr/rspec_piccolo/commit/6e2f6e4721e0274e46e1180e892003f7fa850906

# :
# 略
# :
FileUtils.mkdir_p("./spec/#{File.dirname(class_path)}")
# Dir.mkdir("./spec/#{File.dirname(class_path)}")
# :
# 略
# :

修正後テスト実行

$rspec
Run options: include {:focus=>true}

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

Finished in 0.05 seconds
9 examples, 0 failures

Randomized with seed 27612

rake installで最新のgemをインストールした後にbatの呼び出しチェック

バグ修正前にエラーになっていた2階層のテストコードの生成を実行し、
・想定の階層に出力されていること
・想定のrequire文になっていること
を確認。

$piccolo execute Hoge::Core hoge/hige/hage hoge
$tree
.
spec
  ┗hoge
      ┗hige
          ┗hage_spec.rb
$cat spec/hoge/hige/hage_spec.rb | head -5
# encoding: utf-8
require "spec_helper"
require "hoge/hige/hage"

describe Hoge::Core do

正常動作を確認したのでバージョンをあげてGitHubRubyGemsへリリース

・version.rbのバージョンアップ
・gitのcommit, remote への push
・rake releaseでRubyGemsへリリース

無事バージョンアップ

早速Rubygemsからインストールして動作確認

gem uninstall rspec_piccolo
gem install rspec_piccolo
$piccolo execute Hoge::Core hoge/hige/hage hoge

無事動作確認

おまけのカバレッジレポート