このカテゴリーのサポートは終了しました。
今回達成すること
ユーザーモデルで設定したバリデーションが正しく機能しているか、Railsのテスト機能を使って検証していきます。
今回テストする項目
ユーザーモデルのテスト項目は以下のとおりです。
email保存状態のテスト
- emailが小文字で保存されているか
emailバリデーションテスト
- 空の場合エラーになっているか(入力必須)
- 256文字以上の場合エラーになっているか
- 不正な書式にエラーを出しているか
email一意性テスト
- 同じemailのユーザーは何人でも保存できているか
- 同じemailでかつ、アクティブなユーザーが既に存在しているときにエラーを出しているか
passwordバリデーションテスト
- 空の場合エラーになっているか(入力必須)
- 8文字以下のパスワードにエラーを出しているか
- 72文字を超える場合はエラーを出しているか
- 不正な書式はエラーになっているか
この記事の読み方
最終的な
以下、全て
編集の都度Railsのテストコマンドを実行し、テストが通ることを確認した上で次に進むことをおすすめします。
myapp $ rais t #もしくは $ rails test
それでは実装に入りましょう。
email保存状態のテスト
emailが小文字で保存されているか?
test/models/user_test.rb
test "email_downcase" do
# emailが小文字で保存されているか
email = "USER@EXAMPLE.COM"
user = User.create(email: email, password: "password")
assert user.email == email.downcase
end
-
assert
引数に渡した式がtrueであるか判定します。
emailバリデーションテスト
空の場合にエラーになっているか?(入力必須)
test/models/user_test.rb
test "email_validator" do
user = User.new(password: "password")
# 入力必須
user.save
required = ["メールアドレスを入力してください"]
assert_equal(required, user.errors.full_messages)
end
-
assert_equal(期待値, 実際値)
期待値と実際値が等しいかを判定します。
この場合、用意されたエラーメッセージと実際のエラーメッセージが等しいかを判定しています。
文字数が256文字以上の場合エラーになっているか
test/models/user_test.rb
test "email_validator" do
...
# OK 255文字以下
ok_email = "#{"a" * (255 - 12)}@example.com"
user.email = ok_email
assert user.save
# NG 255文字超
user.email = ok_email + "a"
user.save
length = ["メールアドレスは255文字以内で入力してください"]
assert_equal(length, user.errors.full_messages)
end
不正な書式にエラーを出しているか
- ハイフンとアンダーバー、プラスの記号が混ざったemailはバリデーションを通っているか?
- その他の記号、大文字、@が抜けている場合はエラーとなっているか?
test/models/user_test.rb
test "email_validator" do
...
# OK 書式チェック
# /\A\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*\z/
oks = %w(
A@EX.COM a-_@e-x.c-o_m.j_p a.a@ex.com a@e.co.js 1.1@ex.com a.a+a@ex.com
)
oks.each do |ok|
user.email = ok
assert user.save
end
# NG 書式チェック
ngs = %w(
aaa a.ex.com メール@ex.com a~a@ex.com a@|.com a@ex./ .a@ex.com
a@ex.com A@ex.com a@?,com 1@ex.com "a"@ex.com a@ex@co.jp
)
format = ["メールアドレスの書式が正しくありません"]
ngs.each do |ng|
user.email = ng
user.save
assert_equal(format, user.errors.full_messages)
end
end
email一意性テスト
同じemailのユーザーは何人でも保存できているか?
test/models/user_test.rb
test "email_uniqueness" do
# アクティブなユーザーがいない場合に同じユーザーは保存できているか
10.times do |n|
user = User.new(email: "user@example.com", password: "passowrd")
assert user.save
end
end
アクティブなユーザーが既に存在しているときにエラーを出しているか
- アクティブプラグがtrueのユーザーがいるときは、同じemailでは保存できないようになっているか?
- また、そのemailが大文字の場合でもエラーを吐いているか?
- アクティブなユーザーが存在しなくなったら、同じemailで保存できているか?
test/models/user_test.rb
test "email_uniqueness" do
...
assert @user.activated
user = @user.dup
# NG アクティブなユーザーが既に存在している場合
user.save
unique = ["メールアドレスはすでに存在します"]
assert_equal(unique, user.errors.full_messages)
# NG emailが大文字でもエラーを出しているか
user.email = @user.email.upcase
user.save
assert_equal(unique, user.errors.full_messages)
# OK アクティブなユーザーがいなくなった場合
@user.update(activated: false)
assert user.save
end
user = @user.dup
dup
はオブジェクトのコピーを作成するRubyのメソッドです。
dup
は保存前の値だけをコピーするのに対して、 clone
は、idやcreated_at(作成時間)までコピーします。
-
dup
でコピーしたユーザーオブジェクト -
clone
でコピーしたユーザーオブジェクト
passwordバリデーションテスト
空の場合エラーになっているか?(入力必須)
test/models/user_test.rb
test "password_validator" do
user = User.new(email: "user@example.com")
# 入力必須
user.save
required = ["パスワードを入力してください"]
assert_equal(required, user.errors.full_messages)
end
8文字以下のパスワードにエラーを出しているか?
test/models/user_test.rb
test "password_validator" do
...
# NG 8文字未満
user.password = "a" * 7
user.save
min_length = ["パスワードは8文字以上で入力してください"]
assert_equal(min_length, user.errors.full_messages)
end
72文字を超える場合はエラーを出しているか?
test/models/user_test.rb
test "password_validator" do
...
# NG 72文字超
user.password = "a" * 73
user.save
max_length = ["パスワードは72文字以内で入力してください"]
assert_equal(max_length, user.errors.full_messages)
# ok 72文字以下
user.password = "a" * 72
assert user.save
end
不正な書式はエラーになっているか
test/models/user_test.rb
test "password_validator" do
...
# NG 書式チェック
# VALID_PASSWORD_REGEX = /\A[\w\-]+\z/
ngs = %w(pass/word pass.word |~=?+"a" 12345678 ABCDEFGH)
format = ["パスワードは半角英数字、ハイフン、アンダーバーが使えます"]
ngs.each do |ng|
user.password = ng
user.save
assert_equal(format, user.errors.full_messages)
end
end
全ての編集が完了したらテストコマンドを実行してエラーが出なければOKです。
myapp $ rails t
...
5 tests, 47 assertions, 0 failures, 0 errors, 0 skips
本番環境にpushする
ブランチを作成している場合はmasterブランチにマージします。
myapp $ git commit -am "user_validate_test"
myapp $ git checkout master
myapp $ git merge user_modeling
myapp $ git push
myapp $ git push heroku
まとめ
これにてユーザーモデル開発は終了です。
今回のユーザーモデル開発は、
- マイグレーションファイルの作成
$ rails db:migrate
を実行してテーブルの作成- バリデーションの設定
- seedデータの投入
- バリデーションテスト
の流れで一連の作業を行いました。(4と5は逆でもOK)
今後もこの流れを覚えておくと良きです。
さて、次回は?
さて、次回は。。。
今悩んでいるのですが、Railsチュートリアルに従ってユーザーログイン機能の実装をしましょうか。
はたまた、モデルを一通り作ってしまうか。。。
ログイン機能の場合、JWT認証を使って実装していきます。
更新をご期待ください。(歯切れが悪くてすみません。)
最終的なuser_test.rb
test/models/user_test.rb
require 'test_helper'
class UserTest < ActiveSupport::TestCase
def setup
init
end
test "sqlite3_test" do
assert_not_nil @user
end
test "email_downcase" do
# emailが小文字で保存されているか
email = "USER@EXAMPLE.COM"
user = User.create(email: email, password: "password")
assert user.email == email.downcase
end
test "email_validator" do
user = User.new(password: "password")
# 入力必須
user.save
required = ["メールアドレスを入力してください"]
assert_equal(required, user.errors.full_messages)
# OK 255文字以下
ok_email = "#{"a" * (255 - 12)}@example.com"
user.email = ok_email
assert user.save
# NG 255文字超
user.email = ok_email + "a"
user.save
length = ["メールアドレスは255文字以内で入力してください"]
assert_equal(length, user.errors.full_messages)
# OK 書式チェック
# /\A\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*\z/
oks = %w(
A@EX.COM a-_@e-x.c-o_m.j_p a.a@ex.com a@e.co.js 1.1@ex.com a.a+a@ex.com
)
oks.each do |ok|
user.email = ok
assert user.save
end
# NG 書式チェック
ngs = %w(
aaa a.ex.com メール@ex.com a~a@ex.com a@|.com a@ex./ .a@ex.com
a@ex.com A@ex.com a@?,com 1@ex.com "a"@ex.com a@ex@co.jp
)
format = ["メールアドレスの書式が正しくありません"]
ngs.each do |ng|
user.email = ng
user.save
assert_equal(format, user.errors.full_messages)
end
end
test "email_uniqueness" do
# アクティブなユーザーがいない場合に同じユーザーは保存できているか
10.times do |n|
user = User.new(email: "user@example.com", password: "passowrd")
assert user.save
end
assert @user.activated
user = @user.dup
# NG アクティブなユーザーが既に存在している場合
user.save
unique = ["メールアドレスはすでに存在します"]
assert_equal(unique, user.errors.full_messages)
# NG emailが大文字でもエラーを出しているか
user.email = @user.email.upcase
user.save
assert_equal(unique, user.errors.full_messages)
# OK アクティブなユーザーがいなくなった場合
@user.update(activated: false)
assert user.save
end
test "password_validator" do
user = User.new(email: "user@example.com")
# 入力必須
user.save
required = ["パスワードを入力してください"]
assert_equal(required, user.errors.full_messages)
# NG 8文字未満
user.password = "a" * 7
user.save
min_length = ["パスワードは8文字以上で入力してください"]
assert_equal(min_length, user.errors.full_messages)
# NG 72文字超
user.password = "a" * 73
user.save
max_length = ["パスワードは72文字以内で入力してください"]
assert_equal(max_length, user.errors.full_messages)
# ok 72文字以下
user.password = "a" * 72
assert user.save
# NG 書式チェック
# VALID_PASSWORD_REGEX = /\A[\w\-]+\z/
ngs = %w(pass/word pass.word |~=?+"a" 12345678 ABCDEFGH)
format = ["パスワードは半角英数字、ハイフン、アンダーバーが使えます"]
ngs.each do |ng|
user.password = ng
user.save
assert_equal(format, user.errors.full_messages)
end
end
end
← Prev
Next →
あなたの力になれること
私自身が独学でプログラミングを勉強してきたので、一人で学び続ける苦しみは痛いほど分かります。そこで、当時の私がこんなのあったら良いのにな、と思っていたサービスを立ち上げました。周りに質問できる人がいない、答えの調べ方が分からない、ここを聞きたいだけなのにスクールは高額すぎる。そんな方に向けた単発・短期間メンターサービスを行っています。
独学プログラマのサービス
SPA開発の投稿
1
「Rails apiとNuxt.jsでSPA開発」のデモアプリを開発中...。【2020/05/19追記: このカテゴリーの更新を一旦終了といたします】
1
Railsアプリの完成イメージ画像と作ろうと思った経緯
2
今回作るRailsアプリの全体像と機能の整理
1
macにRailsをゼロからインストールする
2
Rails apiモードのプロジェクトを作成し、Gitにコミットする
3
Bitbucketに公開鍵を追加し、Railsプロジェクトをpushする
4
HerokuCLIのインストールとherokuアプリケーションの作成
1
Herokuのデータベース設定と開発に便利なgemを導入する
2
HerokuにPumaを導入するためのRailsセットアップ
3
Railsに"Hello"を表示してHerokuへデプロイする
1
【RailsとNuxt.jsの共存】Rails上にNuxt.jsのプロジェクトを構築しよう
2
Nuxt.jsからRailsへ、初めてのapi通信でHelloを表示しよう
3
Nuxt.jsにVuetify2.0を導入してFont Awesomeもインストールするぜ
4
初めてのRailsApiアプリの公開。Herokuにデプロイする準備と実際のデプロイまで
1
データベースを正規化する前に、会計システムの勘定科目データを整理する
2
会計システムのデータベース設計に挑む
1
【ご報告】Nuxt.jsを2.10.2にバージョンアップしました
2
【ご報告】Railsを6.0.0にバージョンアップしました
1
本番環境と開発環境でRailsのSeedデータを切り替える
2
Railsにユーザーテーブルを作成する【テーブル確認コマンド】
3
【Rails】EachValidatorクラスを使ったEmailカスタムバリデーション【lib以下読み込み】
4
【Rails】エラーメッセージの日本語化【i18nとja.ymlのセッティング】
5
【Rails】開発・テスト・本番環境の全てにユーザーSeedデータ投入する
6
【Rails】ユーザーモデルのバリデーションをテストする
1
【Nuxt.js】ログインフラグでレイアウトを切り替えるテクニック【2019/12/07追記あり】
2
【Nuxt.js】ウェルカムページのレイアウト構築【sassの導入】
3
【Nuxt.js】ログイン周りの入力フォームコンポーネント設計【2019/12/07追記あり】
4
【Nuxt.js】会員登録フォームを構築してサインアップページを完成させる