当前位置:   article > 正文

Cucumber java + Webdriver (8) 使用命令行风格来编写测试场景(Scenario)_webdriverutil

webdriverutil

团队最近采用了一种与之前的PageFactory思路完全不一样的模式来完成我们的自动化测试编码

 

在编写step过程中,有很多非常通用的步骤定义,这些步骤定义可编写大量与之类似的场景,而无需创建太多的步骤定义。

即采用一种命令式风格来编写场景步骤,使用fill,press这样的词语,对于这样一种风格有很多争议,但是不管好坏,尝试下总归是有好处的。

 这种命令式的风格,是属于用户界面控件的直接操作,所以我们会编写很多通用的step,而使用者只需要传入控件元素属性和其他对于值即可。

如 I fill in "Input_name" with "test"

意思是:在输入框“Input_name”中输入“test”

其中Input_name是对应元素的别称,我们把所有页面的元素都统一组织在一个文件里面去

 

下面就开始搭建该框架,以登录csdn为例子

1、在intellij idea创建一个Maven项KeyWordTest,在pom.xml添加依赖(参考之前文档)

2、创建对象库

在项目根目录下创建一个目录dataEngine,在该目录下创建一个文件ObjectRepository.properties,该文件用于保存CSDN各个页面上的元素对象

  1. #该文件用于保存元素对象,每个Key是对应元素别称,Value是元素查找方式和查找值拼接,中间用英文符号":"分隔
  2. #需要注意每个元素使用查找方式的Id,Name,Class,Xpath,CssSelector,LinkText,PartialLinkText,Tag是固定的
  3. # Home Page Objects
  4. Userbar_logout=LinkText:登录
  5. Tag_body=Tag:body
  6. #Login Page Objects
  7. Input_name=Id:username
  8. Input_password=Id:password
  9. Login_button=Class:logging

3、解析上述元素对象

在项目的test->java下,创建目录com,在目录com中创建目录util

在目录util下创建WebDriverUtil.java
上述对象哭文件中,我们目的是用户在编写测试场景时,输入Input_name,底层代码可以直接定位到元素,则对该文件进行解析

所以,首先操作对象库

  1. /** 操作对象库,根据传进来的Key,来获取Value
  2. * @param a(对应feature中传进来的元素名称即对应的是属性文件中的Key值)
  3. * @return(返回对应的values)
  4. */
  5. public static String readValue(String a){
  6. Properties defaultProperties = new Properties();
  7. String popath = "dataEngine/ObjectRepository.properties";
  8. String value=null;
  9. try {
  10. defaultProperties.load(new FileReader(popath));
  11. value = defaultProperties.getProperty(a);
  12. } catch (FileNotFoundException e) {
  13. e.printStackTrace();
  14. }catch (IOException e) {
  15. e.printStackTrace();
  16. }
  17. return value;
  18. }

之后根据获取到的Value,来获取元素的By值

  1. /**
  2. * 根据对象库中的Value来获取By的值
  3. * @param field(对应feature中传进来的元素名称)
  4. * @return
  5. */
  6. public static By getObjectLocator(String field) {
  7. String locatorProperty = readValue(field);
  8. System.out.println("解析该元素" + locatorProperty.toString());
  9. String locatorType = locatorProperty.split(":")[0];
  10. String locatorValue = locatorProperty.split(":")[1];
  11. By locator = null;
  12. if (locatorType.contains("Id")){
  13. locator = By.id(locatorValue);
  14. }else if (locatorType.contains("Name")){
  15. locator = By.name(locatorValue);
  16. }else if (locatorType.contains("Class")){
  17. locator = By.className(locatorValue);
  18. }else if (locatorType.contains("Xpath")){
  19. locator = By.xpath(locatorValue);
  20. } else if (locatorType.contains("CssSelector")){
  21. locator = By.cssSelector(locatorValue);
  22. }else if (locatorType.contains("LinkText")){
  23. locator = By.linkText(locatorValue);
  24. }else if (locatorType.contains("PartialLinkText")){
  25. locator = By.partialLinkText(locatorValue);
  26. }else if (locatorType.contains("Tag")){
  27. locator = By.tagName(locatorValue);
  28. }
  29. return locator;
  30. }

