pytest用户和调用

通过python -m pytest调用pytest

您可以从命令行通过Python解释器调用测试:

python -m pytest [...]

等同于
pytest [...]

指定测试/选择测试

运行一个模块
pytest test_mod.py
运行一个目录 pytest testing
/

运行包含关键字的表达式 pytest -k "MyClass and not method"

运行特定模块测试:

pytest test_mod.py::test_func

示例如下:

 

运行指定测试方法:

pytest test_mod.py::TestClass::test_method

 

 通过标记表达式运行测试

pytest -m slow

 

运行一个包下的tests

pytest --pyargs pkg.testing

导入pkg.testing,使用其文件系统位置来查找和执行用例。执行pypkg目录下的所有用例

 

异常调试traceback

pytest --showlocals#在tracebacks中显示局部变量
pytest -l #show局部变量(快捷方式)
pytest --tb = auto#(默认)
pytest --tb = long#详细
pytest --tb = short#较短的追溯格式
pytest --tb = line#每次失败只有一行
pytest --tb = native#Python标准库格式
pytest --tb = no #no traceback

 

失败时调用PDB (Python Debugger)

Python带有一个内置的Python调试器称为PDB。pytest可以在命令行选项指定调用:

py.test --pdb

这将在每次失败时调用Python调试器(或KeyboardInterrupt)。 通常你可能只想这样做,对于第一次失败的测试,了解某种失败情况:

pytest -x --pdb#在第一次失败时掉到PDB,然后结束测试会话
pytest --pdb --maxfail = 3#在前三次失败时降至PDB

 

在测试开始时进入到PDB(Python调试器)

pytest允许用户通过命令行选项,在每次测试开始时立即进入PDB提示符:

pytest --trace

这将在每次测试开始时调用Python调试器。

 

设置断点

在用例脚本中加入如下python代码,pytest会自动关闭执行输出的抓取:

•其他测试中的输出捕获不受影响。
•任何先前已经捕获的测试输出,将按此处理。
•不会捕获在同一测试中生成的任何后续输出,而是直接发送到sys.stdout的。 请注意,即使对于退出交互式PDB后发生的测试输出,这也适用
跟踪会话并继续进行常规测试运行。

import pdb
pdb.set_trace()

使用内置断点功能

Python 3.7引入了内置breakpoint()函数。 Pytest支持使用breakpoint()
以下行为:
•当调用breakpoint()并将PYTHONBREAKPOINT设置为默认值时,pytest将使用
自定义内部PDB跟踪UI而不是系统默认Pdb。
•测试完成后,系统将默认返回系统Pdb跟踪UI。
•如果在执行pytest时调用了--pdb,则自定义内部Pdb跟踪UI将用于breakpoint()和失败的测试/未处理的异常。
•如果使用--pdbcls,则在测试失败时(如在现有行为中所预期的那样)执行自定义类调试器,但是当在测试中调用breakpoint()时,将实例化自定义类调试器。

 

分析测试执行耗时时间
要获得最慢的10个测试耗时时间的列表:

pytest --durations = 10

 

创建JUnitXML格式文件
要创建可由Jenkins或其他Continuous集成服务器读取的结果文件,请使用以下调用:

pytest --junitxml = path

在路径上创建XML文件。

要设置根测试套件xml项的名称,可以在配置中配置junit_suite_name选项文件:

[pytest]
junit_suite_name = my_suite

 

record_property
如果要记录测试的其他信息,可以使用record_property fixture

def test_function(record_property):
    record_property("example_key", 1)
    assert True

这将在生成的测试用例标记中添加一个额外的属性,示例key =“1”

<testcase classname="test_function" file="test_function.py" line="0" name="test_function" time="0.0009">
    <properties>
        <property name="example_key" value="1" />
    </properties>
</testcase>

或者,您可以自定义标记集成此功能:

# content of conftest.py

def pytest_collection_modifyitems(session, config, items):
    for item in items:
        for marker in item.iter_markers(name="test_id"):
            test_id = marker.args[0]
            item.user_properties.append(("test_id", test_id))

测试:

# content of test_function.py
import pytest
@pytest.mark.test_id(1501)
def test_functionn():
    assert True

结果:

<testcase classname="test_function" file="test_function.py" line="0" name="test_function" time="0.0009">
    <properties>
        <property name="test_id" value="1501" />
    </properties>
</testcase>

警告:record_property是一项实验性功能,将来可能会发生变化。
另请注意,使用此功能将破坏任何架构验证。 与某些CI服务器一起使用时,这可能是一个问题。

 

record_xml_attribute

要向testcase元素添加其他xml属性,可以使用record_xml_attribute fixture。 这也可以用于覆盖现有值:

def test_function(record_xml_attribute):
    record_xml_attribute("assertions", "REQ-1234")
    record_xml_attribute("classname", "custom_classname")
    print("hello world")
    assert True

