2012-08-08 40 views
9

Hoặc, "Cách thiết kế Sơ đồ Cơ sở dữ liệu của bạn để kiểm tra Đơn vị dễ dàng?"Thử nghiệm Đơn vị với Mô hình Django và rất nhiều quan hệ liên quan đến

Bằng cách này, có một câu hỏi rất tương tự như sau đây: How to test Models in Django with Foreign Keys

Tôi đang cố gắng để làm theo phương pháp TDD cho một dự án có sử dụng khuôn khổ Django. Tôi đang tạo và thử nghiệm các mô hình và chức năng của nó (lưu các phương thức, tín hiệu, ...) và các chức năng mức cao khác dựa trên các mô hình.

Tôi hiểu rằng thử nghiệm đơn vị phải được tách biệt nhất có thể nhưng tôi thấy mình là tạo nhiều bảng và quan hệ bằng FactoryBoy cho mỗi bài kiểm tra, vì vậy bài kiểm tra của tôi không đủ mạnh. bị vỡ.

Làm thế nào để tránh tất cả các phụ thuộc này và làm cho trình kiểm tra sạch hơn?

Bạn nghĩ gì để tránh tất cả các bản mẫu trước khi thử nghiệm thực tế?

Thực tiễn tốt nhất là gì?

+0

@ dm03514 bởi hàm mức cao i có nghĩa là chạy một số tính toán thống kê trên dữ liệu, nhưng đó không phải là vấn đề, vấn đề là rằng bảng chức năng này sử dụng có rất nhiều mối quan hệ của tất cả các loại (một-nhiều, nhiều-nhiều, vv) vì vậy nó là một nỗi đau phải tạo ra các cá thể cho tất cả các mô hình đó để kiểm tra một số hàm – javier

+0

@ dm03514 về câu trả lời bạn đã xóa: Cảm ơn câu trả lời của bạn và liên kết đến pyramid =); Tôi nghĩ rằng có lẽ tôi sẽ thay đổi câu hỏi của mình về cách thiết kế lược đồ cơ sở dữ liệu để kiểm thử đơn vị dễ dàng? loại mô hình nào tồn tại ?; bằng cách này, đồ đạc không phải là một cách tuyệt vời để đối phó với dữ liệu để thử nghiệm vì lý do đó tôi đang sử dụng cậu bé nhà máy như tôi đã đề cập trong câu hỏi, xem ví dụ: [link] http: // lincolnloop.com/blog/2012/may/3/fixtures-and-factories/ – javier

Trả lời

13

Không có danh sách nào của thực tiễn tốt nhất để thử nghiệm, có rất nhiều điều gì phù hợp với bạn và dự án cụ thể mà bạn đang làm việc. Tôi đồng ý với pyriku khi ông nói:

Bạn không nên thiết kế phần mềm của bạn dựa trên cách mà bạn muốn kiểm tra nó

Nhưng, tôi sẽ thêm rằng nếu bạn có một mô-đun tốt và thiết kế phần mềm, cần dễ dàng kiểm tra đúng cách.

Gần đây tôi đã thử nghiệm một số đơn vị trong công việc của mình, và tôi đã tìm thấy một số công cụ thú vị và hữu ích trong Python, FactoryBoy là một trong những công cụ đó thay vì chuẩn bị nhiều đối tượng trong quá trình thiết lập() phương thức của lớp thử nghiệm của bạn, bạn chỉ có thể xác định một nhà máy cho mỗi mô hình và tạo ra chúng với số lượng lớn nếu cần thiết.

Bạn cũng có thể thử nhạo báng, đó là một thư viện để các đối tượng giả và, vì trong Python mọi thứ là một đối tượng, bạn có thể thử chức năng quá, nó rất hữu ích nếu bạn cần một thử nghiệm một chức năng mà tạo ra sự kiện X tại một thời điểm nhất định trong ngày, ví dụ, gửi một tin nhắn lúc 10:00 sáng, bạn viết một mô hình datetime.datetime.now() luôn trả về '10: 00am 'và gọi hàm đó với giả lập.

Nếu bạn cũng cần phải kiểm tra một số front-end hoặc thử nghiệm của bạn cần một số tương tác của con người (như khi làm OAuth chống lại), bạn có những hình thức điền và nộp bằng cách sử dụng Selenium.

Trong trường hợp của bạn, để chuẩn bị đối tượng có quan hệ với FactoryBoy, bạn có thể thử ghi đè lên các phương pháp Factory._prepare(), chúng ta hãy làm điều đó với mô hình này django đơn giản:

