PyTest


一、简介
单元测试框架
测试发现
测试执行
测试判断(断言判断预期记过和实际结果的差异)
测试报告(进度,耗时,通过率)
自动化测试框架∈单元测试框架
pytest可以和selenium,requests。appium结合实现web自动化,接口自动化, app自动化
pytest-html:生成html的自动化测试报告
pytest-xdist:测试用例分布式执行,多cpu分发
pytest-ordering:改变测试用例执行顺序
pytest-rerunfailures:用例失败后重跑
  • -reruns times --reruns-delay time
allure-pytest:用于生成测试报告
pytest-repeat
  • -count=2 --repeat-scope=module
二、默认测试用例规则以及基础应用
  1. 模块名必须以test_开头或者_test结尾
  1. 测试类必须以Test开头,并且不能有init方法
  1. 测试方法必须以test开头
三、运行方式
  1. 主函数方式
  • 运行所有:pytest.main()
  • 运行指定模块:pytest.main(["参数","运行模块"])
  • 指定目录:pytest.main(["参数","./test_1.py"])
  • 通过nodeid:pytest.main(["参数","./test_1.py::Test01::test_04"])
  1. 命令行方式
  • 同主函数方式
  • pytest 参数 运行模块
  1. 通过读取pytest.ini配置文件运行
  • 位置:一般放在项目根目录
  • 编码:ANSI
  • 作用:改变pytest默认行为
  • 运行的规则:主函数和命令行规则都会读取该文件
  • 格式:
[pytest] #命令行参数,用空格分隔 addopts = -vs #测试用例文件夹,可自行配置 testpaths = ./test_ #配置测试搜索的模块文件名称 python_files = test_*.py #配置测试搜索的测试类名 python_classes = Test* #配置测试搜索的测试函数名 python_functions = test #分组 markers = smoke:冒烟用例 usermanage:用户管理
参数详解:
  • s:输出调试信息,包括print打印的信息
  • v:显示更详细的信息
  • vs:两个参数一起使用
  • n:支持多线程或者分布式运行 pytest.main(['-vs','test_01.py','-n=2'])/pytest test_01.py -n 2
  • -reruns NUM:失败用例重跑2次 pytest test_01.py -reruns 2
  • x:只要有一个测试用例失败则所有重跑
  • -maxfail=2:最大失败测试用例就停止
  • k:根据测试用例的部分字符串指定测试用例 pytest -vs /testcase -k 'te'
  • -html 目录+文件名.html:生成报告
四、执行顺序
  1. 默认从上到下执行
  1. @pyrest.mark.run(order=NUM)
五、分组执行(冒烟、分模块执行、分接口和web执行)
  • smoke:冒烟用例
    • @pytest.mark.smoke
pytest -m smoke pytest -m "smoke and/or usermanage" pytest -m "smoke and not usermanage"
六、pytest跳过用例
  1. 无条件跳过
@pytest.mark.skip(reason='想跳过')
2.有条件跳过
@pytest.mark.skipif(age>=18,reason='已成年')
七、前后置(固件、夹具)处理
  1. setup/teatdown,setup_class/teardown_class
def setup():#在每个用例之前执行一次 print("在测试用例之前/之后执行的代码:打开浏览器,加载网页") def setup_class():#在所有用例之前只执行一次 print("在每个类执行前的初始化工作:创建日志对象,创建数据库的连接,创建接口的请求对象") def teardown(): print("在执测试用例之后扫尾的代码:关闭浏览器") def teardown_class(): print("在每个类执行后的扫尾的工作:销毁日志对象,销毁数据库的连接,销毁接口的请求对象")
  1. 使用@pytest.fixture装饰器来实现*部分*用例的前后置
@pytest.fixture(scope="",params="",autouse="",ids="",name="") def my_fixture(): print("这是前置") yield print("这是后置") class Test01(object): """docstring for Test01""" def test_01(self, my_fixture): print("test")
参数详解:
  • scope表示的是作用域:在每个作用域执行一次:function(默认),class,module,package/session
  • params:参数化,支持list[],元祖(),字典{}
  • fixture带['1','2','3']会执行三次
  • autouse=True:自动使用fixture,默认False
  • ids:当使用params参数化时,给每一个值设置一个变量名,意义不大
  • name:给表示的是被@pytest.fixture()标记的方法取一个别名,若起了别名之后,使用原函数名无法调用
传值:
def my_fixture(request): reutrn request.param #注意不带s,一次只传一个,妙啊 def my_fixture(request) print("这是前置") yield request.param print("这是后置") #or: def my_fixture(): return 'a string'
  1. 通过conftest.py和@pytest.fixture()结合使用实现全局的前置应用(比如:项目的全局登录,模块的全局处理)
  • conftest.py是单独存放的一个夹具文件,文件名是不可更改的
  • 可以在不同的py文件中使用同一个conftest.py函数
  • 不需import
总结:
  • setup/teardown,setup_class/teardown_class作用于所有用例或者所有的类
  • @pytest.fixture()作用既可以是部分也可以是全部前后置
  • conftest.py和@pytest.fixture()结合使用作用于全局的前后置
七、断言
  • assert
八、pytest结合allure-pytest插件生成allure测试报告
  1. 生成json格式的临时报告
-alluredir ./temp_path
  1. 生成allure报告
