Project目录架构
在安排QTP test Project的目录树的时候,需要考虑到下面的问题
· 如何组织Function Library,如何引用function library文件?
· 如何组织Testcase,如何在testcas间共享数据/代码?
· 如何配置静态参数,运行时环境和全局测试数据?
如何组织Function Library?
按照前面的设计方法搭建的Function Library会包含大量的函数,最终代码量也会比较庞大(基本上取决于业务逻辑封装函数的多少)。比如最大的一个项目,其Function Library总共代码量达到11000多行,假设1/4是注释,那么实际代码行数大约是8000多行,按照一个函数20行代码,总共大约400多个函数。
为了维护这么多函数,肯定要分成多个文件,按照Module组织起来。但是QTP对于外部文件引用支持很差。基本上10个以上的外部文件引用就让人抓狂了。
所以我采用了一种折中的方法。首先,一个Module对应一个vbs文件,这样代码维护最方便。然后有一个脚本能把所有的Module文件合并为一个大的qfl文件,方便QTP引用。
下面是一个真实项目的Library目录。
· BIZ
业务逻辑封装函数文件所在目录。
· FRM
VBS运行时扩展库文件所在目录。因为VBS的运行时库实在是太简陋(当然,这个也是情有可原,毕竟是70年代的语言),所以必须要写一些基本的扩展例程。比如断言机制,Log机制,动态数组,动态字符串,文件处理,时间格式化,等等。接口基本上参照JVM做可以了:)。
把这些基本功能作为VBS扩展库,和项目的Function Library分开有助于你维护一个跨项目的VBS function Library,更有效的利用代码。
所以,我的项目里,自testcase script向下有下面的层次
+----------------------------------------+
| |
| TestCase Script |
| |
+---------------------------------------->
| |
| Function
Library (BIZ, GUI, UTI) |
| |
+---------------------------------------->
| |
| VBS Extension Library |
| |
+----------------------------------------+
· GUI
GUI封装库所在目录。除了前面介绍的GUI元素库用来定位一个GUI元素,还有对常用的GUI元素操作封装的函数。比如下面是一个对Java Tree的封装。
· Screen
是所有Screen定义文件所在的目录。
· UTI
其他功能函数所在的目录。
· AllInOne_Lib.bat AllInOne_Lib.qfl
AllInOne_Lib.bat把所有上面目录里的vbs文件合并到AllInOne_Lib.qf里,方便QTP引用。
· INIT.qfl
初始化函数库里Module的函数所在文件。因为某些Module的初始化可能有依赖关系,所以提供一个专门用来初始化函数库的地方。
· Library.cfg
配置函数库里Module的配置文件.这个文件内容必须满足VBS的语法.因为他也会合并到AllInOne_Lib.qfl里。在实践中我发现,绝大多数Module其实都不需要外部配置,因为毕竟这只是一个测试项目的Library,对灵活性的要求远没有开发产品的library那么高。
如何组织TestCase?
TestCase被组织在一个四层树状结构列.如下所示.
+-------------+
| TestRepo +-----> Test.qfl
+-+-----------+
|
|
+---------------+
+---->| TestModule +-----> TestModule.qfl
+--+------------+
|
| +----------------+
+->| TestSuite +------> TestSuite.qfl
+--+-------------+
|
| +-----------------+
+->| TestCase |
+-----------------+
最顶层是TestRepo(TestCase Repository Root)。下面是TestModule,是针对产品的一个功能模块的所有testcase的集合。再下面是TestSuite,一般是针对一个特定的测试点的所有testcase的集合。最下面是TestCase。
对于Testcase组织来说,有两个重要的问题,
1) 如何在TestCase之间共享数据和函数
对于第一个问题,每一个TestRepo,TestModule和TestSuite都有一个公共库文件。这个文件会被它所包含的所有Testcase引用。所以在这个文件里,一般配置特定范围的,公共数据和公用方法。举个例子:如果某一个Testsuite里的部分/全部TestCase都依赖于一个特定的对象。那么可以把这个对象的数据,比如名字,配置在TestSuite.qfl里。因为此TestSuite里所有TestCase都引用此文件,所以数据得以共享。
对于任意一个Testcase,它的Resource引用都像下面的样子。
· Library\AllInOne_Lib.qfl
· ..\..\..\Test.qfl
· ..\..\TestModule.qfl
· ..\TestSuite.qfl
· Library\INIT.qfl
2) 如何实现Setup和Cleanup
对于这个问题,通过增加两个特殊的TestCase,00_Setup和99_Teardown来解决。一个TestSuite里如果有这两个TestCase,那么00_Seup会被最先执行,99_Teardown会被最后执行。下面是一个实例。
如何配置运行时环境
对于一个QTP Test Project,环境数据必须是可配置的,而不是绑定到代码里。
我使用了QTP风格的Environment配置文件,方便在运行时被Load进来。QTP的Environment配置文件是XML格式,位置在Conf/Environment.xml,示例如下
<Environment>
<Variable>
<Name>ServerIP</Name>
<Value>172.17.68.40</Value>
</Variable>
</Environment>
在运行时,通过Framwork加载此文件,然后就可以用Environment.Value("ServerIP")的形式在代码里直接获取相应变量的值。
如何把测试数据和测试逻辑分离?
测试数据和测试逻辑分离是一句在自动化测试领域流程甚广的一句话。但有时候它被过于强调,成了QA对外宣传的口号,于是它就成了政治人物.比如对于QTP
Project,有一种做法是定义一个外部的,集中式的的Testdata文件(Excel文件)。但是因为各个TestCase对数据种类的要求是不一样的,把所有这些数据强行统一在一张sheet里的结果就是导致大量的column。我见过在Excel里面用到“T”这个column,也就是用20个Column,简直是维护的灾难。
基本上,最适合”测试数据和逻辑分离”的是这样一个场景。某一批testcase具有类似的逻辑,于是把这个逻辑实现为代码,而用testdata来表达其每一个testcase的不同点。但是事实是,对于QTP Project,这样的情况并不多。特别有些testcase看上去好像测试逻辑差不多,但是从实现上来看,差别很大。如果强行统一,那么测试数据会比较复杂,增加开发和维护的负担。
但是对于QTP Project,“测试数据和测试逻辑分开”其实也是被遵守的。那就是在编写一个具体的testcase的时候,