2017-02-17 1 views
1

Brauchen Sie einige bessere Praktiken Umgang mit Elementen innerhalb von Frames. Selenium WebDriver funktioniert nur im Kontext eines Frame-/Hauptdokuments. Es kann keine Elemente für andere Frames finden, bevor ich IWebDriver.SwitchTo() esFrames in Selen verwalten C# WebDriver

Der Schmerz ist ich muss ständig zwischen den Frames wechseln. Zu keinem Zeitpunkt kann ich darauf vertrauen, welchen Frame IWebDriver derzeit ist.

Kann ich mehrere IWebDriver-Instanzen (einen Klon oder etwas) in einer einzelnen Browserinstanz haben oder gibt es nur eine pro Browserinstanz? Ich stelle mir vor, ich könnte IWebDriver Driver Eigentum haben, auf bestimmten Rahmen geschaltet, wo ich vertrauen kann, werde ich Elemente dort finden. Für eine andere Klasse würde ich IWebDriver Driver Eigenschaft auf einem anderen Rahmen verwenden.

Darüber hinaus wie Frames beim Erstellen von Page Object mit PageFactory.InitElements behandelt werden sollen? Ich muss IWebDriver wechseln, um den Frame zu korrigieren, bevor Elemente gefunden werden. Aber wird meine Page Object Klasse immer funktionieren, unabhängig davon, auf welchen Frame ich später umschalte? Ie.e gegeben 2 Seitenobjekte aus verschiedenen Frames - kann ich sie nahtlos in meinen Tests verwenden, ohne über Frames nachzudenken?

Konnte keine Best Practices in Bezug auf Frame-Management finden.

Antwort

1

Es wäre schön, wenn Iframe-Unterstützung in WebDriver ein wenig robuster wäre, aber es gibt Möglichkeiten, um die Situation zu helfen. Als Antwort auf Ihre Frage, ob WebDriver in Ihren Tests die iFrame-Umschaltung nahtlos umsetzt, wird es nicht funktionieren. Sie müssen diese Umstellung nach Bedarf selbst dann verwalten, wenn PageFactory für das Seitenobjekt ausgeführt wurde.

Eine Option, die eine Überlegung wert sein könnte, ist die Erstellung einiger Hilfsmethoden, die das Ein- und Ausblenden von Iframes handhaben.

Dies bedeutet, dass Sie vor dem Zugriff auf das Element in Ihre iframe-Switching-Methode wechseln können und von der PageFactory gefunden werden. Diese Logik kann im Page Object enthalten sein, sodass der Testschreiber bei Tests keine Iframe-Umschaltung durchführen muss. Wenn Sie diese Komplexität aus den Tests abstrahieren, können Sie sich auf die Geschäftsfälle konzentrieren. Es hilft auch bei der Wartung, da Produktänderungen, die diese Iframes betreffen, nur im Page Object geändert werden können und dann alle Tests, die das Page Object verbrauchen, nicht geändert werden müssen (in Bezug auf Frames).

Ein Beispiel:

public class MyPageObject 
    { 
     private readonly IWebDriver _driver; 

     [FindsBy(How = How.Id, Using = "id")] 
     private IWebElement _myWebElementInIFrame; 

     public MyPageObject(IWebDriver webDriver) 
     { 
      PageFactory.InitElements(webDriver, this); 
      _driver = webDriver; 
     } 

     public void DoStuff() 
     { 
      SwitchToIframe("myiframe"); 
      _myWebElementInIFrame.Click(); //element found using PageFactory data now 
      SwitchToDefaultContent(); 
     } 

     public void SwitchToIframe(string frameName) 
     { 
      _driver.SwitchTo().Frame(frameName); 
     } 

     public void SwitchToDefaultContent() 
     { 
      _driver.SwitchTo().DefaultContent(); 
     } 
    } 

Sie könnten ein bisschen weiter eine Methode Templating mit nehmen dies:

public class MyPageObject : BasePageObject 
    { 

     [FindsBy(How = How.Id, Using = "id")] 
     private IWebElement _myWebElementInIFrame; 

     public MyPageObject(IWebDriver webDriver) 
      : base(webDriver) 
     { 
      PageFactory.InitElements(webDriver, this); 
     } 

     public void DoStuff() 
     { 
      ExecuteActionInIFrame(() => 
      { 
       _myWebElementInIFrame.Click(); //element found using PageFactory data now 
      }, "myiframe", "mynestediframe"); 
     } 
    } 

    public abstract class BasePageObject 
    { 
     protected IWebDriver WebDriver { get; } 

     protected BasePageObject(IWebDriver webDriver) 
     { 
      WebDriver = webDriver; 
     } 

     public void ExecuteActionInIFrame(Action action, params string[] frameNames) 
     { 
      foreach (string frameName in frameNames) 
      { 
       WebDriver.SwitchTo().Frame(frameName); //switch into multiple nested iframes in passed in order 
      } 

      //perform action now that we're in proper iframe 
      action(); 

      //bounce out to root to have a standard starting point for next action 
      WebDriver.SwitchTo().DefaultContent(); 
     } 
    } 

Noch ein Tipp, der mir half, war der Name eines aktuellen iframe über einige bekommen Javascript. Dies kann Ihnen helfen zu bestimmen, wo genau Sie sich im gesamten DOM befinden, während Sie Iframes durchlaufen, wenn Sie diese Art von Informationen benötigen.

Hoffe, das hilft.

+0

Okay, danke für die Antwort. Ich vermutete, dass ich meine Klassen so modellieren muss, dass ich nicht darauf angewiesen bin, in welchem ​​Rahmen ich bin, sondern dass ich immer richtig switche. –