태그 보관물: unit-testing

unit-testing

단위 테스트 대신 수락 및 통합 테스트를 사용하는 것으로 충분합니까? 대해 어떻게 생각하십니까? 편집하다 디자인이 좋은

이 질문에 대한 짧은 소개. 나는 지금 TDD와 요즘 BDD를 1 년 이상 사용했다. 테스트를보다 효율적으로 작성하기 위해 조롱과 같은 기술을 사용합니다. 최근에 나는 작은 돈 관리 프로그램을 작성하기위한 개인 프로젝트를 시작했다. 레거시 코드가 없었기 때문에 TDD로 시작하기에 완벽한 프로젝트였습니다. 불행히도 나는 TDD의 기쁨을 그다지 경험하지 못했습니다. 그것은 심지어 프로젝트를 포기했을 정도로 재미를 망쳐 버렸습니다.

문제는 무엇 이었습니까? 글쎄, 나는 테스트 / 요구 사항이 프로그램의 디자인을 발전 시키도록 TDD와 같은 접근법을 사용했다. 문제는 쓰기 / 리 팩터 테스트와 관련하여 개발 시간의 절반 이상이 문제였습니다. 결국 많은 테스트에 리팩토링하고 작성해야하므로 더 이상 기능을 구현하고 싶지 않았습니다.

직장에서 많은 레거시 코드가 있습니다. 여기에서는 점점 더 많은 통합 및 승인 테스트와 더 적은 단위 테스트를 작성합니다. 버그는 대부분 승인 및 통합 테스트에 의해 감지되므로 이는 나쁜 접근 방법이 아닙니다.

내 생각은 결국 단위 테스트보다 더 많은 통합 및 승인 테스트를 작성할 수 있다는 것입니다. 내가 버그를 감지했다고 말했듯이 단위 테스트는 통합 / 수락 테스트보다 낫지 않습니다. 단위 테스트도 설계에 좋습니다. 나는 그것들을 많이 쓰는 데 사용 되었기 때문에 내 수업은 항상 테스트 할 수 있도록 설계되었습니다. 또한 테스트 / 요구 사항이 설계를 안내하도록하는 접근 방식은 대부분의 경우 더 나은 설계로 이어집니다. 단위 테스트의 마지막 장점은 더 빠릅니다. 나는 단위 테스트만큼 빠르다는 것을 알기에 충분한 통합 테스트를 작성했습니다.

내가 알아 낸 웹을 통해보고 된 후 언급 한 광산과 매우 유사한 아이디어가 있다는 것을 여기거기는 . 이 아이디어에 대해 어떻게 생각하십니까?

편집하다

디자인이 좋은 예에 대한 질문에 대답했지만 다음 요구 사항에 대해 큰 리팩터링이 필요했습니다.

처음에는 특정 명령을 실행하기위한 몇 가지 요구 사항이있었습니다. 확장 가능한 명령 파서를 작성했습니다.이 명령은 일종의 명령 프롬프트에서 명령을 구문 분석하고 모델에서 올바른 명령 프롬프트를 호출했습니다. 결과는 뷰 모델 클래스로 표시되었습니다.
첫 번째 디자인

여기에는 아무런 문제가 없었습니다. 모든 클래스는 서로 독립적이었고 새 명령을 쉽게 추가하고 새 데이터를 표시 할 수있었습니다.

다음 요구 사항은 모든 명령에 자체 뷰 표현이 있어야한다는 것입니다. 명령 결과의 미리보기입니다. 새로운 요구 사항에 맞는 더 나은 디자인을 달성하기 위해 프로그램을 재 설계했습니다.
두 번째 디자인

이제는 모든 명령에 자체 뷰 모델이 있으므로 자체 미리보기가 있기 때문에 좋았습니다.

문제는 명령 구문 분석기가 명령의 토큰 기반 구문 분석을 사용하도록 변경되었으며 명령 실행 기능에서 제거되었다는 것입니다. 모든 명령에는 자체 뷰 모델이 있으며 데이터 뷰 모델은 표시해야 할 데이터를 알고있는 것보다 현재 명령 뷰 모델 만 알고 있습니다.

이 시점에서 내가 알고 싶은 것은 새로운 디자인이 기존 요구 사항을 위반하지 않는 경우입니다. 합격 시험을 변경할 필요가 없었습니다. 거의 모든 단위 테스트를 리팩토링하거나 삭제해야했는데, 이는 엄청난 작업이었습니다.

