【接口测试】5_项目实战 _iHRM登录接口参数化

一、框架

1、api/:接口对象层(代码:python package)

  • ① __ init__.py 无内容
  • ②ihrm_login_api.py

2、common/:通用工具方法、函数(代码:python package)

  • ① __ init__.py 无内容
  • ②read_json_file.py
  • ③assert_tools.py
  • ④logging_use.py

3、data/:测试数据文件(文件:dir)

  • login_data.json

4、report/:测试报告(文件:dir)

5、scripts/:测试脚本层(代码:python package)

  • ① __ init__.py 无内容
  • ② test_ihrm_login_params.py

6、config.py: 项目中的 配置信息。(全局变量)

7、pytest.ini: pytest 配置

二、参数化步骤

  1. 将 测试数据,按 [{},{},{}] 格式 组织到 json文件中。
  2. 读取 json文件,将数据转换为 [(),(),()]
  3. 在通用测试方法上一行,添加 @pytest.mark.parameterize()
  4. 给 parameterize() 传参。参1:字符串类型,内容为 json文件中一组数据的 key。参2:[(),(),()]格式数据。
  5. 给 通用测试方法添加形参,与 parameterize() 参1 字符串的内容一致。
  6. 修改 通用测试方法 内部实现,使用形参。

2.1 api包

2.1.1 ihrm_login_api.py

"""
ihrm 登录接口 对象层
"""
import requests


# 定义 ihrm 登录接口 类
class IhrmLoginApi(object):
    # 定义方法
    @classmethod
    def login(cls, req_data):
        resp = requests.post(url="http://ihrm-test.itheima.net/api/sys/login", json=req_data)
        return resp


# 测试 接口封装是否成功
if __name__ == '__main__':
    # 准备请求体数据
    data = {"mobile": "13800000002", "password": "123456"}
    resp = IhrmLoginApi.login(data)
    print("登录成功:", resp.json())

2.2 common包

2.2.1 read_json_file.py

2.2.1.1 相对路径写法
  1. 在 common/ 下创建 文件 read_json_file.py
  2. 在 文件内,创建 函数,读取json文件中的数据,转换成 [(),(),()] 格式数据
  3. 测试此函数功能通过
import json

# 定义工具函数,读取json文件中的数据,转换成 [(),(),()] 格式数据
def read_json_data(filename):
    with open(filename, "r", encoding="utf8") as f:
        json_data = json.load(f)
        login_list = []
        for data in json_data:
            tmp = tuple(data.values())
            login_list.append(tmp)

        return login_list

if __name__ == '__main__':
    res = read_json_data("../data/login_data.json")   # 相对路径写法
    print(res)
  1. 建议读取 json文件时,使用 绝对路径法传入文件名
    1. 在 config.py 中,添加 全局变量,获取 项目目录 BASE_DIR = os.path.dirname(__file__)
    2. 拼接 json文件的绝对路径 filename = BASE_DIR+"/data/login_data.json"
    3. 使用 绝对路径,传入 json文件读取函数。 read_json_data(filename)
2.2.1.2 绝对路径写法

在计算机的存储路径是固定的。

import json
from config import BASE_DIR


# 定义工具函数,读取json文件中的数据,转换成 [(),(),()] 格式数据
def read_json_data(filename):
    with open(filename, "r", encoding="utf8") as f:
        json_data = json.load(f)
        login_list = []
        for data in json_data:
            tmp = tuple(data.values())
            login_list.append(tmp)

        return login_list


if __name__ == '__main__':
    # res = read_json_data("../data/login_data.json")
    filename = BASE_DIR + "/data/login_data.json"       # 绝对路径写法
    res = read_json_data(filename)
    print(res)

2.2.2 assert_tools.py

"""
定义 通用的 工具函数,实现断言
"""
def common_assert(resp, status_code, success, code, message):
    assert status_code == resp.status_code
    assert success is resp.json().get("success")
    assert code == resp.json().get("code")
    assert message in resp.json().get("message")

2.2.3 logging_use.py

  1. 将 loggin_use.py 文件部署到项目中。 如:拷贝至 common/ 下。

  2. 在 项目下 创建 log/ 用来存放生成的 xxx.log 日志文件

  3. 在 项目中,使用日志之前,初始化日志信息,指定 日志文件名【必填】、单位、单位间隔、保留文件个数。

  4. 在 需要打印输出的位置,使用 logging.级别(“想要输出的信息”)