allure generate ./temp_path -o ./report_path --clean
临时json 输出 生成报告路径 清空原有报告
九、@pyrest.mark.parametrize()基本用法
@pyrest.mark.parametrize(args_name,params) @pyrest.mark.parametrize('name',['phil','fitz']) @pyrest.mark.parametrize('name,age',[['phil','18'],['fitz','19']])
十、YAML文件详解--实现接口自动化
  1. 用于全局的配置文件 ini、yaml
  1. yaml简介:
yaml是一种数据格式,支持注释、换行、多行字符串、裸字符串(整型、字符串)
  1. 语法规则:
  • 区分大小写
  • 使用缩进表示层级,但只能用空格
  • 缩进是没有数量的,只要对齐就是同一层级
  • 注释是#
  1. 数据组成:
  • Map对象:键值对:key:+空格+value
    • 一行的写法:msxy:{name:phil,age:18}
  • 数组(list):用-开头
    • 一行的写法:[]
  1. 读取:转化为字典:
class YamiUtil: def __init__(self, yaml_file) self.yaml_file = yaml_file def read_yaml(self): with open(self.yaml_file, encoding='utf-8') as f: value = yaml.load(f, Loader=yaml.FullLoader) return value
十一、yaml接口自动化实战
  1. 断言的封装
  1. allure报告的定制
  1. 关键字驱动和数据驱动结合实现接口自动化测试
  1. python的反射
  1. jenkins的持续集成和allure报告集成,并且根据自动化报告的错误率发送邮件
  1. 文件和读取
      • yaml_file:
      name: 获取token的接口 request: url: https://api.weixin.qq.com/cgi-bin/token method: get headers: - Content-Type: application/json params: - appid: wx6b11b3efd1cdc290 - secret: 106a9c6157c4db5f6029918738f9529d validate: - eq: {expires_in: 7200}
      • test_Api.py:
      import pytest import requests class TestApi(): @pytest.mark.parametrize('args', YamiUtil(yaml_file).read_yaml()) def test_01(self, args): url = args['request']['url'] params = args['request']['params'] res = request.get(url, params=params) assert args['validate']['expires_in'] in res.text
 

Robot Framework


一、基础
  1. RF项目文件夹
  • 项目文件夹(project)
  • 用例集(suite.robot)
  • 测试用例(test case)
  1. 设置区域
***Setting*** Doucument:添加用例说明 Suite Setup:执行此测试套件的前置操作,如初始化数据等, Suite TearDown;执行此测试套件结束后的操作,如恢复数据等。 Setup:执行用例的前置操作。 Test TearDown:执行用例结束后的操作。 Force Tags:用例标签,suite中的标签会给该测试套件下的所有Test Case增加Force Tags Timeout;设置每一个测试案例的超时时间,只要超过这个时间就会失败,并停止案例运行。防止某些情况导致案例一直卡住不动,也不停止也不失败。 Template:测试模版,可以指定某个关键字为这个测试套件下所有TestCase的模版,这样所有的TestCase就只需要设置这个关键字的传入参数即可。1(TestCase中使用) Arguments:传入参数(NewUser Keyword使用) Return Value:返回值(New User Keyword 使用) ***import*** Add Library:加载测试库,主要是PYTHON目录\Lib\site-packages里的测试库 Add Resource:加载资源,主要是你工程相关的资源文件 Add Variables:加载变量文件 ***Variables*** Add Scalar:定义变量 Add List:定义列表型变量 Add Dict:定义字典专注成就品质 ***Metadata*** Add Metadata:定义元数据。(作用是在report和log里显示定义好的内容,格式和document一样。)
  1. RF关键字驱动
  • 用一个关键字完成某一个功能,以期望解决我们的问题
  1. 数据类型
  • 需要的库Collections
    • 变量
    • ${x1} = set variable 123456 // 赋值 ${x1} // 调用
    • 数组
    • @{list}= create list 1 2 list:${list[0]} Append To List ${list} value1 value2 Remove From List ${list} index Remove Values From List ${list} value
      调用接口传参数的时候,可以用数组
    • 字典
    • &{map}= create dictionary x=1 y=2 map:${map["x"]} Set To Dictionary ${map} z=3 Remove From Dictionary ${map} z Pop
    • json
    • New User Keyword Name:xxx Arguments:${arg1}|${arg2}=2(defaultvalue)|@{list}
  1. 分支和循环
  • 条件运算
  • 比较:
    • 数值比较:> < ==
    • 字符串比较:
    Run Keyword If 条件 做什么... ELSE 做什么
    • 字符串操作变量也要加引号
      Run Keyword And Countinue On Failure
      • 判断包含
        • should contain ${s1} ${s2} msg="Yes" msg="No" # or ${res}= evaluate '${s1}'.__contain__('${s2}')
      • 循环
        • :FOR ${i} IN ${list} 做什么 再做什么
        run keyword if ${i}>3 Exit for loop @{key}= Get Dictionary Keys ${map} :FOR ${i} IN ${key} ${map['${i}']} 做什么 再做什么 run keyword if ${map['${i}']}>3 Exit for loop
        1. 字符串处理
        • 直接写 不用+号
          • 或Catenate SEPARATOR(两个字符串中间间隔)=---
        二、接口自动化
        1. 软件测试阶段
          1. 单元测试、集成测试、系统测试、回归测试
            探索性测试:针对接口验证是否成功发包,即可自动化
        1. 用例内容要包括输入参数集合
        1. 怎么做接口测试
        • 初始化测试数据
        • 发包收包
        • 断言,校验结果
        • 分析原因(自动化做不了)
        1. RF接口自动化
        badge