shared_examples_forに引数を渡して処理をさらにまとめる
ここ最近はリファクタリングやより短い書き方を考えてます。
一行でもコードから文字が減るのは嬉しい。
そんなわけで、カラム名が違うだけで、内容同じじゃん・・・って場合のテストの書き方です。
前提条件
カラムの:login, :passwordは半角英数字のみで文字数制限を含んでいます。 ただし、文字数制限は違います。 けど、やってることは同じなので、処理をまとめます。
shared_examples_forの書き方
shared_examples_for 'alphanumeric' do |column_name, min_len, max_len| let(:factory_name) { described_class.name.underscore } let(:record) { build(factory_name) } context "#{column_name}" do context '登録できる' do context '半角英数字' do it '_を含むもの' do record[column_name] = 'foo_' expect(record).to be_valid end context '文字列の長さ' do it "#{min_len}文字" do record[column_name] = 'a' * min_len expect(record).to be_valid end it "#{max_len}文字" do record[column_name] = 'a' * max_len expect(record).to be_valid end end end end end
こんな感じですかね。
ここでのポイントはrecord[column_name]
で値を入れるようにすることです。
record.column_name
ではno method error
になります。
あとはit_behaves_like
に引数を渡します。
it_behaves_like 'alphanumeric', :login, 4, 20 it_behaves_like 'alphanumeric', :password, 8, 20
これで同じ処理をまとめることができました。
ただ、password
がpassword_confirmation
がいるよ!ってエラーになるので、そこはif文
で分岐処理を書きました。
context '半角英数字' do it '_を含むもの' do value = 'foo_' if column_name == :password expect(record.update(password: value, password_confirmation: value)).to be_truthy else record[column_name] = value expect(record).to be_valid end end end
ここをうまく書ける方法があれば教えていただきたいですm( )m