金融项目实战 06|Python实现接口自动化——日志、实名认证和开户接口

目录

一、日志封装及应用(理解)

二、认证开户接口脚本编写

1、代码编写

1️⃣api目录

2️⃣script目录

2、BeautifulSoup库

1️⃣简介及例子 

2️⃣提取html数据工具封装

3、认证开户参数化


一、日志封装及应用(理解)

🔴日志的作用:

  • 记录程序运行的步骤和错误。

🔴日志的场景:

  • 1、调试bug
  • 2、查看程序运行轨迹

🔴日志基本应用:

# 1、导包
import logging
# 2、调用日志⼊口
logging.error("出错啦,错误原因:{}".format(e))
import logging
# 设置日志级别 及保存⽂件名
logging.basicConfig(level=logging.DEBUG, filename="../log/p2p.log")
# 调用日志
logging.debug("调试信息")
logging.info("信息级别")
logging.warning("警告")
logging.error("断⾔错误!")
logging.critical("严重错误")

🔴测试人员使用的日志的入口:

  • info:记录运行步骤
  • error:记录运行错误

🔴日志底层组成介绍:了解底层是为了修改log打印出的信息进行美化封装

  • 说明:logging库底层有4大组件(日志器、处理器、格式器、过滤器)
    • 1、日志器:接受日志信息,设置日志显示级别
    • 2、处理器:控制日志显示位置或文件
    • 3、格式器:控制日志输出的显示样式
  • 关系:
    • 格式器必须关联处理器
    • 处理器必须关联日志器

🔴日志封装应用:

重组封装的目的:解决日志显示的样式、存储方式

①日志工具的封装

在util.py中添加日志工具的封装:

下面这个日志工具类可以当模板用,最多改一下保存日志的.log文件名称


import logging.handlers

# 日志工具
class GetLog:
    @classmethod
    def get_log(cls):
        cls.log = None
        if cls.log is None:
            # 1、获取日志器
            cls.log = logging.getLogger()
            # 设置日志级别 info
            cls.log.setLevel(logging.INFO)
            filepath = DIR_PATH + os.sep + "log" + os.sep + "p2p.log"
            # 2、获取处理器 TimedRotatingFileHandler:日志保存到文件且根据时间去分割
            tf = logging.handlers.TimedRotatingFileHandler(filename=filepath,
                                                           when="midnight",
                                                           interval=1,
                                                           backupCount=3,
                                                           encoding="utf-8")
            # 3、获取格式器
            fmt = "%(asctime)s %(levelname)s [%(filename)s(%(funcName)s:%(lineno)d)] - %(message)s"
            fm = logging.Formatter(fmt)
            # 4、将格式器添加到处理器中
            tf.setFormatter(fm)
            # 5、将处理器添加到日志器中
            cls.log.addHandler(tf)
        # 返回日志器
        return cls.log


# 下面只是测试上面的工具能不能用的,如果运行成功,则会在log目录下产生p2p.log
# p2p.log文件内容类似为:2025-01-14 22:30:41,013 INFO [util.py(<module>:50)] - 信息级别测试
if __name__ == '__main__':
    GetLog.get_log().info("信息级别测试")

②工具使用

这做的目的只是让log=GetLog.get_log()在只要用到导api包就自动执行,实现自动调用方法;
(为什么这样用: Python中的`__init__.py`文件 -CSDN博客)

应用的级别:info、error

  • info:i记录程序运行的步骤
  • error:记录程序错误

标注地方:api和script

api层:记录程序步骤

script:记录程序执行结果、断言结果、错误原因

可以在api和script中每个方法中标注log,下面仅为示例:

