17

Poszerzam python 2.7 unittest framework do wykonywania niektórych testów funkcji. Jedną z rzeczy, które chciałbym zrobić, to powstrzymanie wszystkich testów przed uruchomieniem wewnątrz testu i wewnątrz metody setUpClass(). Czasami, jeśli test się nie powiedzie, program jest tak zepsuty, że nie jest już dłużej potrzebny do testowania, więc chcę zatrzymać testy.Jak zatrzymać wszystkie testy z poziomu testu lub setUp przy użyciu unittest?

Zauważyłem, że TestResult ma atrybut shouldStop i metodę stop(), ale nie jestem pewien, jak uzyskać dostęp do tego w teście.

Czy ktoś ma jakieś pomysły? Czy istnieje lepszy sposób?

+0

Używam tego, aby przerwać przebieg testu przed uruchomieniem jakichkolwiek testów, jeśli testowana aplikacja jest skonfigurowana z ustawieniami prod. (w rzeczywistości z dowolnymi ustawieniami innymi niż testowe.) –

Odpowiedz

4

Oto kolejna odpowiedź wpadłem po chwili:

pierwsze, dodano nowy wyjątek:

class StopTests(Exception): 
""" 
Raise this exception in a test to stop the test run. 

""" 
    pass 

potem dodał nowy assert aby moje dziecko klasie testu:

def assertStopTestsIfFalse(self, statement, reason=''): 
    try: 
     assert statement    
    except AssertionError: 
     result.addFailure(self, sys.exc_info()) 

i ostatnio przejąłem funkcję run, aby uwzględnić to prawo pod numerem :

except StopTests: 
    result.addFailure(self, sys.exc_info()) 
    result.stop() 

Podoba mi się to lepiej, ponieważ każdy test ma teraz możliwość zatrzymania wszystkich testów i nie ma kodu specyficznego dla cpythona.

+0

Gdzie są podnoszone testy stopów? –

3

Obecnie można zatrzymać testy tylko na poziomie pakietu. Po przejściu do trybu TestCase metoda stop() dla urządzenia TestResult nie jest używana podczas wykonywania testów.

Nieco związane z pytaniem, jeśli używasz Pythona 2.7, możesz użyć flagi -f/--failfast podczas wywoływania testu pod numerem python -m unittest. Spowoduje to zatrzymanie testu przy pierwszej awarii.

Zobacz 25.3.2.1. failfast, catch and buffer command line options

Można również rozważyć użycie Nose uruchomić swoje testy i użyć -x, --stopflag aby zatrzymać test wcześnie.

+0

Dzięki. Widziałem opcję awaryjną, ale nie zawsze chcę nieudane na pierwszym błędzie, tylko w wybranych miejscach. Chyba powinienem edytować moje pytanie, aby wspomnieć, że używam Pythona 2.7. – user197674

0

Spojrzałem na klasę TestCase i zdecydowałem się ją podklasować. Klasa właśnie zastępuje run(). I kopiowane metodę i wychodząc na linii 318 w oryginalnej klasy dodanych w tym:

# this is CPython specific. Jython and IronPython may do this differently 
if testMethod.func_code.co_argcount == 2: 
    testMethod(result) 
else: 
    testMethod() 

Ma trochę CPython specyficzny kod tam sprawdzić, czy metoda badawcza może zaakceptować inny parametr, ale ponieważ używam CPython wszędzie , nie jest to dla mnie problemem.

11

W przypadku zainteresowania, o to prosty przykład, jak można podjąć decyzję pod uwagę wychodzenia zestaw testowy czysto z py.test:

# content of test_module.py 
import pytest 
counter = 0 
def setup_function(func): 
    global counter 
    counter += 1 
    if counter >=3: 
     pytest.exit("decided to stop the test run") 

def test_one(): 
    pass 
def test_two(): 
    pass 
def test_three(): 
    pass 

a jeśli uruchomić to otrzymasz:

$ pytest test_module.py 
============== test session starts ================= 
platform linux2 -- Python 2.6.5 -- pytest-1.4.0a1 
test path 1: test_module.py 

