代码之家  ›  专栏  ›  技术社区  ›  Nick Chapman

可以从python单元测试运行单个测试方法吗。引用该方法的测试用例?

  •  2
  • Nick Chapman  · 技术社区  · 7 年前

    假设我有以下内容 TestCase

    class TestSomething(unittest.TestCase):
        def test_a(self):
            # Do some testing
    
        def test_b(self):
            # Do some other testing
    

    我可以跑步吗 TestSomething.test_a

    def run_test(test):
        # Somehow runs the test
        # HERE IS THE PART I AM REALLY STUCK ON
    
    run_test(TestSomething.test_a)
    

    我知道,对于正常的单元测试来说,这是一件很尴尬的事情。我试图做的是提供一个测试,作为函数装饰器的参数运行。基本上:

    @corresponding_test(TestSomething.test_a)
    def my_function_a():
        # Something here
    

    然后在decorator中,基本上在运行函数之前检查该函数的测试是否通过。

    1 回复  |  直到 7 年前
        1
  •  2
  •   Walter    7 年前

    OP明确表示,实际用例更为复杂,但这仍然需要说明:

    这是 一种运行单元测试的良好、标准的方法。如果您使用这段代码来运行单元测试,您[可能]做错了。

    """
    The `only_if_test_passes` decorator can be used to run a function if and
    only if the argument test (unbound `TestCase` method) passes.
    """
    
    import inspect
    from unittest import TestCase, TestResult
    
    
    class TestError(Exception):
        pass
    
    
    class MyTests(TestCase):
    
        def test_pass(self):
            # This passes because nothing went wrong
            pass
    
        def test_fail(self):
            self.fail('This test will always fail')
    
    
    def only_if_test_passes(test_method):
        # Comments are computed values when passed MyTests.test_pass
        test_case_class = inspect._findclass(test_method)  # MyTests
        test_case_name = test_case_class.__name__  # 'MyTests'
        test_name = test_method.__name__  # 'test_pass'
        # Introspection for Python 2:
        # test_case_class = test_method.im_class
        # test_case_name = test_case_class.__name__  # Same as for Python 3
        # test_name = test_method.if_func.func_name
    
        def decorator(fn):
            def decorated(*args, **kwargs):
                test_result = TestResult()
                case = test_case_class(test_name)  # MyTests('test_pass')
                case(test_result)
                if test_result.wasSuccessful():
                    return fn(*args, **kwargs)
                else:
                    raise TestError('Unit test failed: {}.{}'.format(
                        test_case_name, test_name))
            return decorated
        return decorator
    
    
    @only_if_test_passes(MyTests.test_pass)
    def this_will_run():
        print('This should output')
    
    
    @only_if_test_passes(MyTests.test_fail)
    def this_wont_ever_run():
        print("Don't bother; you'll never see this.")
    
    
    if __name__ == "__main__":
        this_will_run()
        this_wont_ever_run()
    

    gist

    Python 2中的内省将有所不同。

    另请参见: unittest.TestCase docs