#開発環境
- OS:macOS Big Sur 11.2.2
- Ruby:2.6.5
- Ruby on Rails:6.0.0
- Faker:2.18.0
- テキストエディタ:Visual Studio Code
#発生事象
rspecを利用したテストコード実行で以下のようなエラーが頻発するようになった。
まず何をしているかというと、
- deviseモデルであるuser
- userとアソシエーションを持つpresent_order_form
この2つのmodelがあって、user
モデルの単体テストコードは作成済み・問題なく実行済み。
present_order_form
モデルの単体テストコードを作成して、実行してみたところ、紐づけているuser
モデルの方でエラーが起きる。しかも何度か再実行すると、ある特定のexsampleで起きるわけではなく発生箇所がランダムになっていることがわかる。
#原因
userインスタンスはFactoryBotとFakerで以下のようなデータを生成していた。
FactoryBot.define do
factory :user do
nickname { Faker::Name.initials(number: 2) }
email { Faker::Internet.free_email }
password { Faker::Internet.password(min_length: 6) }
password_confirmation { password }
end
end
主にパスワードとなる文字列を生成してくれるFaker::Internet.passwordだが、実は利用できるオプションはとても少ない。
option | 内容 |
---|---|
min_length | 最小文字数の指定 |
max_length | 最大文字数の指定 |
mix_case | 大文字小文字混合指定 |
special_characters | 記号の混合指定 |
見ての通り英数字混合の指定はできないのである。
今回userモデルのpasswordには英数字混合フォーマットでバリデーションをかけていたので、実行するexampleが多くなればなるほど、英字もしくは数字を含まないパターンでpasswordを生成してしまったインスタンスが発生しやすくなり上記のようなエラーが頻発する模様。
かゆいところに手が届いていない気もするが無料で利用させていただいて文句は言えないので、諦めてmin_lengthを大きめにとっておくか、Loremでカスタマイズした文字列を生成するようにするか、もしくはそもそもFakerにこだわらず決めの文字列でインスタンス生成するしか解決案はなさそうである。
#余談
とはいえ英字だけ・数字だけの文字列がそんなに頻繁に生成されるものか?
体感としてはやたら多いと感じたので、ざっくり確率を計算してみた。
###6文字の文字列が英数字混合にならない確率
6文字の文字列パターンは36(数字10個とアルファベット26個)の6乗。数字のみの場合は10の6乗、英字のみの場合は26の6乗なので、
(10の6乗/36の6乗) + (26の6乗/36の6乗) = 14.23%
思ったより高い・・・deviseモデルのpasswordはデフォルトのmin_lengthが6文字だけど、それに合わせてしまうとエラーが頻発しそう。
###10文字の文字列が英数字混合にならない確率
同じように計算すると、
(10の10乗/36の10乗) + (26の10乗/36の10乗) = 3.86%
このあたりでだいぶ安全な範囲かなと思う。
不都合がなければ、最初から10~15桁くらいで設定しておくといいかもしれない。