与record_property不同,这不会添加新的子元素。 相反,这将在生成的testcase标记内添加一个属性assertions =“REQ-1234”,并使用“classname = custom_classname”覆盖默认的classname:

<testcase classname="custom_classname" file="test_function.py" line="0" name="test_function" time="0.003" assertions="REQ-1234">
    <system-out>
        hello world
    </system-out>
</testcase>

警告:record_xml_attribute是一个实验性功能,其界面可能会被未来版本中更强大和更通用的内容所取代。 但是,将保留功能本身。
在使用ci工具解析xml报告时,在record_xml_property上使用它会有所帮助。 但是,一些解析器对允许的元素和属性非常严格。 许多工具使用xsd模式来验证传入的xml。 确保使用解析器解析允许的属性名称。
以下是Jenkins用于验证XML报告的Scheme:

<xs:element name="testcase">
    <xs:complexType>
        <xs:sequence>
            <xs:element ref="skipped" minOccurs="0" maxOccurs="1"/>
            <xs:element ref="error" minOccurs="0" maxOccurs="unbounded"/>
            <xs:element ref="failure" minOccurs="0" maxOccurs="unbounded"/>
            <xs:element ref="system-out" minOccurs="0" maxOccurs="unbounded"/>
            <xs:element ref="system-err" minOccurs="0" maxOccurs="unbounded"/>
        </xs:sequence>
        <xs:attribute name="name" type="xs:string" use="required"/>
        <xs:attribute name="assertions" type="xs:string" use="optional"/>
        <xs:attribute name="time" type="xs:string" use="optional"/>
        <xs:attribute name="classname" type="xs:string" use="optional"/>
        <xs:attribute name="status" type="xs:string" use="optional"/>
    </xs:complexType>
</xs:element>

 

LogXML: add_global_property

如果要在testsuite级别添加属性节点,该节点可能包含与所有测试用例相关的属性,则可以使用LogXML.add_global_properties

import pytest

@pytest.fixture(scope="session")
def log_global_env_facts(f):
    if pytest.config.pluginmanager.hasplugin("junitxml"):
        my_junit = getattr(pytest.config, "_xml", None)
    my_junit.add_global_property("ARCH", "PPC")
    my_junit.add_global_property("STORAGE_TYPE", "CEPH")
@pytest.mark.usefixtures(log_global_env_facts.__name__)

def start_and_prepare_env():
    pass

class TestMe(object):
    def test_foo(self):
        assert True

这会将testsuite节点下的属性节点添加到生成的xml中:

<testsuite errors="0" failures="0" name="pytest" skips="0" tests="1" time="0.006">
    <properties>
        <property name="ARCH" value="PPC"/>
        <property name="STORAGE_TYPE" value="CEPH"/>
    </properties>
    <testcase classname="test_me.TestMe" file="test_me.py" line="16" name="test_foo" time="0.000243663787842"/>
</testsuite>

警告:这是一个实验性功能,其界面可能会被未来版本中更强大,更通用的内容所取代。 将保留功能本身。

 

创建结果日志格式文件

对于仍然需要类似功能的用户来说,另一种选择是使用提供测试数据流的pytest-tap插件。

pytest --resultlog=path

将测试报告发送到在线pastebin服务

为每个测试失败的创建一个URL:

pytest --pastebin=failed

这会将测试运行信息提交给远程Paste服务,并为每个失败提供一个URL。 您可以像往常一样选择测试,或者如果您只想发送一个特定的故障,则添加例如-x。

为整个测试会话日志创建URL

pytest --pastebin=all

 

禁用插件

要在调用时禁用特定插件,请将-p选项与前缀no:一起使用。
示例:禁用加载插件doctest

pytest -p no:doctest

从Python代码调用pytest

您可以直接从Python代码调用pytest:

pytest.main()

这就像你从命令行调用“pytest”一样。 它不会引发SystemExit,而是返回exitcode。 您可以传入选项和参数:

pytest.main(['-x', 'mytestdir'])

您可以为pytest.main指定其他插件:

# content of myinvoke.py
import pytest
class MyPlugin(object):
    def pytest_sessionfinish(self):
        print("*** test run reporting finishing")

pytest.main(["-qq"], plugins=[MyPlugin()])

运行它,将显示已添加MyPlugin并调用

$ python myinvoke.py
.                                     [100%]*** test run reporting finishing

注意:调用pytest.main()将导致导入测试及其导入的任何模块。 因为python导入系统的缓存机制,从同一进程后续调用pytest.main(),不会反映调用之间对这些文件的更改。 出于这个原因,多次调用pytest.main(),不推荐使用相同的过程(例如,为了重新运行测试)

posted @ 2018-08-30 19:11  星之疾风  阅读(987)  评论(0)    收藏  举报