赞
踩
团队最近采用了一种与之前的PageFactory思路完全不一样的模式来完成我们的自动化测试编码
在编写step过程中,有很多非常通用的步骤定义,这些步骤定义可编写大量与之类似的场景,而无需创建太多的步骤定义。
即采用一种命令式风格来编写场景步骤,使用fill,press这样的词语,对于这样一种风格有很多争议,但是不管好坏,尝试下总归是有好处的。
这种命令式的风格,是属于用户界面控件的直接操作,所以我们会编写很多通用的step,而使用者只需要传入控件元素属性和其他对于值即可。
如 I fill in "Input_name" with "test"
意思是:在输入框“Input_name”中输入“test”
其中Input_name是对应元素的别称,我们把所有页面的元素都统一组织在一个文件里面去
下面就开始搭建该框架,以登录csdn为例子
在项目根目录下创建一个目录dataEngine,在该目录下创建一个文件ObjectRepository.properties,该文件用于保存CSDN各个页面上的元素对象
- #该文件用于保存元素对象,每个Key是对应元素别称,Value是元素查找方式和查找值拼接,中间用英文符号":"分隔
- #需要注意每个元素使用查找方式的Id,Name,Class,Xpath,CssSelector,LinkText,PartialLinkText,Tag是固定的
-
- # Home Page Objects
- Userbar_logout=LinkText:登录
- Tag_body=Tag:body
-
- #Login Page Objects
- Input_name=Id:username
- Input_password=Id:password
- Login_button=Class:logging
在项目的test->java下,创建目录com,在目录com中创建目录util
在目录util下创建WebDriverUtil.java
上述对象哭文件中,我们目的是用户在编写测试场景时,输入Input_name,底层代码可以直接定位到元素,则对该文件进行解析
所以,首先操作对象库
- /** 操作对象库,根据传进来的Key,来获取Value
- * @param a(对应feature中传进来的元素名称即对应的是属性文件中的Key值)
- * @return(返回对应的values)
- */
- public static String readValue(String a){
- Properties defaultProperties = new Properties();
- String popath = "dataEngine/ObjectRepository.properties";
- String value=null;
- try {
- defaultProperties.load(new FileReader(popath));
- value = defaultProperties.getProperty(a);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- }catch (IOException e) {
- e.printStackTrace();
- }
- return value;
- }

之后根据获取到的Value,来获取元素的By值
- /**
- * 根据对象库中的Value来获取By的值
- * @param field(对应feature中传进来的元素名称)
- * @return
- */
- public static By getObjectLocator(String field) {
- String locatorProperty = readValue(field);
- System.out.println("解析该元素" + locatorProperty.toString());
- String locatorType = locatorProperty.split(":")[0];
- String locatorValue = locatorProperty.split(":")[1];
-
- By locator = null;
- if (locatorType.contains("Id")){
- locator = By.id(locatorValue);
- }else if (locatorType.contains("Name")){
- locator = By.name(locatorValue);
- }else if (locatorType.contains("Class")){
- locator = By.className(locatorValue);
- }else if (locatorType.contains("Xpath")){
- locator = By.xpath(locatorValue);
- } else if (locatorType.contains("CssSelector")){
- locator = By.cssSelector(locatorValue);
- }else if (locatorType.contains("LinkText")){
- locator = By.linkText(locatorValue);
- }else if (locatorType.contains("PartialLinkText")){
- locator = By.partialLinkText(locatorValue);
- }else if (locatorType.contains("Tag")){
- locator = By.tagName(locatorValue);
- }
- return locator;
- }

然后再根据上面获取到的By值来定位到可见元素
则WebDriverUtil.java文件的完整代码:- import org.openqa.selenium.*;
- import org.openqa.selenium.support.ui.ExpectedConditions;
- import org.openqa.selenium.support.ui.FluentWait;
- import org.openqa.selenium.support.ui.Wait;
-
- import java.io.*;
- import java.util.Properties;
- import java.util.concurrent.TimeUnit;
-
- public class WebDriverUtil {
-
- /**
- * 该方法用于查找可见的元素
- * @param webDriver
- * @param field(对应feature中传进来的元素名称)
- * @return
- */
- public static WebElement findFieldWithToBeVisibility(WebDriver webDriver, String field) {
- try {
- Wait<WebDriver> wait = new FluentWait<WebDriver>(webDriver)
- .withTimeout(30 * 1000, TimeUnit.MILLISECONDS)
- .pollingEvery(500, TimeUnit.MILLISECONDS)
- .ignoring(NoSuchElementException.class);
-
- final By locate = getObjectLocator(field);
-
- wait.until(ExpectedConditions.presenceOfElementLocated(locate));
- wait.until(ExpectedConditions.visibilityOfElementLocated(locate));
- return webDriver.findElement(locate);
- } catch(NoSuchElementException exception) {
- throw exception;
- }
- }
-
- /**
- * 根据对象库中的Value来获取By的值
- * @param field(对应feature中传进来的元素名称)
- * @return
- */
- public static By getObjectLocator(String field) {
- String locatorProperty = readValue(field);
- System.out.println("解析元素 " + field + "=" + locatorProperty.toString());
- String locatorType = locatorProperty.split(":")[0];
- String locatorValue = locatorProperty.split(":")[1];
-
- By locator = null;
- if (locatorType.contains("Id")){
- locator = By.id(locatorValue);
- }else if (locatorType.contains("Name")){
- locator = By.name(locatorValue);
- }else if (locatorType.contains("Class")){
- locator = By.className(locatorValue);
- }else if (locatorType.contains("Xpath")){
- locator = By.xpath(locatorValue);
- } else if (locatorType.contains("CssSelector")){
- locator = By.cssSelector(locatorValue);
- }else if (locatorType.contains("LinkText")){
- locator = By.linkText(locatorValue);
- }else if (locatorType.contains("PartialLinkText")){
- locator = By.partialLinkText(locatorValue);
- }else if (locatorType.contains("Tag")){
- locator = By.tagName(locatorValue);
- }
- return locator;
- }
-
- /** 操作对象库,根据传进来的Key,来获取Value
- * @param a(对应feature中传进来的元素名称即对应的是属性文件中的Key值)
- * @return(返回对应的values)
- */
- public static String readValue(String a){
- Properties defaultProperties = new Properties();
- String popath = "dataEngine/ObjectRepository.properties";
- String value=null;
- try {
- defaultProperties.load(new FileReader(popath));
- value = defaultProperties.getProperty(a);
- } catch (Exception e) {
- e.printStackTrace();
- }
- return value;
- }
- }

则通过该文件,我们就解析了对象库,并获取到对应的元素位置
然后在该目录下创建一个文件login.feature,像编写测试用例步骤一样编写我们预期的step:
- Feature: Login
-
- @login
- Scenario Outline: login in csdn
- #打开csdn首页
- Given I am on csdn
- #单击登录按钮
- And I press "Userbar_login"
- #输入用户名
- And I fill in "Input_name" with "<username>"
- #输入密码
- And I fill in "Input_password" with "<password>"
- And I press "Login_button"
- #登录成功后,可查到到用户名"echo_茵子",可以修改成自己的CSDN用户名
- Then should see text "echo_茵子" in "Tag_body"
-
- Examples:
- |username |password |
- #这里输入对应的用户名和密码
- |***** |***** |

- import com.config.ConfigManager;
- import com.util.SharedDriver;
- import cucumber.api.java.en.Given;
- import org.openqa.selenium.JavascriptExecutor;
- import org.openqa.selenium.NoSuchElementException;
- import org.openqa.selenium.WebDriver;
- import org.openqa.selenium.support.ui.ExpectedCondition;
- import org.openqa.selenium.support.ui.FluentWait;
- import org.openqa.selenium.support.ui.Wait;
-
- import java.util.concurrent.TimeUnit;
-
- public class IAmOnStepDefs {
-
- private final WebDriver driver;
- private final ConfigManager config;
- private static Wait<WebDriver> wait ;
- private static String baseUrl;
-
- public IAmOnStepDefs(SharedDriver driver, ConfigManager config) {
- this.driver = driver;
- this.config = config;
- wait = new FluentWait<WebDriver>(driver)
- .withTimeout(30, TimeUnit.SECONDS)
- .pollingEvery(500, TimeUnit.MILLISECONDS)
- .ignoring(NoSuchElementException.class);
- }
-
- /**
- *该方法用于实现csdn页面的跳转
- */
- @Given("^I am on csdn$")
- public void i_am_on() throws Throwable {
-
- baseUrl = this.config.get("base_path");
- this.driver.navigate().to(baseUrl);
-
- wait.until((new ExpectedCondition<Boolean>() {
- @Override
- public Boolean apply(WebDriver driverObject) {
- System.out.println("*****loading page*****");
- return (Boolean) ((JavascriptExecutor) driverObject).executeScript("return document.readyState === 'complete'");
- }
- }));
- }
- }

