44

我正在使用 py.test 并想知道是否/如何setup在运行每个测试之前调用的方法中检索当前执行的测试的名称。考虑这段代码:

class TestSomething(object):

    def setup(self):
        test_name = ...

    def teardown(self):
        pass

    def test_the_power(self):
        assert "foo" != "bar"

    def test_something_else(self):
        assert True

就在TestSomething.test_the_power执行之前,我希望能够访问该名称,setup如代码中所述,test_name = ...以便test_name== "TestSomething.test_the_power"

实际上,在 中setup,我为每个测试分配了一些资源。最后,查看各种单元测试创​​建的资源,我希望能够看到哪个是由哪个测试创建的。最好的办法是在创建资源时只使用测试名称。

4

9 回答 9

95

您也可以像这样使用请求夹具来执行此操作:

def test_name1(request):
    testname = request.node.name
    assert testname == 'test_name1'
于 2016-01-11T22:25:24.107 回答
41

您还可PYTEST_CURRENT_TEST以为每个测试用例使用 pytest 设置的环境变量。

PYTEST_CURRENT_TEST 环境变量

要获取测试名称:

os.environ.get('PYTEST_CURRENT_TEST').split(':')[-1].split(' ')[0]
于 2018-08-21T19:31:40.930 回答
20

setupteardown方法似乎是支持为其他框架编写的测试的遗留方法,例如鼻子。调用本地pytest方法setup_method以及teardown_method接收当前执行的测试方法作为参数。因此,我想要实现的,可以这样写:

class TestSomething(object):

    def setup_method(self, method):
        print "\n%s:%s" % (type(self).__name__, method.__name__)

    def teardown_method(self, method):
        pass

    def test_the_power(self):
        assert "foo" != "bar"

    def test_something_else(self):
        assert True

然后的输出py.test -s是:

============================= test session starts ==============================
platform linux2 -- Python 2.7.3 -- pytest-2.3.3
plugins: cov
collected 2 items 

test_pytest.py 
TestSomething:test_the_power
.
TestSomething:test_something_else
.

=========================== 2 passed in 0.03 seconds ===========================
于 2013-07-19T10:50:19.240 回答
2

您可以尝试检查模块。

import inspect

def foo():
    print "My name is: ", inspect.stack()[0][3]


foo()

输出:My name is: foo

于 2013-07-18T15:24:01.397 回答
2

简短的回答:

  • 使用名为request
  • 该夹具具有以下有趣的属性:
    • request.node.originalname= 函数/方法的名称
    • request.node.name= 函数/方法的名称和参数的 id
    • request.node.nodeid= 测试文件的相对路径,测试类的名称(如果在一个类中),函数/方法的名称和参数的 id

长答案:

我检查了request.node. 以下是我发现的最有趣的属性:

class TestClass:

    @pytest.mark.parametrize("arg", ["a"])
    def test_stuff(self, request, arg):
        print("originalname:", request.node.originalname)
        print("name:", request.node.name)
        print("nodeid:", request.node.nodeid)

打印以下内容:

 originalname: test_stuff
 name: test_stuff[a]
 nodeid: relative/path/to/test_things.py::TestClass::test_stuff[a]

如果要完全识别测试(包括参数),NodeID 是最有希望的。请注意,如果测试是作为一个函数(而不是在一个类中),那么类名 ( ::TestClass) 就会丢失。

您可以根据需要进行解析nodeid,例如:

components = request.node.nodeid.split("::")
filename = components[0]
test_class = components[1] if len(components) == 3 else None
test_func_with_params = components[-1]
test_func = test_func_with_params.split('[')[0]
test_params = test_func_with_params.split('[')[1][:-1].split('-')

在我的示例中,这导致:

filename = 'relative/path/to/test_things.py'
test_class = 'TestClass'
test_func = 'test_stuff'
test_params = ['a']
于 2021-08-16T13:58:28.313 回答
2

试试我的小包装函数,它返回测试的全名、文件和测试名称。您可以稍后使用任何您喜欢的。我在 conftest.py 中使用了它,据我所知,固定装置不起作用。

def get_current_test():
    full_name = os.environ.get('PYTEST_CURRENT_TEST').split(' ')[0]
    test_file = full_name.split("::")[0].split('/')[-1].split('.py')[0]
    test_name = full_name.split("::")[1]

    return full_name, test_file, test_name
于 2020-04-30T14:06:06.977 回答
2
# content of conftest.py

@pytest.fixture(scope='function', autouse=True)
def test_log(request):
    # Here logging is used, you can use whatever you want to use for logs
    log.info("STARTED Test '{}'".format(request.node.name))  

    def fin():
        log.info("COMPLETED Test '{}' \n".format(request.node.name))

    request.addfinalizer(fin)
于 2021-07-05T08:22:38.313 回答
1

您可能有多个测试,在这种情况下...

test_names = [n for n in dir(self) if n.startswith('test_')]

...将为您提供所有以“test_”开头的函数和实例变量self。只要您没有任何名为“test_something”的变量,这将起作用。

您还可以定义一个方法setup_method(self, method),而不是setup(self)在每次测试方法调用之前调用该方法。使用它,您只需将每个方法作为参数提供。见: http: //pytest.org/latest/xunit_setup.html

于 2013-07-18T15:06:51.303 回答
0

type(self).__name__也许试试?

于 2013-07-18T15:02:25.450 回答