import logging.handlers
import logging
from config import BASE_DIR


def init_log_config(filename, when='midnight', interval=1, backup_count=7):
    """
    功能:初始化日志配置函数
    :param filename: 日志文件名
    :param when: 设定日志切分的间隔时间单位
    :param interval: 间隔时间单位的个数,指等待多少个 when 后继续进行日志记录
    :param backup_count: 保留日志文件的个数
    :return:
    """
    # 1. 创建日志器对象
    logger = logging.getLogger()

    # 2. 设置日志打印级别
    logger.setLevel(logging.DEBUG)
    # logging.DEBUG 调试级别
    # logging.INFO 信息级别
    # logging.WARNING 警告级别
    # logging.ERROR 错误级别
    # logging.CRITICAL 严重错误级别

    # 3. 创建处理器对象
    # 控制台对象
    st = logging.StreamHandler()
    # 日志文件对象
    fh = logging.handlers.TimedRotatingFileHandler(filename,
                                                   when=when,
                                                   interval=interval,
                                                   backupCount=backup_count,
                                                   encoding='utf-8')

    # 4. 日志信息格式
    fmt = "%(asctime)s %(levelname)s [%(filename)s(%(funcName)s:%(lineno)d)] - %(message)s"
    formatter = logging.Formatter(fmt)

    # 5. 给处理器设置日志信息格式
    st.setFormatter(formatter)
    fh.setFormatter(formatter)

    # 6. 给日志器添加处理器
    logger.addHandler(st)
    logger.addHandler(fh)


if __name__ == '__main__':
    # 初始化日志
    init_log_config(BASE_DIR + '/log/sh27.log', interval=3, backup_count=5)

    # 打印输出日志信息
    logging.debug('我是一个调试级别的日志')
    logging.info("AAA BBB CCC")
    logging.error("xxxx 错误。。")

在这里插入图片描述

2.3 data文件夹

2.3.1 login_data.json

总共15条测试案例,但是本案例数据只有7条,仅做演示,后续可以补充全部。

[
  {
    "desc": "登录成功",
    "req_data": {
      "mobile": "13800000002",
      "password": "123456"
    },
    "status_code": 200,
    "success": true,
    "code": 10000,
    "message": "操作成功"
  },
  {
    "desc": "手机号不存在",
    "req_data": {
      "mobile": "13874893701",
      "password": "123456"
    },
    "status_code": 200,
    "success": false,
    "code": 20001,
    "message": "用户名或密码错误"
  },
  {
    "desc": "密码错误",
    "req_data": {
      "mobile": "13800000002",
      "password": "123456890"
    },
    "status_code": 200,
    "success": false,
    "code": 20001,
    "message": "用户名或密码错误"
  },
  {
    "desc": "手机号为空",
    "req_data": {
      "mobile": null,
      "password": "123456"
    },
    "status_code": 200,
    "success": false,
    "code": 20001,
    "message": "用户名或密码错误"
  },
  {
    "desc": "多参",
    "req_data": {
      "mobile": "13800000002",
      "password": "123456",
      "abc": "123"
    },
    "status_code": 200,
    "success": true,
    "code": 10000,
    "message": "操作成功"
  },
  {
    "desc": "少参",
    "req_data": {
      "mobile": "13800000002"
    },
    "status_code": 200,
    "success": false,
    "code": 20001,
    "message": "用户名或密码错误"
  },
  {
    "desc": "无参",
    "req_data": null,
    "status_code": 200,
    "success": false,
    "code": 99999,
    "message": "抱歉,系统繁忙,请稍后重试!"
  }
]

2.4 report文件夹

2.5 scripts包

2.5.1 test_ihrm_login_params.py

## parameterize参数化
1. 在 通用测试方法上一行,添加 @pytest.mark.parameterize()
2. 给 parameterize()添加参数。参1:一个字符串,内容为json文件中,一组测试数据的键。参2:[(),(),()]格式数据。
3. 给 通用测试方法,添加形参。参数与 parameterize()的 参1 保持一致。
4. 修改 通用测试方法 内部实现,使用 形参。
  • 定义通用测试方法,测试登录接口。
  • 作参数化,一个接口就一个方法。
