2016-12-16 6 views
0

現在、さまざまな開発環境で動作するテストスイートがあります。最近、アプリケーションの完全な書き換えが新しい環境に展開された&でした。類似したページロジックを持ち、ロケータが異なる環境の処理

アプリケーションは&とほぼ同じように動作します。ページロジックはほぼ同じです。大きな違いは、HTML書き換えによってロケータが役に立たなくなっていることです。私はこの新しい環境のためにロケータを扱う方法を確信していると同時に、ページオブジェクトモデルを遵守しています。

ページオブジェクトモデルは、すべてのページロジックがそれぞれのページオブジェクトクラスに保持されるべきであることを示します。私はこれにロケータが含まれていると仮定しています。

この戦略を実行すると、重複したロケータでいっぱいの肥大化したページオブジェクトクラスが残されます。この問題に対処するために推奨されるベストプラクティスまたはクリーンなソリューションはありますか?

私は考えることができる可能な解決策は以下のとおりです。

  1. は環境ごとに個別のロケータファイルを作成し、ページオブジェクトのクラスから削除します。

新しい環境のために別々のページオブジェクトを作成します

  • 現在のページオブジェクトクラス内の重複または同様の名前のロケータを作成します。これらのソリューションは、[OK]を鳴らすかどうかにコメントをanyodyすることはできますか?または、代替案を提案してください。

  • +0

    の両方のために使用される文字列あなたのPageObjectクラスの「FindBy」注釈を使用していますか?または、コードからfindElementを使用していますか? – Grasshopper

    +0

    Imは@FindByアノテーションを使用しています – Cathal

    答えて

    3

    pageobjectクラスの外部のロケータを、古いロケータと新しいロケータの2つの異なるクラスに確実に移動します。各ロケータにpublic static final Stringを使用します。あなたが持っている問題は、Javaアノテーションの値には定数式が必要なため、メソッドを使用してFindByに別のロケータを送信することはできません。しかし、三項演算子を使って定数式を作ることができます。

    以下、グローバルフラグに基づいて、単一のWebElementから別のボタンをクリックするが、ロケータはFindBy注釈の 'using'値の式によって変更されるコードを追加しました。プロパティファイルからドライバを初期化するときに、起動時にグローバルフラグの値を設定できます。

    これは、FindByに含める必要があり、findElement()に送信されるロケータ - = GlobalFlag.devEnvを使用していますか? NewLocators.newLocxpath:OldLocators.newLocxpath。これはどこにでもペーストをコピーするのに苦労します。

    ウェブサイトが一般公開されているため、コードを試すことができます。

    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、提案に感謝します。私はあなたがあなたの提案で正しい道にいると思います。最適な解決法はおそらくカスタムElementLoactorFactoryを作成することですが、それは私が達成する方法を完全に理解しているものではありません。私はページロジックの違いが元々思ったより大きかったので、ページオブジェクト全体を書き直しました。しかし、今私はかなりの量の重複したコードを残しています – Cathal

    +0

    セレンコードのデフォルトクラスを拡張するだけなので、独自のカスタムコードを書くのは大変な作業ではありません。私は、既存のものを拡張するカスタムのFindByクラスに新しいパラメータを追加する必要もあると思います。それ以外の場合は、既存の「使用している」ものを混乱させます。重複したコードを基底クラスや他の戦略に抽出してください。成長するプロジェクトがあれば、重複して後の段階であなたに噛み付くでしょう。 – Grasshopper

    0

    これは私がこれを克服する方法です。

    環境ごとに異なる要素プロパティファイルを用意しました。

    環境A、B 私のプロジェクトでは、Elements_A.propertiesとElements_B.propertiesの2つのプロパティファイルを保持します。 これらのプロパティファイルには、すべてのページ要素があります。 環境に基づいてスクリプトを実行しているときに、スクリプト内の関連するプロパティファイルを参照できるため、1つの要素が他の要素と異なる場合は問題ありません。

    は異なるロケータと、テキストボックスがあるホームページにAとBで を言うことができます。

    だから、プロパティファイルAに我々は HomePage_Name_TextBox = id_NameInA 「id_NameInA」としての要素を挙げることができるロケータ値と「HomePage_Name_TextBoxは」あなたがその特定の要素を参照するために使用するつもりの文字列です。

    プロパティファイルAで賢明のように、我々は同じ要素を挙げることができる HomePage_Name_TextBox = id_NameInB 「id_NameInBは」ロケータ値と「HomePage_Name_TextBox」であるあなたは、その特定の要素を参照するために使用するつもりの文字列です。

    両方の要素に同じ名前(HomePage_Name_TextBox)が割り当てられ、ロケータの値が異なることがわかります。すべてのページクラスで

    私は、地図を宣言し、今あなたがあなたのページの要素を初期化しようとして方法を決定するには、いくつかのオプションがあります。

    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. あなたのメインクラスで使用すると、一致する要素のプロパティファイルを読み込み、マップを渡すことができます(パラメータ化コンストラクタを宣言し、ホームページのオブジェクトを初期化する前に、あなたはすべての要素が読んだことがあるマップオブジェクトを渡すことができますホームページのコンストラクタにすべての要素を含む)
    2. または、HomePageコンストラクタ自体の共通プロパティファイルを読み込むことができます。ここで、Elementsプロパティファイルのパスを参照できます。 例:CommonConfig.properties ができるが、そのようなすべてのどの環境でスクリプトを実行しているとして、構成の詳細、および一般的なファイルパス読むこと(そのような要素のファイルパスなど)と、このファイルが含まれているこのファイルは、コンストラクタ内で読み込まれます 設定ファイルを使用すると、Aでスクリプトを実行したいときは、「リソース/ Elements_A.propertiesに共通するプロパティファイルに「ElementPropFilePath」を変更することができ、この
      ElementPropFilePath =リソース/ Elements_A.properties

    のようになります。 "実行する前に。 Bでスクリプトを実行する場合は、実行前に共通プロパティファイルの "ElementPropFilePath"を "Resources/Elements_B.properties"に変更できます(これはマシン内のファイルの場所です)。

    各環境のすべての要素を含むプロパティファイルを維持し、そのプロパティの詳細を提供し、各ページクラス内にあるelementMapを入力すれば、その要素を共通で参照することができますあなたは(この例ではHomePage_Name_TextBoxある)環境

    関連する問題