测试开发工程师成长日记002 - 从0开始做接口自动化

一、安装

  1. python安装及教程
  2. pythonIDE-pycharm安装
  3. allure安装
  4. git安装
  5. 拉取代码: 使用git bash, 输入: git clone ssh://git@10.30.30.3:10022/qagroup/kunlunjing.git
    推荐在gitlab上配置SSH keys
  6. 依赖库安装: cmd 进入命令行后,输入:pip install -r requirements.txt

二、接口封装

1. decorator_helper装饰器 + .ini配置

  1. 接口组成配置封装(framework-conf-interface)
    a. 配置路由, 路由文件夹-服务路由文件(route-{service}.ini)配置
[permission]
auth_login = {'method': 'POST', 'route': '/api/permission/auth/login'}
	  b.  配置域名,域名文件夹-环境文件(domain-{environment}.ini)配置
[permission]
domain=10.30.30.89:38080
	  c.  配置默认入参, 入参文件夹-环境文件夹-服务入参文件(payload-{environment}-{service}.ini)配置
  [apaas]
app_create = {}
app_query = {'appType': 'REPORT', 'current': '1', 'size': '20', 'projectId': ''}
  1. 接口业务类封装 (framework-service-interface)
    a. 配置项文件里(接口的名称)需与业务项文件里(接口的名称)一致
    b. 使用decorator_helper装饰器修饰接口业务类内方法
from framework.service.interface.application_base import ApplicationBase
from framework.utils.deco import *

class Permission(ApplicationBase):
  def __init__(self):
    super(Permission, self).__init__()
    self.proxy = False

    @decorator_helper(Interface)
    def auth_login(self, payload=None):
      """
                登录
                :param payload:
                :return:
                """
      return payload

3.demo实例

import allure
import pytest
from framework.service.interface.basic.apix import Apix
import random,string

@allure.feature("apix")
@allure.story("原生接口")
class TestYuansheng:
    @classmethod
    def setup_class(cls):
        cls.apix  = Apix()

    @allure.severity(allure.severity_level.BLOCKER)
    @allure.title("单个原生接口分组功能测试")
    def test01_category_group(self, **kwargs):

        with allure.step("新建分组"):
            # 新建分组正常调用
            kwargs['name'] = genRandomString()
            m = self.apix.category_add(kwargs)
            assert 'Ok' == str(m['message'])

        with allure.step("查询分组"):
            kwargs['name'] = kwargs['name']
            n = self.apix.category_find(kwargs)
            assert '0' == str(n['code'])

        with allure.step("修改分组"):
            kwargs['id'] = n['data'][0]['id']
            update = self.apix.category_update(kwargs)
            assert '0' == str(update['code'])

        with allure.step('查询所有分组'):
            all = self.apix.category_all(kwargs)
            assert '0' == str(all['code'])

        with allure.step("删除分组"):
            kwargs['id'] = kwargs['id']
            delete = self.apix.category_del(kwargs)
            assert '0' == str(delete['code'])

        with allure.step("删除分组后查询"):
            kwargs['name'] = kwargs['name']
            no = self.apix.category_find(kwargs)
            assert '[]' == str(no['data'])
  • 进阶使用方式 a. 使用固定登录态
    free_login 为内置辅助参数,表示免登录
    isyscore_pc_admin 为内置辅助参数值,表示isyscore系统pc端admin登录。
@decorator_helper(Interface, help_param='free_login=isyscore_pc_admin')
    def model_create(self, payload=None):
        """
        模型创建
        :param payload:
        :return:
        # """
        return payload

b. 数据设定–入参优先级 测试文件中的入参 > 业务文件中入参 > 配置文件中的入参 配置文件中的入参:

  • 针对场景:接口入参固定或方便他人调用时,查看可用的入参数据
  • 使用方式:测试文件中不传入任何参数,此时,默认调用配置文件的入参
  • 业务文件中测试入参:
    1.针对场景:接口部分入参固定或需对部分接口参数进行二次定制(比如加密、签名、调用其它接口)
    2.使用方式:业务文件中进行直接设定,或者进行二次定制修改
  • 测试文件中测试入参:
    1.针对场景:不限制。
    2.使用方式:调用业务文件方法,自由组装各类场景
   配置文件
    get_database_source = {"pageNum":1,"pageSize":20,"search":{"databaseName":"flow_test"}}

