티스토리 뷰

내가 작성한 소스코드를 신뢰할 수 있을까?       

내 동료가 작성한 소스코드를 신뢰할 수 있을까?       

 

사람이 직접 작성한 모든 소스코드는  결함을 가질 수 밖에 없다.      

그래서 우리가 작성한  코드가 올바르게 동작함을 증명할 필요가 있다.            

 

사실 개발 일정에 쫓기다보면 테스트 코드를 작성하지 않고 기능을 만들기에 급급할 수도 있다.            

하지만 그렇게 급하게 만든면 완성도가 떨어지고 결함을 가진 프로그램이 만들어진다.

나중에 오류를 찾느라 더 오랜 시간을 허비하기도 한다.            

 

테스트 코드를 작성하는 것은 다음과 같은 이유로 여러움을 겪는다.

 

1. 개발 시간의 증가

  • 처음 테스트코드를 작성해 보면 시간이 더 많이 필요한 것이 사실이다.
    실제로도 개발 로직에 작성된 코드 수보다 테스트코드를 더 많이 작성해야 하는 경우가 많이 발생한다.
    게다가 테스트 코드 작성이 익숙하지 않다면 더 많은 시간이 필요할 것이다.
  • 테스트코드 없이 개발을 하게 되면 단위별로 개발한 기능을 전체 UI까지 완성하고 나서야 정상 동작을 확인 할 수 있다. 
    그러다 보면 작은 단위로  완성도 있게 개발하지 못하고  전체 기능을 개발한 후에나 오류를 확인하고 수정해야 하기  때문에 프로젝트 전체로 테스트 코드를 작성하면서 개발하는 것보다 더 많은 시간이 필요할지도 모른다.

2. 테스트코드 관리(업데이트)의 어려움

  • 개발 소스가 수정되면 테스트 코드도 함께 수정해야 한다. 
    당연한 이야기처럼 들리겠지만 이것 때문에 테스트 코드가 유지되지 못하고 망가지는 경우를 많이 보았다. 
    예를 들어 클래스 생성자에 하나의 초기 parameter가 추가되었다고 가정해 보자.  이때 관련된 소스만 수정하는 것이 아니라 이 클래스를 사용하는 테스트 코드와 Mock오브젝트 까지 수정해야 한다. 사실 이 정도 수정이야 별거 없어 보이지만 수정이 많아지면 많아질수록 특별히 로직이 변경된 것도 아닌데 수정해야 하는 코드가 기하급수적으로 늘어나는 것을 볼 수 있다. 
  • 테스트코드를 실제개발 소스만큼 지속적으로 잘 관리해야 한다.
    관리해야 하는 코드가 개발소스뿐만 아니라 테스트 코드까지 확장되기 때문에 실제로 신경 써야 할 것이 더 많은 것이 사실이다. 

3. UI 테스트의 어려움

  • 특히 모바일 앱과 같이 UI를 포함하는 프로젝트의 경우 UI관련된 동작이나 표시여부등을 확인하는 것이 쉽지 않다. 
    (이것을 할 수 있는 기능을 제공하고 있지만 일반적인 로직만 테스트하는 것에 비해서 해야 하는 일도 많고, 특정 Widget의 찾고 가져오는 방법도 명확하지 않은 경우가 많다. - Widet의 위치가 부모/자식 관계가 조금만 바뀌어도 찾지 못하는 경우도 생긴다.)
  • UI는 개발 중에도 수시로 변경되는 경우가 많기 때문에 더욱 테스트하기가 쉽지 않고, 이미 작성한 테스트 코드의 수정도 빈번하게 발생한다.
  •  화면의 표시되는 정보와  화면과 관련된 일련의 로직이 잘 분리되게 설계되지 않은 경우 테스트가 어렵다. 
    이런 경우에는 UI의 로직 부분을 잘 분리해서 따로 테스트하는 것이 바람직하다. 
  • 그래서 UI에서  View(화면에 정보를 표시)와 ViewModel(화면의 정보를 표시하는 상태와 로직)의 역할을 명확하게 분리하는 것이 가장 중요하다.
    ( View부분은 오직 정보의 표시하는 것에 중점을 두고, ViewModel에서 로직의 처리와 데이터의 관리를 담당한하면 View의 테스트 없이 ViewModel의 테스트 만으로도 충분할 수 있다고 생각한다. )