然后再根据上面获取到的By值来定位到可见元素

则WebDriverUtil.java文件的完整代码:

  1. import org.openqa.selenium.*;
  2. import org.openqa.selenium.support.ui.ExpectedConditions;
  3. import org.openqa.selenium.support.ui.FluentWait;
  4. import org.openqa.selenium.support.ui.Wait;
  5. import java.io.*;
  6. import java.util.Properties;
  7. import java.util.concurrent.TimeUnit;
  8. public class WebDriverUtil {
  9. /**
  10. * 该方法用于查找可见的元素
  11. * @param webDriver
  12. * @param field(对应feature中传进来的元素名称)
  13. * @return
  14. */
  15. public static WebElement findFieldWithToBeVisibility(WebDriver webDriver, String field) {
  16. try {
  17. Wait<WebDriver> wait = new FluentWait<WebDriver>(webDriver)
  18. .withTimeout(30 * 1000, TimeUnit.MILLISECONDS)
  19. .pollingEvery(500, TimeUnit.MILLISECONDS)
  20. .ignoring(NoSuchElementException.class);
  21. final By locate = getObjectLocator(field);
  22. wait.until(ExpectedConditions.presenceOfElementLocated(locate));
  23. wait.until(ExpectedConditions.visibilityOfElementLocated(locate));
  24. return webDriver.findElement(locate);
  25. } catch(NoSuchElementException exception) {
  26. throw exception;
  27. }
  28. }
  29. /**
  30. * 根据对象库中的Value来获取By的值
  31. * @param field(对应feature中传进来的元素名称)
  32. * @return
  33. */
  34. public static By getObjectLocator(String field) {
  35. String locatorProperty = readValue(field);
  36. System.out.println("解析元素 " + field + "=" + locatorProperty.toString());
  37. String locatorType = locatorProperty.split(":")[0];
  38. String locatorValue = locatorProperty.split(":")[1];
  39. By locator = null;
  40. if (locatorType.contains("Id")){
  41. locator = By.id(locatorValue);
  42. }else if (locatorType.contains("Name")){
  43. locator = By.name(locatorValue);
  44. }else if (locatorType.contains("Class")){
  45. locator = By.className(locatorValue);
  46. }else if (locatorType.contains("Xpath")){
  47. locator = By.xpath(locatorValue);
  48. } else if (locatorType.contains("CssSelector")){
  49. locator = By.cssSelector(locatorValue);
  50. }else if (locatorType.contains("LinkText")){
  51. locator = By.linkText(locatorValue);
  52. }else if (locatorType.contains("PartialLinkText")){
  53. locator = By.partialLinkText(locatorValue);
  54. }else if (locatorType.contains("Tag")){
  55. locator = By.tagName(locatorValue);
  56. }
  57. return locator;
  58. }
  59. /** 操作对象库,根据传进来的Key,来获取Value
  60. * @param a(对应feature中传进来的元素名称即对应的是属性文件中的Key值)
  61. * @return(返回对应的values)
  62. */
  63. public static String readValue(String a){
  64. Properties defaultProperties = new Properties();
  65. String popath = "dataEngine/ObjectRepository.properties";
  66. String value=null;
  67. try {
  68. defaultProperties.load(new FileReader(popath));
  69. value = defaultProperties.getProperty(a);
  70. } catch (Exception e) {
  71. e.printStackTrace();
  72. }
  73. return value;
  74. }
  75. }

则通过该文件,我们就解析了对象库,并获取到对应的元素位置

4、在util中创建一个类来启动driver

其中包括sharedriver.java、ConfigManager.java、custom.properties等文件
具体参考之前的文档:http://blog.csdn.net/yan1234abcd/article/details/49301577
目录结构如下所示:

5、接下来我们开始编写对这些元素对象的操作feature

在test目录下创建resources目录,并在该目录下创建features目录,目录结构如下所示

然后在该目录下创建一个文件login.feature,像编写测试用例步骤一样编写我们预期的step:

  1. Feature: Login
  2. @login
  3. Scenario Outline: login in csdn
  4. #打开csdn首页
  5. Given I am on csdn
  6. #单击登录按钮
  7. And I press "Userbar_login"
  8. #输入用户名
  9. And I fill in "Input_name" with "<username>"
  10. #输入密码
  11. And I fill in "Input_password" with "<password>"
  12. And I press "Login_button"
  13. #登录成功后,可查到到用户名"echo_茵子",可以修改成自己的CSDN用户名
  14. Then should see text "echo_茵子" in "Tag_body"
  15. Examples:
  16. |username |password |
  17. #这里输入对应的用户名和密码
  18. |***** |***** |

6、然后开始编写feature文件中对应的step的实现

这里我们先实现Given I am on csdn
在test->java->com目录下,创建目录stepDefs,在该目录下创建一个文件IAmOnStepDefs.java
  1. import com.config.ConfigManager;
  2. import com.util.SharedDriver;
  3. import cucumber.api.java.en.Given;
  4. import org.openqa.selenium.JavascriptExecutor;
  5. import org.openqa.selenium.NoSuchElementException;
  6. import org.openqa.selenium.WebDriver;
  7. import org.openqa.selenium.support.ui.ExpectedCondition;
  8. import org.openqa.selenium.support.ui.FluentWait;
  9. import org.openqa.selenium.support.ui.Wait;
  10. import java.util.concurrent.TimeUnit;
  11. public class IAmOnStepDefs {
  12. private final WebDriver driver;
  13. private final ConfigManager config;
  14. private static Wait<WebDriver> wait ;
  15. private static String baseUrl;
  16. public IAmOnStepDefs(SharedDriver driver, ConfigManager config) {
  17. this.driver = driver;
  18. this.config = config;
  19. wait = new FluentWait<WebDriver>(driver)
  20. .withTimeout(30, TimeUnit.SECONDS)
  21. .pollingEvery(500, TimeUnit.MILLISECONDS)
  22. .ignoring(NoSuchElementException.class);
  23. }
  24. /**
  25. *该方法用于实现csdn页面的跳转
  26. */
  27. @Given("^I am on csdn$")
  28. public void i_am_on() throws Throwable {
  29. baseUrl = this.config.get("base_path");
  30. this.driver.navigate().to(baseUrl);
  31. wait.until((new ExpectedCondition<Boolean>() {
  32. @Override
  33. public Boolean apply(WebDriver driverObject) {
  34. System.out.println("*****loading page*****");
  35. return (Boolean) ((JavascriptExecutor) driverObject).executeScript("return document.readyState === 'complete'");
  36. }
  37. }));
  38. }
  39. }

7、运行程序,看下日志

可看到第一个step已经可以正常运行了,后面五个步骤还没定义

8、依次定义其他的步骤

创建IPressStepDefs.java,内容如下所示

  1. import com.util.SharedDriver;
  2. import com.util.WebDriverUtil;
  3. import cucumber.api.java.en.When;
  4. import org.openqa.selenium.WebDriver;
  5. import org.openqa.selenium.WebElement;
  6. import org.openqa.selenium.interactions.Actions;
  7. public class IPressStepDefs {
  8. private final WebDriver driver;
  9. public IPressStepDefs(SharedDriver driver) {
  10. this.driver = driver;
  11. }
  12. /**
  13. * 通过 field 找到某个元素,并进行点击
  14. */
  15. @When("^I press \"([^\"]*)\"$")
  16. public void i_press(String field) throws Throwable {
  17. WebElement element = WebDriverUtil.findFieldWithToBeVisibility(this.driver,field);
  18. new Actions(driver).moveToElement(element).perform();
  19. element.click();
  20. }
  21. }
