Selenuim Testing - Framworks

2019-04-22  本文已影响0人  小眼睛的露鹿酱

POM(Page object Model) & Page Factory: WebDriver
POM是一种设计模式,用于创建web ui元素的对象存储库。在这种模式下,每一个WEB应用下的页面都应该具有一个相关的page的class; 这个class能够寻找到所有页面的webElement, 还包含各种能够实现操作的methods;
这些methods的名字应该作为每一个操作的目标。例如, 一个加载器正在等待要显示的支付网关;那就可以将这个POM中cloass的methods写成 waitForPaymentScreenDisplay()

开始一个UI的自动化测试, 并不是一个很艰难的工作。 我们只需要找到相关的Element, 来完成对应的功能。
考虑下面的一个简单的脚本去登陆一个网站



正如你所见, 无非就是去找到元素, 然后输入对应的值。这是一个简单的脚本,脚本看上去很容易, 但是随着时间的增长,你需要增减越来越多的代码, 事情就变得很复杂。
最主要的问题就是 假如10个不同的而脚本正在使用相同的元素,一旦有任何的改变, 我们就需要改变所有的代码。这即费时还费力。
一个更好的维护脚本的方法就是去创建单独的class , 能够找到对应得元素或者就是去输入值, 或者去验证。这个class能够被重复利用,而且能够容易维护。
这种方法被称为 POM;


优势

  1. 代码简单而且容易理解
  2. 重复利用, 还能集成到TestNG和Junit来做单元测试
    代码会简洁而且被优化
  3. methods包含更加容易理解得名称

如何实现POM

简单得POM
POM模式得基本结构就是所有得页面得元素和操作都保存在一个class中;操作都保存在methods中



TestCase:


testcase
这个流程涉及到两个界面
  1. 登陆界面
  2. homepage界面
    分别对应以下两个class
package POMdemo;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;

public class LoginPage4Baidu {
      WebDriver driver;
      By user = By.name("uid");
      By pwd = By.name("password");
      By login = By.name("btnLogin");
      By resetBy = By.name("btnReset");
      By titletext = By.className("barone");  //如果click正确后,用于验证(Guru99 Bank)是否登陆成功;
      
      //构造函数
      public LoginPage4Baidu(WebDriver driver) {
          this.driver = driver;
      }

    public void setUser(String username) {
        driver.findElement(user).sendKeys(username);
    }
    
    public void setPwd(String pwdString) {
        driver.findElement(pwd).sendKeys(pwdString);
    }

    public void clickLogin() {
        driver.findElement(login).click();
    }

    public void clickResetBy() {
        driver.findElement(resetBy).click();
    }
        
    public String getLoginTitle() {
      String titleString = driver.findElement(titletext).getText();
        return titleString;
    }
    
    public boolean loginPass() {
        return "Guru99 Bank".equals(getLoginTitle());
    }
    
    
}

package POMdemo;


import java.io.ObjectInputStream.GetField;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;

public class Homepagedemo {
    WebDriver driver;
    By content = By.xpath("/html/body/table/tbody/tr/td/table/tbody/tr[3]/td");
    
    public Homepagedemo(WebDriver driver) {
        this.driver = driver;
    }
    
    public String GetTitle() {
        return driver.findElement(content).getText();
    }
}

调用以上的class,完成测试

package POMdemo;

import java.sql.Driver;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;

public class pomDemo1 {

      WebDriver driver;
      LoginPage4Baidu loginObj;
      Homepagedemo homepageObj;
      
      //setup before test
      public void setup() {
          String driverLocationString = "D:\\codding\\seleniumTest\\seleniumDemo1\\DriverFolder\\chromedriver.exe";
          System.setProperty("webdriver.chrome.driver", driverLocationString);
          this.driver = new ChromeDriver(); 
          driver.get("http://demo.guru99.com/V4");
      }
      
      // test
      public void Login2checkName() {
          loginObj = new LoginPage4Baidu(this.driver);
          loginObj.setUser("mgr123");
          loginObj.setPwd("mgr!23");
          loginObj.clickLogin();
          System.out.println(loginObj.loginPass());
          
          homepageObj = new Homepagedemo(driver);
          String title = homepageObj.GetTitle();
          System.out.println("login passed and title is"+title);
      }
      
      public static void main(String[] args) {
        pomDemo1 demo1 = new pomDemo1();
        demo1.setup();
        demo1.Login2checkName();
        demo1.driver.quit();
    }
}

page Factory

Page Factory 是一种内建的Page Object 模型概念, 用于Selenuim WebDriver, 但是它是优化的。
在这里,我们遵循页面对象存储和methods的分离概念。另外在PageFatory class的帮助下,我们使用注释 @FindBy 来寻找 WebElement。 我们使用initElements来初始化web元素。



@FindBy 能使用 tagName partialLinkTest,name, linkTest,id,css,className, xpath作为属性。
以下就是一个例子

  1. login Class
package POMDEMO1;

import java.security.PublicKey;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;

public class loginPage {
   WebDriver driver;
   @FindBy(name="uid") WebElement username;      //类似于driver.findElement(By....)
   @FindBy(name="password") WebElement password;
   @FindBy(name="btnLogin") WebElement loginIcon;
   @FindBy(name="btnReset") WebElement resetIcon;
   
   public loginPage(WebDriver driver) {
       this.driver = driver;
       
       //下面的methods会创建所有的webElemets
       PageFactory.initElements(driver, this);
   }
   
   
   public void setUsername(String usernamestring) {
       username.sendKeys(usernamestring);
   }
   
   public void setPWD(String pwdString) {
       password.sendKeys(pwdString);
   }
   
   public void clickLogin() {
       loginIcon.click();
   }
   
   public void clickReset() {
       resetIcon.click();
   }
   
   public void user2login(String user,String pwd) {
       this.setUsername(user);
       this.setPWD(pwd);
       this.clickLogin();
   }
}
  1. homepage class
package POMDEMO1;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;

public class homepage {
    WebDriver driver;
    @FindBy(xpath="/html/body/table/tbody/tr/td/table/tbody/tr[3]/td") WebElement context;
    
    public homepage(WebDriver driver) {
        this.driver = driver;
        PageFactory.initElements(driver, this);
    }
    
    public String getContext() {
        return context.getText();
    }
}

  1. TestNG test
package POMDEMO1;

import java.util.concurrent.TimeUnit;

import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.testng.Assert;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;

public class POMdemo1 {
   WebDriver driver;
   loginPage loginObj;
   homepage homepageObj;
   
   @BeforeTest
   public void setup() {
       String driverLocationString = "D:\\codding\\seleniumTest\\seleniumDemo1\\DriverFolder\\chromedriver.exe";
       System.setProperty("webdriver.chrome.driver", driverLocationString);
       driver = new ChromeDriver();
       driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
       driver.get("http://demo.guru99.com/V4");
   }
   
   @Test(priority=0)
   public void test() {
       loginObj = new loginPage(driver);
       loginObj.user2login("mgr123", "mgr!23");
       homepageObj = new homepage(driver);
       Assert.assertTrue(homepageObj.getContext().toLowerCase().contains("manger id : mgr123"));
   }
   @AfterTest
   public void quit() {
       driver.quit();
   }
}

推荐使用:
AjaxElementLocatorFactory 包含wait时间


waits

在Selenuim中, Waits扮演了一个重要的角色。在这个教程中,你将学习到“implicit”和“Explicit”两种wait

为什么我们需要Waits

其实大部分得页面都是使用Ajax和JavaScript两种。当一个页面在浏览器中被加载得时候,页面中的元素会在不同的时间间隔中被加载。
如果页面没有加载完整, 这不仅会让识别元素变得困难, 而且会报出“ElementNotVisibleException”, 当使用Waits,我们就能有效地避免这个问题。
让我们来模拟一种情景, 我们需要在我们的脚本中使用implicit和explicit两种waits;假定 implicit设置的是20s, 而explicit设置的是10s。
假设我们正在寻找一个元素, 这个元素包含“ExpectedConditions”(外部Wait), 如果这个元素没有在规定的10s内加载好, 那他就会执行implicit Wait(20s); 要是还没有加载好, 就会抛异常。

Implicit Wait

Selenuim WebDriver 参考了Watir的隐式wait的观点。
这种wait会告诉WebDriver去等待确定的时间, 然后再抛出异常:"No Such Element Exception". 默认的时间是0.一旦我们设置了时间, WebDriver会等待。
下面的例子中, 声明了一个隐式的wait, 具体的时间是10s。

driver.manage().timeouts().implicitlyWait(TimeOut, TimeUnit.SECONDS);   
driver = new ChromeDriver(); 
driver.manage().timeouts().implicitlyWait(10,TimeUnit.SECONDS) ;
    String eTitle = "Demo Guru99 Page";

Explicit Wait

显示的wait就是去告诉WebDriver去等待确定的条件或者是最大的时间, 然后再抛出异常“ElementNotVisibleExpection”
显式的wait是一个很智能的等待, 但是他被应用与特定的element;显式的等待比较好的一个原因是 动态的等待Ajax元素的加载
一旦我们声明一个explicit wait, 我们需要使用“ExpectedConditions”或者我们能配置查看条件(使用 Fluent Wait)满足的频率。
These days while implementing we are using Thread.Sleep() generally it is not recommended to use

WebDriverWait wait = new WebDriverWait(WebDriverRefrence,TimeOut);
driver = new ChromeDriver(); 
WebDriverWait wait=new WebDriverWait(driver, 20);
String eTitle = "Demo Guru99 Page";
    String aTitle = "" ;
    // launch Chrome and redirect it to the Base URL
    driver.get("http://demo.guru99.com/test/guru99home/" );
    //Maximizes the browser window
    driver.manage().window().maximize() ;
    //get the actual value of the title
    aTitle = driver.getTitle();
    //compare the actual title with the expected title
    if (aTitle.contentEquals(eTitle))
    {
    System.out.println( "Test Passed") ;
    }
    else {
    System.out.println( "Test Failed" );
    }
    WebElement guru99seleniumlink;
    guru99seleniumlink= wait.until(ExpectedConditions.visibilityOfElementLocated(By.xpath( "/html/body/div[1]/section/div[2]/div/div[1]/div/div[1]/div/div/div/div[2]/div[2]/div/div/div/div/div[1]/div/div/a/i")));
    guru99seleniumlink.click();
    }

注意: 以上的例子中我们会等待20秒直到后面的条件满足, 然后我们点击click
下面举例一些条件语句:
1. alertIsPresent()
2. elementSelectionStateToBe()
3. elementToBeClickable()
4. elementToBeSelected()
5. frameToBeAvaliableAndSwitchToIt()
6. invisibilityOfTheElementLocated()
7. invisibilityOfElementWithText()

  1. presenceOfAllElementsLocatedBy()
  2. presenceOfElementLocated()
  3. textToBePresentInElement()
  4. textToBePresentInElementLocated()
  5. textToBePresentInElementValue()
  6. titleIs()
  7. titleContains()
  8. visibilityOf()
  9. visibilityOfAllElements()
  10. visibilityOfAllElementsLocatedBy()
  11. visibilityOfElementLocated()

Fluent Wait

流利的等待就是为了告诉webDriver, 抛出异常之前的等待条件, 以及检查条件满足的频率。
频率:以一个固定的交互时间来检测是否条件满足。
让我们考虑一个以不同的时间间隔加载元素的场景。如果我们声明显式等待20秒,该元素可能会在10秒,20秒甚至更长时间内加载。在抛出异常之前它会等到指定的时间。在这种情况下,流畅的等待是理想的等待使用,因为这将尝试以不同的频率找到元素,直到它找到它或最终的计时器用完为止。

Wait wait = new FluentWait(WebDriver reference)
.withTimeout(timeout, SECONDS)
.pollingEvery(timeout, SECONDS)
.ignoring(Exception.class);
package guru.test99;

import org.testng.annotations.Test;
import java.util.NoSuchElementException;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.Wait;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.testng.annotations.Test;

public class AppTest3 {
    protected WebDriver driver;
    @Test
    public void guru99tutorials() throws InterruptedException 
    {
    System.setProperty ("webdriver.chrome.driver",".\\chromedriver.exe" );
    String eTitle = "Demo Guru99 Page";
    String aTitle = "" ;
    driver = new ChromeDriver();
    // launch Chrome and redirect it to the Base URL
    driver.get("http://demo.guru99.com/test/guru99home/" );
    //Maximizes the browser window
    driver.manage().window().maximize() ;
    //get the actual value of the title
    aTitle = driver.getTitle();
    //compare the actual title with the expected title
    if (aTitle.contentEquals(eTitle))
    {
    System.out.println( "Test Passed") ;
    }
    else {
    System.out.println( "Test Failed" );
        }
    
    Wait<WebDriver> wait = new FluentWait<WebDriver>(driver)                            
            .withTimeout(30, TimeUnit.SECONDS)          
            .pollingEvery(5, TimeUnit.SECONDS)          
            .ignoring(NoSuchElementException.class);
    WebElement clickseleniumlink = wait.until(new Function<WebDriver, WebElement>(){
    
        public WebElement apply(WebDriver driver ) {
            return driver.findElement(By.xpath("/html/body/div[1]/section/div[2]/div/div[1]/div/div[1]/div/div/div/div[2]/div[2]/div/div/div/div/div[1]/div/div/a/i"));
        }
    });
    //click on the selenium link
    clickseleniumlink.click();
    //close~ browser
    driver.close() ;
    }
}

频率设置的是5s, 最大的时间是30s,每五秒检查一次元素,不超过30s 要是还是没有就会去报" ElementNotVisibleException"


image.png

不推荐使用Thread.Sleep()

上一篇下一篇

猜你喜欢

热点阅读