Cài đặt vue-cli
vue-test-utils
là thư viện kiểm thử chính thức cho Vue và sẽ được sử dụng xuyên suốt trong cẩm nang này của chúng ta. Nó chạy trong cả môi trường trình duyệt Node.js và hoạt động với bất kỳ runner test nào. Chúng ta sẽ chạy các test trong môi trường Node.js trên tất cả nội dung của series này.
Với thư viện vue-cli
là cách dễ nhất để khởi tạo project của chúng ta. Nó sẽ thiết lập, cũng như cấu hình Jest, một khung thực hiện các kiểm thử phổ biến trên Javascript. Chúng ta sẽ cài đặt nó bằng cách chạy terminal:
1 2 | yarn global add @vue/cli |
hoặc với npm:
1 2 | <span class="token function">npm</span> <span class="token function">install</span> -g @vue/cli |
Tạo một dự án mới bằng cách chạy vue create [project-name]
. Chọn “Manually select features” và “Unit Testing”, và “Jest” cho việc kiểm thử.
Sau khi cài đặt kết thúc, cd
vào trong dự án và chạy yarn test:unit
. Nếu mọi thứ đều không có vấn đề gì, bạn sẽ thấy:
1 2 3 4 5 6 7 8 9 | <span class="token constant">PASS</span> tests<span class="token operator">/</span>unit<span class="token operator">/</span>HelloWorld<span class="token punctuation">.</span>spec<span class="token punctuation">.</span>js HelloWorld<span class="token punctuation">.</span>vue ✓ renders props<span class="token punctuation">.</span>msg when <span class="token function">passed</span> <span class="token punctuation">(</span><span class="token number">26</span>ms<span class="token punctuation">)</span> Test Suites<span class="token punctuation">:</span> <span class="token number">1</span> passed<span class="token punctuation">,</span> <span class="token number">1</span> total Tests<span class="token punctuation">:</span> <span class="token number">1</span> passed<span class="token punctuation">,</span> <span class="token number">1</span> total Snapshots<span class="token punctuation">:</span> <span class="token number">0</span> total Time<span class="token punctuation">:</span> <span class="token number">2.074</span>s |
Chúc mừng bạn vừa chạy các bài kiểm tra đầu tiên thành công.
Viết các bài tests đầu tiên
Chúng ta chạy các test hiện có đi kèm với dự án. Theo cách truyền thống khi làm TDD, bạn viết các đoạn mã test trước, sau đó mới triển khai code sao cho các bài test pass các mã test. Bây giờ, chúng ta sẽ viết component đầù tiên.
Chúng ta không cần src/components/HelloWorld.vue
hoặc tests/unit/HelloWorld.spec.js
nữa, vì vậy bạn có thể xóa chúng nếu có thể.
Tạo components Greeting
Tạo một file Greeting.vue
trong src/components
. Bên trong Greeting.vue
, thêm những thứ sau đây:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>template</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span><span class="token punctuation">></span></span> {{ greeting }} <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>template</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span><span class="token punctuation">></span></span><span class="token script language-javascript"> <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span> name<span class="token punctuation">:</span> <span class="token string">"Greeting"</span><span class="token punctuation">,</span> <span class="token function">data</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> greeting<span class="token punctuation">:</span> <span class="token string">"Vue and TDD"</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span> |
Viết test
Greeting
chỉ có một trách nhiệm là render giá trị greeting
. Chiến lược ở đây là:
- Render component với
mount
- Assert văn bản bên trong components có chứa từ khóa “Vue and TDD”
Tạo một Greeting.spec.js
bên trong tests/unit
. Bên trong, import Greeting.vue
, cũng như mount
, và thêm 1 số outline cho test case của bạn:
1 2 3 4 5 6 7 8 9 | <span class="token keyword">import</span> <span class="token punctuation">{</span> mount <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@vue/test-utils'</span> <span class="token keyword">import</span> Greeting <span class="token keyword">from</span> <span class="token string">'@/components/Greeting.vue'</span> <span class="token function">describe</span><span class="token punctuation">(</span><span class="token string">'Greeting.vue'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">'renders a greeting'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> |
Có các cú pháp khác nhau được sử dụng cho TDD, chúng ta sẽ sử dụng cú pháp thường thấy về describe
và it
đi kèm với Jest. describe
phác thảo những gì bài test muốn, ở đây là Greeting.vue
. it
đại diện cho một phần kiểm tra mà đối tượng của bài test đó phải hoàn thành. Khi chúng ta có nhiều tính năng ở components thì chúng ta có nhiều khối it
.
Bây giờ chúng ta render component với mount
và gán component cho 1 biến được gọi là wrapper
và cũng sẽ in console ra, để đảm bảo mọi thứ chạy chính xác:
1 2 3 4 | <span class="token keyword">const</span> wrapper <span class="token operator">=</span> <span class="token function">mount</span><span class="token punctuation">(</span>Greeting<span class="token punctuation">)</span> console<span class="token punctuation">.</span><span class="token function">log</span><span class="token punctuation">(</span>wrapper<span class="token punctuation">.</span><span class="token function">html</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span> |
Chạy test
Chạy test bằng cách gõ yarn test:unit
trên terminal của bạn. Bất kì file tests
đều có kết thúc bằng đuôi .spec.js
được thực hiện tự động. Bạn sẽ thấy:
1 2 3 4 5 6 7 8 9 | <span class="token constant">PASS</span> tests<span class="token operator">/</span>unit<span class="token operator">/</span>Greeting<span class="token punctuation">.</span>spec<span class="token punctuation">.</span>js Greeting<span class="token punctuation">.</span>vue ✓ renders a <span class="token function">greeting</span> <span class="token punctuation">(</span><span class="token number">27</span>ms<span class="token punctuation">)</span> console<span class="token punctuation">.</span>log tests<span class="token operator">/</span>unit<span class="token operator">/</span>Greeting<span class="token punctuation">.</span>spec<span class="token punctuation">.</span>js<span class="token punctuation">:</span><span class="token number">7</span> <span class="token operator"><</span>div<span class="token operator">></span> Vue and <span class="token constant">TDD</span> <span class="token operator"><</span><span class="token operator">/</span>div<span class="token operator">></span> |
Chúng ta có thể thấy các markup là chính xác, và thử nghiệm chạy thành công. Test case sẽ pass vì không có sai sót, nhưng có 1 vấn đề khi chúng ta thay đổi Greeting.vue
và xóa greeting
từ template, test của chúng ta vẫn pass, dưới đây sẽ giải thích cho nó.
Tạo Assert
Chúng ta cần đưa ra một khẳng định để đảm bảo component hoạt động chính xác. Bằng cách sử dụng expect
API của Jest, nó sẽ trông như thế này: expect(result).to [matcher] (actual)
.
expect là một phương thức để so sánh các giá trị và đối tượng. Ví dụ:
1 2 | <span class="token function">expect</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toBe</span><span class="token punctuation">(</span><span class="token number">1</span><span class="token punctuation">)</span> |
Một danh sách đầy đủ các matchers có sẵn trong tài liêu của Jest Jest documentation. vue-test-utils
không bao gồm bất kỳ công cụ so sách nào vì những gì Jest mang lại là quá đủ để dùng. Chúng ta muốn so sánh văn bản từ Greeting
nên ta có thể viết như sau:
1 2 | <span class="token function">expect</span><span class="token punctuation">(</span>wrapper<span class="token punctuation">.</span><span class="token function">html</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">includes</span><span class="token punctuation">(</span><span class="token string">"Vue and TDD"</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toBe</span><span class="token punctuation">(</span><span class="token boolean">true</span><span class="token punctuation">)</span> |
nhưng vue-test-utils
có một cách tốt hơn để đánh dấu – wrapper.text
:
1 2 3 4 5 6 7 8 9 10 11 | <span class="token keyword">import</span> <span class="token punctuation">{</span> mount <span class="token punctuation">}</span> <span class="token keyword">from</span> <span class="token string">'@vue/test-utils'</span> <span class="token keyword">import</span> Greeting <span class="token keyword">from</span> <span class="token string">'@/components/Greeting.vue'</span> <span class="token function">describe</span><span class="token punctuation">(</span><span class="token string">'Greeting.vue'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token function">it</span><span class="token punctuation">(</span><span class="token string">'renders a greeting'</span><span class="token punctuation">,</span> <span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">=></span> <span class="token punctuation">{</span> <span class="token keyword">const</span> wrapper <span class="token operator">=</span> <span class="token function">mount</span><span class="token punctuation">(</span>Greeting<span class="token punctuation">)</span> <span class="token function">expect</span><span class="token punctuation">(</span>wrapper<span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toMatch</span><span class="token punctuation">(</span><span class="token string">"Vue and TDD"</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> |
Chúng ta không cần console.log
, vì vậy bạn có thể xóa chúng. Chạy test với yarn unit:test
, bạn sẽ nhận được:
1 2 3 4 5 6 7 8 9 | <span class="token constant">PASS</span> tests<span class="token operator">/</span>unit<span class="token operator">/</span>Greeting<span class="token punctuation">.</span>spec<span class="token punctuation">.</span>js Greeting<span class="token punctuation">.</span>vue ✓ renders a <span class="token function">greeting</span> <span class="token punctuation">(</span><span class="token number">15</span>ms<span class="token punctuation">)</span> Test Suites<span class="token punctuation">:</span> <span class="token number">1</span> passed<span class="token punctuation">,</span> <span class="token number">1</span> total Tests<span class="token punctuation">:</span> <span class="token number">1</span> passed<span class="token punctuation">,</span> <span class="token number">1</span> total Snapshots<span class="token punctuation">:</span> <span class="token number">0</span> total Time<span class="token punctuation">:</span> <span class="token number">1.477</span>s<span class="token punctuation">,</span> estimated <span class="token number">2</span>s |
Trong TDD truyền thống, bạn sẽ viết các test trước khi thực hiện trong thực tế, hãy thấy nó chạy fail, sau đó sử dụng các lỗi không thành công để sửa tiếp các đoạn code của chúng ta. Hãy chắc chắn rằng bài, test chúng ta thực hiện hiệu quả đúng theo phong cách TDD. Dưới đây là cập nhật Greeting.vue
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>template</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>div</span><span class="token punctuation">></span></span> {{ greeting }} <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>div</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"></</span>template</span><span class="token punctuation">></span></span> <span class="token tag"><span class="token tag"><span class="token punctuation"><</span>script</span><span class="token punctuation">></span></span><span class="token script language-javascript"> <span class="token keyword">export</span> <span class="token keyword">default</span> <span class="token punctuation">{</span> name<span class="token punctuation">:</span> <span class="token string">"Greeting"</span><span class="token punctuation">,</span> <span class="token function">data</span><span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token punctuation">{</span> <span class="token keyword">return</span> <span class="token punctuation">{</span> greeting<span class="token punctuation">:</span> <span class="token string">"Vue without TDD"</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> <span class="token punctuation">}</span> </span><span class="token tag"><span class="token tag"><span class="token punctuation"></</span>script</span><span class="token punctuation">></span></span> |
Và bây giờ chạy test với yarn test:unit
:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | <span class="token constant">FAIL</span> tests<span class="token operator">/</span>unit<span class="token operator">/</span>Greeting<span class="token punctuation">.</span>spec<span class="token punctuation">.</span>js Greeting<span class="token punctuation">.</span>vue ✕ renders a <span class="token function">greeting</span> <span class="token punctuation">(</span><span class="token number">24</span>ms<span class="token punctuation">)</span> ● Greeting<span class="token punctuation">.</span>vue › renders a greeting <span class="token function">expect</span><span class="token punctuation">(</span>received<span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toMatch</span><span class="token punctuation">(</span>expected<span class="token punctuation">)</span> Expected value to match<span class="token punctuation">:</span> <span class="token string">"Vue and TDD"</span> Received<span class="token punctuation">:</span> <span class="token string">"Vue without TDD"</span> <span class="token number">6</span> <span class="token operator">|</span> <span class="token keyword">const</span> wrapper <span class="token operator">=</span> <span class="token function">mount</span><span class="token punctuation">(</span>Greeting<span class="token punctuation">)</span> <span class="token number">7</span> <span class="token operator">|</span> <span class="token operator">></span> <span class="token number">8</span> <span class="token operator">|</span> <span class="token function">expect</span><span class="token punctuation">(</span>wrapper<span class="token punctuation">.</span><span class="token function">text</span><span class="token punctuation">(</span><span class="token punctuation">)</span><span class="token punctuation">)</span><span class="token punctuation">.</span><span class="token function">toMatch</span><span class="token punctuation">(</span><span class="token string">"Vue and TDD"</span><span class="token punctuation">)</span> <span class="token operator">|</span> <span class="token operator">^</span> <span class="token number">9</span> <span class="token operator">|</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token number">10</span> <span class="token operator">|</span> <span class="token punctuation">}</span><span class="token punctuation">)</span> <span class="token number">11</span> <span class="token operator">|</span> at Object<span class="token punctuation">.</span><span class="token operator"><</span>anonymous<span class="token operator">></span> <span class="token punctuation">(</span>tests<span class="token operator">/</span>unit<span class="token operator">/</span>Greeting<span class="token punctuation">.</span>spec<span class="token punctuation">.</span>js<span class="token punctuation">:</span><span class="token number">8</span><span class="token punctuation">:</span><span class="token number">28</span><span class="token punctuation">)</span> |
Jest cho chúng ta kết quả cũng như có thể thấy các kết quả mong đợi và thực tế, cũng như thất bại. Sửa lại Greeting.vue
và đảm bảo test được pass một lần nữa.
Kết luận
Tiếp theo chúng ta sẽ xem xet hai phương thức vue-test-utils
cung cấp để render các components: mount
và shallowMount
.
Reference
Dịch từ: https://lmiller1990.github.io/vue-testing-handbook/setting-up-for-tdd.html