2 Modèles de conception et meilleures pratiques Selenium importants

Dans ce didacticiel, nous allons en apprendre davantage sur les modèles de conception Selenium et les meilleures pratiques tout en travaillant avec le développement de framework Selenium Automation (framework hybride en sélénium), il existe deux variantes de Framework Design ou Framework model que nous devons prendre en compte, à savoir: 

Nous devons savoir et comprendre pourquoi un modèle de conception de langage est nécessaire lorsque nous développons notre cadre dans l'un des modèles de cadre Selenium. Nous suggérons de parcourir les segments précédents du Série de didacticiels sur le développement de Selenium Framework pour avoir toute la compréhension.

Modèles de conception de sélénium et meilleures pratiques - cadre hybride en sélénium
Modèles de conception de sélénium et meilleures pratiques - cadre hybride en sélénium

Comprenons cela en détail: 

modèles de conception de sélénium et meilleures pratiques -charpente hybride en sélénium

Lors de la conception d'un cadre, nous devons prendre en compte une architecture de conception, c'est-à-dire des modèles de conception de sélénium et des meilleures pratiques, et selon les besoins du type de modèle de cadre, nous devons sélectionner un langage Design pattern pour résoudre l'état du problème de la conception du cadre dans son ensemble.

Par conséquent, juste pour conclure, nous pouvons choisir un modèle de cadre Selenium (hybride, modèle d'objet de page, basé sur les données, etc.), mais pour implémenter le modèle, nous devons suivre et implémenter un modèle de conception de langage (par exemple, des modèles de conception java / C # ) 

Pourquoi nous avons besoin d'un modèle de conception de sélénium et des meilleures pratiques lors de la création de Selenium Framework: 

  • Établir la conception du stand du cadre pour développer différents outils et utilitaires.
  • Tout langage (par exemple, Java / C #, etc.) a plusieurs modèles de conception, et chaque modèle de conception a ses propres avantages et inconvénients et est destiné à résoudre différents problèmes.
  • Conception standard et robuste pour les membres de l'équipe. 
  • Réutilisation du code, de manière structurée et standardisée.
  • La maintenabilité et le débogage du code deviennent plus faciles.

Quels modèles de conception à utiliser dans Selenium Framework: 

Il existe quelques modèles de conception que vous pouvez utiliser pour implémenter différentes zones du framework, comme un exemple: 

  • Modèle de conception Singleton pour implémenter les données configurables (pour le cadre d'automatisation comme le nom du navigateur, l'environnement à exécuter, l'URL, etc.). 
  • Modèle de conception d'usine et d'usine abstraite (vous pouvez implémenter les divers pilotes multiples et l'implémentation du navigateur à l'aide de ce modèle de conception et également si vous souhaitez développer la fonctionnalité de travail avec divers flux de données tels que Excel, propriétés, YAML, base de données, pdf, image, etc., vous pouvez également utiliser le modèle de conception d'usine / abstrait).

Nous ferons le modèle de codage en direct de l'ensemble du Framework dans les prochains articles ici.

Modèle de conception Singleton pour le cadre hybride dans Selenium: 

Singleton Design Pattern est un modèle dans lequel vous pouvez créer un seul objet à partir d'une classe et utiliser le même objet pour accéder aux méthodes de la classe; nous pourrions utiliser le modèle de conception dans le configurateur où nous n'avons besoin que de lire les données de configuration et de charger dans un magasin de données (tout type de structure de données que vous pouvez utiliser au fur et à mesure des besoins lors de l'exécution de toutes les classes et méthodes) 

Nous pourrions donc obtenir la même chose de la manière ci-dessous tout en concevant la même chose avec le modèle Singleton Design. 

REMARQUE: Nous allons concevoir et développer le cadre à partir de zéro dans la prochaine section de la série de didacticiels, mais ce didacticiel spécifique vous donnera un aperçu de la nécessité du modèle de conception.

package com.cyborg.core.generic.dataUtils;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.LinkedHashMap;
import java.util.Properties;
import java.util.Set;

import org.apache.log4j.PropertyConfigurator;


// This is the SingleTon Class 
public class PropertiesDataUtils {

   private Properties properties = null;
   public static LinkedHashMap<String, String> configDataStore = new LinkedHashMap<String, String>();
   InputStream is = null;

// This is the static and private reference of the class which you could use anywhere in you framework 
   private static PropertiesDataUtils propertiesDataUtils = null;
   boolean centralizeLog  = false;


// This is the Private constructor to create the object but you can not access this from outside the class to maintain the design of the SingleTon pattern ie only one object creation .

   private PropertiesDataUtils(String filePath) {
       generateDataStore(filePath);
       centralizeLog =  Boolean.parseBoolean(PropertiesDataUtils.configDataStore.get("centralizedLog"));
       if(centralizeLog)
           PropertyConfigurator.configure(System.getProperty("user.dir")+"//src//test//resources//config//log4j_central.properties");
         else
            PropertyConfigurator.configure(System.getProperty("user.dir")+"//src//test//resources//config//log4j_local.properties");
   }

   private PropertiesDataUtils() {

   }
  
 
// This method basically create the instance of the SingleTon class 

   public static PropertiesDataUtils getInstance(String filePath) {
       if (propertiesDataUtils == null)
           propertiesDataUtils = new PropertiesDataUtils(filePath);
       return propertiesDataUtils;
   }


// this method basically creates the datastore where you want to store all the config data as discussed previously 

   private void generateDataStore(String filePath) {
       try {
           this.properties = new Properties();
           is=new FileInputStream(filePath);
           properties.load(is);
           overrideFromEnvironment();
           Set<Object> keys = loadAllKeys();
           for (Object k : keys) {
               String key = (String) k;
               configDataStore.put(key, getPropertyValue(key));
           }

       } catch (FileNotFoundException fileNotFoundException) {
           String exceptionData = String.valueOf(fileNotFoundException.getCause().getMessage());

       } catch (IOException ioException) {
           String exceptionData = String.valueOf(ioException.getCause().getMessage());
       } finally {
           if (null != is) {
               try {
                   is.close();
               } catch (Exception e) {
                   String exceptionData = String.valueOf(e.getCause().getMessage());

               }
           }

       }
   }


// This method is used to load all the keys from the properties file.

   private Set<Object> loadAllKeys() {
       Set<Object> keys = this.properties.keySet();
       return keys;
   }

   private String getPropertyValue(String key) {
       return this.properties.getProperty(key);
   }
   private void setPropertyValue(String key,String value) {
        this.properties.setProperty(key,value);
   }
  
  private void overrideFromEnvironment() {

     if (this.properties.getProperty("run_on_jenkins").equals("true")) {
        System.out.println("SET run_on_jenkins FLAG TO FALSE IN YOUR PROPERTIES FILE TO RUN LOCALLY....");
        String build_number = System.getenv("BUILD_NUMBER");
        this.properties.setProperty("build_number", build_number);
     }
    
  }
}

Par cette approche, nous pourrions utiliser le modèle de conception Singleton et l'utiliser dans notre cadre.

Modèle de conception d'usine dans Selenium Framework: 

Dans le modèle de conception d'usine, nous créons une classe (nous l'appelons une classe Factory), et d'autre part, nous en avons une interface et finalement implémenté par un nombre «n» de classes.

La classe de fabrique renvoie essentiellement l'objet des classes ci-dessus (en fonction du besoin), vous n'avez donc pas à gérer ce qui précède "N" nombre d'objets de classes; à la place, vous pouvez créer un objet de la classe Factory et appeler la méthode de la classe factory qui renvoie l'Object de base nécessaire pour les classes requises parmi les classes adobe «n».

Maintenant, vous pouvez envisager cette conception lors de la création des différentes implémentations de Webdriver / navigateur. 

Nous avons un navigateur différent et l'implémentation avec un type de pilote Selenium différent (par exemple, LocalDriver, RemoteDriver, ThreadDriver, etc.) et au fur et à mesure que vous avez besoin d'un type de pilote spécifique et d'un type de navigateur spécifique que vous pouvez mentionner dans le fichier de configuration et en fonction du besoin, la classe d'usine vous fournira l'instance du pilote et du navigateur que votre script d'automatisation pourra utiliser davantage. 

Voici la base de code pour implémenter ce modèle de conception lors de la création d'interactions pilote-navigateur: 

Conception d'interface: 

package com.cyborg.core.web.utils.driverUtils;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.RemoteWebDriver;



public interface IDriver {
   public WebDriver init(String browserName);

}


Nombre «N» d'implémentations de classes de navigation (qui implémentent l'interface):

package com.cyborg.core.web.utils.driverUtils;


import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.edge.EdgeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;


import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.safari.SafariDriver;

public class LocalDriver implements IDriver {
   public WebDriver init(String browserName) {


       String pathToDriver = getDriverPath(browserName);

       if (null != browserName) {

           switch (browserName) {
               case "chrome":
                   System.setProperty("webdriver.chrome.driver",
                           pathToDriver);
                   return new ChromeDriver();
               case "firefox":
                   System.setProperty("webdriver.gecko.driver", pathToDriver);
                   return new FirefoxDriver();

               default:
                   System.setProperty("webdriver.chrome.driver", pathToDriver);
                   return new ChromeDriver();
           }
       } else {
           System.setProperty("webdriver.chrome.driver",
                   pathToDriver);
           return new ChromeDriver();
       }
   }



   private String getDriverPath(String browserName) {

       String osData = System.getProperty("os.name").toLowerCase().split("\\s")[0];
       if (null != osData) {
           if (osData.equalsIgnoreCase("mac")) {
               return "./DriversExe/" + osData + "_" + browserName;

           } else if (osData.contains("nux") || (osData.contains("nix"))) {
               return "./DriversExe/linux_" + browserName;
           } else if (osData.contains("win")) {
               return "./DriversExe/" + osData + "_" + browserName + ".exe";
           }
       }
       return null;
   }
}

Voici l'implémentation de la classe Remote Driver: 

package com.cyborg.core.web.utils.driverUtils;


import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;

import com.cyborg.core.generic.dataUtils.PropertiesDataUtils;


import java.net.MalformedURLException;
import java.net.URL;

public class RemoteDriver implements IDriver {

   DesiredCapabilities caps;
   String remoteHuburl=PropertiesDataUtils.configDataStore.get("WEB_GRID_IP");

   @Override
   public WebDriver init(String browserName) {

       if (browserName != null) {

           switch (browserName) {
               case "firefox":
                   try {
                       return new RemoteWebDriver(new URL(remoteHuburl), caps.firefox());
                   } catch (MalformedURLException malformedUrlEx) {

                       malformedUrlEx.getCause().getMessage();
                       malformedUrlEx.printStackTrace();
                   }
               case "chrome":
                   try {
                       return new RemoteWebDriver(new URL(remoteHuburl), caps.chrome());
                   } catch (MalformedURLException malformedUrlEx) {

                       malformedUrlEx.getCause().getMessage();
                       malformedUrlEx.printStackTrace();
                   }
               case "ie":
                   try {
                       return new RemoteWebDriver(new URL(remoteHuburl), caps.internetExplorer());
                   } catch (MalformedURLException malformedUrlEx) {

                       malformedUrlEx.getCause().getMessage();
                       malformedUrlEx.printStackTrace();

                   }
               default:
                   try {
                       return new RemoteWebDriver(new URL(remoteHuburl), caps.chrome());
                   } catch (MalformedURLException malformedUrlEx) {

                       malformedUrlEx.getCause().getMessage();
                       malformedUrlEx.printStackTrace();
                   }
           }
           return null;
       } else {
           return null;
       }
   }

Voici l'implémentation de la classe Factory, qui fournit le navigateur et l'objet de classe de pilote respectifs: 

package com.cyborg.core.web.utils.driverUtils;



public class DriverProvider {

   public IDriver getDriver(String typeOfDriver) {


       if (typeOfDriver != null) {
           switch (typeOfDriver) {
               case "local":
                   return new LocalDriver();
               case "remote":
                   return new RemoteDriver();
              
               default:
                   return new LocalDriver();
           }
       } else {
           return null;
       }
   }

}

De même, vous pouvez implémenter le Appium pilote avec la même conception, fournissez simplement l'implémentation et déclarez une méthode dans les interfaces IDriver. 

Conclusion: Avec cela, nous concluons ici comment vous pouvez utiliser les modèles de conception de langage dans le cadre des modèles de conception Selenium et des meilleures pratiques tout en développant le cadre hybride dans Selenium; dans les prochains segments du didacticiel, nous créerons le cadre de modèle d'objet de page pour Selenium Automation.

Pour obtenir le Tutoriel général sur Selenium, vous pouvez visiter ici

À propos de Debarghya

Moi-même Debarghya Roy, je suis un ARCHITECTE en ingénierie travaillant avec la société fortune 5 et un contributeur open source, ayant environ 12 ans d'expérience / expertise dans diverses piles technologiques.
J'ai travaillé avec diverses technologies telles que Java, C#, Python, Groovy, UI Automation (Selenium), Mobile Automation (Appium), API/Backend Automation, Performance Engineering (JMeter, Locust), Security Automation (MobSF, OwAsp, Kali Linux , Astra, ZAP, etc.), RPA, automatisation de l'ingénierie des processus, automatisation mainframe, développement back-end avec SpringBoot, Kafka, Redis, RabitMQ, pile ELK, GrayLog, Jenkins et ayant également une expérience dans les technologies cloud, DevOps, etc.
Je vis à Bangalore, en Inde avec ma femme et j'ai une passion pour les blogs, la musique, jouer de la guitare et ma philosophie de vie est l'éducation pour tous qui a donné naissance à LambdaGeeks. Permet de se connecter via linked-in - https://www.linkedin.com/in/debarghya-roy/

Laisser un commentaire

Votre adresse email n'apparaîtra pas. Les champs obligatoires sont marqués *

Geeks Lambda