[unit-testing] 기존 생산 프로젝트에 단위 테스트를 성공적으로 추가 할 수 있습니까? 그렇다면 어떻게 그리고 가치가 있습니까?

프로덕션중인 기존 프로젝트에 단위 테스트를 추가 할 것을 강력히 고려하고 있습니다. TDD (face palm)의 이점을 실제로보기 전에 18 개월 전에 시작 되었으므로 이제는 많은 프로젝트가있는 다소 큰 솔루션이며 단위 테스트를 추가하기 위해 어디에서 시작 해야할지 가장 어리석은 아이디어가 아닙니다. 내가 이것을 고려하게하는 것은 때때로 오래된 버그가 다시 나타나는 것처럼 보이거나 버그가 실제로 수정되지 않고 수정 된 것으로 체크인 된다는 것입니다. 단위 테스트는 이러한 문제 발생을 줄이거 나 방지합니다.

SO에 대한 비슷한 질문을 읽음으로써 버그 추적기에서 시작하고 회귀를 막기 위해 각 버그에 대한 테스트 사례를 작성하는 것과 같은 권장 사항을 보았습니다. 그러나 나는 큰 그림을 잃어 버리고 결국 TDD를 사용하면 포함 된 기본 테스트가 누락 될까 걱정하고 있습니다.

기존 솔루션이 제대로 단위 테스트를 거치지 않고 제대로 테스트 되도록하기 위해 준수해야하는 프로세스 / 단계가 있습니까? 테스트의 품질 이 우수하고 테스트 의 사례가 아니라는 것이 테스트가없는 것보다 낫다 는 것을 어떻게 보장 할 수 있습니까 ?

그래서 나는 또한 요구하는 것이 같아요.

  • 프로덕션 환경에있는 기존 솔루션에 대한 노력의 가치가 있습니까?
  • 이 프로젝트의 테스트를 무시하고 나중에 다시 작성할 수 있도록 추가하는 것이 더 좋습니까?
  • 더 유익한 것은 무엇입니까? 몇 주 동안 테스트를 추가하거나 몇 주 동안 기능을 추가합니까?

(분명히 세 번째 요점에 대한 답변은 전적으로 관리자 또는 개발자와 대화하고 있는지 여부에 달려 있습니다)


현상금에 대한 이유

현상금을 추가하여 기존의 의심을 확인하는 것뿐만 아니라 수행해야 할 좋은 이유를 확인하는 더 넓은 범위의 답변을 시도하고 유치하려고합니다.

이 장을 나중에 장단점으로 작성하여 경영진에게 제품의 미래 개발을 TDD로 옮기는 데 시간을 투자 할 가치가 있음을 보여 주려고 노력하고 있습니다. 나는이 도전에 접근하고 편견없이 자신의 추론을 발전 시키려고합니다.



답변

이전에는 없었던 코드 기반에 단위 테스트를 도입했습니다. 내가이 작업을 수행 한 마지막 큰 프로젝트는 팀에 도착했을 때 제품 테스트가없는 상태에서 이미 생산되었습니다. 내가 2 년 후에 떠났을 때, 우리는 4500+ 정도의 테스트를 거쳐 230 000 + 프로덕션 LOC (실시간 금융 Win-Forms 응용 프로그램)가 포함 된 코드베이스에서 약 33 %의 코드 커버리지를 산출했습니다. 저음으로 들릴지 모르지만 결과적으로 코드 품질과 결함률이 크게 개선되어 사기와 수익성이 향상되었습니다.

관련 당사자의 정확한 이해와 약속이 모두있을 때 수행 할 수 있습니다.

우선, 단위 테스트는 그 자체가 기술이라는 것을 이해하는 것이 중요합니다. “기존의”표준으로 생산성이 높은 프로그래머가 되더라도 더 큰 프로젝트에서 확장되는 방식으로 단위 테스트를 작성하는 데 어려움을 겪을 수 있습니다.

또한 특히 상황에 따라 테스트가없는 기존 코드베이스에 단위 테스트를 추가하는 것도 전문 기술입니다. 귀하 또는 귀하의 팀원이 기존 코드 기반에 단위 테스트를 도입 한 경험이 없다면, Feather ‘s book을 읽는 것이 필수입니다 (선택적이거나 강력하게 권장되지 않음).