# script目录中文件标注的示例
#2、获取短信验证码接口 测试
    @parameterized.expand(read_json("register_login.json", "phone_code"))
    def test02_phone_code(self,phone,imgVerifyCode,expec_text):
        try:
            # 1、调用获取图片验证码接口 -- 目的:让session对象记录cookie
            # 调用接口后session会自动记录cookie
            self.reg.api_img_code(234)
            # 2、调用短信验证码接口
            r = self.reg.api_phone_code(phone=phone,imgVerifyCode=imgVerifyCode)
            # 3、查看响应结果
            log.info("执行接口结果为:{}".format(r.text))
            self.assertIn(expec_text,r.text) # 使用text提取结果是更方便,json还要根据键找值
            log.info("执行断言通过!")
        except Exception as err:
            # 日志
            # print(err)
            log.error("断言失败,原因:{}".format(err))
            # 抛异常
            raise
# api目录中的示例
# 2、获取短信验证码接⼝ 封装
    def api_phone_code(self,phone,imgVerifyCode):
        data = {
            "phone": phone,
            "imgVerifyCode": imgVerifyCode,
            "type": "reg"
        }
        log.info("正在调用获取短信验证码接口,请求方法:{}, 请求url:{} 请求参数:{}".format("post", self.__url_phone_code,data))
        return self.session.post(url=self.__url_phone_code,data=data)

二、认证开户接口脚本编写

1、代码编写

1️⃣api目录

①结构

from config import HOST


class ApiApproveTrust:
    # 初始化
    def __init__(self, session):
        # 获取session对象
        self.session = session
        # 认证url
        self.__url_approve = HOST + "/member/realname/approverealname"
        # 查询认证状态url
        self.__url_approve_status = HOST + "/member/member/getapprove"
        # 开户url
        self.__url_trust = HOST + "/trust/trust/register"
        # 图片验证码url
        self.__url_img_code = HOST + "/common/public/verifycode/{}"
        # 充值url
        self.__url_recharge = HOST + "/trust/trust/recharge"

    # 1、认证接口 封装
    def api_approve(self):
        pass

    # 2、查询认证状态接口 封装
    def api_approve_status(self):
        pass

    # 3、开户接口 封装
    def api_trust(self):
        pass

    # 4、获取图片验证码接口 封装
    def api_img_code(self, random):
        pass

    # 5、充值接口封装
    def api_recharge(self,valicode):
        pass

②实现

from config import HOST


class ApiApproveTrust:
    # 初始化
    def __init__(self, session):
        # 获取session对象
        self.session = session
        # 认证url
        self.__url_approve = HOST + "/member/realname/approverealname"
        # 查询认证状态url
        self.__url_approve_status = HOST + "/member/member/getapprove"
        # 开户url
        self.__url_trust = HOST + "/trust/trust/register"
        # 图片验证码url
        self.__url_img_code = HOST + "/common/public/verifycode/{}"
        # 充值url
        self.__url_recharge = HOST + "/trust/trust/recharge"

    # 1、认证接口 封装
    def api_approve(self):
        # 1、请求参数
        data = {
            "realname":"华仔",
            "card_id":"350102199003072237"
        }
        # 2、调用请求方法 难题:multipart/form-data使用:data+files来实现多消息体类型
        return self.session.post(url=self.__url_approve, data=data, files={"x": "y"})

    # 2、查询认证状态接口 封装
    def api_approve_status(self):
        return self.session.post(url=self.__url_approve_status)

    # 3、开户接口 封装
    def api_trust(self):
        return self.session.post(url=self.__url_trust)

    # 4、获取图片验证码接口 封装
    def api_img_code(self, random):
        return self.session.get(url=self.__url_img_code.format(random))

    # 5、充值接口封装
    def api_recharge(self,valicode):
        # 1、请求参数
        data = {
            "paymentType": "chinapnrTrust",
            "amount": "1000",
            "formStr":"reForm",
            "valicode":valicode
        }
        # 2、调用请求方法
        return self.session.post(url=self.__url_recharge, data=data)

