最近学习了一下 TestNG+Webdriver 的页面自动化,虽然中 间遇到了很多问题,也走了不少弯路,不过最终还是运行起来了。下 面就详细讲解一下,如何去配置环境及编写测试用例!
环境配置
1,eclipse+jkd 的安装 这是基本的开发环境,具体的配置在此就不累述了,网上有很多
相关文档,请自行查阅。
2,TestNG 的安装
去官网 download 一个 TestNG 插件,这个工作在 eclipse 内完成, |
点击 help->install new software,紧接着填上 http://beust.com/eclips e |
然后一路 next 到 finish。好了 TestNG 插件装上了,为了 check 一下是否正常工作,新建一个空的工程,然后再新建一个一个 Test |
NG 类试一下,如果能够正常建立,那么就成功了,步骤:file->new |
->Other,会看到。到目前为止,测试环境搭建完毕。 |
准备测试需要的包 TestNG+Webdriver 框架需要一些儿相应的 jar 包支持,具体如下: (1)httpclient-4.3.6.jar |
(2)httpcore-4.3.3.jar (3)selenium-java-2.43.0.jar (4)selenium-server-standalone-2.42.2.jar |
(5)testng.jar |
请将以上包下载下来备用,注意版本号可以不与我的相同,尽量 下载最新的包,否则会与浏览器版本相冲突的。
创建测试用例
1,新建一个 java project,取一个合适的名字,如 Test。并近上面 下载的包,附加到工程中。
2,规划代码结构:
编写测试用例之前,我们一定有要一个好的代码结构规划,这样 一是方便维护,二是增加可读性。当然,我们现在的规划如下:
(1)创建 package src/CommonFunction:用于存放所有的共用函数
类,方便所有的测试用例来调用及专人维护。
(2)创建 package src/TestCases:用于存放具体的测试用例,这里
的测试用例是具体的操作与判断语句。
(3)创建 package src/TestData:用来存放测试用例对应的测试数
据,为 xml 格式。
(4)Testing.xml:TestNG 用来组织测试用例,以及设置是否进行多
线程操作等。
3,创建 TestNg 测试用例
新建 TestNG Classic,在弹出的对话框中选择 BeforeTest 和 AfterTest,并在 XML suite file 后输入 testng.xml,单击 Finish 按
钮,则会创建相应该的 HelloWorld.java 测试用例文件及 testng.xml。
4,添加我们的测试代码
具体的测试代码如下:
//HelloWorld.javapackage TestCases;
import org.testng.annotations.Test;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.AfterTest;
public class HelloWorld {@Testpublic void f() {System.out.println("Hello World!");}@BeforeTestpublic void beforeTest() {System.out.println("beforeTest running!");}@AfterTestpublic void afterTest() {System.out.println("afterTest running!");}
}
详解讲解:
在主测试函数 f()中,输出我们经典的字符串“Hello World!”; 在 beforeTest()函数中输出“beforeTest running!”,在 afterTest() 函数中输出“afterTest running!”。我们这样做的目的很简单,就 是检测一下程序输出是不是我们预期的。
5,运行程序
右击 HelloWorld.java 文件,然后选择 run asTestNG Test,然 后查看输出情况:
输出顺序和我们预期的一样,所以,在具体的测试用例编写过程 中,我们通常把变量定义或是测试用例的前置操作放到 beforeTest() 函数中,而对测试使用产生的数据清除或是关闭浏览器,放到 afterTest()函数中。
到目前为止,一个简单的 Testng 测试用例已经写完了,可是我们 好像还没有用到 Webdriver 呢?其实很简单,WebDriver 的应用和其 他的类似,如:
//HelloWorld.javapackage TestCases;import org.testng.annotations.Test;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.AfterTest; //添加对webdriver的引用
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;public class HelloWorld { @Testpublic void f() throws Exception{ //System.out.println("Hello World!"); //创建浏览器,并打开百度
WebDriver driver = new FirefoxDriver(); driver.get("http://www.baidu.com"); //Do anything with baidu what you want! Thread.sleep(5000);driver.quit();}@BeforeTestpublic void beforeTest() { System.out.println("beforeTest running!");}@AfterTestpublic void afterTest() { System.out.println("afterTest running!");} }
再次运行 HelloWorld.java,就可以打开火狐浏览器,并打开百度 网页,等上 5 秒钟后关闭浏览器。其实在打开网页后,你可以利用 Webdriver 做任何与具体测试用例相关的操作。
TestNG 进阶篇
在前面我们利用 TestNG+Webdriver 能操作浏览器,打开测试网站 了,可是我们还没有实现测试用例和测试数据的分离,所以你需要继 续学习进阶篇。
DataProvider 的使用
DataProvider 是 TestNG 数据提供者,利用这个机制,我们可以 实现测试用例与测试数据的分离,网上有很多相关的讲解,如: http://www.cnblogs.com/zhangfei/archive/2012/10/09/2717043. html。
而我们的使用方法是什么呢?
(1)读取 TestData 文件夹下的测试数据文件,如:HelloWorld.xml. (2)根据节点来读取数据。
这就要求我们实现下面的功能,读取 xml 文件,及访问节点数据。
代码详解
(1)创建 DataProvide.java 文件来提供 DataProvider。
//DataProvide.java
package CommonFunction;
import java.io.File;
import java.lang.reflect.Method;
import org.testng.annotations.DataProvider; import org.w3c.dom.*;import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory;public class DataProvide {public Document doc;
public void init(String filename) throws Exception {对象File inputXml = new File(new File(filename).getAbsolutePath()); // documentBuilder为抽象不能直接实例化(将XML文件转换为DOM文件) DocumentBuilder db = null;
DocumentBuilderFactory dbf = null;try {
// 返回documentBuilderFactory对象
dbf = DocumentBuilderFactory.newInstance();
// 返回db对象用documentBuilderFatory对象获得返回documentBuildrdb = dbf.newDocumentBuilder();
// 得到一个DOM并返回给document对象 doc = (Document)db.parse(inputXml);}
catch (Exception e) {e.printStackTrace(); }}@DataProvider(name="Test_xml_dataprovider") public Object[][] providerMethod(Method method){return new Object[][]{new Object[]{doc}}; }}
读取传递过来的 Xml 文件,并传递 Document 对象给调用的函数。
(2)创建 DataReader.java 文件来读取 Xml 的内容。
#DataReader.java
package CommonFunction;import org.w3c.dom.*; public class DataReader {/**
* 从Xml中获取相应的节点的数据
* @param doc 数据文件的Document
* @param firsttag 子节点
* @param secondtag 要获取的元素的节点 * @return 要查找的节点数据
*/public String readnodevalue(Document doc,String firsttag,String secondtag){
String result="";
Element root=doc.getDocumentElement();
NodeList childnode = root.getElementsByTagName(firsttag); NodeList resnode=childnode.item(0).getChildNodes(); for(int i=0;i<resnode.getLength();i++)
{if(resnode.item(i).getNodeName().equals(secondtag)) {result=resnode.item(i).getTextContent();break; }}return result; }}
(3)HelloWorld.xml 的内容
<?xml version="1.0" encoding="UTF-8"?> <testdata><hello name="测试数据"> <name>Webdriver</name></hello> </testdata>
(4)HelloWorld.java 最终版本
package TestCases;import org.testng.annotations.Test;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.AfterTest;
import org.w3c.dom.Document;
import org.openqa.selenium.By; //添加对webdriver的引用
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.firefox.FirefoxDriver; import static org.junit.Assert.*;//添加对DataProvider的引用
import CommonFunction.DataProvide; import CommonFunction.DataReader;public class HelloWorld extends DataProvide { public DataReader dr;//定义DataReader@Test(dataProvider="Test_xml_dataprovider")//添加dataprovider public void f(Document params) throws Exception{//System.out.println("Hello World!");
//创建浏览器,并打开百度
WebDriver driver = new FirefoxDriver(); driver.get("http://www.baidu.com"); //查询从HellWorld.xml中读取的数据
WebElement input=driver.findElement(By.id("kw"));
input.click();
input.sendKeys(dr.readnodevalue(params, "hello", "name"));//读取Xml中的数据并输入到搜索框Thread.sleep(2000);
WebElement submit=driver.findElement(By.id("kw")); submit.click();
Thread.sleep(5000);
//检测查询结果
WebElementresult=driver.findElement(By.xpath("//div[@id='content_left']/div/h3/a" ));String text=result.getText();System.out.println(text);assertNotEquals(0,text.indexOf(dr.readnodevalue(params, "hello", "name")));driver.quit(); }@BeforeTestpublic void beforeTest() throws Exception { //System.out.println("beforeTest running!"); dr=new DataReader();//实例化DataReader init("src/TestData/HelloWorld.xml");//设置数据源}@AfterTestpublic void afterTest() { System.out.println("afterTest running!");} }
经过上面代码的编写,现在再运行一下 HelloWorld.java 程序,我们就 可以看到有如下操作:
A,打开火狐浏览器,同时打开 www.baidu.com.
B,输入 webdriver,然后搜索。
C,判读搜索结果中有没有 webdriver。
D,五秒之后关闭浏览器
testng.xml 文件的配置
Testing.xml 是 TestNG 的配置文件,拥有强大的功能,可以根据需
要来配置测试用例的运行。具体参数有:
name | suite 的名字(他会出现在测试报告中) |
junit | 是否以 junit 模式运行 |
verbose | 在控制台中如何输出,这个设置不影响 html 版本的测试报告 |
parallel | 是否使用多线程测试(可能加速测试) |
configfailurepolicy | 是否在运行失败了一次后继续尝试或跳过 |
thread-count | 如果设置了 parallel,可以设置线程数 |
annotations | 有‘javadoc’的时候寻找,没有的话使用 jdk5 的注释 |
time-out | 在终止method(如果parallel="methods") 或者 test (如果 parallel="tests")之前设置以毫秒为单位的等待 时间 |
skipfailedinvocationcounts | 是否跳过失败的调用 |
data-provider-thread-count | 提供一个整数线程池的范围为了使用 parallel data |
object-factory | 一个继承 IObjectFactory 的类,被用来实例化测试对象 |
allow-return-values | 如果设置 true,将会运行测试用例并返回值 |
详细讲解,请参考:
http://www.cnblogs.com/choosewang /articles/3079983.html,而各个参 数的具体取值及结构,可以参考:http://testng.org /testng-1.0.dtd.php。 而这里我们只讲最常用的几个参数。
(1)Testng 默认内容讲解
当我们创建一个 TestNG 类后,会默认创建一个 testng.xml 文件, 文件的内容如下:
<?xml version="1.0" encoding="UTF-8"?> <suite name="Suite" parallel="false"><test name="Test"> <classes><class name="TestCases.HelloWorld"/> < / class es></test> <!-- Test --> </suite> <!-- Suite -->
-
Suite name 标识测试集的名字,这个名字会在测试报告中显示。
-
Suite parallel 是否并行运行测试用例,这个在多线程中会用到,
false 为不允许多线程。
-
Test name 测试工程的名字,一个测试工程可以包含多个测试类,
一个测试类中可以包含多个测试方法。
通常我们添加测试方法的办法是添加classes节点,当然也可以
添加更多的测试工程和测试集。
例如:
„„<test name="Test"> <classes><class name="TestCases.A/> <class name="TestCases.B"/> <class name="TestCases.C "/>< / classe s> „„</test >
(2)Testng 常用参数讲解
上面默认的参数已经讲解过了,此处不在累述了,下面几个参数也是 比较常用的:
-
Configfailurepolicy 设置如何处理失败的测试用例,取值为
skip | continue,skip 为失败后跳过这个测试用例;continue 为 失败后重跑这个测试用例。由于一些儿测试用例会遇到偶然的现 象导致失败,所以我们通常会设置成失败重跑。
-
thread-count 线程数,当我们设置了并行运行后,这里设置并行 的数量。并行的单位可以是测试用例,测试类或是测试实例等。
-
skipfailedinvocationcounts 是否跳过失败的调用,如果不跳过, 可能会导致测试用例的死锁。
-
preserve-order true|false 测试用例是否顺序执行,如果设置 成 False,则测试用例随机执行。
-
常用的结点
<class name="class1"><methods>
<!-- 此处用方法名来区别 --><include name="method_name" /><exclude name="method_name" /></methods>
</class>
Methods 节点定义在一下测试用例中测试方法有哪儿些执行include,
哪儿些不执行 exclude。虽然我们建议在一个测试用例中要尽量包含 少的测试方法,但是有些儿测试用例中也会包含很多相关的测试方法, 有些儿测试场景不适合执行一些儿方法,所以就可以用此节点来进行 定制。
(3)一个常用的 Testng.xml 实例
Testng.xml 的结点太多了,有很多我们用不到,请看一个比较完成
整的讲解:
http://blog.csdn.net/five3/article/details/25907693
而我们现在要讲解的是一个比较简单,但是很实用的实例,具体内容
如下:
//testng.xml<?xml version="1.0" encoding="UTF-8"?>
<suite name="TestDemo" parallel="tests" Configfailurepolicy="continue"thread-count="3" skipfailedinvocationcounts="true" <test name="Test"><classes>
<class name="TestCases.HelloWorld"/> <class name="TestCases.HelloTom"/><methods>
<include name="saygoodbye" /> <exclude name="havelunch" /></methods>
<class name="TestCases.HelloJim"/> <class name="TestCases.HelloCate"/>< / class es>preserve-order=”true” ></test> <!-- Test --> </suite> <!-- Suite -->
文件讲解:
-
Suite相关:此suite名字为TestDemo,包含了一个测试工程Test,
四个测试文件。
-
Suite 设置:测试用例以 test 为单位并行执行,一次并行 3 个测
试用例,测试用例执行的顺序是顺序执行,遇到失败的测试用例
进行重跑,遇到失败的调用则跳过。
-
在 HelloTom 测试用例中包含了两个测试函数,但是在此测试集中,
只执行 saygoodbye,havelunch 不执行。 这些儿设置虽然很少,不过可以应付日常的测试需要了,如果有特殊 化的需要,可以去网上查询,相关的文章相当多的。
TestNG 报告输出
我们现在使用 testng 跑完测试后,会在测试代码的根目录下生成 一个文件夹 test-output,里面有 testng 生成的测试报告,是对测 试运行结果的展示。如下图:
在 testng 生成的文件中有一个 testng-results.xml,这里面有我 们的测试结果信息。不过这个报告比较丑,我们需要对其进行改造 |
一下。 |
使用 TestNG-xslt 这个插件可以生成较理想的报告。
下载TestNG-xslt并把其中的saxon-8.7.jar复制到测试项目lib
下,并附加到工程中
从你下载的包中拷贝文件 testng-results.xsl 到 test-output 目
录下。testng-results.xsl 文件的位置是 testng-xslt-1.1.1/src/main/resources,为什么要这个文件呢?因为 我们的测试报告就是用这个 style 生成的。
新建 build.xml 文件,内容如下:
<project name= "Test" basedir= "." > <property name= "lib.dir" value= "lib" /> <path id= "test.classpath" ><!-- adding the saxon jar to your classpath --><fileset dir= "${lib.dir}" includes= "*.jar" /> < / path><target name= "transform" > <xsl t"E:/ZhongChouJava/WrokSpace/Test/test-output/testng-results.xml" "E:/ZhongChouJava/WrokSpace/Test/test-output/testng-results.xsl" "E:/ZhongChouJava/WrokSpace/Test/test-output/index1.html " >in=style=out=
ex pression=<!-- you need to specify the directory here again --><p aram name= "testNg Xslt.outputDir" "E:/ZhongChouJava/WrokSpace/Test/test-output/" /> <classpath refid= "test.classpath" /></xslt> </target></project>
用 ant 运行这个 xml 就会在 test-output 目录下生成 index1.html, 如下图:
打开它就能看到新生成的测试报告, 通过生成的报告我们能看到 总体的情况,比如通过了多少 case,失败了多少,跳过了多少没执行。 第二个好处是我们可以查看失败的 case 抛出的异常,有具 体的函数 和行号。我们还可以通过 case 执行后的状态来过滤查询等等。 我们测试用例的代码,运行结果如下图:
我们讲到此处,算是对 TestNG+Webdriver 进行页面自动化测试
达到了最终的结果,有完美的代码架构,数据和程序分享,还有漂亮 的结果报告。最后需要的就是你的具体测试用例的编写了,这里面有 很多技巧,需要大家日积月累,才能达到炉火纯青的地步,最后祝大 家学习愉快,希望我的这篇文档能帮助你窥探自动化测试的皮毛!