코드 단위 테스트로 전환하는 것은 코드베이스의 품질만큼이나 사람과 기술에 대한 투자입니다. 이를 이해하는 것은 사고 방식과 기대 관리 측면에서 매우 중요합니다.

귀하의 의견과 질문에 대해 :

그러나 나는 큰 그림을 잃어 버리고 결국 TDD를 사용하면 포함 된 기본 테스트가 누락 될까 걱정하고 있습니다.

짧은 대답 : 그렇습니다. 테스트를 놓치면 처음에는 그린 필드 상황에서와 똑같이 보이지 않을 수 있습니다.

더 깊은 수준의 대답은 이것입니다 : 그것은 중요하지 않습니다. 테스트없이 시작하십시오. 테스트 추가를 시작하고 진행하면서 리팩터링하십시오. 기술 수준이 향상되면 프로젝트에 추가 된 모든 새로 작성된 코드에 대한 기준을 높이십시오. 계속 개선하십시오 …

자, 여기서 줄 사이를 읽으면서 이것이 “행동을 취하지 않는 변명”으로서의 생각에서 온다는 인상을받습니다. 더 나은 사고 방식은 자기 신뢰에 집중하는 것입니다. 어떻게해야할지 아직 모를 수도 있지만, 빈칸을 채우는 방법을 알아낼 것입니다. 따라서 걱정할 이유가 없습니다.

다시, 그 기술. 선형 방식으로 하나의 “프로세스”또는 “단계별”쿡 북 접근 방식으로 제로 테스트에서 TDD- 완벽으로 이동할 수 없습니다. 과정이 될 것입니다. 점진적이고 점진적인 진전과 개선을 기대해야합니다. 마법의 약은 없습니다.

좋은 소식은 몇 개월 (그리고 몇 년)이지나면서 코드가 점차 “적절하게”잘 인수되고 테스트 된 코드가되기 시작한다는 것입니다.

부수적으로. 오래된 코드 기반에서 단위 테스트를 도입하는 데있어 주요 장애물은 응집력과 과도한 종속성이 없다는 것입니다. 따라서 가장 중요한 기술은 실제 단위 테스트 자체를 작성하지 않고 기존 종속성을 분리하고 코드를 분리하는 방법이 될 것입니다.

기존 솔루션이 제대로 단위 테스트를 거치지 않고 제대로 테스트되도록하기 위해 준수해야하는 프로세스 / 단계가 있습니까?

아직 설치하지 않은 경우 빌드 서버를 설정하고 코드 적용 범위가있는 모든 단위 테스트를 포함하여 모든 체크인에서 실행되는 연속 통합 빌드를 설정하십시오.

사람들을 훈련 시키십시오.

고객의 관점에서 진행하면서 어딘가에서 테스트를 시작하십시오 (아래 참조).

테스트중인 프로덕션 코드베이스의 양에 대한 지침으로 코드 적용 범위를 사용하십시오.

빌드 시간은 항상 빠릅니다. 빌드 시간이 느리면 단위 테스트 기술이 지연됩니다. 느린 테스트를 찾아서 개선하십시오 (제작 코드 분리 및 격리 테스트). 잘 작성하면 쉽게 수천 단위의 단위 테스트를 수행하고 10 분 이내에 빌드를 완료 할 수 있어야합니다 (~ 1 ms / 테스트는 좋지만 매우 거친 지침입니다. 반복을 사용하는 코드와 같은 예외는 거의 없습니다. ).

검사하고 적응하십시오.

테스트 품질이 좋고 테스트가 아닌 테스트가 테스트가 아닌 것보다 낫다는 것을 어떻게 확인할 수 있습니까?

당신 자신의 판단은 당신의 주요 현실의 근원이어야합니다. 스킬을 대체 할 수있는 메트릭이 없습니다.

그 경험이나 판단력이 없다면, 계약을 맺은 사람과 계약을 고려하십시오.

2 개의 대략적인 2 차 지표는 총 코드 적용 범위와 빌드 속도입니다.

프로덕션 환경에있는 기존 솔루션에 대한 노력의 가치가 있습니까?

예. 맞춤형 시스템 또는 솔루션에 소비되는 대부분의 돈은 생산 후 투입됩니다. 그리고 품질, 사람 및 기술에 대한 투자는 스타일을 벗어나서는 안됩니다.

