Cucumber java + Webdriver (8) 使用命令行风格来编写测试场景(Scenario)
2016-09-14 16:21
585 查看
团队最近采用了一种与之前的PageFactory思路完全不一样的模式来完成我们的自动化测试编码
在编写step过程中,有很多非常通用的步骤定义,这些步骤定义可编写大量与之类似的场景,而无需创建太多的步骤定义。
即采用一种命令式风格来编写场景步骤,使用fill,press这样的词语,对于这样一种风格有很多争议,但是不管好坏,尝试下总归是有好处的。
这种命令式的风格,是属于用户界面控件的直接操作,所以我们会编写很多通用的step,而使用者只需要传入控件元素属性和其他对于值即可。
意思是:在输入框“Input_name”中输入“test”
其中Input_name是对应元素的别称,我们把所有页面的元素都统一组织在一个文件里面去
下面就开始搭建该框架,以登录csdn为例子
所以,首先操作对象库
之后根据获取到的Value,来获取元素的By值
然后再根据上面获取到的By值来定位到可见元素
则WebDriverUtil.java文件的完整代码:
则通过该文件,我们就解析了对象库,并获取到对应的元素位置
具体参考之前的文档:http://blog.csdn.net/yan1234abcd/article/details/49301577
目录结构如下所示:
然后在该目录下创建一个文件login.feature,像编写测试用例步骤一样编写我们预期的step:
在test->java->com目录下,创建目录stepDefs,在该目录下创建一个文件IAmOnStepDefs.java
可看到第一个step已经可以正常运行了,后面五个步骤还没定义
则目前整个项目的目录结构如下所示:
这里是因为我们在对象库中使用了中文,默认情况下中文会被读成乱码,所以我们需要设置改下之前读取配置文件的代码:
则上述我们就搭建了一个采用命令行风格来编写测试场景的小框架,欢迎大家批评指正~
源代码在该链接,可免费下载:http://download.csdn.net/detail/yan1234abcd/9630675
在编写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各个页面上的元素对象#该文件用于保存元素对象,每个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
3、解析上述元素对象
在项目的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; } }
则通过该文件,我们就解析了对象库,并获取到对应的元素位置
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:
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 | #这里输入对应的用户名和密码 |***** |***** |
6、然后开始编写feature文件中对应的step的实现
这里我们先实现Given I am on csdn在test->java->com目录下,创建目录stepDefs,在该目录下创建一个文件IAmOnStepDefs.java
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'"); } })); } }
7、运行程序,看下日志
可看到第一个step已经可以正常运行了,后面五个步骤还没定义
8、依次定义其他的步骤
创建IPressStepDefs.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; 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(); } } }
则目前整个项目的目录结构如下所示:
9、运行程序,发现程序出错—中文乱码
这里是因为我们在对象库中使用了中文,默认情况下中文会被读成乱码,所以我们需要设置改下之前读取配置文件的代码:
/** 操作对象库,根据传进来的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
相关文章推荐
- selenium使用testNG测试框架编写webdriver脚本_05
- 使用WebDriver + Java + Junit做自动化测试教程
- Cucumber java + Webdriver (7) 结合Page Object,使用LoadableComponent
- Cucumber java + Webdriver (2) 开始编写第一个Test
- 【软件测试】Java中Selenium Webdriver的使用
- Cucumber java + Webdriver (4) 使用自动化测试的Page对象模式
- Cucumber java + Webdriver (5) Tags的使用
- Java Web笔记 – Servlet中的Filter过滤器的介绍和使用 编写过滤器
- Selenium的RC方式编写的测试脚本部分迁移到WebDriver方式混用的简单示例
- 搭建java web开发环境、使用eclipse编写第一个java web程序
- WebDriver基本API使用手册(基于Java和C#)
- 使用 Java 实现 Comet 风格的 Web 应用
- 面向 Java 开发人员的 Ajax: 使用 Jetty 和 Direct Web Remoting 编写可扩展的 Comet 应用程序
- 面向 Java 开发人员的 Ajax: 使用 Jetty 和 Direct Web Remoting 编写可扩展的 Comet 应用程序
- WebDriver基本API使用(基于Java)V1.0
- JAVA使用Microsoft Web Application Stress Tool对web进行压力测试
- selenium-webdriver用例批量运行和测试套件使用 ------之我见
- 【转载】使用 Java 实现 Comet 风格的 Web 应用
- 使用 Java 实现 Comet 风格的 Web 应用
- 使用 Java 实现 Comet 风格的 Web 应用