class Group(models.Model): 
    name = models.CharField(max_length=128) 
    members = models.ManyToManyField(User, blank=True, null=True) 

    # ... 

Bây giờ, chúng ta hãy định nghĩa một đơn giản UserFactory:

class UserFactory(factory.Factory): 
    FACTORY_FOR = User 

    first_name = 'Foo' 
    last_name = factory.Sequence(lambda n: 'Bar%s' % n) 
    username = factory.LazzyAttribute(lambda obj: '%s.%s' % (obj.first_name, obj.last_name)) 

Bây giờ, chúng ta hãy nói rằng tôi muốn hoặc cần điều đó nhà máy của tôi tạo nhóm với 5 thành viên, GroupFactory sẽ trông như thế này

class GroupFactory(factory.Factory): 
    FACTORY_FOR = Group 

    name = factory.Sequence(lambda n: 'Test Group %s' % n) 

    @classmethod 
    def _prepare(cls, create, **kwargs): 
     group = super(GroupFactory, cls)._prepare(create, **kwargs) 
     for _ in range(5): 
      group.members.add(UserFactory()) 
     return group 

Hy vọng điều này sẽ giúp, hoặc ít nhất là cho bạn một ánh sáng. Ở đây tôi sẽ để lại một số liên kết đến các tài nguyên liên quan với các công cụ tôi đã đề cập:

Factory Boy: https://github.com/rbarrois/factory_boy

nhạo báng: http://niemeyer.net/mocker

Selenium: http://selenium-python.readthedocs.org/en/latest/index.html

Và một chủ đề hữu ích về thử nghiệm:

What are the best practices for testing "different layers" in Django?

+1

được trả lời rất tốt. – Rohit

0

Tôi không thực sự chắc chắn nếu bạn cần phải đi rằng sâu. Bạn không nên thiết kế phần mềm của bạn dựa trên cách bạn muốn thử nghiệm nó, bạn cần phải thích ứng với cách thử nghiệm của bạn với các công cụ bạn đang sử dụng.

Giả sử bạn muốn nhận mức độ chi tiết đó, chẳng hạn như mô hình FK và M2M chế nhạo khi bạn thử nghiệm một số kiểu máy, phải không? Một cái gì đó như

class Invoice(models.Model): 
    client = models.ForeignKey(Client) 

và trong các thử nghiệm của bạn, bạn muốn kiểm tra chỉ Invoice mô hình, mà không đối phó với Client mô hình. Có đúng không? Vì vậy, tại sao bạn không giả lập cơ sở dữ liệu phụ trợ quá, và chỉ cần kiểm tra ONLY những gì mô hình của bạn nên làm gì?

Điểm của tôi là bạn không cần phải đạt đến cấp đó. Thêm một số xét nghiệm vào mô hình của bạn cho những thứ không tầm thường như tín hiệu, phương pháp, kiểm tra xem các sáng tạo mô hình có hoạt động hay không (thậm chí có thể tránh điều này nếu bạn tin tưởng vào cơ sở dữ liệu) và khi bạn cần làm việc với các mô hình bên ngoài. phương pháp setUp() của thử nghiệm.

Ngoài ra nếu bạn muốn, bạn có thể thử bất cứ điều gì bạn muốn bằng thư viện giả của Python: http://www.voidspace.org.uk/python/mock/. Nếu bạn thực sự muốn làm TDD, bạn có thể sử dụng nó để giả lập FK của bạn trong mỗi bài kiểm tra, nhưng nếu bạn thay đổi mô hình đó, bạn sẽ cần phải thay đổi tất cả các mô hình.

+0

Vâng, có lẽ bạn đang đi quá xa; cho thời điểm tôi đang khám phá [cậu bé nhà máy] (https://github.com/dnerdy/factory_boy) và [mô hình mẹ] (https://github.com/vandersonmota/model_mommy) và tôi nghĩ rằng đây chỉ là những gì tôi đang tìm kiếm (cho thời điểm này, nhưng luôn luôn là chỗ để cải thiện) – javier

1

Hãy thử sử dụng Mixer. Nó dễ dàng hơn nhiều so với 'factory_boy' và mạnh hơn nhiều. Bạn không cần phải thiết lập các nhà máy và bạn nhận dữ liệu khi bạn cần chúng:

from mixer.backend.django import mixer 

mixer.blend(MyModel) 
Các vấn đề liên quan