@patch trong Python là gì?

Thay vì TDD [Phát triển theo hướng kiểm tra] buộc bạn phải nghĩ về các bài kiểm tra trước, người ta có thể thực hành TPD [Phát triển song song kiểm tra]. Trong TPD, bạn bắt đầu với việc phát triển mã, nhưng trong quá trình phát triển, bạn kiểm tra tính chính xác của mã bằng cách viết các bài kiểm tra và thực thi chúng [thay vì chạy mã trực tiếp hoặc sử dụng bảng điều khiển]

Giới thiệu. Trong bài viết này, chúng tôi đang thảo luận về bản vá. trăn đối tượng. Hầu hết thời gian, phần mềm chúng tôi viết tương tác trực tiếp với cái mà chúng tôi gọi là dịch vụ "bẩn". Đặt các dịch vụ quan trọng đối với ứng dụng nhưng tương tác của chúng có các tác dụng phụ có chủ ý nhưng không mong muốn, tôi. e. , các dịch vụ không mong muốn trong bối cảnh thực hiện kiểm tra tự động

Ví dụ: bạn đang xây dựng ứng dụng xã hội và muốn thử nghiệm tính năng đăng bài mới trên Facebook, nhưng bạn muốn tránh đăng bài lên Facebook mỗi khi chạy bộ thử nghiệm. Thư viện unittest Python chứa một gói con có tên là unittest. giả [hoặc giả nếu bạn khai báo nó là một phụ thuộc]. Điều này cung cấp một phương tiện mạnh mẽ và thuận tiện để chế giễu và che giấu những tác dụng phụ không mong muốn này

Việc kiểm tra là rất quan trọng để đảm bảo rằng logic phần mềm của bạn là chính xác, đáng tin cậy và xanh khi viết mã mạnh mẽ. Tuy nhiên, lệ phí của bài kiểm tra phụ thuộc vào mức độ bài kiểm tra thể hiện các tiêu chí đó tốt như thế nào. Các rào cản, logic phức tạp và các phụ thuộc không thể đoán trước khiến việc viết các bài kiểm tra thực tế trở nên khó khăn. Thư viện mục mô phỏng Python unittest. giả cho phép vượt qua những ranh giới này

Cách chế giễu hoặc vá lỗi có nghĩa là gì?

Một đối tượng giả thay thế và bắt chước đối tượng thực trong môi trường thử nghiệm. Nó là một thiết bị linh hoạt và mạnh mẽ để nâng cao chất lượng bài kiểm tra của bạn

Một mục đích của việc sử dụng các mục mô phỏng Python là thao túng hành vi mã của bạn trong quá trình kiểm tra

Ví dụ: nếu mã của bạn yêu cầu HTTP đến một nhà cung cấp dịch vụ bên ngoài, thử nghiệm sẽ chạy tốt nhất có thể dự đoán được với số lượng nhà cung cấp dịch vụ hoạt động như dự đoán. Những thay đổi nhanh chóng trong hành vi của các dịch vụ bên ngoài này cũng có thể gây ra các thảm họa không liên tục trong bộ kiểm tra của bạn

Do đó, chúng tôi khuyên bạn nên xem mã của mình trong môi trường được kiểm soát. Thay đổi các yêu cầu thực bằng các đối tượng giả giúp bạn mô phỏng thảm họa của nhà cung cấp bên ngoài và các phản hồi thành công theo cách có thể dự đoán được

Có thể khó kiểm tra các vùng nhất định trong cơ sở mã của bạn. Những vùng đó bao gồm các khối "bên cạnh" và câu lệnh "nếu" khó thực thi. Các đối tượng mô phỏng trong Python có thể giúp bạn quản lý đường dẫn thực thi mã của mình để tiếp cận các khu vực đó và cải thiện mức độ phù hợp của mã

Bản vá lỗi là gì?

