협업에서 테스트코드는 왜 필요할까

Dec 27, 2020


테스트 주도 개발 (TDD, Test Driven Development)에 대해 얘기를 하는 사람은 많았지만, 정확히 테스트가 왜 필요한지, 테스트를 썼을 때 좋은 점이 어떤 게 있는지에 대해 정리해 보려고 합니다. 혼자 개발할 때는 테스트 주도 개발과 테스트의 필요성에 대해 느끼지 못했지만, 협업을 하면서 테스트 코드가 만드는 즐거움에 대해 알게 되었고, 제가 생각하는 테스트의 장점은 크게 2가지로 나눌 수 있었습니다.

외부환경을 분리해 두고 핵심로직을 먼저 개발할 수 있다.

  • 아무래도 협업해서 개발을 할 때는, 제가 만들어야 하는 기능이 다른 개발자가 만드는 기능과 함께 동작해야 기획서에 적혀있는 하나의 기능을 완성하는 경우가 있습니다. 크게는 API에 사용되어 유저 응답에 사용되는 기능과 관리툴 개발의 관계가 있을 수 있고, 작게는 어떤 한 데이터의 파이프라이닝 기능을 구현해야 할 때가 있습니다.

  • 먼저 기능을 구현하기에 앞서서, 모듈간의 통신을 어떻게 해야할 지에 대해 정했다면, 그 후의 기능구현은 매우 간단합니다. 모듈간의 통신에 사용되는 데이터를 만드는 부분을 테스트 코드로 대신할 수 있습니다. 테스트 코드를 작성한다면 제가 구현하고자 하는 로직을 설명할 수 있습니다. 테스트의 시작 부분에서 어떤 요청이 들어오는 지를 정의할 수 있고, 테스트의 끝 부분에서 어떤 응답이 내려가는지에 대한 정의를 할 수 있습니다. 이렇게 먼저 개발하게 되면 미리 정의해 둔 데이터에 대한 명세에서 부족한 점이 어떤건지, 스펙에서 누락된 지점이 어디인지를 먼저 파악할 수 있어서 개발 시간과 커뮤니케이션 비용을 단축할 수 있습니다.

  • 또한, 제가 개발해 오는 동안 겪었던 문제 상황에 대한 케이스들을 테스트케이스의 반복적인 작성에서 관찰할 수 있습니다. 다른 테스트 케이스를 짤 때 확인했던 것과 비슷한 지점에서 에러가 나고, 예외가 생길 지에 대한 확인을 할 수 있습니다. 특히 로직의 동작 확인을 빠른 시간 내에 확인할 수 있다는 점에서, 테스트 케이스 작성은 편리하게 어떤 예외가 발생할지에 대한 확인을 진행할 수 있게 도와줍니다.

  • 마지막으로 다른 사람이 작성해 둔 테스트 데이터와 테스트 환경을 간섭하지 않고 로직에 집중할 수 있습니다. 이 부분은 테스트를 작성할 때도 조심해야 하는데 테스트의 장점은 아무래도 외부 환경에 영향없이 로직이 제대로 동작하는지 확인할 수 있다는 점에 있다고 생각하기 때문입니다. 만약 로직을 작성할 때 DB나 메시지큐 등 공동으로 사용해야하는 자원을 계속해서 수정해가면서 테스트해야 한다면, 아무래도 협업하는 사람들에게 예기치 못한 문제를 일으킬 가능성이 있습니다. 특히 DB의 테이블을 제거한다던가 컬럼을 제거하는 등 어플리케이션 기동에 필요한 정보를 수정할 경우 다른 사람들의 코딩 작업을 아예 막아버릴 수 있기 때문에 이런 부분을 수정할 때는 더 조심해야 합니다.

내가 개발해 둔 스펙의 기능명세서로 사용할 수 있다.

  • 테스트코드를 작성하고 나면, 테스트 코드는 테스트 대상이 되는 메소드에 들어오는 입력의 형태와, 원하는 출력의 형태가 적혀있는 코드가 완성됩니다. 이러한 테스트 코드는 나중에 다른 개발자가 내가 작성한 메소드를 수정할 일이 생겼을 때 코드를 이해하는 데에 도움이 됩니다. 특히 파라미터로 범용의 파라미터용 클래스가 들어올 때, 테스트 코드를 보고 파라미터 클래스 중 어떤 데이터만 사용되는지 확인하는데 크게 도움이 됩니다.

  • 또한, 테스트 코드를 수정하고 실행해 보는 것으로 수정해야할 메소드가 어떻게 동작하는지 빠르게 파악할 수 있도록 도움을 줍니다. 간혹 테스트가 없는 경우 기능확인을 하기 위해 데이터를 입력하기 위한 툴도 확인하고, 기능을 확인하기 위해 앱을 켜야하기도 하고, 원하는 환경을 구성해줘야하는 경우가 있는데, 테스트 코드가 있을 경우 이런 부가 과정을 크게 줄여주는 역할을 합니다.

  • 테스트 코드와 테스트 환경이 완성되어 있다는 것만으로도 해당 기능을 수정해야하는 사람에게 꽤 안정감을 줄 수 있습니다.

주의해야할 점

  • 테스트코드가 공용환경의 자원을 사용하고 있으면 원치 않는 상황에서 테스트가 깨질 수 있습니다. 테스트코드를 사용할 때는 최대한 외부환경의 분리가 필요합니다.
    • 예를 들어, 외부 API를 호출한다거나, DB등을 사용하는 경우에는 IntegrationTest로 따로 환경을 분리해두고, 로직을 테스트하는 부분은 Mock을 적극적으로 활용하는 것이 좋습니다.
    • 너무 많은 Mock이 고민된다면, E2E 테스트의 도입을 고민해보는 것이 좋습니다.
  • DB나 Redis등 외부에 존재하는 데이터를 사용해야 하는 테스트의 경우, 로컬에 환경을 구성할 수 있는지 먼저 확인하고, 부득이하게 데이터를 공용으로 사용해야 한다면 insert와 delete를 테스트에 포함해두는 것이 좋습니다.
  • MySQL등 롤백이 가능한 DB를 사용하고 있다면 테스트환경에서 구동할 때 커밋하지 않고 바로 롤백이 가능하도록 테스트를 구성해야 합니다.
    • 만약 Private Key에서 Auto Increment를 사용할 경우, 테스트가 끝나고 나면 Auto Increment Index가 올라간 채로 돌아오지 않을 수 있습니다.
    • 테스트할 때 Auto Increment인 Private Key를 바꾸지 않도록 임의의 숫자를 넣어서 테스트를 할 수 있도록 하거나, 아예 Private Key가 데이터에서 큰 의미를 가지지 않도록 개발하는 것이 좋을 수 있습니다.