一盏小灯 jerrylizilong/autotest_platform 自动化测试平台设计解析 (1)- flask 平台结构

Jerry li · 2019年01月04日 · 1630 次阅读

前言

自从将项目放到 github(https://github.com/jerrylizilong/autotest_platform ), 不少人对其中的一些设计和运行原理提出了疑问。闲来无事,把其中的一些设计和架构整理一下,也是自己的一个总结。

平台化的需求

当初在尝试将原有用 python+selenium 实现的自动化框架做成平台化时,心目中最简单的需求是:

  • 相关用例管理、报告查看等,都在 web 页面操作。
  • 团队协同工作。

出于这个简单的目的,在 python 的几个 web 框架中,选择了轻量级的 flask,并选用 bootstrap 组件来实现前端布局 。

flask 框架简介

和大部分的 flask 项目相同,实际开发中分为以下几个模块:

1. view 目录:

view 模块是 flask 实现 web 路由跳转和接口接收的关键。

  • 通过 @mod.route('/test_case') 控制路由跳转路由
  • 通过 @user.authorize 控制是否需要登录用户才能访问
  • 通过 return render_template("uitest/test_cases.html") 将实际的 html 页面展示给用户
  • 通过 return redirect('test_cases') 进行路由跳转
  • 通过 return jsonify({'code': code, 'msg': message}),{'Content-Type': 'application/json'} 实现接口的 json 数据返回

2. 功能实现:数据库操作

  • 将数据库的 insert、search 、update 方法封装成公共方法
  • 根据需求合理地设计对应的数据表
  • 为单个模块编写对应的新增、修改、删除、查询等方法
  • 为防止数据误删,建议删除时采用逻辑删除的方式,及使用状态位标记是否已删除

3. 静态文件目录:

  • templates 目录:存放 html 静态页面
  • static 目录:存放 js/css 以 flask 官方 demo 为基础模板,为相关页面编写了对应的 html 文件。 要点:
  • 目录管理:由于涉及的页面较多,所以 templates 目录下按功能模块为子目录管理对应页面。相应地,需要在 view 中指定对应的 template 目录。
  • 模板管理:将所需的菜单内容、平台标题、公用的第三方 js/css(如 boostrap )放在基础的公共模板里,方便进行统一管理。添加新菜单时,只需要在模板中添加对应元素即可。
  • html 语法:熟悉 html 基本语法的使用。

简单说一下对 html\js\css 的关系理解:

html: 网页的基础布局。

  • 页面上需要展示什么元素(输入框、表格、文本框、图片等),就需要对应在 html 中进行管理和排列。
  • 对于我们平台的需求来说,用表格来展示查询列表,用表单进行新增、编辑管理,就可以解决 90% 的页面需求。

css : 页面元素的样式控制。

  • 在简单使用的情况下,直接引用 bootstrap 的默认样式就可以了,所以基本上没有做修改。

js : 功能实现

主要控制:

  • 网页和服务器后台接口的通讯。这里统一采用 ajax 实现。
  • 控制页面的某些功能,如获取选择框当前所选择元素:

5. 实践:

由于我们平台的页面都是基础的增删查改,因此要做的工作是:

5.1 确立需求:

选取一个模块(如用例管理),确定需求:需要新增用例、修改用例、获取用例列表、获取用例详情、删除用例、复制用例

5.2 服务端功能实现:

  • 编写对应的数据库操作方法: insert 、update、 search。 ## 新增用例保存 def new_test_case(self,module,name,steps,description, isPublic): sql = string.Template('insert into test_case (module,name,steps,description,isPublicFunction) values ("$module","$name","$steps","$description",$isPublic);') sql = sql.substitute(name = name, module = module, steps = steps,description=description, isPublic=isPublic) useDB.useDB().insert(sql)
  • 在 view 中编写对应的 json 接口: 新增、修改、查询(通过查询类型区分是返回列表还是返回单个用例)、复制、删除。
@mod.route('/add_test_case', methods=['POST', 'GET'])     #新增用例接口
@user.authorize
def save_new_test_case():
    log.log().logger.info(request)
    if request.method == 'GET':
        log.log().logger.info('post')
        return render_template("uitest/new_test_cases.html")
    if request.method == 'POST':
        info = request.form
        log.log().logger.info('info : %s' %info)
        name = viewutil.getInfoAttribute(info,'name')
        module = viewutil.getInfoAttribute(info,'module')
        description = viewutil.getInfoAttribute(info,'description')
        steps = viewutil.getInfoAttribute(info,'steps')
        steps=steps.replace('"',"'")
        type = viewutil.getInfoAttribute(info,'type')
        if module == '' or name == '' or steps=='' or type=='':
            return '必填字段不得为空!'
        else:
            if type=='公共用例':
                isPublic = 1
            else:
                isPublic = 0
            test_case_manage.test_case_manage().new_test_case(module, name, steps, description, isPublic)      # 保存用例
        return redirect('test_cases')

此时直接访问对应接口,可以实现增、删、改、查等功能。

5.3 页面编写和路由关联:

  • 分别编写对应新增、修改、查询页面的 html 文件。
  • 在 view 中编写对应路由:test_cases(用例列表页面)、add_test_case(新增用例页面)、edit_test_case(修改用例页面),与上一步的 html 文件进行关联。 @mod.route('/test_cases') @user.authorize def test_cases(): return render_template("uitest/test_cases.html")

完成这步后,此时直接访问对应的路由路径,就可以打开对应的 html 页面。

5.4 前后端关联:

  • 编写 test_case.js 文件,编写对应的用例新增、修改、获取列表、获取用例详情、删除用例、复制用例等方法。 // submit form function submitAddForm() { $("#new_test_case").validate(); $.validator.setDefaults({ submitHandler: function() { document.getElementById("new_test_case").submit(); } }); }

此时需要做的,是将页面的元素与后台的接口关联起来。
到这里,相关的模块功能就实现好了。

查询:

新增:

修改:

6. 善用复制、黏贴提高开发效率

在实现后一个模块后,如果要开发新的模块,可以直接套用,只需要修改里面关键的标题、元素、id 等信息即可。 这样只需要复制、批量修改(例如直接把 test_case 替换为 test_suite),很快就能把类似的模块开发出来。

暫無回覆。
需要 登录 後方可回應,如果你還沒有帳號按這裡 注册