该文原创为新潮质量保障技术团队中的 “上进的中年软件测试从业者”,用于技术交流分享

思路清晰的人前途各有不同;不清晰只有一种后果,随波逐流。以我个人举例,最早 12 年就开始使用二次封装过的 Eclipse 作为公司的自动化,当时到了 14 年要被公司因为业务问题裁员的时候都不是知道那是大名鼎鼎的 Eclipse,当时还是自动化组的负责人,写过很多 python 脚本。现在回头想想简直抠脚,同样颠沛流离了好几年。过往的经历后面会穿插介绍。
目前从大厂出来的,基本上都有测试平台的经历,也会提议所在的测试部门有自己的测试平台。慢慢的听多了,自己也会想尝试去搭建一套。由头有了,接下来就是干了,之前短暂的接触过 flask_admin 作为 python web 开发的框架。所以想也没想就用了这个框架。(下图是我们测试平台的首页,背景是借鉴别人的,主要是高大上)

当前这套框架的组成为flask_admin、Apscheduler、MongoEngine、Echart、ThreadPoolExecutor等。数据库包括mysql、mongo、redis(选用) 等。其他相关联工具包括Jenkins、JIRA、Testlink等。

框架的选型

class Header(EmbeddedDocument):
    header_key = StringField(db_field="header_key")
    header_value = StringField(db_field="header_value")
    header_rule = DictField(db_field="header_rule", description=u"规则",
                            default={
                                "header1": {"h_optional": False, "h_check": True, "h_type": "integer", "h_range": [],
                                            "h_len_min": 0, "h_len_max": 0},
                                "header2": {"h_optional": False, "h_check": True, "h_type": "integer", "h_range": [],
                                            "h_len_min": 0, "h_len_max": 0}})

class Data(EmbeddedDocument):
    data_key = StringField(db_field="data_key")
    data_value = StringField(db_field="data_value")
    data_rule = DictField(db_field="data_rule", description=u"规则",
                          default={"body1": {"b_default": "", "b_optional": False, "b_check": True, "b_type": "integer",
                                             "b_range": [],
                                             "b_len_min": 0, "b_len_max": 0},
                                   "body2": {"b_default": "", "b_optional": False, "b_check": True, "b_type": "integer",
                                             "b_range": [],
                                             "b_len_min": 0, "b_len_max": 0}})

class Asset(EmbeddedDocument):
    asset_key = StringField(db_field="asset_key")
    asset_value = StringField(db_field="asset_value")

class InterfaceTestCaseForm(Document):
    project = ReferenceField(ProjectForm)
    creator = ReferenceField(TesterForm)
    updater = ReferenceField(TesterForm)
    interface = StringField(db_field="interface", description=u"接口地址",
                            validators=[DataRequired(message=u"接口地址不能为空")], max_length=100)
    name = StringField(db_field="name", description=u"接口名称",
                       validators=[DataRequired(message=u"接口名称不能为空")], max_length=50)
    interfaceType = StringField(db_field="interfaceType", description=u"接口请求类型",
                                validators=[DataRequired(message=u"接口请求类型不能为空")], max_length=50)
    testPlanType = ReferenceField(TestPlanTypeForm, db_field="testPlanType")
    internal = BooleanField(db_field="internal", default=True)
    smoke = BooleanField(db_field="smoke", default=True)
    regression = BooleanField(db_field="regression", default=True)
    testResult = StringField(db_field="testResult")
    headers = ListField(
        EmbeddedDocumentField(Header),
        max_length=30)
    data = ListField(
        EmbeddedDocumentField(Data),
        max_length=30)
    asset = ListField(
        EmbeddedDocumentField(Asset),
        max_length=30)
    createTime = StringField(db_field='createTime', max_length=20)  # TODO 修改改成DateField格式,参照TEST-57
    updateTime = StringField(db_field='updateTime', max_length=20)  # TODO 修改改成DateField格式,参照TEST-57
    deleted = BooleanField(db_field="deleted", default=False)
    meta = {
        "collection": "interfaceTestCase",
        'ordering': ['-updateTime']
    }

数据库选型

class ProjectForm(Document):
    projectName = StringField(db_field="projectName", validators=[DataRequired(message=u"项目名不能为空")], )
    projectPrefix = StringField(db_field="projectPrefix", validators=[DataRequired(message=u"项目前缀,请与testlink保持一致")])
    projectTestOwner = ReferenceField(TesterForm)
    projectTesters = ListField(ReferenceField(TesterForm))  # 增加项目测试人员
    projectDomain = StringField(db_field="projectDomain", validators=[DataRequired(message=u"项目域名不能为空")], )
    projectAuthUrl = StringField(db_field="projectAuthUrl", validators=[DataRequired(message=u"系统登录地址不能为空")], )
    authUser = StringField(db_field="authUser", validators=[DataRequired(message=u"系统默认登录用户名不能为空")], )
    authPassword = StringField(db_field="authPassword", validators=[DataRequired(message=u"系统默认登录密码不能为空")], )
    projectDescription = StringField(db_field="projectDescription", validators=[DataRequired(message=u"项目描述不能为空")])
    meta = {
        "collection": "projects"
    }

    def __unicode__(self):  # 解决对象引用过程中,前端看到的是可视化的名字,而不是对象名称。
        return self.projectName

其他相关联的工具


↙↙↙阅读原文可查看相关链接,并与作者交流