본문 바로가기

Ruby On Rails/RSpec

각 Spec 기본 구조

1. 디렉터리

  1. app/…. 아래 있는 구성과 spec/…. 아래 있는 구성과 똑같이 만들어주시면 되겠습니다.

2. feature spec 구조

RSpec.describe "Certification_business", type: :feature do
  scenario "index page" do
    signin
    visit '/admin/certification_business'
    four_month_ago = Time.current.months_ago(4).strftime('%Y-%m-%d')
    expect(find_by_id('date').value).to eq four_month_ago
  end
  1. feature spec은 테스트 시에 자바스크립트 이벤트를 발생시키기 위해 capybara를 사용합니다. 그래서 capybara 메서드인 .feature를 사용해서 작성을 해야 합니다. 하지만 rspec에서 vendor로 capybara를 포함하므로, describe로 접근해도 상관없습니다.
  2. scenario 블록 안에서만 capybara가 제공하는 API를 사용할 수 있습니다.
  3. scenario 블록 밖에 describe나 context를 작성해 계층구조를 만들 수 있습니다.
  4. it 은 사용할 수 없습니다.

3. feature spec을 제외한 모든 spec 구조

describe '#get_certification_info' do
  context '사업인증된 유저들' do
    it 'rsIdx를 기준으로 각 유저의 정보 확인' do
      FactoryBot.create_list(:order_goods_info_for_cert_date, 50)
      FactoryBot.create_list(:s_order_sheet_for_cert_date, 50)
      cert_date = Time.current.days_ago(2).strftime('%Y-%m-%d')
      certification_info = CertificationBusinessService.new.get_certification_info(cert_date)
      expect(certification_info).to eq(certification_info)
    end
  end
end
  1. describe, context, it 으로 이렇게 계층 구조를 주어서 만들면 되겠습니다.
  2. describe
    1. #mehtod, #뒤에는 메서드 이름을 적습니다.
    2. .class, . 뒤에는 클래스 이름을 적습니다.
  3. context
    1. when, with, without을 생각하며 적으라고 추천합니다.
    2. 위 예제의 경우 with이 되겠죠.
  4. it
    1. 무슨 작업을 하는 건지에 대한 내용을 적어주세요.
  5. 더 자세한 내용은 betterspec을 참조해주세요.
    1. https://www.betterspecs.org/

4. factorybot 사용 구조

  1. 팩토리봇에서 사용되는 모델들은 테스트 디비에 저장은 되지만 scope에 의해 저장되는 값들이 나누어져 있습니다. describe, context 안에서 factorybot 객체를 생성하게 되면 it scope 밖에서만 그 모델들이 디비에 저장되어 있습니다. 그래서 let()이란 메서드를 통해 그 값들을 저장시켜 놓는 것입니다. 또한 service spec에서 비즈니스 로직을 테스트하려면 모델 간 연관관계가 필요하고 그 데이터들을 유지할 필요가 있어서 it scope 안에서 factorybot 객체를 만들어줘야 db에 저장된 값들을 사용할 수 있습니다.
  2. let()
    1. let(:user) {create :wholesale_ceo_user, userid: userid_capital}
    2. let(:retail_store) { build(:ssm_retail_store)}
    3. 팩토리 객체 다음에는 trait 명, 인스턴스 변수명을 적어 오버라이딩을 할 수 있습니다.
    4. let을 통해 그 값을 저장해놓아야 it scope 안에서 그 값을 사용할 수 있습니다. 그래서 보통 연관관계가 없는 단일 객체를 테스트하는데 사용할 수 있습니다.
  3. it scope 안에서
it do
  FactoryBot.create_list(:order_goods_info_for_cert_date, 50)
  FactoryBot.create_list(:s_order_sheet_for_cert_date, 50)
end
  1. 이렇게 it scope 안에서 생성을 하게 되면 test db에 저장이 영구적으로 되고 DatabaseCleaner[:active_record].strategy = :transaction에 의해 transaction 영향을 받아 test db에 값이 존재하더라도 PK를 unique 하게 만들어줍니다. 그래서 비즈니스 로직을 몇 번이고 편하게 테스트할 수 있습니다.
  2. 만약 test db에 들어 있는 값을 지우고 싶다면 it scope 안에 factorybot을 사용하지 않은 test.rb를 실행시키면 test db가 깨끗해집니다. 보통 저는 비우고 싶을 때 spec/models/retail_store_spec.rb 를 사용합니다.

 

'Ruby On Rails > RSpec' 카테고리의 다른 글

FactoryBot 작성방법  (0) 2021.02.06
helper spec  (0) 2021.02.06
RSpec 실행 명령어  (0) 2021.01.30
RSpec 설정 이야기  (0) 2021.01.30
RSpec 구조에 대한 이야기  (0) 2021.01.10