여기서 보여 드리고 싶은 것은 개발 과정에서 자주 발생하는 일반적인 상황입니다. 기존 디자인이나 새로운 디자인에는 아무런 문제가 없었으며 요구 사항에 따라 자연스럽게 바뀌 었습니다. 어떻게 이해했는지, 이것이 TDD의 장점 중 하나는 디자인이 발전한다는 것입니다.

결론

모든 답변과 토론에 감사드립니다. 이 토론을 요약하면 다음 프로젝트에서 테스트 할 접근법을 생각했습니다.

  • 우선 항상 항상했던 것처럼 구현하기 전에 모든 테스트를 작성합니다.
  • 요구 사항에 대해서는 처음에 전체 프로그램을 테스트하는 승인 테스트를 작성합니다. 그런 다음 요구 사항을 구현해야하는 구성 요소에 대한 통합 테스트를 작성합니다. 이 요구 사항을 구현하기 위해 다른 구성 요소와 밀접하게 작동하는 구성 요소가 있으면 두 구성 요소를 함께 테스트하는 통합 테스트도 작성합니다. 마지막으로 알고리즘이나 순열이 높은 다른 클래스 (예 : 직렬 변환기)를 작성 해야하는 경우이 특정 클래스에 대한 단위 테스트를 작성합니다. 다른 모든 클래스는 테스트되지 않고 단위 테스트가 수행됩니다.
  • 버그의 경우 프로세스를 단순화 할 수 있습니다. 일반적으로 버그는 하나 또는 두 개의 구성 요소로 인해 발생합니다. 이 경우 버그를 테스트하는 구성 요소에 대해 하나의 통합 테스트를 작성합니다. 알고리즘과 관련이 있다면 단위 테스트 만 작성합니다. 버그가 발생하는 구성 요소를 찾기가 쉽지 않으면 버그를 찾기 위해 승인 테스트를 작성합니다. 이는 예외입니다.


답변

오렌지와 사과를 비교하고 있습니다.

통합 테스트, 승인 테스트, 단위 테스트, 행동 테스트-모두 테스트이며 코드를 개선하는 데 도움이되지만 상당히 다릅니다.

나는 내 의견으로 각기 다른 테스트를 살펴보고 왜 당신이 모든 테스트를 혼합해야 하는지를 설명 할 것입니다.

통합 테스트 :

예를 들어, 웹 서비스 요청을 시뮬레이션하고 결과가 다시 나타나는지 확인하는 등 시스템의 여러 구성 요소가 올바르게 통합되는지 테스트하십시오. 나는 일반적으로 실제 정적 데이터와 모의 의존성을 사용하여 일관성있게 확인할 수 있도록합니다.

합격 시험 :

승인 테스트는 비즈니스 사용 사례와 직접적으로 관련되어야합니다. 규모가 크거나 ( “거래가 올바르게 제출되었습니다”) 작거나 ( “필터가 목록을 성공적으로 필터링 함”) 중요하지 않습니다. 중요한 것은 특정 사용자 요구 사항과 명시 적으로 연결되어야한다는 것입니다. 나는 테스트 중심 개발에 초점을 맞추고 싶습니다. 개발자 및 qa에 대한 사용자 스토리에 대한 테스트에 대한 훌륭한 참조 매뉴얼이 있음을 의미하기 때문입니다.

단위 테스트 :

개별 사용자 스토리를 자체적으로 구성하거나 구성하지 않을 수있는 작은 개별 기능 단위의 경우 (예 : 특정 웹 페이지에 액세스 할 때 모든 고객을 검색한다고 말하는 사용자 스토리는 승인 테스트 일 수 있음) 페이지 및 응답 확인)에도 여러 단위 테스트가 포함될 수 있습니다 (보안 권한이 확인되었는지 확인하고 데이터베이스 연결 쿼리를 올바르게 확인하는지, 결과 수를 제한하는 코드가 올바르게 실행되는지 확인하십시오)-모두 “단위 테스트”입니다. 그것은 완전한 합격 시험이 아닙니다.

행동 테스트 :

