测开-接口功能测试及自动化(接口测试)

接口测试:

一、接口流程封装与定义:

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

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风格

  • 资源:就是数据
  • 某种表现层:数据的表现形式
  • 表现层状态转化:增删改查

posted on 2020-08-04 13:48  echooche  阅读(49)  评论(0)    收藏  举报

导航