編集フォームでの更新テストを自動化しよう

学習の目標

本章では、以下の内容を学習します。

  • Railsアプリケーションにおける編集機能の基本的な実装方法について、コントローラからビューまでの一連の流れを体系的に理解する
  • 既存のレコードを安全に更新するための設計パターンと、Strong Parametersを活用したセキュアな実装手法を習得する
  • システムスペックにおける事前データの準備方法と、beforeブロックを使用した効率的なテストコードの書き方を学ぶ
  • 一覧画面から編集画面への遷移、データの更新、エラー処理など、実際のユーザー操作を想定したテストシナリオの組み立て方を実践的に理解する

はじめに

前回はバリデーションのテストについて学習しました。 新規作成機能では、空のデータにユーザーが情報を入力する流れでしたが、実際のWebアプリケーションでは、既存のデータを修正する編集機能も重要な要素です。

本章では、既存のTodoを編集する機能のテストを実装していきます。 編集機能では、既存データの取得、フォームでの表示、更新処理という一連の流れをテストすることになります。

編集機能の実装

まずはコントローラの実装から始めましょう。 編集機能では、データの表示と更新の2つのアクションが必要になります。

コントローラの実装

app/controllers/todos_controller.rbを開きます。 前回のrails generateコマンドで、editアクションとupdateアクションの雛形は作られていますが、実装はまだ行われていません。

これらのアクションを以下のように実装していきます。

class TodosController < ApplicationController
# 既存のアクション(index, new, create)は省略
def edit
@todo = Todo.find(params[:id])
end
def update
@todo = Todo.find(params[:id])
if @todo.update(todo_params)
redirect_to todos_path
else
render :edit
end
end
private
def todo_params
params.require(:todo).permit(:title, :description)
end
end

コントローラの動作解説

このコードについて説明していきましょう。

editアクションでは、URLのパラメータ(id)を使って編集対象のTodoを取得します。 このTodoは、編集用フォームで使用されます。

updateアクションでは、同じくURLのパラメータからTodoを取得し、フォームから送信されたデータで更新を試みます。 更新に成功したら一覧画面に戻り、失敗した場合は編集画面を再表示します。

編集フォームの作成

次に、編集用のビューファイルを作成します。 app/views/todos/edit.html.erbを開きます。

これも雛形が生成されていますが、実装はまだ行われていないため、以下のように実装していきます。

<h1>Todo編集</h1>
<% if @todo.errors.any? %>
<div class="error-messages">
<h2><%= @todo.errors.count %>件のエラーがあります</h2>
<ul>
<% @todo.errors.full_messages.each do |message| %>
<li><%= message %></li>
<% end %>
</ul>
</div>
<% end %>
<%= form_with(model: @todo, local: true) do |f| %>
<div>
<%= f.label :title, 'タイトル' %>
<%= f.text_field :title %>
</div>
<br>
<div>
<%= f.label :description, '説明' %>
<%= f.text_area :description %>
</div>
<div>
<%= f.submit '更新' %>
</div>
<% end %>
<%= link_to '一覧に戻る', todos_path %>

このフォームは、新規作成のフォームとほぼ同じ構造です。 主な違いは、タイトルが「Todo編集」になっていることと、送信ボタンのラベルが「更新」に変更されている点です。

一覧画面への編集リンクの追加

続いて、一覧画面から編集画面へ移動できるように、リンクを追加します。 ユーザーが直感的に編集操作を行えるようにするためです。

app/views/todos/index.html.erbを開いて、各Todoの表示部分に編集リンクを追加します。

<h1>Todo一覧</h1>
<div class="todos">
<% @todos.each do |todo| %>
<div class="todo">
<h2><%= todo.title %></h2>
<p><%= todo.description %></p>
<p>
状態: <%= todo.completed ? "完了" : "未完了" %>
<%= link_to '編集', edit_todo_path(todo) %>
</p>
</div>
<% end %>
</div>
<%= link_to '新規作成', new_todo_path %>

動作確認

では、bundle exec rails sでサーバーを起動して、編集機能が正しく動作するか確認してみましょう。

bundle exec rails s

ブラウザでhttp://localhost:3000/todosにアクセスし、以下の操作を行います。

