最近利用些业余时间自己编写了一个小型自动化测试框架,在设计过程中自己也渐渐对自动化框架的作用有了些新的认识,希望能和大家分享一下。
其实设计这个框架最初的动机是来源于工作中的一个任务——同事让我维护一个很久以前编写的“自动化脚本”,难度不大,只是一串处理和过程,看懂代码以后只需要修改个别逻辑和参数即可。但后来我想了想,这样纯粹只有过程的脚本,在开发测试时用来当做小工具用不错,但一旦需要建立稳定的自动化测试机制,有大量功能点和测试数据的时候就会显得力不从心。一个功能点对应一个脚本,新增功能点甚至测试数据都需要对应增加脚本,开发维护的成本则会非常高。
后来我自己尝试去做了一个小型的自动化测试框架,虽然花费了不少时间才实现了原来脚本的内容,但是磨刀不误砍柴工,有了框架,接下来新增功能点的开发工作量大大减轻。自己在设计该框架时也基本上是摸着石头过河,一边思考自动化框架究竟需要做什么,一边也参考一些开源自动化框架例如Ruby Watir的设计方式,以下便是我总结的一些经验和心得。
一、测试脚本与测试框架脱离
我开头提到的那个“测试脚本”,从程序启动,测试动作执行,测试结果反馈都一手包干,例如对于A1和A2两个相似的功能点,其测试代码如下:
功能A-1的脚本:A1Test.java
public static void main(String[] args) throws Exception { // A1测试逻辑实现 …… Class.forName("oracle.jdbc.driver.OracleDriver"); String url = "jdbc:oracle:thin:@localhost:1521:cui"; Connection conn = DriverManager.getConnection(url, "cui", "cui"); …… } |
功能A-2的脚本:A2Test.java
public static void main(String[] args) throws Exception { // A2测试逻辑实现 …… Connection conn = null; try { Class.forName("oracle.jdbc.driver.OracleDriver"); String connectionUrl = "jdbc:oracle:thin:@localhost:1521:cui"; conn = DriverManager.getConnection(connectionUrl, "cui", "cui"); …… } |
这样一来A1和A2的测试脚本都可以独立运行,也不需要什么自动化框架,但是原本相似的A1和A2功能,却因为这样的架构要写两次代码,如果TestA1和TestA2由两个不同的程序员编写,那么即便是如上面所示连接一个相同的数据库,每个人需要自己写出实现方式,且都可能有不同的代码风格,这样极大增加了测试代码的编写和维护成本。
对于测试脚本而言,仅仅只需要负责测试逻辑本身,不应该负责诸如脚本启动,管理的功能,同时降低提升测试脚本编写和维护成本,一些公用的方法例如数据库连接等,都最好封装成方法放在测试框架中,然后供测试脚本调用。
我在编写自动化脚本时,将每个测试功能点脚本作为一个Scenario类供测试框架调用的,测试框架可以根据用户输入或者任务设定选择执行哪些脚本。
TestFramework.excute(Scenario userInputScenarioName); |
同时,对于如数据库连接查询这样的操作,也都做了封装,在每个Scenario脚本里,编写者可以通过1行代码就能查询想要的数据:
在配置文件中填入数据库信息:
#别名 db_dev #类型 Oracle #IP 127.0.0.1 #端口 1521 #数据库名 db1 #用户名 cui #密码 cui
在脚本文件中就可以这样来访问数据库:
String id = DB("db_dev").getSingleResult("select id from ……");
数据库的链接,关闭工作都由框架进行统一封装。