28

C# .Net을 사용하여 Selenium 2 Web Driver를 사용하여 테스트를 만들고 있습니다. 많은 Selenium 문서를 읽은 후에도 PageObject 디자인 패턴을 사용하여 테스트하는 방법을 알지 못했습니다.Selenium PageObject 디자인 패턴을 사용하는 가장 좋은 방법은 무엇입니까?

많은 셀렌 예제가 Java로만 표시되며 .Net 용 API 바인딩은 제한 사항 및 특정 언어로 설정된 표준으로 인해 항상 그렇다고 볼 수있는 것과 항상 같은 것은 아닙니다.

.Net Selenium Web Driver의 PageFactory에서 PageObject 디자인 패턴을 사용하는 가장 좋은 방법은 무엇입니까?

결국 PageObjects가 PageObject IWebElements를 사용하는 NUnit 테스트보다 더 많은 기능을 처리하기를 원합니다.

다음은 현재 테스트를 진행하는 방법에 대한 예입니다.

public class LoginPage 
{ 
    private IWebDriver webDriver; 

    [FindsBy(How = How.Id, Using = "ctl00_ctl00_ctl00_insideForm_insideForm_content_txtPassword")] 
    public IWebElement Password { get; set; } 

    [FindsBy(How = How.Id, Using = "ctl00_ctl00_ctl00_insideForm_insideForm_content_cmdSubmit")] 
    public IWebElement SubmitButton { get; set; } 

    [FindsBy(How = How.Id, Using = "ctl00_ctl00_ctl00_insideForm_insideForm_content_txtUserName")] 
    public IWebElement UserName { get; set; } 

    public LoginPage() { } 

    public LoginPage(IWebDriver webDriver) 
    { 
     this.webDriver = webDriver; 


     if(!webDriver.Url.Contains("Login.aspx")) 
     { 
      throw new StaleElementReferenceException("This is not the login page"); 
     } 
     PageFactory.InitElements(webDriver, this); 
    } 

    public HomePage signIn(string username, string password) 
    { 
     UserName.SendKeys(username); 
     Password.SendKeys(password); 
     SubmitButton.Submit(); 

     // Even if i create a NUnit test for this 
     // Issue with page loading still occures when I try and return new object 
     HomePage homePage = new HomePage(webDriver); 
     PageFactory.InitElements(webDriver, homePage); 
     return homePage; 
    } 
} 

이 순간이 내가 현재 NUnit과 함께 일을하고 무엇을 : 셀레늄 webdriver 디자인 패턴에 대한 내가 찾은 기사와 블로그 게시물의 대부분
[TestFixture] 
public class LoginPageTest : TestBase 
{ 
    private IWebDriver driver; 
    private LoginPage loginPage; 
    private HomePage homePage; 

    [SetUp] 
    [Description("Sets up the test fixture page objects and navigates to the login page.")] 
    public void SetUp() 
    { 
     driver = StartDriver(); 
     Log.Info("Driver started"); 
     driver.Navigate().GoToUrl("http://" + Environment + "); 
     loginPage = new LoginPage(); 
     PageFactory.InitElements(driver, loginPage); 
     //driver.Navigate().Refresh(); 
    } 

    [Test] 
    [Description("Enters invalid credentials and asserts that a correct error message is displayed.")] 
    public void SubmitFormInvalidCredentials() 
    { 
     loginPage.UserName.SendKeys("invalid"); 
     loginPage.Password.SendKeys("invalid"); 
     loginPage.SubmitButton.Click(); 
     IWebElement invalidCredentials = driver.FindElement(By.Id("ctl00_ctl00_ctl00_insideForm_insideForm_ctl02_title")); 
     Assert.AreEqual("Invalid user name or password", invalidCredentials.Text); 
    } 

    [Test] 
    [Description("Enters valid credentials and asserts that the user is taken to the home page.")] 
    public void SubmitFormValidCredentials() 
    { 
     loginPage.UserName.SendKeys("valid"); 
     loginPage.Password.SendKeys("valid"); 
     loginPage.SubmitButton.Click(); 

     homePage = new HomePage(); 
     PageFactory.InitElements(driver, homePage); 
     Assert.AreEqual("pattest", homePage.Username.Text); 
    } 

} 

내가 찾을 이전 게시물 모순을 제공합니다.

그럼 올바른 방법은 무엇입니까?

이 문제를 해결하기 위해 PageObject 디자인 패턴을 사용해 보았습니다.

[Test] 
    [Description("Login using PageObject Design Pattern")] 
    public void Login() 
    { 
     loginPage = new LoginPage(driver); 
     HomePage signIn = loginPage.SignIn("pattest", "pattest"); 
    } 
내 LoginPage

public LoginPage(IWebDriver driver) 
    { 
     this.driver = driver; 

     if (!driver.Url.Contains("Login.aspx")) 
     { 
      throw new ElementNotFoundException("This is not the login page"); 
     } 
     PageFactory.InitElements(driver, this); 
    } 