4. 조직(팀) 내 동료들의 이해와 참여부족

  • 여러 개발자가 참여하는 프로젝트에서는 함께 참여하는 동료들 간의 소통과 통일된 구조에 대한 이해와 약속이 무엇보다 중요하다. 
    그래서 프로젝트를 시작하기 전에는 코드컨벤션(Code Convention)을 확정하고 시작하곤 한다.
  • 테스트 역시 마찬가지이다. 테스트 코드에 대한 구조와 테스트 방법에 대해 정확한 규칙을 정하는 것이 필요하다.
    특히 테스트 코드 작성이 익숙하지 않은 개발자가 있을 때는 팀에서 정한 규칙에 따라 테스트코드를 작성하는 방법을 익힐 필요가 있다. 
  • 그리고 참여하는 모든 개발자가 빠짐없이 자신의 테스트를 잘 작성해야 테스트가 쓸모 있는 것이 된다. 만약 한 사람이라도 빼먹게 된다면 점점 더 테스트 코드를 작성하지 않게 되고, 결국 그전에 작성한 테스트코드들도 쓸모없는 것이 되기도 한다. 
  • 모든 프로젝트가 마찬가지겠지만 테스트도 개발자들의 일정 수준 이상의 이해와 참여가 꼭 필요하다. 

사실 위와 같은 어려움 때문에 테스트 코드를 작성을 생략하고 개발을 하거나 처음에는 테스코드를 작성하다 나중에는 포기하고 형식적인 형태의 테스트 코드만을 남기는 경우를 많이 보게 된다. 

하지만 잘 작성된 테스트 코드가 줄 수 있는 장점은 분명히 있다.  

 

1. 코드 품질의 향상

  • 개발자가 코드를  더 깊이 이해하고, 더 나은 코드를 작성할 수 있도록 도와줄 수 있다. 
  • 테스트하기 쉬운 구조로 더욱 간결하고 명확한 개발을 하게 되기 때문이다.
    그리고 개발(테스트)하고자 하는 스펙을 명확히 이해하게 된다. 

2. 버그의 감소  

  • 테스트 코드를 작성하면 코드가 예상대로 작동하는지 미리 확인할 수 있다.  단위별 테스트가 가능하기 때문에 다른 의존하는 기능들의 구현에 의지하지 않고 테스트가 가능하기 때문에 단일 동작에 대한 버그를 확인하고 수정할 수 있다.
  • 그리고 코드의 일부분을 변경하거나 수정할 때에도 더욱 안전하게 개발이 가능하다. 
    특히 Side effect가 발생하는 것을 미리 확인 할 수 있기 때문에 더욱 안전한 서비스를 만들 수 있다. 

3.  개발자와의 소통: 코드 기능에 대한 명확한 전달  

  • 개발자들은 테스트 코드를 통해 코드의 기능 및 구조를 더 빠르게 파악할 수 있다.
    코드만 보는 것보다는 그것을 테스트한 과정을 보면 기능에 대한 더 명확히 이해할 수 있다.
  • 코드 리뷰에서도 테스트 코드가 있으면 코드에 대한 설명을 더욱 명확하게 할 수 있고 해당 코드를 다른 개발자가 확인하고 직접 테스트할 수 있어 이해를 높이는데 도움을 준다. 
  • 정말 잘 작성된 테스트 코드와 Description은  코드의 스펙들을 명확하게 설명할 수 있기 때문에 스펙 문서처럼 기능을 확인하는데 도움을 준다.

4.  구조의 명확성 강화

  • 테스트 가능한 구조로 설계되고 테스트하기 좋은 형태로 기능을 분리해서 개발하게 된다.
  • 결합도가 높을수록 테스트하기가 어렵다. 
    결국 테스트하기 쉬운 형태를 만들다 보면 추상화게 되고, 결합도가 낮은 클래스들을 만들게 된다.
  • 결국 개발자는 단순한 기능의 개발을 넘어 프로젝트의 설계(아키텍처)까지 더욱 구조적이고 명확하게 만들게 된다.

