暇人じゃない

Gem を複数バージョンの依存ライブラリでテストする

Gem を複数バージョンの依存ライブラリでテストしたい。
例えば、私が開発している jp_prefecture gem は Rails に組み込んで使用可能で、Rails 3.2 から 4.2 まで (5.0.0.beta3 も一応) をサポートしています。 これらの各バージョンで Gem のテストが通るかを検証しておきたい。

そこで appraisal gem を使います。
appraisal は異なるバージョンのライブラリで Gem をテストできるようにサポートしてくれる Gem です。

以下は jp_prefecture gem の例で Active Record をメインにテストしていますが、 Rails や他のライブラリでも同じように使えると思います。

セットアップ

gem.add_development_dependency 'appraisal'

このファイルにバージョンを分けてテストしたい Gem を定義します。
rails32rails42 などでバージョンを区切り、 ブロックの中で Gem を定義します。

appraise 'rails32' do
  gem 'activerecord', '~> 3.2.0'
end

appraise 'rails40' do
  gem 'activerecord', '~> 4.0.0'
end

appraise 'rails41' do
  gem 'activerecord', '~> 4.1.0'
end

appraise 'rails42' do
  gem 'activerecord', '~> 4.2.0'
end

# Rails 5 は Ruby 2.2.2 以上が要求される
if RUBY_VERSION >= '2.2.2'
  appraise 'rails50' do
    gem 'activerecord', '5.0.0.beta3'
  end
end

作成された gemfiles/rails32.gemfile:

# This file was generated by Appraisal

source "https://rubygems.org"

gem "activerecord", "~> 3.2.0"

gemspec :path => "../"

activerecord gem の後に jp_prefecture gem の gemspec を読み込んでいます。
従って、Appraisal ファイルに定義したもの以外は Gem 自体の add_development_dependencyadd_dependency で定義された Gem が使用されます。

テスト実行

% bundle exec appraisal rake spec
>> BUNDLE_GEMFILE=/path/to/jp_prefecture/gemfiles/rails32.gemfile bundle exec rake spec
/path/to/user/.rbenv/versions/2.3.0/bin/ruby -I/path/to/jp_prefecture/.bundle/ruby/2.3.0/gems/rspec-core-3.4.4/lib:/path/to/jp_prefecture/.bundle/ruby/2.3.0/gems/rspec-support-3.4.1/lib /path/to/jp_prefecture/.bundle/ruby/2.3.0/gems/rspec-core-3.4.4/exe/rspec --pattern spec/\*\*/\*_spec.rb --format documentation --color
-- create_table(:places)
   -> 0.0399s
-- initialize_schema_migrations_table()
   -> 0.0005s
-- assume_migrated_upto_version(1, ["db/migrate"])
   -> 0.0002s

JpPrefecture::Base
  #jp_prefecture
    カラム名の指定について
      prefecture_code を指定した場合
        prefecture_code のコードが変換できること

...skip...
% bundle exec appraisal rails42 rake spec
>> BUNDLE_GEMFILE=/path/to/jp_prefecture/gemfiles/rails42.gemfile bundle exec rake spec
/path/to/user/.rbenv/versions/2.3.0/bin/ruby -I/path/to/jp_prefecture/.bundle/ruby/2.3.0/gems/rspec-core-3.4.4/lib:/path/to/jp_prefecture/.bundle/ruby/2.3.0/gems/rspec-support-3.4.1/lib /path/to/jp_prefecture/.bundle/ruby/2.3.0/gems/rspec-core-3.4.4/exe/rspec --pattern spec/\*\*/\*_spec.rb --format documentation --color
-- create_table(:places)
   -> 0.0024s
-- initialize_schema_migrations_table()
   -> 0.0151s

JpPrefecture::Base
  #jp_prefecture
    カラム名の指定について
      prefecture_code を指定した場合
        prefecture_code のコードが変換できること

...skip...

Travis CI への組み込み

appraisal generate --travis で Travis CI 用の設定を生成できます。
表示されたものを .travis.yml に追加します。

% bundle exec appraisal generate --travis
# Put this in your .travis.yml
gemfile:
  - gemfiles/rails32.gemfile
  - gemfiles/rails40.gemfile
  - gemfiles/rails41.gemfile
  - gemfiles/rails42.gemfile
  - gemfiles/rails50.gemfile

以下は jp_prefecture gem の Travis CI に関係あるものを抜粋したものです。

appraisal を使用する設定に加えて、複数の Ruby のバージョンでビルドを行なったり、Rails 5.0.0 は Ruby 2.2.2 以上が要求されるため、それ以下の Ruby をビルドから除外したりしています。 全体はリポジトリの .travis.yml を参照してください。

rvm:
  - 1.9.3
  - 2.0.0
  - 2.1.8
  - 2.2.4
  - 2.3.0
  - ruby-head
gemfile:
  - gemfiles/rails32.gemfile
  - gemfiles/rails40.gemfile
  - gemfiles/rails41.gemfile
  - gemfiles/rails42.gemfile
  - gemfiles/rails50.gemfile
matrix:
  exclude:
    - rvm: 1.9.3
      gemfile: gemfiles/rails50.gemfile
    - rvm: 2.0.0
      gemfile: gemfiles/rails50.gemfile
    - rvm: 2.1.8
      gemfile: gemfiles/rails50.gemfile

Ruby と Rails のバージョンの組み合わせでテストするためジョブが増えてしまいますが、 以上で Travis CI でテストできるようになりました。

実際のビルドは以下で確認できます。

まとめ

appraisal gem を使って複数バージョンの依存ライブラリで Gem をテストできるようになりました。

Issue を作成してから導入に着手するまで時間がかかってしまいましたが、 意外と簡単に導入することができました。