0

Trải nghiệm viết Unit test cho Vuejs với Jest và những kinh nghiệm mình đã rút ra được.(P1)

Lời mở đầu

Hmm..tiêu đề bài viết có vẻ không hấp dẫn chút nào nhỉ. Thực ra cả bài viết này việc mình suy nghĩ lâu nhất chính là tiêu đề bài viết,tại mình chẳng biết nên đặt tên nó như thế nào cho phù hợp cả. Mà thôi kệ nó đi,vào vấn đề chính cái đã.

Lý do bài viết ra đời

Vào 1 ngày nắng nóng vã mồ hôi cuối tháng 7,mình - 1 backend dev Php rởm (fresher chính hiệu) được gọi vào phòng họp cùng vài anh em khác. Nhiệm vụ lần này của mấy anh em mình được tóm gọn như sau : "Viết test cho Vuejs và sử dụng Jest".

Chà,nghe có vẻ thú vị phết nhỉ (ít nhất thì với 1 đứa đang chập chững trong hành trình theo đuổi ước mơ full-stack dev như mình). Mình đã từng có thời gian 1 năm làm việc với MEAN stack,giờ chuyển qua dev Php,cũng từng code Vuejs,nhưng viết test và cụ thể là viết test cho Vuejs thì đây là lần đầu tiên được đụng vào 🙃 Thế là mấy anh em trong team khăn gói chuẩn bị đồ đạc, nồi, niêu, xoong, chảo chiến thôi (đùa thôi,chuẩn bị kiến thức 🥲)

Lưu ý : bài viết này được viết trên tinh thần những gì mình trải nghiệm và rút ra được,có thể đúng,có thể sai,mong mọi người góp ý và thông cảm bỏ qua

Nội dung chính

Những vấn đề liên quan đến install,setup ban đầu của Jest mình sẽ bỏ qua,căn bản tại cũng có khá nhiều bài viết hướng dẫn rồi nên vào vấn đề luôn cho nóng.

Các bước đầu tiên của Testing

Câu lệnh chạy test

Một trong những việc đầu tiên khi bắt đầu viết test,đấy là phải biết câu lệnh chạy test trước đã,với mình thì mình dùng yarn để test

yarn test:unit --coverage hoặc

yarn test:unit --coverage path/file.spec.js

còn đối với những người dùng npm thì có thể dùng

npm run test:unit

Sau khi chạy câu lệnh test trên,1 cửa sổ report coverage (cửa sổ thống kê về các test case,test suites) sẽ được hiện lên sau mỗi lần chạy câu lệnh test chứa. --coverage.

image.png

Thường thì nó sẽ auto mở 1 tab mới trên trình duyệt để cho các bạn thấy,nếu mà các bạn thấy phiền vì mỗi lần chạy đều tự mở thì có thể mở file jest.config.js và set biến openReport về false nha. Sau khi set thì cửa sổ test sẽ không bị mở mỗi lần chạy command test nữa,với những bạn dùng VScode có thể mở file report đấy trong folder html-report/report.html với Live server để mỗi lần chạy test nó tự cập nhật đỡ mất công mở đi mở lại 😁

Ở file coverage này, khi muốn kiểm tra xem 1 file mình test đã đi qua function nào,các branch nào (các if else,điều kiện rẽ nhánh),line nào các bạn có thể vào phần % Coverage đặt ở góc phải phía trên,chọn file muốn xem. Tại đây file import để test của bạn sẽ hiện lên đầy đủ dòng nào chưa được cover-màu đỏ (chưa chạy qua),dòng nào có branch-màu vàng (rẽ nhánh) để các bạn dễ dàng thấy được. Thường thì chúng ta sẽ chỉ test các phần liên quan đến xử lý js chứ không đụng nhiều đến phần view và các component,với mình thì cứ làm sao cho test full phần js và statement 100% là ok,còn lại thì k cần quan trọng lắm.

image.png

Viết file test