业务文件
    def app_create_by_atype_and_pid(self, a_type, project_id, app_code='auto_test', app_name='auto_test', **kwargs):
        """
        :param a_type: 应用类型
        :param project_id: 项目id
        :param app_code: 应用编码
        :param app_name: 应用名称
        :param kwargs:
        :return:
        """
        kwargs['appCode'] = app_code
        kwargs['appName'] = app_name
        kwargs['appType'] = a_type
        kwargs['artifactId'] = ''
        kwargs['desc'] = app_name
        kwargs['groupId'] = ''
        kwargs['module'] = {'id': ''}
        kwargs['projectId'] = project_id
        if a_type == 'HIGH':
            kwargs['artifactId'] = app_name
            kwargs['groupId'] = app_name
            kwargs['bootVersionId'] = '2.4.10'
        return self.app_create(kwargs)

测试文件
    @pytest.mark.run(order=3)
    @pytest.mark.dependency(depends=["iios_pc_login", 'my_permission', 'project_create'], scope='session',
                            name='app_life_cycle')
    def test_03__app_life_cycle(self, **kwargs):
        # 创建项目获取项目id
        kwargs['name'] = project_name
        kwargs['desc'] = project_desc
        m = self.apaas.project_create(kwargs)
        with allure.step("新建项目:返回码200"):
            assert m['code'] == 200

c. 模板辅助参数 模板辅助参数----支持同接口不同模板数据

配置文件:
[template]
community_model_01 = {"appId":"d54a66fb6e8b8df81424daab041c9763",...}
测试文件:
kwargs['data_template'] = 'community_model_01'
kwargs['app_name'] = '自动测试_app添加'
m = self.workflow.model_validate_by_template(kwargs)

2. Request实例化 + Yaml配置

  1. 接口组成配置封装(framework-conf-interface)
    a. 配置接口的组成(id唯一标识,不可重复)
    b. 目录结构:业务线–接口路径(yapi项目)
    c. pioneers:前置执行接口组成说明,会在其他接口调用前执行一次,并且保存对应参数
    d. request:接口组成说明
api:
  pioneers:
  - name: 登录
    id: auth_login
    path: /api/permission/auth/login
    method: post
    headers:
      {"Content-Type": "application/json"}
    parameters:
      {"loginName": "admin", "password": "1Sysc0re!"}
    extractors:
      {"name":"cookies","value":"cookies"}

  request:
  - name: 查询状态
    id: auth_status
    path: /api/permission/auth/status
    method: get
    cookies: $cookies
    headers:
      {"Content-Type": "application/json"}
  1. 接口业务类封装 (framework-service-interface)
    a. 通过getInstance方法获取指定id的接口组成,调用doRequest下发请求获得响应
    from framework.common.request_yaml import getInstance
class Permission():

    def login(self, user_name, password):
        """
        登录
        """
        request = getInstance("auth_login")
        request.setParamsByPath("$.password", password)
        request.setParams("loginName", user_name)
        res = request.doRequest()
        return res

3.demo实例

from framework.common.request_yaml import getInstance

class TestRentalInfo:

    def test03_login(self):
        request = getInstance("auth_login")
        res = request.doRequest()
        print(res.text)

三、脚本编写

1. 单接口鲁棒性测试

暂不需要用例去覆盖,后续通过一个脚本自动生成用例执行

  1. 读取接口协议组成: 从文件内 或者 yapi平台
  2. 通过公共规则、接口私有规则 ,自动生产 逆向场景的参数组合
  3. 检验每个接口组合 下发的响应

2. 用例编写流程

a. 建立一个脚本架子,明确这个py文件测试范围,补充allure.feature、allure.story

import allure
@allure.feature("用户权限")
@allure.story("登录权限测试")
class TestXXXX:
  def setup_class(self):
    pass
  def teardown_class(self):
    pass
  def test01_XXXX(self):
    pass

b.设计用例, 描述测试步骤和测试点,补充用例描述allure.title

import allure
@allure.feature("用户权限")
@allure.story("登录权限测试")
class TestXXXX:
  def set_up_class(self):
    pass
  def teardown_class(self):
    pass
  @allure.title("修改密码")
  def test01_XXXX(self):
    with allure.step("测试步骤1: 使用用户1登录"):
        pass
    with allure.step("检查点1-1: 用户1能登录成功"):
        pass
    with allure.step("测试步骤1: 修改用户1登录密码"):
        pass
    with allure.step("检查点2-1: 用户1用原密码不能登录成功"):
        pass
    with allure.step("检查点2-2: 用户1用新密码能登录成功"):
        pass