이 프로젝트의 테스트를 무시하고 나중에 다시 작성할 수 있도록 추가하는 것이 더 좋습니까?

사람과 기술에 대한 투자뿐만 아니라 총 소유 비용과 시스템의 예상 수명 시간을 고려해야합니다.

제 개인의 대답은 대부분의 경우 “물론 예”가 될 것입니다. 왜냐하면 나는 그 점을 훨씬 더 잘 알고 있기 때문에 예외가 있다는 것을 알고 있습니다.

더 유익한 것은 무엇입니까? 몇 주 동안 테스트를 추가하거나 몇 주 동안 기능을 추가합니까?

둘 다. 기능 측면에서 발전하고있는 동안 코드베이스에 테스트를 추가해야합니다.

다시 말하지만 사람, 기술 및 코드 기반의 품질에 대한 투자이므로 시간이 필요합니다. 팀 구성원은 종속성을 깨고, 단위 테스트를 작성하고, 새로운 습관을 배우고, 훈련 및 품질 인식을 개선하고, 소프트웨어를 더 잘 디자인하는 방법 등을 배워야합니다. 테스트를 추가 할 때 팀원이 이러한 접근 방식이 성공하기 위해서는 이러한 수준의 기술을 갖추어야하므로 많은 테스트를 추가하기 위해 모든 시간을 소비하기 위해 진행을 중단하는 것만으로는 효과가 없습니다.

또한 모든 규모의 프로젝트 크기의 기존 코드베이스에 단위 테스트를 추가하는 것은 약속과 지속성이 필요한 대규모 사업입니다. 근본적인 것을 바꿀 수 없으며, 많은 학습을 기대하며 스폰서에게 비즈니스 가치 흐름을 중단하여 ROI를 기대하지 않도록 요청할 수 없습니다. 그것은 날지 않을 것이고, 솔직히 말하면 안됩니다.

셋째, 팀에 건전한 비즈니스 중심 가치를 심어 주려고합니다. 품질은 고객을 희생시키지 않으며 품질 없이는 빨리 갈 수 없습니다. 또한 고객은 변화하는 세상에 살고 있으며, 귀하의 업무는 고객이보다 쉽게 ​​적응할 수 있도록하는 것입니다. 고객 맞춤에는 품질과 비즈니스 가치 흐름이 모두 필요합니다.

당신이하고있는 일은 기술 부채를 지불하는 것입니다. 그리고 계속해서 변화하는 요구에 고객에게 서비스를 제공하면서 그렇게하고 있습니다. 점차 부채가 상환되면서 상황이 개선되며 고객에게 더 나은 서비스를 제공하고 더 많은 가치를 제공하는 것이 더 쉽습니다. 기타이 긍정적 인 추진력은 지속 가능한 페이스의 원칙에 밑줄을 긋고 개발팀, 고객 및 이해 관계자 모두에게 도덕을 유지하고 향상시킬 것이기 때문에 목표로 삼아야합니다.

희망이 도움이


답변

  • 프로덕션 환경에있는 기존 솔루션에 대한 노력의 가치가 있습니까?

예!

  • 이 프로젝트의 테스트를 무시하고 나중에 다시 작성할 수 있도록 추가하는 것이 더 좋습니까?

아니!

  • 더 유익한 것은 무엇입니까? 몇 주 동안 테스트를 추가하거나 몇 주 동안 기능을 추가합니까?

테스트 (특히 자동 테스트)를 추가 하면 향후 프로젝트를 훨씬 쉽게 유지할 수 있으며 사용자에게 어리석은 문제가 발생할 가능성이 크게 줄어 듭니다.

우선 순위 에 넣는 테스트 는 코드에 대한 공용 인터페이스 (및 각 모듈)가 생각하는 방식으로 작동하는지 여부를 확인 하는 테스트 입니다. 가능하면 코드 모듈에 포함 된 각각의 분리 된 실패 모드를 유도하십시오 (이것은 사소하지 않을 수 있으므로 실제로 실패하지 않는 방식을주의 깊게 확인하지 않도록주의해야합니다) 로그 기록이 충분한 지 확인하기 때문에 실패시 생성되는 로그 메시지 수 계산과 같은 작업을 수행합니다.

