自动化测试框架pytest系列之两个必备的配置文件(五)

发布时间:2024年01月12日

https://blog.csdn.net/venustech0919/article/details/135495254
https://blog.csdn.net/venustech0919/article/details/135521739
https://blog.csdn.net/venustech0919/article/details/135522722
https://blog.csdn.net/venustech0919/article/details/135546262

接上文 :

3.6 配置文件

在pytest中,常用到的两个配置文件 ,分别是pytest.ini和conftest.py .

pytest.ini主要包含

  1. pytest.ini是什么?
  2. pytest.ini编写格式
  3. pytest.ini包含的选项 。
  4. pytest的常用选项

conftest.py主要包含:

  1. conftest.py是什么 ?
  2. conftest.py有什么作用
  3. conftest.py 使用规则
  4. 需求 :在conftest中实现登录fixture.

3.6.1 pytest.ini介绍

1.pytest.ini是什么 ?

pytest.ini文件是pytest的主配置文件;pytest.ini文件的位置一般放在项目的根目录下,不能随便放,也不能更改名字。在pytest.ini文件中都是存放的一些配置选项 ,这些选项都可以通过pytest -h查看到 。

2.pytest.ini的编写格式

你可能已经看到 ,它的后缀是ini ,这也是标准配置文件的一种 ,而pytest也仅仅是引用了这种配置文件 ,所以 ,既然使用了这种文件,你就得知道它的规则 。

INI文件由节、键、值组成。


  [section]

选项/参数(键=值)
  name=value

注释
  注释使用分号表示(;)。在分号后面的文字,直到该行结尾都全部为注释。在这里插入图片描述
以下就是一个ini的示例 。

[pytest]
addopts = -s -v --reruns 1 --alluredir=./result --clean-alluredir
testpaths = ./testcase/webui/test_register
;python_files = *.py
;python_classes = *
;python_functions = rui*
markers =
    smoke
    regression
    slow
    serial

3.pytest.ini包含的选项**

我们知道了ini文件的编写规则 ,但是你知道pytest.ini里的选项是怎么定义的呢 ?是随意写还是有要求呢 ?其实在pytest.ini里能添加哪些,都是事先已经定义好了 ,你可以打开cmd窗口执行pytest -h查看 。以下这些都是在pytest.ini里能定义的选项 。

[pytest] ini-options in the first pytest.ini|tox.ini|setup.cfg file found:

  markers (linelist):   markers for test functions
  empty_parameter_set_mark (string):
                        default marker for empty parametersets
  norecursedirs (args): directory patterns to avoid for recursion
  testpaths (args):     directories to search for tests when no files or directories are given in the command line.
  filterwarnings (linelist):
                        Each line specifies a pattern for warnings.filterwarnings. Processed after -W/--pythonwarnings.
  usefixtures (args):   list of default fixtures to be used with this project
  python_files (args):  glob-style file patterns for Python test module discovery
  python_classes (args):
                        prefixes or glob names for Python test class discovery
  python_functions (args):
                        prefixes or glob names for Python test function and method discovery
  disable_test_id_escaping_and_forfeit_all_rights_to_community_support (bool):
                        disable string escape non-ascii characters, might cause unwanted side effects(use at your own
                        risk)
  console_output_style (string):
                        console output: "classic", or with additional progress information ("progress" (percentage) |
                        "count").
  xfail_strict (bool):  default for the strict parameter of xfail markers when not given explicitly (default: False)
  enable_assertion_pass_hook (bool):
                        Enables the pytest_assertion_pass hook.Make sure to delete any previously generated pyc cache
                        files.
  junit_suite_name (string):
                        Test suite name for JUnit report
  junit_logging (string):
                        Write captured log messages to JUnit report: one of no|log|system-out|system-err|out-err|all
  junit_log_passing_tests (bool):
                        Capture log information for passing tests to JUnit report:
  junit_duration_report (string):
                        Duration time to report: one of total|call
  junit_family (string):
                        Emit XML for schema: one of legacy|xunit1|xunit2
  doctest_optionflags (args):
                        option flags for doctests
  doctest_encoding (string):
                        encoding used for doctest files
  cache_dir (string):   cache directory path.
  log_level (string):   default value for --log-level
  log_format (string):  default value for --log-format
  log_date_format (string):
                        default value for --log-date-format
  log_cli (bool):       enable log display during test run (also known as "live logging").
  log_cli_level (string):
                        default value for --log-cli-level
  log_cli_format (string):
                        default value for --log-cli-format
  log_cli_date_format (string):
                        default value for --log-cli-date-format
  log_file (string):    default value for --log-file
  log_file_level (string):
                        default value for --log-file-level
  log_file_format (string):
                        default value for --log-file-format
  log_file_date_format (string):
                        default value for --log-file-date-format
  log_auto_indent (string):
                        default value for --log-auto-indent
  pythonpath (paths):   Add paths to sys.path
  faulthandler_timeout (string):
                        Dump the traceback of all threads if a test takes more than TIMEOUT seconds to finish.
  addopts (args):       extra command line options
  minversion (string):  minimally required pytest version
  required_plugins (args):
                        plugins that must be present for pytest to run
  rsyncdirs (pathlist): list of (relative) paths to be rsynced for remote distributed testing.
  rsyncignore (pathlist):
                        list of (relative) glob-style paths to be ignored for rsyncing.
  looponfailroots (pathlist):
                        directories to check for changes