c.封装登录接口方法,封装修改密码接口方法

class Apaas:
	def login(self,username,password):
        request = getInstance("login")
        request.setParams("username", username)
        request.setParams("password", password)
        res =request.doRequest()
        return res
    def changePassword(self,username,old_password.new_password):
        request = getInstance("change_password")
        request.setParams("username", username)
        request.setParams("old_password", old_password)
        request.setParams("new_password", new_password)
        res =request.doRequest()
        return res

d.在脚本中使用封装的方法

import allure
from framework.service.interface.ecology.apaas import Apaas
@allure.feature("用户权限")
@allure.story("登录权限测试")
class TestXXXX:
  username = "isyscore"
  password = "isyscore"
  new_password = "123456"

  def set_up_class(self):
    self.apaas = Apaas()
    
  def teardown_class(self):
    res = self.apaas.changePassword(username,new_password,password)
  
  @allure.title("修改密码")
  def test01_XXXX(self):
    with allure.step("测试步骤1: 使用用户1登录"):
        res = self.apaas.login(username,password)
    with allure.step("检查点1-1: 用户1能登录成功"):
        assert res.json()["msg"] == "success" , "用户1使用默认密码登录失败" 
        
    with allure.step("测试步骤1: 修改用户1登录密码"):
        res = self.apaas.changePassword(username,password,new_password)
    with allure.step("检查点2-1: 用户1用原密码不能登录成功"):
        res = self.apaas.login(username,password)
        assert res.json()["msg"] != "success" , "修改密码后,用户使用原密码登陆成功" 
        
    with allure.step("检查点2-2: 用户1用新密码能登录成功"):
        res = self.apaas.login(username,new_password)
        assert res.json()["msg"] == "success" , "修改密码后,用户使用新密码登陆失败" 
        

四、Allure报告展示

1、报告展示中层级 与 脚本内Allure日志级别

层级高低: feature - > story - > title - > step
step标识 展示在右侧执行步骤中

规约:
○ feature标识测试应用和模块, 一个文件夹下 所有py文件使用同一个feature
○ story标识测试的功能点, 代表这个py文件测试的范围,一个py文件使用同一个story
○ title标识 ,一个test方法使用一个title
○ step标识 , 用来包裹一个测试步骤或测试点
Allure报告扩展:
allure 报告内添加附件:
○ 用于底层添加通用的报告展示(失败时 响应记录、截图保存)
○ 在业务接口封装时 记录一些信息

2、Allure报告扩展:

allure 报告内添加附件:
○ 用于底层添加通用的报告展示(失败时 响应记录、截图保存)
○ 在业务接口封装时 记录一些信息
语法:

  1. allure.attach(body, name, attachment_type, extension)
    参数解释:
    ○ body:要写入附件的内容;
    ○ name:附件名字;
    ○ attachment_type:附件类型,是allure.attachment_type其中的一种;
    ○ extension:附件的扩展名;
  2. allure.attach.file(source, name, attachment_type, extension)
    参数解释:
    ○ source:文件路径,相当于传一个文件;
    ○ name:附件名字;
    ○ attachment_type:附件类型,是allure.attachment_type其中的一种;
    ○ extension:附件的扩展名;
3、 allure.attachment_type枚举

TEXT = (“text/plain”, “txt”)
CSV = (“text/csv”, “csv”)
TSV = (“text/tab-separated-values”, “tsv”)
URI_LIST = (“text/uri-list”, “uri”)

HTML = (“text/html”, “html”)
XML = (“application/xml”, “xml”)
JSON = (“application/json”, “json”)
YAML = (“application/yaml”, “yaml”)
PCAP = (“application/vnd.tcpdump.pcap”, “pcap”)

PNG = (“image/png”, “png”)
JPG = (“image/jpg”, “jpg”)
SVG = (“image/svg-xml”, “svg”)
GIF = (“image/gif”, “gif”)
BMP = (“image/bmp”, “bmp”)
TIFF = (“image/tiff”, “tiff”)

MP4 = (“video/mp4”, “mp4”)
OGG = (“video/ogg”, “ogg”)
WEBM = (“video/webm”, “webm”)

PDF = (“application/pdf”, “pdf”)

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值