まず、一覧画面に表示されているTodoの「編集」リンクをクリックします。 次に、タイトルと説明を変更してみましょう。 最後に、「更新」ボタンをクリックします。

一覧画面に戻り、変更した内容が反映されていることを確認します。 動作確認ができたら、Ctrl+Cでサーバーを停止します。

編集機能のテストの実装

実際の動作が確認できたので、これをテストコードで表現していきましょう。 編集機能では、既存データの準備、編集画面への遷移、データの更新という流れをテストします。

spec/system/todos_spec.rbに編集機能のテストを追加します。

require 'rails_helper'
RSpec.describe 'Todo管理', type: :system do
# 既存のテストは省略...
describe '編集' do
# テストで使用するTodoを準備
before do
@todo = Todo.create!(
title: 'テスト駆動開発',
description: 'アプリケーションをテスト駆動で実装する'
)
end
it 'Todoを編集できる' do
# Todo一覧画面を表示
visit todos_path
# 編集リンクをクリック
click_link '編集'
# フォームに新しい値を入力
fill_in 'タイトル', with: 'RSpec入門'
fill_in '説明', with: 'システムスペックについて理解を深める'
# 更新ボタンをクリック
click_button '更新'
# 一覧画面に遷移していることを確認
expect(current_path).to eq todos_path
# 変更した内容が表示されていることを確認
expect(page).to have_content('RSpec入門')
expect(page).to have_content('システムスペックについて理解を深める')
end
it '編集画面で不正な値を入力するとエラーメッセージが表示される' do
# 編集画面を表示
visit edit_todo_path(@todo)
# 不正な値を入力
fill_in 'タイトル', with: '' # タイトルを空に
fill_in '説明', with: '短すぎ' # 説明を10文字未満に
# 更新ボタンをクリック
click_button '更新'
# エラーメッセージが表示されることを確認
expect(page).to have_content('Title can\'t be blank')
expect(page).to have_content('too short')
end
end
end

テストコードの詳細解説

このテストについて説明していきましょう。

テストデータの準備

まずbeforeブロックを使用してテストで使用するTodoを作成し、後に編集画面を表示するときのために@todoというインスタンス変数に格納しています。 このTodoは、各テストケースで必要になったときに利用できるように準備されます。

正常系のテスト

次に、正常系と異常系の2つのテストケースを実装しました。

正常系のテストでは以下の点を確認しています。

まず、一覧画面から編集画面に移動できることを確認します。 次に、フォームに新しい値を入力できることをテストします。 最後に、更新後に一覧画面に戻り、変更が反映されていることを検証します。

異常系のテスト

異常系のテストでは以下の点を確認しています。

バリデーションエラーが正しく機能することを検証します。 また、エラーメッセージが適切に表示されることも確認します。

テストの実行

では、テストを実行してみましょう。

$ bundle exec rspec spec/system/todos_spec.rb
Todo管理
Todo一覧を表示する
新規Todoを作成できる
バリデーション
タイトルと説明が未入力の場合、エラーメッセージが表示される
説明が10文字未満の場合、エラーメッセージが表示される
エラー後、正しい入力で登録できる
編集
Todoを編集できる
編集画面で不正な値を入力するとエラーメッセージが表示される
Finished in 0.12487 seconds (files took 0.89012 seconds to load)
7 examples, 0 failures

全てのテストが成功しました!これにより、編集機能が期待通りに動作していることが確認できます。

まとめ

本章では、編集機能の実装とそのテストについて学習しました。

具体的には以下の点をテストできるようになりました。 まず、Todo一覧画面から編集画面への遷移ができることを確認できます。 次に、編集フォームでの値の更新が正しく行えることを検証できます。 そして、バリデーションエラーが適切に処理されることも確認できます。

編集機能のテストでは、既存データの準備から更新処理まで、一連の流れを包括的にテストできました。

このセクションは有料サブスクリプションへの登録、またはログインが必要です。完全なコンテンツにアクセスするには、料金ページ(/pricing)をご覧ください。購入済みの場合は、ログインしてください。

Basicプランでより詳しく学習

この先のコンテンツを読むにはBasicプラン以上が必要です。より詳細な解説、実践的なサンプルコード、演習問題にアクセスして学習を深めましょう。

作成者:とまだ
Previous
フォームのバリデーション検証を自動化しよう