测开-接口功能测试及自动化(接口测试)
接口测试:
一、接口流程封装与定义:






二、基于加密接口的测试用例设计:


1、使用 base64 对其做加密,得到一个加密后的文件 demo64.txt;
to_base64.py
import base64 import json bytes_url = {"topics": { "orange":"movie", "school":"testing-studio", "president":"seveniruby" } } data = json.dumps(bytes_url, indent=2) str_url = base64.b64encode(data.encode("utf-8")) # 被编码的参数必须是二进制数据 print(str_url)
demo64.txt
ewogICJ0b3BpY3MiOiB7CiAgICAib3JhbmdlIjogIm1vdmllIiwKICAgICJzY2hvb2wiOiAidGVzdGluZy1zdHVkaW8iLAogICAgInByZXNpZGVudCI6ICJzZXZlbmlydWJ5IgogIH0KfQ==
2、使用 Python 命令在 “demo64.txt” 所在目录启动一个服务;
python -m http.server 10000

3、请求并解密响应
api.py
import base64 import json import requests class BaseApi(): @classmethod def send(self,params): res = requests.request(params['method'],params['url'],headers = params['headers']) if params['encoding'] == 'base64': return json.loads(base64.b64decode(res.content)) # 如果是第三方加密,那么把结果拿到之后再请求第三方解密再返回解密之后信息 elif params['encoding'] == 'private': return requests.request('post','url',data= res.content)
test_base64.py
import base64 import json import requests from requests_demo_framwork.api import BaseApi url = 'http://127.0.0.1:10000/demo64.txt' class TestBase64(): def test1(self): res = requests.get(url=url) data = base64.b64decode(res.content) print("res=",res.text) print(json.loads(data)) def test2(self): data = { 'method': 'get', 'url': 'http://127.0.0.1:10000/demo64.txt', 'headers': None, 'encoding': 'base64' } res = BaseApi.send(data) print(res)
三、多环境下的接口测试:

