단위 테스트는 조기 일반화 (특히 C ++의 맥락에서)로 이어 집니까? 글쎄, 내가 보는 것처럼, (높은?)는 어떤 언어로

예비 메모

나는 다른 종류의 테스트의 구별에 들어 가지 않을 것 입니다.이 사이트에 대해서는 이미 몇 가지 질문 이 있습니다.

나는 거기에 무엇이 있는지를 말할 것이다. 응용 프로그램의 가장 작은 분리 가능한 단위 테스트”라는 의미의 단위 테스트

격리 문제

프로그램 에서 가장 작은 분리 가능한 단위 는 무엇입니까? 글쎄, 내가 보는 것처럼, (높은?)는 어떤 언어로 코딩하고 있는지에 달려 있습니다.

Micheal Feathers솔기 의 개념에 대해 이야기 합니다 : [WEwLC, p31]

이음새는 해당 위치에서 편집하지 않고 프로그램의 동작을 변경할 수있는 장소입니다.

그리고 세부 사항에 들어 가지 않고 단위 테스트의 맥락에서 이음새가 “테스트”가 “단위”와 인터페이스 할 수있는 프로그램의 장소라는 것을 이해합니다.

단위 테스트 (특히 C ++에서)는 테스트중인 코드에서 주어진 문제에 대해 엄격하게 요구되는 이음새 를 추가해야합니다 .

예:

  • 비가 상 구현으로 충분한 가상 인터페이스 추가
  • 분할-일반화 (?)-테스트 추가를 용이하게하는 “작은”클래스.
  • 단일 실행 가능 프로젝트를 “독립적 인”라이브러리로 분리하여 테스트를 위해 독립적으로 컴파일하는 것을 용이하게합니다.

질문

나는 같은 요점에 대해 희망적으로 묻는 몇 가지 버전을 시도 할 것입니다.

  • 단위 테스트가 단위 코드에 “유일한”응용 프로그램 코드를 구성하기 위해 하나를 요구하는 방식입니까 아니면 실제로 응용 프로그램 구조에 유리합니까?
  • 단위 테스트를 수행하는 데 필요한 코드 일반화가 단위 테스트 이외 의 다른 용도에 유용 합니까?
  • 단위 테스트를 추가하면 불필요하게 일반화해야합니까?
  • 코드에서 모양 단위 테스트가 “항상”힘이 문제 영역에서 일반적으로 보이는 코드에도 좋은 모양입니까?

나는 코드를 사용하는 두 번째 장소가 필요할 때까지 / 일반화하지 않았다는 경험 법칙을 기억합니다. 단위 테스트 를 사용하면 항상 코드를 사용하는 두 번째 장소, 즉 단위 테스트가 있습니다. 이 이유는 일반화하기에 충분합니까?



답변

단위 테스트 (특히 C ++에서)는 테스트중인 코드에서 주어진 문제에 대해 엄격하게 요구되는 이음새를 추가해야합니다.

문제 해결의 필수 부분 인 테스트를 고려하지 않는 경우에만 해당됩니다. 사소한 문제가 아니라면 소프트웨어 세계뿐만 아니라 문제가되어야합니다.

하드웨어 세계에서 이것은 오래 전부터 어려운 방법으로 배웠습니다. 다양한 장비 제조업체는 수세기에 걸쳐 떨어지는 다리, 자동차 폭발, CPU 흡연 등 소프트웨어 세계에서 현재 배우고있는 것을 배웠습니다. 그들 모두는 테스트 할 수 있도록 제품에 “추가 심”을 구축합니다. 오늘날 대부분의 신차에는 수리 기사가 엔진 내부에서 무슨 일이 일어나고 있는지에 대한 데이터를 얻을 수있는 진단 포트가 있습니다. 모든 CPU에서 트랜지스터의 상당 부분이 진단 목적으로 사용됩니다. 하드웨어 세계에서는 모든 “추가”재료 비용이 들며, 수백만 명이 제품을 제조 할 때 이러한 비용은 확실히 많은 돈을 더합니다. 그럼에도 불구하고 제조업체는 테스트를 위해이 모든 돈을 기꺼이 사용합니다.

소프트웨어 세계로 돌아가서 C ++은 동적 클래스 로딩, 리플렉션 등을 특징으로하는 이후의 언어보다 실제로 단위 테스트하기가 더 어렵습니다. 여전히 대부분의 문제는 완화 될 수 있습니다. 지금까지 단위 테스트를 사용한 C ++ 프로젝트에서 Java 프로젝트와 같이 자주 테스트를 실행하지는 않았지만 여전히 CI 빌드의 일부 였으므로 유용한 것으로 나타났습니다.