đơn vị nhất. mock cung cấp một cơ chế mô phỏng đối tượng mạnh mẽ được gọi là patch[]. Điều này tìm kiếm một đối tượng trong một mô-đun cụ thể và thay thế đối tượng đó bằng một mô hình. Patch[] thường được sử dụng làm công cụ trang trí hoặc trình quản lý bối cảnh để cung cấp một vùng để mô phỏng đối tượng đích

Chức năng patch[] được sử dụng như một trình phát hiện như thế nào?

Nếu bạn muốn giả lập một đối tượng thông qua chức năng kiểm tra của mình, hãy sử dụng patch[] làm công cụ trang trí chức năng. Để xem cách nó hoạt động, hãy sắp xếp lại my_calendar. báo cáo py bằng cách đặt logic và kiểm tra trong các tài liệu riêng biệt

Ví dụ. Bây giờ, chúng tôi đưa ra một ví dụ về hàm patch[] được sử dụng như một trình phát hiện. Ví dụ được đưa ra dưới đây -

Các chức năng này hiện có trong tệp của chúng, tách biệt với các bài kiểm tra. Sau đó xây dựng lại các bài kiểm tra trong một tệp có tên tests. py. Cho đến nay, chúng tôi đã vá khỉ vào đối tượng trong tệp nơi đối tượng sống. Bản vá khỉ thay thế một đối tượng bằng một đối tượng khác trong thời gian chạy

Chức năng patch[] được sử dụng như một trình quản lý ngữ cảnh như thế nào?

Đôi khi, bạn sẽ muốn sử dụng patch[] làm trình quản lý ngữ cảnh thay vì trình trang trí. Một số lý do khiến bạn có thể chọn trình quản lý bối cảnh bao gồm những điều sau

  1. Bạn chỉ cần giả lập một mục cho một phần của phạm vi thử nghiệm
  2. Bạn đã sử dụng quá nhiều trình trang trí hoặc tham số, điều này làm ảnh hưởng đến sự rõ ràng của bài kiểm tra của bạn

Phần kết luận. Bạn đã học được nhiều về cách chế nhạo các đối tượng với unittest. chế nhạo

bây giờ bạn có thể. sử dụng các mô hình giả để mô phỏng các đối tượng trong séc của bạn, nghiên cứu thông tin sử dụng và cá nhân hóa các giá trị trả về cũng như các hệ quả phụ của các đối tượng mô phỏng để hiểu cách các tiện ích được sử dụng

khám phá các đối tượng patch[] trong quá trình codebase của bạn

tránh xa những rắc rối khi sử dụng các đối tượng giả Python

Tạo ra một nền tảng bí quyết để giúp viết các bài kiểm tra cao hơn. Mocks cung cấp thông tin chi tiết về mã của bạn mà trong bất kỳ trường hợp nào khác, bạn có thể không nhận được nữa

Một tuyên bố từ chối trách nhiệm cuối cùng. Hãy cẩn thận để sử dụng các đối tượng giả một cách tiết kiệm. Thật dễ dàng để sử dụng chức năng đối tượng giả của Python để tạo các bản giả làm giảm giá trị các bài kiểm tra của bạn

[khỉ-] vá lỗi là một kỹ thuật để thay đổi hành vi mã mà không làm thay đổi nguồn của nó. Nó được thực hiện trong thời gian chạy, thường bằng cách ghi đè các thuộc tính của các đối tượng hiện có. Một đối tượng có thể là một thể hiện của một số loại, một lớp hoặc thậm chí là một mô-đun. Kỹ thuật này được [ab] sử dụng phổ biến nhất cho các bài kiểm tra khi chúng ta không thể vượt qua các bản mô phỏng một cách đơn giản

# by default, it will create a new instance of Mock and put it in place of on_commit
@patch["django.db.transaction.on_commit"]
def test_booking_flight__successful_boking__schedueles_notification_after_commit[on_commit_mock]:
    code_that_imports_on_commit_from_djang_db_etc[]

    on_commit_mock.assert_called_once_with[...]

