그것은 것 동적 보다는 정적으로 입력 된보다. 그러면 덕 타이핑 은 인터페이스가 정적으로 유형이 지정된 언어와 동일한 작업을 수행합니다. 또한 테스트 클래스가 기존 클래스에서 메소드를 쉽게 스텁하거나 모방 할 수 있도록 런타임에 클래스를 수정할 수 있습니다. 루비는 그러한 언어 중 하나입니다. rspec 은 TDD를위한 최고의 테스트 프레임 워크입니다.
동적 타이핑이 테스트를 돕는 방법
동적 입력을 사용하면 조롱해야하는 공동 작업자 객체와 동일한 인터페이스 (메소드 서명)가있는 클래스를 간단히 만들어 모의 객체를 만들 수 있습니다. 예를 들어, 메시지를 보낸 클래스가 있다고 가정하십시오.
class MessageSender
def send
# Do something with a side effect
end
end
MessageSender 인스턴스를 사용하는 MessageSenderUser가 있다고 가정 해 보겠습니다.
class MessageSenderUser
def initialize(message_sender)
@message_sender = message_sender
end
def do_stuff
...
@message_sender.send
...
@message_sender.send
...
end
end
단위 테스트의 필수 요소 인 종속성 주입 의 사용에 주목하십시오 . 우리는 다시 돌아올 것입니다.
MessageSenderUser#do_stuff
통화가 두 번 전송되는지 테스트하려고 합니다. 정적으로 유형이 지정된 언어와 마찬가지로 send
호출 횟수를 계산하는 모의 MessageSender를 만들 수 있습니다 . 그러나 정적으로 유형이 지정된 언어와 달리 인터페이스 클래스는 필요하지 않습니다. 계속 진행하여 작성하십시오.
class MockMessageSender
attr_accessor :send_count
def initialize
@send_count = 0
end
def send
@send_count += 1
end
end
그리고 테스트에서 사용하십시오 :
mock_sender = MockMessageSender.new
MessageSenderUser.new(mock_sender).do_stuff
assert_equal(mock_sender.send_count, 2)
동적으로 유형이 지정된 언어의 "오리진 입력"자체는 정적 유형의 언어와 비교할 때 테스트에 큰 도움이되지 않습니다. 그러나 클래스가 닫히지 않았지만 런타임에 수정할 수 있다면 어떨까요? 이것이 게임 체인저입니다. 방법을 보자.
클래스를 테스트 할 수 있도록 종속성 주입을 사용할 필요가 없으면 어떻게합니까?
MessageSenderUser가 MessageSender를 사용하여 메시지를 보내는 경우에만 MessageSender를 다른 클래스로 대체 할 필요가 없다고 가정하십시오. 단일 프로그램 내에서 종종 그렇습니다. 의존성 주입없이 MessageSender를 작성하고 사용하도록 MessageSenderUser를 다시 작성해 봅시다.
class MessageSenderUser
def initialize
@message_sender = MessageSender.new
end
def do_stuff
...
@message_sender.send
...
@message_sender.send
...
end
end
MessageSenderUser는 이제 사용하기가 더 간단합니다. 아무도 작성하기 위해 MessageSender를 작성할 필요가 없습니다. 이 간단한 예제에서는 크게 개선 된 것처럼 보이지 않지만 이제 MessageSenderUser가 두 번 이상 생성되었거나 세 개의 종속성이 있다고 상상해보십시오. 이제 시스템은 디자인을 전혀 개선하지 않기 때문에 단위 테스트를 만족시키기 위해 인스턴스를 전달합니다.
의존성 주입없이 테스트 할 수있는 개방형 클래스
다이나믹 한 타이핑과 오픈 클래스를 가진 언어의 테스트 프레임 워크는 TDD를 상당히 좋게 만들 수 있습니다. MessageSenderUser에 대한 rspec 테스트의 코드 스 니펫은 다음과 같습니다.
mock_message_sender = mock MessageSender
MessageSender.should_receive(:new).and_return(mock_message_sender)
mock_message_sender.should_receive(:send).twice.with(no_arguments)
MessageSenderUser.new.do_stuff
그것은 전체 테스트입니다. 만약MessageSenderUser#do_stuff
호출하지 않습니다 MessageSender#send
정확히 두 번이 테스트가 실패합니다. 실제 MessageSender 클래스는 결코 호출되지 않습니다. 우리는 누군가 누군가 MessageSender를 만들 때마다 모의 MessageSender를 가져와야한다고 테스트에 말했습니다. 의존성 주입이 필요하지 않습니다.
더 간단한 테스트에서 그렇게하는 것이 좋습니다. 디자인에 실제로 의미가 없다면 의존성 주입을 사용하지 않는 것이 훨씬 좋습니다.
그러나 이것은 공개 수업과 어떤 관련이 있습니까? 에 대한 호출에 유의하십시오 MessageSender.should_receive
. MessageSender를 작성할 때 #should_receive를 정의하지 않았습니다. 대답은 시스템 클래스를 신중하게 수정 한 테스트 프레임 워크가 모든 객체에 #should_receive가 정의 된 것처럼 보일 수 있다는 것입니다. 이와 같은 시스템 클래스를 수정하는 데 약간의주의가 필요하다고 생각하면 옳습니다. 그러나 테스트 라이브러리에서 수행하는 작업에 가장 적합하며 열린 클래스를 통해 가능합니다.