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的测试运行器中出现泡沫。

相关问题