그런 다음 버그 데이터베이스에있는 현재 버그 각각을 테스트하여 정확하게 버그를 유발하고 버그가 수정되면 통과합니다. 그런 다음 그 버그를 수정하십시오! 🙂

테스트를 추가하는 데 시간이 오래 걸리지 만 코드 품질이 훨씬 높아짐에 따라 백엔드에서 여러 번 상환됩니다. 새 버전을 배송하거나 유지 보수를 수행 할 때 매우 중요합니다.


답변

개량 단위 테스트의 문제점은 여기서 의존성을 주입하거나 인터페이스를 사용하지 않았다는 사실을 깨닫게되며 얼마 지나지 않아 전체 구성 요소를 다시 작성하게됩니다. 이 작업을 수행 할 시간이 있다면 멋진 안전망을 구축 할 수 있지만 그 과정에서 미묘한 버그가 발생할 수 있습니다.

나는 처음부터 단위 테스트가 실제로 필요한 많은 프로젝트에 참여했으며, 코드가 작동하고 이미 돈을 벌고있을 때 일반적으로 정당화 할 수없는 완전한 재 작성이 부족한 쉬운 방법이 없습니다. 최근에는 결함이 발생하자마자 재생산하는 방식으로 코드를 실행하는 powershell 스크립트를 작성하고 이러한 스크립트를 추가 변경을위한 회귀 테스트 모음으로 유지했습니다. 이렇게하면 응용 프로그램에 대한 테스트를 너무 많이 변경하지 않고도 최소한 일부 테스트를 작성할 수 있지만 적절한 단위 테스트보다 종단 간 회귀 테스트와 비슷합니다.


답변

나는 대부분의 다른 사람들이 말한 것에 동의합니다. 기존 코드에 테스트를 추가하는 것이 중요합니다. 나는 그 점에 동의하지 않을 것이지만 하나의 경고를 추가하고 싶습니다.

기존 코드에 테스트를 추가하는 것은 가치가 있지만 비용이 많이 듭니다. 새로운 기능을 구축 하지 않으면 비용이 발생 합니다. 이 두 가지의 균형을 맞추는 방법은 전적으로 프로젝트에 달려 있으며 여러 변수가 있습니다.

  • 모든 코드를 테스트하는 데 얼마나 걸립니까? 일? 몇 주? 몇 달? 연령?
  • 이 코드를 누가 작성하고 있습니까? 고객 지불? 교수? 오픈 소스 프로젝트?
  • 일정은 어떻습니까? 충족해야 할 마감일이 있습니까? 마감일이 있습니까?

다시 강조하겠습니다. 테스트는 가치가 있으며 이전 코드를 테스트하기 위해 노력해야합니다. 이것은 실제로 어떻게 접근하는지에 대한 문제입니다. 모든 것을 버리고 이전 코드를 모두 테스트 할 여유가 있다면 그렇게하십시오. 그것이 현실적이지 않다면, 최소한 여기에해야 할 일이 있습니다.

  • 작성하는 모든 새 코드는 완전히 단위 테스트를 받아야합니다
  • 만지는 오래된 코드 (버그 수정, 확장 등)는 단위 테스트를 받아야합니다.

또한 이것은 전부가 아닌 제안이 아닙니다. 예를 들어 4 명으로 구성된 팀이 있고 1 ~ 2 명을 레거시 테스트 의무에 맡겨 마감일을 맞출 수 있다면 반드시 그렇게하십시오.

편집하다:

이 장을 나중에 장단점으로 작성하여 경영진에게 제품의 미래 개발을 TDD로 옮기는 데 시간을 투자 할 가치가 있음을 보여 주려고 노력하고 있습니다.

“소스 제어 사용의 장단점은 무엇입니까?” 또는 “채용하기 전에 사람들을 인터뷰 할 때의 장단점은 무엇입니까?” 또는 “호흡의 장단점은 무엇입니까?”

때로는 논쟁의 한 면만 있습니다. 복잡한 프로젝트에 대해 어떤 형태의 자동화 된 테스트가 필요합니다. 아니요, 테스트는 스스로 작성하지 않으며, 문제를 해결하는 데 약간의 시간이 더 걸립니다. 그러나 장기적으로는 테스트를 미리 작성하는 것보다 버그를 수정하는 데 더 많은 시간과 비용이 소요됩니다. 기간. 그것이 전부입니다.


