이 프로젝트의 목표는 다음을 모두 수행할 수 있는 TypeScript 프로젝트를 만드는 것입니다.
jest
와 ts-jest
사용하기 이것을 npm
프로젝트로 초기화하는 것으로 시작합니다.
$ yarn init .
그런 다음 typescript
, jest
, ts-jest
및 @types/jest
종속 항목으로 설치합니다.
$ yarn add -D typescript jest ts-jest @types/jest
이 글을 쓰는 시점에서는 [email protected]
, [email protected]
및 [email protected]
의미합니다.
다음으로 다음을 사용하여 이를 TypeScript 프로젝트로 초기화합니다.
$ npx tsc --init .
TypeScript 생성 코드를 ./lib
에 저장하고 선언을 생성하고 싶습니다. 따라서 tsconfig.json
의 outDir
./lib
로 구성합니다.
내 .gitignore
는 다음과 같이 구성됩니다.
/node_modules
/lib
...내 .npmignore
다음과 같습니다.
/node_modules
같은 이유로 tsconfig.json
에서 files
의 기본값을 제거하고 다음으로 바꿉니다.
"exclude" : [ " node_modules " , " lib " ]
시작하려면 간단한 함수가 포함된 src/index.ts
를 만듭니다.
export function sampleFunction ( x : string ) : string {
return x + x ;
}
또한 간단한 jest
테스트도 추가합니다. 나는 테스트를 완전히 별도의 위치에 보관하는 것을 선호하므로 모든 테스트를 __tests__
에 배치하겠습니다. 그래서 __tests__/base.spec.ts
에 다음 테스트 케이스를 생성합니다.
import { sampleFunction } from "../src" ;
describe ( "This is a simple test" , ( ) => {
test ( "Check the sampleFunction function" , ( ) => {
expect ( sampleFunction ( "hello" ) ) . toEqual ( "hellohello" ) ;
} ) ;
} ) ;
이 시점에서 해당 테스트를 실행하고 싶습니다. 하지만 먼저 모든 jest
설정에 대한 jest.config.js
파일을 만들어야 합니다. 이는 내가 ts-jest
사용하고 있다는 사실과 내 테스트가 __tests__
에 저장되어 있다는 사실을 고려해야 합니다. 결과 파일은 다음과 같습니다.
module . exports = {
transform : {
"^.+\.tsx?$" : "ts-jest" ,
} ,
testRegex : "(/__tests__/.*|(\.|/)(test|spec))\.(jsx?|tsx?)$" ,
moduleFileExtensions : [ "ts" , "tsx" , "js" , "jsx" , "json" , "node" ] ,
} ;
그런 다음 package.json
에 다음 스크립트를 추가합니다.
"scripts" : {
"compile" : " tsc " ,
"test" : " jest "
}
이 시점에서 yarn test
실행하면 내가 기대했던 결과를 정확하게 얻을 수 있습니다.
PASS __tests__/base.spec.ts
This is a simple test
✓ Check the sampleFunction function (3ms)
Test Suites: 1 passed, 1 total
Tests: 1 passed, 1 total
코드 적용 범위를 활성화하려면 jest.config.js
파일을 다음과 같이 업데이트합니다.
module . exports = {
transform : {
"^.+\.tsx?$" : "ts-jest" ,
} ,
testRegex : "(/__tests__/.*|(\.|/)(test|spec))\.(jsx?|tsx?)$" ,
moduleFileExtensions : [ "ts" , "tsx" , "js" , "jsx" , "json" , "node" ] ,
collectCoverage : true ,
} ;
또한 버전 제어나 jest
에 의해 생성된 coverage
디렉터리 게시를 방지하기 위해 .gitignore
및 .npmignore
파일을 업데이트하고 싶습니다.
이제 내 프로젝트에 하위 모듈을 소개하기 시작하겠습니다. 그래서 저는 src/core
와 src/utils
모듈을 추가하여 좀 더 현실적으로 만들겠습니다. 그런 다음 src/index.ts
다음과 같이 보이도록 이 두 가지의 내용을 모두 내보냅니다.
export * from "./core" ;
export * from "./utils" ;
그런 다음 다양한 유형과 기능이 포함된 특정 파일을 가져옵니다. 처음에는 리터럴과 이진 연산 +
, -
, *
및 /
만 사용하여 매우 간단한 표현식을 표현하기 위한 매우 간단한 유형 세트를 만들 것입니다. 그런 다음 다음과 같은 몇 가지 테스트를 작성할 수 있습니다.
import { evaluate , Expression } from "../src" ;
describe ( "Simple expression tests" , ( ) => {
test ( "Check literal value" , ( ) => {
expect ( evaluate ( { type : "literal" , value : 5 } ) ) . toBeCloseTo ( 5 ) ;
} ) ;
test ( "Check addition" , ( ) => {
let expr : Expression = {
type : "binary" ,
operator : "+" ,
left : {
type : "literal" ,
value : 5 ,
} ,
right : {
type : "literal" ,
value : 10 ,
} ,
} ;
expect ( evaluate ( expr ) ) . toBeCloseTo ( 15 ) ;
} ) ;
} ) ;
지금까지는 너무 좋았습니다. 그러나 실제로 이러한 테스트를 실행하면 다음과 같은 결과가 나타납니다.
PASS __tests__/base.spec.ts
Simple expression tests
✓ Check literal value (4ms)
✓ Check addition
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 2.048s
Ran all test suites.
---------------|----------|----------|----------|----------|----------------|
File | % Stmts | % Branch | % Funcs | % Lines |Uncovered Lines |
---------------|----------|----------|----------|----------|----------------|
All files | 66.67 | 37.5 | 50 | 66.67 | |
src | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
src/core | 61.54 | 37.5 | 100 | 61.54 | |
functions.ts | 54.55 | 37.5 | 100 | 54.55 | 14,16,18,20,25 |
index.ts | 100 | 100 | 100 | 100 | |
src/utils | 66.67 | 100 | 0 | 66.67 | |
checks.ts | 50 | 100 | 0 | 50 | 2 |
index.ts | 100 | 100 | 100 | 100 | |
---------------|----------|----------|----------|----------|----------------|
코드 적용 범위가 부족하다는 점에 유의하세요. /* istanbul ignore ... */
주석과 함께 몇 가지 테스트 사례를 추가하여 istanbul
안전하게 무시할 수 있는 내용을 알려면 다음과 같은 결과를 얻을 수 있습니다.
PASS __tests__/base.spec.ts
Simple expression tests
✓ Check literal value (3ms)
✓ Check addition
✓ Check subtraction
✓ Check multiplication (1ms)
✓ Check division
Test Suites: 1 passed, 1 total
Tests: 5 passed, 5 total
Snapshots: 0 total
Time: 1.353s
Ran all test suites.
---------------|----------|----------|----------|----------|----------------|
File | % Stmts | % Branch | % Funcs | % Lines |Uncovered Lines |
---------------|----------|----------|----------|----------|----------------|
All files | 100 | 100 | 100 | 100 | |
src | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
src/core | 100 | 100 | 100 | 100 | |
functions.ts | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
src/utils | 100 | 100 | 100 | 100 | |
checks.ts | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
---------------|----------|----------|----------|----------|----------------|
이제 테스트를 실패하도록 변경하면 다음과 같은 결과가 나타납니다.
● Simple expression tests › Check division
expect(received).toBeCloseTo(expected, precision)
Expected value to be close to (with 2-digit precision):
1
Received:
2
19 | test("Check division", () => {
20 | let expr = bin("/", 10, 5);
> 21 | expect(evaluate(expr)).toBeCloseTo(1);
22 | });
23 | });
24 |
at Object.<anonymous> (__tests__/base.spec.ts:21:32)
Test Suites: 1 failed, 1 total
Tests: 1 failed, 4 passed, 5 total
Snapshots: 0 total
Time: 1.535s
Ran all test suites.
---------------|----------|----------|----------|----------|----------------|
File | % Stmts | % Branch | % Funcs | % Lines |Uncovered Lines |
---------------|----------|----------|----------|----------|----------------|
All files | 100 | 100 | 100 | 100 | |
src | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
src/core | 100 | 100 | 100 | 100 | |
functions.ts | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
src/utils | 100 | 100 | 100 | 100 | |
checks.ts | 100 | 100 | 100 | 100 | |
index.ts | 100 | 100 | 100 | 100 | |
---------------|----------|----------|----------|----------|----------------|
스택 트랙이 올바른지 확인하십시오. 이는 TypeScript 코드의 문제를 나타냅니다.
package.json
에 compile
스크립트를 추가했음을 기억하세요. yarn compile
사용하여 코드를 컴파일할 수 있습니다. 그렇게 하면 lib
디렉토리가 src
및 __tests__
두 개의 하위 디렉토리로 채워지는 것을 볼 수 있습니다.
그러나 해당 디렉토리를 살펴보면 생성된 Javascript 코드만 포함되어 있음을 알 수 있습니다. 유형 정의는 포함되지 않습니다. 다른 TypeScript 사용자가 코드에 추가한 모든 유형 정보의 이점을 누릴 수 있도록 유형 정의( .d.ts
파일)를 생성하려면 tsconfig.json
파일의 declaration
필드를 true
로 설정해야 합니다.
또한 다른 사람들이 이 패키지를 NPM 모듈로 사용하려면 package.json
의 main
필드를 lib/src/index.js
로 설정해야 합니다. 또한 다른 사람이 이 모듈의 유형에 액세스할 수 있도록 하려면 package.json
의 typings
필드를 lib/src/index.d.ts
로 설정해야 합니다. 다시 말해서,
"main" : " lib/src/index.js " ,
"typings" : " lib/src/index.d.ts " ,
올바르게 구성되면 node
세션을 시작하고 새 패키지를 가져올 수 있습니다.
$ node
> var me = require( " . " )
undefined
> me
{ evaluate: [Function: evaluate],
assertNever: [Function: assertNever] }
>
이제 다음 설정을 포함하도록 jest.config.js
업데이트하세요. 그렇지 않으면 jest
lib/__tests__
디렉터리의 코드와 일치하기 시작합니다.
testPathIgnorePatterns: ["/lib/", "/node_modules/"],
마지막으로 디버깅에 들어갑니다. 저는 Visual Studio Code를 사용하고 있으므로 여기서 디버깅 작업을 수행하는 방법을 보여 드리겠습니다. 이 정보 중 일부는 다른 IDE로 잘 변환될 수 있습니다.
VSCode에서는 디버깅 사이드바로 이동할 수 있습니다. 처음에는 "재생" 버튼 옆에 "구성 없음"이라는 단어가 표시됩니다. 이를 클릭하면 "구성 추가..." 옵션이 있는 풀다운 메뉴가 나타납니다.
제가 TypeScript를 좋아하는 만큼 디버깅은 정말 아킬레스건입니다. 디버깅을 할 수 없다는 것이 아니라 작업을 시작하기가 어렵다는 것입니다. "구성 추가..."를 선택한 다음 "Node.js"를 선택하면 mocha
에 대한 구성을 포함하여 여러 가지 사전 구성이 표시됩니다. 그러나 jest
할 만한 사람은 하나도 없습니다. 따라서 고유한 .vscode/launch.json
파일을 만들어야 합니다. 다행스럽게도 jest
페이지에서는 다음과 같은 .vscode/launch.json
파일을 생성하도록 제안합니다.
{
"version" : " 0.2.0 " ,
"configurations" : [
{
"name" : " Debug Jest Tests " ,
"type" : " node " ,
"request" : " launch " ,
"runtimeArgs" : [ " --inspect-brk " , " ${workspaceRoot}/node_modules/.bin/jest " , " --runInBand " ],
"console" : " integratedTerminal " ,
"internalConsoleOptions" : " neverOpen "
}
]
}
평소처럼 테스트를 실행하고 코드 적용 범위를 얻을 수 있을 뿐만 아니라 두 테스트( 예: __tests__/base.spec.ts
)와 코드( 예: src/core/functions.ts
) 디버거가 이를 찾을 것입니다.
저는 이 모든 것을 Node 8.x에서 테스트했습니다. Node 6.x를 사용하여 디버깅할 때 문제가 있는 것을 보았으므로 문제가 있는 경우 업그레이드를 고려할 수 있습니다(또는 문제를 해결한 경우 수정 사항을 설명하는 이 README에 대한 PR을 제출하도록 함).