Chào mừng các pythonistas
Trong phiên trước, chúng ta đã nói về thử nghiệm trong python. Chúng tôi đã đi qua chủ đề chế giễu tương đối nhanh nên tôi muốn bày tỏ ở đây một số phương pháp và ý tưởng mà chúng tôi đã để lại. Những ý tưởng này sẽ được
- Khỉ vá
- Chế nhạo và vá lỗi trong pytest
Các ví dụ ở đây ít nhiều có thể tự giải thích nhưng bạn có thể tìm thấy tất cả các ví dụ trong nhánh `blog1` của kho lưu trữ dành riêng cho thử nghiệm bằng Python. Tôi khuyến khích bạn kiểm tra các ví dụ và mở một cuộc thảo luận về các chủ đề, nghi ngờ hoặc khía cạnh có thể phù hợp với bạn
vật cố vá khỉ
Như bạn có thể biết bản vá khỉ là hành động sửa đổi một lớp hoặc mô-đun trong thời gian chạy. Một ví dụ về việc sử dụng chung khỉ vá có thể là
Bạn có thể nhận thấy rằng chúng tôi đã vá tất cả chức năng dựng sẵn [không nên làm điều này, chỉ vì lý do minh họa]. Hành vi này có thể hữu ích nhiều lần nhưng người ta nên thực sự thận trọng với nó vì nó sẽ để lại các định nghĩa trong môi trường đang chạy mà chính mã viết không rõ ràng
Hãy tưởng tượng một vòng lặp vô hạn trong một máy chủ nơi chúng tôi đã vá một chức năng quan trọng và chúng tôi luôn trả về cùng một chức năng. Nhưng đó chính xác là hành vi mà chúng tôi có thể muốn khi thử nghiệm bằng gói mà chúng tôi không có quyền kiểm soát hoặc chúng tôi không có cơ sở hạ tầng để truy cập
Pytest biết tình huống này và cung cấp một công cụ cố định dựng sẵn để hoạt động với bản vá khỉ trong quá trình thử nghiệm của bạn. Chức năng này đảm nhiệm việc vá lỗi và khi quá trình kiểm tra kết thúc, nó sẽ đưa mô-đun vá lỗi về trạng thái ban đầu, để được sử dụng lại [nếu cần] mà không có bất kỳ thay đổi hoặc vá lỗi nào. Hãy xem một ví dụ về vật cố định này
Hãy tưởng tượng chúng ta có một lớp mô hình hóa đơn trong công ty của chúng ta. Thực thể này phải có ID và các loại dữ liệu khác. Nhưng đối với loại thử nghiệm của chúng tôi, chúng tôi cần đảm bảo và làm việc với cùng một ID vì mục đích đơn giản. Trong khi đối với các đợt kiểm tra khác, chúng tôi không có nhu cầu đó. Trong trường hợp này nhìn vào đoạn mã dưới đây
Người ta có thể quan sát ở đây rằng trong phạm vi thử nghiệm đang sử dụng `monkeypatch`, chúng tôi đang thay thế hàm `uuid4` bằng định nghĩa của riêng chúng tôi, hàm này luôn trả về cùng một uuid. Điều tốt là chúng ta không cần phải phá bỏ [hoàn tác] bản vá này ở cuối vì bộ cố định sẽ xử lý nó
Một cách sử dụng khác của `monkeypatch` có thể là để thay thế một biến môi trường. Như thể hiện trong ví dụ bên dưới, việc sử dụng một biến môi trường để biết môi trường nào đang chạy mã của chúng ta có thể tương đối phổ biến. Dựa trên biến đó, một số tính năng có thể hoạt động, vì vậy nếu khi bắt đầu thử nghiệm, chúng tôi đặt nó ở môi trường `test`. [Hãy nhớ đặt môi trường `ENV` của bạn thành `pro` trong môi trường cục bộ hoặc tại ` của bạn. tập tin env`. ]
Chế giễu và vá lỗi
Như đã đề cập trong phiên trước khi chúng tôi cần một bản sao đôi cung cấp hành vi bổ sung [như số lần nó được gọi hoặc liệu nó có được gọi thành công hay không], người ta nên xem thư viện `Mocking`
MagicMock
Phép thuật đằng sau `mocking` là `MagicMock` [bazinga. ]. Thật vậy, cơ sở của thư viện là lớp `Mock` nhưng lớp con ma thuật đã triển khai hỗ trợ [dung lượng mô phỏng] cho tất cả các phương thức te *magic* hoặc *dunder* [vâng, những phương thức có dấu gạch dưới kép làm tiền tố và hậu tố]. Nói đúng ra, người ta có thể sử dụng các lớp này mà không cần ở trong môi trường thử nghiệm [khung]. Hãy kiểm tra trong một môi trường không thử nghiệm như vậy, khả năng chế nhạo
Bạn có thể nhận thấy rằng
- Một phiên bản của `MagicMock` có thể được sử dụng sao cho nó sẽ chấp nhận bất kỳ phương thức nào mà không tạo ra bất kỳ lỗi nào và không làm gì cả, ngoại trừ việc đếm thời gian và cách nó được gọi. Vì vậy, nói đúng ra, nó là một giả
- Người ta có thể xác định các xác nhận khác nhau trên mô hình này
Chúng ta có thể tăng hành vi của thư viện mô phỏng từ mô phỏng đơn giản thành sơ khai bằng cách sửa đổi ví dụ trên
Vì vậy, chúng ta có thể thấy tiện ích của việc có công cụ này để thử nghiệm, nhưng có hai vấn đề với `MagicMock`
- Thông thường, chúng tôi muốn chế nhạo [thay thế hành vi] của các lớp hiện diện trong một mô-đun con, thậm chí có thể nằm sâu trong kiến trúc của chúng tôi
- Khi một phương thức được thay thế hoặc một tác dụng phụ được đặt ra, nếu chúng ta muốn quay lại hành vi ban đầu trong một ngữ cảnh khác thì sao?
Vá
Vì vậy, tính năng chính cuối cùng của thư viện này là chức năng `patch` cung cấp giải pháp cho các vấn đề trước đó. Nó được sử dụng như một công cụ trang trí hoặc quản lý bối cảnh và để xem nó hoạt động, chúng ta sẽ cần một ví dụ phức tạp hơn
Hãy tưởng tượng chúng ta có một giàn giáo như
Hãy tưởng tượng rằng trong patch_example. py, chúng tôi muốn thử lớp Hóa đơn như chúng tôi đã làm trước đây. Bây giờ tình huống phức tạp hơn vì chúng ta không định nghĩa lớp trực tiếp trong cùng một tệp với mã đang chế nhạo
Trong những tình huống này, bản vá sẽ thực sự tiện dụng. Mã để có một cái gì đó tương tự bằng cách sử dụng bản vá sẽ như thế nào
Điều đầu tiên cần chú ý là cách sử dụng tham số đầu tiên [và bắt buộc] của bản vá [mục tiêu]. Đây phải là đường dẫn đến vị trí trong mã nơi chúng tôi muốn thay thế mô hình hoặc như Lisa Roach đã đề cập trong một cuộc nói chuyện thú vị Bản vá nơi đối tượng được sử dụng. Nó không phải là nơi đối tượng được chế nhạo được xác định trong mã của chúng tôi. đây là chìa khóa, vì vậy hãy dành thời gian của bạn để hiểu cách làm việc này. Trong ví dụ của chúng tôi, Hóa đơn được xác định tại miền nhưng chúng tôi muốn thay thế `Hóa đơn` bằng mô hình trong ngữ cảnh/phạm vi của ứng dụng. py trong ứng dụng
Vì vậy, nó là đường dẫn đến ứng dụng. ứng dụng những gì chúng ta phải sử dụng để mô phỏng ở đó
Như bạn cũng có thể nhận thấy bản vá chỉ được áp dụng trong ngữ cảnh và chúng tôi không phải xử lý quy trình gỡ bản vá. Đây là những tính năng thực sự tiện lợi của thư viện. Khi ở bên ngoài trình quản lý bối cảnh của chúng tôi, chức năng tương tự sẽ chạy mà không cần sử dụng đối tượng giả định
Tình huống mà chúng tôi có một tổ chức phức tạp trong không gian tên được mong đợi khi chúng tôi phải kiểm tra. Ít nhất chúng tôi sẽ luôn chia mã đang được kiểm tra và mã của các bài kiểm tra thành hai tệp khác nhau, nhưng chẳng hạn, tôi có sở thích đặt chúng vào các thư mục riêng biệt và giàn giáo và khoảng cách tên trong src thường sẽ phức tạp. Ngoài ra, có khả năng là mỗi trường hợp thử nghiệm sẽ cần một bản vá cụ thể. Vì vậy, thật thuận tiện khi thư viện xử lý việc gỡ lỗi khi ra khỏi phạm vi
Vì vậy, thay vì sử dụng thư viện mô phỏng như chúng ta đã và đang làm [bên ngoài bất kỳ khuôn khổ thử nghiệm nào], hãy sử dụng nó trong môi trường tự nhiên hơn. trong pytest
Trong trường hợp này, chúng tôi đã sử dụng bản vá làm công cụ trang trí thay vì trình quản lý ngữ cảnh. Lý do là chúng tôi chỉ chế nhạo một lần và chúng tôi không có nhu cầu gỡ bản vá trong ngữ cảnh của chức năng kiểm tra. Thông thường đây là tình huống phổ biến và đó là lý do tại sao phiên bản trang trí phổ biến hơn
Hãy tưởng tượng một tình huống phức tạp hơn trong đó chúng ta có một kho lưu trữ do tốc độ của dự án vẫn chưa được triển khai nhưng chúng ta biết rằng sẽ có một phương thức `write_invoice` sẽ được sử dụng mỗi khi chúng ta cập nhật hóa đơn tồn đọng. Vì vậy kho lưu trữ. tệp py có thể trông giống như
Vì vậy, chúng tôi muốn lưu trữ các thực thể của mình và chúng tôi vẫn muốn chạy thử nghiệm mà chúng tôi đã nghiên cứu trước đó. Để làm được điều này, chúng tôi cần thêm một bản vá mới và có ý nghĩa hơn [mô phỏng] sẽ mô phỏng sự tồn tại của kho lưu trữ này
Khi chúng tôi nói nhiều ý nghĩa hơn, điều chúng tôi muốn nói là kho lưu trữ và các cổng khác vào miền của chúng tôi thường là loại đối tượng sẽ sử dụng cơ sở hạ tầng hoặc tính toán đắt tiền sẽ không được chấp nhận trong các thử nghiệm đơn nhất. Để thích ứng với tình huống này, chúng ta cần sửa đổi một chút các bài kiểm tra trước đó bằng cách thực hiện
Chúng tôi đang sử dụng hai bản vá nhưng lưu ý rằng thứ tự của các tham số mà chúng nhận trong chức năng kiểm tra là nghịch đảo của thứ tự của các bộ trang trí. Chúng tôi mong đợi chỉ có một cuộc gọi đến kho lưu trữ và cùng một lượng cuộc gọi đến phương thức ghi. Điều quan trọng cần nhấn mạnh là bằng cách này, chúng tôi có thể kiểm tra chức năng của miền/ứng dụng của chúng tôi một cách độc lập với việc triển khai kho lưu trữ cụ thể [khi đó sự bền bỉ có thể nằm trong cơ sở dữ liệu, trong ổ đĩa, trong bộ nhớ, v.v. ]. Bằng cách trừu tượng hóa theo cách này, chúng tôi có thể tự do hơn để tập trung vào các phụ thuộc của chính mình
kết luận
Chúng tôi đã thấy rằng trong khi thử nghiệm, có những tình huống mà chúng tôi không đủ khả năng để làm việc với việc triển khai mã hiện tại. Điều này chủ yếu là do chi phí thích ứng mã với môi trường thử nghiệm sẽ khiến mã đó thực sự khó bảo trì và khó đọc. Vì vậy, khỉ vá và chế nhạo cung cấp khả năng thay thế các phần tử trong mã của chúng tôi bằng các phần tử sẽ không có bất kỳ sự phụ thuộc nào và do đó sẽ không phàn nàn
Chúng tôi đã thấy rằng bằng cách sử dụng các công cụ này, chúng tôi cũng có thể mở rộng hoặc thay thế một số hành vi, để bao gồm tất cả các trường hợp góc có thể xảy ra mà chúng tôi có thể nghĩ đến
Mặc dù các gói này được sử dụng chủ yếu trong quá trình thử nghiệm, nhưng việc kiểm tra chúng chỉ chạy trong một tập lệnh thông thường là một bài tập tốt để tránh mọi sự phân tâm khỏi khung thử nghiệm. Đây là những gì chúng tôi đã làm;
Trong bài viết tiếp theo, chúng tôi sẽ xử lý nhiều chủ đề hơn liên quan đến thử nghiệm. Cho đến lúc đó, hãy nhớ dũng cảm và táo bạo. và nhớ