답변

테스트를 추가하기 시작했을 때, UI와보고 코드에 너무 많은 로직을 가진 10 년 된 약 백만 라인 코드베이스였습니다.

우리가 한 첫 번째 작업 (연속 빌드 서버를 설정 한 후) 중 하나는 회귀 테스트를 추가하는 것이 었습니다. 이것들은 엔드-투-엔드 테스트였습니다.

  • 각 테스트 스위트는 데이터베이스를 알려진 상태로 초기화하여 시작합니다. 실제로 Subversion에 보관하는 수십 개의 회귀 데이터 세트가 있습니다 (순서 크기 때문에 코드와 별도의 저장소에 있음). 각 테스트의 FixtureSetUp은 이러한 회귀 데이터 세트 중 하나를 임시 데이터베이스에 복사 한 다음 거기에서 실행됩니다.
  • 그런 다음 테스트 픽스처 설정은 결과에 관심이있는 일부 프로세스를 실행합니다.이 단계는 선택 사항입니다. 일부 회귀 테스트는 보고서를 테스트하기 위해서만 존재합니다.
  • 그런 다음 각 테스트는 보고서를 실행하고 보고서를 .csv 파일로 출력 한 다음 해당 .csv의 내용을 저장된 스냅 샷과 비교합니다. 이 스냅 샷 .csvs는 각 회귀 데이터 세트 옆의 Subversion에 저장됩니다. 보고서 출력이 저장된 스냅 샷과 일치하지 않으면 테스트가 실패합니다.

회귀 테스트의 목적은 변경 사항이 있는지 알려주는 것입니다. 즉, 무언가를 파기하면 실패하지만 의도적으로 무언가를 변경하면 실패합니다 (이 경우 수정은 스냅 샷 파일을 업데이트하는 것임). 스냅 샷 파일이 올바른지조차 모릅니다. 시스템에 버그가있을 수 있습니다 (그런 다음 버그를 수정하면 회귀 테스트가 실패합니다).

그럼에도 불구하고 회귀 테스트는 우리에게 큰 승리였습니다. 우리 시스템의 거의 모든 것이 보고서를 가지고 있으므로 보고서 주위에 테스트 하네스를 얻는 데 몇 주를 소비함으로써 우리는 코드 기반의 상당 부분을 어느 정도 커버 할 수있었습니다. 동등한 단위 테스트를 작성하는 데 몇 개월 또는 몇 년이 걸렸습니다. (단위 테스트는 우리에게 훨씬 더 나은 적용 범위를 제공했을 것이고 훨씬 덜 취약했을 것입니다. 그러나 나는 완벽을 위해 몇 년을 기다리는 대신 지금 무언가를 갖고 싶습니다.)

그런 다음 버그를 수정하거나 개선 사항을 추가하거나 일부 코드를 이해해야 할 때 단위 테스트를 추가하기 시작했습니다. 회귀 테스트는 결코 단위 테스트의 필요성을 제거하지 않습니다. 그것들은 단지 첫 번째 수준의 안전망이므로 어느 정도의 테스트 범위를 빠르게 얻을 수 있습니다. 그런 다음 리팩토링을 시작하여 종속성을 깨뜨릴 수 있으므로 단위 테스트를 추가 할 수 있습니다. 회귀 테스트를 통해 리팩토링으로 인해 아무런 문제가 발생하지 않는다는 확신을 얻을 수 있습니다.

회귀 테스트에는 문제가 있습니다. 속도가 느리고 깨질 수있는 이유가 너무 많습니다. 그러나 우리를 위해 적어도 그들은했다 그래서 가치. 지난 5 년 동안 수많은 버그를 발견했으며 QA주기를 기다리는 대신 몇 시간 내에 버그를 발견했습니다. 우리는 여전히 원래 회귀 테스트를 가지고 있으며, 7 개의 서로 다른 연속 빌드 머신 (고속 유닛 테스트를 실행하는 머신과는 별개)에 퍼져 있으며, 우리는 여전히 6,000 개의 코드를 가지고 있기 때문에 때때로 그것들을 추가합니다. + 단위 테스트는 다루지 않습니다.


답변

