pytest - 使用pytest过程中的5大超级技巧(实例详解篇)

news2024/11/26 16:36:32

从简单的断言和测试用例组织到更先进的参数化和夹具管理,pytest提供了强大的功能和灵活性。让我们一起探索这些技巧,使你的测试变得更加高效精准!

无需担心阅读时间过长,本文已经为您准备了详尽的解析和实际示例。立即开始,您将发现pytest的强大之处!

1、assert的各种使用场景

包含了几十种断言失败的各种场景,涉及断言的,可以查看pytest文档的 5.1.1(以 PDF 格式下载最新版本),举例几个常用的断言:

@pytest.mark.parametrize("param1, param2", [(3, 6)])
def test_generative(param1, param2):
    assert param1 * 2 < param2
    assert (3 * 2) < 6
    
def test_simple(self):
	def f():
		return 42
	def g():
		return 43
	assert f() == g()
	assert 42 == 43
	
def test_eq_long_text(self):
	a = "1" * 100 + "a" + "2" * 100
	b = "1" * 100 + "b" + "2" * 100
	assert a == b

2、基本模式和示例

2.1 更改命令行选项的默认值

# content of pytest.ini
[pytest]
addopts = -ra -q 

2.2 构建一个依赖于命令行选项的测试

根据命令行选项将不同的值传递给测试函数,运行用例:pytest -q test_sample.py --cmdopt=type3

# content of conftest.py
import pytest

def type_checker(value):
    msg = "cmdopt must specify a numeric type as typeNNN"
    if not value.startswith("type"):
        raise pytest.UsageError(msg)
    try:
        int(value[4:])
    except ValueError:
        raise pytest.UsageError(msg)
    return value


def pytest_addoption(parser):
    parser.addoption(
        "--cmdopt",
        action="store",
        default="type1",
        help="my option: type1 or type2",
        choices=("type1", "type2"),
        type=type_checker,
    )


@pytest.fixture
def cmdopt(request):
    return request.config.getoption("--cmdopt")

# content of test_sample.py

def test_answer(cmdopt):
    if cmdopt == "type1":
        print("first")
    elif cmdopt == "type2":
        print("second")
    assert 0

2.3 动态地添加命令行选项

# setuptools plugin
import sys
def pytest_load_initial_conftests(args):
	if "xdist" in sys.modules: # pytest-xdist plugin
		import multiprocessing
		
		num = max(multiprocessing.cpu_count() / 2, 1)
		args[:] = ["-n", str(num)] + args

2.4 控制跳过测试根据命令行选项

# content of conftest.py
import pytest
def pytest_addoption(parser):
	parser.addoption("--runslow", action="store_true", default=False, help="run slow tests" )
def pytest_configure(config):
	config.addinivalue_line("markers", "slow: mark test as slow to run")
def pytest_collection_modifyitems(config, items):
	if config.getoption("--runslow"):
		# --runslow given in cli: do not skip slow tests
		return
	skip_slow = pytest.mark.skip(reason="need --runslow option to run")
	for item in items:
		if "slow" in item.keywords:
			item.add_marker(skip_slow)

# content of test_module.py
import pytest
def test_func_fast():
	pass
@pytest.mark.slow
def test_func_slow():
	pass

2.5 编写良好的断言程序

# content of test_checkconfig.py
import pytest
def checkconfig(x):
	__tracebackhide__ = True
	if not hasattr(x, "config"):
		pytest.fail("not configured: {}".format(x))
def test_something():
	checkconfig(42)

2.6 检测是否从 pytest 运行中运行

# content of your_module.py
_called_from_test = False

# content of conftest.py
def pytest_configure(config):
	your_module._called_from_test = True

2.7 向测试报告题头添加信息

# content of conftest.py
def pytest_report_header(config):
	return "project deps: mylib-1.1"

2.8 分析测试持续时间

pytest --durations=3 test_some_are_slow.py

# content of test_some_are_slow.py
import time
def test_funcfast():
	time.sleep(0.1)
def test_funcslow1():
	time.sleep(0.2)
def test_funcslow2():
	time.sleep(0.3)

2.11 处理过程后的测试报告/失败

