[Selenium Web UI自动化测试笔记-pytest]

pytest是python的一种单元测试框架,与python自带的unittest测试框架类似,但是比unittest框架使用起来更简洁,效率更高

a. 特点

  1. pytest是python当中的一个单元框架,比unittest更灵活
  2. pytest和selenium,requests,appium结合实现web自动化,接口自动化,app自动化
  3. pytest可以实现测试用例的跳过以及reruns失败用例重试
  4. pytest可以和allure生成非常美观的测试报告
  5. pytest可以和Jenkins持续集成

b. pytest插件

  1. pytest
  2. pytest-html 生成html格式的自动化测试报告
  3. pytest-xdist 测试用例分布式执行,多CPU分发
  4. pytest-ordering 用于改变测试用例的执行顺序
  5. pytest-rerunfailures 用例失败后的重跑
  6. allure-pytest 用于生成allure的报告

c. pytest插件安装

  1. 全局安装, 这里以windows为例,首先需要安装好python环境, 然后设置pip为全局环境变量,新建一个requirements.txt,将所有插件按顺序复制到txt文档中,然后打开cmd运行 pip install -r 绝对路径\requirements.txt来安装插件即可
  2. 虚拟环境安装(具体可以网上搜一下如何创建虚拟环境),然后使用相同的命令安装,这时候这些插件就只能作用于当前工作目录

d. pytest使用规则

  1. 模块名必须以test_开头或者_test结尾
  2. 测试类必须以Test开头,并且不能有init方法
  3. 测试方法必须以test开头

e. pytest测试用例运行模式

  1. 运行所有 pytest.main()
  2. 指定模块 pytest.main([‘-vs’, ‘module’]) # 模块为可选,如果没有默认运行当前项目下的所有用例
  3. 指定目录 pytest.main([‘-vs’, ‘./path’]) # 运行的主脚本需要在整个项目根目录下,然后指定目录
  4. 通过nodeid指定用例运行: nodeid由模块名,分隔符,类名,方法名,函数名组成
    例: pytest -vs ./目录/xx.py ::类名::方法名 # 4方法不常用

示例:

pytest.main()                                 # 运行所有
pytest.main(['-vs', 'test_module'])           # 运行指定模块
pytest.main(['./test_path'])                  # 运行指定目录
  1. 运行所有 pytest
  2. 指定模块 pytest -vs xx.py #模块为可选,如果没有默认运行当前项目下
  3. 指定目录 pytest -vs ./目录 #运行的主脚本需要在整个项目根目录下,然后指定目录
pytest                            # 运行所有
pytest xx.py                      # 运行指定模块
pytest './test_path'              # 运行指定目录

pytest.ini 是pytest单元测试框架的核心配置文件
1. 位置: 一般存放在项目的根目录
2. 编码:必须是ANSI, 可以用Notepad++修改编码格式
3. 作用:改变pytest默认的行为, 例如文件名可以不以Test_开头,类名,函数名皆可
4. 运行的规则:不管是主函数模式运行,还是命令行运行模式,都会去读取这个配置文件。
5. pytest.ini格式:
[pytest]
addopts = -vs # 命令行参数, 用空格分隔,可选
testpaths = path # 测试用例文件夹,可自己配置,可选
python_files = .py # 配置测试搜索的模块文件名称,可选
python_classes = class_name ​​# 配置测试搜索的测试类名,可选
python_functions = test_
# 配置测试搜索的测试函数名,可选
注: 配置文件中不要保留中文,这里只是注释,编码ANSI会乱码

-s: 表示输出调试信息,包括print打印的消息
-v: 显示更详细的信息
-vs: 两个参数可以一起使用
-n process_num: 支持多线程或者分布式运行用例 # 需要插件pytest-xdist
–reruns num:用例失败后重新执行 # 需要插件pytest-rerunfailures
-x:表示只要一个用例报错则测试停止
–maxfail=2: 出现两个用例失败就停止
-k: 根据测试用例的部分字符串指定测试用例
–html xxx.html:生成html的测试报告

f. pytest执行顺序

  1. pytest 默认执行顺序是自上而下
  2. 通过装饰器 @pytest.mark.run(order=1)来指定顺序,当有多个装饰器指定顺序一样时,按照自上而下执行,此装饰器需要安装插件pytest-ordering

g. 分组执行 markers

markers是pytest里面用于区分测试用例的标签,主要有两种使用方法

  1. 命令行模式 pytest -vs -m “标签名”
  2. pytest.ini文件中增加 markers[标签名: 标签说明]
    [pytest]
    …… # 前面内容省略
    markers:
    label1:标签说明
    label2:标签说明

