Pytest学习

0 自动化测试框架

自动化测试框架中的组成部分:

  • 单元测试框架
  • pom设计模式
  • 数据驱动
  • 关键字驱动
  • 全局配置文件的封装
  • 日志监控
  • selenium,requests二次封装
  • 断言
  • 报告邮件
  • ...

单元测试框架

  • 单元测试:针对软件的最小单位(函数、方法)进行正确性的检查测试
  • 单元测试框架:
    • java:junit和testing
    • python:unittest和pytest
  • 单元测试框架
    • 测试发现:从多个py模块文件中找到测试用例
    • 测试执行:按照一定的顺序和规则执行
    • 测试判断:通过断言判断预期结果和实际结果的差异
    • 测试报告:统计测试结果(耗时、通过率等)

1 Pytest简介

1 pytest是一个非常成熟的python的单元框架,比unittest更灵活,容易上手。
2 pytest可以和selenium , requests,appium结合实现web自动化,接口自动化, app自动化。
3 pytest可以实现测试用例的跳过以及reruns失败用例重试。
4 pytest可以和allure生成非常美观的测试报告。
5 pytest可以和Jenkins持续集成。
6 pytest有很多非常强大的插件,并且这些插件能够实现很多的实用的操作。
        pytest
        pytest-html                生成htm格式的自动化测试报告
        pytest-xdist               测试用例分布式执行 多CPU分发
        pytest-ordering         用于改变测试用例的执行顺序
        pytest-rerunfailures  用例失败后重跑
        allure-pytest              用于生成美观的测试报告
        使用这些插件时,可以集中放到 requirements.txt 文件中
        在通过命令进行一次性安装所有插件 pip install -r requirements.txt

2  Pytest的规则

模块名必须以test_开头或_test结尾

测试类必须以Test开头,并且不能有init方法

测试方法必须以test开头

3 Pytest测试用例的运行方式

默认为串行方式执行每个测试用例

1.主函数模式
(1)运行所有: pytest.main()
(2)指定模块: pytest.main(["-vs","-n","2","test_ login.py"])
(3)指定目录: pytest.main(["-s","--maxfail=2","./Intertace. testcase"])
(4)通过nodeid指定用例运行: nodeid由模块名,分隔符,类名,方法名,函数名组成。
pytest.main("-vs.","./interface_testcase/test_interface.py::test_04_func")
pytest.main("-vs","./interface_testcase/test_interface.py::TestInterface.test 03_ zhiliao")

2.命令行模式
(1)运行所有: pytest
(2)指定模块: pytest -vs test_ login.py
(3)指定目录: pytest -vs ./interface_ testcase

参数详解:
-s        表示输出调试信息,包括print打印的信息
-v        显示更详细的信息
-vs       这两个参数一起用
-n        支持多线程或者分布式运行测试用例(并行),如 pytest -vs ./test_ login.py -n 2
--reruns NUM         失败用例会跑NUM次
-x                            表示只要一个用例报错,那么测试停止
--maxfail NUM        出现NUM个用例失败就停止
-k                            根据测试用例的部分字符串指定测试用例
                               如 pytest -vs ./testcase -k "ao"   

3.通过pytest.ini配置文件运行

4 Pytest测试用例的执行顺序

Unittest测试用例的执行顺序是按名称ASCII码值大小来执行的

Pytest默认从上到下顺序执行

Pytest改变执行顺序,通过@pytest.mark.run()方法

@pytest.mark.run(order=1)

5 pytest.ini配置文件

pytest.ini配置文件一般放在项目的根目录,编码一般为ANSI(在不同的系统中,ANSI表示不同的编码),pytest.ini配置文件可以改变pytest的默认行为,不管是何种运行方式,都会读取该pytest.ini配置文件。

5.1 改变pytest命名规则

