• 微信公众号:美女很有趣。 工作之余,放松一下,关注即送10G+美女照片!

自动化学习笔记二:Pytest

开发技术 开发技术 4小时前 1次浏览

pytest

pytest介绍

  文档:https://docs.pytest.org/en/latest/contents.html#toc

  第三方库:https://pypi.org/search/?q=pytest

pytest用例识别与运行

  测试文件命名:test_*.py 或者 *_test.py

  类命名:Test*

    注意:测试类里不能包含 __init__方法,pytest会把包含__init__的类当成特殊功能类

  方法命名:test_*

  pytest也可以执行unittest框架写的用例和方法

  pycharm修改默认测试解释器:进到设置,搜索pytest,修改默认test runner 为pytest

  pycharm修改临时解释器:运行按钮左边的选项,添加python解释器,并选择要执行的文件

pytest用例执行入口:

if __name__ == "__main__":
    pytest.main(['test_*.py::TestDemo','-v'])

  test_*.py:指定测试文件

  TestDemo:指定测试类

  -v:打印日志

参数化

pytest数据参数化

  参数化装饰函数:@pytest.mark.parametrize(argnames, argvalues)

    argnames:参数化的变量:string(逗号分割),list,tuple

      装饰器里的参数名要与用例里的参数名保持一致

    argvalues:参数化的值,listlist[tuple]

  例子:

  使用string:@pytest.mark.parametrize(‘a,b’,[(1,2)(10,20)(‘a’,’b’)])

  使用list@pytest.mark.parametrize([‘a’,’b’],[(1,2)(10,20)(‘a’,’b’)])

  使用tuple:@pytest.mark.parametrize((‘a’,’b’),[(1,2)(10,20)(‘a’,’b’)])

  ids参数增加可读性:给参数化的每一个用例起别名

  ids=list@pytest.mark.parametrize(‘a,b’,[(1,2)(10,20)(‘a’,’b’)],ids=[‘name1′,’name2′,’name3’])

  叠加参数化:加多个装饰器,每个装饰器里放1个或1部分参数,最终可以像笛卡尔积一样,根据每一个参数的组合,分别生成测试数据

yaml数据参数化

yaml安装

  ide:搜索安装PYYML

  命令:pip install PYYML

yaml文件语法

  yaml实现list

-10
-20
-30

  yaml实现dict

by:id
locator:name
action:click

  yaml进行嵌套

companies:
    -
        id:1
        name:company1
        price:200W
    -
        id:2
        name:company2
        price:500W

  yaml流式写法

- [1, 2, 3]
-[10,20,30]
-[a, b, c]

加载yaml文件

  语法1:

yaml.safe_load(open("./data/yaml"))

  语法2:

with open("./data/yaml") as f:
    datas = yaml.safe_load(f)

  例子:

@pytest.mark.parametrize('a,b',yaml,safe_load(open("./data/yaml")))

  注意:此处参数化的值要求是 list 类型,如果 yaml 里的最外层数据是 dict 的话只会返回 key 值,可以在最外层加一个 “-” 保证数据以 list 类型被读取

yaml语法

  将文件流转成python对象:yaml.safe_load()

  将python对象转成yaml格式:yam.safe_dump()

数据驱动

数据驱动简介

  简单来说就是参数化的应用。数据量小可以用代码的参数化实现数据驱动;数据量大的情况下建议使用结构化的文件来对数据进行存储,然后在用例中读取这些数据

  应用场景

  1.APP、WEB、接口

  2.测试步骤的数据驱动

  3.测试数据的数据驱动

  4.配置的数据驱动

数据驱动案例:

fixture

  基础语法:@pytest.fixture()

  fixture特点及优势

    1.命令灵活:对于 setup,teardown,可以不起这两个名字

    2.数据共享:在 conftest.py 配置里写方法可以实现数据共享,不需要 import 导入。可以跨文件共享

    3. scope 的层次及神奇的 yield 组合相当于各种 setup 和 teardown

      fixtrue 里 yield 上面的内容相当于 setup,yield 下面的内容相当于 teardown,yield 屁股后面同一行的相当于 return  返回的内容