특정 입력의 경우 애플리케이션의 흐름을 정의하십시오. 예를 들어, “연결을 설정할 수없는 경우 시스템이 연결을 재 시도하는지 확인하십시오.” 다시 말하지만 이것은 완전한 합격 테스트는 아니지만 여전히 유용한 것을 확인할 수 있습니다.

이것들은 모두 작문 시험 경험을 통해 제 생각에 있습니다. 나는 교과서 접근법에 중점을 두는 것이 아니라 테스트 가치를 부여하는 것에 중점을 둡니다.


답변

TL; DR : 귀하의 요구를 충족시키는 한, 그렇습니다.

저는 수년간 ATDD (Acceptance Test Driven Development) 개발을 해왔습니다. 매우 성공할 수 있습니다. 알아 두어야 할 것이 몇 가지 있습니다.

  • 단위 테스트는 실제로 IOC 시행에 도움이됩니다. 단위 테스트가 없으면 개발자는 잘 작성된 코드의 요구 사항을 충족하는지 확인해야합니다 (단위 테스트가 잘 작성된 코드를 구동하는 한).
  • 실제로 조롱되는 리소스를 실제로 사용하는 경우 속도가 느려지고 오류가 발생할 수 있습니다.
  • 단위 테스트와 마찬가지로 테스트에서 특정 문제를 찾아 내지 않습니다. 테스트 실패를 해결하려면 추가 조사를 수행해야합니다.

이제 장점

  • 훨씬 더 나은 테스트 범위, 통합 지점을 다룹니다.
  • 시스템 전체가 소프트웨어 개발의 핵심 인 수용 기준을 충족하는지 확인합니다.
  • 큰 리 팩터를 훨씬 쉽고 빠르며 저렴하게 만듭니다.

항상 그렇듯이 분석을 수행하고이 관행이 귀하의 상황에 적합한 지 파악하는 것은 귀하의 책임입니다. 많은 사람들과 달리 나는 이상적인 정답이 있다고 생각하지 않습니다. 요구 사항과 요구 사항에 따라 다릅니다.


답변

글쎄, 나는 테스트 / 요구 사항이 프로그램의 디자인을 발전 시키도록 TDD와 같은 접근법을 사용했다. 문제는 쓰기 / 리 팩터 테스트와 관련하여 개발 시간의 절반 이상이

단위 테스트는 사용되는 구성 요소의 공용 인터페이스가 너무 자주 변경되지 않을 때 가장 잘 작동합니다. 즉, 구성 요소가 이미 잘 설계되어있는 경우 (예 : SOLID 원칙에 따름)를 의미합니다.

따라서 좋은 디자인이 구성 요소에 대한 많은 단위 테스트를 “던지기”에서 “진화”한다고 믿는 것은 잘못된 것입니다. TDD는 훌륭한 디자인을위한 “교사”가 아니며, 디자인의 특정 측면이 좋은지 (특히 테스트 가능성) 확인하는 데 도움이 될 수 있습니다.

요구 사항이 변경되고 구성 요소의 내부를 변경해야 할 경우 단위 테스트의 90 %가 중단되므로 매우 자주 리팩터링해야합니다.

그래서 내 충고는 : 당신이 만든 구성 요소의 디자인과 개방 / 폐쇄 원칙에 따라 더 구성 요소를 만드는 방법에 대해 생각하십시오. 후자의 개념은 구성 요소의 기능을 나중에 변경하지 않고도 확장 할 수 있도록하는 것입니다 (따라서 단위 테스트에 사용되는 구성 요소의 API를 손상시키지 않음). 이러한 구성 요소는 단위 테스트 테스트로 다룰 수 있으며 경험 한 바에 따라 경험 한대로 고통스럽지 않아야합니다.

이러한 설계를 즉시 제시 할 수없는 경우 승인 및 통합 테스트가 더 나은 시작일 수 있습니다.

편집 : 때로는 구성 요소 디자인이 좋지만 단위 테스트 디자인에 문제가 발생할 수 있습니다 . 간단한 예 : 클래스 X의 “MyMethod”메소드를 테스트하고 작성하려고합니다.

    var x= new X();
    Assert.AreEqual("expected value 1" x.MyMethod("value 1"));
    Assert.AreEqual("expected value 2" x.MyMethod("value 2"));
    // ...
    Assert.AreEqual("expected value 500" x.MyMethod("value 500"));

