For the complete documentation index, see llms.txt. This page is also available as Markdown.

테스트 작성

테스트는 다양한 방식으로 작성할 수 있습니다. 이 섹션에서는 테스트를 작성하는 방식에 대한 표준과 그 근거를 제시하려고 합니다.

테스트는 반드시 다음을 사용하여 작성해야 합니다 describe 그리고 테스트 jest가 제공하는 메서드

컨텍스트 설명 및 구성

이 describe 메서드는 가능하다면 테스트할 코드가 실행될 컨텍스트를 설명하는 데 사용해야 하며, 그 컨텍스트를 자신의 범위 안에서 구성해야 합니다.

describe('플래그가 빨간색일 때', () => {
	...
})

describe('플래그가 파란색일 때', () => {
	...
})

컨텍스트를 설명하기 위해, 다음 단어 중 하나를 사용해야 합니다: 일 때 최상위 describe와 가지고 있는 또는 및 그 이전에 정의된 다른 컨텍스트에 의존하는 컨텍스트가 있음을 나타내기 위해 사용합니다. 이에 대한 근거는 describe 문장을 결합하여 쉽게 이해하고 확인할 수 있는 자기 설명적인 컨텍스트를 갖기 위함입니다. 아이디어는 컨텍스트 설명을 연결하는 것이므로, describe 구문은 반드시 소문자로 작성해야 합니다.

describe('플래그가 빨간색일 때', () => {
	...
	describe('바람이 강할 때', () => {
     // 여기서 컨텍스트는 describe들의 결합으로 설명됩니다:
     // "플래그가 빨간색이고 바람이 강할 때"
     ...
  })
})

여러 describe는 같은 수준과 더 낮은 수준에서 중첩될 수 있습니다. 같은 수준의 describe는 서로 다른 컨텍스트를 나타내고, 더 낮은 수준의 describe(중첩된 describe)는 더 구체적인 컨텍스트를 나타냅니다.

앞서 언급했듯이, 각 describe에는 컨텍스트를 구성하는 메서드나 컨텍스트를 파괴하거나 변경하는 메서드가 함께 있어야 합니다. 반드시 사용해야 하는 메서드는 다음과 같습니다: beforeEach 그리고 afterEach.

다음으로 생성된 컨텍스트는 beforeEach 메서드를 사용할수록 describe 트리를 더 깊게 내려가며 점점 더 구체적으로 정의됩니다. 각 beforeEach 는 자신의 텍스트가 말하는 바에 따라 컨텍스트를 더 구체적으로 지정합니다.

변수 범위

이 변수들 컨텍스트에서 설정된 값은 사용될 범위에 맞게 정의되어야 합니다. 즉, 변수 하나가 describe의 중첩된 수준에서 특정 컨텍스트에만 사용된다면, 그 변수는 해당 특정 컨텍스트에만 정의되어야 합니다. 이에 대한 근거는 변수를 사용되는 코드 가까이에 두어 코드를 더 이해하기 쉽게 만들기 위함입니다.

의 원시 타입, 즉 변경되지 않을 컨텍스트나 이후 컨텍스트에서 사용될 경우 const 를 사용하여 한 번, beforeEach 범위 내 정의보다.

의 원시 타입들 컨텍스트나 이후 컨텍스트에서 변경될 것은 다음과 같이 정의되어야 합니다: let이는 TypeScript의 특성상 필수입니다.

의 비원시 타입 (객체, 배열 등)은 다음과 같이 정의되어야 합니다: let 그리고 그 값은 다음에서 설정되어야 합니다 beforeEach. 이에 대한 근거는 JS의 객체가 변경 가능(mutable)하다는 점입니다. 즉, 해당 객체를 사용하는 코드의 실행은 변경의 영향을 받을 수 있고, 의도치 않게 다른 테스트에 영향을 줄 수 있습니다.

변수는 가능하다면 올바른 타입으로 지정해야 합니다. 반복되는 타입은 타입으로 추상화해야 합니다.

기대 사항 설명과 코드 실행

이 테스트 메서드는 항상 하나의 describe 안에 배치되어야 하며, 우리가 테스트할 코드에서 무엇을 기대하는지 설명하는 데 사용되어야 하고, 가능하다면 오직 하나의 어설션만 포함해야 합니다. 각 테스트 당 여러 개의 어설션이 있을 수 있는 경우는 성능 문제가 있을 때입니다. 테스트는 각 테스트 (때문에 beforeEach), 또는 기대되는 내용을 기대 설명에서 명확하게 설명할 수 있을 때입니다.

이 구조에 대한 근거는 테스트를 검토하는 사람과 코드를 유지보수하고 수정할 개발자에게 명확성을 제공하기 위함입니다. 각 컨텍스트와 기대가 명확하게 열거되므로, 무엇을 테스트하는지, 어떻게 테스트하는지, 그리고 무엇이 아직 테스트되지 않았는지 이해하기 쉬워집니다.

다음의 describe 설명을 따라 테스트가면 개발자는 문장을 연결하여 무엇이 테스트되는지 쉽게 이해할 수 있습니다.

명확한 기대 작성

다음에 작성된 기대 설명은 테스트는 테스트 실행에서 무엇을 기대하는지에 대해 가능한 한 가장 구체적이어야 합니다. 개발자는 기대 내용을 정의할 때 추상적이거나 일반적인 표현을 사용해서는 안 되며, 이는 코드에서 무엇이 기대되는지에 대한 명확성을 떨어뜨립니다.

무엇이 테스트에서 기대되는지 또는 컨텍스트가 무엇인지 지정할 때 describe에서 개발자는 의도를 더 잘 이해하기 위해 필요하다면 함수 이름이나 정확한 오류 메시지를 사용할 수 있지만, 테스트를 더 쉽게 유지보수할 수 있도록 가능한 경우 텍스트 표현을 사용해야 합니다.

