WebStorm 대신 VSCode 로 TypeScript 테스트와 디버깅 해보기 (with Jest)

Rachel Kwak (곽소현)
직방 기술 블로그

--

안녕하세요. 직방 BE Platform 팀에서 백엔드 공통 플랫폼 개발/운영 업무를 담당하고 있는 Rachel 이라고 합니다.

JetBrains 의 ‘WebStorm’ 같은 유료 에디터에서는 디버깅이나 테스트 코드를 실행하는 기능이 UI 로 편리하게 제공이 되었는데, Visual Studio Code (이하 ‘VS Code’) 에서는 해당 기능들을 UI 로 쉽게 사용하기가 어려운 점이 있었습니다.

그래서, 이번 기회에 VS Code 로 TypeScript 테스트와 디버깅 할 수 있는 방법을 공유 해 보려고 합니다.

‘WebStorm’ 보다는 세팅이 복잡하다고 느껴지실 수도 있지만, ‘VS Code’ 는 무료 에디터이면서 다른 유료 에디터에 비해 가볍다는 장점이 있기 때문에 충분히 써볼 만한 가치가 있다고 생각합니다.

이 문서를 순서대로 쭉 따라하다보면 여러분도 충분히 VS Code 로 테스트와 디버깅을 하실 수 있으리라 기대합니다.

시작하기 전에

  1. ‘Node.js + TypeScript’ 로 구성된 프로젝트를 기준으로 하며, 이 문서에서는 ‘TypeScript’ 세팅이 이미 되어있는 것을 전제로 합니다.
  2. Test Framework 는 ‘jest’ 를 사용하는 것을 기준으로 하며, 이 문서에서는 ‘jest’ 세팅이 이미 되어있는 것을 전제로 합니다.
    저희는 ‘jest’, ‘@types/jest’, ‘ts-jest’ 를 설치 하여 사용하고 있습니다.
  3. ‘TypeScript’ 를 좀 더 편하게 사용하기 위해서, ‘ts-node’ 와 ‘tsc-watch’ 를 설치하여 사용하고 있습니다.
  4. 이 문서에서는 ‘Lerna’ 등을 통해 Monorepo 를 사용하는 케이스에 대해서도 함께 가이드 하고 있습니다. Monorepo 를 사용하는 경우 설명을 꼭 확인 해 주세요.
  5. ‘tsconfig.json’ 의 ‘compilerOptions’ 세팅 값 중에서 sourceMap: true 로 해야하고, 기존에 세팅되어 있던 sourceRoot, mapRoot 값이 있다면 주석처리 하시면 됩니다.

Monorepo 를 사용하는 경우

Monorepo 를 사용하는 경우에는 각 패키지 마다 jest 구성이 되어있기 때문에, VS Code 의 Multi-root Workspace 를 사용해야 합니다.

이미 Multi-root Workspace 를 사용하고 있거나 Monorepo 를 사용하지 않는 경우에는, 이 단계는 Skip 해 주세요 🙂

아쉽게도 이 문서에서는 VS Code 의 Workspace 에 대한 설명은 따로 없습니다.

VSCode Multi-root Workspace 생성하는 방법

1. File > Save Workspace As… 를 클릭하여 해당 프로젝트를 워크스페이스로 저장합니다.
예를 들어 프로젝트명이 ‘test-proejct’ 라면, test-project.code-workspace 라는 파일이 생성됩니다. 워크스페이스를 생성하기 전(좌측)과 생성한 후(우측)의 차이는 아래와 같습니다.

2. Explorer 영역에서 마우스 우클릭 하여 ‘Add Folder to Workspace’ 를 클릭합니다. 워크스페이스에 원하는 하위 패키지들을 추가합니다.

3. ‘cmd + shift + p’ 를 입력한 다음, ‘Open Workspace Settings (JSON)’ 을 선택합니다. (‘setting’ 라고입력하면 해당 옵션을 찾을 수 있습니다)

‘Workspace Settings’ 에서는 해당 워크스페이스에만 적용되는 속성을 정의할 수 있습니다. JSON 파일의 ‘folders’ 프로퍼티에는 워크스페이스에 추가한 폴더들의 path 가 자동으로 세팅되어 있는데, 특정 폴더의 alias 를 지정하고 싶은 경우에는 ‘name’ 값을 지정합니다.

