당신은 유용한 테스트만 작성해야 합니다

나의 소프트웨어 경력에서 나는 테스트 코드에 대해 광범위한 태도와 관점을 가지고 있다.두 극단은'테스트는 작성할 가치가 없다. 왜냐하면 어떤 것들은 너무 복잡하기 때문'이나'서명된 모든 코드는 테스트를 수반해야 한다'는 것이다.이 두 가지 확연히 다른 관점 중에서 후자는 항상 이런 극단적인 형식으로 나타나는 것은 아니지만 더욱 보편적이다.여기서 나는 왜 우리가 항상 코드를 테스트해야 하는 세 가지 상황을 토론할 것이다. 독립된 코드 부분은 뚜렷한 정확성을 가질 수 있다.재구성할 때 군더더기, 심각한 결합 테스트, 그리고 업무 핵심 코드의 불변성을 만날 수 있다.반대로 나는 어떤 테스트를 실시하기 전에 우리는 진정으로 테스트가 필요한 곳을 꼼꼼히 고려해야 한다고 생각한다.

명백한 #


만약 당신이 강좌에 참가한 적이 있거나 수업을 본 적이 있거나 단원 테스트에 관한 책을 읽은 적이 있다면, 이 예는 다음과 같은 내용에 따라 테스트 코드를 본 적이 있을 것이다.
func Sum(x int, y int) int { return x + y;}
의심할 여지없이, 다음에 테스트를 작성하는 방법을 보여 드리겠습니다. 이 테스트는 각종 입력을 검사하여 Sum 함수가 당신이 생각할 수 있는 모든 상황에 정확한 결과를 생성할 수 있도록 합니다.
그러나 이 강좌들은 함수가 먼저 테스트가 필요한지 고려하지 않았다.위의 예를 보면, 너는 그것이 주장하는 것처럼 그렇게 하지 못할 가능성이 있다고 생각하니?좀 더 쉽게 표현할 수 있을까요?너는 고개를 돌리기가 매우 어렵지 않니?이 세 가지 문제의 답안은 모두 부정적이다. 이것은 코드가 어떻게 직관적으로 일목요연하게 정확할 수 있는지를 설명한다. 대량의 증명이나 테스트가 필요하지 않다.토니 호르 재즈는 매우 영향력 있는 컴퓨터 과학자로 악명이 높다.

“There are two ways of constructing a piece of software: One is to make it so simple that there are obviously no errors, and the other is to make it so complicated that there are no obvious errors.”


이 수사는 우리가 예시에서 제기한 문제에 완전히 부합된다.실천에서 우리는'매우 복잡해서 뚜렷한 오류가 없다'는 상황에서만 진정으로 테스트가 필요하다는 것을 알 수 있다.그리고 이 테스트들은 뚜렷하지 않은 오류가 존재하지 않는다는 것을 증명함으로써 그 가치를 증명할 것이다.그렇다면 간단하고 명백한 정확한 코드에 대해 테스트를 추가해야 합니까?반대로 테스트를 추가하기 전에 "이 코드가 뚜렷하게 정확합니까? 아니면 제가 그것을 뚜렷하게 정확하게 변경할 수 있습니까?"라고 물어봐야 합니다.만약 이 문제의 답이 긍정적이라면, 무엇이 명백한지 테스트할 필요가 없다.

결합된 #


시스템에 대해 어떤 수준의 테스트 (단위/서비스/사용자 인터페이스/통합/엔드 투 엔드 또는 기타 이름) 를 작성할지 결정할 때 바로 생각됩니다 'Testing Pyramid'.만약 이전에 이 생각을 본 적이 없다면, 이것은 우리가 하나의'단원'단계에서 대부분의 테스트를 진행할 것을 건의합니다. 이 단원 단계의 테스트는 신속하게 실행할 수 있을 뿐만 아니라, 신속하고, 저렴하며, 효율적으로 높은 등급의 코드 커버율을 제공할 수 있습니다.그리고 우리는 더 드문드문 방식으로 더 높은 수준의 테스트를 제공해야 한다. 이러한 테스트에 의존하여 모든 것이 연결되고 정확하게 통신되었음을 효과적으로 증명해야 한다. 논리의 각 부분을 검사하는 것이 아니라.

