Khi sử dụng Retry, các hooks của Mocha hoạt động ra sao?

Khi sử dụng Retry, các hooks của Mocha hoạt động ra sao?

Xem nhanh

Để tăng tỉ lệ chạy thành công của test case thuộc end-to-end testing do các điều kiện bất lợi như: mạng không ổn định, tốc độ hiển thị phần tử trên trang chậm hay độ phản hồi webserver chậm… Lúc này bạn có thể chỉ định cho test case chạy lại một số lần nhất định bằng cách sử dụng tính năng retry của mocha.

Qua bài viết Mocha run cycle? Những điều cần biết cho người mới bắt đầu, bạn đã có cái nhìn tổng thể về cách mà Mocha thực thi các test spec. Tuy nhiên khi sử dụng tính năng retry, mocha run cycle sẽ có những thay đổi, cụ thể là sự thay đổi hoạt động của các hooks. Chúng ta hãy cùng tìm hiểu về hoạt động của mocha hooks khi sử dụng tính năng retry thông qua những trường hợp cụ thể như sau:

  • Retry được sử dụng ở test case
  • Retry được sử dụng trong describe
  • Retry được sử dụng ở cả hai nơi describe và test case
  • Retry được sử dụng trong trường hợp describe lồng describe

Các code snippet trong bài viết được thực hiện trên Mocha version 8.3.0. Để xem chi tiết toàn bộ source code vui lòng truy cập vào đây.

Retry được sử dụng ở test case

Trường hợp bạn muốn chỉ định một test case cụ thể chạy lại nếu thực thi thất bại, bạn hãy sử dụng tính năng retry ngay bên trong test case. Bên dưới là mã nguồn ví dụ cụ thể:

Mã nguồn: retry/sample1.js

Copy
var assert = require('assert');
describe('hooks', function() {

    before(function() {
        console.log('run BEFORE');
    });

    beforeEach(function() {
        console.log('run BEFORE EACH');
    });

    it('retry test case', function() {
        this.retries(1);
        console.log('run TEST CASE');
        assert.equal(0, -1);
    });

    afterEach(function() {
        console.log('run AFTER EACH');
    });

    after(function() {
        console.log('run AFTER');
    });
});

Kết quả chạy:

Copy
Retry test
run BEFORE
run BEFORE EACH
run TEST CASE
run AFTER EACH
run BEFORE EACH
run TEST CASE
    1) retry test case
run AFTER EACH
run AFTER

Mã nguồn bên trên tại dòng 13: this.retries(1); đang sử dụng tính năng retry với số lần retry là 1 cho test case it('retry test case'. Khi test case này thất bại ở lần đầu tiên, nó sẽ được khởi chạy lại 1 lần nữa. Từ kết quả chạy chúng ta dễ dàng nhận thấy:

  • Các hook beforeafter: chạy 1 lần duy nhất
  • Các hook beforeEachafterEach: số lần chạy lại bằng với số lần chạy lại của test case (nói cách khác mỗi lần chạy itsẽ khởi chạy hai hook này). Thứ tự chạy lại vẫn tuân theo mocha run cycle. beforeEachđược chạy lại trước khi test case chạy lại. afterEachđược chạy lại sau khi chạy lại test case.

Retry được sử dụng trong describe

Mocha cho phép sử dụng tính năng retry ngay trong describe để thực hiện retry cho tất cả các test case nằm trong test spec đó. Ở ví dụ bên dưới, test spec: sample2.js gồm 2 test case it('retry test case 1'it('retry test case 2'. Chúng ta chỉ định số lần retry là 1: this.retries(1). Khi test case thất bại, nó sẽ được chạy lại một lần. Cụ thể trong ví dụ này cả hai test case này đều thất bại và đều thực hiện chạy lại một lần.

Mã nguồn: retry/sample2.js

Copy
var assert = require('assert');
describe('Retry test', function() {
    this.retries(1);
    before(function() {
        console.log('run BEFORE');
    });

    beforeEach(function() {
        console.log('run BEFORE EACH');
    });

    it('retry test case 1', function() {
        console.log('run TEST CASE 1');
        assert.equal(0, -1);
    });

    it('retry test case 2', function() {
        console.log('run TEST CASE 2');
        assert.equal(0, -1);
    });

    afterEach(function() {
        console.log('run AFTER EACH');
    });

    after(function() {
        console.log('run AFTER');
    });
});

Kết quả chạy:

Copy
Retry test
run BEFORE
run BEFORE EACH
run TEST CASE 1
run AFTER EACH
run BEFORE EACH
run TEST CASE 1
    1) retry test case 1
run AFTER EACH
run BEFORE EACH
run TEST CASE 2
run AFTER EACH
run BEFORE EACH
run TEST CASE 2
    2) retry test case 2
run AFTER EACH
run AFTER

Khi tính năng retry đươc sử dụng trong describe thì tất cả các test case thất bại đều sẽ được chạy lại. Hoạt động của các hook tương tự như trường hợp retry đặt trong test case.

Retry được sử dụng ở cả hai nơi describe và test case

Có một số trường hợp bạn sẽ thấy retry được chỉ định ở cả describe và nội tại bên trong test case. Mã nguồn dưới đây là ví dụ cho trường hợp này. Tập tin test spec: sample3.js gồm có 2 test case. Chỉ định số lần retry chung cho test spec (đặt trong describe) là 2 lần.

Riêng test case it('retry test case 1' được chỉ định riêng số lần retry là 1. Hai test case trong ví dụ này đều thất bại và được chạy lại. Hãy cùng xem kết quả chạy để xem retry trên hai test case này khác nhau như thế nào nhé!

Mã nguồn: retry/sample3.js

Copy
var assert = require('assert');
describe('Retry test', function() {
    this.retries(2);
    before(function() {
        console.log('run BEFORE');
    });

    beforeEach(function() {
        console.log('run BEFORE EACH');
    });

    it('retry test case 1', function() {
        this.retries(1);
        console.log('run TEST CASE 1');
        assert.equal(0, -1);
    });

    it('retry test case 2', function() {
        console.log('run TEST CASE 2');
        assert.equal(0, -1);
    });

    afterEach(function() {
        console.log('run AFTER EACH');
    });

    after(function() {
        console.log('run AFTER');
    });
});

Kết quả chạy:

Copy
Retry test
run BEFORE
run BEFORE EACH
run TEST CASE 1
run AFTER EACH
run BEFORE EACH
run TEST CASE 1
    1) retry test case 1
run AFTER EACH
run BEFORE EACH
run TEST CASE 2
run AFTER EACH
run BEFORE EACH
run TEST CASE 2
run AFTER EACH
run BEFORE EACH
run TEST CASE 2
    2) retry test case 2