(값에 어떤 종류의 의미가 있다고 가정).

또한 프로덕션 코드에는에 대한 호출이 하나만 있다고 가정하십시오 X.MyMethod. 이제 새로운 요구 사항의 경우 “MyMethod”메서드에는 추가 매개 변수 (예 :와 같은 context)가 필요하므로 생략 할 수 없습니다. 단위 테스트가 없으면 한 곳에서 호출 코드를 리팩터링해야합니다. 단위 테스트를 통해 500 곳을 리팩토링해야합니다.

그러나 여기서의 원인은 단위 테스트 자체가 아니라 “X.MyMethod”에 대한 동일한 호출이 “DRY (Do n’t Repeat Yourself)”원칙을 엄격하게 따르지 않고 반복해서 반복된다는 사실입니다. 여기서는 테스트 데이터와 관련 예상 값을 목록에 넣고 루프에서 “MyMethod”에 대한 호출을 실행합니다 (또는 테스트 도구가 “데이터 드라이브 테스트”를 지원하는 경우 해당 기능을 사용함). 메소드 서명이 1로 변경 될 때 단위 테스트에서 변경되는 위치 수 (500과 반대)

실제 상황에서는 상황이 더 복잡 할 수 있지만 단위 테스트에서 변경 될 수 있는지 알 수없는 구성 요소 API를 사용하는 경우 수를 줄이십시오. 해당 API 호출을 최소한으로합니다.


답변

물론입니다.

이걸 고려하세요:

  • 단위 테스트는 작은 코드를 실행하는 작고 대상이 지정된 테스트입니다. 적절한 코드 범위를 달성하기 위해 많은 것을 작성하여 모든 (또는 어색한 비트의 대부분)을 테스트합니다.
  • 통합 테스트는 코드의 넓은 표면을 시험하는 광범위하고 광범위한 테스트입니다. 적절한 코드 범위를 달성하기 위해 그중 몇 가지를 작성하여 모든 (또는 어색한 비트의 대부분)을 테스트합니다.

전반적인 차이점을 참조하십시오 ….

이 문제는 코드 적용 범위 중 하나입니다. 통합 / 수락 테스트를 사용하여 모든 코드를 완전히 테스트 할 수 있다면 문제는 없습니다. 코드가 테스트되었습니다. 그것이 목표입니다.

모든 TDD 기반 프로젝트는 모든 단위가 실제로 제대로 작동하는지 확인하기 위해 통합 테스트가 필요하기 때문에 혼합해야 할 수도 있습니다 (100 % 통과 된 단위 테스트 코드베이스가 반드시 작동하지는 않습니다. 당신이 그들을 모두 모을 때!)

문제는 실제로 테스트의 용이성, 오류 디버깅 및 수정에 달려 있습니다. 어떤 사람들은 단위 테스트가 매우 훌륭하다는 것을 알고 있으며 작고 단순하며 실패를 쉽게 볼 수 있지만 단점은 단위 테스트 도구에 맞게 코드를 재구성하여 매우 많이 작성해야한다는 단점이 있습니다. 통합 테스트는 많은 코드를 다루기 위해 작성하기가 더 어려우므로 오류를 디버깅하기 위해 로깅과 같은 기술을 사용해야 할 수도 있습니다 (그러나 어쨌든이 작업을 수행해야한다고 말하면 단위 테스트 실패는 불가능합니다) 현장에있을 때!).

어느 쪽이든, 당신은 여전히 ​​테스트 된 코드를 얻습니다. 어떤 메커니즘이 더 적합한 지 결정하면됩니다. (나는 약간의 혼합으로 가고 복잡한 알고리즘을 단위 테스트하고 나머지는 통합 테스트한다).


답변

나는 그것이 끔찍한 생각이라고 생각합니다.

승인 테스트와 통합 테스트는 코드의 더 넓은 부분을 터치하여 특정 대상을 테스트하므로 시간이 지남에 따라 더 많은 리팩토링 이 필요합니다 . 게다가 코드의 넓은 섹션을 다루기 때문에 검색 범위가 넓어 근본 원인을 추적하는 데 소요되는 시간이 늘어납니다.