{
"folders": [
{
"path": "account",
"name": "root" // 폴더 alias 를 지정할 수 있음
},
{
"path": "account/packages/zigbang-account"
},
{
"path": "account/packages/zigbang-account-batch"
},
{
"path": "account/packages/zigbang-account-common"
}
]
}

VSCode Jest Extension 설치

  1. Extensions View 를 클릭합니다.
  2. 검색창에 ‘jest’ 를 입력합니다.
  3. Jest (Use Facebook’s Jest With Pleasure.) Extension 을 설치합니다.

Jest Testing View 세팅

1. ‘cmd + shift + p’ 입력한 다음, ‘Open User Settings (JSON)’ 을 선택 합니다. ‘User Settings’ 에서는 VSCode global 로 적용되는 속성을 정의할 수 있습니다.

2. 프로젝트 Root 경로의 .vscode > settings.json 파일이 열리는데(없으면 생성됨), JSON 에 아래의 값을 추가합니다.

원할 때만 수동으로 테스트를 실행 시키도록 처리하는 옵션인데 (참고 링크), 매번 자동으로 돌리고자 한다면 해당 옵션값을 다른 값으로 세팅 하시면 됩니다.

{
// 기존 값들은 그대로 유지하고, 아래 설정을 추가한다.
"jest.autoRun": "off"
}

3. Monorepo 를 사용하는 경우, 단독 jest 설정이 없는 폴더(예: 최상위 폴더)를 jest 테스트 대상에서 제외 시키려면, JSON 파일의 ‘settings’ 프로퍼티에 아래 내용을 같이 추가합니다.

단, alias 가 지정된 폴더는 실제 폴더명이 아닌 ‘name’ 값을 적어줘야 합니다.

{
"folders": [~~~~~],
"settings": {
"jest.disabledWorkspaceFolders": ["parents", "zigbang-account-common"]
}
}

4. VSCode View 아이콘 중에 ‘비커’ 모양의 Testing 아이콘이 생성된 것을 확인할 수 있습니다. 해당 아이콘을 클릭하면 Testing View 에 아래와 같이 jest 테스트 파일 리스트가 표시 됩니다.

5. 주요 기능은 아래와 같습니다.
(TC 타이틀 우측의 아이콘 혹은 우클릭 메뉴)

  • Run Test — 테스트 실행
  • Debug Test — Debug 모드로 테스트 실행
    (해당 기능이 제대로 동작하지 않는다면, 문서 가장 하단의 ‘TroubleShooting’ 항목을 참고 해주세요)
  • Go to Test — 해당 테스트 파일로 이동

6. Testing View 에서 테스트 목록이 제대로 로딩되지 않는다면, 문서 가장 하단의 ‘TroubleShooting’ 항목에 해당하는 케이스가 있는지 참고 해주세요.

Testing View 에서 Test 실행 하기

기본설정 확인

launch.json 에 별도의 설정을 추가 하지 않은 상태라면, 아래의 설정값을 기본으로 사용합니다.

[info] auto config:

found:
rootPath: /Users/hongildong/repository/test-project // 해당 프로젝트 경로
jestCommandLine: yarn test

[info] auto config debug config:
{
"type": "node",
"name": "vscode-jest-tests.v2",
"request": "launch",
"args": [
"test",
"--runInBand",
"--watchAll=false",
"--testNamePattern",
"${jest.testNamePattern}",
"--runTestsByPath",
"${jest.testFile}"
],
"cwd": "/Users/hongildong/repository/test-project", // 해당 프로젝트 경로
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"disableOptimisticBPs": true,
"runtimeExecutable": "yarn"
}

기본 설정에 따라 pacakge.json 에 ‘test’ 스크립트가 기본적으로 선언되어 있어야 하며, 그렇지 않은 경우에 오류가 발생 합니다.

만약에 해당 스크립트가 선언되어 있지 않다면, pacakge.json 에 아래와 같이 추가 합니다.

{
"scripts": {
"test": "npx jest" // jest option 함께 사용해도 무방합니다.
}
}

launch.json 세팅

위의 기본설정 만으로도 테스트가 동작한다면 이번 단계는 skip 하셔도 됩니다.

pacakge.json 에서 ‘test’ 스크립트를 추가하거나 기존 ‘test’ 스크립트를 수정할 수 없는 경우에는, 아래와 같이 VSCode 의 launch.json 정보를 수정합니다.

