2013-04-12 24 views
5

Tôi đang viết một trình lập lịch biểu công việc nhỏ bằng Python. Bộ lập lịch có thể được cung cấp một loạt các cuộc gọi cộng với các phụ thuộc, và nên chạy các cuộc gọi, đảm bảo rằng không có nhiệm vụ nào được chạy trước bất kỳ người tiền nhiệm nào của nó.Thử nghiệm một hàm có thể trả về kết quả không xác định bằng cách sử dụng Python unittest

Tôi đang cố gắng tuân theo phương pháp thử nghiệm theo hướng thử nghiệm và tôi đã gặp phải sự cố khi kiểm tra việc xử lý phụ thuộc. Mã thử nghiệm của tôi trông giống như sau:

def test_add_dependency(self): 
    """Tasks can be added with dependencies""" 
    # TODO: Unreliable test, may work sometimes because by default, task 
    #  running order is indeterminate. 
    self.done = [] 
    def test(id): 
     self.done.append("Test " + id) 
    s = Schedule() 
    tA = Task("Test A", partial(test, "A")) 
    tB = Task("Test B", partial(test, "B")) 
    s.add_task(tA) 
    s.add_task(tB) 
    s.add_dependency(tA, tB) 
    s.run() 
    self.assertEqual(self.done, ["Test B", "Test A"]) 

Vấn đề là thử nghiệm này (đôi khi) hoạt động ngay cả trước khi tôi thêm mã xử lý phụ thuộc. Điều này là do đặc điểm kỹ thuật không tuyên bố rằng các nhiệm vụ phải được chạy theo một thứ tự cụ thể. Vì vậy, thứ tự đúng là một sự lựa chọn hoàn toàn hợp lệ ngay cả khi thông tin phụ thuộc bị bỏ qua.

Có cách viết bài kiểm tra nào để tránh loại thành công "ngẫu nhiên" này không? Dường như với tôi rằng đây là một loại tình huống khá phổ biến, đặc biệt là khi tham gia thử nghiệm "không viết mã mà không có một thử nghiệm thất bại" phương pháp tiếp cận.

+0

Tôi biết về lịch trình cố ý sử dụng ngẫu nhiên (thường được bật bởi cờ "chế độ thử nghiệm") khi chọn một trong nhiều lựa chọn có thể. Với điều đó, bạn có thể chạy thử nghiệm của bạn một vài lần và kiểm tra xem * tất cả * kết quả là chính xác. Đây không phải là một giải pháp thực sự, tuy nhiên, vì bạn không bao giờ biết bao nhiêu vòng bạn cần. – rainer

+0

Mặc dù các đề xuất để thử nghiệm rất hữu ích, tôi nghĩ rằng vấn đề thực sự của tôi là với ý tưởng "thử nghiệm hướng" mà tôi không nên viết mã trừ khi tôi có kiểm tra không thành công. Trong trường hợp này, đặc điểm kỹ thuật cố tình để lại một mức độ linh hoạt mà làm cho việc viết một bài kiểm tra như vậy là không thể. Đây luôn là nơi tôi gặp khó khăn với cách tiếp cận thử nghiệm, nhưng thông thường chỉ vì tôi quá lười để viết một bài kiểm tra tốt, không phải vì tôi không thể :-) –

Trả lời

1

chiến lược này hoạt động nhiều thời gian:

Thứ nhất, loại bỏ bất kỳ nguồn bên ngoài của entropy (thiết lập hồ bơi thread của bạn để sử dụng một chủ đề duy nhất; nhạo báng bất kỳ RNGs với PRNGs trước hạt giống, vv) Sau đó, tập thể dục của bạn kiểm tra liên tục để sản xuất tất cả các sản phẩm kết hợp, chỉ thay đổi các yếu tố đầu vào máy móc được kiểm tra:

from itertools import permutations 
def test_add_dependency(self): 
    """Tasks can be added with dependencies""" 
    for p in permutations("AB"): 
     self.done = [] 
     def test(id): 
      self.done.append("Test " + id) 
     s = Schedule(threads=1) 
     tasks = {id: Task("Test " + id, partial(test, id)) for id in "AB"} 
     s.add_task(tasks['A']) 
     s.add_task(tasks['B']) 
     s.add_dependency(tasks[p[0]], tasks[p[1]]) 
     s.run() 
     self.assertEqual(self.done, ["Test " + p[1], "Test " + p[0]]) 

thử nghiệm này sẽ thất bại nếu Schedule thất bại trong việc sử dụng thông tin từ add_dependency, vì đó là nguồn duy nhất của entropy (tức thông tin) khác nhau giữa các lần chạy thử nghiệm.

+0

