Cách thiết lập và chạy thử nghiệm Python đầu tiên của bạn với Pytest

Kiểm thử là một phần thiết yếu của quá trình phát triển phần mềm. Nó giúp bắt lỗi sớm và giảm khả năng xảy ra lỗi.


Pytest là một trong những khung thử nghiệm phổ biến nhất dành cho Python. Nó cho phép bạn viết các bài kiểm tra nhỏ và dễ đọc, có thể mở rộng khi ứng dụng của bạn phát triển. Tìm hiểu cách thiết lập và sử dụng Pytest với mã Python của bạn.


Thiết lập Pytest

Trước khi cài đặt Pytest, tốt nhất bạn nên tạo một môi trường ảo để cách ly môi trường thử nghiệm của mình, nhờ đó bạn có thể tránh xung đột với các gói và phần phụ thuộc khác.

Để tạo một môi trường ảo, hãy chạy lệnh sau trước khi cài đặt Pytest.

 python -m venv tests

Thao tác này sẽ tạo một môi trường ảo mới có tên tests trong thư mục hiện tại của bạn. Để kích hoạt môi trường, hãy chạy lệnh này nếu bạn đang dùng Linux hoặc Mac:

 source tests/bin/activate

Đối với Windows, hãy chạy lệnh này:

 tests\Scripts\activate

Để cài đặt Pytest, bạn có thể sử dụng pip, trình quản lý gói Python, với lệnh này trong thiết bị đầu cuối của bạn:

 pip install pytest

Nếu bạn không có Pip, đừng lo lắng; bạn có thể cài đặt Pip trên Windows, Mac và Linux.

Chạy lệnh sau để kiểm tra xem bạn đã cài đặt Pytest đúng chưa.

 pytest --version

Điều này sẽ trả lại số phiên bản đã cài đặt.

Tạo thử nghiệm đầu tiên của bạn

Xét hàm sau cộng hai số và trả về kết quả.

 def add_numbers(a, b):
    return a + b

Một số điều có thể đi sai với chức năng này. Ví dụ, hãy xem xét điều gì sẽ xảy ra nếu bạn gọi hàm với các giá trị không phải là số, chẳng hạn như Không có hoặc một giá trị kiểu chuỗi. Đây là một số trường hợp cạnh tiềm ẩn có thể khiến chức năng bị lỗi.

Một trong những bài kiểm tra đầu tiên bạn viết phải kiểm tra xem hàm có trả về kết quả như mong đợi hay không. Để làm điều này, bạn có thể sử dụng từ khóa khẳng định để so sánh đầu ra thực tế của hàm với đầu ra dự kiến. Trong trường hợp hàm add_numbers, hàm kiểm tra có thể giống như sau:

 def test_add_numbers():
    assert add_numbers(2, 3) == 5
    assert add_numbers(-1, 1) == 0
    assert add_numbers(0, 0) == 0

Hàm kiểm tra này bao gồm ba câu lệnh xác nhận, mỗi câu lệnh so sánh đầu ra của hàm add_numbers với một giá trị dự kiến. Phép thử đầu tiên kiểm tra xem việc cộng 2 và 3 có trả về 5 không, phép thử thứ hai kiểm tra xem phép cộng -1 và 1 có trả về 0 không, và phép thử thứ ba kiểm tra xem phép cộng 0 và 0 có trả về 0 không.

Cách chạy thử nghiệm với Pytest

Sau khi bạn đã viết các bài kiểm tra của mình, bước tiếp theo là chạy chúng. Để thực hiện điều này với Pytest, hãy điều hướng đến thư mục chứa tệp thử nghiệm của bạn và chạy lệnh pytest:

 pytest

Nếu mọi thứ hoạt động như mong đợi, bạn sẽ thấy một thông báo cho biết rằng tất cả các bài kiểm tra đã vượt qua thành công. Tuy nhiên, nếu bất kỳ xác nhận nào không thành công, Pytest sẽ báo lỗi và hiển thị cho bạn các giá trị đầu vào gây ra lỗi.

Ví dụ: giả sử bạn đã chạy hàm kiểm tra sau cho hàm add_numbers:

 def test_add_numbers():
    assert add_numbers(2, 3) == 6
    assert add_numbers(-1, 1) == 0
    assert add_numbers(0, 0) == 0

Xác nhận đầu tiên sẽ không thành công vì giá trị dự kiến ​​là 6, nhưng giá trị thực tế là 5 (tổng của 2 và 3). Pytest sẽ trả về thông báo sau:

Đầu ra của một lần chạy pytest hiển thị một lần thử nghiệm không thành công