Một ví dụ ấn tượng khác là thư viện gevent biến mã đồng bộ thành không đồng bộ bằng cách sử dụng bản vá khỉ

# the first thing to do is to call monkey.patch_all[]
# to turn code into asynchronous one
from gevent import monkey; monkey.patch_all[]
import time

import requests
from gevent.pywsgi import WSGIServer


def application[env, start_response]:
    start = time.time[]
    # we use requests [which is not asyncio-friendly!] 
    # to check how much time it takes example.com to respond
    response = requests.get['//example.com/']
    end = time.time[]
    if not response.ok:
        start_response['500 Internal Server Errord', [['Content-Type', 'text/html']]]
        return [b'Something is wrong with the site!']

    start_response['200 OK', [['Content-Type', 'text/html']]]
    return [f"Server took {end - start}s to respond".encode[]]


if __name__ == '__main__':
    WSGIServer[['127.0.0.1', 8080], application].serve_forever[]

Hãy đánh giá nó bằng cách sử dụng wrk

wrk -c 20 -t 5 -d 5s --timeout 5s //localhost:8080
# requests to example.com takes on average in ~0.25s

# without gevent.patch_all
Running 5s test @ //localhost:8080
  5 threads and 20 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     1.90s     1.59s    4.83s    47.37%
    Req/Sec     2.11      1.52     4.00     57.89%
  19 requests in 5.06s, 2.79KB read
Requests/sec:      3.76
Transfer/sec:     565.48B

# with gevent.patch_all
Running 5s test @ //localhost:8080
  5 threads and 20 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency   364.20ms  116.89ms 613.86ms   74.90%
    Req/Sec    11.72      6.85    30.00     59.35%
  259 requests in 5.10s, 38.00KB read
Requests/sec:     50.77  -------- compared to 3.76 without gevent...
Transfer/sec:      7.45KB

Gevent đã yêu cầu một thư viện thân thiện với coroutine và nhờ đồng thời, nó cho phép máy chủ mẫu của chúng tôi xử lý hơn 13. Yêu cầu gấp 5 lần mỗi giây

Cuối cùng, chúng tôi có một chương trình có đồng thời dựa trên coroutine [nguyên tắc giống như trong asyncio hoặc nút. js] nhưng mã của nó vẫn giống như mã đồng bộ. Chúng tôi không cần các thư viện hợp tác, đặc biệt hoặc các từ khóa không đồng bộ/đang chờ trong mã của chúng tôi. Nó gần giống như ma thuật

Vá lỗi trong các bài kiểm tra

Python bao gồm một tiện ích để vá lỗi, tôi. e. đơn vị nhất. chế nhạo. vá. Cách sử dụng mặc định là trang trí chức năng kiểm tra của chúng tôi. Giả sử chúng ta có chế độ xem Django trông như thế này…

from api.client import ApiClient

def get_stats[request]:
    site_url = request.GET.get['url']

    api_client = ApiClient[]
    stats = api_client.get_stats_for[site_url]

    seconds = int[stats['time_to_respond'].total_seconds[]]
    return JsonResponse[{'latency': f'{seconds}s'}]

và chúng tôi muốn kiểm tra nó. Chúng tôi nhận thấy nó có một phụ thuộc – ApiClient từ một mô-đun khác. Nếu chúng tôi muốn kiểm tra chế độ xem get_stats theo cách đáng tin cậy, có thể dự đoán được, chúng tôi cần sử dụng test-double thay vì ApiClient. Tuy nhiên, không có cách nào đơn giản để làm như vậy. Nếu nó được chuyển đến get_stats làm đối số, thì chúng ta chỉ cần chuyển Mock thay thế

def get_stats[request, api_client_class]:
    ...
    api_client = api_client_class[]
    ...

…nhưng không phải vậy. Tuy nhiên, chúng ta vẫn có thể sử dụng trình trang trí bản vá

