Maison  >  Article  >  Java  >  Explication détaillée de la commutation entre plusieurs sources de données dans les tests automatisés Java

Explication détaillée de la commutation entre plusieurs sources de données dans les tests automatisés Java

黄舟
黄舟original
2017-10-09 10:18:251992parcourir

L'éditeur suivant vous proposera un article sur la commutation entre plusieurs sources de données dans les tests automatisés Java (explication avec exemples). L'éditeur le trouve plutôt bon, je vais donc le partager avec vous maintenant et le donner comme référence pour tout le monde. Suivons l'éditeur pour y jeter un œil

Lors de tests automatisés, la gestion des données est un concept très important. Lorsque les données sont séparées du script, face à l'énorme quantité de données, la gestion des données devient un gros problème. problème. Problème, et les sources de données peuvent en rencontrer plusieurs. Tout comme pendant le processus de développement, vous devez parfois vous connecter à MYSQL et parfois vous devez vous connecter à SQL SERVER. Comment basculer rapidement ? Dans l'exemple suivant, nous allons commencer par une source de données et la démontrer étape par étape :

1 La méthode d'écriture de base consistant à utiliser des fichiers externes pour piloter des données.

1.1 Lorsque nous sommes pilotés par les données, nous stockons les données dans le fichier de propriétés JAVA : data.properties


username=test
password=123456

1.2 Analyser le fichier de propriétés


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 Écrire une classe TestBase , qui est utilisée pour stocker le 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;
 }
  
}

utilisé pour stocker TestNg. une classe, je peux fournir un type de données : les objets de données de Listfe497e2be29e556eda152481563466e6> peuvent être convertis en un tableau bidimensionnel de Object[][], qui peut être fourni à la méthode de test pour exécution .

1.4 Une classe PropertiesData est apparue dans la version 1.3. Implémentons maintenant cette classe


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 Parmi ce qui précède, il existe des classes d'analyse de données, des classes de chargement de données et des classes de base fournissant des données, nous combinons donc les méthodes de test pour intégrer ces trois classes de base, formant un exemple complet. d'un fichier externe comme source de données :


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. Mise en place du remplacement des fichiers de propriétés par des fichiers txt

2.1 S'il existe plusieurs sources de données, je souhaite utiliser txt pour stocker les données. Une chaîne json est stockée dans txt : data.txt <.>


{
 "username":"test",
 "password":"123456"
}

2.2 Lisez ce fichier 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 Analyser la chaîne JSON lue (vous devez utiliser un package JAR ici, 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 Utiliser la classe TxtData, c'est-à-dire remplacer la classe PropertiesData dans la classe TestBase par la classe 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 Après avoir exécuté la classe de test TestDemo, il s'avère que les résultats sont exactement les mêmes que ceux qui apparaissaient avant d'utiliser la classe PropertiesData.

3. Utiliser des interfaces pour implémenter 3.1 Les deux sources de données ci-dessus, dans la source de données Après le contenu est chargé et le type de données chargé est : Listfe497e2be29e556eda152481563466e6>, il suffit de remplacer la classe de chargement de la source de données dans la classe TestBase. De cette façon, nous pouvons utiliser JAVA pour reconstruire notre code à l'aide de l'interface. à l'intérieur, bien sûr nous devons d'abord avoir une interface


3.2 Nos classes PropertiesData et TxtData doivent bien sûr implémenter cette 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;
 }
  
}


3.3 Ensuite, quelque chose va changer dans TestBase, c'est-à-dire que l'objet de classe qui génère le chargement des données se produira. Changement, nous ajoutons une nouvelle méthode dans TestBase (c'est une nouvelle façon de générer des objets de classe)
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;
 }
  
}


3.4 La méthode getTestData() dans la classe TestBase Il est temps de la changer à nouveau
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;
}


3.5 Exécutez à nouveau TestDemo et vous constaterez que le résultat est toujours le même. Par conséquent, pour le moment, il vous suffit de modifier le chemin de la classe de chargement des données.
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 le chemin de la classe de chargement de données 4.1 À ce stade, nous pouvons réfléchir au chemin de la classe de chargement de données Écrit dans le fichier de configuration config.properties


4.2 Chargement du fichier de configuration
DataSource=com.test.testdata.TxtData


4.3 Améliorez la méthode getTestData() dans TestBase :
public class Config {
  
 public static String DATA_SOURCE;
  
 static{
  Map<String, String> map = PropertiesHandler.getPropertyData("config/config.properties");
  DATA_SOURCE = map.get("DataSource");
 }
  
}


4.4 Exécutez à nouveau la classe TestDemo et le résultat est toujours le même. Jusqu'à présent, nous avons implémenté la modification du contenu du fichier de configuration pour sélectionner la source de données à charger.
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. Basculer entre plusieurs sources de données

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"));
 }
  
}

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

六. 工程结构图:

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn