Jest là một thư viện để kiểm tra mã JavaScript. Đó là một dự án mã nguồn mở được duy trì bởi Facebook và nó đặc biệt rất phù hợp để kiểm tra mã React, mặc dù không giới hạn ở điều đó: nó có thể kiểm tra bất kỳ mã JavaScript nào. Jest rất nhanh và dễ sử dụng
- Giới thiệu về Jest
- Cài đặt
- Tạo thử nghiệm Jest đầu tiên
- Chạy Jest với VS Code
- Người đối sánh
- Thiết lập
- Phá bỏ
- Kiểm tra nhóm bằng cách sử dụng description ()
- Kiểm tra mã không đồng bộ
- Chế giễu
- Kiểm tra ảnh chụp nhanh
Giới thiệu về Jest
Jest là một thư viện để kiểm tra mã JavaScript.
Đó là một dự án mã nguồn mở được duy trì bởi Facebook và nó đặc biệt rất phù hợp để kiểm tra mã React, mặc dù không giới hạn ở điều đó: nó có thể kiểm tra bất kỳ mã JavaScript nào. Điểm mạnh của nó là:
- nó nhanh
- nó có thể thực hiệnkiểm tra ảnh chụp nhanh
- nó kiên định và cung cấp mọi thứ mà không yêu cầu bạn đưa ra lựa chọn
Jest là một công cụ rất giống với Mocha, mặc dù chúng có những điểm khác biệt:
- Mocha ít cố chấp hơn, trong khi Jest có một số quy ước nhất định
- Mocha yêu cầu nhiều cấu hình hơn, trong khi Jest thường hoạt động hiệu quả, nhờ vào sự kiên định
- Mocha lâu đời hơn và lâu đời hơn, với nhiều tích hợp công cụ hơn
Theo ý kiến của tôi, tính năng lớn nhất của Jest là nó là một giải pháp out of the box hoạt động mà không cần phải tương tác với các thư viện thử nghiệm khác để thực hiện công việc của nó.
Cài đặt
Jest được tự động cài đặt trongcreate-react-app
, vì vậy nếu bạn sử dụng nó, bạn không cần phải cài đặt Jest.
Jest có thể được cài đặt trong bất kỳ dự án nào khác bằng cách sử dụngSợi:
yarn add --dev jest
hoặc lànpm:
npm install --save-dev jest
lưu ý cách chúng tôi hướng dẫn cả hai cách đưa Jest vàodevDependencies
một phần củapackage.json
để nó chỉ được cài đặt trong môi trường phát triển chứ không phải trong sản xuất.
Thêm dòng này vào phần tập lệnh củapackage.json
tập tin:
{
"scripts": {
"test": "jest"
}
}
để các bài kiểm tra có thể được chạy bằng cách sử dụngyarn test
hoặc lànpm run test
.
Ngoài ra, bạn có thể cài đặt Jest trên toàn cầu:
yarn global add jest
và chạy tất cả các thử nghiệm của bạn bằng cách sử dụngjest
công cụ dòng lệnh.
Tạo thử nghiệm Jest đầu tiên
Các dự án được tạo bằngcreate-react-app
đã cài đặt và định cấu hình sẵn Jest ra khỏi hộp, nhưng việc thêm Jest vào bất kỳ dự án nào cũng dễ dàng như nhập
yarn add --dev jest
Thêm vào của bạnpackage.json
đường thẳng này:
{
"scripts": {
"test": "jest"
}
}
và chạy các thử nghiệm của bạn bằng cách thực hiệnyarn test
trong vỏ của bạn.
Bây giờ, bạn không có bất kỳ bài kiểm tra nào ở đây, vì vậy sẽ không có gì được thực thi:
Hãy tạo thử nghiệm đầu tiên. Mở mộtmath.js
tệp và nhập một vài hàm mà sau này chúng tôi sẽ kiểm tra:
const sum = (a, b) => a + b
const mul = (a, b) => a * b
const sub = (a, b) => a - b
const div = (a, b) => a / b
module.exports = { sum, mul, sub, div }
Bây giờ hãy tạo mộtmath.test.js
trong cùng một thư mục và ở đó, chúng tôi sẽ sử dụng Jest để kiểm tra các chức năng được xác định trongmath.js
:
const { sum, mul, sub, div } = require('./math')
test(‘Adding 1 + 1 equals 2’, () => {
expect(sum(1, 1)).toBe(2)
})
test(‘Multiplying 1 * 1 equals 1’, () => {
expect(mul(1, 1)).toBe(1)
})
test(‘Subtracting 1 - 1 equals 0’, () => {
expect(sub(1, 1)).toBe(0)
})
test(‘Dividing 1 / 1 equals 1’, () => {
expect(div(1, 1)).toBe(1)
})
Đang chạyyarn test
kết quả là Jest được chạy trên tất cả các tệp thử nghiệm mà nó tìm thấy và trả lại cho chúng tôi kết quả cuối cùng:
Chạy Jest với VS Code
Visual Studio Code là một trình soạn thảo tuyệt vời để phát triển JavaScript. CácPhần mở rộng Jestcung cấp tích hợp hàng đầu cho các thử nghiệm của chúng tôi.
Sau khi bạn cài đặt nó, nó sẽ tự động phát hiện nếu bạn đã cài đặt Jest trong devDependencies của mình và chạy các bài kiểm tra. Bạn cũng có thể gọi các bài kiểm tra theo cách thủ công bằng cách chọnJest: Start Runnerchỉ huy. Nó sẽ chạy các bài kiểm tra và ở chế độ xem để chạy lại chúng bất cứ khi nào bạn thay đổi một trong các tệp có bài kiểm tra (hoặc tệp thử nghiệm):
Người đối sánh
Trong bài viết trước tôi đã sử dụngtoBe()
là duy nhấtngười kết hợp:
test('Adding 1 + 1 equals 2', () => {
expect(sum(1, 1)).toBe(2)
})
Trình so khớp là một phương pháp cho phép bạn kiểm tra các giá trị.
Các trình so khớp được sử dụng phổ biến nhất, so sánh giá trị của kết quảexpect()
với giá trị được truyền vào dưới dạng đối số, là:
toBe
so sánh bình đẳng nghiêm ngặt, sử dụng===
toEqual
so sánh các giá trị của hai biến. Nếu đó là một đối tượng hoặc mảng, nó sẽ kiểm tra sự bình đẳng của tất cả các thuộc tính hoặc phần tửtoBeNull
là đúng khi truyền giá trị nulltoBeDefined
là true khi chuyển một giá trị xác định (ngược lại với giá trị trên)toBeUndefined
là đúng khi chuyển một giá trị không xác địnhtoBeCloseTo
được sử dụng để so sánh các giá trị nổi, tránh lỗi làm tròntoBeTruthy
true nếu giá trị được coi là true (như mộtif
làm)toBeFalsy
đúng nếu giá trị được coi là sai (như mộtif
làm)toBeGreaterThan
true nếu kết quả của kỳ vọng () cao hơn đối sốtoBeGreaterThanOrEqual
true nếu kết quả của kỳ vọng () bằng đối số hoặc cao hơn đối sốtoBeLessThan
true nếu kết quả của kỳ vọng () thấp hơn đối sốtoBeLessThanOrEqual
true nếu kết quả của kỳ vọng () bằng đối số hoặc thấp hơn đối sốtoMatch
được sử dụng để so sánh các chuỗi vớibiểu hiện thông thườngphù hợp với mô hìnhtoContain
được sử dụng trong mảng, true nếu mảng mong đợi chứa đối số trong tập hợp phần tử của nótoHaveLength(number)
: kiểm tra độ dài của một mảngtoHaveProperty(key, value)
: kiểm tra xem một đối tượng có thuộc tính hay không và tùy chọn kiểm tra giá trị của nótoThrow
kiểm tra xem một hàm bạn truyền có ném ra một ngoại lệ (nói chung) hoặc một ngoại lệ cụ thể hay khôngtoBeInstanceOf()
: kiểm tra xem một đối tượng có phải là một thể hiện của một lớp hay không
Tất cả các đối sánh đó có thể bị phủ nhận bằng cách sử dụng.not.
bên trong câu lệnh, ví dụ:
test('Adding 1 + 1 does not equal 3', () => {
expect(sum(1, 1)).not.toBe(3)
})
Để sử dụng với những lời hứa, bạn có thể sử dụng.resolves
và.rejects
:
expect(Promise.resolve('lemon')).resolves.toBe('lemon')
expect(Promise.reject(new Error(‘octopus’))).rejects.toThrow(‘octopus’)
Thiết lập
Trước khi chạy các bài kiểm tra, bạn sẽ muốn thực hiện một số khởi tạo.
Để làm điều gì đó một lần trước khi tất cả các thử nghiệm chạy, hãy sử dụngbeforeAll()
chức năng:
beforeAll(() => {
//do something
})
Để thực hiện điều gì đó trước mỗi lần chạy thử nghiệm, hãy sử dụngbeforeEach()
:
beforeEach(() => {
//do something
})
Phá bỏ
Cũng giống như bạn có thể làm với thiết lập, bạn cũng có thể thực hiện một số việc sau mỗi lần chạy thử nghiệm:
afterEach(() => {
//do something
})
và sau khi tất cả các thử nghiệm kết thúc:
afterAll(() => {
//do something
})
Kiểm tra nhóm bằng cách sử dụng description ()
Bạn có thể tạo các nhóm kiểm tra, trong một tệp duy nhất, tách biệt các chức năng thiết lập và chia nhỏ:
describe('first set', () => {
beforeEach(() => {
//do something
})
afterAll(() => {
//do something
})
test(/*...*/)
test(/*...*/)
})
describe(‘second set’, () => {
beforeEach(() => {
//do something
})
beforeAll(() => {
//do something
})
test(/…/)
test(/…/)
})
Kiểm tra mã không đồng bộ
Mã không đồng bộ trong JavaScript hiện đại về cơ bản có thể có 2 dạng: gọi lại và hứa hẹn. Ngoài những lời hứa, chúng ta có thể sử dụng async / await.
Gọi lại
Bạn không thể có một bài kiểm tra trong một cuộc gọi lại, vì Jest sẽ không thực thi nó - việc thực thi tệp kiểm tra kết thúc trước khi lệnh gọi lại được gọi. Để khắc phục điều này, hãy chuyển một tham số cho hàm kiểm tra, bạn có thể gọi hàm này một cách thuận tiệndone
. Jest sẽ đợi cho đến khi bạn gọidone()
trước khi kết thúc bài kiểm tra đó:
//uppercase.js
function uppercase(str, callback) {
callback(str.toUpperCase())
}
module.exports = uppercase
//uppercase.test.js
const uppercase = require(’./src/uppercase’)
test(uppercase 'test' to equal 'TEST'
, (done) => {
uppercase(‘test’, (str) => {
expect(str).toBe(‘TEST’)
done()
}
})
Lời hứa
Với các hàm trả về lời hứa, chúng tôitrả lại một lời hứatừ bài kiểm tra:
//uppercase.js
const uppercase = str => {
return new Promise((resolve, reject) => {
if (!str) {
reject('Empty string')
return
}
resolve(str.toUpperCase())
})
}
module.exports = uppercase
//uppercase.test.js
const uppercase = require(’./uppercase’)
test(uppercase 'test' to equal 'TEST'
, () => {
return uppercase(‘test’).then(str => {
expect(str).toBe(‘TEST’)
})
})
Có thể kiểm tra những lời hứa bị từ chối bằng cách sử dụng.catch()
:
//uppercase.js
const uppercase = str => {
return new Promise((resolve, reject) => {
if (!str) {
reject('Empty string')
return
}
resolve(str.toUpperCase())
})
}
module.exports = uppercase
//uppercase.test.js
const uppercase = require(’./uppercase’)
test(uppercase 'test' to equal 'TEST'
, () => {
return uppercase(’’).catch(e => {
expect(e).toMatch(‘Empty string’)
})
})
Async / await
Để kiểm tra các hàm trả về lời hứa, chúng ta cũng có thể sử dụng async / await, điều này làm cho cú pháp rất đơn giản và dễ hiểu:
//uppercase.test.js
const uppercase = require('./uppercase')
test(`uppercase 'test' to equal 'TEST'`, async () => {
const str = await uppercase('test')
expect(str).toBe('TEST')
})
Chế giễu
Trong thử nghiệm,chế giễucho phép bạn kiểm tra chức năng phụ thuộc vào:
- Cơ sở dữ liệu
- Mạng lướiyêu cầu
- truy cập vàoCác tập tin
- bất kìBên ngoàihệ thống
vậy nên:
- các bài kiểm tra của bạn chạynhanh hơn, mang lại thời gian quay vòng nhanh chóng trong quá trình phát triển
- bài kiểm tra của bạn làđộc lậpđiều kiện mạng hoặc trạng thái của cơ sở dữ liệu
- các bài kiểm tra của bạn khôngô nhiễmbất kỳ lưu trữ dữ liệu nào vì chúng không chạm vào cơ sở dữ liệu
- bất kỳ thay đổi nào được thực hiện trong thử nghiệm không làm thay đổi trạng thái cho các thử nghiệm tiếp theo và việc chạy lại bộ thử nghiệm phải bắt đầu từ điểm xuất phát đã biết và có thể tái lập
- bạn không phải lo lắng về việc giới hạn tốc độ đối với các cuộc gọi API và yêu cầu mạng
Chế nhạo rất hữu ích khi bạn muốn tránh các tác dụng phụ (ví dụ: ghi vào cơ sở dữ liệu) hoặc bạn muốn bỏ qua các phần mã chậm (như truy cập mạng) và cũng tránh các tác động khi chạy thử nghiệm của bạn nhiều lần (ví dụ: hãy tưởng tượng một hàm gửi email hoặc gọi một API giới hạn tỷ lệ).
Quan trọng hơn nữa, nếu bạn đang viếtKiểm tra đơn vị, bạn nên kiểm tra chức năng của một chức năng một cách riêng biệt, không phải với tất cả những thứ mà nó chạm vào.
Bằng cách sử dụng mocks, bạn có thể kiểm tra xem một chức năng mô-đun đã được gọi hay chưa và những tham số nào đã được sử dụng, với:
expect().toHaveBeenCalled()
: kiểm tra xem một hàm do thám đã được gọi chưaexpect().toHaveBeenCalledTimes()
: đếm số lần một hàm do thám đã được gọiexpect().toHaveBeenCalledWith()
: kiểm tra xem hàm đã được gọi với một bộ tham số cụ thể chưaexpect().toHaveBeenLastCalledWith()
: kiểm tra các tham số của lần cuối cùng hàm đã được gọi
Các gói gián điệp mà không ảnh hưởng đến mã chức năng
Khi bạn nhập một gói, bạn có thể yêu cầu Jest “theo dõi” việc thực thi một chức năng cụ thể, bằng cách sử dụngspyOn()
mà không ảnh hưởng đến cách thức hoạt động của phương pháp đó.
Thí dụ:
const mathjs = require('mathjs')
test(The mathjs log function
, () => {
const spy = jest.spyOn(mathjs, ‘log’)
const result = mathjs.log(10000, 10)
expect(mathjs.log).toHaveBeenCalled()
expect(mathjs.log).toHaveBeenCalledWith(10000, 10)
})
Mô phỏng toàn bộ gói hàng
Jest cung cấp một cách thuận tiện để giả mạo toàn bộ một gói. Tạo một__mocks__
trong thư mục gốc của dự án và trong thư mục này, hãy tạo một tệp JavaScript cho mỗi gói của bạn.
Giả sử bạn nhập khẩumathjs
. Tạo một__mocks__/mathjs.js
tệp trong thư mục gốc dự án của bạn và thêm nội dung này:
module.exports = {
log: jest.fn(() => 'test')
}
Điều này sẽ giả lập hàm log () của gói. Thêm nhiều chức năng mà bạn muốn mô phỏng:
const mathjs = require('mathjs')
test(The mathjs log function
, () => {
const result = mathjs.log(10000, 10)
expect(result).toBe(‘test’)
expect(mathjs.log).toHaveBeenCalled()
expect(mathjs.log).toHaveBeenCalledWith(10000, 10)
})
Mô phỏng một chức năng duy nhất
Bạn có thể mô phỏng một chức năng duy nhất bằng cách sử dụngjest.fn()
:
const mathjs = require('mathjs')
mathjs.log = jest.fn(() => ‘test’)
test(The mathjs log function
, () => {
const result = mathjs.log(10000, 10)
expect(result).toBe(‘test’)
expect(mathjs.log).toHaveBeenCalled()
expect(mathjs.log).toHaveBeenCalledWith(10000, 10)
})
Bạn cũng có thể dùngjest.fn().mockReturnValue('test')
để tạo một mô hình đơn giản không làm gì khác ngoài việc trả về một giá trị.
Chế tạo trước
Bạn có thể tìm thấy các bản mô phỏng được tạo sẵn cho các thư viện phổ biến. Ví dụ như gói nàyhttps://github.com/jefflau/jest-fetch-mockcho phép bạn chế nhạofetch()
và cung cấp các giá trị trả về mẫu mà không cần tương tác với máy chủ thực tế trong các thử nghiệm của bạn.
Kiểm tra ảnh chụp nhanh
Kiểm tra ảnh chụp nhanh là một tính năng khá thú vị do Jest cung cấp. Nó có thể ghi nhớ cách các thành phần giao diện người dùng của bạn được hiển thị và so sánh nó với thử nghiệm hiện tại, gây ra lỗi nếu có sự không khớp.
Đây là một bài kiểm tra đơn giản trên thành phần Ứng dụng của mộtcreate-react-app
ứng dụng (đảm bảo bạn cài đặtreact-test-renderer
):
import React from 'react'
import App from './App'
import renderer from 'react-test-renderer'
it(‘renders correctly’, () => {
const tree = renderer.create(<App />).toJSON()
expect(tree).toMatchSnapshot()
})
lần đầu tiên bạn chạy thử nghiệm này, Jest lưu ảnh chụp nhanh vào__snapshots__
thư mục. Đây là những gì App.test.js.snap chứa:
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`renders correctly 1`] = `
<div
className="App"
>
<header
className="App-header"
>
<img
alt="logo"
className="App-logo"
src="logo.svg"
/>
<h1
className="App-title"
>
Welcome to React
</h1>
</header>
<p
className="App-intro"
>
To get started, edit
<code>
src/App.js
</code>
and save to reload.
</p>
</div>
`
Như bạn thấy, đó là mã mà Thành phần ứng dụng hiển thị, không có gì khác.
Lần sau, thử nghiệm sẽ so sánh kết quả đầu ra của<App />
đến điều này. Nếu Ứng dụng thay đổi, bạn sẽ gặp lỗi:
Khi đang sử dụngyarn test
trongcreate-react-app
bạn đang ở trongchế độ xemvà từ đó bạn có thể nhấnw
và hiển thị thêm các tùy chọn:
Watch Usage
› Press u to update failing snapshots.
› Press p to filter by a filename regex pattern.
› Press t to filter by a test name regex pattern.
› Press q to quit watch mode.
› Press Enter to trigger a test run.If your change is intended, pressing u
will update the failing snapshots, and make the test pass.
You can also update the snapshot by running jest -u
(or jest --updateSnapshot
) outside of watch mode.
More devtools tutorials:
- Introduction to Yeoman
- Bower, the browser package manager
- Introduction to Frontend Testing
- Using node-webkit to create a Desktop App
- VS Code: use language-specific settings
- Introduction to Webpack
- A short and simple guide to Babel
- An introduction to Yarn
- Overview of the Browser DevTools
- Format your code with Prettier
- Keep your code clean with ESLint
- A list of cool Chrome DevTools Tips and Tricks
- Testing JavaScript with Jest
- How to use Visual Studio Code
- Introduction to Electron
- Parcel, a simpler webpack
- An Emmet reference for HTML
- The V8 JavaScript Engine
- Configuring VS Code
- Configuring the macOS command line
- How to disable an ESLint rule
- How to open VS Code from the command line
- How to set up hot reload on Electron