[유닛 테스트] 2. Agile과 TDD

rin·2020년 4월 8일
2

유닛 테스트

목록 보기
2/4
post-thumbnail

Agile 방벙론, TDD에 대한 개념과 TDD를 사용하는 이유 등에 대해서 정리해본다.
BDD에 대한 간략한 설명도 덧붙이도록 한다.

Agile Software Development

ref. wiki-애자일 소프트웨어 개발
Agile : 기민한, 좋은 것을 빠르고 낭비없게 만드는 것

개발 배경

  1. ~90년대 후반 : 장기간에 걸쳐 많은 인력과 비용을 투입하여 진행하는 다른 공학의 프로세스와 비슷한 맥락에서 진행
  2. But 소프트웨어는 유동적, 개방적, 요구사항의 변경에 따른 작업량을 예측하기 힘듦
  3. 이에따라 고전적인 소프트웨어 공학이나 관리 기법만으로 대처할 수 없게 되었다.
  4. 즉, 소프트웨어 개발 프로세스는 다른 공학적인 프로세스와 큰 차이가 있음을 인지 (👈핵심!)
  5. 기술적인 해결책의 하나인 객체지향은 소프트웨어 개발 문제를 적절히 대처해주었고, 이에 적합한 개발 프로세스인 애자일 방법론이 만들어졌다. (따라서 애자일 개발 프로세스의 상단수는 객체지향 기술을 기반으로 한다.)

전통적 개발 프로세스 vs. 애자일 개발 프로세스

전통적 개발 프로세스

  • 폭포수 모델과 계획 기반 개발
    • 일련의 차례와 탄탄한 계획을 기반으로 하여 개발을 진행
    • 계획대로 진행되지 않는 경우, 큰 부작용이 발생할 수 있다.
  • 정형적 프로세스 제어 모델
    • 공업에서 사용
    • 동일한 입력에 대해서 동일한 결과가 기대 될 경우에 적합

애자일 개발 프로세스

  • 경험적 프로세스 제어 모델
    • 항상 불확실성을 수반하고 포용하고 있다.

그래서?

애자일 방법론은 소트프웨어 개발 방법에 있어서 아무런 계획이 없는 개발 방법과 계획이 지나치게 많은 개발 방법들 사이에서 타협점을 찾고자 하는 방법론이다.
🤔계획이 없는 방법론 ... 앞으로의 일을 예측하기 힘들고, 효율적이지 못하다는 점에서 취약점을 가지고 있다
🤔그럼 계획이 엄청난 방법론은 ... 형식적인 절차를 따르는데 필요한 시간과 비용 증가, 전체적인 개발 흐름 자체를 느리게 한다.

애자일 방법론은 문서를 통한 개발이 아니라, 실질적인 코딩을 통한 방법론이라고 할 수 있다.

  • 계획을 통해서 주도해 나갔던 과거의 방법론
  • 이와 다르게 앞을 예측하며 개발하지 않고
  • 일정 주기를 가지고 끊임없이 프로토 타입을 생성
  • 추가, 제거되는 요구 사항에 대해 능동적으로 대처하고 수정
  • 이런 단계를 반복하여 하나의 커다란 소프트웨어를 개발에 나가는 adaptive style

애자일 개발 프로세스은 특정 개발 방법론을 가리키는 말은 아니고 "애자일" 개발을 가능하게 해주는 다양한 방법론 전체를 일컫는 말이다.

애자일 선언문

우리는 소프트웨어를 개발하고, 또 다른 사람의 개발을 도와주면서 소프트웨어 개발의 더 나은 방법들을 찾아가고 있다.
이 작업을 통해 우리는 다음을 가치있게 여기게 되었다 :
✔️공정과 도구보다 개인과 상호작용
✔️포괄적인 문서보다 작동하는 소프트웨어
✔️계약 협상보다 고객과의 협력
✔️계약을 따르기보다 변화에 대응하기
이 말은, 왼쪽에 있는 것들도 가치가 있지만, 우리는 오른쪽에 있는 것들에 더 높은 가치를 둔다는 것이다.

💁 애자일의 핵심 : 협력과 피드백

왜 우리는 애자일을 써야 하는가

애자일 방법론은 개발 주기(=스프린트)를 통해 프로젝트의 방향과 목표를 가늠하도록 도와준다.
단축된 일의 반복과 제품 기능 개발에 중점을 두기 때문에 애자일 방법론은 반복적이고 증가적이라고 표현된다.
폭포수 모델에서 개발자들은 단 한 번, 프로젝트의 모든 측면을 검토하는 것과 달리 일정한 주기를 통해 지속적으로 모든 측면을 재검토할 수 있다.
특정 스프린트마다 프로젝트를 재검토하며 처음과 또 다른 방향으로 전환할 기회를 주어준다.