示例:

import pytest

class TestCase:
    @pytest.mark.label1
        xxxx

    @pytest.mark.label2
    def test_02(self):
        xxxx

命令行执行: pytest -vs -m “label” or pytest -vs -m “label1 or label2”
如果使用pytest.ini 则直接pytest -vs即可

h. 跳过测试用例

@pytest.mark.skipif(condition, reason)

示例:

age =18
@pytest.mark.skipif(age >=18, reason ='已成年')
def xxx(self):
    xxx

#条件达成True,跳过测试用例,反之false,执行用例

无条件跳过

@pytest.mark.skipif(reason)

@pytest.mark.skipif('理由')
@pytest.mark.skipif(reason ='理由')

两种方式皆可

i. pytest测试夹具(前置后置)

import pytest

class Test:
    def setup(self):
        print('测试用例执行前执行:打开浏览器')

    def test_01(self):
        print('测试用例一')

    def teardown(self):
        print('测试用例执行后执行: 关闭浏览器')
import pytest

class Test:
    def setup_class(self):
        print('在每个类执行前的初始化操作: 比如创建日志对象,创建数据库链接')

    def test_01(self):
        print('测试用例一')

    def teardown_class(self):
        print('在每个类执行后的扫尾操作: 比如销毁日志对象,关闭数据库链接')

@pytest.fixture(scope=”, params=”, ids=”, names=”, autouse=False)

scope

1. function

@pytest.fixture(scope=’function’)# 类似于setup/teardown

import pytest

@pytest.fixture(scope='function')
def my_fixture():
    print('这是前后置方法,可以实现部分以及全部用例的前后置')
    yield
    print('后置测试方法, 用例执行完之后执行')

class Test:
    def test_01(self, my_fixture):
        print('测试一')

示例​​​​​​​

@pytest.fixture(scope=’function’,autouse=True)
下面用例就无需添加my_fixture ,每个用例执行前后都会执行my_fixture函数, autouse= False则不执行

import pytest

@pytest.fixture(scope='function', autouse=True)                     #类似于setup/teardown
def my_fixture():
    print('这是前后置方法,可以实现部分以及全部用例的前后置')
    yield
    print('后置测试方法, 用例执行完之后执行')

class Test:
    def test_01(self):
        print('测试一')

结果: 在用例执行前后执行my_fixture函数

2. class

@pytest.fixture(scope=’class’,autouse=True) # 类似于setup_class/teardown_class
scope为class的时候,必须配autouse=True,因为autouse默认是False,不附上则不执行

import pytest

@pytest.fixture(scope='class', autouse=True)
def my_fixture():
    print('这是前后置方法,可以实现部分以及全部用例的前后置')
    yield           #带yield的函数是一个生成器,附上要return生成内容即可
    print('后置测试方法, 用例执行完之后执行')

class Test:
    def test_01(self):
        print('测试一')

class Test1:
    def test_02(self):
        print('测试二')

结果: 在Test类的前后执行my_fixture函数,如果有多个类,就每个类的前后执行前置后置一次

3. Module

@pytest.fixture(scope=’module’,autouse=True)
scope为module的时候,必须配autouse=True,因为autouse默认是False,不附上则不执行

import pytest

@pytest.fixture(scope='module', autouse=True)
def my_fixture():
    print('这是前后置方法,可以实现部分以及全部用例的前后置')
    yield           #带yield的函数是一个生成器,附上要return生成内容即可
    print('后置测试方法, 用例执行完之后执行')

class Test:
    def test_01(self):
        print('测试一')

class Test1:
    def test_02(self):
        print('测试二')

结果: 在Test类的前和Test1类后执行my_fixture函数

4. package/session

这两种用的比较少,以后用到再更新

params

参数化, 支持 [1. list[],2. tuple(),3. list_dict[{},{},{}],4. tuple_dict({},{},{}) ]

import pytest

@pytest.fixture(scope='function', params=['年','月','日']) #params是参数名
def my_fixture(request):                        #request为固定写法
    return request.param                        #param是属性名

class Test:
    def test_01(self, my_fixture):
        print('测试一')
        Print('----------' + str(my_fixture))   #这里需要强制转换成str
import pytest

def my_fixture(request):
    print('前置')
    yield request.param     #return和yield都表示返回的意思,但是return后面不能有代码,但yield可以
    print('后置')

ids