fixture的引用

方法1:在测试方法里,将被 fixture 装饰器包裹的方法,的方法名,作为参数,传给测试方法

  这样测试方法执行的时候会先执行传进来的 fixture 方法

  在测试方法里,可以通过 fixture 包裹方法的名字 来引用该方法的返回值。如果没有将 fixtrue 作为参数传给测试方法的话,无法引用 fixture 的返回

方法2:在测试方法前面加装饰器 @pytest.mark.usefixtures(‘funname’)

  这种方法无法引用fixture的返回值

fixture在自动化中的应用

应用1

场景

测试用例执行时,有的用例需要登录才能执行,有些用例不需要登录。setup 和 teardown 无法满足,而 fixture 可以。默认 scope(范围)function

scope 的可选参数控制 fixture 的作用范围,控制 fixture 在哪个级别前执行

步骤

1.导入 pytest

2.在登录的函数上面加 @pytest.fixture()

3.在要使用的测试方法中传入(登录函数名称),就先登录

4.不传入的就不登录直接执行测试方法

应用2

场景

  你与其它测试工程师合作一起开发时,公共的模块要在不同的文件中,要在大家都能访问到的地方

解决

  使用 conftest.py 这个文件进行数据共享,并且它可以方法不同未知起着不同的范围共享作用

前提

  conftest 文件名是不能换的;放在项目下是全局的数据共享的地方

执行

  系统执行到参数 login 时先从本模块中查找是否有这个名字的变量什么的,之后在 conftest.py 中找是否有

步骤

  将登录模块用  @pytest.fixture 包裹 写在 conftest.py

注意

  方法查找参数时,采用就近生效的方式:当前模块->当前目录下 conftest ->父目录下 conftest,一层一层往上

应用3

场景

  不想原测试方法有任何改动,或全部都自动实现自动应用,没特例,也不需要返回值时可以选择自动应用

解决

  使用 fixture 中参数 autouse=True

步骤

  在方法上面加 @pytest.fixture(autouse=True)

应用4

场景

  你已经可以将测试方法前要执行的或依赖的解决了,测试方法执行后销毁/清除数据的操作要如何进行呢?范围是模块级别的。类似setupClass

解决

  通过在同一模块中加入 yield 关键字,yield 是调用第一次返回结果,第二次执行它下面的语句返回

步骤

  在 @pytest.fixture(scope=module)。在登录的方法中加 yield,之后加销毁清除的步骤

应用5

场景

测试离不开数据,为了数据灵活,一般数据都是通过参数传的

解决

  fixture 通过固定参数 request 传递

步骤

  在 fixture 中增加  @pytest.fixture(params=[1,2,3,’linda’]) ;在方法参数里写 request,;方法体里面使用 request.param 接收参数

  扩展:可以通过 ids 参数起别名

        request 其实就是 pytest 内置的一个 fixture

pytest插件

插件地址:pypi.org

常用的插件

pip install pytest-ordering:控制用例的执行顺序(重点)

方法一

加装饰器 @pytest.mark.run(order=1)

  order后面的正数编号,代表正数第几个执行

  order后面的负数编号,代表倒数第几个执行

方法二

加装饰器 @pytest.mark.first

  .first相当于.run(order=1)

  .last相当于.run(order=-1)

pip install pytest-xdist:分布式并发执行测试用例(重点)

xdist应用

场景1

测试用例1000条,一个用例执行1分钟,一个测试人员执行需要1000分钟。通常我们会用人力成本换取时间成本,加几个人一起执行,时间就会缩短。如果10人一起执行只需要100分钟,这就是一种分布式场景。

场景2

假设有个报名系统,对报名总数统计,数据同时进行修改操作的时候有可能出现问题,需要模拟这个场景,需要多用户并发请求数据

解决

  使用分布式并发执行测试用例。分布式插件:pytest-xdist

注意

  用例多的时候效果明显,多进行并发执行,同时支持allure

命令行参数

pytest -n 4:其中 -n 4 表示指定4个cpu并行执行

注意:不要让用例之间有依赖关系