이 시스템은 간단명료해서 처음에는 완전히 합리적이었다.이것도 보편적으로 받아들이는 방법이다.그러나 코드의 처리 가능성이나 재구성 능력이 어떤 테스트를 작성하고 어떻게 테스트를 작성하는지에 대한 주요한 고려 요인임을 인정하지 않았다.계속 작업 중인 모든 시스템은 단원이나 고립된 코드 세션이 시간의 추이에 따라 나타나고 사라지며 완전히 다른 형식을 취하는 것을 볼 수 있다.이것은 업무, 생활 소프트웨어의 자연적인 발전과 변천이다.이 점을 강조하기 위해서 나는 "당신은 기존의 단원 테스트가 전혀 관련되지 않거나 쓸데없는 것을 발견하기 위해 코드 라이브러리의 일부분을 재구성한 적이 있습니까?"라고 물었다.만약 그렇다면, 이것은 초기 테스트와 코드의 레이아웃과 구조가 과도하게 결합되었음을 나타낸다.테스트는 방금 작성한 초기 코드와 일치하는 더 많은 코드일 뿐입니다. (또는 TDD를 실행하면 작성할 코드와 일치하는 더 많은 코드일 뿐입니다.)
구조가 신속하고 끊임없이 변화하는 코드 분야에서 더욱 높은 단계의 테스트는 더욱 높은 단계의 유지보수성과 안정성을 제공한다. 왜냐하면 시스템의 더 높은 단계의 작업은 통상적으로 더욱 안정적이기 때문이다.이 테스트들은 완전히 중복될 수 없다.

그러나 이것은 흥미로운 난제를 제기했다. 우리는 미래 코드의 구조나 방법이 변화할 수 있다는 것을 어떻게 알 수 있습니까?만약 우리가 이 분야들을 앞당겨 발견할 수 있다면, 우리가 새로 발견한 선견지명은 단지 우리가 처음으로 더 좋은 형식으로 그것들을 썼다는 것을 의미할 뿐이다.그러나 유감스럽게도 우리는 여전히 어둠 속에서 모색하고 있다. 현재의 지식 상황을 고려하여 코드를 조직하는 것은 일종의'최선을 다하는'방법이다.
그러나 우리는 시스템에 대해 더 많은 것을 알게 되었다. 그것이 존재하는 시간이 길수록, 또는 우리가 일하는 시간이 길수록.이것은 우리로 하여금 어떤 테스트가 현명한 결정을 내릴 수 있게 한다.젊은 시스템이나 고도의 불확실성을 가진 시스템은 고급 블랙박스식 테스트에서 가장 큰 이익을 얻는다. 왜냐하면 이런 시스템들은 시간의 추이에 따라 구조 변화가 발생할 가능성이 가장 높기 때문이다.이 테스트들은 불필요한 위험이 발생할 가능성이 그다지 높지 않다.그에 비해 더 오래되고 안정적이며 이해하기 쉬운 시스템은 단원 테스트가 제공하는 유연성과 효율적인 커버에서 더 많은 이익을 얻는다.
전체적으로 말하자면 시스템의 나이, 안정성과 불확실성은 우리가 작성한 테스트를 지탱해야 한다. 테스트 피라미드는 너무 간단한 세계시도를 제공하지만 고려해야 할 유용한 도구이다.그러나 우리는 코드와 시간에 따라 변화하는 이해를 통해 이 점을 보충하고 "이 테스트가 얼마나 지속됩니까?"라고 물어봐야 한다.아니면 "이것들은 X개월/년 동안 중요하지 않을 수 있습니까?"

정지의 #


내가 종사하는 많은 대형 소프트웨어 프로젝트에서 상당히 재미있는 풍자가 생겼다. 가장 중요하고 업무의 관건적인 코드 블록은 종종 테스트가 가장 충분하지 않다.그들의 생산은 어떤 작은 변화도 재난을 초래할 수 있는 명확한 정의가 부족한 것 같다.그러나 그들은 여전히 이렇다.

몇 년 전에 나는 NHS 프로젝트에 참여했다.간단하게 말하면 이것은 매우 복잡한 기본 시스템으로 가격을 병원 치료와 연결시키고 이 가격에 따라 보고서를 작성하는 것을 책임진다.이 보고 시스템은 수천 차례의 테스트를 통해 가능한 모든 출력을 꼼꼼히 검사하여 각양각색의 입력을 얻었다.그럼에도 불구하고 이 프로젝트의 핵심인 가격 책정 시스템은 테스트가 거의 부족하다.테스트 보고를 할 때, 그것은 부작용으로 진정한 테스트를 진행했을 뿐이다.이 코드는 처리하기 매우 어렵고 테스트에 적합하지 않기 때문에 여태껏 없었다.당시에 나는 그것이 시스템에서 이렇게 중요한 일부분일 때 어떻게 이럴 수 있는지 이해하지 못했다.
나는 나중에 이유가 매우 간단하다는 것을 깨달았다.원시 코드는 개념적 증명으로 작성된 것이다.그것은 성공했기 때문에 생산 코드가 되었다.미지의 회귀를 초래할 수 있다는 우려 때문에 추적과 복구가 어려울 뿐만 아니라 비용도 비싸기 때문에 아무도 변화를 원하지 않는다.이와 유사하게 가격 결정 과정은 고정된 논리이다. 그것은 시간의 추이에 따라 바뀌지 않고, 새로운 수요가 없으면 그의 작업 방식을 바꾸며, 내부에서 어떻게 일을 하는지 진정으로 알아야 할 사람은 없다. 단지 그것이 해냈을 뿐이다.이렇게 중요한 코드에 대해서도 어떠한 테스트도 하지 않는 비용은 코드를 변경하여 테스트할 수 있도록 하는 위험과 테스트 작업을 크게 초과한다.
여기서 중요한 업무 시스템을 테스트하지 말라고 제창하는 건가요?아니오, 전혀요!그러나 중요한 것은 우리가 완벽한 세계에서 사는 것이 아니라는 것을 깨닫는 것이다.핵심 부품 테스트가 부족한 시스템은 내가 인정하고 싶은 것보다 훨씬 보편적이다.그러나 이것은 내가 상상한 재난이 아니다.만약 코드가 매우 복잡하지만, 그것은 일을 할 수 있고, 변경을 하지 않는다면, 만약 테스트가 좋지 않다면, 이것은 관계가 있습니까?그러나 변경을 진행할 때 테스트를 추가하는 것은 여전히 신중하지만, 우리는 여전히 이런 질문을 할 수 있다. "이 코드를 테스트하는 것이 테스트를 추가하는 어려움보다 좋은가?"이것은 위험한 문제로 답은 거의 완전히'네, 테스트 추가'입니다.그러나 때때로 이것은 고려할 만한 일이다.

요약#


프로젝트의 전체 생명 주기에 지속적인 가치를 제공하기 위해 디자인이 좋은 테스트 세트를 만드는 것은 어려운 작업이다.테스트 피라미드 방법의 창도자는 문제를 지나치게 간소화시켰다.의도는 좋지만 끊임없이 변화하는 소프트웨어 개발 세계의 실용성에 뿌리를 두지 않았다. 시간의 추이에 따라 코드의 변화는 테스트를 군더더기 또는 불필요하게 하기 쉽고 때로는 이런 테스트가 재구성의 장애가 될 수도 있다.코드는'뚜렷한'성질을 가지는데 이것 또한 테스트가 정확한 행위로 증명되는 수요를 감소시켰다.이와 같이 이미 정확하고 변하지 않거나 거의 바뀌지 않은 기존 코드를 고려할 때 간단한 원가 효율 분석을 고려해야 한다.모든 테스트가 작성할 만한 가치가 있는 것은 아니다.매사에 테스트가 필요한 것은 아니다. 이것은 매우 좋다.

좋은 웹페이지 즐겨찾기