PYTHON UNIT TESTING
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
MỚI CẬP NHẬT

Thông báo: Download 4 khóa học Python từ cơ bản đến nâng cao tại đây.

Sử dụng Mock trong Unittest của Python

Không phải lúc nào mình cũng có thể kiểm tra mã nguồn một cách trực tiếp, đặc biệt khi mã nguồn phụ thuộc vào các yếu tố bên ngoài như hệ thống, mạng, hoặc các I/O operation. Để giải quyết vấn đề này, Python cung cấp mô-đun unittest.mock với lớp Mock, giúp mình mô phỏng các đối tượng thực tế và kiểm tra mã nguồn một cách độc lập và hiệu quả hơn. Trong bài viết này, mình sẽ tìm hiểu về lớp Mock của unittest.mock, cách sử dụng nó để mô phỏng các đối tượng khác, và lợi ích của việc sử dụng Mock trong việc kiểm tra mã nguồn Python.

test php

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

Giới thiệu về lớp Mock của unittest trong Python

Mocks mô phỏng hành vi của các đối tượng thực tế. Để kiểm tra một đối tượng phụ thuộc vào các đối tượng khác một cách độc lập, bạn sử dụng các đối tượng mock để mô phỏng các đối tượng thực.

Để mô phỏng các đối tượng, bạn sử dụng mô-đun unittest.mock. Mô-đun này cung cấp lớp Mock cho phép bạn mô phỏng các đối tượng khác. Nó cũng cung cấp lớp MagicMock, là một lớp con của Mock. Ngoài các phương thức và thuộc tính của lớp Mock, lớp MagicMock còn có các triển khai của tất cả các phương thức đặc biệt như __str____repr__.

Xem ví dụ sau:

Bài viết này được đăng tại [free tuts .net]

from unittest.mock import Mock

# tạo một đối tượng mock mới
mock = Mock()

# mô phỏng hàm api
mock.api.return_value = {
    'id': 1,
    'message': 'hello'
}
# gọi hàm api
print(mock.api())

Kết quả:

{'id': 1, 'message': 'hello'}

Cách hoạt động:

Đầu tiên, import lớp Mock từ mô-đun unittest.mock:

from unittest.mock import Mock

Thứ hai, tạo một thể hiện mới của lớp Mock:

mock = Mock()

Thứ ba, mô phỏng hàm api() và gán giá trị trả về của nó là một từ điển:

mock.api.return_value = {
    'id': 1,
    'message': 'hello'
}

Cuối cùng, gọi hàm api() từ đối tượng mock. Nó sẽ trả về giá trị đã gán:

print(mock.api())

Trong ví dụ này, mình có hai đối tượng mock: mockmock.api.

Thêm câu lệnh print() vào chương trình để xem cách nó hoạt động:

from unittest.mock import Mock

# tạo một đối tượng mock mới
mock = Mock()
print(mock)

# mô phỏng hàm api
mock.api.return_value = {
    'id': 1,
    'message': 'hello'
}
print(mock.api)

# gọi hàm api
print(mock.api())

Kết quả:

<Mock id='1830094470496'>
<Mock name='mock.api' id='1830100086416'>
{'id': 1, 'message': 'hello'}

Kết quả cho thấy hai đối tượng Mock.

Tóm lại, nếu bạn gán một thuộc tính không tồn tại trên đối tượng Mock, Python sẽ trả về một đối tượng mock mới. Nhờ vào tính năng này, bạn có thể sử dụng lớp Mock để mô phỏng bất kỳ đối tượng nào bạn muốn.

Khi nào sử dụng mock của unittest trong Python

Đây là những trường hợp bạn nên xem xét sử dụng mock:

  • Các lệnh gọi hệ thống
  • Mạng
  • Hoạt động I/O
  • Đồng hồ & thời gian, múi giờ
  • Hoặc các trường hợp khác mà kết quả không thể dự đoán trước

Tại sao sử dụng mock của unittest trong Python

Lợi ích của mock bao gồm:

  • Tăng tốc độ kiểm tra
  • Loại trừ các yếu tố dư thừa bên ngoài
  • Làm cho các kết quả không thể đoán trước trở nên có thể đoán trước

Ví dụ về sử dụng Mock trong Python Unittest

Giả sử bạn có một mô-đun gọi là odometer.py:

from random import randint

def speed():
    return randint(40, 120)

def alert():
    s = speed()
    if s < 60 or s > 100:
        return True
    return False