# content of conftest.py
import pytest
import os.path
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
	# execute all other hooks to obtain the report object
	outcome = yield
	rep = outcome.get_result()
	# we only look at actual failing test calls, not setup/teardown
	if rep.when == "call" and rep.failed:
		mode = "a" if os.path.exists("failures") else "w"
		with open("failures", mode) as f:
			# let's also access a fixture for the fun of it
			if "tmp_path" in item.fixturenames:
				extra = " ({})".format(item.funcargs["tmp_path"])
			else:
				extra = "" f.write(rep.nodeid + extra + "\n")

# content of test_module.py
def test_fail1(tmp_path):
	assert 0
def test_fail2():
	assert 0

2.12 在固定设备中提供测试结果信息

# content of conftest.py
import pytest
@pytest.hookimpl(tryfirst=True, hookwrapper=True)
def pytest_runtest_makereport(item, call):
	# execute all other hooks to obtain the report object
	outcome = yield
	rep = outcome.get_result()
	# set a report attribute for each phase of a call, which can
	# be "setup", "call", "teardown"
	setattr(item, "rep_" + rep.when, rep)
@pytest.fixture
def something(request):
	yield
	# request.node is an "item" because we use the default
	# "function" scope
	if request.node.rep_setup.failed:
		print("setting up a test failed!", request.node.nodeid)
	elif request.node.rep_setup.passed:
		if request.node.rep_call.failed:
			print("executing test failed", request.node.nodeid)

# content of test_module.py
import pytest
@pytest.fixture
def other():
	assert 0
def test_setup_fails(something, other):
	pass
def test_call_fails(something):
	assert 0
def test_fail2():
	assert 0

2.9 测试步骤的增量测试
2.10 包装/目录级固定装置(设置)
2.13 PYTEST_CURRENT_TEST环境变量
2.14 Freezing pytest

3、用例参数化

3.1 生成参数组合,取决于命令行

  • pytest -vs test_sample.py
  • pytest -vs test_sample.py --all
# content of conftest.py
def pytest_addoption(parser):
    parser.addoption("--all", action="store_true", help="run all combinations")
def pytest_generate_tests(metafunc):
    if "param1" in metafunc.fixturenames:
        if metafunc.config.getoption("all"):  # 如果在命令行中获取到了字符串all:pytest -vs test_sample.py --all
            end = 5
        else:  # 如果在命令什么也没有:pytest -vs test_sample.py
            end = 2
            print("2")
        metafunc.parametrize("param1", range(end))

# content of test_compute.py
def test_compute(param1):
    assert param1 < 4

3.2 参数中设置不同的测试ID

# content of test_time.py
from datetime import datetime, timedelta
import pytest
testdata = [
    (datetime(2001, 12, 12), datetime(2001, 12, 11), timedelta(1)),
    (datetime(2001, 12, 11), datetime(2001, 12, 12), timedelta(-1)),
]
@pytest.mark.parametrize("a,b,expected", testdata)
def test_timedistance_v0(a, b, expected):
    diff = a - b
    assert diff == expected
@pytest.mark.parametrize("a,b,expected", testdata, ids=["forward", "backward"])
def test_timedistance_v1(a, b, expected):
    diff = a - b
    assert diff == expected
def idfn(val):
    if isinstance(val, (datetime,)):
        # note this wouldn't show any hours/minutes/seconds
        return val.strftime("%Y%m%d")
@pytest.mark.parametrize("a,b,expected", testdata, ids=idfn)
def test_timedistance_v2(a, b, expected):
    diff = a - b
    assert diff == expected

@pytest.mark.parametrize(
    "a,b,expected",
    [
        pytest.param(datetime(2001, 12, 12), datetime(2001, 12, 11), timedelta(1), id="forward"),
        pytest.param(datetime(2001, 12, 11), datetime(2001, 12, 12), timedelta(-1), id="backward"),
    ],
)
def test_timedistance_v3(a, b, expected):
    diff = a - b
    assert diff == expected

pytest test_time.py --collect-only,--collect-only 用来显示测试ID

collected 8 items                                                                                                                                                                                             
<Package test>
  <Module test_time.py>
    <Function test_timedistance_v0[a0-b0-expected0]>
    <Function test_timedistance_v0[a1-b1-expected1]>
    <Function test_timedistance_v1[forward]>
    <Function test_timedistance_v1[backward]>
    <Function test_timedistance_v2[20011212-20011211-expected0]>
    <Function test_timedistance_v2[20011211-20011212-expected1]>
    <Function test_timedistance_v3[forward]>
    <Function test_timedistance_v3[backward]>

