Thứ hai, 16/03/2020 | 00:00 GMT+7

Cách kiểm tra module Node.js với Mocha và Assert

Kiểm thử là một phần không thể thiếu trong phát triển phần mềm. Các lập trình viên thường chạy mã kiểm tra ứng dụng của họ khi họ áp dụng các thay đổi để xác nhận nó đang hoạt động như họ muốn. Với cài đặt kiểm tra phù hợp, quá trình này thậm chí có thể được tự động hóa, tiết kiệm rất nhiều thời gian. Việc chạy thử nghiệm một cách nhất quán sau khi viết mã mới đảm bảo các thay đổi mới không phá vỡ các tính năng đã có từ trước. Điều này mang lại cho nhà phát triển niềm tin vào cơ sở mã của họ, đặc biệt là khi nó được triển khai vào production để user có thể tương tác với nó.

Khung thử nghiệm cấu trúc theo cách ta tạo các trường hợp thử nghiệm. Mocha là một khung kiểm tra JavaScript phổ biến tổ chức các trường hợp thử nghiệm của ta và chạy chúng cho ta . Tuy nhiên, Mocha không xác minh hành vi của mã của ta . Để so sánh các giá trị trong một bài kiểm tra, ta có thể sử dụng module assert Node.js.

Trong bài viết này, bạn sẽ viết các bài kiểm tra cho module danh sách CẦN LÀM Node.js. Bạn sẽ cài đặt và sử dụng khung kiểm tra Mocha để cấu trúc các bài kiểm tra của bạn . Sau đó, bạn sẽ sử dụng module assert Node.js để tự tạo các bài kiểm tra. Theo nghĩa này, bạn sẽ sử dụng Mocha như một người xây dựng kế hoạch và assert sẽ thực hiện kế hoạch.

Yêu cầu

Bước 1 - Viết module nút

Hãy bắt đầu bài viết này bằng cách viết module Node.js mà ta muốn kiểm tra. Mô-đun này sẽ quản lý một danh sách các mục CẦN LÀM. Sử dụng module này, ta sẽ có thể liệt kê tất cả những VIỆC CẦN LÀM mà ta đang theo dõi, thêm các mục mới và đánh dấu một số là hoàn thành. Ngoài ra, ta sẽ có thể xuất danh sách các mục CẦN LÀM sang file CSV. Nếu bạn muốn được bồi dưỡng về cách viết module Node.js, bạn có thể đọc bài viết của ta về Cách tạo module Node.js.

Đầu tiên, ta cần cài đặt môi trường mã hóa. Tạo một folder có tên dự án của bạn trong terminal của bạn. Hướng dẫn này sẽ sử dụng tên todos :

  • mkdir todos

Sau đó nhập folder đó:

  • cd todos

Bây giờ hãy khởi tạo npm , vì ta sẽ sử dụng chức năng CLI của nó để chạy các thử nghiệm sau:

  • npm init -y

Ta chỉ có một phụ thuộc, Mocha, ta sẽ sử dụng để tổ chức và chạy các thử nghiệm của bạn . Để download và cài đặt Mocha, hãy sử dụng như sau:

  • npm i request --save-dev mocha

Ta cài đặt Mocha là một dev phụ thuộc, vì nó không cần thiết bởi module trong một khung cảnh production . Nếu bạn muốn tìm hiểu thêm về các gói Node.js hoặc npm, hãy xem hướng dẫn của ta về Cách Sử dụng Mô-đun Node.js với npm và package.json .

Cuối cùng, hãy tạo file của ta sẽ chứa mã của module của ta :

  • touch index.js

Như vậy, ta đã sẵn sàng tạo module của bạn . Mở index.js trong một editor như nano :

  • nano index.js

Hãy bắt đầu bằng cách xác định lớp Todos . Lớp này chứa tất cả các chức năng mà ta cần để quản lý danh sách CẦN LÀM. Thêm các dòng mã sau vào index.js :

todos / index.js
class Todos {     constructor() {         this.todos = [];     } }  module.exports = Todos; 

Ta bắt đầu file bằng cách tạo một lớp Todos . Hàm constructor() của nó không có đối số, do đó ta không cần cung cấp bất kỳ giá trị nào để khởi tạo một đối tượng cho lớp này. Tất cả những gì ta làm khi khởi tạo một đối tượng Todos là tạo một thuộc tính todos đó là một mảng trống.

Dòng modules cho phép các module Node.js khác yêu cầu lớp Todos của ta . Nếu không xuất lớp một cách rõ ràng, file thử nghiệm mà ta sẽ tạo sau này sẽ không thể sử dụng nó.

Hãy thêm một hàm trả về mảng todos ta đã lưu trữ. Viết vào các dòng được đánh dấu sau:

todos / index.js
class Todos {     constructor() {         this.todos = [];     }      list() {         return [...this.todos];     } }  module.exports = Todos; 

Hàm list() của ta trả về một bản sao của mảng được sử dụng bởi lớp. Nó tạo một bản sao của mảng bằng cách sử dụng cú pháp cấu trúc của JavaScript. Ta tạo một bản sao của mảng để những thay đổi mà user thực hiện đối với mảng được trả về bởi list() không ảnh hưởng đến mảng được sử dụng bởi đối tượng Todos .

Lưu ý: Mảng JavaScript là kiểu tham chiếu . Điều này nghĩa là đối với bất kỳ phép gán biến nào cho một mảng hoặc lệnh gọi hàm với một mảng dưới dạng tham số, JavaScript đề cập đến mảng ban đầu đã được tạo. Ví dụ: nếu ta có một mảng có ba mục được gọi là x và tạo một biến mới y sao cho y = x , yx đều tham chiếu đến cùng một thứ. Bất kỳ thay đổi nào ta thực hiện đối với mảng có y ảnh hưởng đến biến x và ngược lại.

Bây giờ ta hãy viết hàm add() , thêm một mục TODO mới:

todos / index.js
class Todos {     constructor() {         this.todos = [];     }      list() {         return [...this.todos];     }      add(title) {         let todo = {             title: title,             completed: false,         }          this.todos.push(todo);     } }  module.exports = Todos; 

Hàm add() của ta nhận một chuỗi và đặt nó vào thuộc tính title của đối tượng JavaScript mới. Đối tượng mới cũng có một thuộc tính completed , được đặt thành false theo mặc định. Sau đó, ta thêm đối tượng mới này vào mảng việc CẦN LÀM.

Chức năng quan trọng trong trình quản lý TODO là đánh dấu các mục là đã hoàn thành. Để thực hiện điều này, ta sẽ lặp qua ta todos mảng để tìm mục TODO user đang tìm kiếm. Nếu một cái được tìm thấy, ta sẽ đánh dấu nó là đã hoàn thành. Nếu không tìm thấy, ta sẽ thông báo lỗi.