Trong mô-đun sensor.py:

  • Hàm speed() trả về tốc độ hiện tại của một phương tiện. Nó trả về một giá trị ngẫu nhiên giữa 40 và 120. Trong thế giới thực, hàm này sẽ đọc dữ liệu từ đồng hồ đo tốc độ.
  • Hàm alert() trả về True nếu tốc độ hiện tại thấp hơn 60 km/h và cao hơn 100 km/h. Hàm alert() sử dụng hàm speed() để lấy tốc độ hiện tại.

Screenshot 202024 06 17 20162333 png

Sẽ rất khó kiểm tra hàm alert() vì giá trị trả về bởi hàm speed() là khác nhau. Để giải quyết, bạn có thể sử dụng lớp Mock.

Sau đây là cách tạo mô-đun kiểm tra test_odometer.py để kiểm tra hàm alert():

import unittest
from unittest.mock import Mock
import odometer

class TestOdometer(unittest.TestCase):
    def test_alert_normal(self):
        odometer.speed = Mock()
        odometer.speed.return_value = 70
        self.assertFalse(odometer.alert())

    def test_alert_overspeed(self):
        odometer.speed = Mock()
        odometer.speed.return_value = 100
        self.assertFalse(odometer.alert())

    def test_alert_underspeed(self):
        odometer.speed = Mock()
        odometer.speed.return_value = 59
        self.assertTrue(odometer.alert())

Chạy kiểm tra:

Screenshot 202024 06 17 20162347 png

python -m unittest test_odometer.py -v

Kết quả:

test_alert_normal (test_odometer.TestOdometer) ... ok
test_alert_overspeed (test_odometer.TestOdometer) ... ok
test_alert_underspeed (test_odometer.TestOdometer) ... ok

----------------------------------------------------------------------
Ran 3 tests in 0.001s

OK

Kết bài

Việc sử dụng lớp Mock của mô-đun unittest.mock trong Python giúp bạn dễ dàng mô phỏng các đối tượng khác để kiểm tra mã nguồn một cách độc lập và hiệu quả. Nhờ vào các tính năng mạnh mẽ của lớp Mock, bạn có thể loại bỏ các yếu tố không thể đoán trước và tăng tốc độ kiểm tra. Hy vọng rằng qua bài viết này, bạn đã hiểu rõ hơn về cách sử dụng mock để nâng cao chất lượng và độ tin cậy của mã nguồn Python.

Cùng chuyên mục:

Cách tạo một widget nhập ngày và giờ sử dụng PyQt QDateTimeEdit

Cách tạo một widget nhập ngày và giờ sử dụng PyQt QDateTimeEdit

Cách tạo một widget nhập giờ sử dụng lớp PyQt QTimeEdit

Cách tạo một widget nhập giờ sử dụng lớp PyQt QTimeEdit

Cách tạo một widget nhập ngày sử dụng lớp PyQt QDateEdit

Cách tạo một widget nhập ngày sử dụng lớp PyQt QDateEdit

Cách sử dụng widget PyQt QSpinBox để tạo một spin box

Cách sử dụng widget PyQt QSpinBox để tạo một spin box

Sử dụng PyQt QComboBox để tạo Widget Combobox

Sử dụng PyQt QComboBox để tạo Widget Combobox

Cách sử dụng lớp PyQt QRadioButton

Cách sử dụng lớp PyQt QRadioButton

Cách sử dụng lớp QCheckBox trong PyQt

Cách sử dụng lớp QCheckBox trong PyQt

Cách sử dụng QFormLayout trong PyQt

Cách sử dụng QFormLayout trong PyQt

Cách sử dụng QGridLayout trong PyQt

Cách sử dụng QGridLayout trong PyQt

Cách sử dụng QVBoxLayout trong PyQt

Cách sử dụng QVBoxLayout trong PyQt

Cách sử dụng widget QLineEdit trong PyQt

Cách sử dụng widget QLineEdit trong PyQt

Cách sử dụng widget QPushButton của PyQt

Cách sử dụng widget QPushButton của PyQt

Cách sử dụng widget PyQt QLabel

Cách sử dụng widget PyQt QLabel

Tín hiệu và Khe (Signals & Slots) trong PyQt

Tín hiệu và Khe (Signals & Slots) trong PyQt

PyQt là gì? Tạo một chương trình

PyQt là gì? Tạo một chương trình "Hello World".

Ứng dụng System Tray với Tkinter

Ứng dụng System Tray với Tkinter

Cách hiển thị đồ thị từ thư viện Matplotlib trong Tkinter

Cách hiển thị đồ thị từ thư viện Matplotlib trong Tkinter

Cách sử dụng Validate trong Tkinter

Cách sử dụng Validate trong Tkinter

Cấu trúc MVC trong Tkinter

Cấu trúc MVC trong Tkinter

Cách sử dụng widget PhotoImage của Tkinter

Cách sử dụng widget PhotoImage của Tkinter

Top