配置项如下(注意实际使用时请去除中文注释

[pytest]
#命令行参数,用空格分开
addopts = -vs
#测试用例文件夹
testpaths = ./TestCase
#配置测试搜索的模块文件名称
python_files = test*.py
#配置测试搜索的测试类名称
python_classes = Test*
#配置测试搜索的测试方法名
python_functions = test

示例:只执行test_01开头的测试用例方法

 结果运行如下,仅执行test_01开头的测试用例方法

5.2 改变pytest执行策略

小知识:python装饰器

实质:    是一个函数

    参数:是你要装饰的函数名(并非函数调用

    返回:是装饰完的函数名(也非函数调用

    作用:为已经存在的对象添加额外的功能

    特点:不需要对对象做任何的代码上的变动

5.2.1 markers配置项进行分组执行

通过markers配置项,可以进行分组

[pytest]
addopts = -vs
testpaths = ./TestCase
python_files = test*.py
python_classes = Test*
python_functions = test
markers =
    smoke:冒烟用例
    login:登录管理模块
    user:用户管理模块

示例:只执行smoke的用例(冒烟用例)

(1) 首先通过@pytest.mark.smoke装饰冒烟用例方法,其中 smoke 可以是任意值,和 markers 的配置一致即可!

(2) 再执行命令, 通过 -m 参数指定执行的组

pytest -vs ./TestCase -m smoke

 其中 -m 参数指定的值支持or and 运算符,如下命令表示执行由smoke或者login修饰的测试用例

pytest -vs ./TestCase -m "smoke or login"

5.2.1 指令跳过

(1) 无条件指令跳过

        通过 @pytest.mark.skip(reason="xxx") 装饰器修饰

(2) 条件指令跳过

        通过 @pytest.mark.skipif(condition,reason="xxx") 装饰器修饰,例如         @pytest.mark.skipif(age>=18,''已成年")

6 报告生成

使用 pytest-html 插件

使用命令: --html 报告输出位置

示例: 

 

使用allure-pytest插件 

注意:除了使用pip或pip3安装了allure-pytest插件外,还需要安装allure命令行工具

allure命令行工具(windows下载zip包即可):Releases · allure-framework/allure2 · GitHub

解压allure命令行工具后,记得配置对应allure的路径bin到系统环境变量里

使用allure步骤如下:

(1)使用 --alluredir 输出文件夹名称 

[pytest]
addopts = -vs --alluredir allure
testpaths = ./TestCase
python_files = test*.py
python_classes = Test*
python_functions = test
markers =
    smoke:冒烟用例
    login:登录管理模块
    user:用户管理模块

(2)此时运行后,在当前目录下新增一个allure文件夹,其下生成了很多json文件

(3)将json文件生成报告命令:allure generate ./allure -o ./report --clean

import os
import pytest

if __name__=='__main__':
    pytest.main()
    os.system('allure generate ./allure -o ./report --clean')

-o 指定输出报告的位置

--clean 表示清空原来报告目录下的文件

(4)点击report目录下的index.html进入,可查看详细报告

7 setup teardown setup_class teardown_class 实现每个/全部用例的前后置方法

setup()              每个测试用例执行之前会执行的方法

teardown()        每个测试用例执行之后会执行的方法

示例

  • setup_class()
    • 所有测试用例执行之前会执行的方法,比如创建日志对象,创建数据库的连接,创建接口的请求对象
  • teardown_class()
    • 所有测试用例执行之后会执行的方法,比如销毁日志对象,销毁数据库的连接等

示例

8 fixture装饰器实现`部分`测试用例的前后置

使用@pytest.fixture()装饰器来实现`部分`测试用例的前后置

@pytest.fixture(scope="",params="",autouse="",ids="",name="")
  • scope
    • 表示的是被@pytest.fixture()装饰器修饰的方法的作用域,值有function(默认)、class、module、package、session  
      • function ---每一个函数或方法都会调用
      • class     ---每一个类调用一次,一个类中可以有多个方法
      • module  ---每一个.py文件调用一次,该文件内又有多个function和class
      • session ---是多个文件调用一次,可以跨.py文件调用,每个.py文件就是module
  • params
    • 参数化
    • 支持 列表、元素、字典列表[{},{},{}...]、字典元组({},{},{}...)
  • autouse 
    • 默认为false,值为true表示自动使用,此时所有测试用例都会使用被@pytest.fixture()装饰器修饰的方法
  • ids
    • 当使用params参数化时,给每一个值设置一个变量名
  • name
    • 给被@pytest.fixture()装饰器修饰的方法取一个别名

示例1:前后置方法,用 yield ,yield前是前置,yield后是后置

示例2:autouse参数为true,所有测试用例都会使用该fixture装饰器的修饰的方法

示例3:返回值

示例4:

参数化,方法接收params数据,必须要用request

params里面个数为用例执行的次数

示例5:idx设置参数名称

示例6:name设置别名,注意设置了name的值后,原名称不可用

 9 conftest.py和@pytest.fixture()结合使用实现`全局`的前后置

conftest.py文件单独存放的一个夹具配置文件,名称必须是conftest

conftest.py提供的fixture函数,可以供当前目录下及子目录下的py文件中使用

示例1:

在conftest.py里定义一个fixture函数

 在测试用例方法调用fixture函数

示例2:使用多个conftest.py里的方法,调用时从右到左,如下图所示

先执行all_fixture的前置

再执行login_fixture的前置

再执行login_fixture的后置

再执行all_fixture的后置

10 断言

assert

  • assert xx 判断xx为真
  • assert not xx 判断xx不为真
  • assert a in b 判断b包含a
  • assert a == b 判断a等于b
  • assert a != b 判断a不等于b
  • ...

11 YAML数据驱动的封装

@pytest.mark.parametrize(args_name,args_value)

args_name        参数名

args_value        可以是列表、元组、字典列表、字典元组,接口用例数量和其长度一致

示例1:多个参数

YAML详解

-                                 表示列表

键(冒号)(空格)只        表示字典

YAML数据类型示例 

              

示例:

目录清单

 (1)编写数据(test_data.yml文件)

-
  name: liuc01
  request:
    method: get
    url: 127.0.0.1
    data:
      id: 45673
      secret: jadgierg892hgag
  validate: None
-
  name: liuc02
  request:
    method: get
    url: 127.0.0.1
    data:
      id: 45673
      secret: jadgierg892hgag
  validate: None
-
  name: liuc03
  request:
    method: get
    url: 127.0.0.1
    data:
      id: 45673
      secret: jadgierg892hgag
  validate: None

(2)编写读取yaml数据的方法(yaml_util.py文件)

import os
import yaml
class YamlUtil:
    #读取测试用例数据
    def read_test_data_yaml(self,yamlname):
        with open(os.getcwd()+"/TestData/"+yamlname,mode="r",encoding="utf-8") as f:
            value = yaml.load(stream=f,Loader=yaml.FullLoader)
            return value

(3)测试用例

import pytest

from common.yaml_util import YamlUtil


class TestLogin:
    @pytest.mark.parametrize('testdata',YamlUtil().read_test_data_yaml('test_data.yml'))
    def test_01_success(self,testdata):
        print("Login01 Success")
        print(testdata)

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

运行结果:


END 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值