Thêm hàm complete() như sau:

todos / index.js
class Todos {     constructor() {         this.todos = [];     }      list() {         return [...this.todos];     }      add(title) {         let todo = {             title: title,             completed: false,         }          this.todos.push(todo);     }      complete(title) {         let todoFound = false;         this.todos.forEach((todo) => {             if (todo.title === title) {                 todo.completed = true;                 todoFound = true;                 return;             }         });          if (!todoFound) {             throw new Error(`No TODO was found with the title: "${title}"`);         }     } }  module.exports = Todos; 

Lưu file và thoát khỏi editor .

Bây giờ ta có một trình quản lý TODO cơ bản mà ta có thể thử nghiệm. Tiếp theo, hãy kiểm tra thủ công mã của ta để xem ứng dụng có hoạt động hay không.

Bước 2 - Kiểm tra mã theo cách thủ công

Trong bước này, ta sẽ chạy các chức năng của mã và quan sát kết quả kết quả đảm bảo nó phù hợp với mong đợi của ta . Đây được gọi là kiểm tra thủ công . Nó có thể là phương pháp thử nghiệm phổ biến nhất mà các lập trình viên áp dụng. Mặc dù ta sẽ tự động kiểm tra sau này với Mocha, nhưng trước tiên ta sẽ kiểm tra thủ công mã của bạn để có cảm nhận rõ hơn về cách kiểm tra thủ công khác với các khung kiểm tra.

Hãy thêm hai mục CẦN LÀM vào ứng dụng của ta và đánh dấu một mục là hoàn thành. Khởi động Node.js REPL trong cùng folder với index.js :

  • node

Bạn sẽ thấy dấu nhắc > trong REPL cho ta biết ta có thể nhập mã JavaScript. Nhập nội dung sau vào dấu nhắc:

  • const Todos = require('./index');

Với request require() , ta tải module TODOs vào một biến Todos . Nhớ lại rằng module của ta trả về lớp Todos theo mặc định.

Bây giờ, hãy khởi tạo một đối tượng cho lớp đó. Trong REPL, hãy thêm dòng mã này:

  • const todos = new Todos();

Ta có thể sử dụng đối tượng todos để xác minh các hoạt động triển khai của ta . Hãy thêm mục TODO đầu tiên của ta :

  • todos.add("run code");

Cho đến nay ta vẫn chưa thấy bất kỳ kết quả nào trong terminal của bạn . Hãy xác minh ta đã lưu trữ mục TODO "run code" của ta bằng cách nhận danh sách tất cả các VIỆC CẦN LÀM:

  • todos.list();

Bạn sẽ thấy kết quả này trong REPL của bạn :

Output
[ { title: 'run code', completed: false } ]

Đây là kết quả mong đợi: Ta có một mục VIỆC CẦN LÀM trong mảng VIỆC CẦN LÀM và nó không được hoàn thành theo mặc định.

Hãy thêm một mục TODO khác:

  • todos.add("test everything");

Đánh dấu mục CẦN LÀM đầu tiên là đã hoàn thành:

  • todos.complete("run code");

Đối tượng todos của ta bây giờ sẽ quản lý hai mục: "run code""test everything" . "run code" TODO cũng sẽ được hoàn thành. Hãy xác nhận điều này bằng cách gọi list() :

  • todos.list();

REPL sẽ xuất ra:

Output
[ { title: 'run code', completed: true }, { title: 'test everything', completed: false } ]

Bây giờ, hãy thoát khỏi REPL với những điều sau:

  • .exit

Ta đã xác nhận module của ta hoạt động như ta mong đợi. Mặc dù ta không đưa mã của bạn vào file thử nghiệm hoặc sử dụng thư viện thử nghiệm, nhưng ta đã kiểm tra mã của bạn theo cách thủ công. Thật không may, hình thức kiểm tra này trở nên tốn thời gian để thực hiện mỗi khi ta thực hiện thay đổi. Tiếp theo, hãy sử dụng kiểm thử tự động trong Node.js và xem liệu ta có thể giải quyết vấn đề này với khung kiểm thử Mocha hay không.

Bước 3 - Viết bài kiểm tra đầu tiên của bạn với Mocha và Assert

Trong bước cuối cùng, ta đã kiểm tra ứng dụng của bạn theo cách thủ công. Điều này sẽ hoạt động cho các trường hợp sử dụng riêng lẻ, nhưng khi module của ta mở rộng, phương pháp này trở nên kém khả thi hơn. Khi ta thử nghiệm các tính năng mới, ta phải chắc chắn rằng chức năng được thêm vào không tạo ra sự cố trong chức năng cũ. Ta muốn kiểm tra lại từng tính năng cho mọi thay đổi trong mã, nhưng làm điều này bằng tay sẽ tốn rất nhiều công sức và dễ bị lỗi.

Một phương pháp hiệu quả hơn sẽ là cài đặt các bài kiểm tra tự động . Đây là các bài kiểm tra theo kịch bản được viết giống như bất kỳ khối mã nào khác. Ta chạy các chức năng của bạn với các đầu vào được xác định và kiểm tra tác dụng của chúng đảm bảo chúng hoạt động như ta mong đợi. Khi cơ sở mã của ta phát triển, các thử nghiệm tự động của ta cũng vậy. Khi ta viết các thử nghiệm mới cùng với các tính năng, ta có thể xác minh toàn bộ module vẫn hoạt động — tất cả mà không cần phải nhớ cách sử dụng từng chức năng mỗi lần.

Trong hướng dẫn này, ta đang sử dụng khung kiểm tra Mocha với module assert Node.js. Hãy lấy một số kinh nghiệm thực tế để xem chúng hoạt động cùng nhau như thế nào.

Để bắt đầu, hãy tạo một file mới để lưu trữ mã thử nghiệm của ta :

  • touch index.test.js

Bây giờ sử dụng editor bạn muốn để mở file thử nghiệm. Bạn có thể sử dụng nano như trước đây:

  • nano index.test.js

Trong dòng đầu tiên của file văn bản, ta sẽ tải module TODOs giống như ta đã làm trong shell Node.js. Sau đó, ta sẽ tải module assert khi ta viết các bài kiểm tra của bạn . Thêm các dòng sau:

todos / index.test.js
const Todos = require('./index'); const assert = require('assert').strict; 

Thuộc tính strict của module assert sẽ cho phép ta sử dụng các bài kiểm tra bình đẳng đặc biệt được Node.js khuyến nghị và tốt cho việc kiểm chứng trong tương lai, vì chúng chiếm nhiều trường hợp sử dụng hơn.

Trước khi bắt đầu viết các bài kiểm tra, hãy thảo luận về cách Mocha tổ chức mã của ta . Các bài kiểm tra có cấu trúc trong Mocha thường tuân theo mẫu này:

describe([String with Test Group Name], function() {     it([String with Test Name], function() {         [Test Code]     }); }); 

Chú ý hai hàm chính: describe()it() . Hàm describe() được sử dụng để group các bài kiểm tra tương tự. Không bắt buộc Mocha phải chạy thử nghiệm, nhưng việc group các thử nghiệm giúp mã thử nghiệm của ta dễ bảo trì hơn. Bạn nên group các bài kiểm tra của bạn theo cách dễ dàng để cập nhật các bài kiểm tra tương tự với nhau.

it() chứa mã thử nghiệm của ta . Đây là nơi ta sẽ tương tác với các chức năng của module của ta và sử dụng thư viện assert . Nhiều hàm it() có thể được định nghĩa trong một hàm describe() .

Mục tiêu của ta trong phần này là sử dụng Mocha và assert sẽ tự động hóa thử nghiệm thủ công của ta . Ta sẽ thực hiện điều này từng bước, bắt đầu với khối mô tả của ta . Thêm phần sau vào file của bạn sau các dòng module :

todos / index.test.js
... describe("integration test", function() { }); 

Với khối mã này, ta đã tạo một group cho các thử nghiệm tích hợp của ta . Các bài kiểm tra đơn vị sẽ kiểm tra một chức năng tại một thời điểm. Kiểm tra tích hợp xác minh xem các chức năng trong hoặc trên các module hoạt động cùng nhau tốt như thế nào. Khi Mocha chạy thử nghiệm của ta , tất cả các thử nghiệm trong khối mô tả đó sẽ chạy trong group "integration test" .

Hãy thêm một hàm it() để ta có thể bắt đầu kiểm tra mã module của bạn :

todos / index.test.js
... describe("integration test", function() {     it("should be able to add and complete TODOs", function() {     }); }); 

Lưu ý cách mô tả ta đã đặt tên của bài kiểm tra. Nếu bất kỳ ai thực hiện bài kiểm tra của ta , sẽ thấy ngay điều gì đạt hay không đạt. Một ứng dụng được kiểm tra tốt thường là một ứng dụng được ghi chép đầy đủ và các bài kiểm tra đôi khi có thể là một loại tài liệu hiệu quả.

Đối với thử nghiệm đầu tiên của ta , ta sẽ tạo một đối tượng Todos mới và xác minh nó không có mục nào trong đó:

todos / index.test.js
... describe("integration test", function() {     it("should be able to add and complete TODOs", function() {         let todos = new Todos();         assert.notStrictEqual(todos.list().length, 1);     }); }); 

Dòng mã mới đầu tiên khởi tạo một đối tượng Todos mới như ta làm trong Node.js REPL hoặc một module khác. Trong dòng mới thứ hai, ta sử dụng module assert .

Từ module assert ta sử dụng phương thức notStrictEqual() . Hàm này nhận hai tham số: giá trị mà ta muốn kiểm tra (được gọi là giá trị actual ) và giá trị mà ta mong đợi nhận được (được gọi là giá trị expected ). Nếu cả hai đối số đều giống nhau, notStrictEqual() sẽ tạo ra một lỗi để kiểm tra không thành công.

Lưu và thoát khỏi index.test.js .

Trường hợp cơ sở sẽ đúng vì độ dài phải là 0 , không phải là 1 . Hãy xác nhận điều này bằng cách chạy Mocha. Để thực hiện việc này, ta cần sửa đổi file package.json . Mở file package.json của bạn bằng editor của bạn:

  • nano package.json

Bây giờ, trong thuộc tính scripts của bạn, hãy thay đổi nó để nó trông giống như sau:

todos / package.json
... "scripts": {     "test": "mocha index.test.js" }, ... 

Ta vừa thay đổi hành vi của lệnh test CLI của npm. Khi ta chạy npm test , npm sẽ xem lại lệnh mà ta vừa nhập trong package.json . Nó sẽ tìm kiếm thư viện Mocha trong folder node_modules của ta và chạy lệnh mocha với file thử nghiệm của ta .

Lưu và thoát khỏi package.json .

Hãy xem điều gì sẽ xảy ra khi ta chạy thử nghiệm của bạn . Trong terminal của bạn, hãy nhập:

  • npm test

Lệnh sẽ tạo ra kết quả sau:

Output
> todos@1.0.0 test your_file_path/todos > mocha index.test.js integrated test ✓ should be able to add and complete TODOs 1 passing (16ms)

Đầu ra này trước tiên cho ta thấy nó sắp chạy group kiểm tra nào. Đối với mỗi thử nghiệm riêng lẻ trong một group , trường hợp thử nghiệm được thụt vào. Ta thấy tên thử nghiệm của bạn như đã mô tả trong hàm it() . Dấu tích ở bên trái của test case cho biết rằng test đã vượt qua.

Ở dưới cùng, ta nhận được bản tóm tắt về tất cả các thử nghiệm của bạn . Trong trường hợp của ta , một bài kiểm tra của ta đã vượt qua và hoàn thành trong 16 mili giây (thời gian thay đổi tùy theo máy tính).

Thử nghiệm của ta đã bắt đầu thành công. Tuy nhiên, trường hợp thử nghiệm hiện tại này có thể cho phép dương tính giả. Dương tính giả là một trường hợp thử nghiệm vượt qua khi nó không thành công.

Ta hiện kiểm tra rằng độ dài của mảng không bằng 1 . Hãy sửa đổi kiểm tra để điều kiện này đúng khi nó không đúng. Thêm các dòng sau vào index.test.js :

todos / index.test.js
... describe("integration test", function() {     it("should be able to add and complete TODOs", function() {         let todos = new Todos();         todos.add("get up from bed");         todos.add("make up bed");         assert.notStrictEqual(todos.list().length, 1);     }); }); 

Lưu và thoát khỏi file .

Ta đã thêm hai mục CẦN LÀM. Hãy chạy thử nghiệm để xem điều gì sẽ xảy ra:

  • npm test

Điều này sẽ cung cấp những điều sau:

Output
... integrated test ✓ should be able to add and complete TODOs 1 passing (8ms)

Điều này đạt kết quả như mong đợi, vì độ dài lớn hơn 1. Tuy nhiên, nó đánh bại mục đích ban đầu của việc kiểm tra đầu tiên đó. Bài kiểm tra đầu tiên nhằm xác nhận ta bắt đầu ở trạng thái trống. Một bài kiểm tra tốt hơn sẽ xác nhận điều đó trong mọi trường hợp.

Hãy thay đổi bài kiểm tra để nó chỉ vượt qua nếu ta hoàn toàn không có VIỆC CẦN LÀM trong cửa hàng. áp dụng các thay đổi sau đối với index.test.js :

