TDD for rorlab.
(1). TDD 인트로.
1. Install
# 소스 받기$ git clone https://github.com/everydayrails/rspec_rails_4.git$ cd rspec_rails_4$ bundle install# 03_models 브랜치 이동$ git checkout -b 03_models origin/03_models# db 생성, Rspec 인스톨 후, Rspec 실행$ bundle exec rake db:create:all$ bundle exec rails generate rspec:install$ bundle exec rake db:test:clone$ bundle exec rspec
2. gems
group :development, :test do
gem "rspec-rails", "~> 2.14.0"
gem "factory_girl_rails", "~> 4.2.1"
end
group :test do
gem "faker", "~> 1.1.2"
gem "capybara", "~> 2.1.0"
gem "database_cleaner", "~> 1.0.1"
gem "launchy", "~> 2.3.0"
gem "selenium-webdriver", "~> 2.35.1"
end
factory_girl : Rails의 테스트 데이터를 더욱 유연하게 만듭니다.
faker: 이름, 이메일 등을 실제 데이터같이 생성합니다.
capybara: 웹 어플리케이션에서 유저와의 상호작용을 쉽게 시뮬레이션 할 수 있습니다.
database_cleaner: RSpec이 실행될때 Test DB를 지워줍니다.
launchy: 디버깅 테스트 할 때 매우 유용합니다. 기본 웹 브라우져를 실행하고 어플리케이션을 랜더링합니다.
selenium-webdriver: Capybara와 함께 유저의 브라우져 상호작용을 테스트합니다.
3. Model Spec
모델 Spec 작성 시 유의 할 점 3가지
1. 모델의 create 메소드에 유효한 데이터를 전송할 때 에러가 없어야 합니다.
2. 데이터 검증 실패시 유효성 검증에서 실패해야 합니다.
3. 클래스와 인스턴스 메소드는 예상한대로 실행되어야 합니다.
a. creating model spec file
spec/models/contact_spec.rb
require 'spec_helper'
describe Contact do
it "is valid with a firstname, lastname and email"
it "is invalid without a firstname"
it "is invalid without a lastname"
it "is invalid without an email address"
it "is invalid with a duplicate email address"
it "returns a contact's full name as a string"
end
b. Testing validations #1
간단한 검증 테스트
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 without an email address" do
expect(Contact.new(email: nil)).to have(1).errors_on(:email)
end
c. TESTING VALIDATIONS #2
이메일 중복 검증
it "is invalid with a duplicate email address" doContact.create( firstname: 'Joe', lastname: 'Tester', email: 'tester@example.com')contact = Contact.new( firstname: 'Jane', lastname: 'Tester', email: 'tester@example.com')expect(contact).to have(1).errors_on(:email)end
d. more complex validations
복잡한 중복 검증
describe Phone do it "does not allow duplicate phone numbers per contact" docontact = Contact.create(firstname: 'Joe', lastname: 'Tester', email: 'joetester@example.com') contact.phones.create(phone_type: 'home', phone: '785-555-1234')mobile_phone = contact.phones.build(phone_type: 'mobile', phone: '785-555-1234') expect(mobile_phone).to have(1).errors_on(:phone) end it "allows two contacts to share a phone number" do contact = Contact.create(firstname: 'Joe', lastname: 'Tester', email: 'joetester@example.com') contact.phones.create(phone_type: 'home', phone: '785-555-1234') other_contact = Contact.newother_phone = other_contact.phones.build(phone_type: 'home', phone: '785-555-1234') expect(other_phone).to be_valid end end
E. Testing instance methods
인스턴스 메소드 테스
트
contact.rb
class Contact < ActiveRecord::Base
def name
[firstname, lastname].join(' ')
end
end
it "returns a contact's full name as a string" do
contact = Contact.new(firstname: 'John', lastname: 'Doe',
email: 'johndoe@example.com')
expect(contact.name).to eq 'John Doe'
end
f. testing class methods and scopes
클래스 메소드와 스코프 테스트
contact.rb
def self.by_letter(letter)
where('lastname LIKE ?','#{letter}%').order(:lastname)
end
contact_spec.rb
#클래스 메소드와 스코프
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
G. DRYer specs with describe context
코드 줄이기
require 'spec_helper' describe Contact do # validation examples... describe "filter last name by letter" do # filtering examples...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') endcontext "matching letters" do # matching examples... end context "non-matching letters" do # non-matching examples...endendend
4. RORLab. 적 용해보기
1. 이메일 중복에 대한 테스트 코드 추가
2. 비밀번호 길이 제한에 대한 테스트 코드 추가
3. 대소문자 구별없이 이메일 중복체크 테스트 코드 추가
4. 공백 구분없이 이메일 중복체크 테스트 코드 추가
결과
https://github.com/RORLabNew/rorla_api/pulls
Ref. URL
RORLab. 프로그래밍 번개
By hanguk lee
RORLab. 프로그래밍 번개
- 1,451