2016-12-16 1 views
0

J'ai une suite de tests qui fonctionne actuellement dans différents environnements de développement. Récemment, une réécriture complète de l'application a été effectuée & déployé dans un nouvel environnement.Gestion d'environnements avec une logique de page similaire mais avec des localisateurs différents

L'application semble & agit presque de manière identique. La logique de la page est plus ou moins la même. La grande différence est que la réécriture HTML a rendu mes localisateurs inutiles. Je ne sais pas comment traiter avec les localisateurs pour ce nouvel environnement tout en adhérant au modèle d'objet page.

Le modèle d'objet de page indique que toute la logique de page doit être conservée dans la classe d'objet de page correspondante. Je suppose que cela inclut aussi les localisateurs. Suite à cette stratégie me laisserait avec une classe d'objet de page gonflée pleine de localisateurs en double. Existe-t-il des meilleures pratiques recommandées ou des solutions propres pour lutter contre ce problème?

Les solutions possibles que je peux penser sont:

  1. Créer des fichiers de localisation séparés pour chaque environnement et les retirer de la classe d'objets de page.
  2. Créer localisateurs double ou le même nom dans la page courante classe d'objets
  3. Créer des objets séparés page pour le nouvel environnement

peut anyody commentaire si oui ou non ces solutions ok le son? Ou offrir des suggestions alternatives?

+0

Utilisez-vous l'annotation 'FindBy' dans vos classes PageObject? Ou utilisez-vous findElement du code? – Grasshopper

+0

Im utilisant @FindBy annotations – Cathal

Répondre

3

Déplacer définitivement les localisateurs en dehors de la classe pageobject dans deux classes différentes, une pour les anciens locators et une pour les nouveaux locators. Utilisez public static final String pour chaque localisateur. Le problème que vous allez rencontrer est que les valeurs d'annotation Java nécessitent une expression constante, donc vous ne pouvez pas utiliser une méthode pour envoyer un localisateur différent à FindBy. Mais vous pouvez utiliser un opérateur ternaire pour créer une expression constante. Ci-dessous j'ai ajouté un code qui, sur la base du drapeau global, clique sur un bouton différent d'un seul WebElement mais le localisateur est modifié par une expression sur la valeur 'using' de l'annotation FindBy. Vous pouvez définir la valeur de l'indicateur global au démarrage lorsque vous initialisez un pilote à partir d'un fichier de propriétés.

C'est ce que vous devrez inclure dans le FindBy et les locators envoyés à findElement() - using = GlobalFlag.devEnv? NewLocators.newLocxpath: OldLocators.newLocxpath. Ce sera une douleur à copier coller partout.

Vous pouvez essayer le code que le site Web est accessible au public.

class CartConstant { 
    //Old locators 
    public static final String cartxpath = "//span[.='Cart']"; 
} 

class AccountConstant { 
    //New locators 
    public static final String accxpath = "//span[.='Account']"; 
} 

class GlobalFlag { 
    //Initialize this at the start 
    public static final boolean devEnv = true; 
} 

public class ChangeAnnotation { 
    //Change this in the code to include the choice 
    @FindBy(how=How.XPATH, using=GlobalFlag.devEnv ? AccountConstant.accxpath : CartConstant.cartxpath) 
    private WebElement butt; 

    @Test 
    public void demoSQA() throws InterruptedException { 

     System.setProperty("webdriver.chrome.driver", "E:/Software Testing/Selenium/Jars/chromedriver.exe"); 
     ChromeOptions chop = new ChromeOptions(); 
     chop.addArguments("test-type"); 
     chop.addArguments("start-maximized"); 
     WebDriver driver = new ChromeDriver(chop); 

     driver.get("http://store.demoqa.com/products-page/product-category/imacs/");   
     Thread.sleep(3000);  
     PageFactory.initElements(driver, this);  
     butt.click();    
    } 
} 
+0

Hey Grasshopper, merci pour la suggestion. Je pense que vous êtes sur la bonne voie avec votre suggestion. La solution optimale implique probablement la création d'une ElementLoactorFactory personnalisée, malheureusement ce n'est pas quelque chose que je comprends parfaitement comment accomplir. J'ai fini par réécrire l'objet de la page dans son intégralité parce que la différence dans la logique de la page était plus grande que je pensais à l'origine. Cependant, maintenant je me retrouve avec une bonne quantité de code dupliqué – Cathal

+0

