기존 코드 작성 테스트


68

하나가 비교적 큰 프로그램 (예 : C #에서 900k SLOC)을 가지고 있다고 가정하십시오. 전체 코드 기반은 더 이상 회사와 함께 있지 않은 한 명의 선임 개발자가 작성했습니다. 모든 코드는있는 그대로 테스트 할 수 있으며 IoC는 전체적으로 사용됩니다. 단, 이상한 이유로 단위 테스트를 작성하지 않았습니다. 이제 귀사는 코드를 분기하고 변경 사항이 핵심 기능을 위반하는시기를 감지하기 위해 추가 된 단위 테스트를 원합니다.

  • 테스트를 추가하는 것이 좋습니다?
  • 그렇다면 어떻게 이런 식으로 시작합니까?

편집하다

OK, 그래서 나는 반대 결론에 대한 좋은 주장을하는 대답을 기대하지 않았습니다. 어쨌든 문제가 발생했을 수 있습니다. 나는 "중복 문제"도 읽었으며 일반적인 합의는 "쓰기 시험이 좋다"는 것입니다 ... 그렇지만이 특별한 경우에는 도움이되지 않습니다.

레거시 시스템에 대한 글쓰기 테스트를 고려할 때 혼자 있다고 생각하지 않습니다. 나는 시간이 얼마나 걸리고 새로운 테스트가 몇 번이나 문제를 포착하는지 (그리고 그들이 몇 번이나하지 않는지)에 대한 통계를 유지할 것입니다. 나는 돌아와서 일년 내내 지금부터 내 결과로 업데이트 할 것입니다.

결론

따라서 기본 코드와 같이 기존 코드에 단위 테스트를 추가하는 것은 기본적으로 불가능합니다. 일단 코드가 작동하면 테스트를 적색 / 녹색으로 밝힐 수 없으며, 테스트를 위해 어떤 동작이 중요한지 명확하지 않으며, 어디서 시작해야하는지 확실하지 않으며 완료되면 확실하지 않습니다. 이 질문을하는 것조차도 처음에는 필기 시험의 요점을 놓칩니다. 대부분의 경우 의도 된 기능을 해독하고 단위 테스트를 소급하여 추가하는 것보다 TDD를 사용하여 코드를 다시 작성하는 것이 실제로 더 쉽다는 것을 알았습니다. 문제를 해결하거나 새로운 기능을 추가 할 때 그것은 다른 이야기이며, 지금은 단위 테스트를 추가 할 때라고 생각합니다 (아래에서 지적했듯이). 결국 대부분의 코드는 종종 예상보다 빨리 재 작성됩니다.


10
테스트를 추가해도 기존 코드가 중단되지 않습니다.
Dan Pichelman

30
@DanPichelman 당신은 schroedinbug를 경험 한 적이 없습니다 - "누군가가 소스를 읽거나 특별한 방식으로 프로그램을 사용할 때까지 프로그램이 즉시 작동하지 않아야한다는 것을 알기 전까지는 나타나지 않는 프로그램의 디자인 또는 구현 버그입니다. "고정 될 때까지 모든 사람의 작업을 중단합니다."

8
@MichaelT 이제 언급했듯이, 나는 그것들 중 하나 나 둘을 본 것 같습니다. 내 의견은 "테스트를 추가해도 일반적으로 기존 코드가 중단되지 않습니다 "라고 읽었어야합니다 . 감사합니다
Dan Pichelman

3
리팩토링하거나 변경하려는 대상에 대해서만 테스트를 작성하십시오.
Steven Evers

3
"레거시 코드로 효과적으로 작업하기"( amazon.com/Working-Effectively-Legacy-Michael-Feathers/dp/…) 책을 확인하십시오. Michael Feathers는 레거시 코드를 수정하기 전에 테스트를 작성하도록 제안합니다.
Skarab

답변:


68

테스트는 좋은 생각이지만, 원래 코더 는 코드가 어떻게 작동해야하는지, 어떻게 깨질 지에 대한 지식을 포착하기 위해 응용 프로그램을 빌드 할 때 테스트 를 빌드하는 것이 목적이었습니다 .

이 접근 방식을 사용하면 중단 가능성이 가장 적은 테스트를 작성하고 응용 프로그램을 빌드하는 동안 발견 된 대부분의 경우를 놓칠 가능성이 높습니다.

문제는 대부분의 가치가 그러한 'gotchas'와 덜 명백한 상황에서 나올 것이라는 점입니다. 이러한 테스트가 없으면 테스트 스위트는 거의 모든 효과를 잃게됩니다. 또한 회귀 증거가 크게 증가하지 않기 때문에 회사는 응용 프로그램에 대해 잘못된 보안 감각을 갖게됩니다.

일반적으로이 유형의 코드베이스를 처리하는 방법은 레거시 코드베이스가 완전히 리팩터링 될 때까지 새 코드 및 이전 코드의 리팩토링에 대한 테스트를 작성하는 것입니다.

참조하십시오 .


11
그러나 TDD가 없어도 리팩토링시 단위 테스트가 유용합니다.
pdr

1
코드가 계속 잘 작동한다면 문제가되지 않지만 최선의 방법은 동작에 의존하는 것을 작성할 때마다 레거시 코드에 대한 인터페이스를 테스트하는 것입니다.
deworde

1
이것이 테스트 범위 를 측정하는 이유 입니다. 특정 섹션에 대한 테스트가 모든 if 및 else 및 모든 경우를 다루지 않는 경우 해당 섹션을 안전하게 리팩터링 할 수 없습니다. 적용 범위는 모든 라인에 도달했는지 알려주므로 리팩토링하기 전에 가능한 한 많은 적용 범위를 늘리는 것이 목표입니다.
Rudolf Olah

3
TDD의 주요 단점은 코드 기반에 익숙하지 않은 개발자에게 스위트를 실행할 수 있지만 이는 잘못된 보안 감각입니다. 출력은 일반 영어로 된 코드 의 의도 이므로 BDD는 이와 관련하여 훨씬 좋습니다 .
Robbie Dee

3
100 % 코드 적용 범위가 코드가 100 % 올바르게 작동한다는 의미는 아닙니다. 메소드에 대한 모든 코드 줄을 테스트 할 수 있지만 value1과 함께 작동한다고해서 value2와 함께 작동한다고 보장되는 것은 아닙니다.
ryanzec

35

예, 테스트를 추가하는 것이 좋습니다.

당신은 그것이 잘 문서화되어 있다고 말하며, 그것은 당신을 좋은 위치에 놓는다. 중요하거나 자주 변경 될 수있는 시스템 부분에 중점을 두어 해당 문서를 가이드로 사용하여 테스트를 작성하십시오.

처음에는 적은 양의 테스트에 비해 코드베이스의 크기가 엄청나게 클 것 같지만 빅 접근 방식은 없으며 최상의 접근 방식에 대해 고민하는 것보다 어딘가 에서 시작하는 것이 더 중요합니다.

Michael Feathers의 저서, 레거시 코드로 효과적으로 작업하기를 추천 합니다.


10
+1. 문서를 기반으로 테스트를 작성하면 작업 코드와 문서간에 불일치가 있음을 발견 할 수 있습니다.
Carl Manaster

1
테스트를 추가해야하는 또 다른 이유 : 버그가 발견되면 향후 회귀 테스트를 위해 테스트 사례를 쉽게 추가 할 수 있습니다.

이 전략은 기본적으로 레거시 코드에 대한 장의 (무료) edX 온라인 과정 CS169.2x에 요약 된 전략입니다. 교사가 말한 바와 같이 : 책 9 장의 "특성 시험을 통한 진실을 확립하기": beta.saasbook.info/table-of-contents
FGM

21

모든 단위 테스트에 동일한 이점이있는 것은 아닙니다. 단위 테스트의 이점은 실패 할 때 발생합니다. 실패 할 가능성이 적을수록 유익하지 않습니다. 새로운 코드 나 최근에 변경된 코드는 프로덕션 환경에서 잘 테스트 된 드물게 변경되는 코드보다 버그를 포함 할 가능성이 높습니다. 따라서 새로운 코드 나 최근에 변경된 코드에 대한 단위 테스트가 더 유리할 것입니다.

모든 단위 테스트에 동일한 비용이있는 것은 아닙니다. 오래 전에 다른 사람이 디자인 한 복잡한 코드보다 오늘날 직접 디자인 한 간단한 코드를 단위 테스트하는 것이 훨씬 쉽습니다. 또한 개발 중에 테스트하면 일반적으로 개발 시간이 절약됩니다. 레거시 코드에서는 더 이상 비용을 절감 할 수 없습니다.

이상적인 세계에서는 레거시 코드를 단위 테스트하는 데 항상 필요한 시간이 있지만 실제 세계에서는 레거시 코드에 단위 테스트를 추가하는 비용이 이점을 능가하는 이유가 있습니다. 요점은 그 지점을 식별하는 것입니다. 버전 관리는 가장 최근에 변경되고 가장 자주 변경된 코드를 표시하여 도움을 줄 수 있으며 단위 테스트를 통해 시작할 수 있습니다. 또한 앞으로 변경 작업을 수행 할 때 이러한 변경 사항과 밀접하게 관련된 코드를 단위 테스트로 적용하십시오.

이 방법을 따르면 결국 가장 유리한 영역에서 꽤 좋은 범위를 갖게됩니다. 수익 창출 활동을 재개하기 전에 단위 테스트를받는 데 수 개월을 소비하는 경우 바람직한 소프트웨어 유지 관리 결정이 될 수 있지만, 이는 비판적인 비즈니스 결정입니다.


3
코드가 거의 실패하지 않으면 실제로는 결코 발생할 수없는 비전 문제를 찾는 데 많은 시간과 노력이 소모 될 수 있습니다. 반면에 코드에 버그가 있고 오류가 발생하기 쉬운 곳이라면 어디에서나 테스트를 시작하고 즉시 문제를 찾을 수 있습니다.
Robbie Dee

8

테스트를 추가하는 것이 좋습니다?

물론 코드가 깨끗하고 잘 작동하며 현대 기술을 사용하고 단위 테스트가 없다고 믿기가 조금 어렵습니다. 그들이 별도의 솔루션에 앉아 있지 않습니까?

어쨌든 코드를 확장 / 유지하려는 경우 실제 단위 테스트는 해당 프로세스에 매우 중요합니다.

그렇다면 어떻게 이런 식으로 시작합니까?

한 번에 한 단계 씩. 단위 테스트에 익숙하지 않다면 조금 배우십시오. 개념에 익숙해지면 코드의 작은 섹션을 하나 선택하여 테스트를 작성하십시오. 그리고 다음과 다음. 코드 적용 범위를 사용하면 놓친 지점을 찾을 수 있습니다.

위험하거나 위험하거나 중요하지 않은 것을 먼저 테스트하는 것이 가장 좋지만, 특히 팀원이 코드베이스 및 / 또는 단위에 익숙하지 않은 경우 먼저 그루브에 들어가기 위해 직접 테스트하는 것이 더 효과적 일 수 있습니다. 테스트.


7
"그들이 별도의 솔루션에 앉아 있지 않습니까?" 좋은 질문입니다. OP가 간과하지 않기를 바랍니다.
Dan Pichelman

불행히도, TDD가 관심을 끌고있는 것처럼 수년 전에 응용 프로그램이 시작 되었기 때문에 어느 시점에서 테스트를 수행하려고했지만 어떤 이유로 프로젝트가 시작되면 결코 도달하지 못했습니다.
Paul

2
그들은 그럴 가치가없는 여분의 시간이 걸리기 때문에 아마 그것을 얻지 못했을 것입니다. 혼자서 작업하는 훌륭한 개발자는 자동화 된 테스트 없이도 비교적 큰 크기의 깨끗하고 명확하며 체계적이며 작동하는 응용 프로그램을 만들 수 있으며 일반적으로 테스트와 마찬가지로 더 빠르고 버그없는 작업을 수행 할 수 있습니다. 그것은 모두 자신의 머리에 있기 때문에 여러 개발자가 버그를 만들 때와 비교할 때 버그 또는 조직 문제가 발생할 가능성이 상당히 낮습니다.
Ben Lee

3

예, 테스트를받는 것이 좋습니다. 기존 코드베이스 작업을 의도 한대로 문서화하고 예기치 않은 동작을 포착하는 데 도움이됩니다. 테스트가 처음에 실패하더라도 테스트를 통과 한 다음 나중에 코드를 리 팩터하여 의도 한대로 통과하고 작동하도록합니다.

더 작은 클래스 (종속성이없고 비교적 간단한 클래스)에 대한 테스트를 작성하고 더 큰 클래스 (종속성이 있고 더 복잡한 클래스)로 넘어갑니다. 시간이 오래 걸리지 만 인내심과 끈기가있어서 코드베이스를 최대한 많이 커버 할 수 있습니다.


제대로 작동하는 프로그램에 실패한 테스트를 추가 하시겠습니까 (OP는 말합니다)?
MarkJ

그렇습니다. 무언가가 의도 한대로 작동하지 않으며 추가 검토가 필요하다는 것을 보여주기 때문입니다. 이것은 토론을 촉구하고 오해 나 이전에 알려지지 않은 결함을 희망적으로 시정합니다.
Bernard

@Bernard-또는 테스트에서 코드의 기능에 대한 오해가 노출 될 수 있습니다. 사실 이후 작성된 테스트는 원래 의도를 올바르게 캡슐화하지 않을 위험이 있습니다.
Dan Pichelman

@ DanPichelman : 동의하지만 테스트를 작성하는 것을 방해해서는 안됩니다.
Bernard

그렇지 않으면 코드가 방어 적으로 작성되지 않았 음을 나타냅니다.
Robbie Dee

3

좋아, 나는 반대 의견을 제시 할 것이다 ....

기존의 작업 시스템에 테스트를 추가하면 해당 시스템이 변경됩니다. 즉, 시스템은 처음부터 조롱으로 작성됩니다. 의심의 여지가 있지만, 모의 인터페이스를 삽입 할 수있는 쉽게 정의 할 수있는 경계를 가진 모든 구성 요소를 잘 분리 할 수는 없습니다. 그러나 그렇지 않다면, 당신은 상당히 중요한 (상대적으로 말하면) 변경 사항을 적용하여 문제를 해결할 수 있습니다. 가장 좋은 경우에는 이러한 테스트를 작성하는 데 많은 시간을 소비 할 것이며, 자세한 설계 문서, 영향 분석 문서 또는 솔루션 구성 문서를 작성하는 데 더 나은 시간을 소비 할 수 있습니다. 결국, 그것은 당신의 상사가 단위 테스트 이상의 일을하기를 원하는 일입니다. 그렇지 않습니까?

어쨌든, 나는 단위 테스트를 추가하지 않을 것입니다.

나는 물건을 바꾸지 않고 합리적인 범위를 제공 할 수있는 외부의 자동화 된 테스트 도구에 집중할 것입니다. 그런 다음 수정하려고 할 때 코드베이스 내에 단위 테스트를 추가 할 수 있습니다.


2

나는 종종이 상황에 부딪 쳤고, 테스트 범위를 적절하지 않거나 제공하지 않고 큰 코드베이스를 상속했으며 이제 기능 추가, 버그 수정 등을 담당합니다.

내 조언은 추가 한 내용을 확인하고 테스트하고 현재 코드에서 버그를 수정하거나 사용 사례를 변경하는 경우 테스트를 작성하는 것입니다. 무언가를 만져야한다면 그 시점에서 테스트를 작성하십시오.

이것이 고장 나면 기존 코드가 단위 테스트를 위해 잘 구성되지 않은 때이므로 리팩토링에 많은 시간을 소비하여 사소한 변경에 대한 테스트를 추가 할 수 있습니다.

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