是否可以 运行 来自 python unittest.TestCase 的单个测试方法并引用该方法?
Is it possible to run a single test method from a python unittest.TestCase with a reference to the method?
假设我有以下 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
然后在装饰器中,在运行启用函数之前,基本上检查该函数的测试是否通过。
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()
内省在Python 2.
中会有些不同
假设我有以下 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
然后在装饰器中,在运行启用函数之前,基本上检查该函数的测试是否通过。
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()
内省在Python 2.
中会有些不同