2012-11-30 6 views

답변

3

테스트가 "매우 결합 조롱하는 취성"보인다는 사실은 코드 자체가 한 번에 너무 많은 일을하고 있다는 신호이다.

은 (어떤 크기의 입력에 대해 "foo는"반환) 의미가 map_url의 구현,보고, 문제를 강조하고 아직 테스트를 통과하려면

class SomeClass 
    def map_url(size) 
    GoogleMap.new.map_url 
    GoogleMap.new(point: model.location.point, size: size) 
    return "foo" 
    end 
end 

주의한다 :

  1. 새로운 맵이 올바른 인수로 시작되지만 리턴 값에 기여하지 않습니다.
  2. map_url이 새로 시작된지도에서는 ​​호출되지만 올바른 인수로 시작된지도에서는 ​​호출되지 않습니다.
  3. map_url의 결과가 반환되지 않습니다.

나는 당신이 코드를 구조화하는 방식이 실제보다 더 단순하게 보이게한다는 것이 문제라고 주장한다. 결과적으로 테스트가 너무 간단하여 메서드의 동작을 완전히 다루지 못합니다.

comment from David Chelimsky

관련 여기 보인다

그들이 상처를 때 일반적으로 설계 문제가 있기 때문에 당신이 에 테스트를 들어야 제안 TDD에있는 오래 된 가이드 라인이있다. 테스트는 테스트중인 코드의 클라이언트이며, 테스트가 아파하면 코드베이스의 다른 클라이언트를 모두 수행합니다. 이 바로 가기 바로 가기 은 가난한 디자인에 대한 변명 거리가됩니다. 나는 그것을 괴롭히기를 원한다. 을 해치려해야한다. 그럼 당신은 개별적으로 테스트 할 수 있습니다

class SomeClass 
    def new_map(size) 
    GoogleMap.new(point: model.location.point, size: size) 
    end 

    def map_url(size) 
    new_map(size).map_url 
    end 
end 

:

describe SomeClass do 
    let(:some_class) { SomeClass.new } 
    let(:mock_map) { double('map') } 

    describe "#new_map" do 
    it "returns a GoogleMap with the correct point and size" do 
     map = some_class.new_map('300x600') 
     map.point.should == [1,2] 
     map.size.should == '300x600' 
    end 
    end 

    describe "#map_url" do 
    before do 
     some_class.should_receive(:new_map).with('300x600').and_return(mock_map) 
    end   

    it "initiates a new map of the right size and call map_url on it" do 
     mock_map.should_receive(:map_url) 
     some_class.map_url('300x600') 
    end 

    it "returns the url" do 
     mock_map.stub(map_url: "http://www.example.com") 
     some_class.map_url('300x600').should == "http://www.example.com" 
    end 
    end 
end 

결과를이 충고에 따라

, 내가 문제를 분리, 별도의 두 가지 방법으로 첫 번째 분할에게 코드를 건의 할 것 테스트 코드가 길어서 2 개가 아닌 3 개 스펙이 있지만 코드에 포함 된 단계를보다 명확하고 깔끔하게 구분하고 메서드 동작을 완전히 다룰 수 있다고 생각합니다. 이 말이 맞는다면 알려주십시오.

+0

) 'mock_map'에 인스턴스 변수 대신'let'을 사용합니다. "should"를 사용하지 않도록 예제 이름을 다시 써주십시오. "무언가를한다"대 "뭔가해야한다").:) – doesterr

+0

아마도 주목할만한 것입니다 : 사양은 별도로 테스트 한'GoogleMap'에 의존합니다. 그래서 당신이 그렇게하는지 확인하십시오. 'map_url'의 이름이'mapurl'으로 바뀐'GoogleMap'의 새로운 버전을 상상해보십시오. 위의 사양은 여전히 ​​지나치지 만 다른 곳에서는 오류가 발생합니다. – doesterr

+0

"let"과 "should"의 사용에 관해서는, 두 가지 모두에 동의하고, 그러한 변경을 할 것입니다. –

0

이것이 내가 한 방법입니다. 이처럼 그것을 조롱하는 것은 매우 결합되고 부서지기 쉬운 느낌입니다. 제안?

describe SomeClass do 
    let(:some_class) { SomeClass.new } 

    describe "#map_url" do 
    it "should instantiate a GoogleMap with the correct args" do 
     GoogleMap.should_receive(:new).with(point: [1,2], size: '300x600') { stub(map_url: nil) } 
     some_class.map_url('300x600') 
    end 

    it "should call map_url on GoogleMap instance" do 
     GoogleMap.any_instance.should_receive(:map_url) 
     some_class.map_url('300x600') 
    end 
    end 
end 
+0

거기에 'some_class = SomeClass.new'가 필요하지 않습니까 (예 :'before' 블록)? –

+0

예, 전체 예제로 업데이트되었지만 (예 : – Yeggeps

관련 문제