[단독 프로젝트인 경우]

1. ‘cmd + shift + p’ 를 입력한 다음, ‘Open Workspace Settings (JSON)’ 을 선택합니다.

2. ‘settings.json’ 파일에 아래와 같이 세팅한 다음 저장합니다.

{
"launch": {
"version": "0.2.0",
"configurations": [
// 기존에 있던 설정값은 그대로 유지하고, 아래 설정값 추가
{
"type": "node",
"name": "vscode-jest-tests.v2", // 이름은 반드시 이걸로 해야 함!
"request": "launch",
"program": "${workspaceFolder}/node_modules/.bin/jest",
"args": [
"--runInBand",
"--watchAll=false",
"--testNamePattern",
"${jest.testNamePattern}",
"--runTestsByPath",
"${jest.testFile}"
],
"cwd": "${workspaceFolder}",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"runtimeExecutable": "node"
}
]
}
}

3. 다시 ‘Debug Test’ 를 실행 합니다.

[Monorepo 사용하는 경우]

1. 해당 패키지 ‘.vscode’ 폴더 하위에 ‘launch.json’ 파일을 생성합니다. (기존에 파일이 생성되어 있었으면 해당 파일을 열어주세요)

2. ‘launch.json’ 파일에 ‘configurations’ 프로퍼티에 아래와 같이 설정값을 추가한 다음 저장합니다.

// 예시) package 이름이 account-batch 일 때
// 파일 경로: packages/account-batch/.vscode/launch.json
{
"version": "0.2.0",
"configurations": [
// 기존에 있던 설정값은 그대로 유지하고, 아래 설정값 추가
{
"type": "node",
"name": "vscode-jest-tests.v2", // 이름은 반드시 이걸로 해야 함!
"request": "launch",
"program": "${workspaceFolder}/node_modules/.bin/jest",
"args": [
"--runInBand",
"--watchAll=false",
"--testNamePattern",
"${jest.testNamePattern}",
"--runTestsByPath",
"${jest.testFile}"
],
"cwd": "${workspaceFolder}",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"runtimeExecutable": "node"
}
]
}

3. 다시 ‘Debug Test’ 를 실행 합니다.

jest config 세팅

jest.config.js 파일을 열어서 ‘testMatch’ 값을 확인한 후, 본인 환경에 맞게 세팅합니다.

module.exports = {
............

rootDir: ".",
// 예시) test 폴더 하위의 ***.test.ts 또는 ***.spec.ts 파일만 테스트 하고자 하는 경우
testMatch: ["<rootDir>/test/**/*(*.)@(spec|test).ts"],

............
};

Run Test 해보기

1. ‘Testing View’ 에서 실행을 원하는 테스트를 선택하여 Run Test 를 실행합니다.

  • 가장 왼쪽의 Run Test 버튼을 클릭하거나, 우클릭 하여 Run Test 를 선택하면 됩니다.
  • 전체 테스트를 실행하거나, 특정 테스트 파일만 실행하거나, 특정 테스트 파일 안의 특정 테스트만 선택적으로 실행할 수도 있습니다.

2. 테스트를 실행하면 ‘Testing View’ 와 ‘Jest Terminal’ 에서 아래와 같이 성공/실패 결과를 확인할 수 있습니다.

<TC 예시>

Debug Test 해보기

1. 디버깅 하고자 하는 테스트 케이스에 ‘Breakpoint’ 를 겁니다. 테스트 파일에서 줄 번호 좌측을 클릭하여 빨간 원이 생기면 됩니다.

2. ‘Testing View’ 에서 해당 테스트를 선택하여 Debug Test 를 실행합니다.

3. ‘Run and Debug View’ 에서 해당 ‘Breakpoint’ 에 걸린 것을 확인하고, 디버깅을 하면 됩니다.

4. 만약에 Debug Test 버튼을 클릭 했을 때 오류가 발생한다면, 문서 가장 하단의 ‘TroubleShooting’ 항목을 참고 해주세요.

Run And Debug View 에서 Debug 실행 하기

VS Code 에서 기본으로 제공하는 ‘Run And Debug View’ 를 이용하여 특정 파일의 로직을 디버깅 할 수 있습니다. (이후로는 ‘Debug View’ 로 지칭)

launch.json 세팅