todos / index.test.js
... describe("integration test", function() {     it("should be able to add and complete TODOs", function() {         let todos = new Todos();         todos.add("get up from bed");         todos.add("make up bed");         assert.strictEqual(todos.list().length, 0);     }); }); 

Bạn đã thay đổi notStrictEqual() thành strictEqual() , một hàm kiểm tra sự bình đẳng giữa đối số thực tế và đối số mong đợi của nó. Sự bình đẳng nghiêm ngặt sẽ thất bại nếu các lập luận của ta không hoàn toàn giống nhau.

Lưu và thoát, sau đó chạy thử nghiệm để ta có thể xem điều gì sẽ xảy ra:

  • npm test

Lần này, kết quả sẽ hiển thị lỗi:

Output
... integration test 1) should be able to add and complete TODOs 0 passing (16ms) 1 failing 1) integration test should be able to add and complete TODOs: AssertionError [ERR_ASSERTION]: Input A expected to strictly equal input B: + expected - actual - 2 + 0 + expected - actual -2 +0 at Context.<anonymous> (index.test.js:9:10) npm ERR! Test failed. See above for more details.

Văn bản này sẽ hữu ích cho ta để gỡ lỗi tại sao kiểm tra không thành công. Lưu ý vì thử nghiệm không thành công, không có đánh dấu ở đầu trường hợp thử nghiệm.

Bản tóm tắt thử nghiệm của ta không còn ở cuối kết quả mà ngay sau khi danh sách các trường hợp thử nghiệm của ta được hiển thị:

... 0 passing (29ms)   1 failing ... 

Đầu ra còn lại cung cấp cho ta dữ liệu về các bài kiểm tra thất bại của ta . Đầu tiên, ta xem trường hợp thử nghiệm nào không thành công:

... 1) integrated test        should be able to add and complete TODOs: ... 

Sau đó, ta thấy tại sao thử nghiệm của ta không thành công:

...       AssertionError [ERR_ASSERTION]: Input A expected to strictly equal input B: + expected - actual  - 2 + 0       + expected - actual        -2       +0        at Context.<anonymous> (index.test.js:9:10) ... 

Một AssertionError được ném ra khi strictEqual() không thành công. Ta thấy rằng giá trị expected , 0, khác với giá trị actual , 2.

Sau đó, ta thấy dòng trong file thử nghiệm của ta , nơi mã không thành công. Trong trường hợp này, đó là dòng 10.

Bây giờ, ta đã tự thấy rằng thử nghiệm của ta sẽ thất bại nếu ta mong đợi các giá trị không chính xác. Hãy thay đổi trường hợp thử nghiệm của ta trở lại đúng giá trị của nó. Đầu tiên, hãy mở file :

  • nano index.test.js

Sau đó, lấy ra các dòng todos.add để mã của bạn trông giống như sau:

todos / index.test.js
... describe("integration test", function () {     it("should be able to add and complete TODOs", function () {         let todos = new Todos();         assert.strictEqual(todos.list().length, 0);     }); }); 

Lưu và thoát khỏi file .

Chạy nó để xác nhận nó trôi qua mà không có bất kỳ khả năng dương tính giả nào:

  • npm test

Đầu ra sẽ như sau:

Output
... integration test ✓ should be able to add and complete TODOs 1 passing (15ms)

Ta hiện đã cải thiện khả năng phục hồi của thử nghiệm một chút. Hãy tiếp tục với thử nghiệm tích hợp của ta . Bước tiếp theo là thêm một mục TODO mới vào index.test.js :

todos / index.test.js
... describe("integration test", function() {     it("should be able to add and complete TODOs", function() {         let todos = new Todos();         assert.strictEqual(todos.list().length, 0);          todos.add("run code");         assert.strictEqual(todos.list().length, 1);         assert.deepStrictEqual(todos.list(), [{title: "run code", completed: false}]);     }); }); 

Sau khi sử dụng hàm add() , ta xác nhận bây giờ ta có một strictEqual() LÀM đang được quản lý bởi đối tượng todos của ta với strictEqual() . Thử nghiệm tiếp theo của ta khẳng định dữ liệu trong todos với deepStrictEqual() . Hàm deepStrictEqual() kiểm tra đệ quy xem các đối tượng thực tế và mong đợi của ta có cùng thuộc tính hay không. Trong trường hợp này, nó kiểm tra xem các mảng mà ta mong đợi đều có đối tượng JavaScript bên trong chúng. Sau đó, nó sẽ kiểm tra xem các đối tượng JavaScript của chúng có cùng thuộc tính hay không, nghĩa là cả hai thuộc tính title của chúng đều là "run code" và cả hai thuộc tính completed của chúng đều là false .

Sau đó, ta hoàn thành các kiểm tra còn lại bằng cách sử dụng hai kiểm tra bình đẳng này nếu cần bằng cách thêm các dòng được đánh dấu sau:

todos / index.test.js
... describe("integration test", function() {     it("should be able to add and complete TODOs", function() {         let todos = new Todos();         assert.strictEqual(todos.list().length, 0);          todos.add("run code");         assert.strictEqual(todos.list().length, 1);         assert.deepStrictEqual(todos.list(), [{title: "run code", completed: false}]);          todos.add("test everything");         assert.strictEqual(todos.list().length, 2);         assert.deepStrictEqual(todos.list(),             [                 { title: "run code", completed: false },                 { title: "test everything", completed: false }             ]         );          todos.complete("run code");         assert.deepStrictEqual(todos.list(),             [                 { title: "run code", completed: true },                 { title: "test everything", completed: false }             ]     );   }); }); 

Lưu và thoát khỏi file .

Thử nghiệm của ta bây giờ bắt chước thử nghiệm thủ công của ta . Với các bài kiểm tra lập trình này, ta không cần phải kiểm tra kết quả liên tục nếu các bài kiểm tra của ta vượt qua khi ta chạy chúng. Bạn thường muốn kiểm tra mọi khía cạnh sử dụng đảm bảo mã được kiểm tra đúng cách.

Hãy chạy thử nghiệm của ta với thử nghiệm npm test để có được kết quả quen thuộc này:

Output
... integrated test ✓ should be able to add and complete TODOs 1 passing (9ms)

Đến đây bạn đã cài đặt một bài kiểm tra tích hợp với khuôn khổ Mocha và thư viện assert .

Hãy xem xét một tình huống mà ta đã chia sẻ module của bạn với một số nhà phát triển khác và họ hiện đang đưa ra phản hồi cho ta . Một phần lớn user của ta muốn hàm complete() trả về lỗi nếu chưa có TODO nào được thêm vào. Hãy thêm chức năng này trong hàm complete() của ta .

Mở index.js trong editor của bạn:

  • nano index.js

Thêm phần sau vào hàm:

todos / index.js
... complete(title) {     if (this.todos.length === 0) {         throw new Error("You have no TODOs stored. Why don't you add one first?");     }      let todoFound = false     this.todos.forEach((todo) => {         if (todo.title === title) {             todo.completed = true;             todoFound = true;             return;         }     });      if (!todoFound) {         throw new Error(`No TODO was found with the title: "${title}"`);     } } ... 

Lưu và thoát khỏi file .

Bây giờ ta hãy thêm một thử nghiệm mới cho tính năng mới này. Ta muốn xác minh nếu ta gọi hoàn thành trên một đối tượng Todos không có mục nào, nó sẽ trả về lỗi đặc biệt của ta .

Quay lại index.test.js :

  • nano index.test.js

Ở cuối file , thêm mã sau:

todos / index.test.js
... describe("complete()", function() {     it("should fail if there are no TODOs", function() {         let todos = new Todos();         const expectedError = new Error("You have no TODOs stored. Why don't you add one first?");          assert.throws(() => {             todos.complete("doesn't exist");         }, expectedError);     }); }); 

Ta sử dụng describe()it() như trước đây. Thử nghiệm của ta bắt đầu bằng việc tạo một đối tượng todos mới. Sau đó, ta xác định lỗi mà ta mong đợi nhận được khi ta gọi hàm complete() .

Tiếp theo, ta sử dụng hàm throws() của module assert . Chức năng này được tạo ra để ta có thể xác minh các lỗi được đưa ra trong mã của ta . Đối số đầu tiên của nó là một hàm có chứa mã ném lỗi. Đối số thứ hai là lỗi mà ta mong đợi nhận được.

Trong terminal của bạn, hãy chạy thử nghiệm với npm test và bây giờ bạn sẽ thấy kết quả sau:

Output
... integrated test ✓ should be able to add and complete TODOs complete() ✓ should fail if there are no TODOs 2 passing (25ms)

Kết quả này nêu bật lợi ích tại sao ta thực hiện kiểm thử tự động với Mocha và assert . Bởi vì các bài kiểm tra của ta được lập kịch bản, mỗi khi ta chạy npm test , ta xác minh tất cả các bài kiểm tra của ta đều vượt qua. Ta không cần phải kiểm tra thủ công xem mã khác có còn hoạt động hay không; ta biết rằng đó là vì bài kiểm tra ta vẫn vượt qua.

Lúc này, các thử nghiệm của ta đã xác minh kết quả của mã đồng bộ. Hãy xem ta cần phải điều chỉnh thói quen thử nghiệm mới của bạn như thế nào để hoạt động với mã không đồng bộ.

Bước 4 - Kiểm tra mã không đồng bộ

Một trong những tính năng ta muốn có trong module TODO của bạn là tính năng xuất CSV. Thao tác này sẽ in tất cả những VIỆC CẦN LÀM mà ta có trong cửa hàng cùng với trạng thái đã hoàn thành vào một file . Điều này yêu cầu ta sử dụng module fs — một module Node.js được tích hợp sẵn để làm việc với hệ thống file .

Ghi vào file là một hoạt động không đồng bộ . Có nhiều cách để ghi vào một file trong Node.js. Ta có thể sử dụng callbacks, Promises hoặc các từ khóa async / await . Trong phần này, ta sẽ xem xét cách ta viết các bài kiểm tra cho các phương pháp khác nhau đó.

Gọi lại

Một hàm gọi lại được sử dụng làm đối số cho một hàm không đồng bộ. Nó được gọi khi hoạt động không đồng bộ hoàn thành.

Hãy thêm một hàm vào lớp Todos của ta được gọi là saveToFile() . Hàm này sẽ xây dựng một chuỗi bằng cách lặp qua tất cả các mục CẦN LÀM và ghi chuỗi đó vào một file .

Mở index.js của bạn:

  • nano index.js

Trong file này, hãy thêm mã được đánh dấu sau:

todos / index.js
const fs = require('fs');  class Todos {     constructor() {         this.todos = [];     }      list() {         return [...this.todos];     }      add(title) {         let todo = {             title: title,             completed: false,         }         this.todos.push(todo);     }      complete(title) {         if (this.todos.length === 0) {             throw new Error("You have no TODOs stored. Why don't you add one first?");         }          let todoFound = false         this.todos.forEach((todo) => {             if (todo.title === title) {                 todo.completed = true;                 todoFound = true;                 return;             }         });          if (!todoFound) {             throw new Error(`No TODO was found with the title: "${title}"`);         }     }      saveToFile(callback) {         let fileContents = 'Title,Completed\n';         this.todos.forEach((todo) => {             fileContents += `${todo.title},${todo.completed}\n`         });          fs.writeFile('todos.csv', fileContents, callback);     } }  module.exports = Todos; 

Trước tiên, ta phải nhập module fs trong file của ta . Sau đó, ta đã thêm chức năng saveToFile() . Hàm của ta nhận một hàm gọi lại sẽ được sử dụng khi quá trình ghi file hoàn tất. Trong hàm đó, ta tạo một biến fileContents để lưu trữ toàn bộ chuỗi mà ta muốn lưu dưới dạng file . Nó được khởi tạo với tiêu đề của CSV. Sau đó, ta lặp qua từng mục TODO với phương thức forEach() của mảng bên trong. Như ta đã lặp, ta thêm titlecompleted thuộc tính của cá nhân todos đối tượng.

Cuối cùng, ta sử dụng module fs để ghi file với hàm writeFile() . Đối số đầu tiên của ta là tên file : todos.csv . Thứ hai là nội dung của file , trong trường hợp này là biến fileContents . Đối số cuối cùng của ta là hàm gọi lại, hàm này xử lý bất kỳ lỗi ghi file nào.

Lưu và thoát khỏi file .

Bây giờ ta hãy viết một bài kiểm tra cho saveToFile() của ta . Thử nghiệm của ta sẽ thực hiện hai việc: xác nhận file tồn tại ngay từ đầu, và sau đó xác minh file có nội dung phù hợp.

Mở file index.test.js :

  • nano index.test.js

hãy bắt đầu bằng cách tải module fs ở đầu file , vì ta sẽ sử dụng nó để giúp kiểm tra kết quả của ta :

todos / index.test.js
const Todos = require('./index'); const assert = require('assert').strict; const fs = require('fs'); ... 

Bây giờ, ở cuối file , hãy thêm trường hợp thử nghiệm mới của ta :

todos / index.test.js
... describe("saveToFile()", function() {     it("should save a single TODO", function(done) {         let todos = new Todos();         todos.add("save a CSV");         todos.saveToFile((err) => {             assert.strictEqual(fs.existsSync('todos.csv'), true);             let expectedFileContents = "Title,Completed\nsave a CSV,false\n";             let content = fs.readFileSync("todos.csv").toString();             assert.strictEqual(content, expectedFileContents);             done(err);         });     }); }); 