@patch['api.client.ApiClient.get_stats_for']
def test__get_stats__time_to_respond_is_timedelta__formats_as_seconds[client]:
    response = client.get['/stats/']

    assert response.json[] == {'latency': '63s'}

Điều này vẫn chưa kết thúc, nhưng nếu chúng tôi đưa trình gỡ lỗi vào thử nghiệm, chúng tôi sẽ nhận thấy rằng ApiClient. get_stats_for hiện là MagicMock

@patch['api.client.ApiClient.get_stats_for']
def test__get_stats__time_to_respond_is_timedelta__formats_as_seconds[client]:
    breakpoint[]
    response = client.get['/stats/']

    assert response.json[] == {'latency': '63s'}

# after running pytest...
[Pdb] from api.client import ApiClient
[Pdb] ApiClient.get_stats_for

Nó có nghĩa là chế giễu của chúng tôi đã thành công. Chúng tôi đã thay thế một phụ thuộc có vấn đề bằng một Mock. Nhân tiện, nếu bạn đang tìm kiếm các phương pháp hay nhất để sử dụng mô phỏng, hãy xem hướng dẫn chính thức [gần như] của tôi về mô phỏng trong Python hoặc tại sao mô phỏng có thể nguy hiểm khi bị lạm dụng

Bây giờ, thử nghiệm vẫn không thành công vì get_stats nhận được MagicMock trong khi nó mong đợi một từ điển. Chúng ta cần tham số hóa mô hình. Chúng ta có thể làm như vậy bằng cách chuyển đối số thứ hai tới @patch

@patch[
    'api.client.ApiClient.get_stats_for',
    Mock[return_value={'time_to_respond': timedelta[minutes=1, seconds=3]}]
]
def test__get_stats__time_to_respond_is_timedelta__formats_as_seconds[client]:
    response = client.get['/stats/']

    assert response.json[] == {'latency': '63s'}

Điều này về cơ bản có nghĩa là thay vì api. khách hàng. ApiClient. get_stats_vì chúng tôi muốn một Mô phỏng mà khi được gọi, sẽ trả về {‘time_to_Response’. múi giờ[phút=1, giây=3]}

Vá mà không cần trang trí

bản vá cũng có thể được sử dụng như một trình quản lý ngữ cảnh. Kết quả trả về sẽ là một Mô hình được chèn vào vị trí của một thuộc tính đang được vá

________số 8

“Bản vá Python không hoạt động. ” – làm thế nào cho đúng?

Đôi khi bạn sẽ phải đối mặt với tình huống mặc dù có sự hiện diện của trình trang trí bản vá hoặc trình quản lý bối cảnh, phần phụ thuộc sẽ trông như thể nó không được vá chút nào. Nói tóm lại, có thể là do có nhiều tài liệu tham khảo hiện có về thứ bạn đang cố gắng vá. Mã đang kiểm tra sử dụng một mã, nhưng bạn đã vá thành công một mã khác. Ca mổ thành công nhưng bệnh nhân tử vong. phải làm gì?

Nói tóm lại, bạn cần đảm bảo rằng bạn vá cùng một tham chiếu mà mã đang thử nghiệm sử dụng

# views/__init__.py
from api import client


def get_stats[site_url]:
    api_client = client.ApiClient[]
    stats = api_client.get_stats_for[site_url]

    seconds = int[stats['time_to_respond'].total_seconds[]]
    return {'latency': f'{seconds}s'}


# test_view.py
@patch[
    # we patch class in the module where it is imported into
    # [the same our code under test comes from]
    'view.client.ApiClient.get_stats_for',
    ...
]
def test__get_stats__time_to_respond_is_timedelta__formats_as_seconds[]:
    ...

Xem phần Nơi vá lỗi của unittest. tài liệu giả để biết thêm chi tiết. Ngoài ra, bạn có thể sử dụng một giải pháp thay thế tiện lợi cho bản vá, đó là bản vá. vật