단위 테스트가 하나의 애플리케이션 코드를 구성하기 위해 하나만 요구하는 방법이 단위 테스트에 유용합니까? 아니면 실제로 애플리케이션 구조에 도움이됩니까?

필자의 경험에 따르면 테스트 가능한 디자인은 단위 테스트 자체에만 해당되는 것이 아니라 전체적으로 유리합니다. 이러한 이점은 다음과 같은 다양한 수준으로 제공됩니다.

  • 디자인을 테스트 가능하게 만들면 응용 프로그램을 제한적이고 잘 정의 된 방식으로 만 서로 영향을 줄 수있는 작고 다소 독립적 인 부분으로 청크 할 수 있습니다. 이는 프로그램의 장기적인 안정성과 유지 관리에 매우 중요합니다. 이 코드가 없으면 코드베이스의 일부를 변경하면 프로그램의 관련이없고 뚜렷한 부분에 예기치 않은 영향을 줄 수있는 스파게티 코드가 악화되는 경향이 있습니다. 말할 것도없이 모든 프로그래머의 악몽이다.
  • 테스트 자체를 TDD 방식으로 작성하는 것은 실제로 API, 클래스 및 메소드를 연습하고 설계가 의미가 있는지 여부를 감지하는 매우 효과적인 테스트 역할을합니다. 테스트에 대해 인터페이스를 작성하는 것이 어색하거나 어려울 경우 귀중한 초기 피드백을 얻습니다. 여전히 API를 쉽게 만들 수 있습니다. 즉, 이렇게하면 API를 조기에 게시하지 못하게됩니다.
  • TDD에 의해 시행되는 개발 패턴은 수행해야 할 구체적인 작업에 집중할 수 있도록 도와 주며 목표에 계속 도달하도록하여 불필요한 문제와 불필요한 추가 기능을 추가하여 다른 문제를 해결할 수있는 기회를 최소화합니다. 등
  • 단위 테스트의 빠른 피드백을 통해 코드를 리팩토링 할 때 대담 할 수 있으므로 코드 수명 동안 설계를 지속적으로 조정하고 발전시켜 코드 엔트로피를 효과적으로 방지 할 수 있습니다.

나는 코드를 사용하는 두 번째 장소가 필요할 때까지 / 일반화하지 않았다는 경험 법칙을 기억합니다. 단위 테스트를 사용하면 항상 코드를 사용하는 두 번째 장소, 즉 단위 테스트가 있습니다. 이 이유는 일반화하기에 충분합니까?

단위 테스트에 의해 “추가”일반화 나 이음새없이 소프트웨어가해야 할 일을 정확하게 수행하고 고객을 만족시킬 수있는 빠르고 반복 가능하며 저렴하고 결정적인 방법으로 소프트웨어를 입증 할 수 있다면 (이 포럼의 많은 사람들이 나만큼 관심이 있으리라 확신하기 때문에 어떻게하는지 알려주십시오.)

Btw “일반화”는 단일 콘크리트 클래스 대신 인터페이스 (개요 클래스) 및 다형성을 도입하는 것과 같은 것을 의미합니다. 그렇지 않은 경우 명확히하십시오.


답변

나는 당신에게 Testivus의 길 을 던질 것입니다.

시스템의 단일 부분을 테스트하기 위해 코드를 더 복잡하게 만드는 데 많은 시간과 에너지를 소비하는 경우 구조가 잘못되었거나 테스트 방법이 잘못되었을 수 있습니다.

가장 간단한 가이드는 다음과 같습니다. 테스트하는 것은 시스템의 다른 부분에서 사용되는 방식으로 코드의 공용 인터페이스입니다.

테스트가 길고 복잡해지면 공용 인터페이스를 사용하는 것이 어려울 것임을 나타냅니다.

상속을 사용하여 현재 사용하려는 단일 인스턴스 이외의 클래스에서 클래스를 사용할 수있게하려면 클래스가 사용 환경에 너무 많이 묶여있을 가능성이 큽니다. 이것이 사실 인 상황의 예를 들어 줄 수 있습니까?

그러나 단위 테스트 교리에주의하십시오. 클라이언트가 당신을 외 치게하는 문제를 감지 할 수있는 테스트를 작성하십시오 .


답변

TDD 및 단위 테스트는 단위 테스트뿐만 아니라 프로그램 전체에 유용합니다. 그 이유는 뇌에 좋기 때문입니다.

이것은 RobotLegs라는 특정 ActionScript 프레임 워크 에 대한 프레젠테이션 입니다. 그러나 처음 10 개의 슬라이드를 넘기면 뇌에 대한 좋은 부분에 도달하기 시작합니다.