Giống như trước đây, ta sử dụng describe() để group thử nghiệm của ta riêng biệt với những thử nghiệm khác vì nó liên quan đến chức năng mới. Hàm it() hơi khác so với các hàm khác. Thông thường, hàm gọi lại mà ta sử dụng không có đối số. Lần này, ta đã done như một đối số. Ta cần đối số này khi kiểm tra các hàm với các lệnh gọi lại. Hàm gọi lại done() được Mocha sử dụng để cho biết khi nào một hàm không đồng bộ được hoàn thành.

Tất cả các hàm gọi lại đang được thử nghiệm trong Mocha phải gọi hàm gọi lại done() . Nếu không, Mocha sẽ không bao giờ biết khi nào chức năng hoàn thành và sẽ bị mắc kẹt khi chờ tín hiệu.

Tiếp tục, ta tạo version Todos và thêm một mục duy nhất vào nó. Sau đó, ta gọi hàm saveToFile() , với một lệnh gọi lại ghi lại lỗi ghi file . Lưu ý cách kiểm tra của ta cho chức năng này nằm trong lệnh gọi lại. Nếu mã kiểm tra của ta nằm ngoài lệnh gọi lại, nó sẽ không thành công miễn là mã được gọi trước khi quá trình ghi file hoàn tất.

Trong chức năng gọi lại của ta , trước tiên ta kiểm tra xem file của ta có tồn tại không:

todos / index.test.js
... assert.strictEqual(fs.existsSync('todos.csv'), true); ... 

Hàm fs.existsSync() trả về true nếu đường dẫn file trong đối số của nó tồn tại, ngược lại là false .

Lưu ý: Các chức năng của module fs là không đồng bộ theo mặc định. Tuy nhiên, đối với các chức năng chính, chúng đã tạo ra các bản sao đồng bộ. Việc kiểm tra này đơn giản hơn bằng cách sử dụng các hàm đồng bộ, vì ta không phải lồng mã không đồng bộ đảm bảo nó hoạt động. Trong module fs , các chức năng đồng bộ thường kết thúc bằng "Sync" ở cuối tên của chúng.

Sau đó, ta tạo một biến để lưu trữ giá trị mong đợi của ta :

todos / index.test.js
... let expectedFileContents = "Title,Completed\nsave a CSV,false\n"; ... 

Ta sử dụng readFileSync() của module fs để đọc file một cách đồng bộ:

todos / index.test.js
... let content = fs.readFileSync("todos.csv").toString(); ... 

Bây giờ ta cung cấp readFileSync() với đường dẫn phù hợp cho file : todos.csv . Khi readFileSync() trả về một đối tượng Buffer lưu trữ dữ liệu binary , ta sử dụng phương thức toString() của nó để ta có thể so sánh giá trị của nó với chuỗi mà ta mong đợi đã lưu.

Giống như trước đây, ta sử dụng strictEqual của module assert để thực hiện so sánh:

todos / index.test.js
... assert.strictEqual(content, expectedFileContents); ... 

Ta kết thúc thử nghiệm của bạn bằng cách gọi lệnh gọi lại done() , đảm bảo Mocha biết để dừng thử nghiệm trường hợp đó:

todos / index.test.js
... done(err); ... 

Ta cung cấp đối tượng err to done() để Mocha có thể không kiểm tra được trong trường hợp xảy ra lỗi.

Lưu và thoát khỏi index.test.js .

Hãy chạy thử nghiệm này với npm test như trước. Control panel của bạn sẽ hiển thị kết quả này:

Output
... integrated test ✓ should be able to add and complete TODOs complete() ✓ should fail if there are no TODOs saveToFile() ✓ should save a single TODO 3 passing (15ms)

Đến đây bạn đã thử nghiệm chức năng không đồng bộ đầu tiên của bạn với Mocha bằng cách sử dụng lệnh gọi lại. Nhưng tại thời điểm viết hướng dẫn này, Promise phổ biến hơn các lệnh gọi lại trong mã Node.js mới, như đã giải thích trong bài viết Cách viết mã không đồng bộ trong Node.js của ta . Tiếp theo, ta hãy tìm hiểu cách ta có thể kiểm tra chúng với Mocha.

Lời hứa

Promise là một đối tượng JavaScript cuối cùng sẽ trả về một giá trị. Khi một Lời hứa thành công, nó sẽ được giải quyết. Khi nó gặp lỗi, nó bị từ chối.

Hãy sửa đổi hàm saveToFile() để nó sử dụng saveToFile() thay vì callback. Mở index.js :

  • nano index.js

Đầu tiên, ta cần thay đổi cách tải module fs . Trong index.js của bạn, hãy thay đổi câu lệnh index.js require() ở đầu file để trông giống như sau:

todos / index.js
... const fs = require('fs').promises; ... 

Ta vừa nhập module fs sử dụng Promises thay vì gọi lại. Bây giờ, ta cần thực hiện một số thay đổi đối với saveToFile() để nó hoạt động với Promises thay thế.

Trong editor của bạn, hãy áp dụng các thay đổi sau đối với hàm saveToFile() để loại bỏ các lệnh gọi lại:

todos / index.js
... saveToFile() {     let fileContents = 'Title,Completed\n';     this.todos.forEach((todo) => {         fileContents += `${todo.title},${todo.completed}\n`     });      return fs.writeFile('todos.csv', fileContents); } ... 

Sự khác biệt đầu tiên là hàm của ta không còn chấp nhận bất kỳ đối số nào. Với Promises, ta không cần hàm gọi lại. Thay đổi thứ hai liên quan đến cách file được viết. Bây giờ ta trả về kết quả của lời hứa writeFile() .

Lưu và đóng index.js .

Bây giờ hãy điều chỉnh thử nghiệm của ta để nó hoạt động với Promises. Mở index.test.js :

  • nano index.test.js

Thay đổi kiểm tra saveToFile() thành thế này:

todos / index.js
... describe("saveToFile()", function() {     it("should save a single TODO", function() {         let todos = new Todos();         todos.add("save a CSV");         return todos.saveToFile().then(() => {             assert.strictEqual(fs.existsSync('todos.csv'), true);             let expectedFileContents = "Title,Completed\nsave a CSV,false\n";             let content = fs.readFileSync("todos.csv").toString();             assert.strictEqual(content, expectedFileContents);         });     }); }); 

Thay đổi đầu tiên ta cần thực hiện là xóa lệnh gọi lại done() khỏi các đối số của nó. Nếu Mocha chuyển đối số done() , nó cần được gọi nếu không nó sẽ gặp lỗi như sau:

1) saveToFile()        should save a single TODO:      Error: Timeout of 2000ms exceeded. For async tests and hooks, ensure "done()" is called; if returning a Promise, ensure it resolves. (/home/ubuntu/todos/index.test.js)       at listOnTimeout (internal/timers.js:536:17)       at processTimers (internal/timers.js:480:7) 

