LoginSignup
23
24

More than 5 years have passed since last update.

RubyMineでRailsをテスト駆動開発(Rspec)してみる(1)

Last updated at Posted at 2013-03-19
Component version
RubyMine 5.0(Windows)
Rails 3.2.12
Rspec 2.13.0
FactoryGirl 4.2.0
Faker 1.1.2
DatabaseCleaner 0.9.1

Setup

  1. コードを書く
Gemfile
group :development, :test do
  gem "rspec-rails"
  gem "factory_girl_rails"
end

group :test do
  gem "faker"
  gem "capybara"
  gem "database_cleaner"
end
  1. bundle install

  2. Tools > Run Rails Script > "rails", "generate rspec:install"

  3. Tools > Run Rails Generator > model > Contact firstname:string lastname:string email:string phone:references

  4. Tools > Run Rails Generator > model > Phone contact:references phone_type:string phone:string

  5. Tools > Run Rake Task > db:migrate

1st red

  1. テストを書く
spec/models/contact_spec.rb
require 'spec_helper'

describe Contact do
  it "is valid with a firstname and lastname"
  it "is invalid without a firstname"
  it "is invalid without a lastname"
  it "is invalid with a duplicate email address"
end
  1. Run > Run > spec

pending

  1. Toggle auto-test

  2. テストを書く

spec/models/contact_spec.rb
require 'spec_helper'

describe Contact do
  it "is valid with a firstname and lastname" do
    contact = Contact.new(
        firstname: 'Tatsuro',
        lastname: 'Ueda',
        email: 'weed_7777@yahoo.co.jp'
    )
    expect(contact).to be_valid
  end

  it "is invalid without a firstname" do
    expect(Contact.new(firstname: nil).to have(1).errors_on(:firstname))
  end

  it "is invalid without a lastname" do
    expect(Contact.new(lastname: nil).to have(1).errors_on(:lastname))
  end

  it "is invalid with a duplicate email address" do
    Contact.create(
        firstname: 'Tatsuro', lastname: 'Ueda', email: 'weed_7777@yahoo.co.jp'
    )
    contact = Contact.new(
        firstname: 'hoge', lastname: 'fuga', email: 'weed_7777@yahoo.co.jp'
    )
    expect(contact).to have(1).errors_on(:email)
  end
end
  1. 保存すると自動でテストが走り、こける

  2. コードを書く

app/models/contact.rb
  validates :firstname, presence: true
  validates :lastname, presence: true
  validates :email, presence: true, uniqueness: true
  1. 保存すると自動でテストが走り、合格する

2nd red

  1. テストを書く
spec/models/phone_spec.rb
describe Phone do
  it "does not allow duplicate phone numbers per contact"
  it "allows two contacts to share a phone number"
end
  1. 保存すると自動でテストが走り、pendingになる

  2. テストを書く

spec/models/phone_spec.rb
describe Phone do
  it "does not allow duplicate phone numbers per contact" do
    contact = Contact.create(
        firstname: 'Tatsuro', lastname: 'Ueda', email: 'weed_7777@yahoo.co.jp'
    )
    home_phone = contact.phones.create(
        phone_type: 'home',
        phone: '01-2345-6789'
    )
    mobile_phone = contact.phones.create(
        phone_type: 'mobile',
        phone: '01-2345-6789'
    )
    expect(mobile_phone).to_not be_valid
  end

  it "allows two contacts to share a phone number" do
    contact = Contact.create(
        firstname: 'Tatsuro', lastname: 'Ueda', email: 'weed_7777@yahoo.co.jp'
    )
    contact.phones.create(
        phone_type: 'home',
        phone: '01-2345-6789'
    )
    other_contact = Contact.new
    other_phone = other_contact.phones.build(
        phone_type: 'home',
        phone: '01-2345-6789'
    )
    expect(other_phone).to be_valid
  end
end
  1. 保存すると自動でテストが走り、こける

  2. コードを書く

app/models/contact.rb
  #  belongs_to :phone
  has_many :phones
app/models/phone.rb
  attr_accessible :phone, :phone_type
  validates :phone, uniqueness: { scope: :contact_id }
  1. 保存すると自動でテストが走り、合格する

3rd red

  1. テストを書く
spec/models/contact_spec.rb
  describe "#name" do
    it "returns a contact's full name as a string" do
      contact = Contact.new(
          firstname: "Tatsuro", lastname: "Ueda", email: "weed_7777@yahoo.co.jp"
      )
      expect(contact.name).to eq 'Tatsuro Ueda'
    end
  end

  1. Run > Run > spec

テストが走り、失敗する

  1. Toggle auto-test

  2. コードを書く

app/models/contact.rb
  def name
    [firstname, lastname].join " "
  end
  1. 自動的にテストが走り、合格する

4th red

  1. テストを書く
spec/models/contact_spec.rb
  describe "#by_letter" do
    it "returns a sorted array of results that match" do
      smith = Contact.create(
          firstname: 'John', lastname: 'Smith', email: 'jsmith@example.com'
      )
      jones = Contact.create(
          firstname: 'Tim', lastname: 'Jones', email: 'tjones@example.com'
      )
      johnson = Contact.create(
          firstname: 'John', lastname: 'Johnson', email: 'jjohnson@example.com'
      )

      expect(Contact.by_letter("J")).to eq [johnson, jones]
    end
  end
  1. 自動的にテストが走り、失敗する

  2. コードを書く

app/models/contact.rb
  def self.by_letter(letter)
    where("lastname LIKE ?", "#{letter}%").order(:lastname)
  end
  1. 自動的にテストが走り、合格する

リファクタリング

beforecontextを使ってテストコードを整理する。

spec/models/contact_spec.rb
  describe "filter last name by letter" do
    before :each do
      @smith = Contact.create(
          firstname: 'John', lastname: 'Smith', email: 'jsmith@example.com'
      )
      @jones = Contact.create(
          firstname: 'Tim', lastname: 'Jones', email: 'tjones@example.com'
      )
      @johnson = Contact.create(
          firstname: 'John', lastname: 'Johnson', email: 'jjohnson@example.com'
      )
    end

    context "matching letters" do
      it "returns a sorted array of results that match" do
        expect(Contact.by_letter("J")).to eq [@johnson, @jones]
      end
    end

    context "non-matching letters" do
      it "returns a sorted array of results that match" do
        expect(Contact.by_letter("J")).to_not include smith
      end
    end
  end

おしまい。


ブログやってます:PAPA-tronix !

23
24
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
23
24