3.3 “测试场景”的快速移植

# content of test_scenarios.py

def pytest_generate_tests(metafunc):
    idlist = []
    argvalues = []
    for scenario in metafunc.cls.scenarios:
        idlist.append(scenario[0])
        items = scenario[1].items()
        argnames = [x[0] for x in items]
        argvalues.append([x[1] for x in items])
    metafunc.parametrize(argnames, argvalues, ids=idlist, scope="class")
    
scenario1 = ("basic", {"attribute": "value"})
scenario2 = ("advanced", {"attribute": "value2"})

class TestSampleWithScenarios:
    scenarios = [scenario1, scenario2]

    def test_demo1(self, attribute):
        assert isinstance(attribute, str)

    def test_demo2(self, attribute):
        assert isinstance(attribute, str)

3.4 延迟对参数化资源的设置

3.5 间接参数化

在参数化测试时,使用indirect=True参数允许参数化测试之前参数化测试:

import pytest
@pytest.fixture
def fixt(request):
    return request.param * 3

@pytest.mark.parametrize("fixt", ["a", "b"], indirect=True)
def test_indirect(fixt):
    assert len(fixt) == 3

3.6 间接地应用于特定的参数

@pytest.mark.parametrize中的值再次做参数化,使用indirect=["x"]指定引用固定装置X再次对值进行参数化处理:

# content of test_indirect_list.py
import pytest

@pytest.fixture(scope="function")
def x(request):
    return request.param * 3
@pytest.fixture(scope="function")
def y(request):
    return request.param * 2

# indirect给了值X:引用了上面的固定装置X,没给Y,没引用固定装置Y,所以Y的取值是b
@pytest.mark.parametrize("x, y", [("a", "b")], indirect=["x"])
def test_indirect(x, y):
    assert x == "aaa"
    assert y == "b"

3.7 通过每个类的配置来参数化测试方法

这里是一个示例pytest_generate_tests函数实现一个参数化方案

# content of ./test_parametrize.py
import pytest
def pytest_generate_tests(metafunc):
    # called once per each test function
    funcarglist = metafunc.cls.params[metafunc.function.__name__]
    argnames = sorted(funcarglist[0])
    metafunc.parametrize(argnames, [[funcargs[name] for name in argnames] for funcargs in funcarglist])
class TestClass:
    # a map specifying multiple argument sets for a test method
    params = { "test_equals": [dict(a=1, b=2), dict(a=3, b=3)], "test_zerodivision": [dict(a=1, b=0)],}
    def test_equals(self, a, b):
        assert a == b
    def test_zerodivision(self, a, b):
        with pytest.raises(ZeroDivisionError):
            a / b

3.8 使用多种固定装置的间接参数化

import shutil
import subprocess
import textwrap
import pytest

pythonlist = ["python3.5", "python3.6", "python3.7", "python3.9.6"]


@pytest.fixture(params=pythonlist)
def python1(request, tmp_path):
    picklefile = tmp_path / "data.pickle"
    return Python(request.param, picklefile)


@pytest.fixture(params=pythonlist)
def python2(request, python1):
    return Python(request.param, python1.picklefile)


class Python:
    def __init__(self, version, picklefile):
        self.pythonpath = shutil.which(version)
        if not self.pythonpath:
            pytest.skip(f"{version!r} not found")
        self.picklefile = picklefile

    def dumps(self, obj):
        dumpfile = self.picklefile.with_name("dump.py")
        dumpfile.write_text(textwrap.dedent(
                r"""
                import pickle
                f = open({!r}, 'wb')
                s = pickle.dump({!r}, f, protocol=2)
                f.close()
                """.format(str(self.picklefile), obj)
        ))
        subprocess.check_call((self.pythonpath, str(dumpfile)))

    def load_and_is_true(self, expression):
        loadfile = self.picklefile.with_name("load.py")
        loadfile.write_text(
            textwrap.dedent(
                r"""
                import pickle
                f = open({!r}, 'rb')
                obj = pickle.load(f)
                f.close()
                res = eval({!r})
                if not res:
                raise SystemExit(1)
                """.format(
                    str(self.picklefile), expression
                )))
        print(loadfile)
        subprocess.check_call((self.pythonpath, str(loadfile)))

