kakasoo

테스트 코드로 커뮤니케이션하기 본문

프로그래밍/NestJS

테스트 코드로 커뮤니케이션하기

카카수(kakasoo) 2023. 3. 12. 20:15
반응형

잘 만들어진 테스트 코드는 일종의 spec, 즉 명세서의 역할을 수행할 수 있어야 한다.

또한 잘 만들어진 테스트는, 코드 설계에 앞서 개발자 간의 커뮤니케이션을 위한 도구로 사용될 수 있어야 한다.

여기서 말하는 개발자는 백엔드 개발자만이 아니라, API를 다루는 모든 관계자를 말한다.

디자인을 이야기하기 위해서는 기획서가 필요하듯이, 개발자들도 개발을 위한 기반 지식들이 필요하다.

이 지식은 단순히 개발을 위한 도메인 지식이 아니라, 서로 간의 이해가 일치하는지 확인하는 일을 포함한다.

테스트 코드는 여기서 이 일치 확인, 전체 프로그램 작성에 일관성을 확보하는 작업을 위한 것이라 볼 수 있겠다.

 

테스트 코드 (spec) 작성

/**
 * 게시글에 대한 좋아요/좋아요 취소
 */
describe('PATCH api/v1/articles/:id', () => {
  /**
   * 만약 유저가 빠르게 눌러서 좋아요가 2번 눌릴 경우,
   * 좋아요 취소 대신 에러를 뱉는 게 옳다면 좋아요/좋아요 취소 API는 분리한다.
   */
  it.todo('게시글에 좋아요가 가능하다.');
  it.todo('이미 좋아요한 게시글에 대해서 해당 API 재호출 시 좋아요가 취소된다.');
  it.todo('사라진 글에 대해서 좋아요는 불가능해야 한다.');

  /**
   * 추후 마이페이지나 그 외 페이지에서 좋아요를 모아보게 될 경우, 사라진 글들은 디자이너가 확인 후 취소가 가능해야 하기 때문
   */
  it.todo('사라진 글에 대해서 좋아요 취소는 가능해야 한다.');
});

/**
 * 게시글 신고
 */
describe('POST api/v1/articles/:id/reports', () => {
  /**
   * article.isReported는 1이 올라가며, ReportArcticle table에 row 1개 생성
   */
  it.todo('게시글을 신고한다.');
  it.todo('신고 사유가 명시되어야 한다.');
  it.todo('동일 유저는 하나의 게시글을 2회 이상 신고할 수 없다.');

  /**
   * 아래의 TODO는 신고 철회 API에서 검증할 것
   */
  // it.todo('동일 유저가 게시글을 신고 후 취소한 경우 isReported는 감소, ReportArticle table는 상태 변경');

  /**
   * isReported는 다시 증가, 그리고 ReportArticle table의 row는 상태 변경
   */
  it.todo('신고가 철회된 게시글에 대해서 다시 신고하는 것이 가능해야 한다.');
});

/**
 * 게시글 중 그리기에 해당하는 글에 대한 수정
 */
describe('PUT api/v1/articles/:id', () => {
  /**
   * 이미지를 수정하는 경우, 해당 이미지를 저장하고 그 이력을 남겨야 한다.
   * 서비스 내 이미지는 개발자의 커밋 이력처럼, 이미지 이력이 남아야 한다.
   * 언젠가 이미지는 블록체인을 이용해서 저장
   */
  it.todo('그리기(drawing) 타입의 게시글 수정 시, 만약 이미지를 수정하는 경우');

  /**
   * 그 외 수정 사항에 대해서는 다른 게시글 타입과 마찬가지로 동작해야 한다.
   */
  it.todo('그리기(drawing) 타입의 게시글 수정 시, 이미지를 제외한 나머지를 수정하는 경우');

  it.todo('그 외 나머지 타입에 대한 게시글 수정이 올바르게 되는지에 대한 검증');
});