do_yaml.py
from ruamel import yaml def do_yaml(): env = { "default":"test", "testing-studio": { "dev":"https://ceshiren.com", "test":"https://baidu.com" } } # 创建env.yaml文件,给可写权限,将env中数据写入env.yaml with open("env.yaml","w") as f: yaml.safe_dump(data=env,stream=f) if __name__ == '__main__': do_yaml()
env.yaml
default: dev
testing-studio: {dev: https://ceshiren.com, test: https://baidu.com}
env_demo.py
import requests class API: @classmethod def send_env(self, data: dict): res = requests.request(method=data['method'], url=data['url'], headers=data['headers']) return res
test_env_demo.py
from ruamel import yaml from requests_demo_framwork.env_demo import API class TestEnv: def test1(self): data = { "method": 'get', "url":"url", "headers": None } env = yaml.safe_load(open("env.yaml")) # 替换 # default: test # testing - stutio: {dev: https: // ceshiren.com, test: https: // baidu.com} data['url'] = str(data['url']).replace("url", env["testing-studio"][env['default']]) res = API.send_env(data) print(res.text)
四、 api object模式与原则
- 思想和pageobject相通
- 隔离变与不变的内容
- 接口细节与业务进行抽离
原则:
- 每个公共方法代表接口所提供功能
- 不要暴露api内部细节
- 不要在接口实现层写断言
- 每个method返回其他的api object或者用来做断言的信息
- 不需要每个api都进行实现
五、通用baseapi封装:

baseapi.py
import requests class BaseApi(): def send(self, data): return requests.request(**data).json() def send_data(self, method='get', url=None, params=None, json=None): data = { "method": method, "url": url, "params": params, "json": json } return data if __name__ == '__main__': _corpid = 'ww3c6b51ae743ae4ec' _company_label_corpsecret = 'xvmyVvTMnJaR0q2eitVBAOqJA-vQKt6zPjpQXixT8do' base_url = "https://qyapi.weixin.qq.com/cgi-bin/" get_token_url = base_url + "gettoken" company_label_token_params = { 'corpid': _corpid, 'corpsecret': _company_label_corpsecret } api = BaseApi() data = api.send_data( method='get', url=get_token_url, params=company_label_token_params ) res = api.send_data(data) print(res)
六、测试步骤的数据驱动


https://docs.python.org/zh-cn/3/library/string.html?highlight=template#string.Template
get_token.yaml
json: null method: get params: {corpid: $corpid, corpsecret: $corpsecret} url: https://qyapi.weixin.qq.com/cgi-bin/gettoken #json: null #method: get #params: {corpid: ww3c6b51ae743ae4ec, corpsecret: xvmyVvTMnJaR0q2eitVBAOqJA-vQKt6zPjpQXixT8do} #url: https://qyapi.weixin.qq.com/cgi-bin/gettoken
baseapi.py
import requests from ruamel import yaml class BaseApi(): def send(self, data): return requests.request(**data).json() def send_data(self, method='get', url=None, params=None, json=None): data = { "method": method, "url": url, "params": params, "json": json } return data def template(self,yaml_file,**sourse_target): """ 将yaml文件读出并替换被$标记的字段 :param yaml_file:yaml文件名 :param sourse_target:需要被替换的原字段及目标数据的字典格式数据 :return:返回从yaml文件中读出并被替换之后的结果数据 """ from string import Template re = Template(open(yaml_file).read()).substitute(**sourse_target) print("re=",re) return yaml.safe_load(re) if __name__ == '__main__': # get_token_data = yaml.safe_load(open("get_token.yaml")) api = BaseApi() sourse_target = { "corpid":"ww3c6b51ae743ae4ec", "corpsecret":"xvmyVvTMnJaR0q2eitVBAOqJA-vQKt6zPjpQXixT8do" } # get_token_data = api.template("get_token.yaml",**sourse_target) get_token_data = api.template("get_token.yaml",**sourse_target) print("get_token_data=",get_token_data) res = api.send(get_token_data) print(res)
七、测试数据的数据驱动
意义:
- 提高数据的可维护性
- 规范化数据管理
- 对数据进行备份
实现:
- 使用@pytest.mark.parametrize()传参
- 使用yaml、json、CSV等方式文件管理数据


八、配置的数据驱动--多环境配置思想
九、通用测试用例封装
意义:
- 把重复的内容封装
- 减少重复的初始化
实现:
- 创建一个TestBase类
- 其他的case都继承自TestBase
十、通用测试框架构建

接口测试流程:
- 1、测试范围:需要覆盖多少业务和接口;
- 2、产品分析:接口的协议、上下游依赖--抓包分析;
- 3、用例设计:业务用例如何模拟和覆盖;
- 4、工具选型:选择合适的框架;
- 5、维护管理:用例编写与维护更新;
- 6、持续集成:不断集成测试;
测试范围:
- 1、业务需求调研:研发和产品反馈常出问题的业务;
- 2、接口文档:人工文档、swagger自动生成的文档;
- 3、代码分析:分析spring等框架的代码;
- 4、线上log和数据:线上的生产监控和接口log;
- 5、客户端抓包:基于用户角度的接口行为分析(接口调用的流程分析);
用例设计:
- 1、人工用例补充:用流程图和思维导图进行业务建模;
- 2、正常场景用例right path;
- 3、异常场景用例;
- 4、安全和稳定性用例;
- 5、常见的等价类边界值、业务流、决策树、决策表;
开源测试框架:Python:requests、httprunner
测试框架基本能力:
- 项目管理:pip virtualenv
- 用例编写:pytest,用例的标签、前置后置的操作、分组、依赖关系等
- 领域能力:app web http
- 执行调度:pytest pycharm shell Jenkins
- 测试报告:allure2
用例原则:
- 1、用例执行前需要有初始化操作;
- 2、每个用例尽量的独立,不依赖其他用例;
- 3、多api的测试用例代码不冗余;
单接口测试:
1. json格式测试: 通常我们的接口一般设计的都是传递json串,那么就需要去测试 如果传递非json的情况,这时候程序会不会正确的处理,返回相应的 error code 2. 默认值测试: 很多情况一些非必填的参数会有默认值,比如说一个查询的接口,参数count为返回查询的结果数量, 默认为10,那么就应该有一条case来测试,当然前置条件是数据库里面必须要存在这样的数据超过10条。 3. 异常类型测试: 比如上面的count参数,这个参数的类型一定是可以转换为int类型的,这时候我们需要测试如果传的一些不可以 转换为int类型值来测试代码是否加入判断 4. 必传项测试: 如果接口的参数有必传项,那么需要测试在不传这个参数的时候接口返回情况,测试是否会提示 相应的error code 5. 非必传项测试: 如果接口有非必填项,当我不传递这些参数的时候会不会正常的返回相应的结果 6.非空测试: 无论是必传的和非必传的参数,传递的key是正确的,但是value=null,这时候返回结果是否正确 7.业务逻辑测试: 传递正确的参数,接口对数据库进行查询的操作,需要去验证数据库查询是否正确,接口对数据库进行 增删改的操作,也需要看数据库是否同步进行了这些操作 8.兼容性测试: 比如说今天接口进行了调整,但是前端没有进行变更,这时候需要验证新的接口是否满足旧的调用方式 9.错误码测试: 通用的错误码与业务错误码是否能够清晰的说明调用问题,错误码是否能够尽可能的全的覆盖所有的情况 10.数据异常测试: 假如数据库设计为32位varchar类型,那么如果传33位会是什么情况,会不会抛出相应的错误码,而不会抛出数据库异常 11.返回值测试: 返回值除了内容需要是正确的,还需要类型也是正确的,保证调用方拿到这些参数能够正确的解析 12.加密测试:
组合接口测试(场景测试)
单个的接口测试通过后,需要将单个的接口组成连续的场景,比如说投资接口需要用到一个类似token的
参数,而这个参数是登陆接口获取到的,所以就需要先调用登陆接口,然后再去调用投资接口。还有就是
像数据权限与操作权限这些,都会依赖一些其他的接口,那么把这些依赖的接口组成一个场景来测试数据的
正确性。还有一部分接口是内部调用的,比如说注册接口,在注册的时候通常需要获取一个验证码,然后输入
验证码再进行提交注册的操作,在这过程中,验证验证码的操作是在注册的内部完成的,那么其实在组合场景
的时候就不需要再去中间加入验证验证码的接口。
restful风格

- 资源:就是数据
- 某种表现层:数据的表现形式
- 表现层状态转化:增删改查
浙公网安备 33010602011771号