environment variables:
  PYTEST_ADDOPTS           extra command line options
  PYTEST_PLUGINS           comma-separated plugins to load during startup
  PYTEST_DISABLE_PLUGIN_AUTOLOAD set to disable plugin auto-loading
  PYTEST_DEBUG             set to enable debug tracing of pytest's internals

所以,你应该从这里开始往下看 。在这里插入图片描述
虽然,我们看到它支持很多参数的配置 ,但其实真正用到的不多 。

参数1:markers

  • 作用:在测试用例中添加了 @pytest.mark.标记符的装饰器,如果不在pytest.ini中添加markers选项的话,运行后就会报warnings 。所以加上次参数的目的就是去掉运行结果的警告 。
  • 格式:可以编写一个或多个值 ,如果是多个值的话 ,需要以换行分割 。
  • 示例 :下面的p1,p2,p3,p4就是在装饰器中可标记的标识符 。
[pytest]
markers=
	p1
    p2
    p3
    p4

比如如下代码 :

"""
pytest所支持的setup和tearDown .
"""

import pytest
from package_pytest.login import login



# case1 : 输入正确的用户名和正确的密码进行登录
@pytest.mark.p1
def test_login_success():
    print("1")
    expect_result = 0
    actual_result = login('admin','123456').get('code')
    assert expect_result == actual_result


# case2 : 输入正确的用户名和错误的密码进行登录
@pytest.mark.p2
def test_password_is_wrong():
    print("2")
    expect_reesult = 3
    actual_result = login('admin','1234567').get('code')
    assert expect_reesult == actual_result


# case3 : 输入用户名和空的密码进行登录
@pytest.mark.abc
def test_password_is_null():
    print("3")
    expect_reesult = 2
    actual_result = login('admin', '').get('code')
    assert expect_reesult == actual_result


if __name__ == '__main__':
    pytest.main(['test08_login_mark.py','-sv','-m','p1'])

请注意 ,以上的第3条测试用例中标记的是abc ,而这个值在pytest.ini中的markers没有 ,故运行后给出警告 ,具体如下 :在这里插入图片描述
但如果把这个abc换成markers里的值,就不会给出警告。在这里插入图片描述
参数2:disable_test_id_escaping_and_forfeit_all_rights_to_community_support

  • 作用:这个参数主要是用在测试用例进行参数化时ids中文出乱码后加的值,设置为True即可解决乱码问题 。
  • 说明 :它的值是一个bool类型 ,默认是False .
  • 示例 :
[pytest]
disable_test_id_escaping_and_forfeit_all_rights_to_community_support = True

具体代码如下 :

import pytest
from package_pytest.login import login

cases = [(0,'admin','123456'),(3,'admin','1234567'),(2,'admin',''),(1,'','123456')]

ids = ['正确的用户名和正确的密码登录','正确的用户名和错误的密码登录','空的密码登录','空的用户名登录']


@pytest.fixture(params=cases,ids=ids)
def fixture_demo(request):
    print("===初始化方法===")
    yield request.param             # request.param :代表将params接受到的数据返回给测试用例中。
    print("===清除方法===")