@pytest.mark.parametrize("obj", [42, {}, {1: 3}])
def test_basic_objects(python1, python2, obj):
    python1.dumps(obj)
    python2.load_and_is_true(f"obj == {obj}")

3.9 可选实现/导入的间接参数化

3.10 为个别参数化测试设置标记或测试ID

# content of test_pytest_param_example.py
import pytest
@pytest.mark.parametrize(
    "test_input,expected",
    [
        ("3+5", 8),
        pytest.param("1+7", 8, marks=pytest.mark.basic),
        pytest.param("2+4", 6, marks=pytest.mark.basic, id="basic_2+4"),
        pytest.param("6*9", 42, marks=[pytest.mark.basic, pytest.mark.xfail], id="basic_6*9"),
    ],
)
def test_eval(test_input, expected):
    assert eval(test_input) == expected

3.11 参数化条件提升

from contextlib import contextmanager
import pytest
@contextmanager
def does_not_raise():
    yield
    
@pytest.mark.parametrize(
    "example_input,expectation",
    [
        (3, does_not_raise()),
        (2, does_not_raise()),
        (1, does_not_raise()),
        (0, pytest.raises(ZeroDivisionError)),
    ],
)
def test_division(example_input, expectation):
    """Test how much I know division."""
    with expectation:
        assert (6 / example_input) is not None

4、自定义标记

4.1 标记测试函数并运行

  • pytest test_module.py -m webtest
  • pytest test_module.py -v -m "not webtest
# content of test_server.py
import pytest
@pytest.mark.webtest
def test_send_http():
    pass # perform some webtest test for your app
def test_something_quick():
    pass
def test_another():
    pass
class TestClass:
    def test_method(self):
        pass

4.2 根据节点选择测试

  • pytest -v test_server.py::TestClass
  • pytest -v test_server.py::TestClass::test_method
  • pytest -v test_server.py::TestClass test_server.py::test_send_http

4.3 根据正则表达式选择测试用例

  • pytest -v -k http test_server.py
  • pytest -v -k "not send_http" test_server.py
  • pytest -v -k "http or quick" test_server.py
# content of test_server.py
import pytest
@pytest.mark.webtest
def test_send_http():
    pass # perform some webtest test for your app
def test_something_quick():
    pass
def test_another():
    pass
class TestClass:
    def test_method(self):
        pass

4.4 注册标记

为测试套件注册标记很简单,查看注册的标记:pytest --markers

# content of pytest.ini
[pytest]
markers =
	webtest: mark a test as a webtest.
	slow: mark test as slow.

4.5 标记整个类或模块

# content of test_mark_classlevel.py
import pytest
@pytest.mark.webtest
class TestClass:
	def test_startup(self):
		pass
	def test_startup_and_more(self):
		pass

要在模块级别应用标记,也可以使用全局变量定义:

import pytest
# 单个标记
pytestmark = pytest.mark.webtest
# 多个标记:
pytestmark = [pytest.mark.webtest, pytest.mark.slowtest]
class TestClass:
	def test_startup(self):
		pass
	def test_startup_and_more(self):
		pass
import pytest
class TestClass:
	pytestmark = pytest.mark.webtest
	def test_startup(self):
		pass

4.6 参数化中标记各个测试

import pytest

@pytest.mark.foo
@pytest.mark.parametrize(("n", "expected"), [(1, 2), pytest.param(1, 3, marks=pytest.mark.bar), (2, 3)])
def test_increment(n, expected):
    assert n + 1 == expected

4.7 自定义标记和命令行选项

pytest -E stage2 test_moule.py

# content of conftest.py
import pytest
def pytest_addoption(parser):
    parser.addoption(
    "-E",
    action="store",
    metavar="NAME",
    help="only run tests matching the environment NAME.", )
def pytest_configure(config):
    # register an additional marker
    config.addinivalue_line(
    "markers", "env(name): mark test to run only on named environment" )
def pytest_runtest_setup(item):
    envnames = [mark.args[0] for mark in item.iter_markers(name="env")]
    if envnames:
        if item.config.getoption("-E") not in envnames:
            pytest.skip(f"test requires env in {envnames!r}")
# content of test_someenv.py
import pytest
@pytest.mark.env("stage1")
def test_basic_db_operation():
	pass

