比如我们使用java+Selenium编写页面自动化测试的功能。
现在有个登录页面。
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")); } }
面向过程就是命令式的编程,就是意识流,把脑子里的想法转换成指令,让计算机去执行。
这样的模式是跳过“抽象”这一步骤,而计算机领域,“抽象”“建模”是非常重要的方法,甚至超过编码本身的重要性。
初级程序员这么写能完成任务也算达成目标了,但我们绝不能止步于此,我们要设想我们的代码要能应对更大的“变化”。
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开发。
中高级程序员如果能合理的划分项目的文件结构和业务对象,构建不同的抽象角色,承担不同的职责,然后在某处组装调用,那么这个项目至少不会被后来的维护者骂脏话了,也能承受相当长一段时间的业务变化,项目也能服役相当一段时间了。
然而毫不夸张的说,面试的时候夸夸其谈的所谓的大佬,也未必能很务实的去面向对象开发,尽管他们知道这些理论。他们会选择第一种方式,“又不是不能用”。要么就是眼高手低,要么就是没有热情和追求。
所以我劝大家务实一点,三思而码。梳理清楚业务需求,先抽象再建模,让代码“活”起来,你在创建一个世界,这个世界里有好多超能力的角色,它们都有自己的职责,而且尽可能地应付变化的袭击。
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,结合编程语言的高级特性(诸如反射、注解等),创造出使调用者使用起来会更加友好和简洁的对象模型。