下面小編就為大家帶來一篇Java自動化測試中多資料來源的切換(實例講解)。小編覺得蠻不錯的,現在就分享給大家,也給大家做個參考。一起跟著小編過來看看吧
在做自動化測試時,數據驅動是一個很重要的概念,當數據與腳本分離後,面對茫茫多的數據,管理數據又成了一個大問題,而資料來源可能面對多個,就跟在開發過程中,有時候要連接MYSQL,有時候又要連接SQL SERVER一樣,如何做到快速切換?在下面的範例中,我們將從一個資料來源開始,一步步的示範下去:
一. 用外部檔案做資料驅動的基本寫法
#1.1 我們在做資料驅動時,把資料儲存在JAVA的屬性檔中:data.properties
username=test password=123456
1.2 解析properties檔案
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<String, String> getPropertyData(String filePath){ try{ return new HashMap<String, String>((Map)PropertiesHandler.loadPropertiesFile(filePath)); }catch(Exception e){ e.printStackTrace(); } return new HashMap<String, String>(); } public static void main(String[] args) { System.out.println(PropertiesHandler.getPropertyData("file/data.properties")); } }
1.3 寫一個TestBase類,裡面用來存放TestNg的DataProvider
public class TestBase { @DataProvider public Object[][] dataProvider(){ return this.getTestData(); } private Object[][] getTestData(){ PropertiesData testData = new PropertiesData(); List<Map<String, String>> 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; } }
可以看出,我只要有一個類,能夠提供出一個資料型別為:List
1.4 在1.3中出現了一個PropertiesData類,現在來實作這個類別
public class PropertiesData { public List<Map<String, String>> getTestMethodData(){ List<Map<String, String>> list = new ArrayList<Map<String, String>>(); list.add(PropertiesHandler.getPropertyData("file/data.properties")); return list; } }
1.5 以上中有資料解析類,有資料載入類,有資料提供的基礎類,於是我們再結合測試方法,把這三個基礎類給融合在一起,就形成了一個外部檔案來做資料來源的完整範例了:
public class TestDemo extends TestBase{ @Test(dataProvider="dataProvider") public void testDemo(Map<String, String> param){ System.out.println(param.get("username")); System.out.println(param.get("password")); } }
二. 屬性檔案換成txt檔案的實作
2.1 如果有多個資料來源,我想用txt來存放數據,txt裡面存放一個json字串:data.txt
{ "username":"test", "password":"123456" }
2.2 讀出這個txt檔案
public class FileUtils { 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")); } }
#2.3 將讀取出來的JSON字串進行解析(這裡需要用到一個JAR包,gson.jar)
public class TxtData { public List<Map<String, String>> getTestMethodData(){ List<Map<String, String>> list = new ArrayList<Map<String, String>>(); String data = FileUtils.readFile("file/data.txt"); Gson gson = new Gson(); Map<String, String> dataMap = gson.fromJson(data, new TypeToken<Map<String, String>>(){}.getType()); list.add(dataMap); return list; } }
#2.4 將TxtData類別給用上,即將TestBase類別裡的用到PropertiesData類別的地方換成TxtData類別即可
private Object[][] getTestData(){ TxtData testData = new TxtData(); List<Map<String, String>> 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; }
2.5 執行TestDemo測試類別後,發現結果與先前使用PropertiesData類別出現的結果一模一樣。
三. 用介面來實作
3.1 上面的兩個資料來源,在把資料來源裡的內容給載入出來且載入出來的資料型別為:List
public interface DataInterface { public List<Map<String, String>> getTestMethodData(); }
public class PropertiesData implements DataInterface{ public List<Map<String, String>> getTestMethodData(){ List<Map<String, String>> list = new ArrayList<Map<String, String>>(); list.add(PropertiesHandler.getPropertyData("file/data.properties")); return list; } }
public class TxtData implements DataInterface{ public List<Map<String, String>> getTestMethodData(){ List<Map<String, String>> list = new ArrayList<Map<String, String>>(); String data = FileUtils.readFile("file/data.txt"); Gson gson = new Gson(); Map<String, String> dataMap = gson.fromJson(data, new TypeToken<Map<String, String>>(){}.getType()); list.add(dataMap); return list; } }
private DataInterface getDataInstance(String key){ DataInterface data = null; try { data = (DataInterface) Class.forName(key).newInstance(); } catch (InstantiationException | IllegalAccessException | ClassNotFoundException e) { e.printStackTrace(); } return data; }
private Object[][] getTestData(){
DataInterface testData = this.getDataInstance("com.test.testdata.PropertiesData");
List<Map<String, String>> 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;
}
private Object[][] getTestData(){ DataInterface testData = this.getDataInstance("com.test.testdata.TxtData"); List<Map<String, String>> 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=com.test.testdata.TxtData
public class Config { public static String DATA_SOURCE; static{ Map<String, String> map = PropertiesHandler.getPropertyData("config/config.properties"); DATA_SOURCE = map.get("DataSource"); } }
private Object[][] getTestData(){ DataInterface testData = this.getDataInstance(Config.DATA_SOURCE); List<Map<String, String>> 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; }
5.1 如果一个测试类里有两个测试方法,那么在配置文件里配置好数据源后,就表示这两个测试方法都将会加载同样的数据源,但如果我们希望一个测试方法用属性文件的数据源,另一个方法用TXT的数据源,这个如何办?也就是需要实现在全局配置化后,局部可再次选择数据源。我将会利用到JAVA里的注解,来实现。所以我们先定义一个DataSource的注解
@Target(ElementType.FIELD) @Retention(RetentionPolicy.RUNTIME) public @interface DataSource { String value(); }
5.2 解析该注解
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 该注解的使用
@DataSource("com.test.testdata.PropertiesData") @Test(dataProvider="dataProvider") public void testDemo(Map<String, String> param){ System.out.println(param.get("username")); System.out.println(param.get("password")); }
5.4 TestBase类里的getTestData()方法再次的更改,要利用上这个注解解析出来的值
private Object[][] getTestData(Method method){ String sourceKey = DataSources.getDataSource(method); if(sourceKey==null){ sourceKey = Config.DATA_SOURCE; } DataInterface testData = this.getDataInstance(sourceKey); List<Map<String, String>> 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里多加一个测试方法,以示区别
public class TestDemo extends TestBase{ @DataSource("com.test.testdata.PropertiesData") @Test(dataProvider="dataProvider") public void testDemo(Map<String, String> param){ System.out.println(param.get("username")); System.out.println(param.get("password")); } @Test(dataProvider="dataProvider") public void testDemo1(Map<String, String> param){ System.out.println(param.get("username")); System.out.println(param.get("password")); } }
上面的测试类中,两个测试方法,一个用了全局的配置数据源值,一个用了注解数据源值。大家可以运行的看看结果。
六. 工程结构图:
以上是Java自動化測試中關於多重資料來源的切換詳解的詳細內容。更多資訊請關注PHP中文網其他相關文章!