大约是13年的10月开始,我在公司里从事着黑盒测试的工作。当时我的任务是要对服务端的接口进行测试。为了能更好(偷懒)的完成好工作,我开发了一个简单的自动化接口测试程序personal,她可以根据我提交的测试数据、接口文档,自动发送报文进行测试并收集测试结果,然后生成报表发邮件通知我。这本来也没什么值得可说的,本来没打算有大用的小程序,随着被头头的喜爱而不断对其的功能进行扩充。于是,本来没有太经过设计规划的代码喜闻乐见的越来越冗余,连我自己都不忍落目。

于是,在一次次下决心之后,我打算对之前的小程序进行重新设计、重写。这也算是对以前工作的一个重新思考、总结,也期待经过这样一次回顾后,我能对python、自动化测试、框架有更深的理解。当然,这些都是垃圾话,问题是,怎样的一个设计才能更灵活,并且在不同项目之间,也能很快的移植、定制。

我果然又标题党了么 (●´ϖ`●) ?这些貌似跟标题没多大的关系,在说这个之前,我想先谈谈qml中关于Rectangle的若干思考。


自从大约是去年6月左右转了Qt开发之后,就掉进了qml的世界。刚接触时,第一眼觉得qml真的跟css长的很像很像,再加上曾经有用PyQt库的经验,学起来还是不是很难理解的。这半年以来,对qml的理解越来越深,觉得qml真的是很有趣的一个东西。在qml里第一个接触到的组件就是Rectangle,矩形,其实就是一个方块嘛,但是在很多可视的控件设计中都少不了它。

Rectangle

唔,好吧,其实我只是手欠,所以画了个Rectangle的示意图。

刚上手Qt的时候,是在老手的带领下,拼装拼装小组件,拼装拼装页面啥的。用“拼装”这个词来描述可是一点都不虚。我那会所做的就是简单的把组件和组件组合在一起,然后就行啦。于是,对那时的我来说,Rectangle就是一个神奇玩意了,为什么这么说呢。比如,你想自己做一个按钮,一被点击就触发一个事件。(我知道还有一个叫做button的控件,但是让我们忽略它。)那就可以画一个Rectangle上面在盖一个MouseArea,就可以了。ヾ( ´ ▽ ‘ )ノ

Button代码示例

Button

//MyButton.qml
import QtQuick 2.4

Rectangle {
    id:button
    implicitWidth: 100
    implicitHeight: 62
    color:"red"

    signal clicked //点击事件

    MouseArea {
        anchors.fill: parent

        onClicked: {
            button.forceActiveFocus()
            button.clicked()
        }
    }
}

再比如说,你打算弄个霸气大板砖形的输入框,最简单的方法就是弄个Rectangle上面放个TextInput,当然也可以通过定制style来实现,不过总觉得麻烦,不如这样简单粗暴。(=。= )

TextinputBar代码示例

TextinputBar

//MyTextinputBar.qml
import QtQuick 2.4

Rectangle {
    id:textinputbar
    implicitWidth: 100
    implicitHeight: 62
    color:"yellow"
    clip:true

    TextInput {
        anchors.fill: parent
    }
}

在每个qml文件里,组件们被串成了一棵树。在久了之后,有时候我就会想知道,为什么是一种树形结构,或者说这种结构有什么样的好处。并且,在每个qml页面里,起码要有一个根组件,也就是说,你不能创建一个全空白的qml,而这又是为何?

当我试图换个角度来重新看待Rectangle这件事时,我觉得我又对qml有了更深的理解。每个qml文件的根组件就好比是一个类,在其中的其他组件就是那些组件类的一个实例,各种继承、各种封装。Rectangle、Text等是继承Item的,ListView各种wiew是继承Flickable的,Flickable也是继承Item。Item是继承QtObject的……于是,一个qml组件的金字塔一层层的展现出来。


那么,回到我那个倒霉悲催的personal程序上,在这一次的重写计划中,我一直在思考,从qml中学习到的东西,有没有我可以加以借鉴学习的。

personal流程

当初的整个personal程序的大体流程就是如此。我的整个程序的输入是用户的测试用例(集),以及由于是要对接口和后台服务进行测试,我需要读取与服务器通讯的接口配置文档。得到之后,根据用例集以及用例顺序,有序的组装报文,以便于进行测试。当得到报文后,发送报文到被测程序开始测试。被测后台服务会根据接口给我返回报文,我收获返回报文后,对报文进行解析,判断报文格式是否正确,报文内的数据是否与用户之前预留的一致,并将结果记录下来。整个测试结束后,开始统计测试结果、计算通过率、绘制图表,然后生成测试报告,打包将其发送到测试人员邮箱。

当时的我,并没有对程序进行仔细的结构设计,于是我就按照流程,就那么面向过程的实现了整个程序还一度沾沾自喜。于是问题来了,当我有序(悠闲)的用这个程序进行着测试工作时,头头觉得我写的这个很方便,并且每天下班后,服务器自己还可以默默的开始几轮测试简直是太攒了之后。小小的personal程序的需求突然变的开始爆炸,更多的接口、不同的报文格式、验证返回报文内容加上逻辑运算、嵌套多层的测试数据等等,为了适应这些需求,程序变得越来越难改、越改越不好用,我开始头疼了…… (๑´灬`๑)

其实,如果在站的高点来看整个pensonal程序,她所做的事不过就是准备测试开始测试测试结果分析,这三大部分。在准备测试里,读取各种数据、组装报文、得到真实用例集;开始测试里,发送报文并接收返回报文、对返回报文进行验证、收集结果;测试结果分析里,统计结果、根据结果生成各种报表等、发送结果。整个流程和每层内部都看着即熟悉又陌生,有那么一点点相似。如果在站的高一点呢,其实我把每个部分都分成了3个部分,即pre、do、after。

do one thing

于是,我可以再抽象一下,定义一个类。这个类它做一件事,并将此事可以分为3个步骤,分别为准备做开始做后续处理。在此基础上,我可以定义上面三大部分里的每一个小类、以及准备测试、开始测试、测试结果分析等等。这样,就像qml的金字塔一样,一层层的搭起来我的测试程序。

(ง •̀_•́)ง 当然这只是我现在最初的构想,细节部分完全没有涉及、譬如插件系统、并发等等,但是总归要一步一步不是,这一次,我定要想好在动笔。哦,回到那个最初的问题上,做一件事需要几个步骤?对于当下的我来说,应该是3步吧~~ (//▽//)