Bài viết này sẽ liệt kê những khái niệm cũng như cách sử dụng và lưu ý của Mocha test framework. Những khái niệm liệt kê dưới đây dựa trên sự phổ biến của nó khi triển khai ở Cybozu Việt Nam trong dự án Garoon's end-to-end testing
Mocha test framework
Mocha là một test framework chạy trên NodeJS với nhiều tính năng hỗ trợ, nó giúp việc viết test automation trở nên đơn giản, linh hoạt.
Thông thường, trong tự động hóa kiểm thử để triển khai một test case bạn cần nơi để mô tả tiêu đề, các bước của test case, sự liên kết của các bước, chuẩn bị test data, xóa test data, hiển thị kết quả sau khi chạy… Mocha sinh ra để phục vụ những việc như vậy.
Cũng như các test frameworks khác, như: Jasmine, Jest, Cucumber thì Mocha cũng tương tự như các framework này. Và tất nhiên mỗi framework sẽ có những ưu nhược và điểm riêng của nó, tùy vào nhu cầu, tính chất của dự án chúng ta đang làm để có sự lựa chọn test framework cho phù hợp.
Để sử dụng Mocha một cách hiệu quả, chúng ta nên hiểu một số khái niệm bên dưới:
describe()
Là một chức năng dùng để nhóm các test case có mối quan hệ mật thiết lại với nhau. Và khi gom các test case lại với nhau, thông thường ta gọi là test suite
describe('Kiểm tra tính năng search tiếng Việt', function() {
// Trường hợp 1: search với tiếng Việt chữ thường
// Trường hợp 2: search với tiếng Việt chữ hoa
});
Có thể khai báo nhiều describe()
lồng nhau. Vậy nên chúng ta có thể linh động trong việc tổ chức test script sao cho phù hợp với nội dung và mục đích test.
describe('mô tả test suite', function(){ // ...})
. Hàm describe
nhận vào hai tham số.
Tham số đầu tiên là phần “mô tả” được viết dạng chuỗi, chúng ta sẽ diễn tả mục đích, tính chất hoặc những tính năng sẽ được test bên trong describe
. Nội dung này nên được viết một cách rõ ràng, ngắn gọn dễ hiểu và đầy đủ nhất để đảm bảo được tính bảo trì của test script. Hơn nữa phần này sẽ được in ra màn hình report sau khi test kết thúc, việc viết mô tả tốt sẽ phần nào giúp ích cho việc đọc report cho kết quả test hiệu quả hơn.
Tham số thứ hai là một callback triển khai nội dung muốn triển khai trong describe.
describe('Kiểm tra tính năng search', function() {
describe('Kiểm tra tính năng search tiếng Việt', function() {
// Trường hợp 1: search với tiếng Việt chữ thường
// Trường hợp 2: search với tiếng Việt chữ hoa
});
describe('Kiểm tra tính năng search tiếng Anh', function() {
// Trường hợp 1: search với tiếng Anh chữ thường
// Trường hợp 2: search với tiếng Anh chữ hoa
});
describe('Kiểm tra tính năng search tiếng Nhật', function() {
// Trường hợp 1: search với tiếng Nhật chữ thường
// Trường hợp 2: search với tiếng Nhật chữ hoa
});
});
it()
Nội dung chính của test case sẽ được viết trong mục it()
, Mocha sẽ hiểu mỗi it()
là một test case trong test report và được xử lý tuần tự từ trên xuống nếu khai báo nhiều it()
trong một describe()
Tổng thể it hook:
it('mô tả test case mà con người hiểu được', function() { //... })
Tương tự describe
bản thân it
hook cũng có hai tham số.
Tham số thứ nhất là mô tả: Chúng ta nên viết mô tả mà con người hiểu được một cách đơn giản không cần phải nội suy.
Tham số thứ hai là một callback
describe('Kiểm tra tính năng search', function() {
it('Trường hợp 1: search với tiếng Việt', function() {
// các bước test
});
it('Trường hợp 2: search với tiếng Anh', function() {
// các bước test
});
it('Trường hợp 3: search với tiếng Nhật', function() {
// các bước test
});
});
Sau khi running test, nếu test case thành công, chúng ta sẽ có kết quả như sau:
[chrome 83.0.4103.116 Mac OS X #0-0] Kiểm tra tính năng search
[chrome 83.0.4103.116 Mac OS X #0-0] ✓ Trường hợp 1: search với tiếng Việt
[chrome 83.0.4103.116 Mac OS X #0-0] ✓ Trường hợp 2: search với tiếng Anh
[chrome 83.0.4103.116 Mac OS X #0-0] ✓ Trường hợp 3: search với tiếng Nhật
Hooks
Mocha cung cấp cho chúng ta một số interface với vai trò và thời điểm khởi chạy nhất định. Chúng giúp chúng ta phân bổ các bước trong kịch bản test phù hợp. Việc tuân thủ và áp dụng các hooks khi triển khai test case giúp cho chúng ta rất nhiều như dễ đọc, maintain dễ dàng và phát huy hiệu quả khi test case rơi vào flaky test. Trước khi đi vào tìm hiểu chi tiết các hook. Chúng ta cùng xem một ví dụ sau đây:
describe('Kiểm tra tính năng search', function() {
before(function() {
// tạo user-01
// Chạy một lần duy nhất
});
beforeEach(function() {
// đăng nhập với user-01
// truy cập vào trang tìm kiếm
// Chạy mỗi khi it khởi chạy
});
it('Trường hợp 1: search với tiếng Việt', function() {
// các bước test
});
it('Trường hợp 2: search với tiếng Anh', function() {
// các bước test
});
it('Trường hợp 3: search với tiếng Nhật', function() {
// các bước test
});
afterEach(function() {
// đăng xuất user-01
// Chạy một lân duy nhất mỗi khi it kết thúc
});
after(function() {
// xóa user-01
// Chạy một lần duy nhất sau it cuối cùng chạy
});
});
before()
Chạy một lần duy nhất, trước khi test case (it
) đầu tiên trong describe
được khởi chạy.
Thông thường hook này chứa những xử lý liên quan đến việc chuẩn bị một số điều kiện tiên quyết để các test case có thể chạy được. Ví dụ: Bật/tắt một số setting hệ thống, chuẩn bị các dữ liệu về người dùng…
beforeEach()
Chạy trước khi mỗi khi test case (it) khởi chạy trong một describe. Ví dụ: login vào hệ thống.
afterEach()
Tương tự beforeEach
. Hook này chạy sau khi mỗi test case (it) được chạy trong một describe. Ví dụ: logout user ra khỏi hệ thống. Hook này thường sẽ chứa các bước để xóa dữ liệu phát sinh do test case.
after()
Tương tự before
. Hook này chạy một lần sau khi test case(it) cuối cùng trong describe được chạy. Đối với những dữ liệu phát sinh phục vụ chung cho toàn bộ các test case sẽ được làm sạch một lần bằng cách xử lý tại after hook.
Kiểm chứng (Assertions)
Để kiểm tra, so sánh kết quả mong đợi của test case và kết quả của chương trình thực hiện, Mocha cho phép chúng ta sử dụng các thư viện bên ngoài Mocha như should.js, expect.js hoặc một thư viện khá phổ biến là chai.
describe('Assertions', function() {
it('Sử dụng chai library trong ', function() {
// Khai báo các biến cần thiết
const expect = require('chai').expect;
const food = 'chicken';
const drink = { tea: ['phuclong', 'highland', 'gongcha'] };
// Dùng chai library để kiểm trả các thuộc tính của các biến.
expect(food).to.be.a('string');
expect(food).to.equal('chicken');
expect(food).to.have.lengthOf(7);
expect(drink)
.to.have.property('tea')
.with.lengthOf(3);
});
});
Thử lại test (Retry Tests)
Để đối phó với vấn đề không ổn định của test case (flaky test) trong quá trình thực hiện test tự động. Như tốc độ mạng, tốc độ khởi tạo giao diện... Mocha có tính năng Retry cho test cas failed.
Tính năng Retry trong Mocha cho phép người dùng định nghĩa số lần test lại (re-run) các it()
, beforeEach/afterEach
.
Để hiểu rõ chi hơn vể Retry test có thể tham khảo bài viết “Khi sử dụng Retry, các hooks của Mocha hoạt động ra sao?”.
Cũng theo Mocha khuyến cáo, chúng ta không nên áp dụng tính năng này cho unit test, mà chỉ áp dụng cho end-to-end test.
Ví dụ bên dưới chúng ta chỉ định chạy lại tối đa 3 lần nếu test case này failed.
describe('Address Book Shared', () => {
it('should be added an AddressBook successull',
() => {
// ...
}, 3);
});
Báo cáo kết quả test (Reporters)
Kết quả của quá trình chạy test được thể hiện qua nhiều cách khác nhau, mặc định Mocha sẽ dùng Spec Reporter. Spec reporter sẽ thể hiện rõ ràng các mô tả của describe()
và it()
và phân theo cấp bậc như chúng ta đã tổ chức trong test script. Ví dụ termial window hiển thị như bên dưới khi chạy test.
[chrome 83.0.4103.116 Mac OS X #0-0] Kiểm tra tính năng search
[chrome 83.0.4103.116 Mac OS X #0-0] Kiểm tra tính năng search tiếng Việt
[chrome 83.0.4103.116 Mac OS X #0-0] ✓ Trường hợp 1
[chrome 83.0.4103.116 Mac OS X #0-0]
[chrome 83.0.4103.116 Mac OS X #0-0] Kiểm tra tính năng search tiếng Anh
[chrome 83.0.4103.116 Mac OS X #0-0] ✓ Trường hợp 1
[chrome 83.0.4103.116 Mac OS X #0-0]
Trong trường hợp dự án của bạn đang thực hiện số lượng test case lớn, và người dùng chỉ muốn biết trạng thái sau cùng của mỗi test case thì có thể dùng Dot Matrix reporter thông qua tham số --reporter dot
. Mỗi test case thực hiện thành công sẽ in ra một dấu chấm (.), test case ở trạng thái chờ (pending) được in ra dấu phẩy (,), test case thất bại được in ra dấu chấm than (!).
Câu lệnh để cài đặt reporter là Dot
mocha /test --reporter dot
Ngoài ra cũng có các loại reporter khác được mô tả trong tài liệu của Mocha.
Có một lưu ý nhỏ, trong một hệ thống test automation nên sử dụng 1-2 loại reporter, để đảm bảo tính nhất quán, tránh gây khó khăn cho người mới tiếp cận hoặc người bảo trì hệ thống.
Nếu bạn có nhu cầu tìm hiểu sâu hơn về mocha, vui lòng truy cập tài liệu chính thức ở đây
Thuật ngữ sử dụng trong bài viết
test data: dữ liệu tham gia vào kịch bản test. Thông thường test data có hai loại, account data
, end-user data