코멘트

스크럼이 애자일 개발 프로세스로 불리는 개발 방법론 중 하나라는 사실을 알았다! 🤔
"30일마다 동작 가능한 제품을 제공하는 스프린트(Sprint)를 중심으로 하고 있다. 매일 정해진 시간에 정해진 장소에서 짧은 시간의 개발을 하는 팀을 위한, 프로젝트 관리 중심의 방법론이다."

TDD

ref. https://gmlwjd9405.github.io/2018/06/03/agile-tdd.html
ref. https://web.archive.org/web/20070628064054/http://xper.org/wiki/xp/TestDrivenDevelopment
ref. TDD에 대한 오해와 진실

Test Driven Development

테스트 주도 개발 : 테스트가 개발을 이끌어 나간다.

  • 이는 테스트를 먼저 만들고 테스트를 통과하기 위한 비즈니스 로직을 작성하는 것을 뜻한다.
  • 여기서 만드는 테스트도 그 자체로 하나의 프로그램이며 프로그램의 요구사항을 반영할 수 있게 만든다.
int testAdd(){
  assert 5+4 == add(5,4)
  assert -4+9 == add(-4,9)
}
  • add 함수를 만들기 전에 반드시 실패하는 testAdd 함수를 먼저 작성한 뒤, 테스트가 성공하게 만드는 add 함수를 작성하도록 한다.
  • 테스트에 요구사항이 제대로 동작함을 입증할 수 있는 코드를 작성하고 이 테스트를 만족하는 실제 프로그램을 써나가는 것이 TDD이다.

단계적 정의

  1. TDD는 소프트웨어 개발 방법론 중의 하나
  2. Test-Driven Development, 테스트 주도 개발 방법론
  3. 테스트 코드를 먼저 작성함으로써 테스트 코드가 개발을 주도한다.
  4. 이를 위해서 반드시 실패를 포함하는 테스트 코드의 작성이 우선된다.
  5. 테스트 코드를 통과할 수 있는 '최소한의 구현 코드'를 작성한다.
  6. 최소한의 구현 코드는 리펙토링 여지가 충분하다. 하지만 이 단계의 목표는 '테스트 통과'이다.
  7. 최소한의 구현 코드를 리펙토링 단계에서 개선한다.
  8. 4~7을 짧은 주기로 반복하며 점증적으로 개발한다.

추상적 레벨에서 TDD의 핵심 개념

📌결정과 피드백 사이의 갭을 조정하기 위한 테크닉

왜 TDD인가

기술적 관점

  1. 선 테스트 / 후 비즈니스 로직 작성 👉테스트되지 않는 코드가 없어진다 = 프로그램의 모든 코드가 테스트된다👉 버그의 발생 가능성이 줄어든다.
  2. 테스트 자체가 요구사항을 분명하게 드러내준다.
  3. 자연스럽게 프로그램의 디자인이 Simple해지는 경향이 있다.
  4. 잘 짜여진 테스트 👉프로그램에 변경 작업이 가해진 경우 예상치 못한 문제가 발생하는 것을 쉽게 알아차릴 수 있다 👉 변경 작업의 두려움이 감소 👉개발 과정의 유연성이 높아지고 생산성 향상에 기여한다.
  5. 개발하고 있는 코드의 문제점을 빠르게 잡아낼 수 있다.
  6. 구현보다는 인터페이스에 집중하게 해준다.

비기술적 관점

  1. 단기적인 목표와 장기적인 목표를 뚜렷하게 제시해주고 올바르게 잡아준다.
  2. 반복되는 짧은 개발 패턴을 통해 개발 리듬을 만듦으로써 개발 집중력을 높여준다.
  3. 테스트 코드는 사용 설명서 혹은 API 문서로서 의사소통의 도구로 활용할 수 있다.
  4. 성취감은 개발자의 개발 능률을 크게 향상시킨다.

목표의 시각화

📌테스트 코드를 먼저 작성하는 것은 목표를 시각화하는 작업이다.
기대하는 input, output 또는 메소드의 signature(메소드 이름과 파라미터) 등을 미리 고민하게 되는데 이는 모듈 개발자와 사용자에게 모두 도움이 된다.
즉, TDD는 구현보다 인터페이스에 집중하게 해준다.

📌TDD를 수행하다보면 '어떻게'보다 '무엇'에 집중하게 된다.
객체가 어떻게 만들어졌는가, 혹은 어떤 방식으로 비즈니스를 수행하는지 보다는 객체가 무슨 역할을 가져야 하는지, 그리고 이러한 역할을 위해 무엇을 노출해야하는지 등에 집중할 수 있다.