难点:认证接口请求参数类型为:multipart/form-data多消息类型,如何实现?

  • 解决:请求使用data+files两种参数格式,消息头会自动切换到multipart即可。
  • 示例:self.session.post(url=self.__url_approve, data=data, files={"x": "y"})
  • files={"x": "y"}只是起到占位作用,表明有文件而已。
2️⃣script目录

 

①结构

import unittest

import requests

from api.api_register_login import ApiRegisterLogin


class TestApproveTrust(unittest.TestCase):
    # 初始化
    def setUp(self) -> None:
        #1、获取session对象
        self.session = requests.Session()
        #2、实例化ApiRegisterLogin类方法
        self.approve = ApiRegisterLogin(self.session)
        #3、调用登录接口
        ApiRegisterLogin(self.session).api_login()
    # 结束
    def tearDown(self) -> None:
        self.session.close()

    #1、认证接口 测试
    def test01_approve(self):
        pass
    #2、查询认证状态接口 测试
    def test02_approve_status(self):
        pass

    #3、开户接口 测试
    def test03_trust(self):
        pass

    #4、获取图片验证码接口 测试
    def test04_img_code(self):
        pass

    #5、充值接口 测试
    def test05_recharge(self):
        pass

②实现

请求第三方开户接口 和 请求第三方充值接口 的代码需要后文的BeautifulSoup库知识。

此处是加了参数化的代码,参数化的其他内容看后文参数化小节。

import unittest

import requests
from parameterized import parameterized

from api import log
from api.api_approve_trust import ApiApproveTrust
from api.api_register_login import ApiRegisterLogin
from util import parser_html, read_json


class TestApproveTrust(unittest.TestCase):
    # 初始化
    def setUp(self) -> None:
        #1、获取session对象
        self.session = requests.Session()
        #2、实例化ApiRegisterLogin类方法
        self.approve = ApiApproveTrust(self.session)
        #3、调用登录接口
        ApiRegisterLogin(self.session).api_login()
    # 结束
    def tearDown(self) -> None:
        r = self.session.close()

    # 1、认证接口 测试
    # 认证接口不需要参数化的原因是:只有一个可测的用例,其他两个测试用例是bug,不适合拿来做实战
    def test01_approve(self,expect_test="提交成功"):
        try:
            r = self.approve.api_approve()
            # print(r.json())
            log.info("正在执行认证接口响应结果为:{}".format(r.text))
            self.assertIn(expect_test,r.text)
            log.info("认证接口断言成功!")
        except Exception as err:
            # 日志
            log.error("断言失败,原因:{}".format(err))
            # 抛异常
            raise


    #2、查询认证状态接口 测试
    # 不需要参数化的原因是:只有一个可测的用例,
    def test02_approve_status(self,expect_test="华"):
        try:
            r = self.approve.api_approve_status()
            # print(r.json())
            log.info("正在执行查询认证状态接口响应结果为:{}".format(r.text))
            self.assertIn(expect_test, r.text)
            log.info("查询认证状态接口断言成功!")
        except Exception as err:
            # 日志
            log.error("断言失败,原因:{}".format(err))
            # 抛异常
            raise

    #3、开户接口 测试
    def test03_trust(self,expect_test="form"):
        try:
            # 1、请求后台开户接口
            r = self.approve.api_trust()
            # print(r.json())
            log.info("正在执行开户接口响应结果为:{}".format(r.json()))
            self.assertIn(expect_test, r.text)
            log.info("认证开户断言成功!")
            # 2、请求第三方开户接口
            result = parser_html(r) # 结果为:(’http://xxxx‘,‘{'xxx':'xxx'},……’)
            r = self.session.post(url=result[0],data=result[1])
            # print(r.text) # 结果为:UserRegister OK
            self.assertIn("OK",r.text)
            log.info("请求第三方开户断言成功!")

        except Exception as err:
            # 日志
            log.error("断言失败,原因:{}".format(err))
            # 抛异常
            raise

    #4、获取图片验证码接口 测试
    @parameterized.expand(read_json("approve_trust.json","img_code"))
    def test04_img_code(self,random,expect_code):
        try:
            r = self.approve.api_img_code(random)
            # print(r.status_code)
            log.info("正在执行获取图片验证码接口响应结果为:{}".format(r.status_code))
            self.assertEqual(expect_code, r.status_code)
            log.info("断言获取图片验证码接口成功!")


        except Exception as err:
            # 日志
            log.error("断言失败,原因:{}".format(err))
            # 抛异常
            raise

    #5、充值接口 测试
    @parameterized.expand(read_json("approve_trust.json","recharge"))
    def test05_recharge(self,valicode,expect_text):
        try:
            # 1、调用图片验证码接口
            self.approve.api_img_code(123)
            # 2、充值接口
            r = self.approve.api_recharge(valicode)
            # print("充值接口响应结果:",r.text)
            log.info("正在执行充值接口响应结果为:{}".format(r.json()))
            if valicode == 8888:
                # # 断言
                self.assertIn("form", r.text)
                log.info("断言充值接口成功!")
                # 3、三方充值
                result = parser_html(r)  # 结果为:(’http://xxxx‘,‘{'xxx':'xxx'},……’)
                r = self.session.post(url=result[0], data=result[1])
                self.assertIn(expect_text, r.text)
                log.info("请求第三方充值断言成功!")
            else:
                # print("验证码错误的响应结果:",r.text)
                self.assertIn(expect_text,r.text)

        except Exception as err:
            # 日志
            log.error("断言失败,原因:{}".format(err))
            # 抛异常
            raise