무엇을 테스트할 것인가

무엇을 테스트할지는 실행되는 코드에 따라 달라질 수 있습니다. 성능이나 입력 도메인의 크기와 같은 다양한 요인이 테스트에서 무엇을 테스트해야 하거나 하지 말아야 하는지를 분명히 바꿀 수 있습니다. 여기서는 가능하다면 개발자가 테스트해야 하는 하나의 케이스 집합을 제시합니다.

여기의 run 함수는 몇 가지 서로 다른 실행 흐름을 가지고 있습니다. 함수나 코드의 일부는 가능한 다양한 실행 흐름만을 기준으로 테스트되어서는 안 되며, 함수에서 기대되는 바를 기준으로 테스트되어야 합니다. 함수가 원래 목적대로 동작하지 않을 수도 있고, 테스트가 코드와 지나치게 결합되어 다른 문제를 잡아내지 못할 수도 있기 때문입니다. 이는 개발자가 항상 가능한 모든 실행 경로를 테스트해야 하며, 함수의 의미에 따라 다른 가능한 경로도 테스트해야 함을 뜻합니다.

이 특정 경우에는 개발자가 적어도 다음 사례들을 테스트해야 합니다:

  1. 1000킬로미터를 초과하는 양의 킬로미터로 run 함수를 실행하는 경우

  2. 10킬로미터와 같은 양으로 run 함수를 실행하는 경우

  3. 10킬로미터보다 크지만 1000킬로미터보다 작은 양으로 run 함수를 실행하는 경우

첫 번째 경우에는 개발자가 run 함수가 예외를 던지는지 테스트해야 합니다. 예외는 반드시 오류 메시지로 확인해야 합니다, 다른 예외도 던져질 수 있어 테스트의 목적을 무효화할 수 있기 때문입니다. 예외가 사용자 정의 예외라면, 개발자는 해당 예외의 인스턴스를 확인해도 됩니다.

두 번째 경우에는 함수가 전달받은 킬로미터 수와 동일한 값을 반환하는지 테스트해야 합니다.

세 번째 경우에는 함수가 외부 함수인 beLazy 가 반환한 값을 반환하는지 테스트해야 하며, doSomething (메서드에서도 실행됨)를 함수의 반환값을 통해 확인할 수 없으므로, 개발자는 올바른 인수로 호출되었는지 테스트해야 합니다.

무엇을 mock할 것인가

무엇을 mock할지는 주로 개발자가 작성하는 테스트의 유형에 따라 달라집니다.

  • 단위 테스트는 문자열 포맷팅 같은 단순한 작업을 수행하는 함수 등을 제외하고 모든 외부 함수를 mock해야 합니다.

  • API 테스트는 외부 서비스와 통신하는 mock만 있어야 합니다. 즉 DB나 다른 API입니다. 테스트에서 수행되는 작업 중 하나가 테스트 스위트의 성능에 영향을 준다면, 이 문제를 완화하기 위해 mock을 구현할 수 있습니다.

모든 mock은 Jest가 제공하는 도구를 사용해 만들어야 합니다. 단, redux-saga-test-plan mock들.

Mock과 유틸리티 함수

  • 모든 Jest mock은 가능하다면 다음의 once 메서드를 사용해 mock해야 합니다. 즉, mockReturnValueOnce 또는 mockResolvedValueOnce 는 권장되지 않습니다 mockReturnValue 또는 mockResolvedValue. 이에 대한 근거는 원치 않는 mock이 실행되어 테스트의 실행을 바꾸는 것을 방지하기 위함입니다.

  • Jest는 다양한 종류의 mock에 사용할 수 있는 여러 타입을 제공합니다. 예를 들어 객체를 mock할 때는 jest.Mocked<typeof someObject>, 클래스를 mock할 때는 jest.MockedClass<typeof SomeClass>, 함수를 mock할 때는 jest.MockedFunction<typeof someFunction>.

  • 하나의 afterEach 는 각 테스트가 끝난 뒤 실행되도록 작성해야 하며, jest.resetAllMocks 을 사용해 전역적으로 mock된 모듈의 mock 구현이 다른 테스트로 새어 나갈 수 있는 것을 지워야 합니다. 다음을 사용하고 있다면 이 초기화는 무시해도 됩니다. mockReturnValueOnce 또는 mockResolvedValueOnce 자동으로 처리되기 때문입니다.

  • 다음과 같은 디렉터리를 만들 수 있습니다: mocks mock을 저장하기 위해 만들 수 있으며, 이들은 test 또는 spec 디렉터리에 배치해야 합니다. 큰 mock은 확장된 테스트 파일을 피하기 위해 테스트와 다른 파일에 저장해야 합니다. 작은 mock은 많지 않다면 테스트 안에 두는 것이 좋습니다.

    • Mock 파일은 mock하는 대상의 이름으로 이름 짓는 것이 좋습니다. 예를 들어 프로필을 mock한다면, mock은 다음 아래에 두어야 합니다. /test/mocks/profile.ts 파일.

    • 여러 개의 큰 mock이 필요하다면, mock할 대상의 이름을 딴 디렉터리 안에 각각 다른 파일로 두어야 합니다. 예를 들어 프로필 mock이 두 개 있다면 다음과 같이 저장합니다: /test/mocks/profile/profile-with-wearables.ts 및 /test/mocks/profile/profile-without-wearables.ts. 쉽게 접근할 수 있도록, index.ts 파일을 다음 안에 만들고 /test/mocks/profile/ 디렉터리에서 내보내야 합니다.

    • mock된 객체의 변이를 피하기 위해, mock은 함수로 내보내야 하며 그 함수가 그것을 반환하도록 해야 합니다.

마지막 업데이트