本节书摘来自异步社区《精通自动化测试框架设计》一书中的第2章,第2.6节使用数据库,作者陈冬严 , 邵杰明 , 王东刚 , 蒋涛,更多章节内容可以访问云栖社区“异步社区”公众号查看。

2.6 使用数据库
如果读者所在的企业正在招聘测试工程师或者读者正在求职,翻开工作说明书,无论是熟悉、掌握还是精通,估计绝大部分都会对于数据库有一定的要求。这说明了数据库在现在软件行业的普遍应用,也说明了这几乎是自动化测试所绕不开的一个技术点。在本小节中,将简要介绍如何通过编写代码与数据库进行交互。当然,这只是浅显的使用层面的介绍。如果牵涉到多套数据库数据配套不同用例集、基础数据导入以及数据清洗等问题,读者可以参考第1章中有关“快速回归测试系统”的介绍,以及下一小节中有关CSV文件的处理部分。因为各类型项目的挑战各不相同,本书给出的各种办法也仅供参考。读者需要结合自身的项目实际发现和解决各自的自动化问题。

2.6.1 JDBC连接数据库
即使是没有写过Java代码连接过数据库的读者,估计也都知道JDBC(Java Data Base Connectivity,Java数据库连接)和它的作用。JDBC对程序员而言是API,为程序开发提供标准的接口,通过这些用于执行SQL语句的Java API,可以为多种关系数据库提供统一访问。自从JDBC出现之后,就不必为访问Oracle数据库专门写一个程序,为访问MySQL数据库又专门写一个程序了。对实现与数据库连接的数据库厂商及第三方中间件厂商而言,JDBC则是接口模型,为实现与数据库的连接提供了标准方法。后者只要提供相应的驱动程序,提供给JDBC即可。数据库连接与操作一般都需要如下3个步骤。

(1)提供驱动程序名,供JDBC加载对应的数据库驱动程序。

(2)提供数据库连接串,从DriverManager中取得与数据库的连接。

(3)在已经取得数据库连接对象Connection的基础上进行各种数据库操作。

下面将介绍如何通过JDBC连接MySQL中TestLink数据库,并且从中完成查询。为了实现上述的前两个步骤,需要提供如下的一些信息。

Driver="com.mysql.jdbc.Driver"; //驱动程序名
URL="jdbc:mysql://localhost:3306/testlink"; //数据库连接串
示例程序实现如下:

package com.dataset.db;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;public class DBDriver {//TODO:put the params below to Configurator class & fileprivate static final String URL="jdbc:mysql://localhost:3306/testlink";private static final String User="root";private static final String Password="";private static final String Driver="com.mysql.jdbc.Driver";private static Connection conn;    public static Connection getConnection(){Connection connection=null;if(conn!=null){connection= conn;}else { connection= getConnection(Driver,URL,User,Password); conn=connection;}return connection;}public static Connection getConnection(String driver,String url,Stringuser,String password){Connection conn=null;try {Class.forName(driver);//load database driverconn = DriverManager.getConnection(url, user, password);//create connectionSystem.out.println("New db conn created::"+conn.toString());} catch (Exception e) {e.printStackTrace();}    return conn;}public static void closeConnection(Connection con,Statement stm,ResultSet rs){  try {  if(rs!=null)rs.close(); //close resultsetif(stm!=null)stm.close();//close statementif(con!=null){con.close();//close connectionSystem.out.println("Connection closed. Bye!");}} catch (SQLException e) { throw new RuntimeException("Failed to close database!", e); } }public static ArrayList select(String selectSql){Statement stm = null;ResultSet rs = null;ResultSetMetaData rsmd =null;ArrayList result=new ArrayList();try {stm = conn.createStatement();rs = stm.executeQuery(selectSql);rsmd = rs.getMetaData();int cols=rsmd.getColumnCount();ArrayList row=new ArrayList();while (rs.next()){row=new ArrayList();for(int i=1;i< cols;i++){if(null==rs.getString(i)){row.add("");}else {row.add(rs.getString(i));}}result.add(row);  }} catch (SQLException e) {e.printStackTrace();} finally{closeConnection(null,stm,rs);}return result;}public static void main(String [] args){DBDriver.getConnection();String sqlString="SELECT * FROM platforms ORDER BY id ASC";ArrayList list=select(sqlString);  System.out.println("**********String to query::"+sqlString+"******************");for(int i=0;i< list.size();i++){System.out.println( list.get(i).toString());} sqlString="SELECT * FROM keywords ORDER BY id ASC ";list=(ArrayList) select(sqlString);  System.out.println("**********String to query::"+sqlString+"******************");for(int i=0;i< list.size();i++){System.out.println( list.get(i).toString());} closeConnection(conn,null,null);  } }

在示例程序中,介绍了获取数据库连接的方法:

getConnection(String driver,String url,String user,String password)
通过传入不同的数据库驱动名称,就可以实现连接不同类型、不同实例的数据库。在实践中,一般通过读取配置文件来获取上述这些信息,避免了代码的重新编译与应用的部署。

另外,这里也提供了一个便利的方法用于关闭数据连接等相关的对象实例。作为一个良好的编程习惯,在程序结束的时候一定要通过调用该方法完成相关资源的释放,否则会造成资源不足等问题。

closeConnection(Connection con,Statement stm,ResultSet rs)
这里并没有在select方法中调用closeConnection的时候关闭数据库连接。

public static ArrayList select(String selectSql)
通过程序的输出也可以看出,整个程序中只连接了一次数据库,而不是在每次的数据库操作中都需要重新连接数据库和关闭数据库连接,没有特别要求,只需重用即可。

New db conn created::com.mysql.jdbc.JDBC4Connection@5c2445
**********String to query::SELECT * FROM 'platforms' ORDER BY 'id' ASC******************
[2, tpf_1409450867125, 19]
[3, tpf_1409465605992, 19]
[4, test111111, 107]
[5, tpf_1414333517893, 114]
[6, tpf_1414333737639, 114]
**********String to query::SELECT * FROM 'keywords' ORDER BY 'keywords'.'id' ASC
******************
[2, k1, 19]
[3, k2, 19]
[4, k3, 19]
[5, 123, 114]
[6, 1234566, 114]
[40, tpf_1416620840767, 125]
Connection closed. Bye!

2.6.2 使用Apache DbUtils
在前一小节介绍了基本的JDBC使用之后,可能会觉得使用JDBC操作数据库并不难。但是需要细致与耐心,做许多繁琐且重复的工作,正如卖油翁所说,“无他,但手熟尔”。除了Spring等相对功能强大但学习成本较高、带有一整套架构理论的框架之外,还有一个适合自动化测试框架构建者的轻量级JDBC工具包,就是Apache基金会Apache Commons项目出品的DbUtils工具包。DbUtils封装了对JDBC的操作,简化了JDBC操作,却只有3个包,并且只依赖于JRE 1.6或以上的版本。该工具包可以从其官网下载,目前最新的版本是1.6。

工具包的功能:
org.apache.commons.dbutils——连接、关闭数据等常规操作。
org.apache.commons.dbutils.handlers——对于ResultSet的操作。
org.apache.commons.dbutils.wrappers——处理、修改ResultSet的一些特殊数据。

1.org.apache.commons.dbutils
该包中的主要类和功能如下。

(1)DbUtils:该类提供了关闭连接、装载JDBC驱动程序之类的常规工作方法,并且这些方法都是静态的。

① close:DbUtils类提供了3个重载的关闭方法。这些方法检查所提供的参数是不是NULL,如果不是,就关闭连接、声明和结果集(ResultSet)。前面介绍的closeConnection方法就是借鉴了这种思想实现的。

② closeQuietly:如果不想捕捉使用close时抛出的诸如SQLEeception之类的异常,那么closeQuitely就是一个更好的选择。在调用handlers完成数据集的处理之后,在数据库操作的最后,只需要调用这一方法即可完成全部关闭操作。

③ loadDriver(String driveClassName):这一方法完成装载并注册JDBC驱动程序,如果注册成功就返回TRUE,否则返回FALSE。这样,就不再需要去捕捉注册驱动程序失败时所抛出的异常ClassNotFoundException,只需要根据返回的布尔值结果进行判断即可。

(2)QueryRunner:简化了数据库的增删改查操作,用来替代JDBC中的executeQuery、executeUpdate等方法。通过与ResultSetHandler配合使用,能够大大减少所要写的代码。

① update:执行INSERT,UPDATE或者DELETE等SQL语句。

② insert:执行INSERT语句。

③ query:执行SELECT语句。

另外,可以调用相关的batch方法来批量执行INSERT, UPDATE或者DELETE等SQL语句。

(3)ResultSetIterator:该类实现了iterator接口,把一个ResultSet对象包装成一个迭代器。

(4)ResultSetHandler:顾名思义,该接口执行处理一个结果集ResultSet对象,将数据转变并处理为任何一种形式,供其他应用使用。

2.org.apache.commons.dbutils.handlers
该包中的类都是对于前述ResultSetHandler的实现。

(1)ArrayHandler:将ResultSet中第一行的数据转化成对象数组 。

(2)ArrayListHandler:将ResultSet中所有的数据转化成List,List中存放的是Object[]。

(3)BeanHandler:将ResultSet中第一行的数据转化成类对象。

(4)BeanListHandler:将ResultSet中所有的数据转化成List,List中存放的是类对象。

(5)ColumnListHandler:将ResultSet中某一列的数据存成List,List中存放的是Object对象。

(6)KeyedHandler:将ResultSet中的每一行数据都封装到一个Map里,再把这些map再存到一个map里,其key为指定的key。

(7)MapHandler:将ResultSet中第一行的数据存成Map映射。

(8)MapListHandler:将ResultSet中所有的数据存成List。List中存放的是Map。

(9)ScalarHandler:将ResultSet中一条记录的某一列数据存成Object。

3.org.apache.commons.dbutils.wrappers
该包内有以下两个包装类。

(1)SqlNullCheckedResultSet:该包装类用来对SQL语句执行完成之后的数值进行NULL的替换,并且可以根据需要替换成预设值,如N/A、-1等。

(2)StringTrimmedResultSet :去除ResultSet中字段的左右空格,就是将ResultSet方法中的getString()和getObject()方法(如果获取的是String类型)获取的值,去除其前后空格,并将装饰过的ResultSet返回,供后续使用。

2.6.3 从TestLink数据库中读取数据
接下来,通过一个简单的案例来简要介绍如何使用DbUtils。当然在DbUtils官网上也提供了一些使用案例。感兴趣的读者可以通过以下网址进一步学习:

http://commons.apache.org/proper/commons-dbutils/examples.html
该示例将从TestLink数据库中读取平台表platforms,并且将结果借助于MapListHandler返回Map类型的数据集。

package com.dataset.db;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Iterator;
import java.util.List;
import java.util.Map;import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.MapListHandler;public class DbUtil {private static final String URL="jdbc:mysql://localhost:3306/testlink";private static final String User="root";private static final String Password="";private static final String Driver="com.mysql.jdbc.Driver";private static Connection conn;public static Connection getConnection(){Connection conn = null;DbUtils.loadDriver(Driver);try {conn =DriverManager.getConnection(URL,User,Password);} catch (SQLException e) {e.printStackTrace();}return conn;}public static void main(String[]args) {conn = getConnection();QueryRunner qr = new QueryRunner();List list = null;String sqlString="SELECT * FROM `platforms` ORDER BY `id` ASC";try {list = qr.query(conn,sqlString, new MapListHandler());Iterator ite = list.iterator();while(ite.hasNext()){Map map = (Map)ite.next();System.out.println(map.toString());}} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}finally {DbUtils.closeQuietly(conn);}}

可以看到通过使用DbUtils可以较为方便地完成数据库的各项操作。并且通过配合MapListHandler,实现了结果集的类型转换。在2.5节中介绍的MockTestLinkAPI这个类的各个方法均使用了Map作为入参,两者如果配合使用,即可完成类似的从数据库中读取测试数据。按需转换后传递给测试执行API执行测试步骤的方案。除了MapListHandler,DbUtils还有其他如BeanListHandler、ArrayListHandler等进行数据集转换的类,可以配合不同的数据读取和处理的需求。读者可以根据实际项目的需要进行选择,这里就不赘述了。

《精通自动化测试框架设计》—第2章 2.6节使用数据库相关推荐

  1. 《精通自动化测试框架设计》—第1章 1.3节五天太久,还能压缩吗

    本节书摘来自异步社区<精通自动化测试框架设计>一书中的第1章,第1.3节五天太久,还能压缩吗,作者陈冬严 , 邵杰明 , 王东刚 , 蒋涛,更多章节内容可以访问云栖社区"异步社区 ...

  2. 《精通自动化测试框架设计》—第2章 2.3节测试数据交互基本方法

    本节书摘来自异步社区<精通自动化测试框架设计>一书中的第2章,第2.3节测试数据交互基本方法,作者陈冬严 , 邵杰明 , 王东刚 , 蒋涛,更多章节内容可以访问云栖社区"异步社区 ...

  3. 《精通自动化测试框架设计》目录—导读

    作者简介 精通自动化测试框架设计 陈冬严,浙江大学硕士,具有10年软件测试和团队管理的工作经验,先后服务于ITSM.PLM软件研发企业,现就职于某金融行业核心机构IT规划部门.业余时间喜欢园艺. 邵杰 ...

  4. 对接接口文档_接口自动化测试框架设计思路

    接口自动化测试--框架设计思路 1 前言 之前文章跟大家分享了一下自己在接口自动化测试中进行测试准备的一些相关知识点,接下来本篇文章详细分享一下接口自动化框架设计的思路总结,希望能对初次探索接口自动化 ...

  5. 自从掌握了Selenium自动化测试框架设计,我在公司都横着走!

    测试工作对技术的要求不低,测试工程师更是高技能职位.但有很多新入行的伙伴认为,测试工作就是钟"点"工,用鼠标在软件点里点~点~点~就能做测试.这种思维是很可怕的,这会对测试人的职业 ...

  6. 一套完整的Selenium自动化测试框架设计实战,这次38K, 妥了

    金九银十,大家都铆足干劲想抓住机会涨薪进大厂.结合这几年的行业趋势,想要挑战大厂面试,首先必须吃透Selenium自动化测试框架设计. 这里说一下原因: 首先,一线互联网大厂无一例外,全都要求测试人掌 ...

  7. python接口自动化测试框架pdf,Python接口自动化测试框架设计到开发完整版2019

    1:课程详细介绍.mp4 ; k& X* V: X! X% \; ]; u- V$ z7 L) h: C; h2:课程答疑.mp4+ J  K* q0 O  x + j( v2 n7 B7 s ...

  8. python接口自动化测试框架实战从设计到开发_【B0753】[java视频教程]Python接口自动化测试框架设计到开发完整版视频教程 it教程...

    Java视频教程名称:Python接口自动化测试框架设计到开发完整版视频教程   java自学网[javazx.com]  Python视频教程   it教程 Java自学网收集整理 java论坛&q ...

  9. 【转】我眼中的自动化测试框架设计要点

    转自:http://blog.csdn.net/snakeshiy/article/details/8565178 对于自动化测试框架,其实并没有多数人想象中的那么高深玄乎,框架的概念只是一系列的被事 ...

最新文章

  1. 安装工程造价课程设计_造价课程设计.docx
  2. python和前端之HTML的激情
  3. hdu2037今年暑假不AC
  4. greenplum gpfdist应用
  5. H.264 中很有用的一些概念
  6. 一梦江湖一直获取服务器信息啥意思,《一梦江湖》原《楚留香》手游:叮咚!少侠你的NPC侠缘送来信物...
  7. 摄像头驱动0V7725学习笔记连载(三):0V7725 SCCB时序的实现
  8. Oracle作业job 没有自动调度起来
  9. Atitit.ALT+TAB没反应车and 点击任务栏程序闪烁但是不能切换
  10. cad如何生成kml文件_如何制作KML文件?
  11. 计算机网络 复习提纲(完整版)
  12. ps4 DNS服务器未响应,【网络dns设置教程】ps4网络设置教程 dns
  13. 递归解决字符串逆序输出
  14. HTML+JS 实现 input 框回车事件
  15. 软件测试字节跳动头条项目面试,字节跳动|今日头条面试经验分享
  16. Linux: vi 编辑器
  17. Svelte框架实现表格协同文档
  18. spring循环依赖让你更好的理解spring!!
  19. 第一篇:初学编程对未来的展望
  20. 2014 SuperMap GIS自主创新与应用研讨会资料集

热门文章

  1. 工作实践之 try-with-resource 资源关闭
  2. windows安装使用jaeger链路追踪
  3. Docker安装及配置镜像加速器
  4. pycharm创建scrapy项目
  5. 微信小程序通用功能设计和实现
  6. 产品运营周报报表分析案例
  7. Linux 初始化之 Systemd机制简介
  8. 详解 Qt 串口通信程序全程图文 (3)
  9. 用四张图说清楚Go程序调度的本质
  10. Go 模块--开始使用 Go Modules