# Interface auto **Repository Path**: chi_queen/interface-auto ## Basic Information - **Project Name**: Interface auto - **Description**: 接口自动化,主要是pytest+allure框架的学习与实战 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2022-12-20 - **Last Updated**: 2023-01-04 ## Categories & Tags **Categories**: Uncategorized **Tags**: 接口自动化项目 ## README ## PyTest框架 > PyTest:是python中一种单元测试框架 ###### 为什么使用pytest框架 1. 能够组织多个用例去执行 2. 方便实现参数化 3. 能够生成测试报告 ### 1. pytest的使用 ##### 1. 文件夹介绍 * common:存在公用的一些工具类 * data:存放json数据 * scripts:存放测试脚本 ##### 2. 编写测试用例 1. 测试模块单独文件,定义一个类,类以Test开头 2. 测试方法,以小写test开头 ##### 3. 执行测试用例 ###### 命令行执行 `pytest -s 文件路径 ##### 4.批量执行测试代码 > **使用配置文件,实现代码批量运行** > > 说明:使用配置文件后可以快速的使用配置的项来选择执行哪些测试模块 > > 使用配置文件后,运行命令可以直接使用pytest,不需要加其他参数和文件路径 ###### 使用步骤 1. 项⽬下新建 `scripts` 包 2. 将测试脚本⽂件放到 `scripts` 中 3. pytest 的配置⽂件放在⾃动化项⽬**根⽬录**下 4. 名称为 `pytest.ini` 5. 命令⾏运⾏时会使⽤该配置⽂件中的配置 ###### ini文件说明 ```python # 第⼀⾏内容为[pytest] [pytest] # 添加命令⾏参数 addopts = -s # ⽂件搜索路径 testpaths = ./scripts # ⽂件名称 python_files = test*.py # 类名称 python_classes = Test* # ⽅法名称 python_functions = test* ``` ### 2. 断言:`assert` 1. assert断言:让程序代替人为判断测试程序执行结果是否符合预期结果的过程 2. 目的: * 提高测试效率 * 实现自动化测试(人脚步在无人值守的状态下运行) 3. 使用`assert`进行断言 * assert断言成功,测试用例就会通过,不会有任何的提示 * assert断言失败,测试用例不会通过,并有详细的错误原因 ### 3. setup 和(前置后后置方法):Fixture 当有些操作需要在⽅法前后运⾏时, 可以放在前置和后置⽅法中 1. 对⼀个测试⽤例的前置处理和后置处理, 需要实现特定的⽅法 * 通常在前置的⽅法⾥, 进⾏⼀些准备⼯作. 打开浏览器\打开⻚⾯\读取测试数据\连接数据库 * 通常在后置的⽅法⾥, 进⾏⼀些收尾⼯作. 关闭浏览器\关闭⻚⾯\删除测试数据\关闭数据库 2. 控制级别: 1. ⽅法级别 2. 类级别 ##### 方法级别 ```python # 使用方式 # 前置处理:首先自动执行 def setup(self): 在 每个 普通测试方法执行之前,自动被调用一次 pass # 后置处理:最后自动执行 def teardown(self):在 每个 普通测试方法执行之后,自动被调用一次 pass # ``` **总结:运行于测试方法的始末,即:运行一次测试方法就会运行一次setup 和teardown** ##### 类级别 ```python # 使用方式 # 前置处理:首先自动执行 def setup_class(self): 在 类中所有 测试方法执行之前,自动被调用一次 pass # 后置处理:最后自动执行 def teardown_class(self): 在 类中所有 测试方法执行结束之后,自动被调用一次 pass ``` **总结:运行与测试类的始末,即:每个测试类只会执行一次setup_class和teardown_class** ### 4. 参数化 参数化:通过参数的方式来传递数据,从而实现数据和脚本的分离,并且可以实现用例的重复执行 #### 1. 方式一 > ```python > # argnames:参数名,以字符串的形式填写,可以直接从方式的参数拷贝 > # argvalues:参数对应值,类型必须为可迭代类型,一班为list:[(),(),(),()] > @pytest.mark.parametrize(argnames, argvalues) > > def test_method(self,x,y): > > pass > ``` #### 2. 方式二:脚本分离 > 参数化, 标准⽽⾔, 应该将数据和脚本进⾏分离 > > 1. data.json: 专⻔存放测试数据 > 2. read_data.py: 专⻔读取JSON数据 > 3. test*.py: 专⻔进⾏脚本代码的编写 ##### 路径问题: **注意:j加载json不建议使用相对路径,容易出错** ###### 解决方案 通常需要使⽤⼀个python⽂件, 来获取到⽂件的绝对路径, 然后在读取json⽂件的地⽅, 追加⽂件路径 ```python import os BASE_DIR = os.path.dirname(__file__) print(BASE_DIR) ``` ### 5.测试报告 #### 5.1 pytest-html生成测试报告 #### 1. 基本操作 HTML测试报告:就是执⾏完测试⽤例后,以HTML(⽹⻚)⽅式将执⾏结果⽣成报告 说明: pytest-html是PyTest框架⽣成HTML测试报告的插件 1. 使⽤前需要先安装 安装:`pip install pytest-html / pip3 install pytest-html` 2. 修改配置:`addopts = -s --html=report/report.html --self-contained-html` --self-contained-html 只⽣成⼀个html⽂件, 不要⽣成⽂件夹了 3. pytest --help 查看帮助⽂档 #### 5.2 pytest+allure生成测试报告 见pdf ### 6. 跳过测试用例 **在我们自动化测试过程中,经常会遇到功能阻塞、功能未实现、环境等一系列外部因素问题导致的一些用例执行不了,这时我们就可以用到跳过skip用例,如果我们注释掉或删除掉,后面还要进行恢复操作** 1. `pytest.mark.skip` 装饰器可以标记无法在某些平台上运行的测试功能,或者希望失败的测试功能,使其跳过。 ## 库 ### 1. Requests库 1. 安装库 ```shell pip intall reqursts ``` #### 使用 ##### 设置http请求 ```yacas resp = resqursts.请求方式(url=“请求地址”,param={k:v},headers={k,v}, data={k:v},json={k,v},cookires='cookir数据(如:令牌)') 请求方式: get请求- get方法 post请求- post方式 put请求 - put方法 delete请求 - delete url:要访问的地址 - string类型 params:查询参数 - 字典 header:请求头 - 字典 data:表单,格式请求体数据 - 字典 json:json 格式请求体数据 - 字典 cookies:用来传递cookies【了解】 resp:代表响应结果 ``` ##### 获取指定响应数据 **常用** * 获取URL:`resp.url` * ==获取响应状态码:`resp.status.code`== * 获取Cookie:`resp.cookies` * 获取响应头:`resp.headers` * 获取响应体: * 文本格式:resp.text * ==json格式:resp.json()== * 如果看到`JSONDecodeError`错误提示,说明不能转换为json ## Cookie ### Cookie的简介 - ookie 是工程师,针对 http协议 是无状态这一特征,设计的一种技术。 - cookie 将数据保存在浏览器端。默认存储空间大小为 4k(可以修改)。 - cookie 中的数据,用户和随意获取,没有安全性可言。 - cookie 中存放的数据类型,受浏览器限制。 - cookie 中大多存放于网络通信相关的不敏感数据信息。提高访问速度。如:用户名、登录状态等。 ### Cookie +Session认证方式 * **校验用户身份的方法:** - **令牌校验 - ihrm项目** - **cookie+session - tpshop商城** ![cookie和session认证方法](README.assets/cookie和session认证方法.png) ## Session ### Session简介 **概念: 叫 会话!从客户端登录服务器开始,直到客户端退出登录,所产生的所有通信数据,保存在 session 中** * **session将数据保存在服务器中** * **session 使用服务器存储空间,没有大小限制** * **session 支持的数据类型,受服务器主机影响。几乎支持所有的数据类型** * **session 中的数据,大都采用加密,转码。安全性较高** ### Session 自动管理 Cookie **因为,cookie中的数据,都是由session提供的** ##### 案例 > 借助 session 重新实现 TPshop商城登录,并获取 “我的订单” 页面数据。 > > 获取验证码:http://tpshop-test.itheima.net/index.php?m=Home&c=User&a=verify > 登录:http://tpshop-test.itheima.net/index.php?m=Home&c=User&a=do_login > 我的订单:http://tpshop-test.itheima.net/Home/Order/order_list.html **实现步骤:** 1. **创建 session 实例。session = requests.Session()** 1. **使用 session 实例 发送 获取验证码 get 请求。( 不需要提取 cookie )** 1. **使用 同一个session 实例 发送 登录 post 请求。( 不需要携带 cookie )** 1. **使用 同一个session 实例 发送 查看我的订单 get请求。( 不需要携带 cookie )** ```python # 1. 导包 import requests # 2. 创建 session 实例 session = requests.Session() # 3. 借助 session实例,发送 获取验证码 get请求,指定url(不需要提取cookie) session.get(url="http://tpshop-test.itheima.net/index.php?m=Home&c=User&a=verify") # 4. 借助 同一个session实例,发送 登录 post请求,指定 url、请求头、请求体(不需要携带cookie) resp2 = session.post(url="http://tpshop-test.itheima.net/index.php?m=Home&c=User&a=do_login", data={"username": "13812345678", "password": "123456", "verify_code": "8888"}) print("登录结果:", resp2.json()) # 5. 借助 同一个session实例,发送 查询我的订单 get请求,指定 url(不需要携带cookie) resp3 = session.get(url="http://tpshop-test.itheima.net/Home/Order/order_list.html") print("我的订单:", resp3.text) ``` ### 面试题:Cookie和Session 1. 数据存储位置 * Cookie 存储在 浏览器端 * Session 存储在 服务器端 2. 安全性 * Cookie 直接存储在浏览器, 可以任意获取,没有安全性可言 * Seesion 存储在 服务器端,采用 加密,转码形式存储数据,安全性较高。 3. 数据类型 * Cookie 直接存储在浏览器,支持测试数据类型受浏览器限制 * Session 存储在 服务器端,服务就是一条主句,因此几乎支持所有的数据类型 4. 大小 * Cookie默认大小4k * Session 直接使用服务器存储。没有大小限制 ## PyMysql 安裝:`pip install PyMySQL` ### 1. 操作数据库的基本流程 #### 1. 导包 ```python import pymysql ``` #### 2. 创建数据库连接 ```python conn = pymysql.connect(host=None,user = None,password="",database= None,port =0,charset = "") ``` **参数说明** * host : 数据库服务器连接地址 * user : 登录用户名 * password : 密码 * database : 要连接的数据库名称 * port : 数据库连接断开(默认值3306) * charset :字符集(设置为utf-8) #### 3. 获取游标对象 ```python cursor = conn.cursor() ``` **说明** * 调用数据库连接对象的cursor()方法获取游标对象 #### 4. 执行增删改查操作 ```python cursor.execute(sql) ``` **说明** * 调用游标对象的execute()方法来执行SQL语句 * sql:要执行的sql语句 #### 5. 关闭游标对象 ```python cursor.close() ``` #### 6. 关闭数据库连接 ```python conn.close() ``` **说明** * 调用数据库连接对象,游标对象的close()方法来释放资源 ### 2. 数据库操作 #### 1. 查询 ##### 常见fetch*()方法 * **fetchon()** : 获取结果集中的下一行数据,返回元组数据 * **fetchmany(size)** : 获取结果集中指定size行数据,返回值:`((),(),..` * **fetchall() ** : 获取结果集中所有行数据,返回值为:`((),(),...)` ##### 其他方法 * **rowcount()** : 获取结果集中的总记录数 * **rownumber()** ### 2. 增删改 ![数据库-增删改](README.assets/数据库-增删改.png) #### 思路 ```yacas 1.导包 try: 程序前期,需要执行的代码 2.创建连接对象 3.获取游标对象 4.执行sql + 在图书表中插入一行数据 + 主动抛出异常 + 在英雄人物表中插入一行数据 调用提交事务:conn.commit() except: 程序出现异常后,处理代码 调用事务回滚:conn.rollback() finally: 程序结束时,需要执行的代码 5.关闭游标 6.关闭连接 ``` 代码实现: ```python import pymysql import traceback conn = pymysql.connect(host="211.103.136.244", port=7061, user="student", password="iHRM_student_2021", database="test_db", charset="utf8") cursor = conn.cursor() try: # sql_i = "insert into t_book(id, title, pub_date) values(5, '西游记', '1986-01-01')" # sql_u = "update t_book set `read` = `read` + 1 where title='西游记'" sql_d = "delete from t_book where title='西游记'" cursor.execute(sql_d) conn.commit() except Exception as e: conn.rollback() raise e finally: cursor.close() conn.close() ``` #### 操作 * 自动提交(不推荐):`autocommit = True` * 手动提交(推荐): * 提交事务:`conn.commit()` * 回滚事务:`conn.rollback`