【金融项目实战】7_接口测试 _代码实现接口测试(重点)

文章目录

  • 一、基于代码实现自动化
    • [1.1 代码实现自动化相关理论](#1.1 代码实现自动化相关理论)
    • [1.2 代码实现接口自动化步骤](#1.2 代码实现接口自动化步骤)
  • 二、具体代码框架实现
    • [2.1 api](#2.1 api)
      • [2.1.1 __ init __.py](#2.1.1 __ init __.py)
      • [2.1.2 api_register_login.py](#2.1.2 api_register_login.py)
      • [2.1.3 api_approve_trust.py](#2.1.3 api_approve_trust.py)
      • [2.1.4 api_recharge.py](#2.1.4 api_recharge.py)
      • [2.1.5 api_tender.py](#2.1.5 api_tender.py)
      • [2.1.6 api_factory.py](#2.1.6 api_factory.py)
    • [2.2 script](#2.2 script)
      • [2.2.1 test01_register_login.py](#2.2.1 test01_register_login.py)
      • [2.2.2 test02_approve_trust.py](#2.2.2 test02_approve_trust.py)
      • [2.2.3 test03_recharge.py](#2.2.3 test03_recharge.py)
      • [2.2.4 test04_tender.py](#2.2.4 test04_tender.py)
      • [2.2.5 test05_tender_list.py](#2.2.5 test05_tender_list.py)
    • [2.3 data](#2.3 data)
      • [2.3.1 register_login.json](#2.3.1 register_login.json)
      • [2.3.2 tender.json](#2.3.2 tender.json)
    • [2.4 config.py](#2.4 config.py)
    • [2.5 tool.py](#2.5 tool.py)
    • [2.6 log](#2.6 log)
    • [2.7 report](#2.7 report)
    • [2.8 pytest.ini](#2.8 pytest.ini)
  • 三、持续集成
  • 四、小技巧
    • [4.1 接口参数化步骤](#4.1 接口参数化步骤)
    • [4.2 日志](#4.2 日志)
    • [4.3 抛异常](#4.3 抛异常)

一、基于代码实现自动化

1.1 代码实现自动化相关理论

  • 代码编写脚本和工具实现脚本区别是啥?
yacas 复制代码
代码︰
- 优点:代码灵活方便
- 缺点:学习成本高

工具:
- 优点:易上手
- 缺点:灵活度低,有局限性。

1.2 代码实现接口自动化步骤

yacas 复制代码
1、抽取功能用例作为自动化用例;
2、搭建环境(测试工具)
3、搭建目录结构
4、实现测试脚本(实现目录结构中内容)
5、运行调试
6、持续集成

1、抽取功能用例作为自动化用例:

2、搭建环境(测试工具)

python 复制代码
python解释器+pycharm(集成开发工具)+requests+pytest(测试框架,用例管理和执行的框架)+allure+parameterize参数化

3、搭建目录结构

yacas 复制代码
思想:分层
重点:
1、api(封装-被测接口封装实现)
2、script(调用-测试业务)
辅助:
3、log(日志-存储脚本运行日志)
4、data(测试数据)
5、report(测试报告)
6、tools(工具)
7、config.py (公共变量)
8、pytest.ini (pytest框架配置文件)

4、实现测试脚本(实现目录结构中内容)

5、运行调试

6、持续集成

二、具体代码框架实现

2.1 api

2.1.1 __ init __.py

python 复制代码
from tool import GetLog
# 日志器
log = GetLog.get_log()

2.1.2 api_register_login.py

python 复制代码
import requests

from api import log
from config import BASE_URL

""""
重点:封装注册登录模块相关被测的接口
"""

class ApiRegisterLogin():
    # 初始化
    def __init__(self, session):
        # 获取session对象。
        # 谁用谁传入,传过来的session变成实例属性。因为下面的接口调用,需要调用session相关的方法。
        self.session = session
        # 获取图片验证码url
        self.__url_img_code = BASE_URL + "/common/public/verifycode1/{}"
        # 获取短信验证码url
        self.__rl_phone_code = BASE_URL + '/member/public/sendSms'
        # 注册接口url
        self.__url_register = BASE_URL + '/member/public/reg'
        # 登录接口url
        self.__url_login = BASE_URL + '/member/public/login'
        # 查询登录状态url
        self.__url_login_status = BASE_URL + '/member/public/islogin'

    # 1、获取图片验证码接口 封装
    def api_img_code(self, random):
        log.info("正在调用获取图片验证码接口,请求方法:get 请求url: {}".format(self.__url_img_code.format( random)))
        # 调用get方法,传入图片验证码url
        return self.session.get(url = self.__url_img_code.format(random))

    # 2、获取短信验证码接口 封装
    def api_phone_code(self,phone,imgVerifyCode):
        #①定义请求参数
        data = {'phone': phone,'imgVerifyCode': imgVerifyCode ,'type':'reg'}

        log.info("正在调用获取短信验证码接口,请求方法:post 请求url: {} 请求参数:{}".format(self.__url_phone_code,data))
        #②调用请求方法
        response = self.session.post(url = self.__url_phone_code,data=data)
        #返回响应
        return response

    # 3、注册接口封装 封装
    def api_register(self,phone,password,imgVerifyCode,phone_code):
        data = {"phone": phone,
                "password": password,
                "verifycode": imgVerifyCode,
                "phone_code": phone_code,
                "dy_server": "on",
                'invite_phone':" "}
        log.info("正在调用注册接口,请求方法:post 请求url: {} 请求参数:{}".format(self.__url_register,data))
        response = self.session.post(url=self.__url_register, data=data)
        return response

    # 4、登录接口 封装
    def api_login(self,keywords,pwd):
        data = {"keywords": keywords,"password": pwd}
        log.info("正在调用登录接口,请求方法:post 请求url: {} 登录参数:{}".format(self.__url_login,data))
        response = self.session.post(url=self.__url_login, data=data)
        return response

    # 5、查询接口 封装
    def api_login_status(self):
        log.info("正在调用查询登录状态接口,请求方法:post 登录url: {}".format(self.__url_login_status))
        return self.session.post(url = self.__url_login_status)

2.1.3 api_approve_trust.py

python 复制代码
from config import BASE_URL


class ApiApproveTrust():
    # 初始化
    def __init__(self, session):
        # 获取session对象,将实例化创建的session对象传过来,然后变成实例属性
        self.session = session
        # 认证url
        self.__url_approve = BASE_URL + '/member/realname/approverealname'
        # 查询认证状态url
        self.__url_approve_status = BASE_URL + '/member/member/getapprove'
        # 开户url(后台开户)
        self.__url_trust = BASE_URL + '/trust/trust/register'


    # 1、认证接口 封装
    def api_approve(self,session,realname,cardId):
        # ① 请求数据
        data = {"realname": realname, "card_id": cardId}
        # ②调用方法,难点请求要求multipart-form/data -->data +files
        response = self.session.post(self.__url_approve, data=data, files={'x': 'y'})
        return response


    # 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)

2.1.4 api_recharge.py

python 复制代码
from api import log
from config import BASE_URL


class ApiRecharge:
    def __init__(self):
        # 获取session对象
        self.session = session
        # 充值验证码url
        self.__url_code = BASE_URL + "/common/public/verifycode/{}"
        # 后台充值url
        self.__url_recharge = BASE_URL + "/trust/trust/recharge"


    """测试几个接口,封装几个"""
    # 1、充值验证码接口,封装
    def api_img_code(self, random):
        log.info("正在调用充值验证码接口,请求方法get 请求url:{}".format(self.__url_code.format(random)))
        # 调用get方法
        return self.session.get(url = self.__url_code.format(random))

    # 2、后台充值接口,封装
    def api_recharge(self, data):
        data = {
            "paymentType": "chinapnrTrust",
            "amount": 100000,
            "formStr": "reForm"
            "valicode":"8888"
        }
        log.info("正在后台充值接口,请求方法post 请求url:{} 请求参数".format(self.__url_recharge, data))
        return self.session.post(url = self.__url_recharge, data = data)

2.1.5 api_tender.py

python 复制代码
from config import BASE_URL


class ApiTender:
    # 初始化
    def __init__(self):
        # 获取session
        self.session = session
        # 后台投资url
        self.__url_tender = BASE_URL + "/trust/trust/tender"

    # 后台投资接口封装
    def api_tender(self, amount):
        # 请求参数
        data = {
            "id": 642,
            "depositCertificate": -1,
            "amount":amount,
        }
        # 请求方法
        return self.session.post(url=self.__url_tender, data=data)

2.1.6 api_factory.py

python 复制代码
# 工厂模式,管理所有的api
from api.api_approve_trust import ApiApproveTrust
from api.api_recharge import ApiRecharge
from api.api_register_login import ApiRegisterLogin
from api.api_tender import ApiTender


class ApiFactory:
    def __init__(self):
        self.session = session

    # 获取注册登录api对象
    def get_register_login(self):
        return ApiRegisterLogin(self.session)
    # 获取认证api对象
    def get_approve(self):
        return ApiApproveTrust(self.session)
    # 获取开户充值api对象
    def get_recharge(self):
        return ApiRecharge(self.session)
    # 获取投资对象
    def get_tender(self):
        return ApiTender(self.session)

2.2 script

2.2.1 test01_register_login.py

python 复制代码
import requests

from api import log
from api.api_register_login import ApiRegisterLogin
from tool import common_assert, read_json, clear_data


class TestRegisterLogin:
    def setup_class(cls):
        log.info("正在清除数据库注册数据····")
        # 只能用类方法,调用清除测试数据
        clear_data()
        log.info("数据库注册数据清理完成")

    # 初始化
    def setUp(self):
        # 创建session对象
        self.session = requests.Session()
        log.info("正在获取session对象:{}".format(self.session))
        # 获取 ApiRegisterLogin实例对象
        self.api=ApiRegisterLogin(self.session)
        log.info("正在获取ApiRegisterLogin实例对象:{}".format(self.api))
    # 结束
    def tearDown(self):
        # 关闭session对象
        self.session.close()
        log.info("正在关闭session对象:{}".format(self.session))

    """" 测试方法 """
    # 1、图片验证码接口测试
    @pytest.mark.parametrize("random,expect_code",read_json("register_login.json","img_code"))
    def test01_img_code(self,random,expect_code):
        try:
            result = self.api.api_img_code(random)
            log.info("图片验证码接口返回结果:{}".format(result.status_code))
            common_assert(result,status_code=expect_code)
            log.info("图片验证码断言通过")
            print(result.status_code)
        except Exception as e:
            # 捕获异常的目的就是记录错误日志
            print("错误:", e)
            log.error(e)
            # 抛异常
            raise


    # 2、短信验证码接口测试
    @pytest.mark.parametrize("phone,imgVerifyCode,expect_json", read_json("register_login.json", "phone_code"))
    def test02_phone_code(self,phone,imgVerifyCode,expect_json):
        try:
            # ①请求图片验证码
            self.api.api_img_code(123123)
            # ②调用手机短信接口
            result = self.api.api_phone_code(phone,imgVerifyCode)
            log.info("短信验证码接口返回结果:{}".format(result.text))
            common_assert(result, expect_json=expect_json)
            log.info("短信验证码断言通过")  # 如果这句话输出,说明上面断言通过
            print(result.json())
        except Exception as e:
            # 捕获异常的目的就是记录错误日志
            print("错误:", e)
            log.error(e)
            # 抛异常
            raise

    # 3、注册接口测试
    @pytest.mark.parametrize("phone,password,imgVerifyCode,phone_code,expect_json",read_json("register_login.json","register"))
    def test03_register(self,phone,password,imgVerifyCode,phone_code,expect_json):
        try:
            # ① 调用图片验证码
            self.api.api_img_code(123123)
            # ② 调用手机验证码
            self.api.api_phone_code(phone,imgVerifyCode)
            # ③调用注册接口
            result = self.api.api_register(phone,password,imgVerifyCode=imgVerifyCode,phone_code=phone_code)
            log.info("注册接口返回结果:{}".format(result.text))
            common_assert(result, expect_json=expect_json)
            log.info("注册接口断言通过")
        except Exception as e:
            # 捕获异常的目的就是记录错误日志
            print("错误:", e)
            log.error(e)
            # 抛异常
            raise


    # 4、登录接口测试,
    # 这个参数化最难,如何处理错误密码业务逻辑
    @pytest.mark.parametrize("keywords,password,expect_json",read_json("register_login.json", "login"))
    def test04_login(self,keywords,password,expect_json):
        try:
            i = 1
            result = None
            if password == "error123":
                while i<=3:
                    result = self.api.api_login(keywords, password)
                    log.info("登录接口返回结果:{}".format(result.text))
                    i +=1
                assert "锁定" in result.text
                log.info("登录-->锁定断言通过")
                sleep(60)
                # 登录成功 ->判断解锁
                result = self.api.api_login("13600001111", "test123")
                log.info("登录接口返回结果:{}".format(result.text))
                common_assert(result, expect_json=expect_json)
                log.info("登录接口断言通过")
            else:
                result = self.api.api_login(keywords,password)
                common_assert(result, expect_json=expect_json)
        except Exception as e:
            # 捕获异常的目的就是记录错误日志
            print("错误:", e)
            log.error(e)
            # 抛异常
            raise

    # 5、查询登录状态接口 测试
    @pytest.mark.parametrize("status,expect_json",read_json("register_login.json", "login_status"))
    def test05_login_status(self,status,expect_json):
        try:
            if status == "已登录":
                # 调用登录
                self.api.api_login("13600001111","test123")
            # 调用查询登录状态接口
            result = self.api.api_login_status()
            log.info("查询登录状态接口返回结果:{}".format(result.text))
            common_assert(result, expect_json=expect_json)
            log.info("查询登录状态接口断言通过")

        except Exception as e:
            # 捕获异常的目的就是记录错误日志
            print("错误:", e)
            log.error(e)
            # 抛异常
            raise

2.2.2 test02_approve_trust.py

python 复制代码
import requests

from api import log
from api.api_approve_trust import ApiApproveTrust
from api.api_register_login import ApiRegisterLogin
from tool import common_assert, html_parser


class TestApproveTrust:
      # 初始化
    def setUp(self):
        # 获取session对象
        self.session = requests.session()
        # 获取ApiApproveTrust对象
        self.api = ApiApproveTrust(self.session)
        # 获取ApiRegisterLogin对象并调用登录
        ApiRegisterLogin(self.session).api_login("13600001111", "test123")

    # 结束
    def tearDown(self):
        self.session.close()

    # 1、认证接口测试
    def test01_approve(self,expect_json = "提交成功"):
        try:
        # 调用认证接口
            result = self.api.api_approve()
            log.info('认证接口执行结果为:{}'.format(result.text))
            common_assert(result, expect_json=expect_json)
            log.info('认证接口断言通过')
        except Exception as e:
            log.error(e)
            raise

    # 2、查询认证状态接口测试
    def test02_approve_status(self, expect_text = "1111"):
        try:
        # 查询认证状态接口
            result = self.api.api_Approve_status()
            log.info('查询认证状态接口执行结果为:{}'.format(result.text))
            common_assert(result, expect_text=expect_text)
            log.info('查询认证状态接口断言通过')
        except Exception as e:
            log.error(e)
            raise

    # 3、后台开户接口测试
    def test03_trust(self,expect_text="form",expect_text2= "ok"):
        try:
        # 后台开户接口
            result = self.api.api_trust()
            log.info('后台开户接口执行结果为:{}'.format(result.json()))
            common_assert(result, expect_text=expect_text)
            log.info('后台开户接口断言通过')
            # 三方开户如何实现?-依赖后台开户响应结果
            data = html_parser(result)
            result = self.session.post(url=data[0], data=data[1])
            print("三方开户执行结果为:", result.text)
            common_assert(result, expect_text=expect_text2)
            log.info('三方开户执行结果为:{}'.format(result.text))
        except Exception as e:
            log.error(e)
            raise

2.2.3 test03_recharge.py

python 复制代码
import requests

from api import log
from api.api_recharge import ApiRecharge
from api.api_register_login import ApiRegisterLogin
from tool import html_parser, common_assert


class TestRecharge:
    # 初始化
    def setup(self):
        # 获取session对象
        self.session = requests.session()
        # 获取ApiRecharge实例对象
        self.api = ApiRecharge(self.session)
        # 登录
        ApiRegisterLogin(self.session).api_login()

    # 结束
    def teardown(self):
        self.session.close()

    # 充值验证码接口测试方法
    def test01_img_code(self, random=123123):
        try:
            result = self.api.api_img_code(random)
            print(result.status_code)
            log.info("充值验证码执行结果为:{}".format(result.status_code))
        except Exception as e:
            log.error(e)
            raise

    # 后台充值接口测试方法
    def test02_recharge(self,expect_text="OK"):
        try:
            self.api.api_img_code(random)
            result = self.api.api_recharge()
            print(result.status_code)
            log.info("后台充值接口执行结果为:{}".format(result.json()))
            # 三方充值如何实现?-依赖后台开户响应结果
            data = html_parser(result)
            result = self.session.post(url=data[0], data=data[1])
            print("三方开户执行结果为:", result.text)
            common_assert(result, expect_text=expect_text)
            log.info('三方充值执行结果为:{}'.format(result.text))
        except Exception as e:
            log.error(e)
            raise

2.2.4 test04_tender.py

python 复制代码
import requests

from api import log
from api.api_register_login import ApiRegisterLogin
from api.api_tender import ApiTender
from tool import html_parser, common_assert


class TestTender:
    # 初始化
    def setup(self):
        # 获取session对象
        self.session = requests.session()
        # 获取ApiTender实例对象
        self.api = ApiTender(self.session)
        # 登录
        ApiRegisterLogin(self.session).api_login()

    # 结束
    def teardown(self):
        self.session.close()


    @pytest.mark.parametrize("amount,expect_text", read_json("tender.json","tender"))
    def test01_tender(self,amount,expect_text):
        try:
            result = self.api.api_tender(amount)
            log.info("后台投资接口为:{}".format(result.json()))
            if expect_text == "OK":
                # 三方充投资如何实现?-依赖后台开户响应结果
                data = html_parser(result)
                result = self.session.post(url=data[0], data=data[1])
                log.info('三方投资执行结果为:{}'.format(result.text))
            common_assert(result, expect_text=expect_text)
        except Exception as e:
            log.error(e)
            raise

2.2.5 test05_tender_list.py

python 复制代码
from api import log
from api.api_factory import ApiFactory
import requests

from tool import html_parser


class TestTenderList:
    # 初始化
    def setup(self):
        self.session = requests.session()
        self.api = ApiFactory(self.session)
    # 结束
    def teardown(self):
        self.session.close()

    def test01_tender_list(self):
        try:
            # 1、获取图片验证码接口
            self.api.get_register_login().api_img_code(123123)
            # 2、获取短息验证码接口
            self.api.get_register_login().api_phone_code("13600001111",8888)
            # 3、注册接口
            self.api.get_register_login().api_register("13600001111","test123","8888",666666)
            # 4、登录接口
            self.api.get_register_login().api_login()
            # 5、认证接口
            self.api.get_approve().api_approve()
            # 6、后台开户接口
            result = self.api.get_approve().api_trust()
            # 7、三方开户
            data = html_parser(result)
            result = self.session.post(url=data[0], data=data[1])
            log.info('三方开户接口执行结果为:{}'.format(result.text))
            # 8、充值验证码接口
            self.api.get_recharge().api_img_code(88881123)
            # 9、后台充值接口
            result = self.api.get_recharge().api_recharge()
            # 10、三方充值接口
            data = html_parser(result)
            result = self.session.post(url=data[0], data=data[1])
            log.info('三方充值接口执行结果为:{}'.format(result.text))
            # 11、后台投资接口
            result = self.api.get_tender().api_tender(100)
            # 12、三方投资接口
            data = html_parser(result)
            result = self.session.post(url=data[0], data=data[1])
            log.info('三方投资接口执行结果为:{}'.format(result.text))

        except Exception as e:
            log.error(e)
            raise

2.3 data

2.3.1 register_login.json

json 复制代码
{
  "img_code": [
    {
      "desc": "获取图片验证码成功(随机整数)",
      "random": 123123,
      "expect": 200
    },
    {
      "desc": "获取图片验证码成功(随机小数)",
      "random": 0.123123,
      "expect": 200
    },
    {
      "desc": "获取图片验证码失败(随机数为空)",
      "random": "",
      "expect": 404

    },
    {
      "desc": "获取图片验证码失败(随机数为字符串)",
      "random": "123123a",
      "expect": 400
    }
  ],
  "phone_code": [
    {
      "desc": "获取短信验证码成功",
      "phone": "13600001111",
      "imgVerifyCode": "8888",
      "expect_json": "成功"
    },
    {
      "desc": "获取短信验证码失败(图片验证码错误)",
      "phone": "13600001111",
      "imgVerifyCode": "8889",
      "expect_json": "错误"
    }
  ],
  "register": [
    {
      "desc": "注册成功",
      "phone": "13600001111",
      "password": "test123",
      "verifycode": "8888",
      "phone_code": "6666",
      "expect_json": "成功"
    },
    {
      "desc": "注册失败(图片验证码错误)",
      "phone": "13600001112",
      "password": "test123",
      "verifycode": "8889",
      "phone_code": "6666",
      "expect_json": "错误"
    },
    {
      "desc": "注册失败(手机验证码错误)",
      "phone": "1360000112",
      "password": "test123",
      "verifycode": "8888",
      "phone_code": "6666",
      "expect_json": "错误"
    },
    {
      "desc": "注册失败(手机号已注册)",
      "phone": "13600001111",
      "password": "test123",
      "verifycode": "8888",
      "phone_code": "6666",
      "expect_json": "已存在"
    }
  ],
  "login": [

    {
      "desc": "登录成功",
      "keywords": "13600001111",
      "password": "test123",
      "expect_json": "成功"
    },
    {
      "desc": "登录失败(手机号未注册)",
      "keywords": "13600001112",
      "password": "test123",
      "expect_json": "不存在"
    },
    {
      "desc": "登录失败(密码为空)",
      "keywords": "13600001111",
      "password": "",
      "expect_json": "为空"
    },
    {
      "desc": "登录成功(锁定)",
      "keywords": "13600001111",
      "password": "error123",
      "expect_json": "成功"
    }
  ],
  "login_status": [
    {
      "desc": "查询登录状态(已登录)",
      "status": "已登录",
      "expect_json": "ok"
    },
    {
      "desc": "查询登录状态(未登录)",
      "status": "已登录",
      "expect_json": "未登"
    }
  ]
}

2.3.2 tender.json

json 复制代码
{
  "tender": [
    {
      "desc":"后台投资成功",
      "amount": 100,
      "expect_text": "OK"
  },
    {
      "desc":"请求后台投资失败(金额为空)",
      "amount": "",
      "expect_text": "不是正确的金额"
  }
  ]
}

2.4 config.py

python 复制代码
import os

# 项目服务器地址
BASE_URL = "http://user-p2p-test.itheima.net"

# 项目目录
DIR_PATH = os.path.dirname(__file__)

2.5 tool.py

python 复制代码
# 断言工具封装
# response响应结果,响应对象传过来
import os, json, logging.handlers
from bs4 import BeautifulSoup
from config import DIR_PATH
import  pymysql



def common_assert(response,status_code=None,expect_json=None,expect_text=None):
    # 如果status_code不为空,那么就断言
    if status_code:
        assert response.status_code == status_code, "状态码断言错误,预期状态码:{} != 实际状态码:{}".format(status_code,response.status_code)
    if expect_json:
        assert expect_json in response.json().get("description"), " json断言错误.实际结果:{} 不包含 预期结果:{}".format(response.json().get("description"),expect_json)
    if expect_text:
        assert expect_text in response.text, "text断言错误, 响应结果:{} 不包含 预期结果:{}".format(response.text,expect_text)


# 读取json工具
def read_json(filename,key):
    filepath = DIR_PATH + os.sep + "data" + os.sep + filename
    arrs = []
    with open(filepath,"r",encoding="utf-8") as f:
       for data in json.load(f).get(key):
          arrs.append(tuple(data.values())[1:])
    return arrs

# 日志工具
# 封装成类,保证对象的使用是同一个对象,否则多处调用会产生多个对象,在多事引用每行的记录都是重复的
class GetLog:
    log = None
    @classmethod
    def get_log(cls):
        if cls.log == None:
            # 1、初始化日志对象
            cls.log = logging.getLogger()
            # 2、设置日志级别,大写表示全局变量
            cls.log.setLevel(logging.INFO)
            # 3、创建控制台日志处理器和文件日志处理器
            filepath = DIR_PATH + os.sep + "log" + os.sep + "p2p.log"
            tf = logging.handlers.TimedRotatingFileHandler(filename = filepath,when="midnight",interval=1,backupCount=3,encoding="utf-8")
            # 4、设置日志格式,创建格式器
            fm = '%(asctime)s %(levelname)s [%(name)s] [%(filename)s(%(funcName)s:%(lineno)d)] - %(message)s'
            fmt = logging.Formatter(fm)
            # 5、将格式化器设置到日志处理器中
            tf.setFormatter(fmt)
            # 6、将日志处理器添加到日志对象
            cls.log.addHandler(tf)
        return cls.log


# 提取html信息
def html_parser(result):
    # 1、提取html.result.json()得到字典格式的数据
    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  # 以逗号分割,返回元祖


# 连接数据库共库
def connect_mysql():
    conn = None
    cursor = None
    try:
        # 获取连接对象
        conn = pymysql.connect(host="121.43.169.97",port=3306,user="root",password="p2p_student_2022",database="czbk_member",charset="utf8",autocommit= True)
        # 获取游标对象
        cursor = conn.cursor()
        # 执行sql语句
        cursor.execute(sql)
        # 返回什么结果
        if sql.lower().split()[0] == "select":
            # 返回所有结果
            return cursor.fetchall()
        else:
            return cursor.rowcount

    except Exception as e:
        print(e)
        # 回滚
        conn.rollback()
    finally:
        # 关闭游标对象
        if cursor:
            cursor.close()
        # 关闭连接对象
        if conn:
            conn.close()


# 清除数据
def clear_data():
    # python中不支持批量执行sql语句
    sql_1 = "delete info.* from mb_member as mb inner join mb_member_info as info on info.member_id = mb.id where mb.phone in ("13600001111","13600001112","13600001113","13600001114");"
    connect_mysql(sql_1)


    sql_2 = "delete login.* from mb_member as mb inner join mb_member_login_log as login on login.member_id = mb.id where mb.phone in ("13600001111","13600001112","13600001113","13600001114");"
    connect_mysql(sql_2)

    sql_3 = "delete from mb_member where phone in ("13600001111","13600001112","13600001113","13600001114");"
    connect_mysql(sql_3)

    sql_4 = "delete from mb_member_register_log where phone in ("13600001111","13600001112","13600001113","13600001114");"
    connect_mysql(sql_4)


if __name__ == '__main__':
    print(read_json("register_login.json","login_status"))
    GetLog.get_log().info("信息级别测试")


"""
 分析:parametrize ---> [()]
 核心:
   1、从json文件中读取数据
   2、再组装到列表、元祖中

"""

2.6 log

2.7 report

2.8 pytest.ini

ini 复制代码
[pytest]
addopts = -s --alluredir report
testpaths = ./script
python_files = test*.py
python_classes = Test*
python_functions = test*

三、持续集成

1、代码推上去和gitee代码管理。

2、启动 jenkins.war包。

shell 复制代码
java -jar jenkins.war

3、在jekins中,新建一个任务,选择"构建一个自由风格的软件项目"。然后配置源码和运行。

4、先从gitee上克隆仓库代码,然后运行

四、小技巧

4.1 接口参数化步骤

json 复制代码
1、编写数据存储文件json
2、编写读取工具方法 read_json()
3、使用参数化组件进行引用parametrize
json 复制代码
心得:
1、根据模块来新建json文件(1个模块1个json文件)
2、最外侧使用{},模块下几个接口,编写几个key,值为列表
3、列表值中,单接口有几组数据,就写几个[}.
4、每个{}中,组成格式:说明+要进行参数的参数+预期结果
json 复制代码
// 有几个接口,写几个key,值为列表。 在api_register_login.py中有5个接口
// []中有几组数据,就有几个{}

4.2 日志

yacas 复制代码
作用:
  1、记录程序运行步骤
  2、记录程序运行错误
位置:
  api层:info(记录步骤执行请求url、参数、方法)
  scripts层:执行结果+错误(捕获的异常)

4.3 抛异常

python 复制代码
try:
    result = self.api.api_img_code(random)
    common_assert(result,status_code=200)
    print(result.status_code)
except Exception as e:
    # 捕获异常的目的就是记录错误日志
    print("错误:", e)
    # 抛异常
    raise
相关推荐
深蓝电商API5 小时前
爬虫IP封禁后的自动切换与检测机制
爬虫·python
m0_550024635 小时前
持续集成/持续部署(CI/CD) for Python
jvm·数据库·python
B站_计算机毕业设计之家5 小时前
豆瓣电影数据采集分析推荐系统 | Python Vue Flask框架 LSTM Echarts多技术融合开发 毕业设计源码 计算机
vue.js·python·机器学习·flask·echarts·lstm·推荐算法
渣渣苏6 小时前
Langchain实战快速入门
人工智能·python·langchain
lili-felicity6 小时前
CANN模型量化详解:从FP32到INT8的精度与性能平衡
人工智能·python
数据知道6 小时前
PostgreSQL实战:详解如何用Python优雅地从PG中存取处理JSON
python·postgresql·json
ZH15455891316 小时前
Flutter for OpenHarmony Python学习助手实战:面向对象编程实战的实现
python·学习·flutter
玄同7656 小时前
SQLite + LLM:大模型应用落地的轻量级数据存储方案
jvm·数据库·人工智能·python·语言模型·sqlite·知识图谱
User_芊芊君子6 小时前
CANN010:PyASC Python编程接口—简化AI算子开发的Python框架
开发语言·人工智能·python