2、BeautifulSoup库

1️⃣简介及例子 

说明:⼀个python解析html/xml的三方库

安装: pip install beautifulsoup4 -i https://mirrors.tuna.tsinghua.edu.cn/ 

基本用法

应用步骤:

  • 1、导包
  • 2、实例化
  • 3、调用方法

例子:

重点:

1、查找所有标签 bs.find_all("标签名") == 元素的集合 == ["元素1","元素2"]

2、查找属性 元素.get("属性名")

其他方法:

2️⃣提取html数据工具封装

 ①思路:

②实现

在工具类py文件末尾添加下面的封装方法

from bs4 import BeautifulSoup
def parser_html(result):
    # 1、提取html
    html = result.json().get("description").get("form")
    # 2、获取bs对象
    bs = BeautifulSoup(html,"html.parser")
    # 3、提取url
    url = bs.form.get("action")
    data = {}
    # 4、查找所有的input标签
    for input in bs.find_all("input"):
        data[input.get("name")]=input.get("value")
    return url, data

使用BeautifulSoup库后就可以实现三方开户和三方充值了,代码已经在前文2️⃣script目录展示过。

3、认证开户参数化

实现难点:

 

{
  "img_code": [
    {
      "desc": "获取图片验证码成功(随机小数)",
      "random": 0.123,
      "expect_code": 200
    },
    {
      "desc": "获取图片验证码成功(随机整数)",
      "random": 123,
      "expect_code": 200
    },
    {
      "desc": "获取图片验证码失败(随机数为空)",
      "random": "",
      "expect_code": 404
    },
    {
      "desc": "获取图片验证码失败(随机数为字符串)",
      "random": "123hello",
      "expect_code": 400
    }
  ],
  "recharge": [
    {
      "desc": "后台充值响应成功",
      "valicode": 8888,
      "expect_text": "OK"
    },
    {
      "desc": "后台充值响应成功",
      "valicode": 8889,
      "expect_text": "验证码错误"
    }
  ]
}

添加了参数化的完整认证开户script文件已在前文展示:2️⃣script目录

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/954316.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

基于springboot+vue+微信小程序的宠物领养系统

