[unit-testing] 단위 테스트를 처음 사용하는 경우 훌륭한 테스트를 작성하는 방법은 무엇입니까? [닫은]

단위 테스트 세계에 익숙하지 않아 이번 주에 기존 앱에 대한 테스트 범위를 추가하기로 결정했습니다.

이것은 테스트 할 클래스의 수는 많지만 테스트 작성은 모두 나에게 새롭기 때문에 큰 작업입니다.

이미 여러 클래스에 대한 테스트를 작성했지만 지금 제대로하고 있는지 궁금합니다.

메소드에 대한 테스트를 작성할 때 메소드 자체에 이미 쓴 내용을 두 번 다시 쓰는 느낌이 듭니다.
내 테스트는 메소드에 너무 밀접하게 묶여있는 것 같습니다 (모든 인수를 사용하여 일부 내부 메소드가 여러 번 호출 될 것으로 예상하는 모든 코드 경로 테스트). 메소드를 리팩터링하면 테스트가 실패하더라도 방법의 최종 행동은 변하지 않았다.

이것은 단지 느낌 일 뿐이며 앞서 말한 것처럼 테스트 경험이 없습니다. 경험이 풍부한 테스터 중 일부가 기존 앱에 대해 훌륭한 테스트를 작성하는 방법에 대한 조언을 제공 할 수 있다면 크게 감사하겠습니다.

편집 : Stack Overflow에 감사 드리고 싶습니다 .15 분도 채 안되는 시간 동안 온라인에서 읽은 시간보다 더 많은 답변을 얻었습니다.



답변

내 테스트는 메소드에 너무 밀접하게 묶여있는 것 같습니다 (모든 인수를 사용하여 일부 내부 메소드가 여러 번 호출 될 것으로 예상하는 모든 코드 경로 테스트). 메소드를 리팩터링하면 테스트가 실패하더라도 테스트가 실패하는 것처럼 보입니다. 방법의 최종 행동은 변하지 않았다.

당신이 잘못하고 있다고 생각합니다.

단위 테스트는 다음을 수행해야합니다.

  • 하나의 방법을 테스트
  • 그 방법에 대한 특정 주장을 제공
  • 결과가 예상대로인지 테스트

내부를 변경하면 테스트가 실패하지 않아야합니다. 개인 메소드가 호출되는지 직접 테스트해서는 안됩니다. 개인 코드를 테스트하고 있는지 확인하려면 코드 범위 도구를 사용하십시오. 그러나이 점에 집착하지 마십시오. 100 % 적용 범위는 필수 사항이 아닙니다.

메소드가 다른 클래스의 공용 메소드를 호출하고 이러한 호출이 인터페이스에 의해 보장되는 경우 모의 프레임 워크를 사용하여 이러한 호출이 수행되고 있는지 테스트 할 수 있습니다.

예상되는 결과를 동적으로 생성하기 위해 메소드 자체 (또는 메소드가 사용하는 내부 코드)를 사용해서는 안됩니다. 예상 결과는 구현이 변경 될 때 변경되지 않도록 테스트 케이스에 하드 코딩되어야합니다. 다음은 단위 테스트의 간단한 예입니다.

testAdd()
{
    int x = 5;
    int y = -2;
    int expectedResult = 3;
    Calculator calculator = new Calculator();
    int actualResult = calculator.Add(x, y);
    Assert.AreEqual(expectedResult, actualResult);
}

결과 계산 방법은 확인되지 않으며 결과 만 정확합니다. 가능한 한 많은 시나리오를 다룰 때까지 위와 같이 더 간단한 테스트 사례를 계속 추가하십시오. 코드 커버리지 도구를 사용하여 흥미로운 경로를 놓쳤는 지 확인하십시오.


답변

단위 테스트의 경우 Test Driven (첫 번째 테스트, 코드 두 번째)과 code first (테스트 두 번째)가 모두 유용하다는 것을 알았습니다.

코드를 작성하고 테스트를 작성하는 대신. 코드를 작성하고 코드가해야 할 일을 살펴보십시오. 의도 된 모든 용도에 대해 생각한 다음 각각에 대한 테스트를 작성하십시오. 코딩 테스트보다 코딩 테스트가 더 빠르지 만 더 복잡합니다. 테스트는 의도를 테스트해야합니다. 또한 시험 작문 단계에서 코너 케이스를 찾는 의도에 대해 생각하십시오. 그리고 물론 테스트를 작성하는 동안 몇 가지 용도 중 하나가 버그를 일으키는 것을 알 수 있습니다.

