测试平台(二)后端开发(2)需求介绍及后端框架搭建

前言

本章主要讲述需求介绍及后端框架搭建


整体环境:

  • 前端:Vue
  • 后端:Flask
  • 数据库:mysql5.7
  • 持续集成:jenkins


一、需求介绍

  • 一般情况下,我们会根据整个需求再去设定对应的前后端技术框架,因为要实现的功能都很简单,后端直接用flask,比较轻量级

注意:这个平台只是简单打来练手的,告诉大家有一个简单的搭建思路并简单实现功能,因为正常情况下,公司的基础架构都早已搭建好了,并有很完善的功能,并且会直接在别人的开源项目下进行二次开发,不会像我们这样自己着手去打一个平台(又费时/又费力,打出来的效果还没别人开源的好)我们只需要在原公司基础架构上去实现自己的功能即可。

测试平台(二)后端开发(2)需求介绍及后端框架搭建_第1张图片

本次实战的整体功能,后端API实现简单来说:

1、实现【测试用例】的增删改查
2、实现【测试计划】的查询/新增
3、实现【构建记录】的查询/新增

可能稍微复杂点的逻辑就是【生成计划】这个操作
--> 不仅需要同步生成一条测试任务,将测试任务和测试用例关联上
--> 还要能同步调用jenkins,生成一条构建记录,并且把jenkins生成的测试报告给返回回来 


二、整体框架概要

测试平台(二)后端开发(2)需求介绍及后端框架搭建_第2张图片


三、后端框架概要

1、后端分层简要介绍

  • 为了让我们的代码更规范,我们后端分层实现,这个分层如果之前大家打过Java项目的话,是很好理解了

测试平台(二)后端开发(2)需求介绍及后端框架搭建_第3张图片

测试平台(二)后端开发(2)需求介绍及后端框架搭建_第4张图片


2、后端所有依赖包(requirements.txt)

  • 自己统一下载下相关依赖即可

测试平台(二)后端开发(2)需求介绍及后端框架搭建_第5张图片

Flask==2.0.3
Flask_Cors==3.0.10
flask_restx==0.5.1
Flask_SQLAlchemy==2.5.1
jenkinsapi==0.3.11
PyYAML==6.0
SQLAlchemy==1.4.39


四、具体框架搭建准备工作

1、启动类配置(app.py)

测试平台(二)后端开发(2)需求介绍及后端框架搭建_第6张图片

"""
    启动类
"""
import yaml
from flask import Flask
from flask_restx import Api, Namespace
from flask_sqlalchemy import SQLAlchemy
from sqlalchemy.orm import Session
from flask_cors import CORS

app = Flask(__name__)
api = Api(app)

# 用例的命名空间,CORS解决跨域问题
CORS(app, supports_credentials=True)

# 数据库配置
# 读取数据库配置
with open("../config/data.yml", encoding='utf-8') as f:
    result = yaml.safe_load(f)
    username = result.get("database").get('username')
    password = result.get("database").get('password')
    server = result.get("database").get('server')
    database = result.get("database").get('database')

app.config['SQLALCHEMY_DATABASE_URI'] = \
    f"mysql+pymysql://{username}:{password}@{server}/{database}?charset=utf8"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = True
# SQLALchemy 绑定app
db = SQLAlchemy(app)
db_session: Session = db.session


def add_router():
    from controller.testcase_controller import case_ns
    # 添加api的命名空间,解决swagger不展示内容的问题
    api.add_namespace(case_ns, "/testcase")


if __name__ == '__main__':
    add_router()
    app.run(debug=True, host="0.0.0.0", port=8888)

2、数据库配置(config/data.yml)

测试平台(二)后端开发(2)需求介绍及后端框架搭建_第7张图片

测试平台(二)后端开发(2)需求介绍及后端框架搭建_第8张图片

## 进行数据库的配置
database:
  username: root
  password: yy1998123
  server: localhost
  database: test_platform

3、实体类设计(do层)

实体类字段和数据库表字段是一一对应的,而我们在做需求的时候肯定是先把整个需求的逻辑理清楚,再去做,首先要做的就是把数据库表给设计出来,这里表就设计的很简单。

  • 测试计划和测试用例之间:多对多关系

    为什么要用中间表呢?
    如果说当表结构逻辑很复杂的话,那添加的外键就会越来越多,到时候表结构里面会有一堆和业务没那么有关系的外键

  • 测试计划和构建记录之间:一对多关系

测试平台(二)后端开发(2)需求介绍及后端框架搭建_第9张图片

测试平台(二)后端开发(2)需求介绍及后端框架搭建_第10张图片


3.1、testcase_entity.py

  • 之前分层说过,所有的实体类统一放在do目录下
"""
    测试用例实体类
"""
from sqlalchemy import *
from app import db