Thông báo này hiển thị cho bạn các giá trị đầu vào gây ra giá trị đó và cũng cho bạn biết giá trị thực sẽ là bao nhiêu. Điều này giúp dễ dàng xác định và sửa lỗi nhanh chóng trong mã của bạn.

Sử dụng Pytest.raise để khẳng định ngoại lệ

Bây giờ, hãy viết một bài kiểm tra để giải quyết một trong các trường hợp cạnh của hàm add_numbers. Khi bạn chuyển một đối số không phải là số như Không có cho hàm, Python sẽ đưa ra một ngoại lệ TypeError.

Bạn đã phải xử lý các ngoại lệ trong chương trình Python của mình và bạn có thể kiểm tra xem mã của mình có tăng chúng một cách chính xác hay không.

Để thực hiện việc này, hãy sao chép chức năng kiểm tra sau vào tệp của bạn. Nó sử dụng trình quản lý ngữ cảnh pytest.raise để kiểm tra xem việc gọi hàm add_number bằng “Không” có làm tăng ngoại lệ TypeError hay không.

 import pytest
def test_add_numbers_with_invalid_inputs():
    with pytest.raises(TypeError):
        add_numbers(None, 2)


Sau đó chạy Pytest từ dòng lệnh. Nếu ngoại lệ không được đưa ra, thử nghiệm sẽ thất bại.

Bạn có thể đi xa hơn và kiểm tra chi tiết của thông báo ngoại lệ. Trình quản lý bối cảnh tạo đối tượng ExceptionInfo với các chi tiết.

Ví dụ: trong chức năng kiểm tra này, hãy xác nhận thông báo ngoại lệ như sau:

 def test_add_numbers_with_invalid_inputs():
    with pytest.raises(TypeError) as exc_info:
        add_numbers(None, 2)
    assert exc_info.value.args[0] == "unsupported operand type(s) for +: 'NoneType' and 'int'"


Nếu thông báo không khớp với thông báo trong thử nghiệm, Pytest sẽ báo lỗi.

Cách sử dụng Kiểm tra tham số hóa để kiểm tra nhiều đầu vào cùng một lúc

Thay vì gọi thủ công một chức năng có nhiều đầu vào như thế này:

 def test_add_numbers():
    assert add_numbers(2, 3) == 6
    assert add_numbers(-1, 1) == 0
    assert add_numbers(0, 0) == 0

Pytest cung cấp tính năng kiểm tra được tham số hóa cho phép bạn thực hiện điều tương tự dễ dàng hơn. Đây là cách bạn có thể viết lại chức năng kiểm tra ở trên:

 import pytest
@pytest.mark.parametrize("a,b,expected", [
    (2, 3, 5),
    (-1, 1, 0),
    (0, 0, 0)
])
def test_add_numbers(a, b, expected):
    assert add_numbers(a, b) == expected


Cách chạy nhiều bài kiểm tra

Cho đến giờ, bạn mới chỉ viết hai bài kiểm tra cho hàm add_numbers. Đối với các chức năng phức tạp hơn với nhiều bài kiểm tra hơn, bạn có thể muốn nhóm chúng trong một lớp.

Ví dụ, đây là cách bạn tạo một lớp kiểm tra cho hàm add.

 class TestAddFunction:
@pytest.mark.parametrize("a, b, expected", [
        (2, 3, 5),
        (-1, 1, 0),
        (0, 0, 0),
    ])
    def test_addition_with_numbers(self, a, b, expected):
        assert add_numbers(a, b) == expected
    def test_add_numbers_with_invalid_inputs(self):
        with pytest.raises(TypeError) as exc_info:
            add_numbers(None, 2)
        assert exc_info.value.args[0] == "unsupported operand type(s) for +: 'NoneType' and 'int'"


Lưu ý rằng bạn cần thêm tiền tố vào tên lớp là “Test” để Pytest có thể xác định nó là một lớp thử nghiệm và chạy nó.

Pytest có nhiều tính năng hơn

Sử dụng Pytest, bạn có thể tự động xác minh mã của mình hoạt động như mong đợi. Pytest cung cấp nhiều tính năng khác, chẳng hạn như đồ đạc cho phép bạn thiết lập và chia nhỏ dữ liệu kiểm tra và đánh dấu để thiết lập siêu dữ liệu trên các chức năng kiểm tra của bạn.

Ngoài ra, bạn có thể tích hợp Pytest trong quy trình CI của mình và bắt đầu chạy thử nghiệm tự động và liên tục khi bạn thay đổi mã của mình.

Previous Post
Next Post

post written by: