通过Selenium Page Factory谈程序员三境界

需求例子

比如我们使用java+Selenium编写页面自动化测试的功能。
现在有个登录页面。

1. It works

public class Login {
  public void testLogin() {
    // fill login data on sign-in page
    driver.findElement(By.name("user_name")).sendKeys("testUser");
    driver.findElement(By.name("password")).sendKeys("my supersecret password");
    driver.findElement(By.name("sign-in")).click();

    // verify h1 tag is "Hello userName" after login
    driver.findElement(By.tagName("h1")).isDisplayed();
    assertThat(driver.findElement(By.tagName("h1")).getText(), is("Hello userName"));
  }
}

面向过程就是命令式的编程,就是意识流,把脑子里的想法转换成指令,让计算机去执行。
这样的模式是跳过“抽象”这一步骤,而计算机领域,“抽象”“建模”是非常重要的方法,甚至超过编码本身的重要性。
初级程序员这么写能完成任务也算达成目标了,但我们绝不能止步于此,我们要设想我们的代码要能应对更大的“变化”。

2. OOP

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

/**
 * Page Object encapsulates the Sign-in page.
 */
public class SignInPage {
  protected static WebDriver driver;

  // <input name="user_name" type="text" value="">
  private By usernameBy = By.name("user_name");
  // <input name="password" type="password" value="">
  private By passwordBy = By.name("password");
  // <input name="sign_in" type="submit" value="SignIn">
  private By signinBy = By.name("sign_in");

  public SignInPage(WebDriver driver){
    this.driver = driver;
  }

  /**
    * Login as valid user
    *
    * @param userName
    * @param password
    * @return HomePage object
    */
  public HomePage loginValidUser(String userName, String password) {
    driver.findElement(usernameBy).sendKeys(userName);
    driver.findElement(passwordBy).sendKeys(password);
    driver.findElement(signinBy).click();
    return new HomePage(driver);
  }
}

这样就好了一点,利用OOP编程语言提供的OO特性(字段,属性,方法,继承,实现等),进行OOP开发。

中高级程序员如果能合理的划分项目的文件结构和业务对象,构建不同的抽象角色,承担不同的职责,然后在某处组装调用,那么这个项目至少不会被后来的维护者骂脏话了,也能承受相当长一段时间的业务变化,项目也能服役相当一段时间了。

然而毫不夸张的说,面试的时候夸夸其谈的所谓的大佬,也未必能很务实的去面向对象开发,尽管他们知道这些理论。他们会选择第一种方式,“又不是不能用”。要么就是眼高手低,要么就是没有热情和追求。

所以我劝大家务实一点,三思而码。梳理清楚业务需求,先抽象再建模,让代码“活”起来,你在创建一个世界,这个世界里有好多超能力的角色,它们都有自己的职责,而且尽可能地应付变化的袭击。

3. Best Practice

package pages;

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

public class Login {
	
	final WebDriver driver;
	
	//Constructor, as every page needs a Webdriver to find elements
	public Login(WebDriver driver){
			this.driver=driver;
		}
		
	//Locating the username text box
	@FindAll({
		@FindBy(id="wrapper"),
		@FindBy(id="userName")
	})
	WebElement username;
	
	//Locating the password text box
	@FindBy(id="password")
	WebElement pswd;
	
	//Locating Login Button
	@FindBy(id="login")
	WebElement loginBtn;
	
	
	//Method that performs login action using the web elements
	public void LogIn_Action(String uName, String pwd){
		username.sendKeys(uName);
		pswd.sendKeys(pwd);
		loginBtn.click();
	}
}
public static void main(String[] args) {
	driver = new ChromeDriver();
	Login loginPg = PageFactory.initElements(driver, Login.class);
	loginPg.LogIn_Action("---your username---", "---your password---");
	driver.quit();		
}

简单看好像与第二种方式没啥区别。事实上,纯熟OOP已经很棒了。如果在此基础上,还能站的更高,甚至站在上帝视角进行看待问题和抽象设计,那么无疑是最佳实践了。
这种方式使用Page Object Model,将页面视为对象,抽象Factory,结合编程语言的高级特性(诸如反射、注解等),创造出使调用者使用起来会更加友好和简洁的对象模型。

原文地址:https://www.cnblogs.com/talentzemin/p/15319410.html