<p style="text-align:justify;">최근 프론트엔드 영역에서도 테스트 코드를 많이 작성하는 편입니다. 특히 채용공고를 둘러보면 Cypress, Jest, testing-library 등의 테스트 기술이 적혀있는 것을 확인할 수 있습니다. 그러나 아직 프론트엔드에서의 테스트 코드는 백엔드 영역과 달리, 팀의 개발 문화로 자리 잡거나 개인이 익숙해질 정도의 단계는 아닌 것 같은데요.</p><p style="text-align:justify;"> </p><p style="text-align:justify;">그러다 보니 테스트 코드를 저마다의 스타일로 작성하는 경우가 많습니다. 그러나 테스트 코드도 가독성이 중요한 만큼, 이번 글에서는 테스트 코드를 어떻게 작성해야 가독성을 높일 수 있을지 테스트 코드 작성 팁에 관해 살펴보고자 합니다.</p><div class="page-break" style="page-break-after:always;"><span style="display:none;"> </span></div><h3 style="text-align:justify;"><strong>테스트 코드의 역할</strong></h3><p style="text-align:justify;">먼저 테스트 코드 작성 방법을 살펴보기 전, 테스트 코드의 역할이 무엇인지 알아야 하는데요. 우리는 왜 테스트 코드를 작성할까요? 그 이유는 작성한 코드가 제대로 동작하는지 검사하고, 코드를 수정할 때 예상하지 못했던 버그를 미리 발견하기 위함입니다. 이외에도 테스트 코드는 문서로서 중요한 역할을 합니다.</p><p style="text-align:justify;"> </p><p style="text-align:justify;">여러분이 누군가 작성한 테스트 코드를 읽는다고 할 때, 복잡한 테스트 코드를 원하는 사람은 없을 것입니다. 그렇다면 어떻게 해야 더 나은 테스트 코드를 작성할 수 있을까요? 지금부터 하나씩 살펴보겠습니다.</p><p style="text-align:justify;"> </p><p style="text-align:justify;"> </p><h3 style="text-align:justify;"><strong>테스트 코드 제목 작성 팁</strong></h3><p style="text-align:justify;">테스트 코드에서 가장 중요한 부분 중 하나는 제목을 올바르게 작성하는 것인데요. 저는 테스트 코드 작성법을 묻는 동료 개발자들에게 책의 목차를 쓰듯 테스트 코드를 작성하라고 조언해 줍니다.</p><p style="text-align:justify;"> </p><figure class="image image_resized" style="width:80%;"><img src="https://yozm.wishket.com/media/news/2435/image2.png"><figcaption>책은 목차만 읽어도 전반적인 내용을 파악할 수 있다. <출처: DALL·E 생성 이미지></figcaption></figure><p style="text-align:justify;"> </p><h4 style="text-align:justify;"><strong>A를 만족하면 B가 도출되는 형식으로 작성하기</strong></h4><p style="text-align:justify;">책에서 목차는 내용만큼이나 중요합니다. 작가가 어떤 내용으로 책을 썼는지 단번에 알 수 있기 때문이죠. 테스트 코드도 마찬가지입니다. 테스트 코드는 ‘테스트 제목만으로 어떤 테스트인지 알 수 있어야’ 합니다. 아무리 좋은 테스트 코드를 작성했다고 해도 제목이 이상하거나 이해하기 힘들다면, 다른 개발자가 같은 주제로 중복된 테스트 코드를 작성할지도 모릅니다.</p><p style="text-align:justify;"> </p><p style="text-align:justify;">그래서 제목은 A를 만족하면 B가 도출되는 형식으로 작성하는 것이 좋습니다. 아래 예시를 통해 살펴볼게요.</p><p style="text-align:justify;"> </p><pre><code class="language-javascript">// Bad test("구매 버튼 클릭", () => { render(<SignUpForm />); const purchaseButton = screen.queryByTestId("data-submit-button")!; const modal = screen.queryByTestId("modal"); expect(modal).not.toBeInDocument(); purchaseButton.click(); expect(modal).toBeInDocument(); })</code></pre><p style="text-align:justify;"> </p><p style="text-align:justify;">위 테스트 코드의 문제점은 무엇일까요? 제목은 구매 버튼을 눌렀음을 알려주지만, 테스트 코드 본문에는 구매 버튼을 누른 뒤 모달이 화면에 띄워졌는지를 검사하고 있습니다. 이처럼 제목이 잘못된 경우, 제목과 본문을 모두 확인해야 어떤 테스트인지 알 수 있어서 피로도가 높아집니다.</p><pre><code class="language-javascript">// Good test("구매 버튼을 클릭하면, 모달을 띄운다", () => { render(<SignUpForm />); const purchaseButton = screen.queryByTestId("data-submit-button")!; const modal = screen.queryByTestId("modal"); expect(modal).not.toBeInDocument(); purchaseButton.click(); expect(modal).toBeInDocument(); })</code></pre><p style="text-align:justify;"> </p><p style="text-align:justify;">위 사례의 제목을 구매 버튼을 클릭하면 모달이 띄워진다고 변경해 보았습니다. 훨씬 더 눈에 잘 들어오지 않나요? 제목만 바꿨을 뿐인데 훨씬 알기 쉬운 테스트가 되었습니다. 아직 테스트 코드 작성이 낯설다면, 우선 제목을 바꾸는 연습부터 해보시길 바랍니다.</p><p style="text-align:justify;"> </p><h4 style="text-align:justify;"><strong>분류별로 나눠서 작성하기</strong></h4><p style="text-align:justify;">테스트 코드를 작성하다 보면, 여러 조건 중 테스트하려는 세부 내용을 제외한 나머지는 같은 경우도 있을 텐데요. 예를 들어, 회원가입 폼을 띄우고 그 안에서 아이디와 비밀번호를 입력하는 각각의 테스트라면 회원가입 폼을 띄우는 것까진 같은 내용이죠. 그래서 테스트 코드 제목을 구체적으로 적다 보면, 제목이 길어져 오히려 가독성을 해치지 않을까 우려되기도 합니다.</p><p style="text-align:justify;"> </p><p style="text-align:justify;">이럴 때는 제목과 연관된 점을 분류별로 나누면 좋습니다. 책의 목차도 챕터가 있고, 각 챕터별로 다시 소제목이 있는 것과 마찬가지로 시각적인 효과를 줄 수 있습니다.</p><p style="text-align:justify;"> </p><pre><code class="language-javascript">// Bad describe("SignUp Page", () => { test("회원가입 폼이 렌더링 될 때, 아이디란이 비어있으면, 버튼이 비활성화되어야 한다", () => { ... }) test("회원가입 폼이 렌더링 될 때, 비밀번호란이 비어있으면, 버튼이 비활성화되어야 한다", () => { … }) })</code></pre><pre><code class="language-javascript">// Good describe("SignUp Page", () => { describe("회원가입 폼이 렌더링 될 때", () => { test("아이디란이 비어있으면, 버튼이 비활성화되어야 한다", () => { ... }) test("비밀번호란이 비어있으면, 버튼이 비활성화되어야 한다", () => { ... }) }) })</code></pre><p style="text-align:justify;"> </p><p style="text-align:justify;">위와 같이 제목을 동일한 분류로 묶어 상위에 작성해 봤습니다. 이처럼 제목을 잘 분류하는 것만으로도 가독성을 개선할 수 있는데요.</p><p style="text-align:justify;"> </p><figure class="image image_resized" style="width:100%;"><img src="https://yozm.wishket.com/media/news/2435/image3.png"><figcaption>1번부터 3번까지 차례대로 읽었을 때 하나의 문장으로 읽히는 것이 좋다. <출처: 요즘 IT></figcaption></figure><p style="text-align:justify;"> </p><p style="text-align:justify;">한 가지 팁을 공유해 볼게요. 테스트 제목의 가장 바깥쪽에 있는 1번부터 들여쓰기가 적용된 차례대로 2, 3번을 순서대로 읽었을 때, 하나의 문장으로 완성될 수 있게 만들면 가독성이 좋아질 수 있습니다.</p><p style="text-align:justify;"> </p><p style="text-align:justify;">(예시)</p><ul><li style="text-align:justify;">SignUp Page, 회원가입 폼이 렌더링 될 때, 아이디란이 비어있으면, 버튼이 비활성화되어야 한다.</li><li style="text-align:justify;">SignUp Page, 회원가입 폼이 렌더링 될 때, 비밀번호란이 비어있으면, 버튼이 비활성화되어야 한다.</li></ul><p style="text-align:justify;"> </p><p style="text-align:justify;">완벽한 문장은 아니더라도 하나의 문장으로 인식할 수 있다면 성공입니다.</p><p style="text-align:justify;"> </p><p style="text-align:justify;"> </p><h3 style="text-align:justify;"><strong>Given-When-Then 법칙 이용하기</strong></h3><p style="text-align:justify;">테스트 코드를 작성할 때 간단하지만 엄청난 효과를 가진 법칙이 있습니다. 바로 ‘Given-When-Then’ 테스트 코드 법칙입니다.</p><p style="text-align:justify;"> </p><figure class="image image_resized" style="width:100%;"><img src="https://yozm.wishket.com/media/news/2435/image1.png"><figcaption>Given-When-Then은 하나의 파이프라인과 같다. <출처: DALL·E 생성 이미지></figcaption></figure><p style="text-align:justify;"> </p><ul><li style="text-align:justify;">Given: 테스트 코드를 작성하기 위해 필요한 변수를 선언하는 준비 과정</li><li style="text-align:justify;">When: 테스트에 필요한 준비물(변수)을 가지고 이를 수행하려는 대상(함수)을 테스트하는 과정</li><li style="text-align:justify;">Then: 수행한 테스트에 관한 결과를 확인하는 과정</li></ul><p style="text-align:justify;"> </p><p style="text-align:justify;">이렇게 3단계로 이뤄진 간단한 법칙만 적용해도, 테스트 코드의 가독성이 놀라울 만큼 좋아질 수 있습니다.</p><p style="text-align:justify;"> </p><pre><code class="language-javascript">// 이렇게 작성해 보세요 describe("calculator", () => { test("3 adds 5 equals 8", () => { // Given - 테스트에 필요한 준비물 생성 const num1 = 3; const num2 = 5; // When - 테스트 대상을 수행 const result = add(num1, num2); // Then - 결과가 올바른지 검증 expect(result).toBe(num1 + num2); }) })</code></pre><p style="text-align:justify;"> </p><p style="text-align:justify;">위 예시처럼 Given, When, Then을 주석과 함께 영역을 분리해 주면 가독성이 높아집니다. 테스트 코드를 작성할 때 기능이 복잡해지면, 코드도 100~200줄을 넘어가는 경우가 많은데요. 이럴 때 영역을 확실하게 나눠 주면 읽기도 쉽고, 나중에 유지보수를 관리하기에도 편합니다.</p><p style="text-align:justify;"> </p><p style="text-align:justify;"> </p><h3 style="text-align:justify;"><strong>테스트 데이터는 난수를 만들어 사용하기</strong></h3><p style="text-align:justify;">대부분 테스트 코드를 작성할 때 예상 가능한 변수나 값을 만들어 사용하는데요. 바로 위에서 살펴본 예시에서도 num1과 num2에 3, 5라는 값을 직접 할당해 테스트했습니다. 그렇다면 add 함수는 임의로 설정한 서로 다른 두 값 A, B에 관한 모든 테스트를 통과할 수 있을까요? 개발자가 테스트 코드를 작성할 때 예상 가능한 값으로만 테스트한다면, 예기치 못한 범위에서 버그가 발생할 확률을 잡아내기 힘들 것입니다. 그래서 되도록 난수를 만들어서 사용하거나, 임의 값을 불러와 사용하는 것이 더 바람직합니다.</p><p style="text-align:justify;"> </p><p style="text-align:justify;">이때 <a href="https://www.npmjs.com/package/@faker-js/faker"><u>faker.js</u></a>를 사용하면 상황별로 적합한 임의 값을 만들 수 있습니다. 테스트에서만 사용한다면 개발 의존성(devdependency)에 패키지를 설치하는 것이 좋습니다.</p><p style="text-align:justify;"> </p><pre><code class="language-javascript">// faker.js 를 사용해 위의 예시를 다시 재구성했습니다. import { faker } from '@faker-js/faker'; describe("calculator", () => { test("A adds B equals A+B", () => { // Given - 테스트에 필요한 준비물 생성 // faker.number.int 는 임의의 정수를 생성합니다. const num1 = faker.number.int(); const num2 = faker.number.int(); // When - 테스트 대상을 수행 const result = add(num1, num2); // Then - 결과가 올바른지 검증 expect(result).toBe(num1 + num2); }) })</code></pre><p style="text-align:justify;"> </p><p style="text-align:justify;">여기서 테스트 제목까지 변경해 주면 더욱 바람직한 테스트가 되겠죠? 이렇듯 faker.js를 사용하면 테스트를 수행할 때마다 임의의 정수를 만들어 함수를 테스트할 수 있습니다. 항상 같은 케이스만 테스트하게 된다면 꼭 활용해 보시기 바랍니다.</p><p style="text-align:justify;"> </p><p style="text-align:justify;"> </p><h3 style="text-align:justify;"><strong>마치며</strong></h3><p style="text-align:justify;">지금까지 어떻게 하면 더 명확하고 가독성 높은 테스트 코드를 작성할 수 있을지 몇 가지 방법을 살펴보았습니다. 이외에도 여러 방법이 있겠지만, 제가 시도해 본 결과 최소한의 노력으로 최대한의 효과를 얻을 수 있었던 방법 위주로 소개해 보았는데요. 이를 참고해 실제 테스트 코드에 적용해 보면서, 여러분도 본인만의 테스트 코드 작성 노하우를 만들어 갈 수 있길 바랍니다.</p><p style="text-align:justify;"> </p><p style="text-align:center;"><span style="color:#999999;">요즘IT의 모든 콘텐츠는 저작권법의 보호를 받는 바, 무단 전재와 복사, 배포 등을 금합니다.</span></p>