아니요, UI가 90 % 인 이상한 앱이나 단위 테스트에 어색한 것이 없다면 일반적으로 더 많은 단위 테스트를 작성해야합니다. 당신이 겪고있는 고통은 단위 테스트가 아니라 테스트 첫 개발을하는 것입니다. 일반적으로 대부분의 필기 시험에서 1/3의 시간 만 투자해야합니다. 결국, 그들은 당신을 섬기기 위해 거기에 있습니다.


답변

TDD의 “승리”는 일단 테스트가 작성되면 자동화 될 수 있다는 것입니다. 단점은 개발 시간의 상당한 부분을 소비 할 수 있다는 것입니다. 이것이 실제로 전체 프로세스 속도를 늦출 지 여부는 바보입니다. 선행 테스트를 통해 개발주기가 끝날 때 수정해야 할 오류 수가 줄어든다는 주장이 있습니다.

이것은 행동이 단위 테스트에 포함될 수 있기 때문에 BDD가 발생하는 곳이므로 프로세스는 덜 추상적이며 유형적입니다.

시간이 얼마 남지 않았다면 가능한 한 다양한 종류의 테스트를 많이해야합니다. 그러나 시간은 일반적으로 제한되어 있으며 지속적인 테스트는 비용 효율적입니다.

이 모든 것이 가장 가치있는 테스트가 프로세스의 최전방에 있어야한다는 결론으로 ​​이어집니다. 이것은 그 자체로 한 가지 유형의 테스트를 다른 유형보다 자동으로 선호하지 않습니다.

개인적인 용도로 명령 행 위젯을 작성하는 경우 주로 단위 테스트에 관심이 있습니다. 웹 서비스가 말하는 반면, 상당한 양의 통합 / 행동 테스트가 필요합니다.

대부분의 유형의 테스트는 “레이싱 라인”이라고하는 것에 중점을 두는 반면, 오늘날 비즈니스에서 요구하는 것을 테스트하는 반면, 단위 테스트는 이후 개발 단계에서 나타날 수있는 미묘한 버그를 제거하는 데 탁월합니다. 이는 쉽게 측정 할 수없는 이점이므로 간과되는 경우가 많습니다.


답변

단위 테스트의 마지막 장점은 더 빠릅니다. 나는 단위 테스트만큼 빠르다는 것을 알기에 충분한 통합 테스트를 작성했습니다.

이것이 바로 “마지막 이점”이 아니라 요점입니다. 프로젝트가 점점 커질수록 통합 승인 테스트는 점점 느려지고 있습니다. 그리고 여기, 나는 당신이 그것들을 실행을 멈출 수 있도록 너무 느리다는 것을 의미합니다.

물론 단위 테스트도 느려지고 있지만 여전히 몇 배 이상 빠릅니다. 예를 들어, 이전 프로젝트 (c ++, 약 600kLOC, 4000 단위 테스트 및 200 통합 테스트)에서는 통합 테스트를 실행하는 데 약 15 분 이상이 소요되었습니다. 변경되는 부품에 대한 단위 테스트를 빌드하고 실행하려면 평균 30 초 미만이 소요됩니다. 그렇게 빨리 할 수 ​​있으면 항상하고 싶을 것입니다.

분명히하기 위해 : 통합 및 승인 테스트를 추가하지 말라고 말하지는 않지만 잘못된 방식으로 TDD / BDD를 한 것처럼 보입니다.

단위 테스트도 설계에 좋습니다.

예, 테스트 가능성을 염두에두고 디자인하면 디자인이 향상됩니다.

문제는 쓰기 / 리 팩터 테스트와 관련하여 개발 시간의 절반 이상이 문제였습니다. 결국 많은 테스트에 리팩토링하고 작성해야하므로 더 이상 기능을 구현하고 싶지 않았습니다.

요구 사항이 변경되면 코드를 변경해야합니다. 단위 테스트를 작성하지 않으면 작업을 완료하지 않았다고 말할 것입니다. 그러나 이것이 단위 테스트를 100 % 적용해야한다는 의미는 아닙니다. 이것이 목표가 아닙니다. GUI 나 파일에 접근하는 것과 같은 것들도 단위 테스트를위한 것이 아닙니다.

그 결과 코드 품질이 향상되고 또 다른 테스트 계층이 만들어집니다. 그만한 가치가 있다고 말할 것입니다.


또한 1000 번의 수락 테스트를 받았으며 모두 실행하는 데 1 주일이 걸렸습니다.