1. ‘Run And Debug View’ 에서 ‘create a launch.json file’ 링크를 클릭 합니다.

Monorepo 를 사용하는 경우에는 아래와 같이 ‘Multi-Root Workspace’ 상에서 어떤 폴더의 launch.json 을 생성할 것인지 선택해야 합니다.

이미 launch.json 에 정의가 되어 있거나 기존에 launch 정보를 세팅한 적이 있는 경우에는 ‘Debug View’ 에 아래와 같이 보여집니다.

2. launch.json 파일에 아래 예시를 참고하여 각자 환경에 맞게 변경하여 입력 합니다.

‘command’ 나 ‘runtimeArgs’ 등은 본인의 환경에 맞게 변경하셔서 사용하시면 되고, ‘configurations’ 의 각 JSON 프로퍼티에 대한 자세한 설명은 링크에서 확인 하시면 됩니다.

아래의 예시는 ‘ts-node’, ‘tsc-watch’ 패키지가 설치 되어 있는 경우를 함께 고려하여 작성 되었습니다.

// command, runtimeArgs, args 등은 본인의 환경에 맞게 변경하셔서 사용하시면 됩니다.
// 예시)
// - dist 값과 App.ts 값을 각자 환경에 맞게 변경하여 사용하면 됩니다!
// - tsconnfig 에서 compilerOptions 의 outDir 값: dist
// - 실행하려는 메인 파일: src/App.ts
{
"version": "0.2.0",
"configurations": [
{
// 1. node 기본 명령어로 실행하는 방법
"name": "Launch via basic node",
"type": "node-terminal",
"request": "launch",
"command": "rm -rf ./dist && npx tsc -p tsconfig.json && node dist/src/App.js"
},
{
// 2. ts-node 를 통해 실행하는 방법
"name": "Launch via ts-node",
"type": "node",
"request": "launch",
"args": [
"${workspaceFolder}/src/App.ts"
],
"runtimeArgs": [
"-r",
"ts-node/register"
],
"console": "integratedTerminal",
"skipFiles": ["<node_internals>/**"],
"runtimeExecutable": "node"
},
{
// 3. tsc-watch 를 통해 watch 모드로 실행하는 방법
"name": "Launch via tsc-watch",
"type": "node-terminal",
"request": "launch",
"command": "rm -rf ./dist && npx tsc-watch --onSuccess \"node dist/src/App.js\""
},
{
// 4. npm script 를 통해 실행하는 방법
// 단, 'dev' 라는 script 가 package.json 에 선언되어 있어야 함
"name": "Launch via npm",
"type": "node",
"request": "launch",
"skipFiles": ["<node_internals>/**"],
"console": "integratedTerminal"
"runtimeExecutable": "npm",
"runtimeArgs": ["run-script", "dev"]
}
]
}

launch.json 파일을 세팅하면 아래와 같이 ‘Debug View’ 의 Select Box 에서 원하는 테스트 옵션을 선택할 수 있습니다.

Debug 실행하기

1. 디버깅 하려는 위치에 줄 번호 왼쪽 영역을 클릭하여, 빨간 점으로 표시되는 ‘Breakpoint’ 를 찍습니다.

2. ‘Debug View’ 에서 원하는 테스트 옵션을 선택한 다음에, Starting Debugging 버튼을 클릭 하거나 F5키를 눌러서 디버깅을 실행합니다.

3. ‘Variables’, ‘Watch’, ‘Call Stack’ 과 같은 기본적인 디버깅 기능들을 사용할 수도 있습니다.

4. 만약에 ‘Breakpoint’ 가 제대로 걸리지 않는 경우에는, 디버깅을 종료한 후 컴파일을 다시 한 다음에 다시 디버깅을 시도 해 주세요.
(컴파일 된 파일이 tsconfig.json 의 ‘outDir’ 경로에 제대로 생성 되었는지 확인)

5. 그래도 안된다면, tsconfig.json 의 ‘compilerOptions’ 세팅 값이 sourceMap: true 로 되어있는지, sourceRoot, mapRoot 값이 주석처리 되어 있는지 확인 합니다.

6. 일반 ‘Breakpoint’ 대신에 우클릭 메뉴에서 ‘Conditional Breakpoint’ 를 추가할 수도 있습니다. ‘Expression’ 이나 ‘Hit Count’ 조건을 추가하거나 ‘Log Message’ 를 추가할 수도 있습니다.