TDD에 대한 오해

초기비용

초기에 테스트 코드를 작성하는 부담으로 인해 비용이 더 들고 개발 속도를 저하시킨다.
👉테스트 코드를 먼저 작성하면 개발해야하는 것에 대한 목적과 요소들을 명확히할 수 있다. 이는 구현체 코드를 작성할 때 고민 시간을 줄여준다.
👉테스트 코드를 작성하기 어렵다? = 설계가 잘못되었음을 암시(해주기도 한다)
👉이는 설계 미스로 인한 유지 보수 비용의 증대를 대폭 감소 시킬 수 있음을 뜻한다.

유지보수

테스트 코드가 없다면, 요구 사항이 변경되는 상황에서..
👉변경된 요구사항을 구현한 후 연관된 요소들이 문제 없을 것을 확신할 수 있는가?
👉TDD는 코드 수정에 대한 불안감을 해소시켜주고 즉각적으로 확신을 줄 수 있다.

소프트웨어 복잡도가 증가함과 비례하여 테스트 코드를 추가로 작성하는 부담이 있다
👉오히려 TDD를 적용하지 않는다면 복잡도가 증가함에 따른 유지보수 비용이 기하급수적으로 증가하는 것이 일반적
👉일정수준까지는 테스트 코드 작성이란 부담이 있을 수 있으나, 특정 시점을 기준으로 거의 비용이 증가하지 않고 일정하게 유지된다.

TDD와 Mock

테스트 코드를 작성해야하는데 필요한 모듈이 미처 완성되지 않은 상황에서 우리는 'Mock'을 활용할 수 있다!! (🤔애자일-TDD-Mock이 이런관계가 있다는걸 처음 알았다.)
단, Mock 객체가 행위에 대한 기능 검증을 빠르게 수행할 때는 도움이 되지만 너무 남용할 경우 테스트 코드 자체의 가치를 깨뜨릴 수 있다.


예를 들어,
Mock으로 처리한 모듈에 사용되는 argument가 이전에는 유효했지만, 현재는 유효하지 않은 경우...
더 이상 기존의 Mock 객체를 이용한 테스트 결과가 시스템이 올바르게 동작함을 보장하지 못한다.


TDD의 올바른 사용 습관

Top-Down으로 방향을 잡고, Bottom-Up 으로 구현에 집중하자.

Top-Down 방식으로 설계 및 시나리오를 잡고, Bottom-Up 방식으로 기능에 대한 코드 구현을 구체화 시키면서 문제점을 차례로 해결한다.
📌디자인은 Top-Down, 기능은 Bottom-Up

바보 단계 거치기

처음부터 완벽한 코드를 작성하는 것에 집착하지 말자.
이는 개발 속도를 저하하며 개발자의 정신건강🤬에도 좋지않다.
클라이언트 관점에 기대하는 바를 충족하는 정도로 빠르게 구현한 뒤 테스트 코드를 깨트리지 않으며 리팩토링을 해나간다.
📌TDD는 이렇게 해야한다는 틀에 갖히지 말자
'반드시 툴(단위 테스트 프레임워크)을 써서 이렇게 해야된다.'라는 생각/규칙에 얽매이는 것은 애자일이 아니다.
규칙에 얽매이면 결국 똑같은 테스트를 copy&paste하는 것이다. 도구와 규칙에 집착하면 TDD는 어려워진다.

시나리오 구상하기

Given / When / Then 템플릿을 통해 기대 행위에 대한 명세화에 초점을 맞춘다.
이는 테스트 메소드 각각의 시나리오 작성을 수월하게 할 수 있도록 돕는다.

TDD의 단위 테스트를 문서화하자

테스트 코드는 항상 거의 최신을 유지할 가능성이 높으며, 이 자체가 메소드에 대한 사용법이나 예외 등을 담고 있음으로 좋은 샘플 코드로서도 가치가 있다.
또한, Given / When / Then 구조의 코드를 통해 테스트 코드를 읽는 것만으로도 다른 구현체와의 의존성을 파악할 수 있다. (물론 가독성이 확보된 경우)

함께 읽어보면 좋을 글

[번역] TDD 변절자 : TDD는 설계 기법이 아니다

profile
🌱 😈💻 🌱

1개의 댓글

comment-user-thumbnail
2022년 9월 20일

If you appreciate challenging video games, run 3 will pleasantly surprise you. I had a lot of fun playing a new game that I just learned about. This challenging running game will put your skills to the test. haphazardly down the incline.

답글 달기