TDD 및 단위 테스트는 뇌가 정보를 처리하고 기억하는 데 더 나은 방식으로 행동하도록 강요합니다. 따라서 앞의 정확한 작업은 더 나은 단위 테스트를 수행하거나 코드를 더 단위 테스트 가능하게 만드는 것입니다 … 실제로 수행하는 작업은 코드를 더 읽기 쉽게 만들어 코드를 유지 관리하기 쉽게 만드는 것입니다. 이를 통해 habbits에서 코딩 속도가 빨라지고 기능을 추가 / 제거하거나 버그를 수정하거나 일반적으로 소스 파일을 열어야 할 때 코드를 더 빨리 이해할 수 있습니다.


답변

응용 프로그램의 가장 작은 분리 가능한 장치 테스트

이것은 사실이지만, 너무 멀리 가져 가면 많은 비용이 들지 않으며 비용이 많이 들며, BDD라는 용어를 TDD가 모두 사용해야했던 것으로 홍보하는 것이이 측면이라고 믿습니다. 함께-가장 작은 isolatable 단위는 당신이 원하는 것입니다.

예를 들어, 한 번은 IP 주소를 설정하고 다른 하나는 포트 번호를 설정하기 위해 2 가지 방법이있는 네트워크 클래스를 디버깅했습니다. 당연히, 이것은 매우 간단한 방법이었고 가장 간단한 테스트를 쉽게 통과 할 것이지만, 포트 번호를 설정 한 다음 ip 주소를 설정하면 작동하지 않을 것입니다. ip setter는 포트 번호를 기본값으로 덮어 쓰고있었습니다. 그래서 당신은 올바른 행동을 보장하기 위해 클래스 전체를 테스트해야했습니다 .TDD의 개념이 누락되었다고 생각하지만 BDD가 제공합니다. 전체 애플리케이션에서 가장 현명하고 가장 작은 영역 (이 경우 네트워킹 클래스)을 테스트 할 수있을 때 각각의 작은 방법을 테스트 할 필요는 없습니다.

궁극적으로 테스트에는 마법의 총알이 없으므로 제한된 테스트 리소스를 적용 할 양과 세분성에 대해 합리적인 결정을 내려야합니다. 자동으로 스텁을 생성하는 도구 기반 접근 방식은 무딘 힘 접근 방식을 수행하지 않습니다.

따라서 TDD를 달성하기 위해 특정 방식으로 코드를 구성 할 필요는 없지만 달성하는 테스트 수준은 코드의 구조에 따라 달라집니다. 모든 논리가 밀접하게 묶여있는 모 놀리 식 GUI가있는 경우 GUI 구조를 사용하면 해당 부분을 분리하기가 더 어려워 지지만 ‘unit’이 GUI를 참조하고 모든 백엔드 DB 작업이 조롱되는 단위 테스트를 작성할 수 있습니다. 이것은 극단적 인 예이지만 여전히 자동화 된 테스트를 수행 할 수 있음을 보여줍니다.

작은 단위를보다 쉽게 ​​테스트 할 수 있도록 코드를 구성하는 부작용은 응용 프로그램을 더 잘 정의하는 데 도움이되므로 부품을보다 쉽게 ​​교체 할 수 있습니다. 또한 다른 사람의 작업을 방해하는 종속성을 혼합 한 모 놀리 식 앱과 달리, 2 명의 개발자가 주어진 시간에 동일한 구성 요소로 작업 할 가능성이 적으므로 코딩시 도움이됩니다.


답변

언어 디자인의 장단점에 대해 잘 알고 있습니다. C ++ (정적 함수 호출 메커니즘과 혼합 된 가상 함수 메커니즘)의 일부 핵심 설계 결정은 TDD를 어렵게 만듭니다. 이 언어는 실제로 쉽게 만드는 데 필요한 것을 지원하지 않습니다. 단위 테스트가 거의 불가능한 C ++을 작성하는 것은 쉽습니다.

프로 시저 (인수를 취하지 않고 void를 반환하지 않는 함수)가 아닌 유사 기능적 사고 방식의 쓰기 기능에서 TDD C ++ 코드를 사용하는 것이 더 좋았으며 가능하면 구도를 사용했습니다. 이러한 멤버 클래스를 대체하기가 어려우므로 해당 클래스를 테스트하여 신뢰할 수있는 기반을 구축 한 다음 다른 것에 추가 할 때 기본 단위가 작동한다는 것을 알고 있습니다.

핵심은 준 기능적 접근입니다. 생각해보십시오. 모든 C ++ 코드가 전역에 액세스하지 않은 무료 함수라면 단위 테스트에 스냅 될 것입니다. 🙂


답변