基于springbootvue微信小程序的宠物领养系统 一、介绍 本项目利用SpringBoot、Vue和微信小程序技术&#xff0c;构建了一个宠物领养系统。 本系统的设计分为两个层面&#xff0c;分别为管理层面与用户层面&#xff0c;也就是管理者与用户&#xff0c;管理权限与用户权限是不…

【微服务】面试题 5、分布式系统理论:CAP 与 BASE 详解

分布式系统理论&#xff1a;CAP 与 BASE 详解 一、CAP 定理 背景与定义&#xff1a;1998 年由加州大学科学家埃里克布鲁尔提出&#xff0c;分布式系统存在一致性&#xff08;Consistency&#xff09;、可用性&#xff08;Availability&#xff09;、分区容错性&#xff08;Part…

【Vue】Vue组件--上

目录 一、组件基础 二、组件的嵌套关系 1. 基础架构 2. 嵌套 三、组件注册方式 1. 局部注册&#xff1a; 2. 全局注册&#xff1a; 四、组件传递数据 1. 基础架构 2. 传递多值 3. 动态传递数据 五、组件传递多种数据类型 1. Number 2. Array 3. Object 六、组…

鸿蒙UI开发——键盘弹出避让模式设置

1、概 述 我们在鸿蒙开发时&#xff0c;不免会遇到用户输入场景&#xff0c;当用户准备输入时&#xff0c;会涉及到输入法的弹出&#xff0c;我们的界面针对输入法的弹出有两种避让模式&#xff1a;上抬模式、压缩模式。 下面针对输入法的两种避让模式的设置做简单介绍。 2、…

python Streamlit和AKShare 实现的股票数据查询系统

1. 系统概述 这是一个基于Streamlit和AKShare的股票数据查询系统&#xff0c;提供了便捷的股票数据查询和可视化功能。系统支持按板块筛选股票、多股票代码查询、数据导出等功能。 1.1 主要功能 股票代码直接输入查询按板块筛选和选择股票历史数据和实时行情查询财务报表数据…

蓝桥杯备赛:顺序表和单链表相关算法题详解(上)

目录 一.询问学号&#xff08;顺序表&#xff09; 1.题目来源&#xff1a; 2.解析与代码实现&#xff1a; &#xff08;1&#xff09;解析&#xff1a; &#xff08;2&#xff09;代码实现&#xff1a; 二.寄包柜&#xff08;顺序表&#xff09; 1.题目来源&#xff1a; …

数据结构-ArrayLIst-一起探索顺序表的底层实现

各位看官早安午安晚安呀 如果您觉得这篇文章对您有帮助的话 欢迎您一键三连&#xff0c;小编尽全力做到更好 欢迎您分享给更多人哦 大家好&#xff0c;我们今天来学习java数据结构的第一章ArrayList&#xff08;顺序表&#xff09; 1.ArrayList的概念 那小伙伴就要问了线性表到…

RabbitMQ(四)

SpringBoot整合RabbitMQ SpringBoot整合1、生产者工程①创建module②配置POM③YAML④主启动类⑤测试程序 2、消费者工程①创建module②配置POM③YAML文件内配置&#xff1a; ④主启动类⑤监听器 3、RabbitListener注解属性对比①bindings属性②queues属性 SpringBoot整合 1、生…

初始Java4

目录 一.继承 1.定义&#xff1a; 2.继承的语法&#xff1a; 3.子类访问父类 4.子类构造方法 5.super与this 6.继承方法 7.final关键字 &#xff08;1&#xff09;.变量不变 &#xff08;2&#xff09;.方法不变 &#xff08;3&#xff09;.类不可继承 8.继承与组合…

极限竞速 地平线5“d3dx12_43.dll”文件丢失或错误导致游戏运行异常如何解决?windows系统DLL文件修复方法

d3dx12_43.dll是存放在windows系统中的一个重要dll文件&#xff0c;缺少它可能会造成部分软件不能正常运行。当你的电脑弹出提示“无法找到d3dx12_43.dll”或“计算机缺少d3dx12_43.dll”等错误问题&#xff0c;请不用担心&#xff0c;我们将深入解析DLL文件错误的成因&#xf…

