霍格沃兹测试开发

测试平台训练营实战2

霍格沃兹测试开发 ceshiren.com

测试平台表结构

@startuml
'https://plantuml.com/sequence-diagram

!define Table(name,desc) class name as "desc" << (T,#FFAAAA) >>
!define primary_key(x) <color:red><b>x</b></color>
!define unique(x) <color:green>x</color>
!define not_null(x) <u>x</u>
hide methods
hide stereotypes
Table(项目, "项目\n(This is 项目)"){
    not_null(id)
    not_null(plan_id) int 测试计划id
 }

 Table(测试计划, "测试计划"){
    not_null(id) int
    not_null(case_id) int 关联用例id
    not_null(执行器_id) int ForeignKey 执行器_id
    not_null(build_id) int 测试记录
    filter_by varchar  过滤条件
 }

 Table(测试类型, "测试类型"){
    not_null(id) int
    not_null(type) varchar  类型
    not_null(framework) varchar  框架
    not_null(command) varchar  命令
 }

  Table(测试用例, "测试用例"){
    not_null(id) int
    not_null(type_id) varchar 用例类型(git or json)
    not_null(case_title) varchar 用例标题
    not_null(case_info) varchar 用例信息
  }

'  计划和条件挂钩, 测试用例和测试套件多对多的关系

  Table(测试套件, "测试套件"){
    not_null(id) int
    name str
  }




   Table(Plan2Suite, "Plan2Suite"){
    not_null(id) int
    not_null(id) suite_id
    not_null(id) plan_id
 }

   Table(Testcase2Suite, "Testcase2Suite"){
    not_null(id) int
    not_null(id) suite_id
    not_null(id) case_id
 }

Table(执行器, "执行器"){
    not_null(id) int column_1
    not_null(执行器类型) varchar 执行器类型【jenkins】
    执行器配置 varchar 执行器配置
}

Table(构建记录, "构建记录"){
    not_null(id) int column_1
    not_null(plan_id) varchar ForeignKey 测试计划id
    not_null(report) varchar 测试报告
}

项目::plan_id--测试计划::id:项目对应多个测试计划
Plan2Suite::plan_id -- 测试计划::id
Plan2Suite::suite_id -- 测试套件::id

Testcase2Suite::case_id -- 测试用例::id 
Testcase2Suite::suite_id -- 测试套件::id

执行器::id --> 测试计划::id
测试用例::type_id -- 测试类型::id
测试计划::id -->构建记录::plan_id : 测试计划对应多个构建记录

@enduml

教学版

'https://plantuml.com/sequence-diagram

!define Table(name,desc) class name as "desc" << (T,#FFAAAA) >>
!define primary_key(x) <color:red><b>x</b></color>
!define unique(x) <color:green>x</color>
!define not_null(x) <u>x</u>
hide methods
hide stereotypes
  Table(测试用例, "测试用例"){
    not_null(id) int
    not_null(uid) varchar 用例唯一标识
    not_null(remark) varchar 用例备注
  }

 Table(测试计划, "测试计划"){
    not_null(id) int
    not_null(name) str  名称
 }

Table(构建记录, "构建记录"){
    not_null(id) int column_1
    not_null(plan_id) varchar ForeignKey 测试计划id
    not_null(report) varchar 测试报告
    not_null(created_at) time 创建时间
}

  Table(PlanToTestcase, "PlanToTestcase"){
    not_null(id) int
    not_null(id) plan_id
    not_null(id) case_id
 }

测试计划::plan_id--构建记录: 一个测试计划对应多次构建记录

PlanToTestcase::case_id -- 测试用例: 测试用例对应多个测试计划
PlanToTestcase::plan_id -- 测试计划: 测试计划对应多个测试用例

实战思路

  1. 实现完整表结构
  2. service层逻辑实现
    1. Plan(增加、获取、执行)
    2. build(save、get)
  3. service层的测试用例
  4. dao层(数据库交互层)
  5. 接口层
  6. 前端
  7. 封装JenkinsUtils
    1. 实现JenkinsUtils逻辑优化
    2. 实现二次封装

一对多(测试计划与构建记录)

class BuildEntity(db.Model):
    # 表名
    __tablename__ = "build"
    # 用例ID 用例的唯 一标识
    id = db.Column(Integer, primary_key=True)
    # 用例的标题 或者文件名,限定 80个字符 ,不为空,并且唯一
    plan_id = db.Column(Integer)
    report = db.Column(String(80))
    create_time = Column(DateTime, nullable=True, default=datetime.now().strftime('%Y-%m-%d %H:%M:%S'))

    def as_dict(self):
        return {"plan_id": self.plan_id, "report": self.report, "create_time": str(self.create_time)}

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,
                             backref="plans")

    def as_dict(self):
        return {"id": self.id, "name": self.name,
                "testcase_info": " ".join([testcase.case_title for testcase in self.testcases]) }

多对多(测试计划与测试用例)

# 中间表
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)
)
# 测试计划表

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,
                             backref="plans")

    def as_dict(self):
        return {"id": self.id, "name": self.name,
                "testcase_info": " ".join([testcase.case_title for testcase in self.testcases]) }
# 用例表
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))
    # 用例的创建时间
    # created_at = ""
    def as_dict(self):
        return {"id": self.id, "case_title": self.case_title, "remark": self.remark}
class BuildEntity(db.Model):
    # 表名
    __tablename__ = "build"
    # 用例ID 用例的唯 一标识
    id = db.Column(Integer, primary_key=True)
    plan_id = Column(Integer)
    report =  Column(String(120))
    create_time = Column(DateTime, nullable=True,
                         default= datetime.now().strftime('%Y-%m-%d %H:%M:%S'))
    # created_at = db.Column(db.DateTime, default=datetime.datetime.now())

    # 用例的创建时间
    # created_at = ""
    def as_dict(self):
        return {"plan_id": self.plan_id, "report": self.report,
                "create_time": str(self.create_time)}

前端原型图

跨域

跨域请求:同源判断 - CSRF(Cross-site request forgery),中文名称:跨站请求伪造。 - 如果两个 URL 的 protocol、port (如果有指定的话)和 host 都相同的话,则这两个 URL 是同源

跨域示例

URL 结果 原因
http://store.company.com/dir2/other.html
http://store.company.com/dir/inner/another.html
https://store.company.com/secure.html
http://store.company.com:81/dir/etc.html
http://news.company.com/dir/other.html

跨域示例-结果

URL 结果 原因
http://store.company.com/dir2/other.html 同源 只有路径不同
http://store.company.com/dir/inner/another.html 同源 只有路径不同
https://store.company.com/secure.html 失败 协议不同
http://store.company.com:81/dir/etc.html 失败 端口不同 ( http:// 默认端口是80)
http://news.company.com/dir/other.html 失败 主机不同

axios的使用

解决跨域问题

  • 安装pip install -U flask-cors
from flask_cors import CORS

# 实例化一个flask服务
app = Flask(__name__)
# 解决跨域
CORS(app, supports_credentials=True)

常见错误

  • 错误信息:QueuePool limit of size 10 overflow 10 reached
  • 解决方案:app.config[‘SQLALCHEMY_MAX_OVERFLOW’] = 100