システムスペック

導入

以下追加

Gemfile
gem 'webdrivers' #ChromeDriverのインストールを簡単にしてくれる?
  gem 'capybara' #E2ETest(UIテスト)のためのrubyフレームワーク
spec/spec_helper.rb
require 'capybara/rspec'

rails g rspec:system tasksでシステムスペックファイルの作成

ドライバ設定

ドライバとは、Capybaraを使ったテスト/Specにおいて、ブラウザ相当の機能を利用するために必要なプログラム

spec/support/capybara.rb
RSpec.configure do |config|
  config.before(:each, type: :system)do
    driven_by(:selenium_chrome_headless)
  end

ログイン前・ログイン後に分けてテストを実施するので、モジュールにログイン処理を設定

spec/support/login_macros.rb
module LoginModule
  def login(user)
    visit login_path
    fill_in 'Email', with: user.email
    fill_in 'Password', with: 'password'
    click_button 'Login'
  end
end

spec/rails_helper.rbで読み込み

config.include LoginMacros

rails_helper.rbを読み込むために、各Specファイルに、require 'rails_helper'を設定

spec/support以下を読み込むように設定

コメントアウトを外す
Dir[Rails.root.join('spec', 'support', '*', '.rb')].sort.each { |f| require f }を追記

システムスペックファイルの設定をする 長いので省略

モデルスペック

導入

モデルスペックの作成

rails g rspec:model taskでタスクモデルを作成

FactoryBotの設定

emailとtitleはユニーク制約がついている

spec/factories/users.rb
FactoryBot.define do
  factory :user do
    sequence(:email) { |n| "tester#{n}@example.com" }
    password { 'password' }
    password_confirmation { 'password' }
  end
end

sequenceとは、連番データを作成できるもの
ユニークな値にすることができる

spec/factories/tasks.rb
FactoryBot.define do
  factory :task do
    sequence(:title, "title_1")
    content { 'Content' }
    status { 'todo' } #enumで定数を設定している。
    deadline { Date.current.tomorrow }
    association :user
  end
end

sequence(:title, "title_1")の部分は、sequenceはブロックを渡さず第2引数を渡すと、.nextが呼ばれる。変えたい場所が末尾の場合のみ使える書き方 なのかなと思う

FactoryBotは、FactoryBot.create(略)のように記述するが、以下の設定をしておくと、FactoryBotを省略できる

spec/rails_helper.rb
RSpec.configure do |config|
  config.include FactoryBot::Syntax::Methods #追記
end

テストコード記述

spec/models/task_spec.rb
require 'rails_helper'

RSpec.describe Task, type: :model do
  pending "add some examples to (or delete) #{__FILE__}"
  describe 'validation' do
    it 'is valid with all attributes' do
      task = build(:task)
      expect(task).to be_valid
      expect(task.errors).to be_empty
    end

    it 'is invalid without title' do
      task_without_title = build(:task, title: "")
      expect(task_without_title).to be_invalid
      expect(task_without_title.errors[:title]).to eq ["can't be blank"]
    end

    it 'is invalid without status' do
      task_without_status = build(:task, status: nil)
      expect(task_without_status).to be_invalid
      expect(task_without_status.errors[:status]).to eq ["can't be blank"]
    end

    it 'is invalid with a duplicate title' do
      task = create(:task)
      task_with_duplicated_title = build(:task, title: task.title)
      expect(task_with_duplicated_title).to be_invalid
      expect(task_with_duplicated_title.errors[:title]).to eq ["has already been taken"]
    end

    it 'is valid with another title' do
      task = create(:task)
      task_with_another_title = build(:task, title: 'another_title')
      expect(task_with_another_title).to be_valid
      expect(task_with_another_title.errors).to be_empty
    end
  end
end

validとinvalid

valid

バリデーションが実行された結果 エラーが無い場合trueを返し,エラーが発生した場合falseを返す

invalid

validとは逆の結果を返す エラーが発生した場合true,エラーが無い場合falseを返す

Rspecセットアップ

環境構築

Gemfile.rb
  group :development, :test do
    gem 'rspec-rails', '~> 5.0.0'
    gem 'factory_bot_rails'
  end

bundle install後rails g rspec:installコマンドで.rspec, spec_helper.rb, rails_helper.rbを生成

create  .rspec
  create  spec
  create  spec/spec_helper.rb
  create  spec/rails_helper.rb
.rspec
--require spec_helper

他にも以下のように便利なものがあるらしい 出力結果を色分け
--color
rails_helperの読み込み
--require rails_helper
出力結果をドキュメント風に見やすくする
--format documentation

vendor/bundle以下に取得したRubyのライブラリをリモートリポジトリにプッシュしたくないので以下を記述

.gitignore
  /vendor/bundle

spec/support/配下のファイルを読み込むために、以下のコメントアウトを外す

rails_helper.rb
  Dir[Rails.root.join('spec', 'support', '**', '*.rb')].each { |f| require f }

以下の記述を追加してFactoryBot.をいちいち書かずにインスタンスを生成できるようにする

rails_helper.rb
 RSpec.configure do |config|
    config.include FactoryBot::Syntax::Methods
  end

特定のテストケースのみ実行できるようにするために、以下追記してfocus: trueを使えるように設定

spec_helper.rb
RSpec.configure do |config|
    config.filter_run_when_matching :focus
  end

これにより、テストブロックにfをつけることでそのテストブロックのみテストが実行される
fdescribe, fcontext, fit のように使う

参考記事:

github.com

!がつくときとつかないときの違い

!がつくときとつかないときの違い

結論、処理が失敗したときの挙動が違う

saveを使う場合

掲示板作成ファームなど、処理が失敗する可能性が想定されて、失敗した場合に何かハンドリングしたい場合

save!を使う場合

削除機能など、処理が必ず成功すると想定されていて、万が一失敗したらそこで処理を中断したい場合

HTMLのdata属性

data属性について

f:id:uuuuuDi_3712:20220117164743p:plain
上記のような、ダイアログを表示させるためにdata属性を使用する

導入

<%= link_to 'リンク', ○○_path, data: { confirm: 'ダイアログで表示させるメッセージ' } %>とすると先程の画像のようなダイアログを使用できる

content_for

content_forとは

各ページごとにタイトルを変更したい場合に使用
コンテンツを名前付きのyieldブロックとしてレイアウトに挿入できる

ヘルパーメソッドの作成

app/helpers/application_helper.rb
def page_title(page_title = '')
    base_title = 'Ruby on Rails 学習記録'

#ページタイトルが空がどうかで処理が変わる  
#条件式(.empty?) ? trueの処理 : falseの処理の形で記述  
#emptyはオブジェクトの中身が空の場合にtrueを返すメソッド

    page_title.empty? ? base_title : page_title + " | " + base_title
  end

作成したヘルパーで全体のレイアウト

app/views/layouts/application.html.erb
<title><%= page_title(yield(:title)) %></title>

各ビューファイルに記述

<%= content_for(:title, t('.title')) %>

yieldメソッド
ビューを挿入すべき場所を指定するのに使用する