# case1 : 输入正确的用户名和正确的密码进行登录
def test_login(fixture_demo):
    # fixture_demo : 每次循环进来以后,都给到一组数据 ,而这组数据其实就是一个元组
    print(fixture_demo)
    expect_result = fixture_demo[0]
    username = fixture_demo[1]
    password = fixture_demo[2]
    actual_result = login(username,password).get('code')
    assert expect_result == actual_result

代码运行结果 :在这里插入图片描述
参数3:testpaths

  • 作用:testpaths指示pytest去哪里访问。testpaths是一系列相对于根目录的路径,用于限定测试用例的搜索范围,这样就可以缩搜索范围,提高执行效率。只有在pytest未指定文件目录参数或测试用例标识符时,该选项才有作用
  • 格式:它的值需要是一个文件夹 。
  • 示例:
[pytest]
testpaths = test_001

运行结果如下:在这里插入图片描述
参数4:addopts

  • 作用:在命令行输入一堆执行指令如果嫌麻烦记不住 ,你就可以假如该参数,可以省去重复输入这些参数的过程 。
  • 格式 :接受的是命令行参数的值 。
  • 示例 : 以下是生成测试报告必须要带的参数 ,配置这里就可以省略这个操作 。

以下这种是直接在命令中加入参数 :在这里插入图片描述
如果将上面的参数配置到addopts中 ,具体配置如下 :

[pytest]
addopts = -sv --alluredir=./result --clean-alluredir

你将在命令行直接输入 :pytest test02_login.py 和上面加参数运行结果一样 。

参数5:python_files|python_class|python_functions

  • 作用:更改搜索测试用例的匹配规则 ,pytest默认的搜索规则是搜索指定目录下的以test文件开头,以Test开头的类,以test开头的函数 。但是如果你想改变这个规则就可以指定这个函数
  • 格式 :一般输入的是通配符方式的规则 ,就是匹配规则。
  • 说明 :
    • python_files :匹配的是Python文件名
    • python_classes :匹配的是Python的类名
    • python_functions :匹配的是Python的函数名
  • 示例 :
[pytest]
python_files = test_*.py
python_classes = Test*
python_functions = test*

通过这样编写 ,pyest搜索就会按照这个规则搜索测试用例 ,当然,其实我们这里修改的还是它默认的 。

参数6:norecursedirs

  • 作用 :指定哪些目录不被搜索 ,默认情况下,他会搜索指定路径下的所有目录 ,如果你不想让某个目录被搜索,就可以加入这个参数 。
  • 格式 :它的值需要是具体的目录名
  • 示例 :
[pytest]
norecursedirs = test01

运行后将不会搜索该目录下的测试用例进行运行 。

参数7:log_cli

  • 作用 :让日志输出到控制台 ,这个需要集成日志模块logging .
  • 格式 :它的值只有两个 ,要么是True ,要么是False .但是相关日志的配置参数还有好几个 。
  • 示例 :
[pytest]
testpaths = test01
log_cli = True
log_file = ./log/test.log			; 日志存放路径
log_cli_level = INFO 				; 日志等级
log_cli_format = %(asctime)s [%(levelname)s] | %(filename)s:%(lineno)s | %(message)s	;日志格式化
log_cli_date_format = %Y-%m-%d %H:%M:%S			;日志日期格式 。

运行结果后,可以在控制台下看到对应的日志格式 ,同时将日志文件输出到了log/test.log下 。

参数8:xfail_strict

  • 作用 :可以让那些标记为@pytest.mark.xfail但实际通过显示XPASS的测试用例被报告为失败
  • 格式 :它的值只有两个 ,要么是True ,要么是False . 默认值为False .
  • 示例 :比如让标记为失败的用例运行失败 。

接下来我们来看段代码 :

import pytest
from package_pytest.login import login
import sys


# case1 : 输入正确的用户名和正确的密码进行登录
@pytest.mark.xfail()
def test_login_success():
    print("1")
    expect_result = 0
    actual_result = login('admin','123456').get('code')
    assert expect_result == actual_result


# case2 : 输入正确的用户名和错误的密码进行登录
@pytest.mark.xfail()
def test_password_is_wrong():
    print("2")
    expect_reesult = 3
    actual_result = login('admin','1234567').get('code')
    assert expect_reesult == actual_result


