단위 테스트-시작


14

방금 단위 테스트를 시작했지만 그 점을 실제로 이해하고 있는지 확실하지 않습니다. 튜토리얼과 책을 모두 읽었지만 두 가지 간단한 질문이 있습니다.

  1. 단위 테스트의 목적은 실제로 작성한 코드를 테스트하는 것이라고 생각했습니다. 그러나 테스트를 실행하려면 원래 코드를 변경해야합니다.이 시점에서 실제로 작성한 코드를 테스트하는 것이 아니라 테스트를 위해 작성한 코드를 테스트해야합니다.

  2. 우리 코드의 대부분은 외부 소스에 의존합니다. 그러나 코드를 리팩토링하면 원래 코드가 손상 되더라도 외부 소스는 테스트 케이스 내부에서 모방되기 때문에 테스트는 여전히 잘 실행됩니다. 단위 테스트의 목적을 무효화하지 않습니까?

내가 바보처럼 들리면 미안하지만 누군가 나를 조금 밝힐 수 있다고 생각했다.

미리 감사드립니다.

답변:


7

내 0.02 $ ... 이것은 약간 주관적이므로 소금 한 알을 섭취하십시오.

  1. 나에게 단위 테스트의 기본 목적은 작성한 코드가 계약 및 코드가 수행하려는 최종 사례를 충족하는지 확인하는 것입니다. 단위 테스트를 실시하면 코드를 리팩터링 할 때 코드의 모든 외부 소비자가 적절한 주 적용 범위를 유지하더라도 영향을받지 않아야합니다. (적어도 그들에게 영향을 미치지 않을 정도).

    대부분의 경우 프로덕션으로 제공되고 쉽게 단위 테스트가 가능한 코드를 작성할 수 있어야합니다. 시작하기에 좋은 장소는 Dependency Injection 패턴과 프레임 워크를 살펴 보는 것입니다. (또는 귀하의 언어 / 선택 플랫폼에 대한 다른 철학).

  2. 외부 구현이 코드에 영향을 줄 수있는 것은 맞습니다. 그러나 더 큰 시스템의 일부로 코드가 올바르게 작동하는지 확인하는 것은 통합 테스트 기능입니다 . (다양한 노력으로 자동화 할 수도 있음).

    이상적으로 코드는 타사 구성 요소의 API 계약에만 의존해야합니다. 즉, 모의가 올바른 API를 충족하는 한 단위 테스트는 여전히 가치를 제공합니다.

    즉, 통합 테스트만으로 단위 테스트를 포기한 경우가 있었지만 API가 제대로 문서화되지 않은 타사 구성 요소와 코드가 상호 작용 해야하는 경우에만 있음을 쉽게 인정할 것입니다. (즉, 규칙이 아닌 예외).


5
  1. 먼저 테스트를 작성하십시오. 그렇게하면 코드 동작에 대한 견고한 기반을 갖게되고 테스트는 코드의 필수 동작에 대한 계약이됩니다. 따라서, 테스트를 통과하기위한 코드 변경은 "테스트를 통과하기위한 코드 변경"대신 "테스트에서 제안한 계약을 이행하기위한 코드 변경"이된다.
  2. 스텁과 모의 차이점에주의하십시오. 코드 변경으로 인해 영향을받지 않는 것은 스텁의 특징적인 동작이지만 모의는 아닙니다. 모의의 정의로 시작하자 :

    Mock 객체는 테스트 조건에서 실제 객체를 대체하고 시스템 또는 단위 테스트의 일부로 자체 호출 (상호 작용)을 확인할 수 있습니다.

    -단위 테스트 기술

기본적으로, 모의는 상호 작용의 필수 동작을 확인해야합니다. 따라서 리팩토링 후에 데이터베이스와의 상호 작용이 실패하면 모의 테스트도 실패해야합니다. 물론 여기에는 한계가 있지만, 신중하게 계획하면 모의가 "앉아"있는 것 이상을 수행 할 것이며 "단위 테스트의 목적을 어기는 것"은 아닙니다.


1

좋은 질문을하는 것은 어리석은 일이 아닙니다.

