随着项目后期的业务趋于稳定之后,传统的手工方式进行回归测试消耗太多的人力资源,那就要思考如何利用计算机帮助我们达到自动化测试的目的了;编写此篇文档的主要目的是为了针对项目组的新人员加入,如何让他们能够更快的熟悉什么是自动化测试,怎样来进行实现自动化测试,我这里主要采用标题所提到的框架与技术。
注意:如果你的系统业务还在持续改进还没有稳定下来请不要使用自动化测试,切记!切记!否则所消耗的人力成本会更大,一定要趋于稳定之后使用自动化测试。
防爬虫专用,作者的主要博客地址:点击这里, 全路径:blog.csdn.net/littlebrain4solving。
我们这里主要采用Java作为编写自动化测试代码的语言,利用标准化的maven
环境进行运行测试,具体如何利用maven
创建项目和管理项目相关的知识我这里不赘述,主要环绕TestNG
与Selenium
的使用知识点进行展开。
TestNG
&Selenium
我想刚开始的时候总会有些同学对TestNG
和Selenium
的概念模糊不清,以下我会简单的把两者的大致功能与作用描述一下。
这个玩意主要是一个测试框架工具(与JUnit
相同,当然你也可以选择JUnit亦可),对定义了测试的概念及理论并进行实现提供了许多方便的工具,如Assert
工具之类的;从而如何有效快速化达到我们的目的,针对其核心主要涉及断言
对实际值
与预期值
进行处理,主要围绕结果二个主要状态(Failure、Skipped)进行判断通过率。
注意:
TestNG
与JUnit
我所说的相同只是宏观上的,可能具体还会存在某些理论上的冲突,而在JUnit
中存在结果为Error
的状态,在TestNG
是没有的。
此款框架就比较复杂了,当然归根结底其核心功能主要围绕模拟终端用户的行为进行操作,如:浏览器用户行为、手机端用户行为;其所涉及到的内容较多,对很多语言都有相关的SDK支持;当然在这里我们只用到了Java的SDK包与Chrome驱动的使用方式,更多方式可以参考其开源库:点击这里。
<dependency>
<groupId>org.testnggroupId>
<artifactId>testngartifactId>
<version>6.9.12version>
dependency>
由于我只使用了Chrome
驱动,所以我过滤了其他的驱动包,可以根据需求进行导入就可以了。
<dependency>
<groupId>org.seleniumhq.seleniumgroupId>
<artifactId>selenium-javaartifactId>
<version>3.5.3version>
<exclusions>
<exclusion>
<groupId>org.seleniumhq.seleniumgroupId>
<artifactId>selenium-edge-driverartifactId>
exclusion>
<exclusion>
<groupId>org.seleniumhq.seleniumgroupId>
<artifactId>selenium-ie-driverartifactId>
exclusion>
<exclusion>
<groupId>org.seleniumhq.seleniumgroupId>
<artifactId>selenium-opera-driverartifactId>
exclusion>
<exclusion>
<groupId>org.seleniumhq.seleniumgroupId>
<artifactId>selenium-safari-driverartifactId>
exclusion>
<exclusion>
<groupId>org.seleniumhq.seleniumgroupId>
<artifactId>htmlunit-driverartifactId>
exclusion>
<exclusion>
<groupId>net.sourceforge.htmlunitgroupId>
<artifactId>htmlunitartifactId>
exclusion>
<exclusion>
<groupId>net.sourceforge.htmlunitgroupId>
<artifactId>htmlunit-core-jsartifactId>
exclusion>
<exclusion>
<groupId>net.sourceforge.htmlunitgroupId>
<artifactId>neko-htmlunitartifactId>
exclusion>
<exclusion>
<groupId>org.eclipse.jetty.websocketgroupId>
<artifactId>websocket-apiartifactId>
exclusion>
<exclusion>
<groupId>org.eclipse.jetty.websocketgroupId>
<artifactId>websocket-clientartifactId>
exclusion>
<exclusion>
<groupId>org.eclipse.jetty.websocketgroupId>
<artifactId>websocket-commonartifactId>
exclusion>
<exclusion>
<groupId>org.eclipse.jettygroupId>
<artifactId>jetty-ioartifactId>
exclusion>
<exclusion>
<groupId>org.eclipse.jettygroupId>
<artifactId>jetty-utilartifactId>
exclusion>
exclusions>
dependency>
当我们在maven
的mvn test
命令测试的时候我们主要用到一个运行插件maven-surefire-plugin
,此插件支持与TestNG
的集成,帮助我们做了很多简便的事情,具体可以点击这里查看更多。
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-compiler-pluginartifactId>
<version>2.5.1version>
<configuration>
<source>${java.version}source>
<target>${java.version}target>
<encoding>${project.build.sourceEncoding}encoding>
configuration>
plugin>
<plugin>
<groupId>org.apache.maven.pluginsgroupId>
<artifactId>maven-surefire-pluginartifactId>
<version>2.20version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>src/test/resources/testng.xmlsuiteXmlFile>
suiteXmlFiles>
<systemPropertyVariables>
<driver.path>${driver.path}driver.path>
<driver.mode>${driver.mode}driver.mode>
<driver.address>${driver.address}driver.address>
<driver.arguments>${driver.arguments}driver.arguments>
<buildDirectory>${project.build.directory}buildDirectory>
systemPropertyVariables>
<properties>
<property>
<name>usedefaultlistenersname>
<value>falsevalue>
property>
<property>
<name>reportername>
<value>org.testng.reporters.XMLReportervalue>
property>
<property>
<name>testnamesname>
<value>${testng.testnames}value>
property>
properties>
configuration>
plugin>
plugins>
build>
关于此插件有几处重要的属性需要注意,根据以下的描述进行了解这些属性的作用性:
TestNG
的用例文件,用例文件中描述了TestNG
核心处理的配置;maven
的profile
层面做环境控制处理;TestNG
集成用来控制TestNG
配置的内容,比如最后输出的报告控制或者是指定具体的测试名称。注意: 示例中
${xxx}
主要取值于maven
的最外层即全局的properties
属性值,这样利于我们之后的统一管理。
.build.sourceEncoding>UTF-8 .build.sourceEncoding>
.version>1.8 .version>
.html.enabled>false .html.enabled>
.path>/Users/cary/Desktop/chromedriver .path>
.mode>local .mode>
.address>http://172.16.1.12:4444/wd/hub .address>
.arguments>--window-size=1280,800 .arguments>
.testnames>testname .testnames>
由于我们采用chrome driver
进行测试,所以需要预先把相应的执行文件下载到本地,可以参看selenium
的文档进行下载:点击打开。
注意:
chrome driver
不能单独运行,需要依赖chrome
浏览器,所以浏览器也要安装。
由于我自定义封装了一些全局的属性值,方便我们更好的进行管理,那就会有相应的工具类进行支持处理。
public class DriverHelper {
public static void quit(WebDriver webDriver){
if(webDriver != null) {
webDriver.manage().deleteAllCookies();
webDriver.quit();
}
}
public static WebDriver open() {
WebDriver webDriver = null;
String driverPath = System.getProperty("driver.path");
String driverMode = System.getProperty("driver.mode");
String driverAddress = System.getProperty("driver.address");
String driverArguments = System.getProperty("driver.arguments");
if (StringUtils.equalsIgnoreCase(driverMode, "local")) {
System.setProperty("webdriver.chrome.driver", driverPath);
webDriver = new ChromeDriver(getChromeOptionsByString(driverArguments));
} else if (StringUtils.equalsIgnoreCase(driverMode, "remote")) {
URL url = null;
try {
url = new URL(driverAddress);
} catch (MalformedURLException e) {
e.printStackTrace();
}
webDriver = new RemoteWebDriver(url, getCapabilitiesByString(driverArguments));
} else {
throw new UnsupportedOperationException("Driver mode value is range of [local,remote]");
}
webDriver.manage().timeouts().pageLoadTimeout(120, TimeUnit.SECONDS); // 超时等待时间20s
return webDriver;
}
private static ChromeOptions getChromeOptionsByString(String argumentsString) {
ChromeOptions chromeOptions = new ChromeOptions();
if(StringUtils.isNotEmpty(argumentsString)){
String[] chromeArguments = argumentsString.split(" ");
chromeOptions.addArguments(chromeArguments);
}
return chromeOptions;
}
private static DesiredCapabilities getCapabilitiesByString(String argumentsString) {
DesiredCapabilities capabilities = DesiredCapabilities.chrome();
capabilities.setCapability("chromeOptions", getChromeOptionsByString(argumentsString));
return capabilities;
}
}
这里我们主要编写一个自动查询百度我们想要的关键字,然后通过断言查看第一条结果是否是百度百科并且是否满足我们的预期值。
public class BaiduSearchTest {
private WebDriver webDriver;
@BeforeTest
public void testBefore(){
webDriver = DriverHelper.open();
}
@Test
public void testSearch(){
webDriver.get("http://www.baidu.com");
new WebDriverWait(webDriver,60l)
.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@id=\"kw\"]")))
.sendKeys("陈冠希");
new WebDriverWait(webDriver,60l)
.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//*[@id=\"su\"]")))
.click();
String text = new WebDriverWait(webDriver,60l)
.until(ExpectedConditions.visibilityOfElementLocated(By.xpath("//div[@id='content_left']//div[1]//a")))
.getText();
Assert.assertTrue(text.contains("百度百科"),"不满足预期值");
}
@AfterTest
public void testAfter(){
DriverHelper.quit(webDriver);
}
}
这里的XML路径位置一般位于项目的src/test/resources/testng.xml
下。
<suite name="testsuite" parallel="methods" thread-count="1">
<test name="testname">
<classes>
<class name="com.nakedhub.autotester.nhos.BaiduSearchTest">
<methods>
<include name="testSearch"/>
methods>
class>
classes>
test>
suite>
主要利用MAVEN的命令进行执行,如果用到了profile
的话,可以使用-P
参数进行指定具体的profile
环境控制,如:mvn test -Pcary
。
mvn test