해당 옵션에 대한 자세한 내용은 공식 문서를 참고 하시면 됩니다.

Trouble Shooting

Q1. Jest Extension 을 설치 했는데도 비커 모양의 Testing View 아이콘이 나타나지 않는다면?

  • ‘jest’ 가 테스트 파일들을 제대로 로딩하지 못하여 발생하는 문제 입니다.
  • settings.json 에 ‘jest.rootPath’ 가 올바르게 지정되어야만, ‘비커’ 모양의 Testing 아이콘이 생성 됩니다.
  • Monorepo 를 사용하는 경우에는 ‘Multi-Root Workspace’ 를 사용해야 정상적으로 사용이 가능합니다.

Q2. Testing View 에서 테스트 목록이 제대로 로딩이 되지 않는다면?

[해당 패키지를 컴파일 (tsc) 했는지 확인]

  • 해당 패키지 컴파일에 성공한 후에는 VS Code 를 Reload 해주세요.

[jest.config.js의 ‘testMatch’ 값을 제대로 작성 했는지 확인]

  • ‘testMatch’ 정규식이 올바르지 않으면 테스트 코드를 제대로 로딩하지 못할 수 있습니다. 올바르게 수정한 후 VS Code 를 Reload 해주세요.

[@testdeck/jest 을 사용하는 경우]

  • 해당 케이스 일 때는, Testing View 에서 테스트 파일명 까지만 나오고 하위의 각 테스트들은 출력되지 않을 수 있습니다.
  • 이 경우에는 해당 파일에서 Run Test 를 실행하면 하위의 테스트 항목들이 함께 출력됩니다.

[Lerna 와 같이 Monoropo 를 사용하는 경우]

  • 해당 케이스 일 때는, ‘jest.rootPath’ 가 명확하지 않기 때문에 Testing 아이콘이 나타나지 않을 수 있습니다.
  • 이 문서 제일 상단의 ‘Monorepo 를 사용하는 경우’ 항목을 참고 해주세요.

Q3. Testing View 에서 ‘Debug Test’ 실행 했는데 오류가 발생한다면?

[Can’t find Node.js binary “node” 오류]

Can’t find Node.js binary “node”: path does not exist. Make sure Node.js is installed and in your PATH, or set the “runtimeExecutable” in your launch.json

1. ‘F1 (혹은 cmd + shift + p)’ 를 입력한 다음, ‘Install ‘code’ command in PATH’ 를 실행 합니다.

2. VSCode 를 종료 합니다.

3. 터미널에서 ‘code’ 명령어를 사용하여 해당 프로젝트를 다시 실행 합니다.

# 예시 1) 단독 프로젝트 일 때
# repository 폴더에 test-project 프로젝트가 존재하는 상황

cd repository/test-project
code .
# 예시 2) monorepo 를 사용하는 경우
# repository 폴더에 test-project.code-workspace 가 존재하는 상황

cd repository
code test-project.code-workspace

4. 다시 ‘Debug Test’ 를 실행 합니다.

[Command “test” not found 오류]

error Command “test” not found. Did you mean “nest”? info Visit https://yarnpkg.com/en/docs/cli/run for documentation about this command.

  1. 문서 상단의 ‘Testing View 에서 Test 실행 하기 > 기본설정 확인’ 항목을 참고하여, ‘package.json’ 에 ‘test’ 스크립트를 세팅 합니다.
  2. ‘test’ 스크립트를 추가할 수 없거나 기존 ‘test’ 스크립트를 수정할 수 없는 경우에는, 문서 상단의 ‘Testing View 에서 Test 실행 하기 > launch.json 세팅’ 항목을 참고하여 ‘launch.json’ 정보를 수정합니다.

마치며

코드의 품질을 높이기 위해서는 다양한 테스트 시나리오를 통해 충분히 검증을 거쳐야 하는데, 디버깅과 테스트 코드 실행을 쉽게 수행할 수 있으면 검증의 효율을 높이고 나아가 코드의 품질을 높일 수 있을 것이라고 생각 합니다.

이 문서에서 가이드 하는 방법이 여러분들의 개발환경에 따라 그대로 통하지 않을 수도 있지만, VS Code 에서 디버깅과 테스트 실행환경을 세팅 하는 데 조금이나마 도움이 되기를 바랍니다.

--

--