Tujuan dalam proyek ini adalah membuat proyek TypeScript yang dapat melakukan semua hal berikut:
jest
dan ts-jest
untuk pengujian Saya mulai dengan menginisialisasi ini sebagai proyek npm
.
$ yarn init .
Kemudian, saya menginstal typescript
, jest
, ts-jest
dan @types/jest
sebagai dependensi:
$ yarn add -D typescript jest ts-jest @types/jest
Pada saat penulisan ini, itu berarti [email protected]
, [email protected]
dan [email protected]
.
Selanjutnya, kami menginisialisasi ini sebagai proyek TypeScript menggunakan:
$ npx tsc --init .
Saya ingin kode yang dihasilkan TypeScript saya disimpan di ./lib
dan saya ingin deklarasi dibuat. Jadi, saya mengkonfigurasi outDir
di tsconfig.json
menjadi ./lib
.
.gitignore
saya kemudian dikonfigurasi menjadi:
/node_modules
/lib
...sementara .npmignore
saya hanya:
/node_modules
Untuk alasan yang sama, saya menghapus nilai default untuk files
di tsconfig.json
dan menggantinya dengan:
"exclude" : [ " node_modules " , " lib " ]
Untuk memulai, saya membuat src/index.ts
yang berisi fungsi sederhana:
export function sampleFunction ( x : string ) : string {
return x + x ;
}
Saya juga menambahkan tes jest
sederhana. Saya lebih suka menyimpan pengujian saya di lokasi yang benar-benar terpisah, jadi saya akan meletakkan semua pengujian saya di __tests__
. Jadi saya membuat test case berikut di __tests__/base.spec.ts
:
import { sampleFunction } from "../src" ;
describe ( "This is a simple test" , ( ) => {
test ( "Check the sampleFunction function" , ( ) => {
expect ( sampleFunction ( "hello" ) ) . toEqual ( "hellohello" ) ;
} ) ;
} ) ;
Pada titik ini, saya ingin menjalankan tes itu. Tapi pertama-tama saya perlu membuat file jest.config.js
untuk semua pengaturan jest
saya. Ini harus memperhitungkan fakta bahwa saya menggunakan ts-jest
dan fakta bahwa pengujian saya disimpan di __tests__
. Sehingga file yang dihasilkan terlihat seperti ini:
module . exports = {
transform : {
"^.+\.tsx?$" : "ts-jest" ,
} ,
testRegex : "(/__tests__/.*|(\.|/)(test|spec))\.(jsx?|tsx?)$" ,
moduleFileExtensions : [ "ts" , "tsx" , "js" , "jsx" , "json" , "node" ] ,
} ;
Saya kemudian menambahkan skrip berikut ke package.json
:
"scripts" : {
"compile" : " tsc " ,
"test" : " jest "
}
Pada titik ini, jika saya menjalankan yarn test
, saya mendapatkan apa yang saya harapkan:
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
Untuk mengaktifkan cakupan kode, saya memperbarui file jest.config.js
saya ke:
module . exports = {
transform : {
"^.+\.tsx?$" : "ts-jest" ,
} ,
testRegex : "(/__tests__/.*|(\.|/)(test|spec))\.(jsx?|tsx?)$" ,
moduleFileExtensions : [ "ts" , "tsx" , "js" , "jsx" , "json" , "node" ] ,
collectCoverage : true ,
} ;
Saya juga ingin memperbarui file .gitignore
dan .npmignore
saya untuk menghindari pengontrolan versi atau penerbitan direktori coverage
yang dihasilkan oleh jest
.
Pada titik ini, saya akan mulai memperkenalkan sub-modul dalam proyek saya. Jadi saya akan menambahkan modul src/core
dan src/utils
agar semuanya lebih realistis. Lalu saya akan mengekspor konten keduanya sehingga src/index.ts
terlihat seperti ini:
export * from "./core" ;
export * from "./utils" ;
Ini kemudian mengimpor file tertentu yang berisi berbagai jenis dan fungsi. Awalnya, saya akan membuat sekumpulan tipe yang sangat sederhana untuk merepresentasikan ekspresi yang sangat sederhana hanya dengan literal dan operasi biner +
, -
, *
dan /
. Lalu saya bisa menulis beberapa tes seperti ini:
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 ) ;
} ) ;
} ) ;
Sejauh ini bagus. Namun perhatikan bahwa jika saya benar-benar menjalankan tes ini, saya mendapatkan hasil berikut:
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 | |
---------------|----------|----------|----------|----------|----------------|
Perhatikan kurangnya cakupan kode. Menambahkan beberapa kasus uji lagi bersama dengan beberapa komentar /* istanbul ignore ... */
agar istanbul
mengetahui apa yang dapat diabaikan dengan aman, kita dapat:
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 | |
---------------|----------|----------|----------|----------|----------------|
Sekarang, jika kita mengubah pengujian agar gagal, kita mendapatkan sesuatu seperti ini:
● 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 | |
---------------|----------|----------|----------|----------|----------------|
Perhatikan bahwa jalur tumpukan sudah benar. Ini menunjuk pada masalah dalam kode TypeScript .
Ingatlah bahwa kami menambahkan skrip compile
ke package.json
kami. Kita dapat mengkompilasi kode dengan yarn compile
. Dengan melakukan hal ini, kita melihat bahwa direktori lib
diisi dengan dua subdirektori, src
dan __tests__
.
Namun, jika kita melihat direktori tersebut, kita akan menemukan bahwa direktori tersebut hanya menyertakan kode Javascript yang dihasilkan. Mereka tidak menyertakan definisi tipe. Untuk menghasilkan definisi tipe (file .d.ts
) sehingga pengguna TypeScript lainnya bisa mendapatkan manfaat dari semua informasi tipe yang telah kita tambahkan ke kode, kita harus menyetel bidang declaration
di file tsconfig.json
menjadi true
.
Perhatikan juga bahwa agar orang lain dapat menggunakan paket ini sebagai modul NPM, Anda perlu menyetel bidang main
di package.json
ke lib/src/index.js
. Selanjutnya, agar orang lain dapat mengakses tipe-tipe dalam modul ini, kita juga perlu mengatur field typings
di package.json
menjadi lib/src/index.d.ts
. Dengan kata lain,
"main" : " lib/src/index.js " ,
"typings" : " lib/src/index.d.ts " ,
Jika dikonfigurasi dengan benar, kita kemudian dapat meluncurkan sesi node
dan mengimpor paket baru kita:
$ node
> var me = require( " . " )
undefined
> me
{ evaluate: [Function: evaluate],
assertNever: [Function: assertNever] }
>
Sekarang pastikan untuk memperbarui jest.config.js
Anda untuk menyertakan pengaturan berikut atau jest
akan mulai mencocokkan kode di direktori lib/__tests__
:
testPathIgnorePatterns: ["/lib/", "/node_modules/"],
Akhirnya, kita sampai pada debugging. Saya menggunakan Visual Studio Code, jadi saya akan menunjukkan cara agar debugging berfungsi di sana. Beberapa informasi ini mungkin dapat diterjemahkan ke IDE lain.
Di VSCode, kita bisa pergi ke sidebar debugging. Awalnya, di sebelah tombol "play" akan ada tulisan "No Configuration". Mengkliknya akan menampilkan menu tarik-turun dengan opsi "Tambahkan Konfigurasi...".
Meskipun saya menyukai TypeScript, debugging sebenarnya merupakan kelemahannya. Bukannya Anda tidak bisa melakukan debug, hanya saja sulit untuk mulai bekerja. Jika Anda memilih "Tambahkan Konfigurasi..." dan kemudian "Node.js", Anda akan melihat beberapa prakonfigurasi termasuk satu untuk mocha
. Tapi tidak ada yang bisa dijadikan jest
. Jadi, Anda harus membuat file .vscode/launch.json
Anda sendiri. Untungnya, halaman jest
menyarankan Anda membuat file .vscode/launch.json
yang terlihat seperti ini:
{
"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 "
}
]
}
Saya sangat terkejut saat mengetahui bahwa saya tidak hanya dapat menjalankan pengujian dan mendapatkan cakupan kode seperti biasa, namun juga menetapkan breakpoint pada kedua pengujian ( yaitu, dalam __tests__/base.spec.ts
) serta dalam kode ( misalnya, src/core/functions.ts
) dan debugger akan menemukannya.
Perhatikan bahwa saya menguji semua ini pada Node 8.x. Saya telah melihat masalah dengan debugging menggunakan Node 6.x jadi jika Anda mengalami masalah di sana, Anda mungkin mempertimbangkan untuk melakukan upgrade (atau biarkan, jika Anda berhasil memperbaikinya, kirimkan PR untuk README ini yang menjelaskan perbaikannya).