使用params参数化时,给每一个值设置一个变量来替换结果中输出的unicode
@pytest.fixture(scope=’function’, params=[‘年’, ‘月’ ,’日’], ids=[‘nian’ ,’yue’ ,’ri’])

name

给表示被@pytest.fixture标记的方法取一个别名
注: 当设置别名后原本的名称就不能再当参数使用了

import pytest

@pytest.fixture(scope='function', name='aaa')

class Test:
    def test_01(self, aaa):
        print('测试一')

autouse

是否自动执行,默认为False,True则自动执行

不常用的另一种方法

conftest.py和 @pytest.fixture 结合使用全局 的前置 应用
conftest.py文件是单独存放的一个夹具配置文件,名称不能修改
可以在不同的py文件中使用同一个fixture函数
原则上 conftest.py和需要调用的用例在同一层目录,无须import操作
可以每个模块全局,也可以整个项目全局,注意这种使用情况的话,调用顺序为先项目全局再模块全局

  1. setup/teardown, setup_class/teardown_class 作用于所有用例或者类
  2. @pytest.fixture() 作用可是是部分也可以全局前后置
  3. conftest.py和@pytest.fixture结合使用,作用域全局的前后置

j. 断言

assert condition

k. pytest+allure测试报告

验证添加是否成功,打开cmd,运行allure –version,查看是否添加成功

命令行模式 pytest -vs –alluredir ./temp
pytest.ini文件
[pytest]
addopts = -vs –alluredir ./temp
…..

allure generate ./temp -o ./report –clean
参数解释
./temp 临时json格式的报告路径
-o 输出output参数
./report 生成allure报告的路径
–clean 清空./report路径原来的报告

l. @pytest.mark.parametrize装饰器

@pytest.mark.parametrize(args_name, args_value),一般有两种用法
args_name: 参数名
args_value: 参数值(list, tuple,list_dict, tuple_dict), 有多个值用例就会执行多次

  1. 第一种用法

传入一个list,然后查看结果,将整个列表 “年 月 日”打印出来

import pytest

class TestApi:
    @pytest.mark.parametrize('args',['年', '月', '日'])        # 传入了一个list
    def test_01(self, args):
        print(args)

if __name__='__main__':
    pytest.main()
  1. 第二种用法

和unittest里面ddt的@unpack解包一致,将两个列表item1,item2依次传入test01用例,结果打印两次分别是”年 月 日”,”小时 分 秒”

import pytest

class TestApi:
    @pytest.mark.parametrize('args, item1, item2', [['年', '月', '日'],['小时', '分', '秒']])
    def test_01(self, args, item1, item2):
        print(args, item1, item2)

if __name__='__main__':
    pytest.main()

m. yaml文件–实现接口自动化

yaml是一种数据格式,支持注释,换行, 多行字符串,裸字符串(整形,字符串),需要安装选择PyYAML插件
1. 用于全局的配置文件 ini/yaml
2. 用于写测试用例(接口测试用例)

区分大小写
使用缩进表示层级,不能使用tab键缩进,只能用空格(和python一样)
缩进没有数量限制,只要前面是对齐的就行
注释也是#

Map对象:
格式:字典键值对
一行写法:
test:{name: ‘名称’, age: ‘年龄’}
多行写法:
test:
name: ‘名称’
age: ‘年龄’

数组:
格式:列表字典键值对
一行的写法

test: [{name: ‘名称’},{age: ‘年龄’}]
多行写法:

test
– name: ‘名称’
– age: ‘年龄’

test1:
– name: ‘名称’
– age: ‘年龄’

yaml文件就以字典键值对为例
test:{name: ‘名称’, age: ‘年龄’},确保文件和脚本在同一目录,这里python运行即可,不要用pytest

import yaml

class YamlUtil:
    def __init__(self, yaml_file):
"""
        通过init方法将yaml文件传入这个类
        :param yaml_file:
"""
        self.yaml_file = yaml_file

    def read_yaml(self):
"""
        读取yaml, 对yaml反序列化, 就是把yaml格式转换成dict格式
        :return:
"""
        with open(self.yaml_file, encoding='utf-8') as file_object:
            value = yaml.load(file_object, Loader=yaml.FullLoader)
            print(value)

if __name__ == '__main__':
    YamlUtil('test_api.yaml').read_yaml()

结果: {‘test’: {‘name’: ‘姓名’, ‘age’: ‘年龄’}

Original: https://blog.csdn.net/weixin_41923467/article/details/122449137
Author: LL-Dynabook
Title: [Selenium Web UI自动化测试笔记-pytest]

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/773828/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球