vá. đối tượng - đơn giản hơn để làm cho đúng

vá. đối tượng rất đơn giản để sử dụng – bạn chỉ cần nhập đối tượng có thuộc tính mà bạn muốn vá và áp dụng bản vá. vật

# the first thing to do is to call monkey.patch_all[]
# to turn code into asynchronous one
from gevent import monkey; monkey.patch_all[]
import time

import requests
from gevent.pywsgi import WSGIServer


def application[env, start_response]:
    start = time.time[]
    # we use requests [which is not asyncio-friendly!] 
    # to check how much time it takes example.com to respond
    response = requests.get['//example.com/']
    end = time.time[]
    if not response.ok:
        start_response['500 Internal Server Errord', [['Content-Type', 'text/html']]]
        return [b'Something is wrong with the site!']

    start_response['200 OK', [['Content-Type', 'text/html']]]
    return [f"Server took {end - start}s to respond".encode[]]


if __name__ == '__main__':
    WSGIServer[['127.0.0.1', 8080], application].serve_forever[]
0

Nếu bạn muốn sử dụng bản vá. đối tượng cho một phương thức, bạn nhập một lớp. Nếu bạn muốn vá. phản đối một hàm hoặc toàn bộ lớp, hãy nhập mô-đun mà chúng nằm trong đó

Bạn có nên vá?

[khỉ-] vá nên được sử dụng một cách tiết kiệm. Đó nên là phương sách cuối cùng của bạn. Trong mã của tôi, tôi không có lựa chọn nào khác ngoài việc vá nhờ tiêm phụ thuộc

Về lâu dài, giá cho những mánh khóe như vậy là rất, rất cao. Vá thường có nghĩa là chạm và thay đổi các chi tiết triển khai theo cách mà các tác giả không lường trước được. Điều này giới thiệu khớp nối bổ sung với những thứ không nên có. Có nghĩa là họ sẽ khó thay đổi hơn

Bản vá có nghĩa là gì trong Python?

[monkey-] là một kỹ thuật để thay đổi hành vi của mã mà không làm thay đổi nguồn của nó . Nó được thực hiện trong thời gian chạy, thường bằng cách ghi đè các thuộc tính của các đối tượng hiện có. Một đối tượng có thể là một thể hiện của một số loại, một lớp hoặc thậm chí là một mô-đun.

Làm cách nào để giả lập lệnh gọi API bằng Python?

Chế nhạo API bên ngoài bằng Python .
Những bước đầu tiên
Tái cấu trúc mã của bạn thành một dịch vụ
Mô phỏng đầu tiên của bạn
Các cách khác để vá
Chế giễu hành vi dịch vụ hoàn chỉnh
Mocking chức năng tích hợp
Tái cấu trúc các bài kiểm tra để sử dụng các lớp
Kiểm tra các bản cập nhật cho dữ liệu API

Làm cách nào để giả lập một đối tượng trong Python?

Làm cách nào để chúng tôi mô phỏng bằng Python? . Khi bản vá chặn cuộc gọi, nó sẽ trả về một đối tượng MagicMock theo mặc định. Bằng cách đặt các thuộc tính trên đối tượng MagicMock, bạn có thể mô phỏng lệnh gọi API để trả về bất kỳ giá trị nào bạn muốn hoặc đưa ra một Ngoại lệ. using patch to hijack an API function or object creation call. When patch intercepts a call, it returns a MagicMock object by default. By setting properties on the MagicMock object, you can mock the API call to return any value you want or raise an Exception .

Chế giễu trong Pytest là gì?

Trong pytest , chế nhạo có thể thay thế giá trị trả về của một hàm trong một hàm . Điều này hữu ích để kiểm tra chức năng mong muốn và thay thế giá trị trả về của hàm lồng trong chức năng mong muốn mà chúng tôi đang kiểm tra.

Chủ Đề