JAVA自动化测试中多数据源的切换

在做自动化测试时,数据驱动是一个很重要的概念,当数据与脚本分离后,面对茫茫多的数据,管理数据又成了一个大问题,而数据源又可能面对多个,就跟在开发过程中,有时候要连接MYSQL,有时候又要连接SQL SERVER一样,如何做到快速切换?下面的示例中,我们将从一个数据源开始,一步步的演示下去:

一. 用外部文件做数据驱动的基本写法

1.1 我们在做数据驱动时,把数据存储在JAVA的属性文件中:data.properties

java;gutter:true; username=test password=123456</p> <pre><code> 1.2 解析properties文件 ;gutter:true;
public class PropertiesHandler {

private static Properties loadPropertiesFile(String filePath){
Properties p = new Properties();
InputStream in = null;
try {
in = new FileInputStream(new File(filePath));
p.load(in);
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}finally{
try {
if(in != null){
in.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
return p;
}

/**
* 将property转换成Map
* @param key
* @return
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public static Map getPropertyData(String filePath){
try{
return new HashMap((Map)PropertiesHandler.loadPropertiesFile(filePath));
}catch(Exception e){
e.printStackTrace();
}
return new HashMap();
}

public static void main(String[] args) {
System.out.println(PropertiesHandler.getPropertyData("file/data.properties"));
}
}

1.3 写一个TestBase类,里面用来存放TestNg的DataProvider

java;gutter:true; public class TestBase {</p> <pre><code>@DataProvider public Object[][] dataProvider(){ return this.getTestData(); } private Object[][] getTestData(){ PropertiesData testData = new PropertiesData(); List> listData = testData.getTestMethodData(); Object[][] object = new Object[listData.size()][]; for (int i = 0; i < listData.size(); i++) { object[i] = new Object[]{listData.get(i)}; } return object; } </code></pre> <p>}</p> <pre><code> 可以看出,我只要有一个类,能够提供出一个数据类型为:List 1.4 在1.3中出现了一个PropertiesData类,现在来实现这个类 ;gutter:true;
public class PropertiesData {

public List> getTestMethodData(){
List> list = new ArrayList>();
list.add(PropertiesHandler.getPropertyData("file/data.properties"));
return list;
}

}

1.5 以上中有数据解析类,有数据加载类,有数据提供的基础类,于是我们再结合测试方法,把这三个基础类给融合在一起,就形成了一个外部文件来做数据源的完整示例了:

java;gutter:true; public class TestDemo extends TestBase{</p> <pre><code>@Test(dataProvider="dataProvider") public void testDemo(Map param){ System.out.println(param.get("username")); System.out.println(param.get("password")); } </code></pre> <p>}</p> <pre><code> 1.6 以上的运行结果输出为: 二. 属性文件换成txt文件的实现 2.1 如果有多个数据源,我想用txt来存放数据,txt里面存放一个json串:data.txt ;gutter:true;
{
"username":"test",
"password":"123456"
}

2.2 读出这个txt文件

java;gutter:true; public class FileUtils {</p> <pre><code>public static String readFile(String fileName) { InputStream is = null; StringBuffer sb = new StringBuffer(); try { is = new FileInputStream(fileName); byte[] byteBuffer = new byte[is.available()]; int read = 0; while((read = is.read(byteBuffer)) != -1){ sb.append(new String(byteBuffer, 0, read)); } } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); }finally{ try { if(is!=null){ is.close(); } } catch (IOException e) { e.printStackTrace(); } } return sb.toString(); } public static void main(String[] args) { System.out.println(FileUtils.readFile("file/data.txt")); } </code></pre> <p>}</p> <pre><code> 2.3 将读取出来的JSON串进行解析(这里需要用到一个JAR包,gson.jar) ;gutter:true;
public class TxtData {

public List> getTestMethodData(){
List> list = new ArrayList>();
String data = FileUtils.readFile("file/data.txt");
Gson gson = new Gson();
Map dataMap = gson.fromJson(data, new TypeToken>(){}.getType());
list.add(dataMap);
return list;
}

}

2.4 将TxtData类给用上,即将TestBase类里的用到PropertiesData类的地方换成TxtData类即可

java;gutter:true; private Object[][] getTestData(){ TxtData testData = new TxtData(); List> listData = testData.getTestMethodData(); Object[][] object = new Object[listData.size()][]; for (int i = 0; i < listData.size(); i++) { object[i] = new Object[]{listData.get(i)}; } return object; }</p> <pre><code> 2.5 运行TestDemo测试类后,发现结果与之前用PropertiesData类出现的结果一模一样。 三. 用接口来实现 3.1 上面的两种数据源,在把数据源里的内容给加载出来且加载出来的数据类型为:List ;gutter:true;
public interface DataInterface {
public List> getTestMethodData();
}

3.2 我们的PropertiesData类与TxtData类当然要实现这个接口了

java;gutter:true; public class PropertiesData implements DataInterface{</p> <pre><code>public List> getTestMethodData(){ List> list = new ArrayList>(); list.add(PropertiesHandler.getPropertyData("file/data.properties")); return list; } </code></pre> <p>}</p> <pre><code> ;gutter:true;
public class TxtData implements DataInterface{

public List> getTestMethodData(){
List> list = new ArrayList>();
String data = FileUtils.readFile("file/data.txt");
Gson gson = new Gson();
Map dataMap = gson.fromJson(data, new TypeToken>(){}.getType());
list.add(dataMap);
return list;
}

}

3.3 然后在TestBase里就要有所改变了,即产生数据加载的类对象要发生改变,我们在TestBase里新加一个方法(这是产生类对象的一种新的方式)

java;gutter:true; private DataInterface getDataInstance(String key){ DataInterface data = null; try { data = (DataInterface) Class.forName(key).newInstance(); } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { e.printStackTrace(); } return data; }</p> <pre><code> 3.4 TestBase类里的getTestData()方法就要重新的改变一下了 ;gutter:true;
private Object[][] getTestData(){
DataInterface testData = this.getDataInstance("com.test.testdata.PropertiesData");
List> listData = testData.getTestMethodData();
Object[][] object = new Object[listData.size()][];
for (int i = 0; i < listData.size(); i++) {
object[i] = new Object[]{listData.get(i)};
}
return object;
}

java;gutter:true; private Object[][] getTestData(){ DataInterface testData = this.getDataInstance("com.test.testdata.TxtData"); List> listData = testData.getTestMethodData(); Object[][] object = new Object[listData.size()][]; for (int i = 0; i < listData.size(); i++) { object[i] = new Object[]{listData.get(i)}; } return object; }</p> <pre><code> 3.5 再次运行TestDemo,即可发现结果仍然是一样的。所以,这时候只需要改变数据加载类的路径即可了。 四. 将数据加载类的路径可配置化 4.1 这时候,我们就可以想着把数据加载类的路径写在配置文件中了config.properties ;gutter:true;
DataSource=com.test.testdata.TxtData

4.2 加载config文件

java;gutter:true; public class Config {</p> <pre><code>public static String DATA_SOURCE; static{ Map map = PropertiesHandler.getPropertyData("config/config.properties"); DATA_SOURCE = map.get("DataSource"); } </code></pre> <p>}</p> <pre><code> 4.3 将TestBase里的getTestData()方法再改进一下: ;gutter:true;
private Object[][] getTestData(){
DataInterface testData = this.getDataInstance(Config.DATA_SOURCE);
List> listData = testData.getTestMethodData();
Object[][] object = new Object[listData.size()][];
for (int i = 0; i < listData.size(); i++) {
object[i] = new Object[]{listData.get(i)};
}
return object;
}

4.4 再次运行TestDemo类,结果仍然是一样的。到此为止,我们已实现了去更改配置文件里面的内容,来选择加载数据源。

五. 多数据源的切换

5.1 如果一个测试类里有两个测试方法,那么在配置文件里配置好数据源后,就表示这两个测试方法都将会加载同样的数据源,但如果我们希望一个测试方法用属性文件的数据源,另一个方法用TXT的数据源,这个如何办?也就是需要实现在全局配置化后,局部可再次选择数据源。我将会利用到JAVA里的注解,来实现。所以我们先定义一个DataSource的注解

java;gutter:true; @Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface DataSource { String value(); }</p> <pre><code> 5.2 解析该注解 ;gutter:true;
public class DataSources {

public static String getDataSource(Method method){
DataSource ds = method.getAnnotation(DataSource.class);
if(ds != null){
return ds.value();
}
return null;
}

}

5.3 该注解的使用

java;gutter:true; @DataSource("com.test.testdata.PropertiesData") @Test(dataProvider="dataProvider") public void testDemo(Map param){ System.out.println(param.get("username")); System.out.println(param.get("password")); }</p> <pre><code> 5.4 TestBase类里的getTestData()方法再次的更改,要利用上这个注解解析出来的值 ;gutter:true;
private Object[][] getTestData(Method method){
String sourceKey = DataSources.getDataSource(method);
if(sourceKey==null){
sourceKey = Config.DATA_SOURCE;
}
DataInterface testData = this.getDataInstance(sourceKey);
List> listData = testData.getTestMethodData();
Object[][] object = new Object[listData.size()][];
for (int i = 0; i < listData.size(); i++) {
object[i] = new Object[]{listData.get(i)};
}
return object;
}

这段代码可以看到,如果测试方法标注DataSource,则会以标注的注解值为准,否则则会以全局配置的值为准。

5.5 在TestDemo里多加一个测试方法,以示区别

java;gutter:true; public class TestDemo extends TestBase{</p> <pre><code>@DataSource("com.test.testdata.PropertiesData") @Test(dataProvider="dataProvider") public void testDemo(Map param){ System.out.println(param.get("username")); System.out.println(param.get("password")); } @Test(dataProvider="dataProvider") public void testDemo1(Map param){ System.out.println(param.get("username")); System.out.println(param.get("password")); } </code></pre> <p>}

上面的测试类中,两个测试方法,一个用了全局的配置数据源值,一个用了注解数据源值。大家可以运行的看看结果。

六. 工程结构图:

JAVA自动化测试中多数据源的切换

至于源码,大家自行的拷贝粘贴吧,也当作是一种知识的巩固。

Original: https://www.cnblogs.com/zhangfei/p/5229434.html
Author: 张飞_
Title: JAVA自动化测试中多数据源的切换

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/538808/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • 浏览器书签同步收藏扩展插件更新,浏览器书签插件需要那么功能?

    新增:浏览器插件新增简介,标签,星标,封面图等操作功能 新增:浏览器插件收藏快捷键启动(浏览器插件扩展自定义快捷键) 浏览器通用默认快捷键 win:Ctrl+Shift+S mac…

    Java 2023年6月5日
    086
  • rocketmq总结

    1:角色关系 2:顺序消息 消费消息的顺序要同収送消息的顺序一致,在 RocketMQ 中,主要挃的是局部顺序,即一类消息为满足顺序性,必须 Producer 单线程顺序収送,丏収…

    Java 2023年5月30日
    089
  • Jenkins安装(Docker)版

    一、jenkins安装 1.查找,下载jenkins镜像文件 启动docker,查找Jenkins镜像文件 docker&#xA0;search&#xA0;jenk…

    Java 2023年6月15日
    088
  • SpringBoot整合MyBatis

    一、准备工作 首先新建一个空工程,springboot相关的整合都放在该工程下。 该空工程名称为spring-boot-example 创建好的空工程如下: 接着我们创建模块 注:…

    Java 2023年6月8日
    083
  • 正规文法与正规式

    3型文法也叫作正规文法,它对应于有限状态自动机,它是在2型文法的基础上满足:A->a|aB(右线性)或A->a|Ba(左线性)。如果有A->a,A->aB,…

    Java 2023年6月7日
    0119
  • java C 类自动转换规则

    C类型转换规则 posted @2018-05-05 21:34 zengkefu 阅读(194 ) 评论() 编辑 Original: https://www.cnblogs.c…

    Java 2023年5月29日
    088
  • js移除style样式

    removeAttribute() 例: 保存 let btnadd=document.getElementById("btnadd");btnadd.remo…

    Java 2023年6月15日
    077
  • 黑群晖 Active Backup for Business 套件激活方法(群晖备份远程samba)

    通过 Synology Active Backup for Business 软件,IT 人员可以在单一界面上集中管理分散在 PC、服务器、虚拟机中的数据,并可在灾难发生时,在服务…

    Java 2023年6月6日
    0214
  • MybatisPlus核心功能——实现CRUD增删改查操作 (包含条件构造器)

    CRUD 官方文档:https://baomidou.com/(建议多看看官方文档,每种功能里面都有讲解)【本文章使用的mybatisplus版本为3.5.2】 条件构造器 一般都…

    Java 2023年6月14日
    078
  • eclipse导入依赖后不生效问题

    在父程component中引入子工程entity,导入依赖之后不生效,无法导入包 解决办法: 右键Maven—–>update project Ori…

    Java 2023年6月9日
    077
  • Springmvc基础及应用

    SpringMVC简介和环境搭建 SpringMVC简介 Spring 为展现层提供的基于 MVC 设计理念的优秀的Web 框架,是目前最主流的 MVC 框架之一。在Spring3…

    Java 2023年6月9日
    080
  • PDF加密、分割和生成封面图操作

    由于某些不可抗力原因,公司不允许使用itext系列的jar包,因此系统中使用的相关jar得替换成开源的。经比较和尝试考虑使用org.apache.pdfbox来替换,同时修改系统中…

    Java 2023年6月5日
    070
  • Jni 线程JNIEnv,JavaVM,JNI_OnLoad(GetEnv返回NULL?FindClass返回NULL?)

    此文章是关于NDK线程的第二篇理论知识笔记。主要有两个点,如下: 1.pthread_create(Too many arguements, expected 1) ?2.线程中如…

    Java 2023年5月29日
    086
  • Java学习 (19) Java数组篇(03)数组的使用

    数组使用 数组使用一般分四种情况 1.普通 For 循环 2.For-Each 循环 (增强For循环) 3.数组作方法入参 4.数组作返回值 语法实例 多维数组 语法实例 数组使…

    Java 2023年6月8日
    096
  • Java 加载动态库 dll 文件

    不知道具体原理,但是,加载 dll 文件时,带路径或者更改 dll 文件的名字,都会报错。虽然库记载成功了,但是处女座认为这不可接受。于是有了这个解决方案。 在根目录为库创建软连接…

    Java 2023年5月29日
    079
  • Java程序员必备的工具和框架

    最近几年,Java 的技术栈发展的非常快,成百上千的技术工具正不断地涌出来,这也造成了一个问题: 我们作为开发者,到底应该选哪些工具搭建出最合适的技术栈呢? 今天我就推荐一波我常用…

    Java 2023年6月7日
    070
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球