IT이야기

다른 메서드를 호출하는 메서드 단위 테스트

cyworld 2021. 4. 19. 20:49
반응형

다른 메서드를 호출하는 메서드 단위 테스트


여러 메서드를 호출하는 메서드를 단위 테스트하는 가장 좋은 방법은 다음과 같습니다.

modify(string value)
{
    if(value.Length > 5)  replaceit(value);

    else changeit(value);
}

이 의사 코드에는 (현재) replaceit()또는을 호출하는 수정 메서드가 있습니다 changeit(). 나는 이미 replaceitchangeit대한 테스트를 작성 했으므로 수정을위한 새 테스트를 작성하는 것은 99 % 동일한 코드 세트입니다. 나는 그것이 미래에 바뀔 수 있기 때문에 생각을 테스트해야합니다.

그렇다면 기존 테스트 코드를 복사하여 붙여 넣어야합니까? 테스트 코드를 공통 기능으로 이동 하시겠습니까? 다른 아이디어가 있습니까? 여기에서 모범 사례를 잘 모르겠습니다.


이것은 고전적인 상태 기반 테스트 대 동작 기반 테스트 시나리오입니다.

이 엄청나게 간단한 예제에서 출력 테스트는 괜찮습니다. 하지만 언젠가는 실행 후 상태를 검사하는 것이 복잡한 테스트에 부딪 힐 것입니다. 대신 동작을 확인하려고합니다 (예 : changeit가 특정 값으로 호출되었는지 확인).

이 시점에서 Rhino.Mocks (.Net) 또는 Mockito (Java)와 같은 모의 개체 프레임 워크를 살펴보고 더 많은 인터페이스 기반 코드를 작성해야합니다.


