2011-08-24 32 views
13

Tôi có một mô-đun kiểm tra trong tiêu chuẩn unittest định dạngChạy Python unittest để không có gì được in nếu thành công, chỉ AssertionError() nếu không

class my_test(unittest.TestCase): 

    def test_1(self): 
     [tests] 

    def test_2(self): 
     [tests] 
    etc.... 

Công ty của tôi có một khai thác thử nghiệm độc quyền sẽ thực hiện mô-đun của tôi như một kịch bản dòng lệnh và sẽ bắt bất kỳ lỗi nào được mô-đun của tôi nêu lên, nhưng yêu cầu mô-đun của tôi bị tắt tiếng nếu thành công. Vì vậy, tôi đang cố gắng tìm cách để chạy mô-đun thử nghiệm của mình, vì vậy nếu tất cả các bài kiểm tra của tôi vượt qua thì không có gì được in trên màn hình, và nếu một bài kiểm tra thất bại với AssertionError, lỗi đó sẽ được truyền qua tiêu chuẩn Python đống lỗi (giống như bất kỳ lỗi khác sẽ trong một kịch bản Python bình thường.)

các docs ủng hộ bằng cách sử dụng unittest.main() chức năng để chạy tất cả các bài kiểm tra trong một mô-đun được như

if __name__ == "__main__": 
    unittest.main() 

Vấn đề là điều này kết thúc tốt đẹp kết quả kiểm tra trong khai thác unittest, để ngay cả khi tất cả các bài kiểm tra thành công, nó vẫn pr ints một số fluff vào màn hình, và nếu có một lỗi, nó không chỉ đơn giản là bán phá giá như một lỗi python bình thường, mà còn mặc quần áo trong khai thác.

tôi đã cố gắng chuyển hướng đầu ra cho một dòng luân phiên sử dụng

with open('.LOG','a') as logf: 
    suite = unittest.TestLoader().loadTestsFromTestCase(my_test) 
    unittest.TextTestRunner(stream = logf).run(suite) 

Vấn đề ở đây là mọi thứ đều được cấp nước tập trung vào file log (bao gồm tất cả các thông báo lỗi). Vì vậy, khi các công ty của tôi khai thác chạy mô-đun, nó hoàn thành thành công bởi vì, theo như nó có thể nói, không có lỗi đã được nâng lên (bởi vì tất cả chúng đều được dẫn tới tệp nhật ký).

Bất kỳ đề xuất nào về cách tôi có thể xây dựng một Á hậu thử nghiệm để triệt tiêu tất cả các lông tơ, và ống dẫn lỗi thông qua ngăn xếp lỗi Python bình thường? Như mọi khi, nếu bạn nghĩ rằng có cách tốt hơn để tiếp cận vấn đề này, vui lòng cho tôi biết.

EDIT:

Đây là những gì tôi đã sử dụng để giải quyết vấn đề này. Đầu tiên, tôi đã thêm một "get_test_names()" phương pháp để lớp thử nghiệm của tôi:

class my_test(unittest.TestCase): 
    etc.... 
    @staticmethod 
    def get_test_names(): 
     """Return the names of all the test methods for this class.""" 
     test_names = [ member[0] for memeber in inspect.getmembers(my_test) 
         if 'test_' in member[0] ] 

Sau đó, tôi thay thế cuộc gọi của tôi để unittest.main() như sau:

# Unittest catches all errors raised by the test cases, and returns them as 
# formatted strings inside a TestResult object. In order for the test 
# harness to catch these errors they need to be re-raised, and so I am defining 
# this CompareError class to do that. 
# For each code error, a CompareError will be raised, with the original error 
# stack as the argument. For test failures (i.e. assertion errors) an 
# AssertionError is raised. 
class CompareError(Exception): 
    def __init__(self,err): 
     self.err = err 
    def __str__(self): 
     return repr(self.err) 

# Collect all tests into a TestSuite() 
all_tests = ut.TestSuite() 
for test in my_test.get_test_names(): 
    all_tests.addTest(my_test(test)) 
# Define a TestResult object and run tests 
results = ut.TestResult() 
all_tests.run(results) 
# Re-raise any script errors 
for error in results.errors: 
    raise CompareError(error[1]) 
# Re-raise any test failures 
for failure in results.failures: 
    raise AssertionError(failure[1]) 

Trả lời

3

tôi đến với điều này. Nếu bạn có thể thay đổi dòng lệnh, bạn có thể loại bỏ chuyển hướng io bên trong.

import sys, inspect, traceback 

# redirect stdout, 
# can be replaced by testharness.py > /dev/null at console 
class devnull(): 
    def write(self, data): 
     pass 

f = devnull() 
orig_stdout = sys.stdout 
sys.stdout = f 

class TestCase(): 
    def test_1(self): 
     print 'test_1' 

    def test_2(self): 
     raise AssertionError, 'test_2' 

    def test_3(self): 
     print 'test_3' 


if __name__ == "__main__": 
    testcase = TestCase() 
    testnames = [ t[0] for t in inspect.getmembers(TestCase) 
         if t[0].startswith('test_') ] 

    for testname in testnames: 
     try: 
      getattr(testcase, testname)() 
     except AssertionError, e: 
      print >> sys.stderr, traceback.format_exc() 

# restore 
sys.stdout = orig_stdout 
+0

Cảm ơn bạn rất nhiều Gringo Suave. Tôi đã kết thúc xây dựng một Á hậu thử nghiệm bằng cách sử dụng các lớp TestSuite và TestResult, nhưng tôi đã thực hiện cuộc gọi inspect.getmembers() từ mã của bạn. – jeremiahbuddha

+0

@jeremiahbuddha Bạn có thể chấp nhận câu trả lời hoặc viết câu trả lời của riêng bạn và chấp nhận nó không? –

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