17

我正在擴展python 2.7 unittest框架來做一些功能測試。我想要做的一件事就是停止在測試中運行所有測試,並在方法內部停止。有時候如果一個測試失敗了,那麼這個程序就會被破壞,不再用於繼續測試,所以我想停止運行測試。如何使用unittest停止測試或setUp中的所有測試?

我注意到TestResult有一個shouldStop屬性和一個stop()方法,但我不確定如何訪問測試的內部。

有沒有人有任何想法?有沒有更好的辦法?

+0

如果使用prod設置配置了測試下的應用程序,我會在運行任何測試之前使用它來中止測試運行。 (實際上,與任何非測試設置。) – 2017-03-08 20:04:24

回答

4

下面是另一個答案,我想出了一段時間後:

首先,我添加了一個新的異常:

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

""" 
    pass 

然後我添加了一個新的assert我的孩子測試類:

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

and last I overrde run function to include this right below the testMethod() call:

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

我更喜歡這樣,因爲現在任何測試都可以停止所有測試,並且沒有特定於cpython的代碼。

+0

StopTests在哪裏引發? – 2017-03-21 09:17:02

3

目前,您只能在套件級別停止測試。一旦你在TestCase中,在遍歷測試時不會使用TestResultstop()方法。

與您的問題有些相關,如果您使用的是Python 2.7,那麼在調用您的測試python -m unittest時可以使用-f/--failfast標誌。這將在第一次失敗時停止測試。

25.3.2.1. failfast, catch and buffer command line options

您也可以考慮使用Nose運行測試,並使用-x, --stopflag提前停止測試。

+0

謝謝。我看到了failfast選項,但我並不總是想在第一個錯誤上失敗,只是在選定的位置。我想我應該編輯我的問題,提到我使用Python 2.7。 – user197674 2010-09-27 20:17:10

0

我看着TestCase類,並決定將其繼承。該課程僅覆蓋run()。我複製的方法,並在原班開始於行318添加了這個:

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

它有沒有一些具體的CPython代碼告訴如果測試方法可以接受另一個參數,而且因爲我到處使用的CPython ,這對我來說不是問題。

11

如果你有興趣,這裏是一個簡單的例子,你怎麼能自己做決定有關乾淨退出測試套件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 

,如果你運行這個你:

$ 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 ============= 

您還可以將py.test.exit()調用放入測試中或放入項目特定的插件中。

旁註:py.test原生支持py.test --maxfail=NUM實現在NUM失敗後停止。

Sidenote2:py.test對傳統unittest.TestCase風格的運行測試的支持有限。

+0

謝謝。我不知道這個測試框架。我會看看它。 – user197674 2010-10-04 18:42:26

+2

當前版本的Py.Test:導入pytest,然後你可以做pytest.exit(「你的消息」) – RvdK 2014-04-10 08:24:18

+1

這也適用於在conftest.py文件中聲明的pytest夾具,scope ='session',autouse =真正。這將在項目的每個測試之前運行。從這裏調用pytest.exit可以在任何測試運行之前中止整個測試運行。我用它來中止測試,如果他們正在使用prod配置(實際上是任何非測試配置)運行 – 2017-03-08 20:06:59

1

unittest.TestSuite測試迴路中,有在開始一個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 

所以我用一個自定義的測試套件是這樣的:

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) 

使用自定義的測試結果類似這樣:

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

和我的測試類是像:

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

在某些條件下,我中止測試套件;例如,測試套件與登錄開始,如果失敗了,我沒有嘗試休息:

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() 

然後我使用測試套件通過以下方式:

suite = CustomTestSuite() 

    self.add_tests(suite) 

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

我不確定是否有更好的方法來做到這一點,但它對我的測試表現正確。

0

儘管目前爲止您無法獲得目前運行的測試的常規測試報告,但在TestCase方法中停止測試的一種非常簡單的方法就是在該方法內部提升KeyboardInterrupt

通過查看012y中的CPython代碼here,您可以看到KeyboardInterrupt只允許在unittest的測試運行器中出現泡沫。

相關問題