다양한 옵션이 있습니다. 어떤 것이 가장 좋은지는 질문에서 명확하지 않은 세부 사항에 따라 다릅니다.

  • modify마치 관련없는 방법 인 것처럼 테스트합니다 . 장점 : 언젠가는 하나가 될 수 있습니다.
  • if 문이 올바른지 테스트하십시오. 즉, 테스트 호출 곳 (당신이 필요로하는 구현을 작성하도록 강요하는 것이 바로 테스트 충분하다 replaceitchangeit단지입니다 가능성이 일할 수있는 간단한 구현 당신이 TDD를 실행하는 경우,이 당신에게 자연스럽게해야한다 장점 :.. 높은 테스트 커버리지없이 많은 중복 된 노력.
  • 서브 클래스에서 재정의 방법 (이 책 "효과적으로 레거시 코드 작업"에서 종속성 파괴 기술입니다) : 테스트는 테스트 목적, 재정으로 만 소개하는 서브 클래스의 방법 replaceitchangeit그들이 감지 변수를 설정하는 것이 정도 통조림 답변 (메서드가 올바른 값으로 호출되었는지 여부를 나타내는 변수). 장점 : 테스트를 단순화 할 수도 있고 단순화 할 수도 있고 때로는 테스트를 가능하게 할 수도 있습니다.
  • 해당 클래스에 대한 인터페이스를 포함 하여 replaceitchangeit메서드에 대한 새 클래스를 추출합니다 . 테스트 할 때 해당 인터페이스를 Stub 또는 Mock합니다 modify. 장점 : 힘을 모두 설계가 더 테스트 할 수 있도록 하고 더 나은 분리 / 일반 (여부)에 재사용.

이미 테스트 replaceit()하고 changeit()독립적으로 테스트 한 경우 테스트 할 유일한 것은 if 조건입니다. 테스트 modify()몇 가지 값은 (있는 이러한 조건 권리 적절한 조건에서 함수를 호출 확인합니다 null그리고 Strings당신이 준 예제 코드 길이 4, 5, 6 참조).


그냥 테스트하십시오 modify.

Modify 특정 값이 주어지면 특정 값을 반환해야합니다.

그것은 중요하지의 방법 에만 있음 - 수정이 일을 수행 그것의 일을.

그리고 향후에 modify다른 방법을 사용하거나 사용하지 않도록 변경 하는 경우 테스트에 영향을주지 않으며 영향을주지 않아야합니다.

즉, replaceit' andchangeit 도 테스트하십시오 .


선호하는 순서대로

  1. modify (test)에는 2 개의 시나리오 (if stmt의 각 팔)가 있으므로 양식 수정을 위해 2 개의 테스트를 작성합니다.
    replaceit (value)의 예상 결과를 쉽게 알 수 있다면 ..

.

public TestModifyIfValueLength..()
    {
      string expectedValue = .. ;// literal result of replaceit(value)
      Assert.Equals( expectedValue, modify("asd") );
    }
  1. 그렇지 않은 경우 스텁 (서브 클래스 사용 및 changeit, replaceit 재정의)을 사용하여 올바른 메서드가 호출되었는지 확인하는 것이 좋습니다.
  2. 스텁이 너무 많은 작업이면 모의 작업을 수행하십시오. 인터페이스를 추출하고 changeit, replaceit에 대한 기대치를 설정하십시오.

가정

  • 두 가지 방법을 포괄적으로 테스트하는 replaceit (value) 및 changeit (value) 테스트 (예 : 모든 경계 조건)가 있습니다.
  • replaceit () 및 changeit ()는 공용 메서드입니다. 그렇지 않은 경우 공용 메서드에 대해서만 테스트 작성을 고려해야합니다. 테스트 코드를 알지 못해도 개인 메서드를 자유롭게 조정 / 제거 할 수 있습니다.

이 경우 "테스트 코드"는 무엇입니까? 결과를 설정하고 확인 하시겠습니까? 그렇다면 다른 방법으로 리팩토링하고 각 테스트에서 사용합니다. 그래도 상당한 양이있는 경우에만이 작업을 수행 할 것입니다. 해당 메서드의 코드를 읽는 것만으로 테스트가 수행하는 모든 작업을 볼 수있는 가독성 이점이 있습니다.

복잡한 테스트 방법은 솔직히 말해서 종종 처음부터 귀찮게합니다. 종종 현실적으로 피할 수 없지만 단순화 있다면 그렇게 가치가 있습니다.


아니요, 테스트 코드는 99 % 동일하지 않을 것입니다. 왜냐하면 replaceit, changeit 및 modify가 모두 동일한 값을 반환하지 않는 한 여기서 실제로 다른 것을 테스트하고 있기 때문입니다.

왜 어려운지 잘 모르겠습니다. 수정 메서드에 대한 테스트는 약 4 줄 길이 여야합니다. 이미 기본 기능을 테스트하고 있고 원하는 것은이 특정 메서드가 중단되지 않는지 확인하는 것이므로이 함수에서 가능한 두 코드 경로를 테스트하는 테스트를 작성하면 예상 값을 반환하는 것으로 충분합니다.


replaceit () 및 changeit ()에 대한 테스트를 이미 작성했다면 modify 테스트는 단순히 'value'의 값에 따라 다른 결과가 반환되는지 확인합니다. 그러나 테스트에서 메서드의 논리를 간단히 다시 구현하는 것은 약간 어리석은 일입니다.

이 경우 더 복잡한 로직이 있거나 더 나은 테스트를 위해 더 중요한 다른 방법에서 사용되기 전까지는 수정을 테스트하지 않습니다.


기본적으로 2 개의 테스트가 필요합니다.

1) "The Quick Brown Fox Jumps!"와 같은 문자열을 전달합니다. (5보다 큰 길이) 값이 영향을 받는지 확인합니다.replaceit(...)

2) "Foo"(길이가 5 미만)와 같은 문자열을 전달하고 값이 영향을 받는지 확인하십시오. changeit(...)

테스트 (의사 코드)는 다음과 같습니다.

testLongValue() {
    string testValue = "A value longer than 5 chars";
    string expected = "Replaced!";
    string actual = modify(testValue);
    assertEqual(expected, actual);
}

testShortValue() {
    string testValue = "len4";
    string expected = "Changed!";
    string actual = modify(testValue);
    assertEqual(expected, actual);
}

replacit () 및 changeit ()이 무엇을해야하는지 알고 있다면보다 현실적인 예제를 제공 할 수 있지만, 이것이 여러분에게 아이디어를 줄 것입니다. 원래 값 참조를 반환하는 대신 변경하면 호출이 발생한 후 testValue를 실제 값으로 사용할 수 있습니다.


같은 경계 조건을 테스트 할 때는 테스트 if (value.length > 5)데이터에 value길이 45, 또는 인 값이 포함되어 있는지 확인해야합니다 6.


You can create a func out of the methods and mock those funcs. Or, you can create a virtual methods and using Rhino mocks - partial mock, you can mock those virtual methods.


Same as Justin Standard, plus passing null as value (which obviously will fails for the code snippet you give us ;)) Basic rule for Unit testing is "test only what is specific to the method under test". And it quite ... uncommon to have a method that doesn't call another one.

ReferenceURL : https://stackoverflow.com/questions/363596/unit-testing-a-method-that-calls-another-method

반응형