Khi kiểm tra Promises, không bao gồm lệnh gọi lại done() trong it() .

Để kiểm tra lời hứa của bạn , ta cần đặt mã xác nhận của bạn trong hàm then() . Lưu ý ta trả về lời hứa này trong thử nghiệm và ta không có hàm catch() để bắt khi Promise bị từ chối.

Ta trả về lời hứa để bất kỳ lỗi nào được đưa ra trong hàm then() sẽ được chuyển sang hàm it() . Nếu các lỗi không bị sủi bọt thì Mocha sẽ không bị lỗi test case. Khi kiểm tra Promises, bạn cần sử dụng return trên Promise đang được kiểm tra. Nếu không, bạn có nguy cơ bị dương tính giả.

Ta cũng bỏ qua mệnh đề catch() vì Mocha có thể phát hiện khi nào một lời hứa bị từ chối. Nếu bị từ chối, nó sẽ tự động không đạt được bài kiểm tra.

Bây giờ ta đã có bài kiểm tra tại chỗ, hãy lưu và thoát file , sau đó chạy Mocha với npm test và để xác nhận ta nhận được kết quả thành công:

Output
... integrated test ✓ should be able to add and complete TODOs complete() ✓ should fail if there are no TODOs saveToFile() ✓ should save a single TODO 3 passing (18ms)

Ta đã thay đổi mã và thử nghiệm của bạn để sử dụng Promises và bây giờ ta biết chắc rằng nó hoạt động. Nhưng các mẫu không đồng bộ mới nhất sử dụng từ khóa async / await do đó ta không phải tạo nhiều hàm then() để xử lý kết quả thành công. Hãy xem cách ta có thể kiểm tra với async / await .

async / await

Các từ khóa async / await giúp làm việc với Promise ít dài dòng hơn. Khi ta xác định một hàm là không đồng bộ với từ khóa async , ta có thể nhận được bất kỳ kết quả nào trong tương lai trong hàm đó với từ khóa await . Bằng cách này, ta có thể sử dụng Promises mà không cần phải sử dụng các hàm then() hoặc catch() .

Ta có thể đơn giản hóa kiểm tra saveToFile() của ta , đó là lời hứa dựa trên async / await . Trong editor của bạn, hãy thực hiện các chỉnh sửa nhỏ này đối với kiểm tra saveToFile() trong index.test.js :

todos / index.test.js
... describe("saveToFile()", function() {     it("should save a single TODO", async function() {         let todos = new Todos();         todos.add("save a CSV");         await todos.saveToFile();          assert.strictEqual(fs.existsSync('todos.csv'), true);         let expectedFileContents = "Title,Completed\nsave a CSV,false\n";         let content = fs.readFileSync("todos.csv").toString();         assert.strictEqual(content, expectedFileContents);     }); }); 

Thay đổi đầu tiên là hàm được sử dụng bởi hàm it() bây giờ có từ khóa async khi nó được định nghĩa. Điều này cho phép ta sử dụng từ khóa await bên trong phần thân của nó.

Thay đổi thứ hai được tìm thấy khi ta gọi saveToFile() . Từ khóa await được sử dụng trước khi nó được gọi. Bây giờ Node.js biết phải đợi cho đến khi chức năng này được giải quyết trước khi tiếp tục thử nghiệm.

Mã hàm của ta dễ đọc hơn bây giờ vì ta đã chuyển mã có trong hàm then() sang phần thân của hàm it() . Chạy mã này với npm test tạo ra kết quả này:

Output
... integrated test ✓ should be able to add and complete TODOs complete() ✓ should fail if there are no TODOs saveToFile() ✓ should save a single TODO 3 passing (30ms)

Bây giờ ta có thể kiểm tra các hàm không đồng bộ bằng cách sử dụng bất kỳ mô hình không đồng bộ nào trong ba mô hình không đồng bộ một cách thích hợp.

Ta đã đề cập rất nhiều mặt bằng việc thử nghiệm mã đồng bộ và không đồng bộ với Mocha. Tiếp theo, hãy đi sâu hơn một chút về một số chức năng khác mà Mocha cung cấp để cải thiện trải nghiệm thử nghiệm của ta , đặc biệt là cách hook có thể thay đổi môi trường thử nghiệm.

Bước 5 - Sử dụng Hooks để cải thiện các trường hợp thử nghiệm

Hooks là một tính năng hữu ích của Mocha cho phép ta cấu hình môi trường trước và sau khi kiểm tra. Ta thường thêm các hook trong khối hàm description describe() , vì chúng chứa logic cài đặt và chia nhỏ cụ thể cho một số trường hợp thử nghiệm.

Mocha cung cấp bốn hook mà ta có thể sử dụng trong các thử nghiệm của bạn :

  • before : hook này được chạy một lần trước khi thử nghiệm đầu tiên bắt đầu.
  • beforeEach : hook này được chạy trước mọi trường hợp thử nghiệm.
  • after : hook này được chạy một lần sau khi hoàn tất test case cuối cùng.
  • afterEach : hook này được chạy sau mỗi test case.

Khi ta kiểm tra một chức năng hoặc tính năng nhiều lần, các hook rất hữu ích vì chúng cho phép ta tách mã cài đặt của thử nghiệm (như tạo đối tượng todos ) khỏi mã xác nhận của thử nghiệm.

Để xem giá trị của hook, hãy thêm nhiều bài kiểm tra hơn vào khối kiểm tra saveToFile() của ta .

Mặc dù ta đã xác nhận ta có thể lưu các mục CẦN LÀM của bạn vào một file , nhưng ta chỉ lưu một mục. Hơn nữa, mục không được đánh dấu là đã hoàn thành. Hãy thêm các bài kiểm tra khác đảm bảo rằng các khía cạnh khác nhau của module của ta hoạt động.

Đầu tiên, hãy thêm thử nghiệm thứ hai để xác nhận file của ta được lưu đúng cách khi ta hoàn thành một mục CẦN LÀM. Mở file index.test.js của bạn trong editor của bạn:

  • nano index.test.js

Thay đổi bài kiểm tra cuối cùng thành sau:

todos / index.test.js
... describe("saveToFile()", function () {     it("should save a single TODO", async function () {         let todos = new Todos();         todos.add("save a CSV");         await todos.saveToFile();          assert.strictEqual(fs.existsSync('todos.csv'), true);         let expectedFileContents = "Title,Completed\nsave a CSV,false\n";         let content = fs.readFileSync("todos.csv").toString();         assert.strictEqual(content, expectedFileContents);     });      it("should save a single TODO that's completed", async function () {         let todos = new Todos();         todos.add("save a CSV");         todos.complete("save a CSV");         await todos.saveToFile();          assert.strictEqual(fs.existsSync('todos.csv'), true);         let expectedFileContents = "Title,Completed\nsave a CSV,true\n";         let content = fs.readFileSync("todos.csv").toString();         assert.strictEqual(content, expectedFileContents);     }); }); 

