NỘI DUNG BÀI HỌC
✅ Hiểu được vòng đời thực thi kiểm thử tự động (Test Execution Lifecycle)
✅ Hiểu được ý nghĩa của từng Hook trong Test Listener trong Katalon
1. GIỚI THIỆU VÀ HƯỚNG DẪN TẠO TEST LISTENER TRONG KATALON
Test Listener trong Katalon là gì?
-
-
-
- Là thành phần dùng để thu thập và xử lý các thông tin, trạng thái của Test Suites và Test cases trước và sau khi thực thi
- Nó như một Cánh tay nối dài của Framework. Nó cho phép chúng ta định nghĩa các "mối quan tâm xuyên suốt" (cross-cutting concerns) - những hành động cần được thực hiện tại nhiều điểm trong chương trình nhưng không thuộc về logic nghiệp vụ cốt lõi - và "tiêm" chúng vào các điểm nối (join points) của vòng đời thực thi. Điều này giúp giữ cho các Test Case sạch sẽ, tập trung vào logic kiểm thử, và làm cho framework dễ bảo trì hơn rất nhiều.
- Ví dụ về các mối quan tâm xuyên suốt trong kiểm thử tự động:
- Logging và báo cáo.
- Xử lý lỗi và chụp ảnh màn hình.
- Tích hợp với các hệ thống của bên thứ ba (Jira, Slack, TestRail).
-
-
Cách tạo Test Listener trong Katalon
-
-
-
- Chuột phải [Test Listeners] trên cây thư mục
- Chọn [New]
- Chọn [New Test Listener]
-
-

-
-
-
- Nhập tên Test Listener ở phần "Name" trên dialog "New Test Listener"
- Nhấn [OK]
-
-

2. GIẢI MÃ VÒNG ĐỜI THỰC THI CỦA KIỂM THỬ TỰ ĐỘNG
Vòng đời thực thi kiểm thử tự động