그러나 테스트는 거의 두 번 코딩하는 것과 같습니다. 실제로 응용 프로그램 코드보다 테스트 코드 (수량)가 더 많은 응용 프로그램이 있습니다. 하나의 예는 매우 복잡한 상태 머신입니다. 더 많은 로직을 추가 한 후 모든 것이 항상 이전의 모든 유스 케이스에서 작동했는지 확인해야했습니다. 그리고 코드를 살펴보면 이러한 경우를 따르기가 매우 어려웠으므로 변경을 한 후에도 중단되지 않을 것이라고 확신하는이 컴퓨터에 적합한 테스트 스위트를 갖추었고 테스트 결과 내 엉덩이가 몇 번 절약되었습니다. . 그리고 사용자 나 테스터가 설명되지 않은 흐름 또는 코너 사례로 버그를 발견함에 따라 무엇을 테스트하고 테스트에 추가했으며 다시는 발생하지 않았 음을 추측하십시오. 이것은 정말로 모든 것을 매우 안정적으로 만드는 것 외에도 사용자에게 내 작업에 대한 자신감을 주었다. 성능상의 이유로 다시 작성해야했을 때

모든 간단한 예제 function square(number)는 훌륭하고 모두 테스트에 많은 시간을 할애 할 수 있습니다. 중요한 비즈니스 로직을 수행하는 것, 테스트가 중요한 것. 요구 사항을 테스트하십시오. 배관 테스트 만하지 마십시오. 요구 사항이 바뀌면 무엇을 추측해야하는지 테스트도해야합니다.

테스트는 문자 foo를 호출 한 함수 표시 줄을 3 번 테스트하는 것이 아닙니다. 그건 잘못이야 내부 역학이 아닌 결과와 부작용이 올바른지 확인하십시오.


답변

기존 코드에 개장 단위 테스트를 수정하는 것이 처음에 테스트로 코드를 작성하는 것보다 훨씬 어렵다는 점에 주목할 가치가 있습니다. 레거시 응용 프로그램을 다루는 데있어 가장 큰 질문 중 하나입니다. 단위 테스트 방법? 이것은 여러 번 전에 요청되었으므로 (질문 과 같은 질문으로 닫힐 있음) 사람들은 보통 여기에 있습니다.

기존 코드를 테스트 중심 개발로 이동

나는 받아 들인 답변의 책 추천을 두 번째로 넘어서지 만 그 외에도 답변에 연결된 더 많은 정보가 있습니다.


답변

코드를 완전히 다루기 위해 테스트를 작성하지 마십시오. 요구 사항을 보장하는 테스트를 작성하십시오. 불필요한 코드 경로를 발견 할 수 있습니다. 반대로, 필요한 경우, 어떤 종류의 요구 사항을 충족해야합니다. 그것이 무엇인지 찾고 요구 사항을 테스트하십시오 (경로 아님).

테스트는 작게 유지하십시오 (요구 사항 당 하나의 테스트).

나중에 변경하거나 새 코드를 작성해야 할 경우 먼저 하나의 테스트를 작성하십시오. 딱 하나만. 그런 다음 테스트 중심 개발의 첫 단계를 밟게됩니다.


답변

단위 테스트는 함수 / 메소드 / 애플리케이션에서 얻은 출력에 대한 것입니다. 결과가 어떻게 생성되는지는 중요하지 않으며 결과가 정확하다는 것만 중요합니다. 따라서 내부 메소드에 대한 호출을 계산하는 방식은 잘못되었습니다. 내가하는 경향은 앉아서 특정 입력 값이나 특정 환경에서 메소드가 반환 해야하는 것을 작성한 다음 반환 된 실제 값과 내가 얻은 것과 비교하는 테스트를 작성하는 것입니다.


답변

테스트 할 메소드를 작성하기 전에 단위 테스트를 작성하십시오.

그렇게하면 일이 어떻게 진행되고 있는지에 대해 조금 다르게 생각하게 될 것입니다. 방법이 어떻게 작동하는지, 어떻게해야하는지 전혀 모를 것입니다.

메소드가 결과를 얻는 방법이 아니라 항상 메소드 결과를 테스트해야합니다.


답변

테스트는 유지 관리 성을 향상시켜야합니다. 방법을 변경하고 테스트를 중단 하면 좋은 결과가 될 있습니다. 반면에, 메소드를 블랙 박스로 보면 메소드 내부의 내용이 중요하지 않습니다. 사실 일부 테스트를 위해 조롱해야하며,이 경우 실제로 방법을 블랙 박스로 취급 할 수 없습니다. 통합 테스트를 작성하는 것이 유일한 방법입니다. 테스트중인 서비스의 완전히 인스턴스화 된 인스턴스를로드하고 앱에서 실행되는 것과 같은 방식으로 수행하십시오. 그런 다음 블랙 박스로 취급 할 수 있습니다.

When I'm writing tests for a method, I have the feeling of rewriting a second time what I
already wrote in the method itself.
My tests just seems so tightly bound to the method (testing all codepath, expecting some
inner methods to be called a number of times, with certain arguments), that it seems that
if I ever refactor the method, the tests will fail even if the final behavior of the
method did not change.

코드를 작성한 후 테스트를 작성하기 때문입니다. 다른 방법으로 테스트를 수행했다면 (먼저 테스트를 작성하십시오) 이런 느낌이 들지 않습니다.