TDD&iOS [2] 반복, 반복. 테스트 주도 개발기법

도대체 언제 했는지도 모를 스터디... 블로깅이라기보단 노트에 가까운데, 너무 많은 노력을 들이려는게 아닌지 ㅠㅠ 여튼 꽤 많은 시간이 지났기에 @agiletalk님께서 교재를 정리해주신 포스팅 내용 중 일부를 발췌하고, 느낌+생각+기억하고 있는 것들을 가감하여 복습/정리하고자 한다.

hello_bob

(아니요! ;ㅁ; )

  • 장소 : 강남역 윙스터디 해커스점
  • 시간 : 2014.1.28 20:00-22:00
  • 참석자 : 8명
  • 교재 : 테스트 주도 iOS 애플리케이션 개발

2장. 테스트 주도 개발용 기법

첫 테스트

일반적인 테스트 주도 작업 접근법은 테스트를 하나 만들고 실행해서 실패하는지 확인한 후 이 테스트를 통과할 코드를 작성하는 것이다. 통과하면 다음 테스트를 작성하는 것을 반복한다.

적색, 녹색, 리팩토링

tdd_2_diagram

테스트 주도 앱 설계

구현할 클래스와 메소드의 목록을 전부 나열한 자세한 모델은 필요 없다. 작은 단위의 설계는 테스트에서 나온다. 필요한 것은 기능이 무엇인지와 해당 기능을 어떻게 함께 맞추어 갈 것인지다.
시스템 메타포(익스트림 프로그래밍), 도메인 모델(객체지향 프로그래밍)은 애플리케이션에서 사용자가 서비스를 사용해 객체에 무엇을 시도하려는지를 바라보는 관점이다.
이 정보를 사용해 앱의 동작뿐만 아니라 앱이 설계 기획에 따르고 있음을 점검하는 테스트를 기획할 수 있다.

리팩토링

  • 코드는 필요한 동작을 하지만 이 동작이 마음에 들지 않는 코드라면 리팩토링이 필요하다.
  • 더 이상 나빠 보이지 않거나 나쁜 냄새가 나지 않을 때 리팩토링을 그만 둔다.
  • 리팩토링 과정은 나쁜 코드를 나쁘지 않은 코드로 바꾼다.

YAGNI

  • 앱 코드 중 필요한 것을 설명한 테스트를 작성하고 테스트를 통과하는 코드를 작성하기만 하면 필요로 하지 않는 코드를 작성할 필요가 없다.
  • YAGNI : 지금 당장 필요 없으면 앞으로를 위해 준비할 필요가 없다, Ya Ain’t Gonna Need It
  • 기본적으로 사용하지 않을 코드를 작성하지 않는다. (당장은.)
  • 테스트 주도 앱은 불필요한 코드가 전혀 없고 테스트하지 않은 코드도 없다. (-> 질문1)

코드 작성 전, 작성 중, 작성 후 테스트

테스트 주도 개발을 하려고 적색, 녹색, 리팩토링 접근 방식을 따른다면 코드를 작성하기 전에 테스트가 실패함을 증명하려고 테스트를 실행할 것이다. 이는 테스트를 해서 명세한 행동을 구현할 필요가 있다고 말한다. 코드를 만들면서 녹색 막대로 향하는 작업을 하는 동안에도 이외의 기능에 영향을 미치는지 확인하려고 테스트를 계속 수행할 것이다. 기능을 모두 구현한 이후 리팩토링 단계에서도 코드를 정리하는 작업이 부정적인 영향을 끼치지 않는지 확인하려고 테스트를 계속할 것이다.

tdd_2_flowchart

다른 중요한 방어벽은 제품의 배포 후보 버전을 준비할 때마다 테스트를 수행한다고 보장하는 것이다. 이 시점에서 테스트가 실패하면 해당 빌드를 테스터나 고객에게 전달할 이유가 없다. 뭔가 잘못됐고 잘못을 수정할 필요가 있다.
일반적으로 일하는 것보다 테스트하는 시간이 더 길다고 느껴지지 않는 한 가능할 때마다 자동으로 테스트하게 하는 것을 목표로 해야 한다. 테스트를 하면 다음에 해야 할 일과 진행 상황을 바로 피드백해서 알 수 있기 때문이다.


기억나는게 정말 없구나... 그나마 기억나는 굵직한 것 정리.

질문1. 1장에서는 분명 '모든 코드를 테스트할 수 없다'고 했고, 2장에서는 '테스트하지 않은 코드가 없다'라고 했다. 뭐지!?

이해 > 단순화시켜서, main과 class가 있을때, class 안에서 작성되는 모든 코드는 테스트가 완료된 코드만 존재해야 한다. 미리 정의된 테스트 케이스에 따라 작성되므로, 테스트하지 않은 코드가 없는 상태가 되는 것이고, 그것들을 호출해서 main에서 이렇게 저렇게 사용할 때에는 테스트 코드를 작성할 필요가 없기 때문에 '모든 코드를 테스트 할 수 없다'고 한 것같다.

질문2. 스터디 도중에 '테스트 케이스'와 '테스트 코드'라는 말이 수없이 반복된다. 차이는?

이해 > 테스트 케이스는 테스트 코드를 작성하기 위한 테스트를 나열한 것들이다. 각 테스트 케이스와 코드는 1:1로 짝을 이루기 때문에 해당 테스트 케이스가 더 이상 쓸모 없어진 경우라면, 테스트 코드와 실제 코드까지 걷어내는 것이 맞다. (나쁜냄새가 나는 주석따위!! 파워삭제!!)

덧.
2장에서 말하는 말하는 나쁜 냄새가 나는 코드에는 불필요한 주석도 포함되는데,
//이 함수의 기능은... (블라블라)
이런거도 때에 따라 포함되지만,
// 언젠가 쓸지도 몰라. 우선 주석.
// 사장님이 다시 넣자고 할 수도 있는 기능. 숨겨놓자
뭐 이런 식으로 쓰지않는 코드들을 임시로+좋은말로 archive 시켜두는 주석들도 모두 포함된다.

line by line 으로 다는 주석은 크게 의미가 없으므로(:코딩할때 남들이 짜놓은 소스에 달린 주석을 봐가면서 이해하는게 아니라 그냥 갖다쓰기 때문에 아무리 설명해놔도 안보고 쓸 가능성이 많다는 의미) 문서화 되어 있는 테스트 케이스만 보더라도 해당 클래스의 기능을 모두 이해하고 사용할 수 있어야 하며, 실제 소스코드에는 Doxygen 형식으로 주석을 작성하여 문서자동화에도 도움이 되도록 해야한다는 팁.

질문3. 그럼 함수 구현에 따른 예외처리는?

이해 > 예외 처리 자체도 하나의 테스트 케이스로 고려가 되어야 하며, 따라서 독립된 코드로 다뤄줘야 한다. 클래스 내부에서 쓰이는 함수는 파라미터 던지면 리턴값 퉤 뱉는 수준의 코드로만 작성되어야 한다. 그 안에서 분기처리가 시작되면 그건 이미 냄새나는 코드. 필요한 분기처리는 가져다 쓸 때 하는 것.(이라고...기억이 가물가물)

뭔가 엄청 빼먹은 듯한 복습. 3장은 소스코드로 설명돼 있어서 더 모르는데... (카테고리 닫을까(진지))

적게 일하고 많이 버는 법을 늘 고민합니다. 일이 되게 하는 것에 간혹 목숨을 겁니다. 지금은 우아한형제들과 함께 일하고 있어요.