그만한 가치가 있습니다. 앱에 복잡한 교차 유효성 검사 규칙이 있으며 최근 비즈니스 규칙을 크게 변경해야했습니다. 결국 사용자가 저장하지 못하게하는 충돌이 발생했습니다. 나는 applcation에서 그것을 분류하는 데 영원히 걸릴 것이라고 깨달았습니다 (문제가 발생한 지점까지 도달하는 데 몇 분이 걸립니다). 자동화 된 단위 테스트를 도입하고 프레임 워크를 설치하고 싶었지만, 몇 가지 더미 테스트 외에는 아무런 작업도 수행하지 않았습니다. 새로운 비즈니스 규칙에 따라 테스트를 시작했습니다. 테스트를 통해 충돌을 일으킨 조건을 신속하게 파악하고 규칙을 명확하게 파악할 수있었습니다.

추가하거나 수정하는 기능을 다루는 테스트를 작성하면 즉각적인 이점이 있습니다. 다시 쓰기를 기다리는 경우 자동 테스트가 없을 수 있습니다.

이미 작동하는 기존 항목에 대한 테스트를 작성하는 데 많은 시간을 소비해서는 안됩니다. 대부분의 경우 기존 코드에 대한 사양이 없으므로 테스트하려는 주요 사항은 리버스 엔지니어링 기능입니다. 반면에 무언가를 수정하려는 경우 해당 기능을 테스트로 다루어야 변경 사항이 올바르게 적용되었음을 알 수 있습니다. 물론 새로운 기능의 경우 실패한 테스트를 작성한 다음 누락 된 기능을 구현하십시오.


답변

음성을 추가하고 예라고 말하겠습니다. 항상 유용합니다!

그러나 블랙 박스와 화이트 박스, 그리고 유닛과 기능의 차이점을 명심해야합니다. 정의가 다양하기 때문에 다음과 같은 의미를 갖습니다.

  • 블랙 박스 = 구현에 대한 특별한 지식없이 작성된 테스트로, 일반적으로 순진한 사용자가 예상 한대로 일이 발생하는지 확인하기 위해 엣지 케이스를 탐색합니다.
  • 화이트 박스는 기록 된 테스트 = 종종 잘 알려진 장애 지점을 행사하려고 구현, 지식.
  • 단위 테스트 = 개별 단위 (기능, 분리 가능한 모듈 등)의 테스트. 예를 들어, 배열 클래스가 예상대로 작동하고 문자열 비교 함수가 광범위한 입력에 대해 예상 된 결과를 리턴하는지 확인하십시오.
  • 기능 테스트 = 한 번에 전체 시스템을 테스트합니다. 이 테스트는 한 번에 시스템의 큰 덩어리를 시험합니다. 예를 들어 : 초기화, 연결 열기, 실제 작업 수행, 종료, 종료. 나는 이것들과 단위 테스트가 다른 목적을 제공하기 때문에 구별하기를 원합니다.

게임 후반에 배송 제품에 테스트를 추가했을 때 화이트 박스기능 테스트 에서 가장 많은 비용을 지불했습니다 . 특히 취약한 코드 부분이 있으면 문제를 해결하기 위해 화이트 박스 테스트를 작성하여 같은 방식으로 두 번 깨지지 않도록하십시오. 마찬가지로 전체 시스템 기능 테스트는 가장 일반적인 10 가지 사용 사례를 위반하지 않도록하는 유용한 온 전성 검사입니다.

작은 단위의 블랙 박스 및 단위 테스트도 유용하지만 시간이 제한되어 있으면 조기에 추가하는 것이 좋습니다. 배송 할 때 일반적으로 이러한 테스트에서 발견 된 대부분의 엣지 사례와 문제를 발견했습니다.

다른 사람들과 마찬가지로 TDD에 대해 가장 중요한 두 가지 사항을 상기시켜 드리겠습니다.

  1. 테스트 작성은 지속적인 작업입니다. 절대 멈추지 않습니다. 새 코드를 작성하거나 기존 코드를 수정할 때마다 새 테스트를 추가해야합니다.
  2. 테스트 스위트는 절대 완벽하지 않습니다! 테스트를 받았다는 사실로 인해 잘못된 보안 감각이 생길 수 있습니다. 테스트 스위트를 통과했다고해서 그것이 올바르게 작동하거나 미묘한 성능 회귀 등을 도입하지 않았다는 의미는 아닙니다.