나는 당신의 질문을 다룰 것입니다.

  1. 단위 테스트의 목적은 이미 작성한 코드를 테스트하는 것이 아닙니다 . 시간의 개념이 없습니다. TDD에서만 테스트 우선해야하지만 모든 종류의 단위 테스트에는 엄격하게 적용되지 않습니다. 요점은 클래스 수준에서 프로그램을 자동으로 효율적으로 테스트하는 것입니다. 코드 변경을 의미하더라도 도착하기 위해해야 ​​할 일을합니다. 그리고 내가 당신에게 비밀을 말해 보자-그것은 종종 그것을 의미합니다.
  2. 테스트를 작성할 때 테스트가 올바른지 확인하는 데 도움이되는 2 가지 기본 옵션이 있습니다.

    • 각 테스트에 대한 입력을 변경하십시오
    • 프로그램이 올바르게 작동하는지 확인하는 테스트 사례를 작성한 다음 프로그램 작동 하지 않는 방식으로 작동 하지 않는 해당 테스트 사례를 작성하십시오.

    예를 들면 다음과 같습니다.

    TEST(MyTest, TwoPlusTwoIsFour) {
        ASSERT_EQ(4, 2+2);
    }
    
    TEST(MyTest, TwoPlusThreeIsntFour) {
        ASSERT_NE(4, 2+3);
    }
    

    그 꼭대기에, 당신이있는 거 단위 테스트하는 경우 논리를 내부 사용자의 코드 (안 제 3 자 라이브러리), 그것은 그 상황에서하는 동안, 다른 코드 파괴에 대한 걱정을하지 않는 것이 좋은 완벽합니다. 기본적으로 논리가 래핑되는 방식을 테스트하고 있으며 클래식 테스트 시나리오 인 타사 유틸리티를 사용합니다.

클래스 수준에서 테스트를 마치면 클래스 (내가 이해 한 중재자)와 타사 라이브러리 간의 통합을 테스트 할 수 있습니다. 이러한 테스트를 통합 테스트라고하며 모의를 사용하지 않고 모든 클래스의 구체적인 구현을 사용합니다. 그들은 조금 느리지 만 여전히 매우 중요합니다!


1

void main()데이터베이스 액세스에서 출력 생성에 이르기까지 모든 것을 수행하는 단일 응용 프로그램이있는 것처럼 들립니다 . 적절한 단위 테스트를 시작하기 전에 여기에 몇 가지 단계가 있습니다.

1) 한 번 이상 작성 / 복사-붙여진 코드를 찾으십시오. 그냥하더라도 string fullName = firstName + " " + lastName. 다음과 같은 방법으로 나누십시오.

private static string GetFullName (firstName, lastName)
{
    return firstName + " " + lastName;
}

이제 단위 테스트 가능한 코드 조각이 있지만 사소한 것일 수 있습니다. 단위 테스트를 작성하십시오. 이 과정을 헹구고 반복하십시오. 결국에는 논리적으로 그룹화 된 많은 메소드가 생겨나 고 그로부터 많은 클래스를 추출 할 수 있습니다. 이 수업의 대부분은 테스트 가능합니다.

또한 여러 클래스를 추출한 후에는 인터페이스에서 인터페이스를 추출하고 객체 대신 인터페이스와 통신하도록 프로그램을 업데이트 할 수 있습니다. 이 시점에서 프로그램을 전혀 변경하지 않고 조롱 / 스터 빙 프레임 워크 (또는 자신의 수동 롤업 가짜)를 사용할 수 있습니다. 데이터베이스 쿼리를 클래스 (또는 여러 개)로 추출하면 쿼리 반환 해야하는 데이터를 가짜로 만들 수 있기 때문에 매우 유용 합니다 .


0

어떤 영리한 사람은 "테스트하기 어렵다면 아마도 나쁜 코드 일 것"이라고 말했다. 그렇기 때문에 코드를 다시 작성하여 unittest 할 수있는 것은 나쁜 일이 아닙니다. 외부 의존성이있는 코드는 테스트하기가 매우 어렵고 코드에 대한 위험을 나타내며 가능한 한 피해야하며 코드의 특정 영역 fx에 집중해야합니다. 정면 / 게이트웨이 유형 클래스. 이렇게하면 외부 구성 요소의 변경에 훨씬 쉽게 대처할 수 있습니다.

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