2026/8/22 10:24:11

接口自动化基础知识

接口自动化基础知识 一、接口自动化requests1.核心内容1.get请求参数 使用 params,参数拼接在url后面多用于查询2.post请求json格式 使用 json; 表单格式 使用 data;3.response对象的常用属性status_code ,json(),text,headers,cookies4.异常处理接口 返回的不是json的时候使用 .json()会报错误.案例get请求import requests url http://xxx/api/user/list payload {page:1,pageSize:10} resp requests.get(urlurl, paramspayload) print(resp.status_code) # 响应状态码 200 print(resp.json()) # 将响应转为字典 # 简单响应断言 assert resp.status_code 200 assert resp.json()[code] 0params参数说明params是GET 请求的查询参数格式Python 字典 dict。requests 会自动把字典拼接成 URL 后面?key1val1key2val2这一段。(1几种常见的写法普通字典params {page:0,pageSize:10} requests.get(url, paramsparams)值为数字、字符串、Noneparams { name: 测试, age: 20, beginDate: None }同一个key多个值有些接口需要?id1id2id3案例 post-json请求常用import requests url http://xxx/api/login headers {Content‑Type:application/json} body {username:zxj,password:123456} resp requests.post(urlurl, jsonbody, headersheaders) token resp.json()[data][token] print(token)二、pytest核心用例命名规则文件test_xxx.py函数def test_xx()类TestXxx方法test_xxx()执行参数‑v详细输出、‑s打印 print、‑x失败停止fixture前置后置scope 作用域yield 实现前置 后置清理返回数据给用例pytest.mark.parametrize数据驱动allure 报告基础使用案例fixture基础。scopesession全局登录 获取 tokenimport pytest import requests pytest.fixture(scopesession) def get_token(): session级别整个测试只登录一次 url http://xxx/api/login data {username:zxj,password:123456} r requests.post(url,jsondata) # 提取token token r.json()[data][token] yield token # 返回给测试用例yield前面前置 # yield之后全部用例执行完成之后执行后置这里无需清理 # 测试用例直接接收fixture返回值 def test_query_list(get_token): headers {token:get_token} resp requests.get(http://xxx/api/list,headersheaders) assert resp.json()[code] 0scope取值function默认每个用例执行一次class每个测试类执行一次module每个 py 文件执行一次session整个测试会话执行一次登录、数据库连接首选案例parametrize数据驱动同一套逻辑多组输入生成多条用例测试代码和数据分离import pytest # 参数参数名字多组测试数据 pytest.mark.parametrize(page,expect_code, [(0,-1), (1,0), (-1,-1)]) def test_page_param(page,expect_code,get_token): headers {token:get_token} params {page:page,pageSize:10} res requests.get(http://xxx/api/log,headersheaders,paramsparams) assert res.json()[code] expect_code三、pymysql数据库操作数据库断言连接数据库、创建游标DictCursor查询结果返回字典可以按字段名取值写断言必备execute 执行 sql占位符%s防止 sql 注入fetchone () 取一条fetchall () 取全部增删改必须conn.commit()异常conn.rollback()回滚fixture封装全局数据库连接不要每个用例反复打开关闭数据库断言场景新增 / 修改接口调用后查询数据库校验数据是否落库正确重点接口返回成功不等于数据库落库正确必须数据库断言案例session fixture封装数据库连接import pymysql import pytest pytest.fixture(scopesession) def get_db(): # 建立连接 conn pymysql.connect( host127.0.0.1, port3306, userroot, password123456, databasetest_command_log, charsetutf8mb4 ) # DictCursor 返回字典格式 cur conn.cursor(cursorpymysql.cursors.DictCursor) yield conn, cur # 给用例返回连接、游标 # 后置全部用例跑完关闭资源 cur.close() conn.close()开启cursorpymysql.cursors.DictCursor查询返回字典 / 字典列表fetchone()返回1 条字典key 数据库字段名value 字段值没有数据返回Nonefetchall()返回列表里面每一项是一条记录字典cur.execute(select commandName,commandValue from command_log limit 1) row cur.fetchone() print(row) #输出 {commandName: 显示设置, commandValue: standard} rows cur.fetchall() print(rows) #输出 [ {commandName: 显示设置, commandValue: standard}, {commandName: 亮度设置, commandValue:high} ]普通 Cursor 不写 DictCursor返回元组(显示设置,standard)不知道哪个值对应哪个字段写断言很麻烦。案例数据库断言场景调用新增命令日志接口接口返回成功查询数据库校验数据是否正确存入# get_token 和 get_db是 fixture def test_add_command_log(get_token, get_db): # 获取连接和游标 conn, cur get_db # token headers {token:get_token} # 1、调用新增接口 req_body {commandName:显示设置,commandValue:standard} resp requests.post(http://xxx/api/addLog,headersheaders,jsonreq_body) assert resp.json()[code] 0 # 2、数据库断言查询刚刚插入的数据 sql select commandName,commandValue from command_log where commandName%s order by create_time desc limit 1 cur.execute(sql, (显示设置,)) # %s占位传参防止SQL注入 db_result cur.fetchone() # 获取第一条结果字典格式 # 3、断言数据库的值和请求入参一致 assert db_result[commandName] 显示设置 assert db_result[commandValue] standard注意事项不要字符串拼接 SQL用%s占位传参防止 SQL 注入insert/update/delete 操作后需要conn.commit()异常场景conn.rollback()回滚自动化尽量清理测试脏数据避免脏数据导致用例失败注意点详解11、禁止字符串拼接 SQL使用%s占位符防止 SQL 注入❌错误字符串拼接有注入风险# 千万不要这么写 name xxx sql fselect * from command_log where commandName {name} cur.execute(sql)✅正确写法SQL 语句写%s占位execute 第二个参数传元组把值传入sql select * from command_log where commandName %s cur.execute(sql, (显示设置,)) # 参数放在元组里多个参数就 (a,b) res cur.fetchone()注意这里的%s不是 python 字符串格式化是pymysql 的占位符不管字段是字符串、数字统一用%s。多个参数案例sql select * from command_log where commandName%s and commandValue%s cur.execute(sql, (显示设置,standard))2insert /update/delete必须 commit异常要 rollback () 回滚conn.commit()提交事务数据才真正写入数据库如果程序发生异常执行conn.rollback()回滚撤销本次修改案例import pymysql conn pymysql.connect(host127.0.0.1,port3306,userroot,password123456,databasetest_command_log,charsetutf8mb4) cur conn.cursor(cursorpymysql.cursors.DictCursor) try: # insert操作 insert_sql insert into command_log(commandName,commandValue) values(%s,%s) cur.execute(insert_sql, (日志测试,test001)) conn.commit() # ✨DML操作一定要commit数据落库 print(插入成功) except Exception as e: print(执行出错,e) conn.rollback() # ✨出错回滚放弃本次修改 finally: cur.close() conn.close()3清理脏 数据自动化测试产生的测试数据如果不删除会堆积在库中影响后面用例执行。 两种方案用例执行完主动 delete 删除本次产生的数据推荐使用事务用例执行完直接 rollback不提交测试数据根本不会保存适合纯测试案例接口自动化用例结束清理脏数据配合 fixture yield 后置import pytest import requests import pymysql pytest.fixture(scopefunction) def db_and_token(): function级别每个用例执行yield后置清理脏数据 # 前置建立连接、获取token conn pymysql.connect(host127.0.0.1,userroot,password123456,databasetest_command_log,charsetutf8mb4) cur conn.cursor(cursorpymysql.cursors.DictCursor) #登录拿token login_resp requests.post(http://xxx/api/login,json{username:zxj,password:123456}) token login_resp.json()[data][token] yield conn, cur, token # ✨后置用例跑完删除本次测试数据清理脏数据 try: del_sql delete from command_log where commandName%s cur.execute(del_sql, (日志测试,)) conn.commit() except: conn.rollback() cur.close() conn.close() def test_add_log_case(db_and_token): conn,cur,token db_and_token headers {token:token} body {commandName:日志测试,commandValue:test001} resp requests.post(http://xxx/api/addLog,headersheaders,jsonbody) assert resp.json()[code] 0 #数据库断言 sql select commandName,commandValue from command_log where commandName%s order by create_time desc limit 1 cur.execute(sql,(日志测试,)) db_data cur.fetchone() assert db_data[commandValue] test001上面这个 fixture 是scopefunction每一条测试用例执行完成都会执行 delete 清理测试数据不会留脏数据。