pip install pytest-dependency:控制用例的依赖关系(了解)

pip install pytest-rerunfailures:失败重跑(了解)

pip install pytest-assume:多重校验(了解)

pip install pytest-random-order:用例随机执行(了解)

pip install pytest-html:测试报告(了解)

插件开发

插件分类

外部插件:pip install 安装的插件

本地插件:pytest 自动发现机制(conftest.py存放的)

内置插件:代码内部的_pytest目录加载

根据 _pytest 目录下 hookspec.py 进行插件开发

测试人社区搜索:pytest hook,思涵总结了 pytest 里 所有 hook 的执行顺序

pytest框架结构

模块级:setupmodule 和 teardownmodule

  模块始末,全局的(优先级最高)

函数级:setupfunction 和 teardownfunction

  只对函数用例生效(不在类中)

类级:setupclass 和 teardownclass

  只在当前所属的类前后运行一次(在类中)

方法级:setupmethod 和 teardownmethod

  开始于方法始末(在类中)

方法级:setup 和 teardown

  运行在调用方法的前后

pytest命令行指令

pytest:执行当前目录下所有test_*.py文件里的测试类和测试方法

pytest -v:打印结果的详细信息

pytest -s:打印print的信息

pytest -vs:既打印结果的详细信息也打印print的信息

pytest -k ‘testa’ or ‘testb’:执行包含关键字的用例

pytest -x:遇到失败的用例就停止

pytest –maxfail=num:失败num条用例后停止

pytest -m:加标签

pytest –help |findstr allure:查看包含allure关键字的pytest帮助信息

pytest –collect-only:只收集用例不执行

pytest –junitxml=./result.xml:生成一个执行的结果文件

pytest –lf:只执行上一次失败的

pytest –ff:先执行失败的,再执行其它的

pytest一些装饰器

  @pytest.mark.xxx:添加名字叫做 xxx 的标签

    解决警告,需要在 pytest.ini 文件里把 xxx 这个标签加进去

    1. pytest.ini需要手动创建
    2. 文件内加一个头[pytest]
    3. 文件内头下面加markers = xxx;多个标签的话,需要换行+tab然后输下一个标签

pytest配置

使用 pytest.ini 文件

  头:[pytest]

  key

markers:自定义mark标签名

addopts =:运行时自动添加= 后面的参数(可添加多个命令行参数,空格分隔,所有参数与命令行一致)

python_files:自动与测试文件命名规则

python_classes = Test_*:自定义测试类命名规则

python_functions = test_* check_*:自定义测试方法命名规则

norecursedirs = result logs datas test_demo*:运行时忽略某些文件夹

 

命令行输入 pytest –help

  打印内容里可以找到pytest 所有的 [pytest] ini 配置项

pytest.ini配置日志

[pytest]
;日志开关 true false
log_cli = true
;日志级别
log_cli_level = info
;打印详细日志,相当于命令行加 -vs
addopts = --capture=no
;日志格式
log_cli_format = %(asctime)s [%(levelname)s] %(message)s (%(filename)s:%(lineno)s)
;日志时间格式
log_cli_date_format = %Y-%m-%d %H:%M:%S
;日志文件位置
log_file = ./log/test.log
;日志文件等级
log_file_level = info
;日志文件格式
log_file_format = %(asctime)s [%(levelname)s] %(message)s (%(filename)s:%(lineno)s)
;日志文件日期格式
log_file_date_format = %Y-%m-%d %H:%M:%S

注意:windows系统,pytest.ini文件中不能使用中文注释

代码里使用logging这个模块来收集日志 logging.info(“xxx”) 取代print(“xxx”)

pytest异常处理机制

 

with pytest.raises(errorname1,errorname2):
    xxxxxx

  xxxxx 执行的结果报错,错误名在 (errorname1,errorname2) 里面时,执行通过

pcharm

创建目录和包的区别

  目录:Directory

  包:Python Package

    包的路径下多了一个init文件,这个文件可以让包里的内容被其它地方调用到


程序员灯塔
转载请注明原文链接:自动化学习笔记二:Pytest
喜欢 (0)