Khi thực hiện manual testing cho 1 test case, chúng ta thực hiện các bước của kịch bản test một cách tuần tự. Từng bước sẽ có dữ liệu tương ứng.
Bản chất của việc chuyển 1 test case từ manual testing sang automation testing là dùng một ngôn ngữ máy tính cụ thể để ánh xạ tuần tự các bước của kịch bản của test case. Nơi triển khai kịch bản test trong mã nguồn được gọi là test spec
hoặc test script
.
Tại Cybozu Vietnam chúng tôi đang sử dụng framework WebdriverIO để thực hiện việc tự động hóa nên sẽ sử dụng từ test spec
để mô tả cho test script
. Về tổng thể để triển khai chúng ta sẽ đi qua 4 thành phần test spec
, test flow
, page object
và test data
. Trong bài viết này chúng ta tìm hiểu về test spec.
Test spec là gì?
Test spec: là file test script, triển khai các bước kịch bản test của một hay nhiều test case.
Cybozu dùng WebdriverIO triển khai kiểm thử tự động cho nhiều loại test (acceptance test, API test) và nhiều test case. Bên cạnh đó, dự án automation có nhiều người với nhiều vai trò khác nhau cùng tham gia như QA, developer, … Do đó, test spec
được công thức hoá để mọi người thuận tiện trong việc tìm hiểu và tham khảo khi triển khai.
Đặc điểm của test spec
được triển khai tại Cybozu:
Công thức
Test spec
= ∑Test-CaseTest-Case = Testing-data(*1) + Testing-flows(*2) [+Action-methods(*3)]
Mô tả
*1: Tham khảo tại bài viết về Testing-data.
*2: Tham khảo tại bài viết về Testing-flow.
*3: Các action methods tùy chọn. Nếu test flow không thể đáp ứng đủ cho kịch bản test. Chúng ta có thể gọi trực tiếp action methods từ
test spec
. Tìm hiểu thêm về action method tại bài viết này.
Test spec
có thể chứa một hoặc nhiều kịch bản test (test case). Bản thân 1 test case sẽ gồm: testing-data và các testing-flow. Cũng có trường hợp test case gọi trực tiếp các action method không thông qua test flow. Nhiệm vụ của test flow hay action method là thực hiện các bước của kịch bản test.
Chúng ta có thể mô hình hóa lại test spec
như sau:
Bạn đã tìm hiểu về định nghĩa của test spec
. Và bạn có hình dung được một file test spec sẽ có hình hài ra sao chưa? Hãy cũng tìm hiểu điều này thông qua phần Mô tả test spec template dưới đây nhé!
Mô tả test spec template
Kết hợp với WebdriverIO, dự án automation tại Cybozu VN còn sử dụng Mocha framework. Do đó cách thực thi test spec
tuân theo Mocha run cycle. Trong bài viết này, bạn sẽ tìm thấy [step 7] execute the test files (chế độ chạy tuần tự). Đây chính là bước thực thi các test spec đang đề cập.
Mocha cung cấp template để triển khai test spec
cho kịch bản test mà bạn đang tiến hành. Bên dưới là template của một test spec
:
describe('hooks', function () { // Bao gồm một hoặc nhiều kịch bản của test case
before(function () {
// Khởi chạy một lần trước tiên và duy nhất trước các hook khác khởi chạy
});
after(function () {
// Khởi chạy một lần duy nhất và sau tất cả hook khác chạy xong
});
beforeEach(function () {
// Khởi chạy trước mỗi lần test case (it) khởi chạy
});
afterEach(function () {
// Khởi chạy sau mỗi lần test case (it) khởi chạy xong
});
// test cases
it('should return something', function () {
// Khởi chạy các logic chính của test case
});
});
Để tìm hiểu chi tiết hơn về từng thành phần trong template, bạn có thể đọc bài blog Mocha framework tóm lược dưới dạng handbook.
Ví dụ cụ thể
Từ template chung, chúng ta triển khai thành những file test spec
cụ thể. Sau đây là một ví dụ thêm mới một appointment của Schedule application: schedule/test-specs/added-new-appoiment/added-new-appointment.spec.js
import {
AddingAppointment,
ViewingAppointment,
DeletingAppointment,
} from '#e2e-cores/schedule/test-flows';
import testData from './added-new-appointment.data';
describe('Adding Regular Appointment', () => {
before('Login Garoon testing site', () => {
new Authenticating(testData.account).login();
});
it('Should add a regular appointment successfully', () => {
new AddingAppointment(testData.appointmentInfo).addRegularAppointment();
new ViewingAppointment(testData.appointmentInfo).verifyAppointmentDetails();
});
after('Remove test data after testing', () => {
new DeletingAppointment(testData.appointmentInfo).deleteAppointmentOnDetailsPage();
})
});
Phân bổ test spec
trong cấu trúc dự án:
acceptance
|---schedule
| |---test-specs
| | |---added-new-appoiment
| | | |---added-new-appointment.spec.js|.data.js
// ...
Trong ví dụ này bạn có thể thấy được:
-
Test spec
này chứa 1 test case -
Trong test case có sử dụng:
- testData là test data
AddingAppointment
,ViewingAppointment
,DeletingAppointment
là các test flow- Test case không sử dụng action method của page object
Một vài lưu ý
Qua kinh nghiệm thực tế trải qua project automation tại Cybozu, chúng tôi đưa ra một vài điểm lưu ý khi triển khai test spec
như sau:
-
Tên của
test spec
phản ánh nội dung mà nó đang đảm nhiệm test, càng rõ càng tốt. Điều này giúp maintain dễ dàng hơn.Tên
test spec
là adding-all-day-appointment.spec.js, tức làtest spec
này đang thực hiện test cho chức năng thêm all day appointment (một chức năng của sản phẩm Garoon) -
Mỗi hook như before, beforeEach, after, afterEach,… trong
test spec
nên đảm nhiệm một công việc/ hành vi duy nhất. Điều này giúp debug và tái hiện lỗi thuận lợi hơn. Cũng xem qua hai ví dụ về cách bố trí hành vi trong các hook dưới đây để hiểu rõ hơn về điểm lưu ý này:BAD
describe('Adding comment with appointment type', function () { before('Prepare', () => { // add appointment types // add appointment notes // add appointment }); after('Clean', () => { // delete appointment // delete appointment notes // delete appointment types }); // test cases it('should add comment with appointment type', function () { // ... }); });
GOOD
describe('Adding comment with appointment type', function () { before('AddAppointmentTypes', () => { // add appointment types }); before('Add appointment notes', () => { // add appointment notes }); before('Add appointment', () => { // add appointment }); after('Delete added appointment', () => { // delete appointment }); after('Delete added appointment notes', () => { // delete appointment notes }); after('Delete added appointment types', () => { // delete appointment types }); // test cases it('should add comment with appointment type', function () { // ... }); });
Trước khi test case được khởi chạy, có rất nhiều công việc cần chuẩn bị cho nó. Như đối với code snippet bên trên chẳng hạn, bạn cần: add appointment types, add appointment notes, add appointment trước khi chạy test case.
Bạn có thể dồn tất cả các công việc này vào 1 hook before duy nhất, rồi mô tả cho hook là 'Prepare'. Tuy nhiên, khi làm như thế, bạn sẽ gặp phải khó khăn khi maintain. Bug xảy ra tại before hook nhưng bạn sẽ khó mà nhận biết được cụ thể xảy ra lỗi ở công việc nào.
Vì vậy hãy tách nhỏ các công việc ra thành nhiều hook khác nhau và mô tả rõ ràng công việc mà hook thực hiện là gì. Nó giúp source code dễ đọc hơn, maintain dễ dàng hơn. Bạn có thể áp dụng điều này cho tất cả các loại hook:
before
,beforeEach
,after
,afterEach
. -
Bạn nên cân nhắc số lượng test case trong 1 describe section (test suite) để vận hành việc test song song (parallel test) một cách hiệu quả. Lời khuyên ở đây: nên có từ 1 đến 2 test case trong 1 test suite.
-
Tập trung hiện thực cho nghiệp vụ chính của test case. Những nghiệp vụ như đăng nhập, thay đổi setting và một số công việc tiền trạm khác của test case chúng ta nên dùng các thư viện, hay những giải pháp ít tương tác bằng UI để giảm thời gian thực hiện (implement) tăng độ ổn định của test case cũng như giảm thời gian chạy test tổng thể. Cybozu có triển khai cách làm với tên gọi là "UILess" để xử lý một số công việc tiền trạm.
Lời kết
Test spec
là nơi thể hiện kịch bản test. Test spec cũng là nơi liên kết các thành phần khác trong project như: test data, test flow hay action method. Test spec là nơi đầu tiên bạn cần tìm đến khi muốn truy tìm lỗi phát sinh.
Vì vậy việc hiện thực test spec một cách rõ ràng có ý nghĩa lớn trong việc maintain source code automation. Khi đọc một test spec bạn hiểu được test spec đang thực hiện test cho function gì, các bước thực hiện ra sao thì đó là một test spec viết thành công.