ためすう
rspec で WebMock を使う
2019-06-08やったこと
WebMock の stub を利用して rspec でテストを書いてみます。
確認環境
$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]
$ rails --version
Rails 5.2.3
$ gem list | grep rspec-rails
rspec-rails (3.8.2)
調査
インストール
Gemfile
group :development, :test do
gem 'webmock'
end
$ bundle install
spec/models/task5_spec.rb
require 'rails_helper'
require 'webmock/rspec'
RSpec.describe Task, type: :model do
before do
WebMock.enable!
end
it 'test1' do
WebMock.stub_request(:get, "http://localhost").to_return(
body: JSON.generate({b: 3, c: 8}),
status: 200
)
p Net::HTTP.get('localhost', '/')
end
end
出力結果
$ bundle exec rspec spec/models/task5_spec.rb
"{\"b\":3,\"c\":8}"
.
Finished in 0.0048 seconds (files took 1.5 seconds to load)
1 example, 0 failures
参考
rspec で Faraday の stub を使う
2019-06-07やったこと
Faraday の stub を利用して rspec でテストを書いてみます。
確認環境
$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]
$ rails --version
Rails 5.2.3
$ gem list | grep rspec-rails
rspec-rails (3.8.2)
$ gem list | grep faraday
faraday (0.15.4)
調査
spec/models/task4_spec.rb
require 'rails_helper'
RSpec.describe Task, type: :model do
it 'test1 allow success' do
conn = Faraday.new do |conn|
conn.adapter :test, Faraday::Adapter::Test::Stubs.new do |stub|
stub.get '/fuga/test.json' do
[200, {}, JSON.generate({a: 'hogehoge'})]
end
end
end
response = conn.get '/fuga/test.json'
p response.body
end
end
出力結果
$ bundle exec rspec spec/models/task4_spec.rb
"{\"a\":\"hogehoge\"}"
.
Finished in 0.00817 seconds (files took 2.74 seconds to load)
1 example, 0 failures
所感
こんな感じでレスポンスを差し替えることができます。
メリット
外部サービスのAPIのテストなどがやりやすくなりそうです。
デメリット
外部サービスのAPIのレスポンスが変わってもテストでは気づきにくくなりそうです。
レスポンスが変わったことについて、テストを実行しないと気付かないという体制の方が問題だと思うので、デメリットはあまり気にしなくても良いかもしれません。
参考
Ruby の reject を使う
2019-06-07やったこと
Ruby で reject を使ってみます。
確認環境
$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]
調査
test.rb
ary = ["a", "", nil]
p ary
p ary.compact.reject(&:empty?)
出力結果
$ ruby test.rb
["a", "", nil]
["a"]
参考
Ruby の compact を使う
2019-06-07やったこと
Ruby で compact を使ってみます。
確認環境
$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]
調査
test.rb
ary = ["a", "", nil, 4]
p ary
p ary.compact
出力結果
$ ruby test.rb
["a", "", nil, 4]
["a", "", 4]
compact は自身から nil を取り除いた配列を生成して返します。
参考
Rails5 で Faraday を使ってみる
2019-06-07やったこと
Rails5 で Faraday を使ってみます。
確認環境
$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]
$ rails --version
Rails 5.2.3
調査
インストール
Gemfile
gem 'faraday'
$ bundle install
使ってみる
app/controllers/tasks_controller.rb
class TasksController < ApplicationController
def index
render :json => {c:3, d:4}
end
def new
uri = 'http://127.0.0.1:3000/'
conn = Faraday::Connection.new(:url => uri) do |builder|
builder.use Faraday::Adapter::NetHttp
builder.use Faraday::Response::Logger
end
res = conn.get "/", {a:1, b:2}
logger.debug(res.body)
end
end
URL にアクセス
$ curl http://localhost:3000/tasks/new
$ less log/development.log
Started GET "/tasks/new" for ::1 at 2019-06-07 00:37:53 +0900
Processing by TasksController#new as */*
Started GET "/?a=1&b=2" for 127.0.0.1 at 2019-06-07 00:37:53 +0900
Processing by TasksController#index as */*
Parameters: {"a"=>"1", "b"=>"2"}
Completed 200 OK in 1ms (Views: 0.3ms | ActiveRecord: 0.0ms)
{"c":3,"d":4}
Rendering tasks/new.html.erb within layouts/tasks
Rendered tasks/new.html.erb within layouts/tasks (0.3ms)
Completed 200 OK in 45ms (Views: 33.4ms | ActiveRecord: 0.0ms)
参考
Rails5 で rubocop を使ってみる
2019-06-06やったこと
今回、 rubocop を使ってみます。
rubocop は、static code analyzer です。(引用そのまま)
確認環境
$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]
$ rails --version
Rails 5.2.3
調査
インストールその1 (失敗)
Gemfile
gem 'rubocop', '~> 0.71.0', require: false
$ bundle install
なんかエラーが出て、gem 追加しろと言われています。
Post-install message from rubocop:
Rails cops will be removed from RuboCop 0.72. Use the `rubocop-rails` gem instead.
Put this in your `Gemfile`.
```rb
gem 'rubocop-rails'
```
And then execute:
```sh
$ bundle install
```
Put this into your `.rubocop.yml`.
```yaml
require: rubocop-rails
```
More information: https://github.com/rubocop-hq/rubocop-rails
インストールその2 (成功)
Gemfile
gem 'rubocop', '~> 0.71.0', require: false
gem 'rubocop-rails'
$ bundle install
使ってみる
ヘルプ
$ bundle exec rubocop -h
手元のファイルで実行する
$ bundle exec rubocop app/controllers/tasks_controller.rb
Inspecting 1 file
C
Offenses:
app/controllers/tasks_controller.rb:1:1: C: Style/Documentation: Missing top-level class documentation comment.
class TasksController < ApplicationController
^^^^^
app/controllers/tasks_controller.rb:1:1: C: Style/FrozenStringLiteralComment: Missing magic comment # frozen_string_literal: true.
class TasksController < ApplicationController
^
app/controllers/tasks_controller.rb:14:5: C: Style/RedundantBegin: Redundant begin block detected.
begin
^^^^^
app/controllers/tasks_controller.rb:17:5: C: Style/RescueStandardError: Avoid rescuing without specifying an error class.
rescue => e
^^^^^^
app/controllers/tasks_controller.rb:28:3: C: Style/EmptyMethod: Put empty method definitions on a single line.
def new ...
^^^^^^^
app/controllers/tasks_controller.rb:47:12: C: Style/HashSyntax: Use the new Ruby 1.9 hash syntax.
render :json => tmp.to_jso
C は、Convention です。
ここには載っていませんが、
W (Warning)、E (Error)、F (Fatal) とあります。
参考
Rails5 で例外が発生したときに backtrace を出す
2019-06-06やったこと
Rails5 で例外が発生したときにどこで発生したのかを知るため
Exception クラスの backtrace を使ってみます。
確認環境
$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]
$ rails --version
Rails 5.2.3
調査
ソースコード編集
app/controllers/tasks_controller.rb
class TasksController < ApplicationController
def index
begin
@task = Task.new
private_dummy
rescue => e
logger.debug(e.backtrace.join("\n"))
logger.info('logger.info')
logger.info(e)
end
end
def private_dummy
raise 'private_dummy'
end
end
ログ確認
log/development.log
Started GET "/" for ::1 at 2019-06-06 22:12:58 +0900
Processing by TasksController#index as HTML
/Users/xxxxx/sample2/app/controllers/tasks_controller.rb:25:in `private_dummy'
/Users/xxxxx/sample2/app/controllers/tasks_controller.rb:16:in `index'
... (省略)
logger.info
private_dummy
参考
Rails5 のレイアウト指定をコントローラ単位で行う(自動)
2019-06-03やったこと
Rails5 のレイアウトをコントローラ単位で適用する方法について調べました。
今回はコントローラに明示的に設定せずに、適用する方法を試します。
確認環境
$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]
$ rails --version
Rails 5.2.3
調査
app/views/layouts/tasks.html.erb
<!DOCTYPE html>
<html>
<head>
<title>Task-Sample2</title>
<%= csrf_meta_tags %>
<%= csp_meta_tag %>
<%= stylesheet_link_tag 'application', media: 'all', 'data-turbolinks-track': 'reload' %>
<%= javascript_include_tag 'application', 'data-turbolinks-track': 'reload' %>
</head>
<body>
<p>Taskのレイアウト<p>
<%= yield %>
</body>
</html>
下記のようなコントローラがあるとします。
app/controllers/tasks_controller.rb
class TasksController < ApplicationController
def new
end
end
コントローラ側では特に指定しなくても、レイアウトが切り替わります。
参考
rspec の allow と expect の違い
2019-06-03やったこと
Rails5 で使っている rspec の allow と expect の違いについて調べます。
確認環境
$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]
$ rails --version
Rails 5.2.3
$ gem list | grep rspec-rails
rspec-rails (3.8.2)
調査
spec/models/task3_spec.rb
require 'rails_helper'
RSpec.describe Task, type: :model do
it 'test1 allow success' do
o = Object.new
allow(o).to receive(:display).and_return(:display_value2)
expect(o.display).to eq(:display_value2)
end
it 'test1 expect fail' do
o = Object.new
expect(o).to receive(:display).and_return(:display_value)
end
it 'test1 expect success' do
o = Object.new
expect(o).to receive(:display).and_return(:display_value)
expect(o.display).to eq(:display_value)
end
end
出力結果
$ bundle exec rspec spec/models/task3_spec.rb
.F.
Failures:
1) Task test1 expect fail
Failure/Error: expect(o).to receive(:display).and_return(:display_value)
(#<Object:0x00007fef8b614e28>).display(*(any args))
expected: 1 time with any arguments
received: 0 times with any arguments
# ./spec/models/task3_spec.rb:15:in `block (2 levels) in <top (required)>'
Finished in 0.02301 seconds (files took 1.13 seconds to load)
3 examples, 1 failure
Failed examples:
rspec ./spec/models/task3_spec.rb:12 # Task test1 expect fail
allow と expect の違いは、呼び出しの検査をするかどうかになります。
expect で定義したメソッドを呼び出さないとエラーになります。
参考
Rails5 の rspec で allow_any_instance_of を使う
2019-06-02やったこと
Rails5 の rspec で allow_any_instance_of を使ってみます。
確認環境
$ ruby --version
ruby 2.6.3p62 (2019-04-16 revision 67580) [x86_64-darwin17]
$ rails --version
Rails 5.2.3
$ gem list | grep rspec-rails
rspec-rails (3.8.2)
調査
allow_any_instance_of は、不具合があるので
あまり使わない方が良いようです。
spec/models/task3_spec.rb
require 'rails_helper'
RSpec.describe Task, type: :model do
it 'test1 allow_any_instance_of' do
allow_any_instance_of(Object).to receive(:display).and_return(:display_value)
o = Object.new
expect(o.display).to eq(:display_value)
end
end
出力結果
$ bundle exec rspec spec/models/task3_spec.rb
.
Finished in 0.0136 seconds (files took 0.86209 seconds to load)
1 example, 0 failures