可看到第一个step已经可以正常运行了,后面五个步骤还没定义
- import com.util.SharedDriver;
- import com.util.WebDriverUtil;
- import cucumber.api.java.en.When;
- import org.openqa.selenium.WebDriver;
- import org.openqa.selenium.WebElement;
- import org.openqa.selenium.interactions.Actions;
-
- public class IPressStepDefs {
-
- private final WebDriver driver;
-
- public IPressStepDefs(SharedDriver driver) {
- this.driver = driver;
- }
-
- /**
- * 通过 field 找到某个元素,并进行点击
- */
- @When("^I press \"([^\"]*)\"$")
- public void i_press(String field) throws Throwable {
- WebElement element = WebDriverUtil.findFieldWithToBeVisibility(this.driver,field);
- new Actions(driver).moveToElement(element).perform();
- element.click();
- }
- }

创建IFillInWithStepDefs.java,内容如下所示
- import com.util.SharedDriver;
- import com.util.WebDriverUtil;
- import cucumber.api.java.en.When;
- import org.openqa.selenium.WebDriver;
- import org.openqa.selenium.WebElement;
-
- public class IFillInWithStepDefs {
-
- private final WebDriver driver;
-
- public IFillInWithStepDefs(SharedDriver driver) {
- this.driver = driver;
- }
-
- /**
- * 通过 field 找到某个元素,并向该元素输入文字
- */
- @When("^I fill in \"([^\"]*)\" with \"([^\"]*)\"$")
- public void i_fill_in_with(String field, String content) throws Throwable {
- WebElement element = WebDriverUtil.findFieldWithToBeVisibility(this.driver,field);
- if (null != element) {
- element.clear();
- element.sendKeys(content);
- }
- }
- }

创建ShouldSeeTextForElement.java,内容如下所示
- import com.util.SharedDriver;
- import com.util.WebDriverUtil;
- import cucumber.api.java.en.Then;
- import org.openqa.selenium.*;
- import org.openqa.selenium.support.ui.ExpectedConditions;
- import org.openqa.selenium.support.ui.FluentWait;
- import org.openqa.selenium.support.ui.Wait;
-
- import java.util.concurrent.TimeUnit;
-
- public class ShouldSeeTextForElement {
-
- private final WebDriver driver;
- private final Wait<WebDriver> wait;
-
- public ShouldSeeTextForElement(SharedDriver driver) {
- this.driver = driver;
- wait = new FluentWait<WebDriver>(this.driver)
- .withTimeout(30, TimeUnit.SECONDS)
- .pollingEvery(500, TimeUnit.MILLISECONDS)
- .ignoring(NoSuchElementException.class);
- }
-
- /**
- * 找到某个元素,并验证该元素存在内容text
- */
- @Then("^should see text \"([^\"]*)\" in \"([^\"]*)\"$")
- public void should_see_text(String text,String field) throws Throwable {
- try{
- WebElement element = WebDriverUtil.findFieldWithToBeVisibility(driver,field);
- ((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView();", element);
- wait.until(ExpectedConditions.textToBePresentInElement(element,text));
- }catch(Exception e){
- e.printStackTrace();
- }
- }
- }

则目前整个项目的目录结构如下所示:
这里是因为我们在对象库中使用了中文,默认情况下中文会被读成乱码,所以我们需要设置改下之前读取配置文件的代码:
- /** 操作对象库,根据传进来的Key,来获取Value
- * @param a(对应feature中传进来的元素名称即对应的是属性文件中的Key值)
- * @return(返回对应的values)
- */
- public static String readValue(String a){
- Properties defaultProperties = new Properties();
- String popath = "dataEngine/ObjectRepository.properties";
- String value=null;
- try {
- InputStream in=new FileInputStream(popath);
- InputStreamReader re=new InputStreamReader(in,"GB2312");
- BufferedReader bf=new BufferedReader(re);
- defaultProperties.load(bf);
- value = defaultProperties.getProperty(a);
- System.out.println(value);
- in.close(); // 关闭流
-
- } catch (Exception e) {
- e.printStackTrace();
- }
- return value;
- }

之后使用MAVEN中再次运行程序,查看日志
则上述我们就搭建了一个采用命令行风格来编写测试场景的小框架,欢迎大家批评指正~
源代码在该链接,可免费下载:http://download.csdn.net/detail/yan1234abcd/9630675
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。