创建IFillInWithStepDefs.java,内容如下所示
  1. import com.util.SharedDriver;
  2. import com.util.WebDriverUtil;
  3. import cucumber.api.java.en.When;
  4. import org.openqa.selenium.WebDriver;
  5. import org.openqa.selenium.WebElement;
  6. public class IFillInWithStepDefs {
  7. private final WebDriver driver;
  8. public IFillInWithStepDefs(SharedDriver driver) {
  9. this.driver = driver;
  10. }
  11. /**
  12. * 通过 field 找到某个元素,并向该元素输入文字
  13. */
  14. @When("^I fill in \"([^\"]*)\" with \"([^\"]*)\"$")
  15. public void i_fill_in_with(String field, String content) throws Throwable {
  16. WebElement element = WebDriverUtil.findFieldWithToBeVisibility(this.driver,field);
  17. if (null != element) {
  18. element.clear();
  19. element.sendKeys(content);
  20. }
  21. }
  22. }
创建ShouldSeeTextForElement.java,内容如下所示

  1. import com.util.SharedDriver;
  2. import com.util.WebDriverUtil;
  3. import cucumber.api.java.en.Then;
  4. import org.openqa.selenium.*;
  5. import org.openqa.selenium.support.ui.ExpectedConditions;
  6. import org.openqa.selenium.support.ui.FluentWait;
  7. import org.openqa.selenium.support.ui.Wait;
  8. import java.util.concurrent.TimeUnit;
  9. public class ShouldSeeTextForElement {
  10. private final WebDriver driver;
  11. private final Wait<WebDriver> wait;
  12. public ShouldSeeTextForElement(SharedDriver driver) {
  13. this.driver = driver;
  14. wait = new FluentWait<WebDriver>(this.driver)
  15. .withTimeout(30, TimeUnit.SECONDS)
  16. .pollingEvery(500, TimeUnit.MILLISECONDS)
  17. .ignoring(NoSuchElementException.class);
  18. }
  19. /**
  20. * 找到某个元素,并验证该元素存在内容text
  21. */
  22. @Then("^should see text \"([^\"]*)\" in \"([^\"]*)\"$")
  23. public void should_see_text(String text,String field) throws Throwable {
  24. try{
  25. WebElement element = WebDriverUtil.findFieldWithToBeVisibility(driver,field);
  26. ((JavascriptExecutor) driver).executeScript("arguments[0].scrollIntoView();", element);
  27. wait.until(ExpectedConditions.textToBePresentInElement(element,text));
  28. }catch(Exception e){
  29. e.printStackTrace();
  30. }
  31. }
  32. }

则目前整个项目的目录结构如下所示:

9、运行程序,发现程序出错—中文乱码

这里是因为我们在对象库中使用了中文,默认情况下中文会被读成乱码,所以我们需要设置改下之前读取配置文件的代码:

  1. /** 操作对象库,根据传进来的Key,来获取Value
  2. * @param a(对应feature中传进来的元素名称即对应的是属性文件中的Key值)
  3. * @return(返回对应的values)
  4. */
  5. public static String readValue(String a){
  6. Properties defaultProperties = new Properties();
  7. String popath = "dataEngine/ObjectRepository.properties";
  8. String value=null;
  9. try {
  10. InputStream in=new FileInputStream(popath);
  11. InputStreamReader re=new InputStreamReader(in,"GB2312");
  12. BufferedReader bf=new BufferedReader(re);
  13. defaultProperties.load(bf);
  14. value = defaultProperties.getProperty(a);
  15. System.out.println(value);
  16. in.close(); // 关闭流
  17. } catch (Exception e) {
  18. e.printStackTrace();
  19. }
  20. return value;
  21. }
之后使用MAVEN中再次运行程序,查看日志


则上述我们就搭建了一个采用命令行风格来编写测试场景的小框架,欢迎大家批评指正~

源代码在该链接,可免费下载:http://download.csdn.net/detail/yan1234abcd/9630675


声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/706833
推荐阅读
相关标签
  

闽ICP备14008679号