Pas une tâche majeure pour écrire votre propre code personnalisé car il suffirait d'étendre les classes par défaut dans le code Selenium.Je pense que vous devrez également ajouter un nouveau paramètre à votre classe FindBy personnalisée en étendant la classe existante. Sinon, il va gâcher l'existant en utilisant un. Extraire votre code dupliqué dans une classe de base ou une autre stratégie, à peu près sûr qu'il viendra vous mordre à un stade ultérieur avec la duplication, si vous avez un projet en pleine croissance. – Grasshopper

0

Voici comment j'ai réussi à surmonter cela. J'ai gardé différents fichiers de propriétés d'éléments pour différents environnements.

Disons l'environnement A, B Dans mon projet je garde deux fichiers de propriétés nommés Elements_A.properties et Elements_B.properties Ces fichiers de propriétés ont tous les éléments de la page. Si un élément diffère de l'autre, cela ne posera aucun problème car, lors de l'exécution du script en fonction de l'environnement, vous pouvez référencer le fichier de propriétés pertinent dans le script.

Disons dans A et B dans HomePage il y a une zone de texte avec différents locators.

Donc, dans le dossier de la propriété A, on peut citer l'élément comme HomePage_Name_TextBox = id_NameInA « id_NameInA » est la valeur de localisation et « HomePage_Name_TextBox » est la chaîne que vous allez utiliser pour faire référence cet élément particulier.

Comme sage dans le dossier de la propriété A, on peut citer le même élément que HomePage_Name_TextBox = id_NameInB « id_NameInB » est la valeur de localisation et « HomePage_Name_TextBox » est la chaîne que vous allez utiliser pour faire référence cet élément particulier.

Vous pouvez remarquer que les deux éléments portent le même nom (HomePage_Name_TextBox) et que les valeurs de localisation sont différentes.

Dans chaque classe de page j'ai déclaré une carte et maintenant vous avez plusieurs options pour décider comment vous allez initialiser les éléments pour votre page.

public class HomePage { 

    Map<String, String> elementsMap = new HashMap<String, String>(); 

    //Option 1 
    public HomePage(Map<String, String> elementMapObj) { 
     elementsMap = elementMapObj; 
    } 

    //Option 2 
    public HomePage() { 
     Properties    prop  = new Properties(); 
     FileReader    reader; 
     HashMap<String, String> propertyMap = new HashMap<String, String>(); 

     try { 
      reader = new FileReader(new File("CommonConfig.properties")); 
      prop.load(reader); 
      for (String key : prop.stringPropertyNames()) 
      { 
       String value  = prop.getProperty(key); 
       propertyMap.put(key, value); 
      } 
     } catch (Exception e) { 
      //System.out.println(e.toString()); 
     } 

     try { 
      reader = new FileReader(new File(propertyMap.get("ElementPropFilePath"))); 
      prop.load(reader); 
      for (String key : prop.stringPropertyNames()) 
      { 
       String value  = prop.getProperty(key); 
       elementsMap.put(key, value); 
      } 
     } catch (Exception e) { 
      //System.out.println(e.toString()); 
     } 

    } 
} 
  1. Vous pouvez déclarer un constructeur paramétrés et passer un objet de la carte où vous avez tous les éléments lire avant d'initialiser un objet de HomePage (dans votre classe principale, vous pouvez lire le fichier de propriétés d'élément correspondant et passer la carte OU vous pouvez lire un fichier de propriétés commun dans le constructeur HomePage lui-même où vous pouvez mentionner le chemin du fichier de propriétés d'éléments. ex: CommonConfig.properties ce fichier peut contenir tous les détails de configuration tels que l'environnement dans lequel vous exécutez les scripts et les chemins de fichiers communs à lire (tels que le chemin du fichier d'élément) et ce fichier seront lus dans le constructeur fichier de configuration ressemblera à ceci
    ElementPropFilePath = Ressources/Elements_A.properties

Lorsque vous voulez exécuter des scripts en A, vous pouvez changer le « ElementPropFilePath » dans le fichier de propriété commune à « Ressources/Elements_A.properties "avant de courir. Lorsque vous voulez exécuter des scripts dans B, vous pouvez remplacer "ElementPropFilePath" dans le fichier de propriétés commun par "Resources/Elements_B.properties" avant de l'exécuter (il s'agit de l'emplacement du fichier dans la machine). Pour dire simplement, si vous gérez des fichiers de propriétés contenant tous les éléments pour chaque environnement, et fournissez ces détails de propriété et remplissez l'elementMap que vous avez à l'intérieur de chaque classe de page, vous pourrez référencer cet élément avec le commun string que vous avez utilisé pour les deux environnements (qui est HomePage_Name_TextBox dans cet exemple)