2012-09-19 41 views
20

我想我的Python单元测试模块告诉测试运行器在某些情况下(如无法导入模块或找到关键资源)跳过其全部内容。如何在运行时跳过整个Python unittest模块?

我可以使用@unittest.skipIf(...)跳过unittest.TestCase类,但是如何跳过整个模块?对每个类应用跳过是不够的,因为如果模块导入失败,类定义本身可能会导致异常。

+2

仅供参考,在http://colinnewell.wordpress.com/2012/08/31/skippng-python-unit-tests-if-a-dependency-is-missing/上有一篇关于此确切内容的博客文章 –

+1

@Mu心灵,这个作品,除了我告诉'鼻子“,”失败快“。调用'unittest.SkipTest()'似乎算作失败并暂停执行。 –

回答

6

看其他answe后在这里,这是我想到的最好的答案。这很丑陋,将整个测试套件嵌入到异常处理中,但它似乎按照你的意愿去做。特别是在进口不起作用时跳过测试。

假设你正在讨论使用nosetests -x来运行测试,它应该继续跳过测试,至少它在我尝试时会出现。

import unittest 
try: 
    import PyQt4 
    # the rest of the imports 


    # actual tests go here. 
    class TestDataEntryMixin(unittest.TestCase): 
     def test_somefeature(self): 
      # .... 

except ImportError, e: 
    if e.message.find('PyQt4') >= 0: 
     class TestMissingDependency(unittest.TestCase): 

      @unittest.skip('Missing dependency - ' + e.message) 
      def test_fail(): 
       pass 
    else: 
     raise 

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

如果导入失败,它将用单个跳过的单个测试代替测试运行。我也试图确保它不会无意中吞噬任何异常。这个解决方案对这个问题的所有其他答案和评论都有很大的帮助。

如果您在详细模式下运行它,你会看到这个的时候它会跳过,

test_fail (test_openihm_gui_interface_mixins.TestMissingDependency) ... skipped 'Missing dependency - No module named PyQt4' 
+0

我认为这是最好的答案,但你是对的,这很丑。 :-) –

+0

获取'DeprecationWarning:BaseException.message从Python 2.6'已被弃用?你需要这样做:http://stackoverflow.com/questions/1272138/baseexception-message-deprecated-in-python-2-6 – crazysim

2

这可能是把所有的unittest.TestCase子类定义的try...except块,但它的工作:

如果 eggs导入失败和所有那些
import unittest 
try: 
    import eggs 
    class Spam(unittest.TestCase): 
     pass 
    class Ham(unittest.TestCase): 
     pass 
    # ... 
except ImportError: 
    # print 'could not import eggs' 
    pass 

无子类将被定义类()被跳过。不会反映在输出中(取决于你想要的是好还是坏)。

+0

对于一个人为的问题,一个肮脏的解决方案并不是那么糟糕;) –

+1

@Mu Mind,真的是人为的吗?我的用例是在多个平台上运行测试套件(其中有些可能无法'导入蛋')。 –

+0

我主要是给你一个难过的时光。我认为关于类定义失败的一点听起来有点奇怪,但禁用“这个模块”确实比禁用“本模块中的所有类”更清洁。 –

12

如果您看一下unittest.skipIfunittest.skip的定义,您可以看到执行测试时密钥正在执行raise unittest.SkipTest(reason)。如果您能够接受有它显示为一个中的TestRunner跳过测试而不是几个,你可以简单地提高自己的unittest.SkipTest进口:

import unittest 
try: 
    # do thing 
except SomeException: 
    raise unittest.SkipTest("Such-and-such failed. Skipping all tests in foo.py") 

nosetests -v运行提供了:

Failure: SkipTest (Such-and-such failed. Skipping all tests in foo.py) ... SKIP: 
Such-and-such failed. Skipping all tests in foo.py 

---------------------------------------------------------------------- 
Ran 1 test in 0.002s 

OK (SKIP=1) 
+0

我不知道这是否会在*模块*范围工作; 'loader.py'似乎表明如果抛出任何*异常,模块就会失败。 – nneonneo

+0

我试过用nosetests运行测试,它工作正常。编辑我的答案以添加实际输出... –

+2

'nosetests'!='unittest',尽管它们使用相同的库。很确定它确实无法通过简单的'unittest'。 – nneonneo

2

试试你的模块中定义自定义load_tests功能:

import unittest 
try: 
    (testcases) 
except ImportError as e: 
    def load_tests(*args, **kwargs): 
     print("Failed to load tests: skipping") 
     return unittest.TestSuite() # no tests 
+1

我喜欢这种方法。如果它使用SkipTest机制而不仅仅是一个'print',它可能会更好,因为输出可能会在一堆其他测试输出/结果中被淹没。 –

+0

这是可能的。只要'TestSuite'包含一个虚拟测试用例,说明它被跳过了。 ('unittest'模块的'loader'做类似的事情,如果导入失败就会产生保证失败的测试用例)。 – nneonneo

6

我发现,在安装使用skipTest运作良好。如果您需要导入模块,则使用try块来设置module_failed = True,并在setUp中调用skipTest(如果已设置)。该报告检验跳过正确数量只需要很短的try块:

import unittest 

try: 
    import my_module 
    module_failed = False 
except ImportError: 
    module_failed = True 

class MyTests(unittest.TestCase): 
    def setUp(self): 
     if module_failed: 
      self.skipTest('module not tested') 

    def test_something(self): 
      #... 
3

solution提出的OTU的作品,比在我看来,接受的解决方案更容易。但至少有一个缺点。如果你在一个装饰查询my_module跳过一个单一的测试,如

@unittest.skipIf(my_module.support_foo, 'foo not supported') 
def test_foo(self): 
... 

你会得到一个NameError: name 'my_module' is not defined。将溶液放跳过内部函数定义:

def test_foo(self): 
    if not my_module.support_foo: 
     self.skipTest('foo not supported') 
0

结合所提到的答案,并使用this answer

import unittest 
def module_exists(module_name): 
    try: 
     __import__(module_name) 
    except ImportError: 
     return False 
    else: 
     return True 

class TestClass(unittest.TestCase): 

    @unittest.skipUnless(module_exists("moduleA"), 'ModuleA not installed') 
    def test_something(self): 
     # test something with moduleA 
1

用于Python 2.7+(或使用unittest2反向移植):

... 

import unittest 

def setUpModule(): 
    try: 
     import something 
    except ImportError as err: 
     raise unittest.SkipTest(str(err)) 

class Tests(unittest.TestCase): 
    @classmethod 
    def setUpClass(cls): 
     try: 
      import something 
     except ImportError as err: 
      raise unittest.SkipTest(str(err)) 
... 
相关问题