5. 코드의 신뢰

  • 본인이 작성한 코드가 아닌 이상 작성된 코드만 보면 이것이 정상동작하는지 알기가 쉽지 않다.  코드를 하나씩 다 분석해 보지 않고서는 정상 동작의 유무를 알 수 없다. (본인이 작성한 코드도 나중에는 이해하기 못하는 경우도 많다)
  • 개발자가 작성한 코드의 동작을 신뢰 할 수 있다는 것을 테스트코드가 증명해 줄 수 있다.

이런 장점들 때문에 많은 조직에서 테스트 코드의 작성을 권장하거나 강제하고 있다. 

하지만 역시 현실은 그리 호락호락하지 않다. 여러 이유로 지속적인 테스트코드가 잘 관리되지 못하고 형식적인 테스트 코드만 남게된 프로젝트를 보게 된다.

 

그렇다면 제대로 된 테스트 코드를 작성하며 프로젝트를 완성할 수 있는 방법은 무엇일까? 

개인적으로는 그 해결책이 될 수 있는 방법이 TDD가 아닐까 생각한다.  

 

TDD? 

테스트 케이스를 먼저 작성하고, 그 테스트 케이스를 통과하는 코드를 작성하는 개발 방법론으로 다음과 같은 과정을 반복하며 기능과 테스트코드를 완성하는 개발 방법론이다.

1. 기능(스펙) 정의
   . 개발할 단위기능에 대한 스펙을 명확하게 정의하고, 스펙을 정의한 추상화된 클래스(인터페이스)나 함수를 선언한다. 

2. 테스트 코드 작성
   . 정의된 기능(스펙)을 검증할 테스트 코드를 작성한다.

3. 테스트 실행 - 실패
   . 테스트 코드는 실패한다.
           - (최초): 구현이 필요한 빈 구현체만 존재.
           - (코드작성) : 코드가 올바르게 동작하지 않을 경우. 

4. 코드 작성
    . 실패한 테스트 코드를 성공시킬 수 있는 코드를 작성한다.

5. 테스트 실행 
    . 테스트 코드를 반복수행하며 테스트에 성공하는 코드를 완성한다. 

6. 리팩토링
    . 작성한 코드를 리팩터링 하여 더 나은 코드로 개선한다.

TDD는 프로젝트를 진행하는 동안 위 과정을 반복하며 단위 기능을 만들어 가며 개발하게 된다. 

테스트 코드를 먼저 작성한 후 기능을 구현해야 하기 때문에 테스트 코드의 작성이 강제된다.  이런 이유로 팀에서 TDD를 도입하고 이 방법에 익숙해지게 되면 테스트 코드 작성을 지속하며 개발하는 것이 가능하다. 

 

https://ko.wikipedia.org/wiki/%ED%85%8C%EC%8A%A4%ED%8A%B8_%EC%A3%BC%EB%8F%84_%EA%B0%9C%EB%B0%9C

 

테스트 주도 개발 - 위키백과, 우리 모두의 백과사전

위키백과, 우리 모두의 백과사전. -->

ko.wikipedia.org

 

 

마지며

작은 단위의 프로젝트나 간단한 기능은 테스트 코드 없이도 쉽게 개발할 수 있습니다.

하지만 이런 개발 습관을 지속하다 보면 크고 작은 개발의 실수들을 개발 중에 쉽게 찾아낼 수 없고  화면을 보면서 오류를 찾아내거나 배포 후에나 알 수 있게 되는 경우가 많습니다. 

많은 개발자들에게 잘 작성된 테스트 코드를 지속적으로 만들어 내는 일은 쉽지 않은 일입니다. 테스트 작성에 익숙하지 않고 처음에는 시간도 많이 필요하기 때문입니다.

하지만 우리가 개발자로서 앞으로도 오랜 시간일을 해야 하고 좀 더 완성도 높은 서비스와 코드들을 만들어 나가야 한다면 더 이상 미루지 말고 테스트 코드를 작성하는 것이 습관이 될 수 있도록 노력해야 합니다.

 

다음 글부터 본격적으로 Test Driven Development(TDD)를  Flutter 프로젝트에 적용하는 방법에 대해서 상세하게 설명해보겠습니다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/05   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
글 보관함