    public HomePage SignIn(string username, string password) 
    { 
     UserName.SendKeys(username); 
     Password.SendKeys(password); 
     SubmitButton.Click(); 
     return new HomePage(driver); 
    } 

내부

그리고, 물론 내 홈페이지가 자사의 생성자와 함께 시작되는 방법을 보여 : 효과적으로

public HomePage(IWebDriver d) 
    { 
     webDriver = d; 
     // I need to use this as its not freaking waiting for my Page to load when I pass the webdriver in the consturctor. 
     var wait = new WebDriverWait(webDriver, TimeSpan.FromSeconds(60)); 

     try 
     { 
      wait.Until(driver => driver.FindElement(By.Id("ctl00_ctl00_ctl00_insideForm_insideForm_loginStatus"))); 
     } 
     catch(Exception e) 
     { 
      throw new ElementNotFoundException("This is not the home page."); 
     } 
     PageFactory.InitElements(webDriver, this); 
    } 

은 어떻게 사용합니까 WebDriver PageObject 디자인 패턴 테스트. 나는 이것을 이해할 수 없다.

답변

16

PageFactory.InitElements(_driver, this); 당신의 기본 페이지 클래스의 생성자에 :

public class Page 
{ 
    public IWebDriver _driver; 

    public Page(IWebDriver driver) 
    { 
     this._driver = driver; 
     PageFactory.InitElements(_driver, this); 
    } 
} 

PageFactory documentation

+0

예, 프로젝트를 시작할 때이 구조가 완성되었습니다. +1 –

+4

질문입니다. 요소가 pageobject에서'Select' (드롭 다운 목록)이면 어떻게 될까요? 내가 select (dropdownlist)에 대한 pageobject를 사용할 수 없다는 말은 사실입니까? –

+0

누군가가 @Nick Kahn의 질문에 답할 수 있습니까 :) 나는 똑같은 문제를 겪고 있습니다. –

1

테스트에서 어설 션을 피하고 LoginPage.signIn 메서드를 고수하면 로그인에 실패 할 경우 예외가 발생합니다. 나는 NUnit에 익숙하지 않지만 '실패 할 것으로 예상'하는 행동을 지원한다고 생각한다.

페이지 별 로직을 한 곳 (페이지 클래스)에 보관하는 것이 좋습니다.

어쨌든 메인 앱이 발전함에 따라 웹 UI 테스트를 많이 수정해야 할 것입니다.

+1

답장을 보내 주셔서 감사합니다.하지만 여전히 페이지 객체 디자인 패턴을 사용하는 방법에 대해 설명하지 않거나 페이지를로드하는 것을 무시하는 webdriver와 같은 오류가 발생하는 이유는 무엇입니까? 자동으로) 그리고 내가 제출 한 페이지를 로딩하는 것을 차단하는 이유. 새로운 PageObject를 반환 할 때 일어나는 것처럼 보입니다.하지만 여전히 동일한 웹 드라이버에 대한 참조를 전달하므로 잘못된 것을 보지 못합니다. 이 전체 pageobject 디자인 패턴 물건 정말 셀렌 위키에 대한 자세한 설명서가 필요합니다. =/ –

+0

나는 또한 주장에 대한 귀하의 조언에 동의합니다. 그것은 한 번에 한 단계 씩 예상되는 예외를 지원합니다. 누군가가이 특별한 문제에 대해 나를 깨우칠 때까지 –

+0

나는 질문을 잘못 이해했다. 미안하다. – Bond

1

