Nếu bạn thực sự muốn có nhiều unitttest thì bạn cần nhiều phương pháp. Cách duy nhất để có được điều đó là thông qua một số loại tạo mã. Bạn có thể làm điều đó thông qua một metaclasses, hoặc bằng cách tinh chỉnh lớp sau khi định nghĩa, bao gồm (nếu bạn đang sử dụng Python 2.6) thông qua một trình trang trí lớp.
Đây là giải pháp tìm kiếm các thành viên 'multitest' và 'multitest_values' đặc biệt và sử dụng các thành viên đó để xây dựng các phương pháp thử nghiệm nhanh chóng. Không tao nhã, nhưng nó gần như những gì bạn muốn:
import unittest
import inspect
class SomeValue(object):
def __eq__(self, other):
return other in [1, 3, 4]
class ExampleTestCase(unittest.TestCase):
somevalue = SomeValue()
multitest_values = [1, 2, 3, 4]
def multitest(self, n):
self.assertEqual(self.somevalue, n)
multitest_gt_values = "ABCDEF"
def multitest_gt(self, c):
self.assertTrue(c > "B", c)
def add_test_cases(cls):
values = {}
functions = {}
# Find all the 'multitest*' functions and
# matching list of test values.
for key, value in inspect.getmembers(cls):
if key.startswith("multitest"):
if key.endswith("_values"):
values[key[:-7]] = value
else:
functions[key] = value
# Put them together to make a list of new test functions.
# One test function for each value
for key in functions:
if key in values:
function = functions[key]
for i, value in enumerate(values[key]):
def test_function(self, function=function, value=value):
function(self, value)
name ="test%s_%d" % (key[9:], i+1)
test_function.__name__ = name
setattr(cls, name, test_function)
add_test_cases(ExampleTestCase)
if __name__ == "__main__":
unittest.main()
Đây là sản phẩm từ khi tôi chạy nó
% python stackoverflow.py
.F..FF....
======================================================================
FAIL: test_2 (__main__.ExampleTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "stackoverflow.py", line 34, in test_function
function(self, value)
File "stackoverflow.py", line 13, in multitest
self.assertEqual(self.somevalue, n)
AssertionError: <__main__.SomeValue object at 0xd9870> != 2
======================================================================
FAIL: test_gt_1 (__main__.ExampleTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "stackoverflow.py", line 34, in test_function
function(self, value)
File "stackoverflow.py", line 17, in multitest_gt
self.assertTrue(c > "B", c)
AssertionError: A
======================================================================
FAIL: test_gt_2 (__main__.ExampleTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
File "stackoverflow.py", line 34, in test_function
function(self, value)
File "stackoverflow.py", line 17, in multitest_gt
self.assertTrue(c > "B", c)
AssertionError: B
----------------------------------------------------------------------
Ran 10 tests in 0.001s
FAILED (failures=3)
Bạn có thể thấy ngay một số vấn đề xảy ra với thế hệ mã. "Test_gt_1" xuất phát từ đâu? Tôi có thể đổi tên thành "test_multitest_gt_1" dài hơn nhưng sau đó thử nghiệm nào là 1? Tốt hơn ở đây sẽ bắt đầu từ _0 thay vì _1, và có lẽ trong trường hợp của bạn, bạn biết các giá trị có thể được sử dụng như một tên hàm Python.
Tôi không thích phương pháp này. Tôi đã làm việc trên các cơ sở mã mà các phương pháp thử tự động (trong một trường hợp sử dụng một metaclass) và thấy nó khó hiểu hơn rất nhiều so với các phương thức hữu ích. Khi một bài kiểm tra thất bại, thật khó để tìm ra nguồn gốc của trường hợp lỗi, và thật khó để dính vào mã gỡ lỗi để thăm dò lý do cho sự thất bại.
(Lỗi gỡ lỗi trong ví dụ tôi đã viết ở đây không phải là khó khăn như cách tiếp cận metaclass cụ thể mà tôi đã phải làm việc với.)
Bạn đã tìm thấy một cách để làm điều này? Hoặc có thể bạn đã tìm thấy một công cụ khác cho công việc này? Tôi cũng cần hành vi như vậy. – legesh
http://thebongtraveller.blogspot.sg/2015/12/art-of-unittest-writing-auto-generation.html Đây có phải là điều tương tự không? –