2013-03-27 32 views
6

Tôi đang sử dụng Khung REST của Django cho API mà tôi đang làm việc. Vì một vài lý do, tôi muốn sử dụng chế độ xem dựa trên lớp học. Tuy nhiên, tôi là một chút đặc biệt về thử nghiệm đơn vị của tôi, và tôi không bao giờ cho phép các bài kiểm tra đơn vị của tôi chạm vào cơ sở dữ liệu. Lưu ý: Tôi luôn luôn sử dụng "thủ thuật" được trình bày bởi Carl Meyer tại Pycon 2012, nơi anh ấy đã loại bỏ trình bao bọc Cursor.Chức năng mô phỏng trong chế độ xem dựa trên lớp của Django

cursor_wrapper = Mock() 
cursor_wrapper.side_effect = RuntimeError("No touching the database!") 

@patch('django.db.backends.util.CursorWrapper', cursor_wrapper) 
class TestMyCode(TestCase): 

Đây là link nếu bạn quan tâm đến trang trình bày.

Tôi có một phương pháp ở một trong các chế độ xem kiểm tra thứ gì đó trong cơ sở dữ liệu. Để DRY được chia sẻ giữa POST và PUT. Nhưng, tôi đang gặp vấn đề với việc thử nghiệm đơn vị của mình. Đó là bởi vì classmethod as_view tạo ra một cá thể mới và class dispatch và trả về hàm "handler" để gửi trả về. Vì vậy, tôi dường như không thể có được phương pháp chia sẻ trong chế độ xem dựa trên lớp học của tôi để giả lập nó.

Tôi có thể giả lập các mô hình được sử dụng bởi chế độ xem dựa trên lớp học, nhưng sau đó tôi phải phá vỡ mục tiêu của mình là "KHÔ" và sao chép mã trong cả POST và PUT. Tôi đoán tôi có thể refactor mã và di chuyển logic vào Model. Nhưng, tôi không tích cực tôi muốn làm điều đó.

Làm cách nào bạn có thể thử phương pháp chia sẻ chế độ xem dựa trên lớp học để tránh thực sự chạm vào cơ sở dữ liệu? Chỉ cần tránh chúng?

Trả lời

3

Tôi nghĩ bạn đã trả lời câu hỏi của riêng bạn. Những điều tương tự bạn sử dụng để kiểm tra mọi khung công tác web áp dụng cho Django, chẳng hạn như đảo ngược kiểm soát và tiêm phụ thuộc. Bạn có thể giữ nó khá đơn giản trong Python, do đó, không bị đe dọa hoặc bị tắt bởi những gì tồn tại trong một cái gì đó giống như Spring chẳng hạn.

Tại sao bạn không di chuyển mã ra khỏi chế độ xem dựa trên lớp học? Mã của bạn vẫn không bị DRY nếu bạn vì lý do nào đó cần logic giống nhau ở nơi khác. Chỉ vì đó là Django không có nghĩa là các nguyên tắc lập trình tốt không áp dụng.

Tôi đề nghị chỉ tóm tắt một số điều trong các lớp mới/mô-đun python như dịch vụ (như khái niệm, không phải định nghĩa dịch vụ của Django) và trừu tượng logic khác để truy cập dữ liệu. Sau đó, bạn hoàn toàn độc lập với vòng đời yêu cầu/phản hồi của chế độ xem Django. Có một xu hướng của các nhà phát triển Django và Rails để đặt từng bit logic trực tiếp vào một trong hai mô hình hoặc khung nhìn. Điều này chỉ dẫn đến các lớp thần và những thứ khó kiểm tra.

Bạn có thể tạo thuận lợi cho điều này bằng cách suy nghĩ xem của bạn như là một trừu tượng ánh sáng xử lý những thứ như tham số marshalling (GET/POST), vv cho phần còn lại của mã của bạn và gọi logic cần thiết đóng gói ở nơi khác. IMO, nếu bạn muốn mã có thể thử nghiệm, 99% logic nên ở bên ngoài ngữ cảnh web trừ khi nó hoàn toàn quan trọng đối với quy trình. Điều này làm cho nó cũng dễ dàng hơn để chạy những thứ trong nền và song song.

Điều bạn nên kết thúc là các mô-đun python bình thường và các lớp dễ kiểm tra vì chúng không có phụ thuộc trực tiếp trên HTTP. Nếu bạn cần giả lập HTTP, bạn có thể chỉ cần thử đối tượng yêu cầu. Bạn may mắn rằng sự kết hợp của python/django làm cho nó dễ dàng để đổ ra và thử những thứ này như là các dicts/kwargs đơn giản. Một điều tôi nhận thấy bằng cách sử dụng chế độ xem dựa trên lớp là tốt cho việc sử dụng mixin và thực thi một số quy ước (trả về json, mở thuộc tính biểu đồ, v.v.), nhưng sử dụng chế độ xem dựa trên lớp "nâng cao" trực tiếp yêu cầu mô hình chẳng hạn như DetailView chỉ làm phức tạp những thứ không cần thiết. Các chế độ xem này rất phù hợp với màn hình quản trị, nhưng đối với các ứng dụng thực thì sẽ giúp ích nhiều hơn là bị tổn thương. Họ làm cho mọi thứ khó khăn để kiểm tra và giết người hiệu suất trừ khi bạn tìm thấy một cách tốt đẹp, liền mạch để tích hợp các lớp đệm và như vậy. Tại thời điểm này, nó thường chỉ để kế thừa từ View hoặc TemplateView và được thực hiện với nó.

Liên quan đến DB chế nhạo cụ thể, tạo mocks của bạn và xem xét logic nghiệp vụ của bạn. Sau đó, nó sẽ không quan trọng những gì bạn đang nhập/xuất miễn là nó phù hợp với một bộ quy tắc và giao diện cụ thể. Xem ví dụ như Mixer. Bạn cũng có thể tạo/hủy các DB tạm thời trong quá trình thử nghiệm. Một cách là tạo các mô-đun cài đặt riêng biệt cho dev/dàn dựng/sản xuất/thử nghiệm, v.v. và tải chúng tự động tùy thuộc vào môi trường. Bằng cách đó bạn có thể tránh làm hư hỏng cơ sở dữ liệu làm việc của bạn khi chạy thử nghiệm đơn vị. Tất nhiên điều này là vượt qua nhiều hơn vào một hình thức thử nghiệm tích hợp, nhưng bạn có lẽ nên làm một số trong đó là tốt. Các giải pháp nói trên là phổ biến trong các ORM khác như Hibernate.

Liên quan đến trước đó, bạn có thể làm điều gì đó giống như mã bên dưới trong cài đặt của mình để sử dụng cơ sở dữ liệu trong bộ nhớ để kiểm tra đơn vị. Cuối cùng, mặc dù bạn vẫn cần phải xem xét thử nghiệm tích hợp chống lại kiểu lưu trữ dữ liệu thực tế của bạn, ví dụ MySQL

if 'test' in sys.argv: 
    DATABASES['default']['ENGINE'] = 'sqlite3' 

; TLDR

  1. Đặt quan điểm lớp bên ngoài logic của bạn thành các đối tượng phù hợp và mô-đun.

  2. Đừng tự khóa mình khi cố gắng thực hiện các chế độ xem dựa trên lớp học khác nhau cho các ứng dụng thực và mọi trường hợp sử dụng; cuộn của riêng bạn.

  3. Sử dụng các nguyên tắc TDD nói chung tốt như IOC, chuyển các tham số cần thiết cho các nhà xây dựng, một vài điều, tránh các yêu cầu trạng thái độc quyền quá mức (đặc biệt là HTTP).

    1. Tránh sự phụ thuộc DB bằng cách tạo các đối tượng giả chuẩn (xem # 3) và thực hiện các giao diện giống như dịch vụ (Xem # 1).
Các vấn đề liên quan