NỘI DUNG BÀI HỌC

✅ Giới thiệu và hướng dẫn tạo Test Listener trong Katalon
✅ 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:

      1. Bắt đầu thực thi Test Suite.
      2. Kích hoạt Hook @BeforeTestSuite. Logic được định nghĩa ở đây sẽ chạy MỘT LẦN DUY NHẤT.
      3. 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).
      4. Bắt đầu vòng lặp qua từng Test Case trong Test Suite.
      5. Kích hoạt Hook @BeforeTestCase. Logic này chạy TRƯỚC MỖI Test Case.
      6. 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).
      7. Thực thi các bước trong script của Test Case.
      8. 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).
      9. 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).
      10. Kết thúc vòng lặp, chuyển sang Test Case tiếp theo.
      11. 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).
      12. 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.
      13. 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

@BeforeTestSuite: Đây là điểm khởi đầu của toàn bộ quá trình thực thi. Logic đặt ở đây là lý tưởng cho các tác vụ thiết lập một lần, tốn kém về thời gian hoặc tài nguyên, và kết quả của chúng có thể được chia sẻ cho tất cả các Test Case trong Suite.
        • 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ẽ.

@AfterTestSuite: Đây là điểm kết thúc, nơi chúng ta thực hiện các hành động dọn dẹp cuối cùng và tổng kết kết quả.
        • 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.
@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.

Các phương thức của TestSuiteContext

Phương thức

Mục đích

getStatus()

Lấy trạng thái của Test Suite

getTestSuiteId()

Lấy đường dẫn Test suite đang thực thi (đường dẫn tính từ thư mục Test Suites)


@BeforeTestCase: Hook này được thực thi trước mỗi Test Case, cung cấp một cơ hội hoàn hảo để đảm bảo rằng mỗi Test Case bắt đầu trong một môi trường độc lập và có thể dự đoán được. Nguyên tắc "độc lập" của các test case là cực kỳ quan trọng để tránh các lỗi dây chuyền, nơi một test case thất bại gây ảnh hưởng và làm thất bại các test case tiếp theo.
        • 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.

@AfterTestCase: Đây là hook mạnh mẽ và được sử dụng thường xuyên nhất. Nó không chỉ dùng để dọn dẹp mà còn để thực hiện các hành động thông minh dựa trên kết quả của Test Case vừa 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@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:

      1. Chụp lại chính xác màn hình tại thời điểm xảy ra lỗi.
      2. Tạo một ticket bug trong Jira.
      3. Gán ticket đó cho đội ngũ phát triển phù hợp.
      4. Đí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

getMessage()

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

getTestCaseId()

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)

getTestCaseStatus()

Lấy trạng thái của Test case sau khi hoàn tất việc thực thi

getTestCaseVariables()

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 đó)

isSkipped()

Kiểm tra Test case có đang ở trạng thái “Skipped” (bỏ qua thực thi)

skipThisTestCase()

Bỏ qua thực thi Test case

Teacher

Teacher

Phạm Đức Hải

QA Automation Engineer

  • Nick name: Chuột Béo Tester cool
  • Kinh nghiệm: 05 năm trong xây dựng và kiến trúc các dự án Kiểm thử tự động bằng sử dụng Công cụ Katalon Studio Enterprise

Cộng đồng Automation Testing Việt Nam:

🌱 Telegram Automation Testing:   Cộng đồng Automation Testing
🌱 
Facebook Group Automation: Cộng đồng Automation Testing Việt Nam
🌱 
Facebook Fanpage: Cộng đồng Automation Testing Việt Nam - Selenium
🌱 Telegram
Manual Testing:   Cộng đồng Manual Testing
🌱 
Facebook Group Manual: Cộng đồng Manual Testing Việt Nam

Chia sẻ khóa học lên trang

Bạn có thể đăng khóa học của chính bạn lên trang Anh Tester để kiếm tiền

Danh sách bài học