rspecを初めて使ってみた

「スキルなし・実績なし」 32歳窓際エンジニアがシリコンバレーで働くようになるまで
これ読んでブログがんばろうかなーという気持ちになっている榊間です。(前回から結構空いちゃいましたが)

今さらながらしっかりとtestできるようにならないとということで、社員さんからrspecの本を薦められて読んでいます。今日はそのことについて書いていきたいと思います。leanpub.com


本を読んで実際に書いたコード

主に使うのは

gem 'rspec-rails'
gem 'factory-girl-rails'
gem 'faker'

です。個人的には、rspecが実際にテストをするために必要なgemで、factorygirlはtestするためのデータ生成に使用、fakerは生成するデータをより現実のデータに近づけるために使用するといったイメージを持ってます。

僕が最初に書いたのは

require 'spec_helper'

describe "Inquiry" do
  it "is valid with contents, email and name" do
    expect(build(:inquiry)).to be_valid
  end

  it "is invalid without contents" do
    inquiry = build(:inquiry, contents: nil)
    inquiry.valid?
    expect(inquiry.errors[:contents]).to include("を入力してください。")
  end

...


  describe "length of contents" do

    it "is invalid with more than 500 words" do
      inquiry = build(:invalid_contents)
      inquiry.valid?
      expect(inquiry.errors[:contents]).to include("は500文字以内で入力してください。")
    end
  end

  describe "format email" do
    it "match regex" do
      inquiry = build(:inquiry)
      expect(inquiry.email).to match(/.+@.+\..+/i)
    end

    it "does not match regex" do
      inquiry = build(:inquiry,
        email: "testexample.com"
      )
      inquiry.valid?
      expect(inquiry.errors[:email]).to include("は不正な値です。")
    end
  end

...

end 

長くなるので少し省略していますが、この中でやりたかったことは
1、name,email,contentsのpresent: trueを確かめる。
2、contentsのvalidationを確かめる。
3、emailのvalidationを確かめる。
この三つです。
でも
・ちょっと長くて読みにくい
・テスト内容が細かすぎる(エラー文もテストしている)
・emailのvalidのテストは一番最初のテストで確かめられている(重複している)
などなど問題がありました。
そしてアドバイスを受けて書いたコードがこちら

require 'spec_helper'

describe "Inquiry" do
  context "when valid" do
    subject(:inquiry) { build(:inquiry) }
    it { expect(inquiry).to be_valid }
  end

  context "when no contents" do
    subject(:inquiry) { build(:inquiry, contents: nil) }
    it { expect(inquiry).not_to be_valid }
  end

...

  context "with more than 500 words in contents" do
    subject(:invalid_contents) { build(:invalid_contents) }
    it { expect(invalid_contents).not_to be_valid }
  end

  context "with non-marching format of email" do
    subject(:invalid_email) { build(:inquiry, email: "testexample.com") }
    it { expect(invalid_email).not_to be_valid }
  end

...

end

もう全然違います。contextで状態を表し、全てvalidかinvalidかテストするにとどめました。subujectでまとめることで、すっきりして読みやすくなっています。

テストの書き方は、結構好み・状況に左右されるなーという印象ですが、漏れと重複だけは気をつけてやらないといけないというのが今回の学びです。。