4.8 从多个地方读取标记

# content of test_mark_three_times.py
import pytest
pytestmark = pytest.mark.glob("module", x=1)
@pytest.mark.glob("class", x=2)
class TestClass:
	@pytest.mark.glob("function", x=3)
	def test_something(self):
		pass
# content of conftest.py`在这里插入代码片`
import sys
def pytest_runtest_setup(item):
	for mark in item.iter_markers(name="glob"):
		print(f"glob args={mark.args} kwargs={mark.kargs}")
		sys.stdout.flush()

4.9 标记不同的测试平台环境

pytest -m linux test_plat.py

# content of conftest.py
#
import sys
import pytest
ALL = set("darwin linux win32".split())
def pytest_runtest_setup(item):
	supported_platforms = ALL.intersection(mark.name for mark in item.iter_markers())
	plat = sys.platform
	if supported_platforms and plat not in supported_platforms:
		pytest.skip(f"cannot run on platform {plat}")
# content of test_plat.py
import pytest
@pytest.mark.darwin
def test_if_apple_is_evil():
	pass
@pytest.mark.linux
def test_if_linux_works():
	pass
@pytest.mark.win32
def test_if_win32_crashes():
	pass
def test_runs_everywhere():
	pass

4.10 基于测试名称自动添加标记

  • pytest -m interface --tb=short test_moudle.py
  • pytest -m "interface or event" --tb=short test_moudle.py
# content of test_module.py
def test_interface_simple():
	assert 0
def test_interface_complex():
	assert 0
def test_event_simple():
	assert 0
def test_something_else():
	assert 0
# content of conftest.py
import pytest
def pytest_collection_modifyitems(items):
	for item in items:
	if "interface" in item.nodeid:
		item.add_marker(pytest.mark.interface)
	elif "event" in item.nodeid:
		item.add_marker(pytest.mark.event)

 

5、session级别的固定装置

会话范围的夹具有效地访问所有收集的测试项目。 这是一个fixture函数的例子 遍历所有收集的测试并查看他们的测试类是否定义了 callme 方法并调用它:

# content of conftest.py
import pytest
@pytest.fixture(scope="session", autouse=True)
def callattr_ahead_of_alltests(request):
    print("callattr_ahead_of_alltests called")
    seen = {None}
    session = request.node
    for item in session.items:
        cls = item.getparent(pytest.Class)
        if cls not in seen:
            if hasattr(cls.obj, "callme"):
                cls.obj.callme()
                seen.add(cls)
# content of test_module.py
class TestHello:
    @classmethod
    def callme(cls):
        print("callme called!")
    def test_method1(self):
        print("test_method1 called")
    def test_method2(self):
        print("test_method2 called")
class TestOther:
    @classmethod
    def callme(cls):
        print("callme other called")
    def test_other(self):
        print("test other")
# works with unittest as well ...
import unittest
class SomeTest(unittest.TestCase):
    @classmethod
    def callme(self):
        print("SomeTest callme called")
    def test_unit1(self):
        print("test_unit1 method called")
C:\Users\mc\Desktop\python>pytest -q -s test_module.py
callattr_ahead_of_alltests called
callme called!
callme other called
SomeTest callme called
test_method1 called
.test_method2 called
.test other
.test_unit1 method called

 

6、更改标准 (Python) 发现测试用例

6.1 在测试收集期间忽略路径: --ignore

  • 通过传递 --ignore=path 选项,您可以在收集过程中轻松忽略某些测试目录和模块cli,pytest 允许多个 --ignore 选项。 例如test目录上执行:
    pytest --ignore=tests/foobar/test_foobar_03.py --ignore=tests/hello/
  • --ignore-glob 选项允许忽略基于 Unix shell 样式通配符的测试文件路径。 如果要排除以 _01.py 结尾的测试模块:
    pytest --ignore-glob='*_01.py'
tests/
|-- example
|  |-- test_example_01.py
|  |-- test_example_02.py
|  |-- test_example_03.py
|-- foobar
|  |-- test_foobar_01.py
|  |-- test_foobar_02.py
|  |-- test_foobar_03.py
|-- hello
	|-- world
		|-- test_world_01.py
		|-- test_world_02.py
		|-- test_world_03.py

6.2 在测试收集期间忽略测试用例:--deselect

