Giới thiệu chung
Pytest là một khung kiểm thử phần mềm mã nguồn mở dành cho ngôn ngữ Python, giúp đơn giản hóa quy trình viết các bộ kiểm thử. Nó hỗ trợ nhiều phiên bản Python trên cả hệ điều hành Windows, Unix và macOS. Điểm mạnh của công cụ này nằm ở khả năng đọc hiểu dễ dàng của các đoạn mã kiểm thử và cơ chế tự động phát hiện các trường hợp cần chạy.
Cài đặt Pytest
Để bắt đầu sử dụng, bạn có thể cài đặt gói thông qua trình quản lý package tiêu chuẩn bằng lệnh dưới đây:
pip install -U pytest
Sau khi hoàn tất, hãy xác minh phiên bản đã cài đặt trong dòng lệnh để đảm bảo quá trình thiết lập thành công:
$ pytest --version
This is pytest version X.Y.Z, imported from .../site-packages/pytest.py
Ví dụ về bài kiểm thử đơn giản
Dưới đây là một kịch bản kiểm thử tối giản chỉ gồm vài dòng mã. Chúng ta sẽ tạo một hàm tính toán và viết một assertions để kiểm tra kết quả:
# test_math_operations.py
def add_value(number):
return number + 10
def test_addition_logic():
# Trường hợp này cố tình sai để mô phỏng lỗi
assert add_value(5) == 12
Khi chạy lệnh pytest, hệ thống sẽ tìm kiếm và thực thi các tập tin khớp với quy tắc định danh:
$ pytest
=========================== test session starts ============================
platform win32 -- Python 3.x,pytest-X.Y.z
collected 1 item
test_math_operations.py F [100%]
================================= FAILURES =================================
_______________________________ test_addition_logic ________________________________
def test_addition_logic():
> assert add_value(5) == 12
E assert 15 == 12
E + where 15 = add_value(5)
test_math_operations.py:4: AssertionError
========================= 1 failed in 0.15 seconds =========================
Nếu biểu thức assert không đúng, Pytest sẽ trả về trạng thái thất bại kèm thông tin chi tiết về giá trị nhận được so với giá trị mong đợi nhờ cơ chế nội soi thông minh.
Thực thi nhiều bài kiểm thử cùng lúc
Bằng cách gọi lệnh pytest tại thư mục gốc, công cụ sẽ tự động quét và chạy mọi tệp có tên chứa test_ hoặc kết thúc bằng _test.py trong cây thư mục hiện tại. Quy tắc này tuân thủ theo chuẩn tìm kiếm mặc định của hệ sinh thái Python testing.
Xác nhận việc ném ra ngoại lệ
Để kiểm tra xem một đoạn mã có chính xác gây ra lỗi nhất định hay không, chúng ta sử dụng context manager pytest.raises:
# test_exception_handling.py
import pytest
def divide_by_zero(value):
if value == 0:
raise ZeroDivisionError("Cannot divide by zero")
def test_error_raised_correctly():
with pytest.raises(ZeroDivisionError):
divide_by_zero(0)
Chạy chế độ tĩnh gọn gàng để thấy kết quả:
$ pytest -q test_exception_handling.py
. [100%]
1 passed in 0.10 seconds
Tổ chức kiểm thử bằng lớp
Khi số lượng kịch bản tăng lên, việc nhóm các phương thức vào bên trong một lớp kiểm thử là phương án tối ưu. Pytest không yêu cầu lớp phải kế thừa từ bất kỳ đối tượng đặc biệt nào:
# test_user_class.py
class TestUserFeatures(object):
def test_username_contains_letters(self):
user_name = "Admin"
assert user_name.isalpha()
def test_password_has_minimum_length(self):
pwd = "pass"
assert len(pwd) >= 8
Hệ thống sẽ phát hiện lớp bắt đầu bằng tiền tố Test và các phương thức bắt đầu bằng test_. Trong ví dụ trên, phương thức thứ hai sẽ báo lỗi vì chuỗi mật khẩu quá ngắn.
$ pytest -q test_user_class.py
.F [100%]
================================= FAILURES =================================
_____________________ TestUserFeatures.test_password_has_minimum_length ______________________
def test_password_has_minimum_length(self):
pwd = "pass"
> assert len(pwd) >= 8
E AssertionError: assert 4 >= 8
test_user_class.py:9: AssertionError
1 failed, 1 passed in 0.10 seconds
Sử dụng thư mục tạm độc lập trong Fixture
Một trong những tính năng mạnh mẽ là việc cung cấp tài nguyên dùng cho từng bài kiểm thử thông qua các tham số fixture. Ví dụ, Pytest tự động tạo đường dẫn tới thư mục tạm riêng cho mỗi lần chạy:
# test_temp_files.py
def test_accessing_temp_directory(temp_path):
print (temp_path)
# Tạo một tập tin rỗng để kiểm tra
file_obj = temp_path.join('log.txt')
file_obj.write('data')
assert file_obj.check(file=True)
Lưới fixture temp_path (hoặc tmpdir tùy phiên bản) sẽ được inject vào hàm trước khi nó được thực thi, đảm bảo sự cô lập giữa các test case.
Tài nguyên học tập nâng cao
- Hướng dẫn sử dụng CLI và các cờ lệnh phổ biến.
- Cách tích hợp Pytest với các cấu trúc kiểm thử cũ như unittest hoặc nose.
- Tìm hiểu sâu về cơ chế đánh dấu (marker) để phân nhóm test.
- Cơ sở dữ liệu về các plugin và cách đóng gói extension.
- Best practices về virtual environment và quản lý dependency cho dự án kiểm thử.