问题
I am currently writing some functional tests using nose. The library I am testing manipulates a directory structure.
To get reproducible results, I store a template of a test directory structure and create a copy of that before executing a test (I do that inside the tests setup
function). This makes sure that I always have a well defined state at the beginning of the test.
Now I have two further requirements:
- If a test fails, I would like the directory structure it operated on to not be overwritten or deleted, so that I can analyze the problem.
- I would like to be able to run multiple tests in parallel.
Both these requirements could be solved by creating a new copy with a different name for each test that is executed. For this reason, I would like to get access to the name of the test that is currently executed in the setup
function, so that I can name the copy appropriately. Is there any way to achieve this?
An illustrative code example:
def setup_func(test_name):
print "Setup of " + test_name
def teardown_func(test_name):
print "Teardown of " + test_name
@with_setup(setup_func, teardown_func)
def test_one():
pass
@with_setup(setup_func, teardown_func)
def test_two():
pass
Expected output:
Setup of test_one
Teardown of test_one
Setup of test_two
Teardown of test_two
Injecting the name as a parameter would be the nicest solution, but I am open to other suggestions as well.
回答1:
Sounds like self._testMethodName
or self.id() should work for you. These are property and method on unittest.TestCase
class. E.g.:
from django.test import TestCase
class MyTestCase(TestCase):
def setUp(self):
print self._testMethodName
print self.id()
def test_one(self):
self.assertIsNone(1)
def test_two(self):
self.assertIsNone(2)
prints:
...
AssertionError: 1 is not None
-------------------- >> begin captured stdout << ---------------------
test_one
path.MyTestCase.test_one
--------------------- >> end captured stdout << ----------------------
...
AssertionError: 2 is not None
-------------------- >> begin captured stdout << ---------------------
test_two
path.MyTestCase.test_two
--------------------- >> end captured stdout << ----------------------
Also see:
- A way to output pyunit test name in setup()
- How to get currently running testcase name from testsuite in unittest
Hope that helps.
回答2:
I have a solution that works for test functions, using a custom decorator:
def with_named_setup(setup=None, teardown=None):
def wrap(f):
return with_setup(
lambda: setup(f.__name__) if (setup is not None) else None,
lambda: teardown(f.__name__) if (teardown is not None) else None)(f)
return wrap
@with_named_setup(setup_func, teardown_func)
def test_one():
pass
@with_named_setup(setup_func, teardown_func)
def test_two():
pass
This reuses the existing with_setup
decorator, but binds the name of the decorated function to the setup
and teardown
functions passed as parameters.
回答3:
In the case you neither want to subclass unittest.TestCase
or use a custom decorator (as explained in the other answers) you can get the information by digging through the call stack:
import inspect
def get_current_case():
'''
Get information about the currently running test case.
Returns the fully qualified name of the current test function
when called from within a test method, test function, setup or
teardown.
Raises ``RuntimeError`` if the current test case could not be
determined.
Tested on Python 2.7 and 3.3 - 3.6 with nose 1.3.7.
'''
for frame_info in inspect.stack():
if frame_info[1].endswith('unittest/case.py'):
return frame_info[0].f_locals['self'].id()
raise RuntimeError('Could not determine test case')
来源:https://stackoverflow.com/questions/16710061/get-name-of-current-test-in-setup-using-nose