Các file test sẽ được để trong folder tests/unit/.../*.spec.js hoặc tests/unit/.../*.test.js,thông thường thì mình sẽ phân chia thư mục đúng theo các thư mục của các file .vue. Ví dụ ta có 1 file vue src/pages/login/index.vue thì hãy tạo 1 file test tương ứng trong tests/unit/pages/login/index.spec.js,như vậy mỗi khi cần tìm lại file test sẽ dễ dàng hơn.

Việc đầu tiên phải làm mỗi khi tạo xong 1 file test,là phải import file được test vào, như với file tests/unit/pages/login/index.spec.js thì chúng ta sẽ import import Index from '@/pages/login/Index.vue'import { shallowMount } from '@vue/test-utils' . Giải thích qua về shallowMount thì nó giúp chúng ta render component mà chúng ta cần test chứ không đi sâu vào các component con,từ đó mà việc test component sẽ dễ dàng hơn do nó đã độc lập với các child component (đúng chất UnitTest).

Dưới đây là cấu trúc bạn đầu khi tạo 1 file test

import Index from '@/pages/login/Index.vue';
import { shallowMount } from '@vue/test-utils';

describe('Test component login/index', () => {
  const wrapper = shallowMount(Index, {
    data(vm) {
      return {};
    },
    mocks: {},
  });

  it('Test case', async () => {
    expect().toBe();
  });
});

Những trường hợp mình gặp phải khi viết test

Khi viết test,mục tiêu của mình là đạt 100% statement và terminal không báo lỗi đỏ. Vậy nên thi thoảng mặc dù test case đã passed nhưng terminal vẫn báo lỗi,thì lúc ý các bạn sẽ phải tìm ra nguyên nhân và cách khắc phục nó. Dưới dây là 1 vài trường hợp test case và cách giải quyết mà mình đã làm.

Test các init state trong data()

Thường thì mặc định các state được khai báo ở data() mỗi khi chúng ta gọi shallowMount,nó sẽ tự động chạy qua tất cả các state hiện có trong đó. Tuy nhiên đó là trong trường hợp những state là object,hoặc là những variable thông thường như object : {}. Vậy nếu như state là 1 function thì sao ?

data(vm) {
mail: [
          (value) =>
            /^[a-zA-Z0-9_+-]+(\.[a-zA-Z0-9_+-]+)*@([a-zA-Z0-9][a-zA-Z0-9-]*[a-zA-Z0-9]*\.)+[a-zA-Z]{2,}$/.test(
              value
            )
        ],
}

Như các bạn thấy thì state này là 1 function test giá trị đầu vào (value) có đúng định dạng mail hay không rồi return ra true hoặc false. Tuy nhiên,thi thoảng ta sẽ gặp trường hợp mà function đó nằm trong mảng,chứ không phải đơn thuần là 1 object. Vậy thì đơn giản cứ chọc thẳng vào index array thằng đó để test thôi.

 it('Test data rules mail', async () => {
    expect(wrapper.vm.mail[0]('testmail@email.com')).toBe(true);
  });

Test các computed prop

 computed: {
    disabled() {
      if (this.mail && this.mailCheck && this.mail === this.mailCheck) {
        return false;
      } else {
        return true;
      }
    },
  },

Với case này thì đơn giản là gọi trực tiếp vào computed và expect ra thôi :

it('Test computed disabled with full mail check', async () => {
    wrapper.vm.mail = true;
    wrapper.vm.mailCheck = true;
    const compute = await Index.computed.disabled.call(wrapper.vm, wrapper.vm);
    expect(compute).toBe(false);
  });

Test các methods

Test các methods thì chỉ đơn giản là gọi thẳng vào rồi expect là ok. Tuy nhiên , do mỗi 1 function trong methods là 1 logic khác nhau,nên mình sẽ không thể liệt kê hết được.Thay vào đó, mình sẽ cho các b xem 1 vài trường hợp khá thú vị của mình khi viết test.


All rights reserved

Viblo
Hãy đăng ký một tài khoản Viblo để nhận được nhiều bài viết thú vị hơn.
Đăng kí