2011-08-24 8 views
13

Mam moduł testowy w standardzie unittest formacieRun Python unittest tak, że nic nie jest drukowany w przypadku powodzenia, tylko AssertionError() jeśli nie

class my_test(unittest.TestCase): 

    def test_1(self): 
     [tests] 

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

Moja firma posiada opatentowaną uprząż testowy, który będzie wykonywał moje modułu jako skrypt wiersza poleceń, który będzie wychwytywał błędy zgłaszane przez mój moduł, ale wymaga, aby mój moduł był wyciszony, jeśli się powiedzie.

Próbuję więc znaleźć sposób na uruchomienie mojego modułu testowego nago, więc jeśli wszystkie moje testy przejdą, nic nie zostanie wydrukowane na ekranie, a jeśli test zakończy się niepowodzeniem z AssertionError, błąd zostanie przesłany przez błąd standardowy Python stosu (podobnie jak w każdym innym błędem byłoby w normalnym skryptu Pythona.)

docs zwolennikiem używania funkcji unittest.main(), aby uruchomić wszystkie testy w danym module jak

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

Problem polega na tym, że wyniki testu są zawijane w uprzęż unittest, tak więc nawet jeśli wszystkie testy zakończą się sukcesem, nadal Na ekranie pojawia się odrobina kłaczków, a jeśli wystąpi błąd, nie jest po prostu wyrzucany jako zwykły błąd Pythona, ale również ubrany w uprząż.

Próbowałem przekierowanie wyjścia do alternatywnego strumienia używając

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

Problemem jest to, że wszystko staje się rurami do pliku logu (w tym wszystkie powiadomienia o błędach). Tak więc, kiedy moje firmy wykorzystują moduł, jego ukończenie powiodło się, ponieważ, o ile można to stwierdzić, nie zgłoszono żadnych błędów (ponieważ wszystkie zostały podłączone do pliku dziennika).

Jakieś sugestie, w jaki sposób mogę skonstruować test biegacza, który tłumi cały puch i drąży błędy przez zwykły stos błędów Pythona? Jak zawsze, jeśli uważasz, że istnieje lepszy sposób rozwiązania tego problemu, daj mi znać.

EDIT:

Oto co skończyło się rozwiązać ten problem. Po pierwsze, dodałem "get_test_names()" metodę mojej klasie testu:

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] ] 

Potem wymieniłem moje wezwanie do unittest.main() z następujących czynności:

# 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]) 

Odpowiedz

3

wpadłem na to. Jeśli możesz zmienić wiersz poleceń, możesz usunąć wewnętrzne przekierowanie io.

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

Bardzo spóźnione podziękowania Gringo Suave. Skończyło się na tym, że budowałem testera używając klas TestSuite i TestResult, ale podniosłem wywołanie inspect.getmembers() z twojego kodu. – jeremiahbuddha

+0

@jeremiahbuddha Czy możesz zaakceptować odpowiedź lub napisać własną i zaakceptować ją? –

Powiązane problemy