test_module.py .. 

!!!! Exit: decided to stop the test run !!!!!!!!!!!! 
============= 2 passed in 0.08 seconds ============= 

Możesz również umieścić wywołanie py.test.exit() w teście lub w wtyczce specyficznej dla projektu.

Przedruk: py.test natywnie obsługuje py.test --maxfail=NUM w celu wykonania zatrzymania po niepowodzeniach NUM.

Sidenote2: py.test ma tylko ograniczone wsparcie dla uruchamiania testów w tradycyjnym unittest.TestCase stylu.

+0

Dzięki. Nie wiedziałem o tej strukturze testowania. Przyjrzę się temu. – user197674

+2

Aktualna wersja Py.Test: import pytest, a następnie można wykonać pytest.exit ("twoja wiadomość") – RvdK

+1

Działa to również dobrze w zadaniu pytest zadeklarowanym w pliku conftest.py, z scope = 'session', autouse = Prawdziwe. To będzie działać przed każdym testem w projekcie. Wywołanie programu pytest.exit z tego miejsca może przerwać cały test przed wykonaniem jakichkolwiek testów. Używam tego do przerwania testów, jeśli są one uruchomione przy użyciu prod config (w rzeczywistości jakiejkolwiek konfiguracji innej niż testowa) –

1

W pętli testowej unittest.TestSuite, jest to warunek na początku break:

class TestSuite(BaseTestSuite): 

    def run(self, result, debug=False): 
     topLevel = False 
     if getattr(result, '_testRunEntered', False) is False: 
      result._testRunEntered = topLevel = True 

     for test in self: 
      if result.shouldStop: 
       break 

Więc używam niestandardowego zestawu testowego takiego:

class CustomTestSuite(unittest.TestSuite): 
    """ This variant registers the test result object with all ScriptedTests, 
     so that a failed Loign test can abort the test suite by setting result.shouldStop 
     to True 
    """ 
    def run(self, result, debug=False): 
     for test in self._tests: 
      test.result = result 

     return super(CustomTestSuite, self).run(result, debug) 

z wynikiem zwyczaj testowym Klasa podobna do tej:

class CustomTestResult(TextTestResult): 
    def __init__(self, stream, descriptions, verbosity): 
     super(CustomTestResult, self).__init__(stream, descriptions, verbosity) 
     self.verbosity = verbosity 
     self.shouldStop = False 

a moje zajęcia testowe są następujące:

class ScriptedTest(unittest.TestCase): 
    def __init__(self, environment, test_cfg, module, test): 
     super(ScriptedTest, self).__init__() 
     self.result = None 

Pod pewnymi warunkami przerywam pakiet testowy; Na przykład, zestaw testowy rozpoczyna logowania, a jeśli to się nie powiedzie, nie muszę spróbować reszty:

try: 
     test_case.execute_script(test_command_list) 
    except AssertionError as e: 
     if test_case.module == 'session' and test_case.test == 'Login': 
      test_case.result.shouldStop = True 
      raise TestFatal('Login failed, aborting test.') 
     else: 
      raise sys.exc_info() 

Potem korzystania z zestawu testowego w następujący sposób:

suite = CustomTestSuite() 

    self.add_tests(suite) 

    result = unittest.TextTestRunner(verbosity=self.environment.verbosity, stream=UnitTestLoggerStream(self.logger), 
            resultclass=CustomTestResult).run(suite) 

Nie jestem pewien, czy jest lepszy sposób, aby to zrobić, ale zachowuje się poprawnie dla moich testów.

0

Mimo że nie otrzymujesz zwykłych raportów z testów przeprowadzonych do tej pory, bardzo prostym sposobem zatrzymania testu z metody TestCase jest po prostu podniesienie KeyboardInterrupt wewnątrz metody.

Można zobaczyć, jak jest dozwolone tylko KeyboardInterrupt bulgotać wewnątrz unittest „s testowym biegacza patrząc na kod CPython za here wewnątrz testPartExecutor().

Powiązane problemy