Leecode刷题C语言之超过阈值的最小操作数②

执行结果:通过 执行用时和内存消耗如下&#xff1a; // 最小堆的节点结构体 typedef struct {long long* heap;int size;int capacity; } MinHeap;// 初始化最小堆 MinHeap* createMinHeap(int capacity) {MinHeap* minHeap (MinHeap*)malloc(sizeof(MinHeap));minHeap->s…

[Qt]常用控件介绍-按钮类控件-QPushButton、QRedioButton、QCheckBox、QToolButton控件

目录 1.QPushButton按钮 介绍 属性 Demo&#xff1a;键盘方向键控制人物移动 2.Redio Button按钮 属性 clicked、pressed、released、toggled区别 单选按钮的分组 Demo&#xff1a;点餐小程序 3.CheckBox按钮 属性 Demo&#xff1a;获取今天的形成计划 4.ToolBu…

寒假第一次牛客周赛 Round 76回顾

AC数&#xff1a;2&#xff08;A、C&#xff09; B 思路&#xff1a; 等价于求&#xff1a; 数量最多的字符 #include<stdio.h> int main() {int n,num;int a[26]{0};//用于存储字母 a 到 z 的出现次数。scanf("%d",&n);char s[n];scanf("%s",s)…

StyleGaussian: Instant 3D Style Transferwith Gaussian Splatting 论文解读

目录 一、概述 二、相关工作 1、辐射场 2、3D编辑 3、风格迁移 三、StyleGaussian 1、特征嵌入 2、风格迁移 3、解码 四、实验 1、不同backbone下的量化和定性指标 2、解码器设计上的测试 3、内容损失平衡 4、风格平滑插值 一、概述 提出了StyleGaussian&#x…

基于django实现类似ebay的电子商务系统全英文

完整源码项目包获取→点击文章末尾名片&#xff01;

win32汇编环境,窗口程序中组合框的应用举例

;运行效果 ;win32汇编环境,窗口程序中组合框的应用举例 ;比如在窗口程序中生成组合框&#xff0c;增加子项&#xff0c;删除某项&#xff0c;取得指定项内容等 ;直接抄进RadAsm可编译运行。重点部分加备注。 ;以下是ASM文件 ;>>>>>>>>>>>>…

Docker 镜像制作原理 做一个自己的docker镜像

一.手动制作镜像 启动容器进入容器定制基于容器生成镜像 1.启动容器 启动容器之前我们首先要有一个镜像&#xff0c;这个镜像可以是从docker拉取&#xff0c;例如&#xff1a;现在pull一个ubuntu镜像到本机。 docker pull ubuntu:22.04 我们接下来可以基于这个容器进行容器…

微信小程序获取openid

2025年1月15日&#xff1a; 1、现在云服务器上安装nodejs&#xff0c;然后写个get接口&#xff1a; const express require(express); const app express();app.get(/getOpenid,(req,res)>{res.send("success"); })app.listen(3000,()>{console.log(server…

ASP.NET Core - 配置系统之配置添加

ASP.NET Core - 配置系统之配置添加 2. 配置添加 2. 配置添加 配置系统可以读取到配置文件中的信息&#xff0c;那必然有某个地方可以将配置文件添加到配置系统中。之前的文章中讲到 ASP.NET Core 入口文件中&#xff0c;builder(WebApplicationBuilder 对象) 中有一个 Config…

C#中通道(Channels)的应用之(生产者-消费者模式)

一.生产者-消费者模式概述 生产者-消费者模式是一种经典的设计模式&#xff0c;它将数据的生成&#xff08;生产者&#xff09;和处理&#xff08;消费者&#xff09;分离到不同的模块或线程中。这种模式的核心在于一个共享的缓冲区&#xff0c;生产者将数据放入缓冲区&#x…