The following editor will bring you an article on switching between multiple data sources in Java automated testing (explanation with examples). The editor thinks it’s pretty good, so I’ll share it with you now and give it as a reference. Let’s follow the editor and take a look.
When doing automated testing, data-driven is a very important concept. When the data is separated from the script, facing the vast amount of data, managing the data becomes a big problem. Problem, and data sources may face multiple ones. Just like during the development process, sometimes you need to connect to MYSQL and sometimes you need to connect to SQL SERVER. How to switch quickly? In the following example, we will start with a data source and demonstrate it step by step:
1. The basic method of writing data-driven using external files
1.1 When we are data-driven, we store the data in the JAVA property file: data.properties
username=test password=123456
1.2 Parse the properties file
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 Write a TestBase class, which is used DataProvider that stores TestNg
##
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; } }It can be seen that as long as I have a class, I can provide a data type: List9a9bf6e7320d2fa9556654d94c7e96dc> can be converted into a two-dimensional array of Object[][], which can be provided to the test method to run.
1.4 A PropertiesData class appeared in 1.3, now let’s implement this class
##
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 There are data parsing classes, data loading classes, and basic classes for data provision among the above, so we combine the testing methods to integrate these three basic classes, and we have A complete example of an external file as a data source is formed:
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")); } }
2. Implementation of replacing the property file with a txt file
2.1 If there are multiple data sources, I want to use txt to store the data. A json string is stored in txt: data.txt
{ "username":"test", "password":"123456" }
2.2 Read out this txt file
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 Parse the read JSON string (you need to use a JAR package here, 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 Use the TxtData class, that is, replace the propertiesData class in the TestBase class with the TxtData class
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 After running the TestDemo test class, it is found that the results are exactly the same as those that appeared before using the PropertiesData class.
3. Use interfaces to implement 3.1 For the above two data sources, add the After the content is loaded and the loaded data type is: Listfe497e2be29e556eda152481563466e6>, we only need to replace the data source loading class in the TestBase class. In this way, we can use JAVA To reconstruct our code using the interface inside, of course we must first have an interface
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; }
4. Configurable path of data loading class4.1 At this time, we can think about the path of data loading class Written in the configuration file config.properties
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. Switching between multiple data sources 5.1 如果一个测试类里有两个测试方法,那么在配置文件里配置好数据源后,就表示这两个测试方法都将会加载同样的数据源,但如果我们希望一个测试方法用属性文件的数据源,另一个方法用TXT的数据源,这个如何办?也就是需要实现在全局配置化后,局部可再次选择数据源。我将会利用到JAVA里的注解,来实现。所以我们先定义一个DataSource的注解 5.2 解析该注解 5.3 该注解的使用 5.4 TestBase类里的getTestData()方法再次的更改,要利用上这个注解解析出来的值 这段代码可以看到,如果测试方法标注DataSource,则会以标注的注解值为准,否则则会以全局配置的值为准。 5.5 在TestDemo里多加一个测试方法,以示区别 上面的测试类中,两个测试方法,一个用了全局的配置数据源值,一个用了注解数据源值。大家可以运行的看看结果。 六. 工程结构图:@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface DataSource {
String value();
}
public class DataSources {
public static String getDataSource(Method method){
DataSource ds = method.getAnnotation(DataSource.class);
if(ds != null){
return ds.value();
}
return null;
}
}
@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"));
}
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;
}
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"));
}
}
The above is the detailed content of Detailed explanation of switching between multiple data sources in Java automated testing. For more information, please follow other related articles on the PHP Chinese website!