Điểm tốt. Mối quan tâm của tôi ở đây là phương pháp phát triển theo hướng thử nghiệm, nơi tôi phải "tìm lỗi" (thông tin phụ thuộc bị bỏ qua) trước khi tôi có thể viết mã. Nhưng tôi quên mất thực tế rằng đây là những bài kiểm tra đơn vị, không phải kiểm tra hộp đen. Vì vậy, tôi có thể giả lập các bên trong của bộ lập lịch để tập trung hoàn toàn vào việc xử lý phụ thuộc. Cảm ơn! –

1

Một tùy chọn sẽ là sử dụng một phiên bản khác, xác định, của lớp Schedule (hoặc thêm tùy chọn để xác định phiên bản hiện tại) cho mục đích thử nghiệm, nhưng có thể đánh bại mục đích của thử nghiệm đơn vị.

Một tùy chọn khác sẽ không làm phiền khi viết các trường hợp kiểm tra đối với các kết quả không xác định.


Nói chung, tuy nhiên, câu trả lời cho câu hỏi của bạn ...

Có một cách để kiểm tra bằng văn bản để tránh loại này thành công "tình cờ"?

... có lẽ là "không", điều khác đặc biệt thận trọng khi viết chúng. Mặc dù nếu bạn có đủ khả năng thận trọng để tránh viết các trường hợp kiểm tra có vấn đề, và bạn đã áp dụng cảnh giác đó để viết mã ngay từ đầu, thì có thể bạn thậm chí không cần kiểm tra đơn vị. ;-)

Nếu điểm kiểm tra đơn vị là phát hiện lỗi trong mã, thì làm thế nào để bạn phát hiện lỗi trong các bài kiểm tra đơn vị?

Bạn có thể viết các bài kiểm tra đơn vị 'meta' cho các bài kiểm tra đơn vị của mình, nhưng sau đó làm cách nào để phát hiện lỗi trong các bài kiểm tra đơn vị 'meta'? Và cứ như vậy ...

Bây giờ, điều đó không có nghĩa là các xét nghiệm đơn vị không thể hữu ích, nhưng chúng không đủ, trong sự cô lập, để 'chứng minh' rằng mã là 'chính xác'. Trong thực tế, tôi thấy các đánh giá mã dựa trên peer là một phương tiện hiệu quả hơn trong việc phát hiện các lỗi trong mã.

+0

Thêm tùy chọn vào trình lên lịch để buộc một đơn đặt hàng chắc chắn sẽ là một lựa chọn. Tôi không nghĩ về điều đó - cảm ơn. –

2

Bạn đang ở trong tình huống của mỗi nhà nghiên cứu xem xét một bộ sưu tập dữ liệu không hoàn hảo và cố gắng nói liệu giả thuyết đó có đúng hay không.

Nếu kết quả thay đổi giữa các lần chạy, sau đó chạy lại nhiều lần sẽ cung cấp cho bạn mẫu mà bạn có thể áp dụng số liệu thống kê để quyết định xem nó có đang hoạt động hay không. Tuy nhiên, nếu một đợt chạy sẽ cho bạn kết quả tương tự, nhưng một lô khác nhau vào một ngày khác sẽ cho bạn một kết quả khác, thì tính không xác định của bạn phụ thuộc vào các sự kiện bên ngoài chương trình và bạn sẽ cần phải tìm cách để kiểm soát chúng, lý tưởng để chúng tối đa hóa cơ hội vấp phải thuật toán xấu.

Đây là chi phí không xác định; bạn phải nghỉ mát để thống kê và bạn phải có được số liệu thống kê đúng. Bạn cần có khả năng chấp nhận giả thuyết với mức độ tin cậy nào đó, và cũng bác bỏ giả thuyết không. Điều này đòi hỏi ít mẫu hơn nếu bạn có thể tối đa hóa phương sai của kết quả; có tải CPU khác nhau hoặc IO bị gián đoạn hoặc lên lịch một tác vụ với chế độ ngủ ngẫu nhiên.

Tìm hiểu xem lịch biểu nào bị ảnh hưởng bởi có thể được khuyến khích cho mục đích xác định một thử nghiệm đáng giá.

1

Tôi khuyên bạn nên xác định những gì cần phải được kiểm tra trước khi viết bài kiểm tra.

Trong mẫu mã ở trên, những gì đang được thử nghiệm là một chuỗi nhiệm vụ cụ thể được tạo bởi trình lên lịch, mặc dù chuỗi thực tế không xác định theo mô tả của bạn về bộ lập lịch, vì vậy thử nghiệm không thực sự cung cấp bất kỳ sự bảo đảm nào về mã này: đôi khi nó sẽ vượt qua, đôi khi nó sẽ không, và khi nó xảy ra, nó sẽ chỉ là ngẫu nhiên.

Mặt khác, một xét nghiệm có giá trị hơn có thể là để khẳng định sự hiện diện (hay không) của nhiệm vụ trong các kết quả mà không khẳng định bất cứ điều gì về vị trí của họ: "là trong tập" vs "là ở vị trí mảng"

Các vấn đề liên quan