[Ruby on Rails]パスワードリセットをRSpecでテストする方法

はじめに

こんにちは!運営メンバーのなかやん(@nakayarn)といいます!前回、会員管理システムのSendGrid APIを用いたリセットメールの実装を行ったので、今回はそのテスト内容について記載させていただきます。

[Ruby on Rails]SendGridを用いたパスワードリセット機能の実装

前回同様、会員管理システムについては@adachin0817さんのスライドを見てください!

ローカル開発環境

  • バックエンド:Ruby on Rails(API)
  • フロントエンド:React
  • 開発環境:Docker

今回のテストに関しては、既に導入済みのRspecでテストを実施します。

Rspecとは?

RubyやRubyOnRailsの代表的なテストフレームワークです。クラスやメソッド単位でテストすることができ、単体テスト・総合テスト・システムテストなど、幅広いテストに対応できます。

実装

今回、controllerではcreate・show・updateを作成したので、以下のテストを実施。

  • POST /create(リセット要求)のテスト
  • GET /show(トークン検証)のテスト
  • PATCH /update(パスワード更新)のテスト

また、modelにtoken_valid?メソッドを作成したので、境界値テストを実施します。

  • テスト環境の準備

まずは、メールを送信テストを実施するための設定を行います。

  • techbull-app/spec/requests/api/password_resets_spec.rb

beforeを使用して、メール送信設定を行い、afterでメール内容をクリアにしています。これにより、各テストが実行された前後にbeforeとafterが実行され、各テストが独立した状態で実行されるようにしています。

  • POST /create(リセット要求)のテスト

このテストでは以下の点をテストします。

  • 正常系と異常系のテスト
  • 存在しないメールアドレスでも成功メッセージを返すか?
  • エラーハンドリングテスト

トークンの更新に関しては、travel_toを使用して現在時刻を固定し、リセットパスワードを送信した日時をテストしています。travel_toで時刻を固定することで、コード実行とテスト検証の間に生じるわずかな時間経過による誤差を防いでくれます。

  • GET /show(トークン検証)のテスト

以下の点をテストしていきます。

  • 有効なトークン・無効なトークン
  • 期限切れトークン
  • 存在しないトークン

この中で、無効なトークン・期限切れ・存在しないトークンのテストを行なっていますが、エラーを返す際には、同じメッセージを返すようにしています(セキュリティの観点から攻撃者に情報を与えないため)。このメッセージが正しく機能するかを確認します。

また、ここではコントローラーの “Get /show” の動きをテストしたいので、token_valid?をモックして値を固定しています。

(ここで記載されているtoken_valid?は後述するuser_spec.rbにテストを記載しています)

  • PATCH /update(パスワード更新)のテスト

このテストでは以下の点をテストします。

  • パスワードの一致確認
  • パスワードが要件を満たしているかのチェック
  • トークンのクリア確認

ここではトークンとパスワード関連の確認を行うため、冒頭で作成したreset_tokenhashed_tokenを使用してテストしていきます。なお、既にユーザーにトークンが送付されている後なので、エラーメッセージはユーザビリティを考えて詳細な内容を出力しています。

  • token_valid?(有効期限チェック)のテスト

このテストでは以下の点をテストします。

  • 境界値テスト(ちょうど10分前と10分1秒前の場合)
  • techbull-app/spec/models/user_spec.rb

有効期限が切れている場合とそうでない場合のテストを行なっています。その際に、トークンの有効期限のギリギリの「ちょうど10分前」と「10分1秒」の場合をテストしています。

テストの実行

テストの実行は以下のコマンドで実行します。

画像のように failures が 0 になっていればテストは通っています。

おわりに

今回、リセットメールのテストを書くことで、travel_toを使用した時間固定や境界値テストについて学ぶことができました。今回は、機能実装を先に行なってしまったのですが、今後はTDD(テスト駆動開発)を実践し、次からはテストファーストを心がけようと思います。

最後まで読んでいただき、ありがとうございました!

コメントする

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

上部へスクロール