import logging

import pytest
from api.ihrm_login_api import IhrmLoginApi
from common.assert_tools import common_assert
from common.logging_use import init_log_config
from common.read_json_file import read_json_data
from config import BASE_DIR


class TestIhrmLoginParams(object):
    init_log_config(BASE_DIR + '/log/sh27.log', interval=3, backup_count=5)
    # 读取json文件,获取[(),(),()]格式数据
    data = read_json_data(BASE_DIR + "/data/login_data.json")

    @pytest.mark.parametrize("desc, req_data, status_code, success, code, message", data)
    # 定义 通用测试方法 - 测试ihrm登录接口
    def test_ihrm_login(self, desc, req_data, status_code, success, code, message):
        # 调用 自己封装的 api, 获取响应结果
        resp = IhrmLoginApi.login(req_data)
        # 打印查看
        # print(desc, ":", resp.json())
        logging.info(f"{desc} : {resp.json()}")
        # 断言
        common_assert(resp, status_code, success, code, message)

2.6 config.py

import os

# 定义全局变量,获取项目路径(绝对路径)
BASE_DIR = os.path.dirname(__file__)

2.7 pytest.ini

[pytest]
addopts = -s
testpaths = ./scripts
python_files = test*.py
python_classes = TestAdd*Params
python_functions = test*
欧姆龙FINS(工厂集成网络系统)协议是专为该公司自动化设备间数据交互而设计的网络通信标准。该协议构建于TCP/IP基础之上,允许用户借助常规网络接口执行远程监控、程序编写及信息传输任务。本文档所附的“欧ronFins.zip”压缩包提供了基于C与C++语言开发的FINS协议实现代码库,旨在协助开发人员便捷地建立与欧姆龙可编程逻辑控制器的通信连接。 FINS协议的消息框架由指令头部、地址字段、操作代码及数据区段构成。指令头部用于声明消息类别与长度信息;地址字段明确目标设备所处的网络位置与节点标识;操作代码定义了具体的通信行为,例如数据读取、写入或控制器指令执行;数据区段则承载实际交互的信息内容。 在采用C或C++语言实施FINS协议时,需重点关注以下技术环节: 1. **网络参数设置**:建立与欧姆龙可编程逻辑控制器的通信前,必须获取控制器的网络地址、子网划分参数及路由网关地址,这些配置信息通常记载于设备技术手册或系统设置界面。 2. **通信链路建立**:通过套接字编程技术创建TCP连接至控制器。该过程涉及初始化套接字实例、绑定本地通信端口,并向控制器网络地址发起连接请求。 3. **协议报文构建**:依据操作代码与目标功能构造符合规范的FINS协议数据单元。例如执行输入寄存器读取操作时,需准确配置对应的操作代码与存储器地址参数。 4. **数据格式转换**:协议通信过程中需进行二进制数据的编码与解码处理,包括将控制器的位状态信息或数值参数转换为字节序列进行传输,并在接收端执行逆向解析。 5. **异常状况处理**:完善应对通信过程中可能出现的各类异常情况,包括连接建立失败、响应超时及错误状态码返回等问题的处理机制。 6. **数据传输管理**:运用数据发送与接收函数完成信息交换。需注意FINS协议可能涉及数据包的分割传输与重组机制,因单个协议报文可能被拆分为多个TCP数据段进行传送。 7. **响应信息解析**:接收到控制器返回的数据后,需对FINS响应报文进行结构化解析,以确认操作执行状态并提取有效返回数据。 在代码资源包中,通常包含以下组成部分:展示连接建立与数据读写操作的示范程序;实现协议报文构建、传输接收及解析功能的源代码文件;说明库函数调用方式与接口规范的指导文档;用于验证功能完整性的测试案例。开发人员可通过研究这些材料掌握如何将FINS协议集成至实际项目中,从而实现与欧姆龙可编程逻辑控制器的高效可靠通信。在工程实践中,还需综合考虑网络环境稳定性、通信速率优化及故障恢复机制等要素,以确保整个控制系统的持续可靠运行。 资源来源于网络分享,仅用于学习交流使用,请勿用于商业,如有侵权请联系我删除!
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

少云清

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值