リア充爆発日記

You don't even know what ria-ju really is.

Rspec2->Rspec3にバージョンアップしたときのメモ

仕様の変更部分とかそういうのは置いといて、実際に2.14.xで運用していたRailsアプリを3.0.xにアップデートしたときの作業メモ。無くなったメソッドなどは書き換えで対応することとし、後方互換のためのgemなどは一切使わぬゆえ。

なので、3へのアップデート手順としては、当然アプリによって過不足がでるからね。

というわけでGemに更新から。

group :development, :test do
  gem 'rspec-rails', '~> 3.0.1'
  gem 'rspec-mocks', '~> 3.0.2'
~snip~

で、まず実行。

$ rspec
/Users/ria10/IdeaProjects/ria10-web/spec/controllers/application_controller_spec.rb:4:in `block in ': undefined method `controller' for RSpec::ExampleGroups::ApplicationController:Class (NoMethodError)
~snip~

起動しなかった。調べると、これだった。
https://github.com/rspec/rspec-rails/pull/970
今までは、ディレクトリの場所でそれがcontrollerなのかとかの判断をする機能がデフォルトで有効になってたんだけど、3からはそれをオプトイン方式にしたそうで、これは特定のフレームワーク依存じゃないツールとしては適当じゃないよね、ということなんでしょう。

対処方法は

spec_helper.rb

RSpec.configure do |config|
  config.infer_spec_type_from_file_location! # 追加!
~snip~

これでこのエラーはでなくなった。

再実行。

$ rspec
/Users/ria10/IdeaProjects/ria10-web/spec/models/user_spec.rb:11:in `block in ': undefined method `its' for RSpec::ExampleGroups::Route:Class (NoMethodError)
~snip~

見ての通り、itsはなくなったんですな。理由はこのとおり。
https://gist.github.com/myronmarston/4503509

で、どう書き換えていくべきかを調べていたら、なんと廃止された記法などをシャレオツなやつに自動的に書き換えてくれるgemを発見した。
http://yujinakayama.me/transpec/


で、インストラクションに従って実行すると結果のサマリーが最後にでる。

$ transpec
~snip~
Summary:

163 conversions
from: it { should ... }
to: it { is_expected.to ... }
17 conversions
from: describe 'some controller' { }
to: describe 'some controller', :type => :controller { }
13 conversions
from: describe 'some routing' { }
to: describe 'some routing', :type => :routing { }
12 conversions
from: obj.should_receive(:message)
to: expect(obj).to receive(:message)
9 conversions
from: describe 'some model' { }
to: describe 'some model', :type => :model { }
4 conversions
from: it { should_not ... }
to: it { is_expected.not_to ... }
2 conversions
from: describe 'some mailer' { }
to: describe 'some mailer', :type => :mailer { }
1 conversion
from: == expected
to: eq(expected)
1 conversion
from: be_true
to: be_truthy
1 conversion
from: its(:attr) { }
to: describe '#attr' do subject { super().attr }; it { } end
1 conversion
from: obj.should_not_receive(:message)
to: expect(obj).not_to receive(:message)

224 conversions, 0 incompletes, 0 warnings, 0 errors

A commit message that describes the conversion summary was generated to
.git/COMMIT_EDITMSG. To use the message, type the following command for
the next commit:
git commit -aeF .git/COMMIT_EDITMSG


具体的な部分を抜粋するとこんな感じ。
should系

 -    it { should render_template 'index' }
 +    it { is_expected.to render_template 'index' }

 -        UserMailer.should_receive(:password_reset).and_return(stub_mailer)
 +        expect(UserMailer).to receive(:password_reset).and_return(stub_mailer)

 -      it { should respond_with(404) }
 -      it { should render_template('errors/404') }
 +      it { is_expected.to respond_with(404) }
 +      it { is_expected.to render_template('errors/404') }

 -  its(:user) { should == @route.user }
 +  describe '#user' do
 +    subject { super().user }
 +    it { is_expected.to eq(@route.user) }
 +  end

最後の、「これもカバーしてるんか」って思った。


true, false系

 -          expect(post.draft?).to be_true
 +          expect(spot.draft?).to be_truthy

type系

 -describe ApplicationController do
 +describe ApplicationController, :type => :controller do

これは、さっき設定でカバーしたからいらないかったなぁ。


これは、後で追加するものとの一貫性を保ちたいので戻したい。たくさんあるので、手でやるのはキツイ。
オプションがないかな、と思ったらあった。

$ transpec -t

ヘルプは-hで確認できるので、他に飛ばしたいやつとかあればどうぞ。
また、このツールはgitに未コミットのものがあると起動されずにエラーを吐くため、、実行前後の状態が保ちやすい。そのため、こういうケースでも切り戻しが楽にできてすごくよかった。


で、テストが問題なく通るか確認する。

$ rspec
................................................................................................................................................................................................................................................................................................................................

Deprecation Warnings:

                                                                                                                                                              • -

Capybara::RSpecMatchers::HaveText implements a legacy RSpec matcher
protocol. For the current protocol you should expose the failure messages
via the `failure_message` and `failure_message_when_negated` methods.
(Used from /Users/ria10/IdeaProjects/ria10-web/spec/features/signup_spec.rb:10:in `block (2 levels) in ')

                                                                                                                                                              • -

~snip~

むぅ。これはcapybaraが2.2だったためで、2.3で対応されているらしい。なので最新の2.4にすればOKだった。
https://github.com/jnicklas/capybara/issues/1254

Gemfile書き換えてupdateして再実行

$ rspec
................................................................................................................................................................................................................................................................................................................................

Deprecation Warnings:

                                                                                                                                                              • -

Paperclip::Shoulda::Matchers::HaveAttachedFileMatcher implements a legacy RSpec matcher
protocol. For the current protocol you should expose the failure messages
via the `failure_message` and `failure_message_when_negated` methods.
(Used from /Users/ria10/IdeaProjects/ria10-web/spec/models/user.rb:8:in `block (2 levels) in ')

                                                                                                                                                              • -

~snip~

むむぅ。

これはpaperclipか。対応してるのかしら。ごく最近対応されていた。Gemにもなってた。
https://github.com/thoughtbot/paperclip/issues/1568#issuecomment-48601191

Gemfile書き換えてupdateして再実行

$ rspec
................................................................................................................................................................................................................................................................................................................................

Deprecation Warnings:

Requiring `rspec/autorun` when running RSpec via the `rspec` command is deprecated. Called from /Users/ria10/IdeaProjects/ria10-web/vendor/bundle/ruby/2.1.0/gems/activesupport-4.1.4/lib/active_support/dependencies.rb:247:in `require'.

If you need more of the backtrace for any of these deprecations to
identify where to make the necessary changes, you can configure
`config.raise_errors_for_deprecations!`, and it will turn the
deprecation warnings into errors, giving you the full backtrace.

1 deprecation warning total

むむむぅ。

でもこれはWarningどおりやるだけで、spec_helper.rbから

require 'rspec/autorun'

を削除するだけだった。


これでテストがキレイに通った!


パーフェクト Ruby on Rails

パーフェクト Ruby on Rails