# case3 : 输入用户名和空的密码进行登录
@pytest.mark.xfail()
def test_password_is_null():
    print("3")
    expect_reesult = 20
    actual_result = login('admin', '').get('code')
    assert expect_reesult == actual_result

不标记xfail时,第三条用例运行是失败的 ,前两条正常运行是正常的 ;标记上xfail时 , 运行的结果是以下这样的 :

================================================= test session starts ==================================================
platform win32 -- Python 3.6.4, pytest-7.0.1, pluggy-1.0.0 -- C:\Python36\python.exe
cachedir: .pytest_cache
rootdir: E:\python_project\python01_demo\package_pytest01, configfile: pytest.ini
plugins: allure-pytest-2.9.45, assume-2.4.3, forked-1.4.0, ordering-0.6, repeat-0.9.1, xdist-1.23.2
collected 3 items

test15_login_xfail.py::test_login_success 1
XPASS
test15_login_xfail.py::test_password_is_wrong 2
XPASS
test15_login_xfail.py::test_password_is_null 3
XFAIL

============================================ 1 xfailed, 2 xpassed in 0.05s =============================================

以前成功的变为xpassed ,而以前失败的变为xfailed了 。但如果加上以下的配置

[pytest]
xfail_strict = True

运行结果如下 ,你会发现,以前结果是xpassed的都变为failed 了 。

================================================= test session starts ==================================================
platform win32 -- Python 3.6.4, pytest-7.0.1, pluggy-1.0.0 -- C:\Python36\python.exe
cachedir: .pytest_cache
rootdir: E:\python_project\python01_demo\package_pytest01, configfile: pytest.ini
plugins: allure-pytest-2.9.45, assume-2.4.3, forked-1.4.0, ordering-0.6, repeat-0.9.1, xdist-1.23.2
collected 3 items

test15_login_xfail.py::test_login_success 1
FAILED
test15_login_xfail.py::test_password_is_wrong 2
FAILED
test15_login_xfail.py::test_password_is_null 3
XFAIL

======================================================= FAILURES =======================================================
__________________________________________________ test_login_success __________________________________________________
[XPASS(strict)]
________________________________________________ test_password_is_wrong ________________________________________________
[XPASS(strict)]
=============================================== short test summary info ================================================
FAILED test15_login_xfail.py::test_login_success
FAILED test15_login_xfail.py::test_password_is_wrong
============================================= 2 failed, 1 xfailed in 0.04s =============================================

3.6.2 conftest.py介绍

1.conftest.py是什么 ?

conftest.py是fixture函数的一个集合,将一些前置动作放在fixture中,然后供其它测试用例调用。不同于普通被调用的模块,conftest.py使用时不需要导入,Pytest会首先查找这个文件。

2.conftest.py有什么作用?

那么它到底有什么使用场景呢 ? 执行用例前往往会做一些准备工作,而且都是一次性的操作 ,比如:

  • 调用系统之前你需要先做登录操作 ,获取token
  • 执行测试用例前先需要搜集测试用例数据 。
  • 执行测试用例前先需要进行筛选数据等 。

以上的这种一次性动作都可以放在conftest.py中的fixture中 。

3.conftest.py使用规则

  1. 它的文件名是固定的,不可更改 。
  2. 它可以放在项目的跟目录下 ,也可以放在每个测试用例的文件夹下 ,
  3. 每次执行时都是首先先运行此文件下的fixture函数 ,然后才去执行测试用例文件 。
  4. 被自动调用的fixture就涉及到fixure里的知识了,这里不做详说 。

4.需求 :在conftest.py中编写登录fixture且被自动调用

import pytest

# 实现登录 : 在执行测试用例前首先会被自动调用。
@pytest.fixture(scope='session',autouse=True)
def login():
    """
    登录:请求方法,请求地址,请求体
    :return:
    """
    base = Base()
    # 1.) 登录请求接口
    login_url = base.get_url('/admin/auth/login')
    
    # 2.) 获取响应体数据
    result = base.post(login_url,LOGIN_INFO)

    # 3.)判断是否登录成功
    if not result.get('errno'):
        logger.success("请求登录接口成功")
        token = result.get('data').get('token')     # 提取token值
        cache.set('token',token)        # 存放在缓存中了
    else:
        logger.error("登录失败:{}".format(result))
    return result
文章来源:https://blog.csdn.net/venustech0919/article/details/135546679
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。