/**
 * 게시글에 댓글 남기기
 * 그리기 타입 글에 대해서는 댓글에 좌표 값이 반드시 있어야 한다.
 */
describe('POST api/v1/articles/:id/comments', () => {
  it.todo('게시글에 댓글 남기기');
});

/**
 * 답글 달기
 */
describe('POST api/v1/articles/:articleId/comments/:commentId', () => {
  it.todo('게시글의 댓글에 답변을 남기기');
});

/**
 * 댓글에 대한 좋아요/좋아요 취소
 */
describe('PATCH api/v1/articles/:articleId/comments/:commentId', () => {
  it.todo('댓글에 좋아요 하기');
  it.todo('이미 좋아요한 댓글에 대해 좋아요를 할 경우 취소가 된다.');

  it.todo('삭제된 댓글에 대해서 좋아요를 할 수는 없다.');

  /**
   * 추후 마이페이지나 그 외 페이지에서 좋아요를 모아보게 될 경우, 사라진 글들은 디자이너가 확인 후 취소가 가능해야 하기 때문
   */
  it.todo('삭제된 댓글에 대해서는 좋아요 취소가 가능해야 한다.');
});

/**
 * 댓글 삭제
 */
describe('DELETE api/v1/articles/:articleId/comments/:commentId', () => {
  it.todo('작성자는 댓글을 삭제할 수 있어야 한다.');
  it.todo('본인의 댓글이 아닌 경우에는 에러를 뱉어야 한다.');

  /**
   * 추후 필요한 기능
   */
  it.todo('신고 당한 댓글이 삭제될 경우, 관리자 채널로 알림을 보내야 한다.');
});

/**
 * 댓글 수정
 * 수정 시에는, 이전 내역이 욕설이나 그 외 상대의 기분을 해칠 수 있는 댓글인지를 확인해야 한다.
 */
describe('PUT api/v1/articles/:articleId/comments/:commentId', () => {
  it.todo('댓글을 수정할 수 있다.');

  /**
   * 수정을 여러 차례에 나눠서 할 경우, 그 이력을 알 수 없기 때문에 모두 저장해야 한다.
   * 당장 급한 스펙은 아니다.
   */
  it.todo('신고당한 글을 수정할 때에는 그 수정 이력을 저장해야 한다.');
});

/**
 * 댓글 신고
 * 댓글이 신고된 경우, 해당 댓글의 내역을, 유저가 수정할 경우를 대비해 따로 저장해두어야 한다.
 */
describe('POST api/v1/articles/:articleid/comments/:commentId', () => {
  /**
   * ReportComment에 칼럼을 두고, 신고 당시의 글 내용을 저장해두는 걸 추천한다.
   */
  it.todo('댓글이 신고될 때, 신고 당시의 내용을 저장해야 한다.');
});

단순 CRUD성 API를 만든다고 가정할 때, 나는 이런 식으로 e2e 테스트를 작성했다.

주석들은 그 API에 대해 추가로 알아야 할 부분이 있을 경우를 작성한 것이다.

이걸 이제 각 파트를 개발해야 하는 개발자들에게 뿌려서 요구 사항을 모두 충족하게 개발을 시키면 된다.

이 테스트 코드들은 그들이 스펙을 이해하고 올바른 개발을 할 수 있도록 할 것이며, 덕분에 관리 소요를 줄여준다.

원래라면 각자가 제대로 개발이 되었는지를 확인해주어야 하며, 서로가 서로의 작업물을 평가해주어야 한다.

하지만 코드 리뷰에 앞서 일단 요구사항을 충족했는지를 알면, 우리는 그저 컨벤션만을 확인하면 된다.

적절한 네이밍을 지었는지, 코드는 생산성과 효율성이 적당한 타협을 이뤘는지 등을 확인하면 된다.

만약 부족한 부분이 있다면, 추가적인 테스트 코드를 작성하여 서로에게 이 부분을 달성해줄 것을 요청하면 된다.

반응형