pytest --deselect tests/foobar/test_foobar_01.py::test_a

6.3 更改目录递归

告诉 pytest 不要递归到典型的 subversion 或 sphinx-build 目录或任何以 tmp 为前缀的目录。

# content of pytest.ini
[pytest]
norecursedirs = .svn _build tmp*

6.4 更改命名约定

在你的配置文件中,您可以通过设置 python_files、python_classes 和 python_functions :pytest --collect-only

# content of pytest.ini
# Example 1: have pytest look for "check" instead of "test"
[pytest]
python_files = check_*.py test_*.py example_*.py
python_classes = Check
python_functions = *_check

# content of check_myapp.py
class CheckMyApp:
	def simple_check(self):
		pass
	def complex_check(self):
		pass

注意:对unittest发现用例的方法不管用,因为pytest将测试用例方法的发现委托给unittest

6.5 查看测试用例树

pytest --collect-only test_module.py

# content of test_module.py
class TestHello:
    @classmethod
    def callme(cls):
        print("callme called!")
    def test_method1(self):
        print("test_method1 called")
    def test_method2(self):
        print("test_method2 called")
class TestOther:
    @classmethod
    def callme(cls):
        print("callme other called")
    def test_other(self):
        print("test other")
# works with unittest as well ...
import unittest
class SomeTest(unittest.TestCase):
    @classmethod
    def callme(self):
        print("SomeTest callme called")
    def test_unit1(self):
        print("test_unit1 method called")

C:\Users\mc\Desktop\python基础>pytest --collect-only test_module.py
======================================================================= test session starts ========================================================================
platform win32 -- Python 3.9.6, pytest-7.1.1, pluggy-0.13.1
rootdir: C:\Users\mc\Desktop\python基础
collected 4 items                                                                                                                                                   

<Module test_module.py>
  <Class TestHello>
    <Function test_method1>
    <Function test_method2>
  <Class TestOther>
    <Function test_other>
  <UnitTestCase SomeTest>
    <TestCaseFunction test_unit1>

==================================================================== 4 tests collected in 0.03s ====================================================================

6.6 忽略收集的某些文件

然而,许多项目会有一个他们不想被导入的 setup.py。 此外,可能只有文件可由特定的 python 版本导入。 对于这种情况,您可以通过将它们列出来动态定义要忽略的文件一个 conftest.py 文件

# content of pytest.ini
[pytest]
python_files = *.py

# content of conftest.py
import sys
collect_ignore = ["setup.py"]
if sys.version_info[0] > 2:
	collect_ignore.append("pkg/module_py2.py")

# content of pkg/module_py2.py
def test_only_on_python2():
try:
	assert 0
except Exception, e:
	pass

7、使用非python进行测试

7.1 在Yaml文件中指定测试的基本示例

这是一个示例 conftest.py( pytest-yamlwsgi 插件),conftest.py 将收集 test*.yaml 文件并将 yaml 格式的内容作为自定义测试执行:pytest -vs test_simple.yaml

 
collected 2 items
test_simple.yaml::hello FAILED
test_simple.yaml::ok PASSED

# content of conftest.py
import pytest
def pytest_collect_file(parent, file_path):
    if file_path.suffix == ".yaml" and file_path.name.startswith("test"):
        return YamlFile.from_parent(parent, path=file_path)
class YamlFile(pytest.File):
    def collect(self):
    # We need a yaml parser, e.g. PyYAML.
        import yaml
        raw = yaml.safe_load(self.path.open())
        for name, spec in sorted(raw.items()):
            yield YamlItem.from_parent(self, name=name, spec=spec)
class YamlItem(pytest.Item):
    def __init__(self, *, spec, **kwargs):
        super().__init__(**kwargs)
        self.spec = spec
    def runtest(self):
        for name, value in sorted(self.spec.items()):
        # Some custom test execution (dumb example follows).
            if name != value:
                raise YamlException(self, name, value)
    def repr_failure(self, excinfo):
        """Called when self.runtest() raises an exception."""
        if isinstance(excinfo.value, YamlException):
            return "\n".join(
            [ "usecase execution failed", " spec failed: {1!r}: {2!r}".format(*excinfo.value.args),
            " no further details known at this point.", ] )
    def reportinfo(self):
        return self.path, 0, f"usecase: {self.name}"

