一、接口自动化概述
二、数据库概述
2.1 概念
- 存储数据的仓库,程序中数据的载体
2.2 分类
-
关系型数据库:安全
-
如mysql,oracle,SQLLite
-
database tables 行+列
-
-
非关系型数据库:高效
-
如redis,mongoDB
-
数据存储结构多样
- 键值对,列表,字符串
-
2.3 数据库和变量都可以存储数据,二者的区别
-
数据库可以持久性存储数据(存到硬盘上)
-
变量不能持久性存储数据,而是运行在内存中
三、Python操作数据库的相关实现
3.1 背景
- 各种编程语言本身不具备直连数据库的功能,必须导入第三方包
3.2 相关实现
-
驱动
-
mysqldb
-
mysqlclient
-
pymysql(重点)
-
四、pymysql实现操作数据库增删改查
4.1 总体介绍
安装:pip install pymysql
校验:pip list (显示安装的包及版本号)
流程:
1、创建一个连接connection,填入数据库配置信息
2、创建一个游标cursor
3、执行sql语句
- cur.execute("sql语句")
- 执行查询语句-fetchall()
- 执行增删改语句-判断是否有异常
有异常:回滚事务(conn.rollback)
无异常:提交事务(conn.commit())
4、关闭游标cursor
5、关闭连接connection
基本框架:
python
# 导包
import pymysql
# 创建连接
conn = pymysql.connect(host='localhost',port=3306,database='api_test',user='root',password='123456',charset='utf8')
# 创建游标
cur = conn.cursor()
# 发送sql语句(核心操作)
# 释放资源
cur.close()
conn.close()
4.2 pymysql操作_查询
python
import pymysql
conn = pymysql.connect(host='localhost',port=3306,user='root',passwd='123456',db='api_test',charset='utf8')
cur = conn.cursor()
cur.execute('select * from t_area')
# fetchall()是输出所有查询信息
fetch = cur.fetchall()
# for i in fetch:
# print(i)
print("所有数据:",fetch)
for row in fetch:
print("每一条数据:",row)
print("id",row[0])
print("区域名称",row[1])
print("优先级",row[2])
print("创建时间",row[3])
print("更新时间",row[4])
# fetchmany(n)是输出n条信息
fetchm = cur.fetchmany(2)
print(fetchm)
# # fetchchone()是逐行输出信息
fetch1 = cur.fetchone()
fetch2 = cur.fetchone()
fetch3 = cur.fetchone()
fetch4 = cur.fetchone()
fetch5 = cur.fetchone()
fetch6 = cur.fetchone()
print("总共多少行信息:",cur.rowcount)
print("第一行信息",fetch1)
print("第二行信息",fetch2)
print("第三行信息",fetch3)
print("第四行信息",fetch4)
print("第五行信息",fetch5)
print("第六行信息",fetch6)
cur.close()
conn.close()
4.3 pymysql操作_增删改
python
import pymysql
conn = pymysql.connect(host='localhost',port=3306,user='root',passwd='123456',db='api_test',charset='utf8')
cur = conn.cursor()
# 增------操作
sql_add = "insert into t_area(area_name,priority) values('四川','1234')"
cur.execute(sql_add)
print("受影响的行数:",cur.rowcount)
# 删------操作
sql_delete = "delete from t_area where area_name = '四川'"
cur.execute(sql_delete)
print("受影响的行数:",cur.rowcount)
# 改------操作
sql_update = "update t_area set area_name = '北京' where priority = '11'"
cur.execute(sql_update)
print("受影响的行数:",cur.rowcount)
# 这里一定要确认,保证安全性
conn.commit()
cur.close()
conn.close()
4.4 pymysql操作_事务
4.4.1 事务概念
一套完整的业务逻辑,在这套业务中可能包含多条sql语句,这些sql语句,要么都成功,要么都失败
4.4.2 事务四大特性
- 原子性
事务中包含的操作被看作一个逻辑单元,这个单元的操作要么都成功,要么都失败
- 一致性
逻辑单元中的操作不应该一部分失败,一部分失败
- 隔离性
事务的中间状态对其他事务是不可见的
- 持久性
指一个事务一旦提交成功,它对数据库中数据的改变应该是永久性的
4.4.3 事务提交机制
-
提交:commit,将修改写入数据库
-
回滚:rollback,拒绝将修改写入数据库
-
方式
-
手动提交
- 连接对象.commit()
-
自动提交
- 创建连接时设置 autocommit=True
-
代码:
python
import pymysql
conn = pymysql.connect(host='localhost',port=3306,user='root',passwd='123456',db='api_test',charset='utf8')
cur = conn.cursor()
# 增------操作
try:
sql_add1 = "insert into t_area(area_name,priority) values('咚咚咚','222')"
sql_add2 = "insert into t_area(area_name,priority) values('嘻嘻嘻','333')"
cur.execute(sql_add1)
cur.execute(sql_add2)
print("受影响的行数:",cur.rowcount)
conn.commit()
except Exception as e:
print("error",e)
# 回滚,拒绝将数据写入
conn.rollback()
cur.close()
conn.close()
4.5 pymysql方法封装
python
"""
实现封装:将pymysql的常见用法实现封装进一个专门工具类
封装的功能:1、获取连接 2、获取游标 3、释放资源
"""
import pymysql
class DBUtils:
@classmethod
def create_conn(cls):
return pymysql.connect(host='localhost',port=3306,user='root',passwd='123456',db='api_test',charset='utf8')
@classmethod
def create_cur(cls,conn):
return conn.cursor()
@classmethod
def close_res(cls,conn,cur):
if cur:
cur.close()
if conn:
conn.close()
@classmethod
def conn_commit(cls,conn):
conn.commit()
封装方法执行查询:
python
from Demo.pymysql_05 import DBUtils
conn = DBUtils.create_conn()
cur = conn.cursor()
sql = "select * from t_area"
cur.execute(sql)
fetch = cur.fetchall()
for row in fetch:
print(row)
DBUtils.close_res(conn,cur)
封装方法执行增删改:
python
from Demo.pymysql_05 import DBUtils
conn = DBUtils.create_conn()
cur = DBUtils.create_cur(conn)
# 增------操作
sql_add = "insert into t_area(area_name,priority) values('四川','1234')"
cur.execute(sql_add)
print("受影响的行数:",cur.rowcount)
# 删------操作
sql_delete = "delete from t_area where area_name = '四川'"
cur.execute(sql_delete)
print("受影响的行数:",cur.rowcount)
# 改------操作
sql_update = "update t_area set area_name = '北京' where priority = '11'"
cur.execute(sql_update)
print("受影响的行数:",cur.rowcount)
DBUtils.conn_commit(conn)
DBUtils.close_res(conn,cur)
五、requests库-模拟接口请求
5.1 概述
概念
- requests库是使用python编写的,可以调用该库的函数直接向服务器发送HTTP请求,并接收响应
角色定位
- 相当于jmeter中的http请求
安装
- pip install requests
校验
- pip list找到对应库及版本号
5.2 基本实现请求
-
GET
-
POST
-
PUT
-
DELETE
四种请求代码实现方式基本一致:
python
import requests
"""
需求:编写Python代码,访问案例,查询area
流程:三要素
1、首先,根据URL定位接口资源
2、然后,提交测试数据
3、最后,发送请求,接收并处理响应结果
"""
# 1、get请求
response_get = requests.get("http://localhost:1234/area/listarea")
# 打印结果
print("状态码:",response_get.status_code)
print("响应体:",response_get.text)
# 2、post请求
data = {"areaName":"加利福尼亚","priority":"222"}
# 传递参数:data是键值对,json是josn字符串
response_post = requests.post("http://localhost:1234/area/addarea",data=data)
# 打印结果
print("状态码:",response_post.status_code)
print("响应体:",response_post.text)
# 3、put请求
JSON = {
"areaId":"1",
"areaName":"华盛顿",
"priority":"666"
}
# 传递参数:data是键值对,json是josn字符串
response = requests.put("http://localhost:1234/area/modifyarea",json=JSON)
# 打印结果
print("状态码:",response.status_code)
print("响应体:",response.text)
# 4、delete请求
# 传递参数:data是键值对,json是josn字符串
response = requests.delete("http://localhost:1234/area/removearea",params={'areaId':'9'})
# 打印结果
print("状态码:",response.status_code)
print("响应体:",response.text)
5.3 实现请求发出与响应
python
import requests
# 传递参数:data是键值对,json是josn字符串
response = requests.get('https://www.baidu.com')
# 行解析
print("URL:",response.url)
print("状态码:",response.status_code)
print("-"*80)
# 头获取
print("获取所有响应头:",response.headers)
print("获取所有cookie:",response.cookies)
print("获取所有编码集:",response.encoding)
# 体获取
print("以文本的方式获取响应体:",response.text) #服务器传过来的是文本信息,如html文档
print("以二进制的方式获取响应体:",response.content) #服务器传过来的是图片/视频/音频等非文本数据
print("以JSON的方式获取响应体:",response.json()) #服务器传过来的是json格式数据,调用该方法以json语法解析数据
5.4 实现登录接口请求(cookie和session)
需求案例:
-
先登录,登录成功后获取'我的订单'页面
-
login接口(post)
- 键值对提交数据username和password
-
order_list接口(get)
-
cookie版登录:
python
import requests
# 1、获取验证码,并获得cookie中的PHPSESSID
response1 = requests.get('验证码接口')
print(response1.status_code)
print(response1.cookies)
id= response1.cookies.get("PHPSEESSID")
print(id)
print("-"*80)
# 2、登录,并提交cookie
data = {"username":"","password":"","verify_code":""}
cookie = {"PHPSEESSID":id}
response2 = requests.post("登录接口",data=data,cookies=cookie)
print(response2.status_code)
print(response2.text)
print("-"*80)
# 3、获取订单,需要再次提交cookie
response3 = requests.get("获取订单接口",cookies=cookie)
print(response3.status_code)
print(response3.text)
session版登录:
python
import requests
# 创建session对象
session = requests.Session()
# 1、获取验证码(隐式获取cookie)
response1 = session.get('验证码接口')
print(response1.status_code)
print("-"*80)
# 2、登录
data = {"username":"","password":"","verify_code":""}
response2 = session.post("登录接口",data=data)
print(response2.status_code)
print(response2.text)
print("-"*80)
# 3、获取订单
response3 = session.get("获取订单接口")
print(response3.status_code)
print(response3.text)
六、pytest单元测试框架
6.1 概述
**概念:**pytest是python的一种第三方单元测试框架
**特点:**同自带的unittst单元测试框架相比,使用起来更加简洁、高效
6.2 运行
命名规则:文件名和方法名一定要以"test_"开头,类名以Test开头,使pytest能够识别到
代码准备:
test_login.py:
python
class TestDemo1:
def test_1(self):
print("断言成功")
assert True
def test_2(self):
print("断言失败")
assert False
运行方式:
主函数运行:
python
# 运行文件:all.py
import pytest
if __name__ == '__main__':
pytest.main()
命令行运行:
直接输入pytest即可
6.3 setup和teardown
概念
函数级别: 运行于测试方法的始末,运行一次测试函数会执行一次 setup 和 teardown。
示例代码:
python
class TestLogin:
# 函数级初始化方法
def setup_method(self, method):
print("---setup---")
# 函数级结束
def teardown_method(self, method):
print("---teardown---")
def test_a(self):
print("test_a")
assert 1
def test_b(self):
print("test_b")
assert 0
执行结果:
6.4 pytest配置文件
6.4.1 概述
应用场景
使用配置文件,可以通过配置项来选择执行哪些目录下的哪些测试模块。
使用方式
1.项目下新建 scripts 模块
2.将测试脚本文件放到 scripts 中3.pytest 的配置文件放在自动化项目目录下
4.名称为 pytest.ini
5.第一行内容为 [pytest],后面写具体的配置参数6.命令行运行时会使用该配置文件中的配置
6.4.2 配置实现
python
[pytest]
addopts = -s --html=report/report_demo.html
testpaths = ./scripts
python_files = test_*.py
python_classes = Test*
python_functions = test_*
addopts=-s 表示命令行参数
testpaths,python_files,python_classes, python_functions表示执行 scripts 文件夹下的 test_开头 .py 结尾的文件下的 Test 开头的类下的 test _开头的函数
注意点
1.配置文件是否已经正确的加载?
- 通过控制台的 inifile 进行查看
2.windows中可能出现"gbk"错误?
- 删除 ini 文件中的所有中文
3.在工作中这个文件也需要复制粘贴?
- 是的,一个项目只会用一次,只需理解,会修改即可
6.5 数据参数化
应用场景:
登录功能都是输入用户名,输入密码,点击登录。但登录的用户名和密码如果想测试多个值时,数据参数化可以使代码更整洁,可读性更好。
方法:
python
数据参数化
# 参数:
argnames:参数名
井argva1ues:参数对应值,类型必须为可迭代类型,一般使用1ist@pytest.mark.parametrize("argnames",argvalues)
示例和结果: 参数化运行两条用例
python
import pytest
class TestLogin:
@pytest.mark.parametrize("params",[
{"username": "zhangsan", "password": "1234"},
{"username": "lisi", "password": "6666"}
])
def test_a(self,params): #以test开头的测试函数
print(params)
print(params["username"])
print(params["password"])
assert 1 #断言成功
6.6 测试报告插件
应用场景
自动化测试脚本最终执行是通过还是不通过需要通过测试报告进行体现。
安装
使用命令 pip install pytest-html进行安装pip install pytest-html==1.21.1 在最新的2.0上有错误
使用
在配置文件中的命令行参数中增加 --htmi-用户路径/report.html
示例
pytest.ini中addopts =-s --html=report/report.html
结果
在项目目录下会对一个 report 文件夹,里面有个report.html 即为测试报告