Rails에서 문제를 테스트하는 방법


104

메서드 Personable가있는 Rails 4 애플리케이션에 문제 가 있다는 점을 감안할 때 full_nameRSpec을 사용하여이를 테스트하려면 어떻게해야합니까?

관심사 /personable.rb

module Personable
  extend ActiveSupport::Concern

  def full_name
    "#{first_name} #{last_name}"
  end
end

어떤 테스트 프레임 워크를 사용하고 있습니까? 또한 Personable은 일반적인 Ruby 모듈이라는 것을 기억하십시오. 다른 믹스 인을 테스트하는 것처럼 테스트하십시오.
Lee Jarvis

하지 않은 ActiveSupport::Concern레일 밖으로 촬영되었다? 조금 전에 갔다고 생각했습니다.
Russell

@LeeJarvis 저는 FactoryGirl과 함께 Rspec을 사용하고 있습니다
Kyle Decot


4
@Russell 동의합니다. 즉, 내가 동의하지 않는 일을하는 Rails-y 방식을 따르고 있다는 이유만으로 질문에 대해 누군가를 돕지 않을 것입니다. 어쨌든이 좀 :-)이 질문의 제목을 탈출하다
리 자비스

답변:


176

발견 한 방법은 확실히 약간의 기능을 테스트하는 데는 효과가 있지만 매우 취약 해 보입니다. 더미 클래스 (실제로는 Struct솔루션에 포함되어 있음)가 include관심사 인 실제 클래스처럼 동작 할 수도 있고 그렇지 않을 수도 있습니다 . 또한 모델 문제를 테스트하려는 경우 그에 따라 데이터베이스를 설정하지 않는 한 객체의 유효성을 테스트하거나 ActiveRecord 콜백을 호출하는 등의 작업을 수행 할 수 없습니다 (더미 클래스에 데이터베이스 테이블 백업이 없기 때문). 그것). 또한 우려 사항을 테스트 할뿐만 아니라 모델 사양 내에서 우려 사항의 동작을 테스트하고 싶을 것입니다.

그렇다면 한 돌로 두 마리의 새를 죽이는 것은 어떨까요? RSpec에의 사용에 의해 공유 예를 들어 그룹을 , 당신은 그들 (예를 들어, 모델)을 사용하여 실제 수업에 대한 우려를 테스트 할 수 있습니다 그리고 당신은 그들이 사용하고 사방을 테스트 할 수 있습니다. 그리고 테스트를 한 번만 작성하고 관심사를 사용하는 모델 사양에 포함하면됩니다. 귀하의 경우에는 다음과 같이 보일 수 있습니다.

# app/models/concerns/personable.rb
module Personable
  extend ActiveSupport::Concern

  def full_name
    "#{first_name} #{last_name}"
  end
end

# spec/concerns/personable_spec.rb
require 'spec_helper'

shared_examples_for "personable" do
  let(:model) { described_class } # the class that includes the concern

  it "has a full name" do
    person = FactoryBot.build(model.to_s.underscore.to_sym, first_name: "Stewart", last_name: "Home")
    expect(person.full_name).to eq("Stewart Home")
  end
end

# spec/models/master_spec.rb
require 'spec_helper'
require Rails.root.join "spec/concerns/personable_spec.rb"

describe Master do
  it_behaves_like "personable"
end

# spec/models/apprentice_spec.rb
require 'spec_helper'

describe Apprentice do
  it_behaves_like "personable"
end

이 접근 방식의 장점은 AR 콜백 호출과 같은 작업을 시작할 때 훨씬 더 분명해집니다. AR 객체보다 적은 것은 수행하지 않습니다.


2
이것의 한 가지 단점은 속도가 느려진다는 것 parallel_tests입니다. 나는 그것을 사용하는 대신 별도의 시험이 더 좋을 것이라고 생각 shared_examples_for하고을 it_behaves_like.
Artem Kalinchuk 2014 년

6
@ArtemKalinchuk 내가 당, 사실이 확실하지 않다 github.com/grosser/parallel_tests/issues/168은 parallel_tests 파일 당을 기반으로, 그래서 공유 예를 느리게하지 않아야합니다. 또한 적절하게 그룹화 된 공유 행동이 테스트 속도를 능가한다고 주장합니다.
Aaron K

8
인클루드해야합니다 concerns귀하의 디렉토리 spec_helper.rb github.com/rspec/rspec-core/issues/407#issuecomment-1409871
저 친구

1
해당 링크에 관심사 디렉토리를 포함하는 것에 대해 아무것도 찾을 수 없습니다. 이것이 어떻게 수행되는지 명확히 해주시겠습니까? 내 관심사 중 하나에서 모듈을 인식하는 RSpec 테스트를 얻을 수 없습니다.
제이크 스미스

4
_specshared_examples_for (이 경우에는 personable_spec.rb)가 포함 된 파일 이름에 추가하지 마십시오 . 그렇지 않으면 잘못된 경고 메시지 ( github.com/rspec/rspec-core/issues/828) 가 표시 됩니다.
Lalu

62

내가받은 댓글에 대한 응답으로 내가 한 일은 다음과 같습니다 (개선 사항이 있으면 언제든지 게시 해주세요) .

spec / concerns / personable_spec.rb

require 'spec_helper'

describe Personable do
  let(:test_class) { Struct.new(:first_name, :last_name) { include Personable } }
  let(:personable) { test_class.new("Stewart", "Home") }

  it "has a full_name" do
    expect(personable.full_name).to eq("#{personable.first_name} #{personable.last_name}")
  end
end

1
예,라는 실제 클래스를 테스트하는 경우 다른 테스트가 중단됩니다 Person. 수정하여 수정하겠습니다.
Russell

이것은 작동하지 않습니다. 그것은 나에게 오류를 준다 :undefined method 'full_name' for #<struct first_name="Stewart", last_name="Home">
Kyle Decot

확장하기보다는 Personable을 포함 해보십시오. 답변을 업데이트하겠습니다.
Russell

지금 잘 작동합니다. 올바른 방향으로 날을 가리키는 나를 @Russell 리팩토링 도움을 주셔서 감사합니다
카일 Decot

크고 모양 좋은 작품
에드워드

7

또 다른 생각은 with_model gem 을 사용하여 이와 같은 것을 테스트하는 것입니다. 나는 관심사를 직접 테스트하려고했고 pg_search gem이 이것을하는 것을 보았다 . 개별 모델을 테스트하는 것보다 훨씬 낫습니다. 변경 될 수 있기 때문에 사양에 필요한 것을 정의하는 것이 좋습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.