Vòng đời thực thi (Test Execution Lifecycle) là một chuỗi các sự kiện được sắp xếp một cách nghiêm ngặt. Sơ đồ dưới đây mô tả luồng thực thi từ khi bắt đầu một Test Suite cho đến khi kết thúc:
-
-
- Bắt đầu thực thi Test Suite.
- Kích hoạt Hook @BeforeTestSuite. Logic được định nghĩa ở đây sẽ chạy MỘT LẦN DUY NHẤT.
- Katalon thực hiện các thiết lập nội bộ cho Test Suite (ví dụ: khởi tạo báo cáo).
- Bắt đầu vòng lặp qua từng Test Case trong Test Suite.
- Kích hoạt Hook @BeforeTestCase. Logic này chạy TRƯỚC MỖI Test Case.
- Katalon thực hiện các thiết âlập nội bộ cho Test Case (ví dụ: khởi tạo trình duyệt).
- Thực thi các bước trong script của Test Case.
- Katalon thực hiện các công việc dọn dẹp nội bộ cho Test Case (ví dụ: đóng trình duyệt nếu được cấu hình).
- Kích hoạt Hook @AfterTestCase. Logic này chạy SAU MỖI Test Case, bất kể kết quả của nó (pass, fail, hay error).
- Kết thúc vòng lặp, chuyển sang Test Case tiếp theo.
- Sau khi tất cả các Test Case đã chạy xong, Katalon thực hiện các công việc dọn dẹp nội bộ cho Test Suite (ví dụ: hoàn tất báo cáo).
- Kích hoạt Hook @AfterTestSuite. Logic được định nghĩa ở đây sẽ chạy MỘT LẦN DUY NHẤT sau khi mọi thứ đã hoàn tất.
- Kết thúc thực thi Test Suite.
-
Bảng dưới đây tóm tắt chi tiết về thứ tự thực thi và các trường hợp sử dụng điển hình
STT |
Sự kiện / Hook |
Phạm vi |
Đối tượng Context có sẵn |
Ví dụ về trường hợp sử dụng điển hình |
1 |
@BeforeTestSuite |
Test Suite |
TestSuiteContext |
Khởi tạo kết nối DB, lấy token xác thực, đọc file cấu hình, dọn dẹp môi trường trước khi chạy. |
2 |
@BeforeTestCase |
Test Case |
TestCaseContext |
Tạo dữ liệu test riêng cho từng test case (ví dụ: tạo user mới qua API), xóa cookies, thiết lập trạng thái ban đầu sạch sẽ. |
3 |
Thực thi Test Case |
Test Case |
- |
Thực thi logic kiểm thử chính. |
4 |
@AfterTestCase |
Test Case |
TestCaseContext |
Dọn dẹp dữ liệu test đã tạo, chụp ảnh màn hình nếu test thất bại, tích hợp với Jira/TestRail để tạo bug hoặc cập nhật kết quả. |
5 |
@AfterTestSuite |
Test Suite |
TestSuiteContext |
Đóng kết nối DB, tạo báo cáo tùy chỉnh, gửi thông báo kết quả qua Slack/Email, nén và lưu trữ logs. |
Phân tích chi tiết từng Test Hooks
-
-
-
- Mục đích: Thiết lập môi trường và tài nguyên toàn cục cho toàn bộ Test Suite.
- Đối tượng Context: TestSuiteContext cung cấp thông tin về Test Suite đang chạy, chẳng hạn như ID (getTestSuiteId()).
- Ví dụ thực tế:
-
-
-
-
-
-
- Khởi tạo kết nối cơ sở dữ liệu: Mở một kết nối đến cơ sở dữ liệu kiểm thử và lưu đối tượng kết nối vào một biến static trong GlobalVariable để các Test Case sau đó có thể tái sử dụng mà không cần phải mở kết nối mới mỗi lần.
-
-
-
// Trong TestListener.groovy
import java.sql.Connection
import com.mycompany.database.utils.DBConnector
class DefaultListener {
@BeforeTestSuite
def setupDatabaseConnection(TestSuiteContext testSuiteContext) {
println "Setting up database connection for suite: " + testSuiteContext.getTestSuiteId()
Connection conn = DBConnector.getConnection()
// Lưu kết nối vào một biến toàn cục để tái sử dụng
GlobalVariable.dbConnection = conn
}
}
-
-
-
-
- Lấy Token Xác thực: Gọi một API đăng nhập để lấy một token xác thực (ví dụ: JWT) có hiệu lực trong suốt quá trình chạy. Lưu token này vào GlobalVariable để các Test Case sau đó có thể sử dụng cho các lời gọi API yêu cầu xác thực.
- Dọn dẹp Môi trường: Xóa tất cả các file screenshot, video, hoặc log từ lần chạy trước đó để đảm bảo thư mục báo cáo sạch sẽ.
-
-
-
-
-
-
- Mục đích: Dọn dẹp tài nguyên toàn cục và thực hiện các hành động sau khi toàn bộ Test Suite đã hoàn thành.
- Đối tượng Context: TestSuiteContext cung cấp thông tin về Test Suite vừa chạy.
- Ví dụ thực tế:
-
-
-
-
-
-
- Đóng kết nối cơ sở dữ liệu: Đóng kết nối đã được mở trong @BeforeTestSuite để giải phóng tài nguyên.
- Đóng kết nối cơ sở dữ liệu: Đóng kết nối đã được mở trong @BeforeTestSuite để giải phóng tài nguyên.
-
-
-
@AfterTestSuite
def cleanupDatabaseConnection(TestSuiteContext testSuiteContext) {
println "Cleaning up database connection."
if (GlobalVariable.dbConnection!= null) {
GlobalVariable.dbConnection.close()
}
}
-
-
-
-
- Gửi thông báo kết quả: Sử dụng các thư viện HTTP để gọi API của Slack hoặc Microsoft Teams, gửi một thông báo tóm tắt kết quả (tên Test Suite, số lượng test case pass/fail, thời gian thực thi) đến một kênh của đội ngũ phát triển.
- Tạo báo cáo tùy chỉnh: Phân tích các file kết quả XML do Katalon tạo ra để tổng hợp và tạo một báo cáo HTML tùy chỉnh theo định dạng của công ty.
Lưu trữ (Archiving): Nén toàn bộ thư mục báo cáo (logs, screenshots, reports) thành một file ZIP duy nhất và di chuyển nó đến một vị trí lưu trữ lâu dài.
-
-
-
Phương thức |
Mục đích |
Lấy trạng thái của Test Suite |
|
Lấy đường dẫn Test suite đang thực thi (đường dẫn tính từ thư mục Test Suites) |
-
-
-
- Mục đích: Thiết lập trạng thái ban đầu sạch sẽ và các điều kiện tiên quyết cụ thể cho mỗi Test Case.
- Đối tượng Context: TestCaseContext cung cấp thông tin về Test Case sắp chạy, bao gồm ID (getTestCaseId()) và danh sách các biến của nó. Nó cũng cho phép lưu trữ các giá trị tạm thời để sử dụng trong @AfterTestCase.
- Ví dụ thực tế:
-
-
-
-
-
-
- Tạo Dữ liệu Test "Dùng một lần": Đây là một thực hành tốt nhất trong kiểm thử tự động. Thay vì dựa vào dữ liệu có sẵn trong hệ thống (có thể bị thay đổi bởi người khác), hãy sử dụng API để tạo ra dữ liệu mới ngay trước khi test case chạy.
-
-
-
import com.kms.katalon.core.annotation.BeforeTestCase
import com.kms.katalon.core.context.TestCaseContext
import com.kms.katalon.core.util.KeywordUtil
import internal.GlobalVariable
class TestListener {
@BeforeTestCase
def beforeTestCase(TestCaseContext testCaseContext) {
if (GlobalVariable.STOP_WHEN_FAILED == true) {
KeywordUtil.markFailed('PREVIOUS TESTCASE FAILED!')
testCaseContext.skipThisTestCase()
}
}
}
-
-
-
-
- Xóa Cookies Trình duyệt: WebUI.deleteAllCookies() để đảm bảo mỗi Test Case bắt đầu với một session người dùng hoàn toàn mới, không bị ảnh hưởng bởi session của Test Case trước đó.
- Thiết lập Cờ trong DB: Thực thi một câu lệnh SQL để đặt một cờ hoặc một giá trị cấu hình trong cơ sở dữ liệu cần thiết cho kịch bản của Test Case sắp chạy.
-
-
-
-
-
-
- Mục đích: Dọn dẹp sau mỗi Test Case và thực hiện các hành động tích hợp dựa trên kết quả (pass/fail).
- Đối tượng Context: TestCaseContext cung cấp quyền truy cập vào kết quả của Test Case thông qua getTestCaseStatus(). Trạng thái có thể là PASSED, FAILED, ERROR, INCOMPLETE.
- Ví dụ thực tế (đây là phần quan trọng nhất):
-
-
-
-
-
-
- Xử lý Logic có điều kiện dựa trên kết quả:
-
-
-
import com.kms.katalon.core.annotation.AfterTestCase
import com.kms.katalon.core.context.TestCaseContext
import internal.GlobalVariable
class TestListener {
@AfterTestCase
def afterTestCase(TestCaseContext testCaseContext) {
if (testCaseContext.getTestCaseStatus() == 'FAILED') {
GlobalVariable.STOP_WHEN_FAILED = true
}
}
}
Tác động của việc sử dụng thành thạo @BeforeTestCase và @AfterTestCase là vô cùng to lớn. Nó nâng cấp framework từ một công cụ chỉ để chạy script và báo cáo pass/fail thành một hệ thống tự động hóa kiểm thử toàn diện. Hãy tưởng tượng một kịch bản: một bộ hồi quy chạy vào ban đêm. Một test case thất bại. Thay vì chỉ gửi một email thông báo lỗi, hệ thống tự động:
-
-
- Chụp lại chính xác màn hình tại thời điểm xảy ra lỗi.
- Tạo một ticket bug trong Jira.
- Gán ticket đó cho đội ngũ phát triển phù hợp.
- Đính kèm screenshot, logs, và các thông tin chi tiết về môi trường (trình duyệt, phiên bản OS) vào ticket.
-
Khi kỹ sư đến văn phòng vào buổi sáng, họ không chỉ thấy một test case bị lỗi. Họ thấy một quy trình xử lý lỗi đã được khởi tạo và sẵn sàng để phân tích. Điều này giảm đáng kể độ trễ giữa việc phát hiện lỗi và việc bắt đầu sửa lỗi, tối ưu hóa toàn bộ vòng lặp phản hồi (feedback loop) của quy trình phát triển. Đây là một tác động ở cấp độ quy trình nghiệp vụ, chứ không chỉ đơn thuần là kỹ thuật.
Các phương thức của TestCaseContext
Phương thức |
Mục đích |
Lấy thông báo lỗi của Test case khi Test case bị lỗi trong quá trình thực thi |
|
Lấy đường dẫn Test case đang thực thi trong Test Suite (đường dẫn tính từ thư mục Test Cases) |
|
Lấy trạng thái của Test case sau khi hoàn tất việc thực thi |
|
Lấy các biến được khai báo trong tab Variables của Test case đang được thực thi (trả về dữ liệu dạng Map với key là tên biến và value là giá trị ban đầu của biến đó) |
|
Kiểm tra Test case có đang ở trạng thái “Skipped” (bỏ qua thực thi) |
|
Bỏ qua thực thi Test case |