run AFTER EACH
run AFTER

Kết quả chạy cho thấy:

  • test case it('retry test case 1' chạy lại 1 lần. Các hook beforeEachafterEachcủa test case này đều được chạy lại 1 lần. Như vậy tại đây đang áp dụng số lần retry được chỉ định nội tại bên trong test case
  • test case it('retry test case 2' chạy lại 2 lần. Các hook beforeEachafterEachcủa test case này đều được chạy lại 2 lần. Như vậy tại đây đang áp dụng số lần retry được chỉ định tại describe

Retry được sử dụng trong trường hợp describe lồng describe

Trong một file test spec sẽ có những trường hợp chúng ta thiết kế nhiều describe nằm trong describe khác. Khi đó số lần retry được áp dụng cho các test case sẽ lấy theo chỉ định của describe nào đây? Hãy cùng làm rõ điều này thông qua ví dụ bên dưới.

Mã nguồn: retry/sample4.js

Copy
var assert = require('assert');
describe('parent describe', function() {
    this.retries(1);
    it('retry test case out site', function() {
        console.log('run TEST CASE outside');
        assert.equal(0, -1);
    });
    describe('child describe', function() {
        this.retries(2);
        before(function() {
            console.log('run BEFORE');
        });

        beforeEach(function() {
            console.log('run BEFORE EACH');
        });

        it('retry test case inside', function() {
            console.log('run TEST CASE');
            assert.equal(0, -1);
        });

        afterEach(function() {
            console.log('run AFTER EACH');
        });

        after(function() {
            console.log('run AFTER');
        });
    });
});

Kết quả chạy:

Copy
Retry test
run TEST CASE outside
run TEST CASE outside
    1) retry test case out site
    child describe
run BEFORE
run BEFORE EACH
run TEST CASE
run AFTER EACH
run BEFORE EACH
run TEST CASE
run AFTER EACH
run BEFORE EACH
run TEST CASE
      2) retry test case inside
run AFTER EACH
run AFTER

Chúng ta có 2 describe: describe('parent describe'describe('child describe'. Trong đó:

  • describe('parent describe' chứa test case it('retry test case out site'describe('child describe'. Số lần retry chỉ định trong describe này là 1.
  • describe('child describe' chứa test case it('retry test case inside'. Số lần retry chỉ định trong describe này là 2.

Kết quả chạy như sau:

  • it('retry test case out site' được chạy lại 1 lần. Như vậy tại đây đang áp dụng số lần retry được chỉ định trong describemà nó thuộc về.
  • it('retry test case inside' được chạy lại 2 lần. Các hook beforeEachafterEachcủa test case này đều được chạy lại 2 lần. Như vậy tại đây đang áp dụng số lần retry được chỉ định trong describe mà nó thuộc về.

Lời kết

Trong bài viết với khá nhiều thông tin do đó rất khó để hiểu ngay sau một lần đọc. Tóm tắt lại sau một số trường hợp đã trình bày bên trên, chúng ta có thể đúc kết ngắn gọn một số điểm như sau:

  • Các hook beforeafterhook không ảnh hưởng bởi retry, chúng vẫn chạy duy nhất một lần.

  • Các hook beforeEachafterEachthì đi theo test case, do đó test case retry bao nhiều lần chúng cũng chạy lại bấy nhiêu lần

  • Trường hợp trong file test spec có nhiều chỉ số retry được chỉ định thì test case sẽ chạy lại với số lần retry lấy theo thứ tự ưu tiên như sau:

    • Số lần retry chỉ định nội tại bên trong test case
    • Số lần retry chỉ định trong describe mà test case trực tiếp thuộc về
    • Số lần retry chỉ định trong describe ngoài cùng.

Tài liệu tham khảo

https://mochajs.org/#retry-tests

Thuật ngữ sử dụng

test spec: là file test script, thể hiện kịch bản của một hay nhiều test case.

Các bài viết cùng chủ đề