드라이버와 브라우저를 닫는 등의 탐색 및 해체에 대한 고토()와 같은 유사한 기능을() 만들 수있는 브라우저 클래스 만들기를 참조하십시오. `

public class Browser 
    { 
     static IWebDriver webDriver = new FirefoxDriver(); 
     //static IWebDriver webDriver = new ChromeDriver(); 
     //InternetExplorerOptions options = new InternetExplorerOptions(); 
     //static IWebDriver webDriver = new InternetExplorerDriver(@"C:\Program Files\Selenium\"); 
     public static void GoTo(string url) 
     { 
      //webDriver.Manage().Timeouts().ImplicitlyWait(new TimeSpan(0, 0, 5)); 
      webDriver.Url = url; 
     } 
     public static ISearchContext Driver 
     { 
      get { return webDriver; } 
     } 
     public static void Teardown() 
     { 
      webDriver.Quit(); 
     } 
     public static void MaximizeWindow() 
     { 
      webDriver.Manage().Window.Maximize(); 
     } 

페이지의 개별 클래스를 만들고 요소를 초기화하려면 PageFactory를 사용하십시오.

public class Admin 
    { 
     public static AdminPage AdminPage 
     { 
      get 
      { 
       var adminpage = new AdminPage(); 
       PageFactory.InitElements(Browser.Driver, adminpage); 
       return adminpage; 
      } 

     } 
    } 
    public class AdminPage 
    { 
     string Url = "http://172.18.12.225:4444/admin/admin.aspx"; 
     string Title = "Login"; 
     string Text = "Admin"; 
     public void GoTo() 
     { 
      Browser.GoTo(Url); 
     } 
     public bool IsAt() 
     { 
      return Browser.Title == Title; 
     } 
     public bool Is_At() 
     { 
      return Browser.Title == Text; 
     } 
     [FindsBy(How = How.Id, Using = "ctl16_lblUdpSageMesageCustom")] 
     public IWebElement UpdateMessage { get; set; } 

     [FindsBy(How = How.Id, Using = "hypPreview")] 
     public IWebElement BackHomeLink { get; set; } 
     //Login 
     // [FindsBy(How = How.Id, Using = "ctl14_UserName")] 
     // public IWebElement UserNameLink { get; set; } 
     [FindsBy(How = How.Id, Using = "ctl14_Password")][CacheLookup] 
     public IWebElement PasswordLink { get; set; } 
     [FindsBy(How = How.Id, Using = "ctl14_LoginButton")][CacheLookup] 
     public IWebElement LoginLink { get; set; } 
     //Forgot Password 
     [FindsBy(How = How.Id, Using = "ctl14_hypForgotPassword")][CacheLookup] 
     public IWebElement FPWLink { get; set; } 
     [FindsBy(How = How.Id, Using = "ctl14_wzdForgotPassword_txtUsername")][CacheLookup] 
     public IWebElement FPWUserNameLink { get; set; } 
     [FindsBy(How = How.Id, Using = "ctl14_wzdForgotPassword_CaptchaValue")][CacheLookup] 
     public IWebElement FPWCaptchaLink { get; set; } 
     [FindsBy(How = How.Id, Using = "ctl14_wzdForgotPassword_StartNavigationTemplateContainerID_StartNextButton")][CacheLookup] 
     public IWebElement FPWNextLink { get; set; } 
     [FindsBy(How = How.Id, Using = "ctl14_wzdForgotPassword_StartNavigationTemplateContainerID_CancelButton")][CacheLookup] 
     public IWebElement FPWCancelLink { get; set; } 
     [FindsBy(How = How.Id, Using = "sfToppane")][CacheLookup] 
     public IWebElement TopPane { get; set; } 
     [FindsBy(How = How.Id, Using = "sidebar")][CacheLookup] 
     public IWebElement sidebar { get; set; } 
     //Role 
     //[FindsBy(How = How.Id, Using = "ctl19_rptDashBoard_ctl01_hypPageURL")] 
     //public IWebElement Role { get; set; }  
     //User 
     //[FindsBy(How = How.Id, Using = "ctl19_rptDashBoard_ctl02_hypPageURL")] 
     //public IWebElement User { get; set; } 
     public void LogIn(string Username, string Password) 
     { 
      Browser.MaximizeWindow(); 
      IWebElement UserNameLink = Browser.WaitForElement(By.Id("ctl14_UserName"), 15); 
      UserNameLink.Click(); 
      UserNameLink.Clear(); 
      UserNameLink.SendKeys(Username); 
      PasswordLink.Click(); 
      PasswordLink.Clear(); 
      PasswordLink.SendKeys(Password); 
      LoginLink.Click(); 
     } 
} 

로그인 기능이있는 작은 예입니다. 답변이 늦어도 도움이되기를 바랍니다.

+0

위의 프레임 워크를위한 것입니다. 그리고 Microsoft Visual Studio Unit Test Framework를 사용하여 만든 단위 테스트에서 페이지 기능을 호출하는 테스트를 만드는 것이 더 좋습니다. – user3687440

+0

Browser.WaitForElement 메소드에 사용 된 코드를 공유 할 수 있습니까? 또한 페이지 객체를 통해 생성 된 IWebElement에서 IWebDriver를 얻으려면 어떻게해야합니까? –

관련 문제