Bài kiểm tra tương tự như những gì ta đã có trước đây. Sự khác biệt chính là ta gọi hàm complete() trước khi ta gọi saveToFile() và các Nội dung expectedFileContents của ta hiện có true thay vì false đối với giá trị của cột completed .

Lưu và thoát khỏi file .

Hãy chạy thử nghiệm mới của ta và tất cả các thử nghiệm khác, với npm test :

  • npm test

Điều này sẽ cung cấp những điều sau:

Output
... integrated test ✓ should be able to add and complete TODOs complete() ✓ should fail if there are no TODOs saveToFile() ✓ should save a single TODO ✓ should save a single TODO that's completed 4 passing (26ms)

Nó hoạt động như mong đợi. Tuy nhiên, vẫn có chỗ để cải thiện. Cả hai đều phải khởi tạo một đối tượng Todos khi bắt đầu thử nghiệm. Khi ta thêm nhiều trường hợp thử nghiệm hơn, điều này nhanh chóng trở nên lặp lại và lãng phí bộ nhớ. Ngoài ra, mỗi khi ta chạy thử nghiệm, nó sẽ tạo ra một file . Điều này có thể bị nhầm lẫn với kết quả thực bởi một người ít quen thuộc với module . Sẽ thật tuyệt nếu ta dọn dẹp các file kết quả của bạn sau khi thử nghiệm.

Hãy thực hiện những cải tiến này bằng cách sử dụng móc thử nghiệm. Ta sẽ sử dụng beforeEach() để cài đặt bộ cố định thử nghiệm của các mục TODO. Vật cố định thử nghiệm là bất kỳ trạng thái nhất quán nào được sử dụng trong thử nghiệm. Trong trường hợp của ta , vật cố định thử nghiệm của ta là một đối tượng todos mới đã thêm một mục TODO vào nó. Sau đó, ta sẽ sử dụng afterEach() để xóa file được tạo bởi thử nghiệm.

Trong index.test.js , hãy áp dụng các thay đổi sau đối với thử nghiệm cuối cùng của bạn cho saveToFile() :

todos / index.test.js
... describe("saveToFile()", function () {     beforeEach(function () {         this.todos = new Todos();         this.todos.add("save a CSV");     });      afterEach(function () {         if (fs.existsSync("todos.csv")) {             fs.unlinkSync("todos.csv");         }     });      it("should save a single TODO without error", async function () {         await this.todos.saveToFile();          assert.strictEqual(fs.existsSync("todos.csv"), true);         let expectedFileContents = "Title,Completed\nsave a CSV,false\n";         let content = fs.readFileSync("todos.csv").toString();         assert.strictEqual(content, expectedFileContents);     });      it("should save a single TODO that's completed", async function () {         this.todos.complete("save a CSV");         await this.todos.saveToFile();          assert.strictEqual(fs.existsSync('todos.csv'), true);         let expectedFileContents = "Title,Completed\nsave a CSV,true\n";         let content = fs.readFileSync("todos.csv").toString();         assert.strictEqual(content, expectedFileContents);     }); }); 

Hãy chia nhỏ tất cả những thay đổi mà ta đã thực hiện. Ta đã thêm một beforeEach() khối kiểm tra:

todos / index.test.js
... beforeEach(function () {     this.todos = new Todos();     this.todos.add("save a CSV"); }); ... 

Hai dòng mã này tạo ra một đối tượng Todos mới sẽ có sẵn trong mỗi thử nghiệm của ta . Với Mocha, đối tượng this trong beforeEach() tham chiếu đến cùng một đối tượng this trong it() . this giống nhau đối với mọi khối mã bên trong khối description describe() . Để biết thêm thông tin về this , hãy xem hướng dẫn của ta Hiểu Điều này, Ràng buộc, Gọi và Áp dụng trong JavaScript .

Chia sẻ ngữ cảnh mạnh mẽ này là lý do tại sao ta có thể nhanh chóng tạo các thiết bị kiểm tra hoạt động cho cả hai bài kiểm tra của ta .

Sau đó, ta xóa file CSV của bạn trong hàm afterEach() :

todos / index.test.js
... afterEach(function () {     if (fs.existsSync("todos.csv")) {         fs.unlinkSync("todos.csv");     } }); ... 

Nếu thử nghiệm của ta không thành công, thì có thể nó chưa được tạo file . Đó là lý do tại sao ta kiểm tra xem file có tồn tại hay không trước khi ta sử dụng hàm unlinkSync() để xóa nó.

Các thay đổi còn lại chuyển tham chiếu từ todos , đã được tạo trước đó trong hàm it() sang this.todos có sẵn trong ngữ cảnh Mocha. Ta cũng xóa các đường mà trước đây instantiated todos trong các trường hợp thử nghiệm cá nhân.

Bây giờ, hãy chạy file này để xác nhận các thử nghiệm của ta vẫn hoạt động. Nhập npm test vào terminal của bạn để nhận:

Output
... integrated test ✓ should be able to add and complete TODOs complete() ✓ should fail if there are no TODOs saveToFile() ✓ should save a single TODO without error ✓ should save a single TODO that's completed 4 passing (20ms)

Các kết quả đều giống nhau và vì một lợi ích, ta đã giảm một chút thời gian cài đặt cho các thử nghiệm mới cho hàm saveToFile() và tìm ra giải pháp cho file CSV còn lại.

Kết luận

Trong hướng dẫn này, bạn đã viết một module Node.js để quản lý các mục TODO và kiểm tra mã theo cách thủ công bằng cách sử dụng Node.js REPL. Sau đó, bạn tạo một file thử nghiệm và sử dụng khuôn khổ Mocha để chạy các thử nghiệm tự động. Với module assert , bạn có thể xác minh mã của bạn hoạt động. Bạn cũng đã thử nghiệm các chức năng đồng bộ và không đồng bộ với Mocha. Cuối cùng, bạn đã tạo các hook với Mocha giúp cho việc viết nhiều trường hợp thử nghiệm liên quan dễ đọc và dễ bảo trì hơn nhiều.

Được trang bị với sự hiểu biết này, hãy thử thách bản thân để viết các bài kiểm tra cho các module Node.js mới mà bạn đang tạo. Bạn có thể nghĩ về các đầu vào và kết quả của hàm và viết thử nghiệm trước khi viết mã không?

Nếu bạn muốn biết thêm thông tin về khung thử nghiệm Mocha, hãy xem tài liệu chính thức của Mocha . Nếu bạn muốn tiếp tục học Node.js, bạn có thể quay lại trang Cách viết mã trong chuỗi Node.js.


Tags:

Các tin liên quan