class YamlException(Exception):
    """Custom exception for error reporting."""

# test_simple.yaml
ok:
  sub1: sub1
hello:
  world: world
  some: other

  

结语

这篇贴子到这里就结束了,最后,希望看这篇帖子的朋友能够有所收获。

 获取方式:留言【软件测试学习】即可

如果你觉得文章还不错,请大家 点赞、分享、留言 下,因为这将是我持续输出更多优质文章的最强动力!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/662595.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

基于MATLAB的前景检测器实现道路车辆实时检测跟踪(完整代码分享)

交通问题越来越开始影响着人们的生产和生活,由于汽车拥有量的急剧增加,城市交通问题日益严重,因此交通问题开始成为人们关心的社会热点。在我国,近年来,交通事故频繁发生,有效的交通监测和管理已迫在眉睫。 完整代码: clc; clear; close all; warning off; addpath(gen…

redis源码之:字典dict

先来看看dict的大致结构&#xff1a; debug所用demo如下&#xff1a; void testDict(); int main(int argc, char **argv) {testDict(); } void testDict(){dict *dict0 dictCreate(&hashDictType, NULL);//注意key要用sds,如果是普通字符串&#xff0c;长度会判为0&…

这年头不会还有人纯文字聊天吧 ?教你用Python一键获取斗图表情包

前言 嗨喽&#xff0c;大家好呀~这里是爱看美女的茜茜呐 很多兄弟在聊天上没有下太多的功夫&#xff0c;导致自己聊天的时候很容易尬住&#xff0c; 然后就不知道聊啥了&#xff0c;这时候合适表情包分分钟就能救场&#xff0c; 但是一看自己收藏的表情包&#xff0c;好家伙…

【MySQL】一文带你彻底了解事务机制

文章目录 何谓事务&#xff1f;事务的特性&#xff1a;ACID事务的操作隔离性引发的并发问题不可重复读和幻读有什么区别 事务的隔离级别MySQL 的隔离级别是基于锁实现的吗&#xff1f;默认隔离级别解决幻读的方法总结 我们设想一个场景&#xff0c;这个场景中我们需要插入多条相…

网络安全学术顶会——CCS '22 议题清单、摘要与总结(下)

注意&#xff1a;本文由GPT4与Claude联合生成。 161、Secure Auctions in the Presence of Rational Adversaries 密封竞标拍卖用于在一组感兴趣的参与者之间分配资源。传统上&#xff0c;拍卖需要一个受信任的拍卖师在场&#xff0c;竞标者向其提供他们的私人出价。然而&#…

Flask简单入门

Flask 是一个使用 Python 编写的轻量级 Web 应用框架。它使用 Werkzeug 作为底层 WSGI 实现&#xff0c;而 Jinja2 则是其默认模板引擎。Flask 的设计简单易用&#xff0c;灵活性高&#xff0c;可以快速构建出完整功能的 Web 应用。 本文将从 Flask 的基础知识介绍、开发环境…

基于SSD算法的电动车头盔检测【附代码】

本项目是基于SSD算法实现的电动车头盔检测。完整的项目是基于SSD的改进-->知识蒸馏-->自蒸馏-->剪枝-->trt推理。本想用来发论文的&#xff0c;但可能没那时间和精力了&#xff0c;这里仅选择项目中的一部分内容进行开源。 目录 开源说明 项目功能说明 项目代码…

尚硅谷微信小程序开发 仿网易云音乐App 小程序 后端接口服务器搭建

小程序学习 尚硅谷微信小程序开发 项目网易云小程序学习地址&#xff1a; 01-尚硅谷-小程序-课程介绍_哔哩哔哩_bilibili 视频相关的教程文档与笔记分享 链接&#xff1a;https://pan.baidu.com/s/1aq7ks8B3fJ1Wahge17YYUw?pwd7oqm 提取码&#xff1a;7oqm 配套服务器 老师…

还敢说你会接口测试吗?全覆盖接口测试扫描总结(详细)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 接口的本质及其工…

搭建SpringBoot项目 详细教程

一、搭建SpringBoot项目 这个项目&#xff0c;可以作为种子项目&#xff0c;我打算把它放置Gitee上。包含大部分web开发的相关功能&#xff0c;后期所有的Spring Boot项目都可以用这个项目&#xff0c;简单修改一下配置&#xff0c;就可以快速开发了。 选择Spring initializr…

C51/C52--led流水灯、静态数码管

目录 一、led流水灯&#xff08;flowing water lamp&#xff09; 二、静态数码管 一、led流水灯&#xff08;flowing water lamp&#xff09; 我们在点亮一个led灯的基础上&#xff0c;对8个led灯按照某种特定的点亮规律进行操作&#xff0c;从而形成像水按顺序流动的效果。 …

缓存在高并发场景下的常见问题

缓存一致性问题 当数据时效性要求很高时&#xff0c;需要保证缓存中的数据与数据库中的保持一致&#xff0c;而且需要保证缓存节点和副本中的数据也保持一致&#xff0c;不能出现差异现象。这就比较依赖缓存的过期和更新策略。一般会在数据发生更改的时&#xff0c;主动更新缓…

JMeter性能测试---完整入门到白了少年头

目录 一、性能测试 二、负载/压力/可靠性 三、JMeter工具 四、负载脚本 五、Jmeter参数化 六、远程操作运行脚本 一、性能测试 测试目的&#xff1a; 1.客户有明确要求&#xff0c;如&#xff1a;系统要求同时满足5000个用户登录&#xff0c;平均每个用户登录时间不能超…

体积小纯净无打扰,新版微软电脑管家在教国内做杀软

早在去年初&#xff0c;微软电脑管家就开启了 V1.0 版本内测&#xff0c;咱们也在第一时间替大伙儿体验了一番。 微软电脑管家最初就是专为国内用户推出的&#xff0c;算是真正做到了精简省心&#xff0c;无任何流氓广告弹窗行为。 这与咱们国内各种流氓杀软环境形成了极为鲜明…

IIS 7中添加匿名访问FTP站点

1. 开启FTP和IIS服务&#xff1a; 2.打开IIS 管理器&#xff1a; 我电脑上是IIS 7.5 &#xff0c;所以选择第一个并点击打开哦。 如果你想知道自己IIS的版本&#xff0c;打开帮助菜单&#xff1a; 3. 新建FTP站点&#xff1a; 4. 填写站点基本信息&#xff1a; 5. 设置绑定和S…

Stable diffusion WebUI img2img使用教学

图生图 (img2img) 相较于文生图 (txt2img)&#xff0c;因存在参考图片的基础上创作&#xff0c;其可控性自然更强。下面从图生图的几个应用方向出发&#xff0c;详述其功能特性。 文章目录 推提示词img 重新绘制参考图Resize mode 缩放模式Denoising 重绘幅度 Sketch 绘图Inpai…

集成光子芯片量子器件研究重要进展

前言&#xff1a; 中国科学技术大学郭光灿院士团队在集成光子芯片量子器件的研究中取得重要进展。该团队邹长铃、李明研究组提出人工合成光学非线性过程的通用方法&#xff0c;在集成芯片微腔中实验观测到高效率的合成高阶非线性过程&#xff0c;并展示了其在跨波段量子纠缠光源…

亚马逊云科技中国峰会“创业者之日”,赋能不同领域创业者前行

IDC预测&#xff0c;到2025年全球数据规模将达到175 ZB&#xff0c;这为人工智能模型训练提供了海量数据资源&#xff0c;全球AI产业迅速发展为创业者们带来了巨大的机遇&#xff0c;但也提出了全新的挑战。新的市场、高效的工具和智能的资源&#xff0c;开辟了创新的领域和商业…

23年互联网Java后端面试最全攻略,只花一周时间逼自己快速通关面试

大家从 Boss 直聘上或者其他招聘网站上都可以看到 Java 岗位众多&#xff0c;Java 岗位的招聘薪酬天差地别&#xff0c;人才要求也是五花八门。而很多 Java 工程师求职过程中&#xff0c;也是冷暖自知。很多时候技术有&#xff0c;但是面试的时候就是过不了&#xff01; 为了帮…

JVM存储模型、值传递和引用传递

JVM存储模型、值传递和引用传递 一、首先根据下图理解一下JVM是什么&#xff1f; — Java程序和操作系统之间的桥梁 二、Java数据存储模型 因为栈区、本地方法栈、程序计数器是线程私有的&#xff0c;每一个线程在运行时会单独去创建这样一个内存&#xff0c;所以说有多少个线…