罗广恒
(中国电子科技集团公司第十研究所,四川成都610036)
自动测试系统(ATS)是指完全或大部分代替人工,利用计算机执行程序控制测试仪器和被测设备,自动进行测量以及数据处理,自动显示、输出或保存测试结果的系统。随着各生产行业智能制造的发展,高效灵活的生产模式、产业链的有效协作与整合、新型生产服务型制造、系统开发和云制造等智能化优势越来越多地得到企业的认同和追逐。智能工厂创造价值的主要技术前提是大量生产数据的集成[1],自动测试系统实现了生产现场测试数据的采集,但对测试数据的后端应用却较为不足。因此,从生产现场管理或企业运营角度来说,将自动化与信息化技术紧密结合,把来自不同测试系统的测试数据网络化归集、融合、分析和可视化的需求,显得越来越迫切。近年来,随着计算机技术的蓬勃发展,开源软件在操作系统、数据库、Web服务等各个方面的应用已成为主流,使用开源软件可快速、低成本构建企业独特的应用系统。本文运用开源的Django网络框架和MySQL数据库构建自动测试数据查询系统,突破测试测量中数据孤岛的现状,实现测试数据从测试端到应用端的网络连通。
Django是一种基于python语言的具有完整架站能力的开源网络框架。通过Django,设计人员可以专注于网站应用业务逻辑的实现,而无须处理网络底层协议、线程、进程等方面的问题,这样大大提高了开发效率和Web应用质量[2]。测试数据查询系统基于B/S架构,分为三层设计,包括前端、后端和数据库,Django的MTV模型(即Model+Template+View设计模式)基于这三层设计优化而来,框架结构如图1所示。
Model:使用ORM(对象数据映射)机制,封装与应用程序业务逻辑相关的数据及对数据的处理方法,是Django框架和数据库的交互层;
Template:通过格式化模板,将数据与HTML语言、Js语言等结合起来的引擎,用于Web页面的前端渲染;
View:负责实际的业务逻辑实现,即后端的查询操作和数据处理。
在工程开发时,Django用文件夹(包)的形式组织脚本文件和静态文件,通过路由文件进行路径关联,从而使整个工程目录清晰有序,适用于前后端设计人员的分离和协同开发。
图2所示为测试数据查询系统的文件组织结构图,在shell中执行django-admin startproject xxx语句,可自动创建工程目录和manage.py文件,然后根据需要在此基础上进行文件扩展和应用创建。测试数据查询系统中建立了账户管理应用和数据查询应用,在项目设计过程中,主要就是围绕这2种应用,运用MTV的思想进行前后端设计。测试数据查询系统中的应用说明见表1。
表1 测试数据查询系统中的应用说明
图1 Django网络框架结构图
同Oracle、SQL Server等大型数据库相比,MySQL在功能性和安全性等方面表现得差一些,规模也较小。但由于MySQL的开源特性,可以以较低的资金和开发成本满足大多数中小用户的使用需求。本文选用MySQL作为测试数据库的搭建平台,适用于由若干自动测试设备和计算机构建的企业局域网环境。在数据频次不高、数据量较小的情况下,使用一台服务器即可满足要求,后期随着数据容量增加可考虑通过建设分布式数据库的方式来提高系统性能。
测试数据查询系统使用MySQL作为数据存储和管理的数据库管理系统,作为一种关系型数据库,数据表的设计应遵循固定的范式[3]。数据表中尽量不要出现重复字段,并且每个字段不能再拆分。
Django自带网站的后台应用管理功能,包括账户的登陆管理、权限管理、应用管理等,功能已较为齐备。因此,为了方便设计,账户管理应用的数据表直接沿用Django的用户表和用户权限管理表,然后再关联自定义的用户信息附加表即可,本文重点介绍测试数据表的设计方法。从测试数据查询系统业务应用的角度出发,管理人员或技术人员除了关注测试本身的信息,包括测试项目、测试时间、测试产品、测试指标和测试结论等信息,还关注与测试相关的工艺环节和工程信息,以便进行多层次查询和分类统计分析。随着网络化自动测试站的增加,测试数据的存储量随着时间呈指数级增长,为了提高测试数据的存储、删减、修改和查询效率,依据层级关系,测试数据库中将建成测试结果表、测试记录表、工程信息表、产品信息表和调试工艺表,各表之间通过id进行外键关联,实现联合查询。以测试数据中较为重要的测试记录表和测试结果表为例,其表中字段的定义如表2所示。
图2 测试数据查询系统的文件组织结构
Django使用ORM机制在数据库和业务应用之间进行映射,这样在访问数据库时,不需构建复杂且难以拼装的SQL语句,通过简单地操作对象的属性和方法即可轻松实现数据的访问,甚至进行一些功能性的操作。在MySQL数据库中创建2.1节的数据表,只需在相应应用的models.py文件中编写数据模型类,然后执行数据迁移操作,每个数据模型类都是django.db.models.Model的子类,都将对应着数据库中的一张数据表。下面将具体讨论如何运用ORM机制创建和访问MySQL数据库。
第一步:在远程服务器上安装MySQL数据库,并设置数据库的名称、管理员账户、地址和端口号,本系统中使用的是MySQL5.7版本。
第二步:在shell中,运行命令pip install PyMySQL(也可通过离线文件包安装),安装MySQL的python库,作为Django访问MySQL的引擎。
第三步:在Django的工程脚本文件settings.py中,设置MySQL引擎和访问数据库的地址、端口、用户名、密码等信息,用于连接远程数据库。
DATABASES={
表2 测试数据库中测试结果表和测试记录表示例
′db01′:{
′ENGINE′:′django.db.backends.mysql′,
′NAME′:′数据库名′,
′USER′:′用户名’
′PASSWORD′:′密码
′HOST′:′远程地址
‘PORT′:端口号,
},
}
第四步:在Django数据查询应用的脚本文件models.py中,创建相关数据表的类,并在类中定义字段的类型和关联关系,下面以测试结果表和测试数据表为例进行说明。
#测试记录表的类
class MeasureRecord(models.Model):
measurename=models.CharField(max_length=20)
projectname=models.ForeignKey(ProjectDb,on_delete=models.DO_NOTHING,related_name=“prjname”)
people=models.ForeignKey(User,on_delete=models.DO_NOTHING)
product=models.ForeignKey(ProductDb,on_delete=models.DO_NOTHING)
craft=models.ForeignKey(CraftDb,on_delete=models.DO_NOTHING)
starttime=models.DateTimeField()
endtime=models.DateTimeField()
def__str__(self):
return self.measurename
def get_absolute_url(self):
return reverse(“record:datadetail”,args=[self.id,])
class Meta:
app_label="RecordApp"
#测试结果表的类
class MeasureResult(models.Model):
record=models.ForeignKey(MeasureRecord,on_delete=models.CASCADE)
quotaname=models.CharField(max_length=20)
resultvalue=models.CharField(max_length=20)
conclusion=models.CharField(max_length=20)
starttime=models.DateTimeField()
endtime=models.DateTimeField()
def__str__(self):
return self.quotaname
class Meta:
app_label=“RecordApp”
第五步:执行数据表迁移工作,在shell中执行命令“python manage.py migrate应用名”,则Django将调用ORM机制在数据库中自动创建与models.py中的类相对应的数据表。
第六步:从models.py文件中导入类到应用的views.py文件,并创建类相对应的对象,通过对象的函数访问数据库中的表和字段,执行数据的查询操作,包括简单查询、过滤、跨表查询等。
#依据id号进行简单查询示例
from.models import MeasureRecord,MeasureResult#导入类
def DataDetail(request,id):
reslist=MeasureResult.objects.filter(record_id=id)#创建对象并用filter函数执行过滤操作
record=MeasureRecord.objects.get(id=id)#创建对象并用get函数执行查询操作
用户通过浏览器的Web页面执行数据库的查询操作,查询进程、查询结果等信息通过Web页面进行可视化展示。Web页面的设计应遵从用户至上的理念,以方便用户理解和操作为前提进行开发,并配以生动的色彩、图形、排版等形式,让数据以最直观的方式呈现出来。
为了提高数据查询的灵活性,数据查询的关键词包含工程代码、产品名称、工艺名称、测试项目和测试起止时间,用户可自由选择组合关键词进行查询。查询功能的设计主要包括:用户权限认证、关键词自动关联和依据关键词进行数据查询3个方面。
用户权限认证是指执行查询函数之前对当前是否登录以及登录用户是否授权进行查询。为降低开发难度,直接沿用Django的用户权限认证函数,只要在查询函数之前添加装饰函数@login_required(login_url=“/account/login/”)即可。关键词自动关联是根据数据库的已有数据,按照“工程代码-产品名称”进行二级联动,即初始查询页面会在下拉框中显示数据库已有的工程代码列表,用户选定某一项工程代码之后,页面会自动查询并显示该工程代码对应的全部产品列表。当用户选定或录入关键词之后,查询函数将依据关键词组装ORM查询语句,执行查询,查询完成后,将查询结果进行整理并转换成JSON格式,最终渲染到Web页面中来,用户即可看到生动灵活的可视化数据。数据查询函数的执行流程如图3所示。
图3 数据查询函数执行流程
Js(JavaScript)是一种面向客户端浏览器的基于对象、事件驱动式的脚本语言。得益于开源技术的蓬勃发展,目前在网络上有各式各样面向不同功能的Js库,Js库简化了Js编程,使代码更简洁,可以直接运用在Html页面中。在本系统中,主要运用的Js库及其功能如表3所示。
表3 测试数据查询系统中应用的Js库
Django有一套自成体系的模板系统,包含很多内置标签和接口函数,方便页面的继承和扩展。在页面设计中使用模板和Js库,后台程序只需要将JSON格式的数据传递给指定路径的Html模板文件,就可以很便利地动态生成Html页面。
图4 网站管理页面
以一台连网的Windows服务器布置网站服务端程序和MySQL数据库,开启服务端的网络服务后,将10台自动测试系统通过终端计算机接入局域网,终端上的应用程序将测试数据自动上传到服务端的数据库中。测试数据查询系统主要包括用户权限认证和测试数据查询两个模块。
4.1.1 用户权限认证
用户主要分为管理员用户、普通用户和未注册用户,由于本系统沿用Django自带的用户权限控制模块,因此在浏览器中将直接使用系统默认的管理页面。
管理员用户:主要指对网站进行后台管理的人员,按权限范围又可分为超级管理员和受限管理员。主要功能包括用户管理、应用模块管理、历史操作追溯等。当管理员通过超链接进入后台管理页面时,首先输入用户名和密码,然后进入网站管理页面,如图4所示。
普通用户:由于系统面向的是企业用户,因此不采用开放注册的模式,用户只能通过管理员添加。普通用户是指经过管理员在Users组中添加账户的用户,其可以正常访问网站,通过自动测试系统的终端应用向数据库上传测试数据,在浏览器中查询、修改和删除测试数据等。
未注册用户:未注册用户是指在Users组中没有相关账户的用户,其不能访问网站,也不能通过自动测试系统的终端应用向数据库上传测试数据。
4.1.2 测试数据添加
测试数据添加主要分两种,一种是通过自动测试系统软件在当前项目测试完成后自动添加,前提是确保测试时自动测试系统已正常接入测试局域网,然后通过自动测试软件访问网络端的测试数据库,自动找到对应的测试数据表并追加测试数据;另一种是自动测试在离线环境下完成,测试数据无法即时上传到服务器数据库中,而是保存在本地的MySQL数据库,可以通过使用Navicat软件访问测试数据服务器,然后手动上传数据至服务端。
4.1.3 测试数据查询
从远程计算机的浏览器输入服务端的网页地址,浏览器首先访问网站的登陆页面,输入用户名和密码后,进入测试数据查询页面。如图5所示,为查询页面的最终效果,页面按照典型的空间布局方式(上、下、左、右、中)分割,包括用户管理区、功能导航区、数据查询区和图形化分析展示区。数据查询区可实现6种关键词(工程代码、产品名称、工艺名称、测试项目、开始时间和结束时间)的组合查询,选择或录入查询关键词,点击查询按钮即可将数据库中的信息按条件可视化地展示在数据网格中。查询出的数据自动分页展示,用户可自定义按照时间顺序正序或倒序排列数据,数据中的不合格项以红底色显现,页面右端将以柱状图分析各工程的指标合格率。由此,用户在远程计算机上即可实现测试数据的网络化查询,后期将在此基础上进行深度开发,如扩展数据表和字段、强化后端查询和数据处理、增强数据分析能力等,让该系统变得更丰富、更智能。
图5 查询页面实际应用展示
随着系统使用过程中数据量的不断积累,会面临数据量大导致效率无法满足要求的情况,因此需要探索对数据库查询性能的持续优化。查询性能的优化主要涉及MySQL数据库中表结构优化、索引优化和查询操作优化。当单表中存储数据量过大,查询冗余过多时,会直接导致数据库执行许多不必要的操作和遍历大量无关数据,影响查询时间。因此,在数据表设计时,可以以工程代码为后缀对测试结果表和测试数据表进行分表存储,这样,当执行查询时,就不会去访问无关工程的数据表,大大减少遍历的数据行。同时,在测试数据表中,以测试项目作索引,并进行排序,也可提高数据的检索速度。其缺点是,当新增工程时,需要在Django的models.py文件中新增以工程代码为标识的数据表类,并执行数据表迁移操作,在数据库中增加新的数据表。
另一方面,由于MySQL的数据是存储在磁盘上的,访问MySQL需要进行磁盘的IO操作,因此直接从MySQL中读取数据不如直接从内存中读取数据的效率高。为了提高访问效率,可以在数据库和应用程序之间放置一个基于内存的缓存系统。在查询数据时,先从内存中查找,如果找到则使用,没有找到再访问真正的数据库,并将查询到的结果放入缓存中供第二次查询时使用。本系统在后期优化中,将考虑采用目前较为流行的Redis NoSQL数据库(以下简称Redis)作为MySQL数据库的缓存,形成以MySQL(主)+Redis(辅)的数据存储形式。需要注意的是,Redis是以键-值对的形式存储在内存中,而MySQL是按行存储数据的,要将行数据存储于Redis中,需要在Redis中找到一种对应于MySQL行的数据结构。由于JSON格式也是一种键-值对的形式,并且能被python识别和使用,因此,可将结果集格式化为若干JSON对象,然后将JSON对象序列化为字符串存入Redis中。
运用Django和MySQL可以成功搭建网络化测试数据查询系统,开源软件提供了功能丰富的库和框架,具有很强的实用性和扩展性,让设计人员在开发过程中更专注于查询逻辑和用户体验,而不需理会底层复杂的协议和算法。该系统让原来离线的测试数据统一归集于网络数据库,并利用浏览器远程查询和可视化展示。本文所探讨的测试数据网络化方法,是实现智能物联的基础技术途径之一,其以较低的成本和灵活的技术手段快速搭建起整个系统,并最终成功部署应用,可供中小型企业(项目)参考应用。同时,参阅互联网上的各种技术方案,该系统还可以继续扩展和优化,如提高数据查询性能、增加业务处理工作流程、强化数据分析能力等。