class TestCaseEntity(db.Model):
    # 表名
    __tablename__ = "testcase"
    # 用例ID 用例的唯 一标识
    id = db.Column(Integer, primary_key=True)
    # 用例的标题 或者文件名,限定 80个字符 ,不为空,并且唯一
    case_title = db.Column(String(80), nullable=False, unique=True)
    # 备注
    remark = db.Column(String(120))

    def as_dict(self):
        return {"id": self.id, "case_title": self.case_title, "remark": self.remark}

3.2、plan_enetity.py

"""
    测试计划实体类
"""
from sqlalchemy import *
from sqlalchemy.orm import relationship

from do.testcase_plan_rel import testcase_plan_rel
from app import db


class PlanEntity(db.Model):
    # 表名
    __tablename__ = "plan"
    # 用例ID 用例的唯 一标识
    id = db.Column(Integer, primary_key=True)
    # 用例的标题 或者文件名,限定 80个字符 ,不为空,并且唯一
    name = db.Column(String(80), nullable=False, unique=True)
    testcases = relationship("TestCaseEntity",
                             secondary=testcase_plan_rel)

    def as_dict(self):
        # [TestcaseEntity<1>] => test_demo.py testcase_2.py
        return {"id": self.id, "name": self.name,
                # 遍历拿到测试用例名称,并且将名称转为字符串格式
                "testcase_info": " ".join([testcase.case_title for testcase in self.testcases])}

3.3、testcase_plan_rel.py

"""
    测试用例_测试计划_中间表 实体类
"""
from sqlalchemy import *

from app import db

testcase_plan_rel = db.Table(
    'testcase_plan_rel',
    Column('testcase_id', Integer,
           ForeignKey('testcase.id'),
           primary_key=True),
    Column('plan_id', Integer,
           ForeignKey('plan.id'),
           primary_key=True))

3.4、plan_enetity.py

"""
    测试计划实体类
"""
from sqlalchemy import *
from sqlalchemy.orm import relationship

from do.testcase_plan_rel import testcase_plan_rel
from app import db


class PlanEntity(db.Model):
    # 表名
    __tablename__ = "plan"
    # 用例ID 用例的唯 一标识
    id = db.Column(Integer, primary_key=True)
    # 用例的标题 或者文件名,限定 80个字符 ,不为空,并且唯一
    name = db.Column(String(80), nullable=False, unique=True)
    testcases = relationship("TestCaseEntity",
                             secondary=testcase_plan_rel)

    def as_dict(self):
        # [TestcaseEntity<1>] => test_demo.py testcase_2.py
        return {"id": self.id, "name": self.name,
                # 遍历拿到测试用例名称,并且将名称转为字符串格式
                "testcase_info": " ".join([testcase.case_title for testcase in self.testcases])}

4、创建数据库表

  • 大家可以自己在mysql客户端去添加表,也可以直接运行文件,我这里采用运行文件的方法

    注意 :创建一次后,代码就可以注释掉,避免之后每次启动项目都创建

测试平台(二)后端开发(2)需求介绍及后端框架搭建_第11张图片

"""
    数据库表创建
    注意:创建一次后,就可以注释掉,避免之后每次启动项目都创建
"""
from do.build_entity import BuildEntity
from do.plan_enetity import PlanEntity
from do.testcase_plan_rel import testcase_plan_rel
from app import db
from do.testcase_entity import TestCaseEntity

if __name__ == '__main__':
    db.create_all()

测试平台(二)后端开发(2)需求介绍及后端框架搭建_第12张图片


5、新建utils/log_utils.py

  • 新建自定义日志类,方便查看打印日志信息

测试平台(二)后端开发(2)需求介绍及后端框架搭建_第13张图片

"""
    该类为日志封装类
"""
import logging
import os

from logging.handlers import RotatingFileHandler

# 绑定绑定句柄到logger对象
logger = logging.getLogger(__name__)
# 获取当前工具文件所在的路径
root_path = os.path.dirname(os.path.abspath(__file__))
# 拼接当前要输出日志的路径
log_dir_path = os.sep.join([root_path, f'/logs'])
if not os.path.isdir(log_dir_path):
    os.mkdir(log_dir_path)
# 创建日志记录器,指明日志保存路径,每个日志的大小,保存日志的上限
file_log_handler = RotatingFileHandler(os.sep.join([log_dir_path, 'log.log']), maxBytes=1024 * 1024, backupCount=10)
# 设置日志的格式
date_string = '%Y-%m-%d %H:%M:%S'
formatter = logging.Formatter(
    '[%(asctime)s] [%(levelname)s] [%(filename)s]/[line: %(lineno)d]/[%(funcName)s] %(message)s ', date_string)
# 日志输出到控制台的句柄
stream_handler = logging.StreamHandler()
# 将日志记录器指定日志的格式
file_log_handler.setFormatter(formatter)
stream_handler.setFormatter(formatter)
# 为全局的日志工具对象添加日志记录器
# 绑定绑定句柄到logger对象
logger.addHandler(stream_handler)
logger.addHandler(file_log_handler)
# 设置日志输出级别
logger.setLevel(level=logging.DEBUG)

你可能感兴趣的:(测试平台,python,flask)