第五章 测试用例规划及TestNG的使用
2015-06-16 16:49阅读:
------Web自动化测试之Webdriver+TestNG--从零到熟练(系列)
经过上一章的学习,我们已经可以将一个手要测试用例转化成代码编写的测试用例,但是一个测试任务通常有很多测试用例。我们就这样一个一个地编写下去吗?答案是否定的。原因是这样编写的测试用例,代码重用率低,数据和测试用例混在一起不便于维护,所以我们得在编写大型的测试用例之前,对我们的测试用例工程进行规划一下。
5.1 测试工程规划
为了方便测试用例的管理,代码重用,以及出错后维护等工作,我们在编写测试用例之前都需要对测试工程的架构进行规划。本人习惯于测试通用函数,测试用例,测试数据分开这样的规划方式,所以我们仍然这样规划我们的测试用例。
(1)创建package:/src/CommonFunction:用来存放所有的公共操作,测试操作步骤,数据操作等。
(2)创建package:/src/TestCases:用来存放具体的测试用例文件,通常一个测试用例文件包含两到三个测试用例,太多的话就不方便调试和出错定位。
(3)创建Package:/src/TestData:存放测试用例用到的测试数据文件xml,通常xml文件和测试用例文件同名,这样方便一一对应。
(4)由于TestNG
pan
>的用例管理是通过
testng.xml文件进行的,所以我们不需要再创建测试用例管理相关的文件夹。
通过上面的规划,我们只要在编写测试用例的过程中,编写好公用函数,然后在测试用例文件中调用公用函数,读取测试用例文件进行具体的测试用例操作即可。如果页面有所变动,我们只需要修改相应的文件即可,不用大面积地去修改。
5.2 TestNG DataProvider讲解
TestNG
DataProvider是TestNG的数据驱动者,我们要实现数据驱动型的自动化测试用例编写,就一定要学会TestNG
DataProvider的使用,网上有很多相关的讲解,如:http://www.cnblogs.com/zhangfei/archive/2012/10/09/2717043.html。
而我们的使用方法是什么呢?
(1)读取TestData文件夹下的测试数据文件,如:HelloWorld.xml.
(2)根据节点来读取数据。
这就要求我们实现下面的功能,读取xml文件,及访问节点数据。
一,创建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对象获得返回documentBuildr对象
db
=
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对象给调用的函数。这也是java操作xml文件的基础,如果不会,请自己学习。@DataProvider(name=””)用来标识不同的DataProvider,以便后续对其进行调用。
二,读取具体的节点值
通过传递过来的Document对象,父节点和节点标签,读取节点对应的值。
#DataReader.java
package CommonFunction;
import org.w3c.dom.*;
public class
DataReader {
public String
readnodevalue(Document doc,String
firsttag,String
secondtag)
{
String
result='';
Element
root=doc.getDocumentElement();
NodeList childnode =
root.getElementsByTagName_r(firsttag);
NodeList
resnode=childnode.item(0).getChildNodes();
for(int
i=0;i<</SPAN>resnode.getLength();i++)
{
if(resnode.item(i).getNodeName().equals(secondtag))
{
result=resnode.item(i).getTextContent();
break;
}
}
return
result;
}
}
通过这两个文件,我们就可以读取xml文件为测试用例文件提供测试数据。
5.3 新架构下测试用例编写
在上我们还以第四章的众筹网登录检测为例,来在新框架进编写对应的测试用例。具体步骤如下:
(1)分析测试用例。我们要实现测试用例和测试数据的分离和代码重用。就要先将上面的两个DataProvider相关的文件存放到package:/src/CommonFunction下。然后再创建一个共用函数类文件CommonFunctions.java文件,存放公用的函数。
(2)编写公用函数。创建java类文件CommonFunctions.java,由于登录退出操作是通用的操作,所以我们会在这个类文件中写两个相应的函数。并且根据我们第四章的了解,在这个测试用例中我们用到了获取元素文本的操作,所以我们也写一个函数来完成这个功能。最终的CommonFunctions.java代码如下:
package CommonFunction;
import
java.util.HashSet;
import java.util.Set;
import
org.openqa.selenium.By;
import
org.openqa.selenium.WebDriver;
import
org.openqa.selenium.firefox.FirefoxDriver;
import
org.openqa.selenium.support.ui.Select;
import
org.openqa.selenium.WebElement;
import static
org.junit.Assert.*;
public class
CommonFunctions {
static
public WebDriver
driver;
public
CommonFunctions()
{
//do nothing
}
public
CommonFunctions(String
url)
{
//
如果你的 FireFox
没有安装在默认目录,那么必须在程序中设置
//System.setProperty('webdriver.firefox.bin',
'E:\\software\\firefox\\firefox.exe');
//
创建一个 FireFox 的浏览器实例
driver = new
FirefoxDriver();
driver.manage().window().maximize();
driver.get(url);
}
public
void geturl(String
url) throws
Exception
{
driver.get(url);
Thread.sleep(5000);
}
public
void teardown()
{
try {
driver.quit();
}
catch (Exception
e) {
e.printStackTrace();
}
}
public String
gettext(String type,String
location)
{
WebElement
elem=null;
if(type.equals('xpath'))
{
elem=driver.findElement(By.xpath(location));
}
if(type.equals('name'))
{
elem=driver.findElement(By.name(location));
}
if(type.equals('id'))
{
elem=driver.findElement(By.id(location));
}
if(type.equals('classname'))
{
elem=driver.findElement(By.className(location));
}
if(type.equals('css'))
{
elem=driver.findElement(By.cssSelector(location));
}
return
elem.getText();
}
public
void clickitem(String
type,String
location)
{
WebElement
elem=null;
if(type.equals('xpath'))
{
elem=driver.findElement(By.xpath(location));
}
if(type.equals('classname'))
{
elem=driver.findElement(By.className(location));
}
if(type.equals('text'))
{
elem=driver.findElement(By.linkText(location));
}
if(type.equals('name'))
{
elem=driver.findElement(By.name(location));
}
elem.click();
}
public
void clearvalue(String
type,String
location)
{
WebElement
elem=null;
if(type.equals('xpath'))
{
elem=driver.findElement(By.xpath(location));
}
if(type.equals('name'))
{
elem=driver.findElement(By.name(location));
}
elem.clear();
}
public
void inputvalue(String
type,String
location,String
text)
{
WebElement
elem=null;
if(type.equals('xpath'))
{
elem=driver.findElement(By.xpath(location));
}
if(type.equals('name'))
{
elem=driver.findElement(By.name(location));
}
if(type.equals('id'))
{
elem=driver.findElement(By.id(location));
}
elem.sendKeys(text);
}
public
void checkequal(String
str1,String
str2)
{
assertEquals(str1,str2);
}
public void
login(String name,String
psd) throws
Exception
{
this.clickitem('classname',
'Js-showLogin');
Thread.sleep(3000);
this.clearvalue('name',
'username');
this.inputvalue('name',
'username',
name);
this.clearvalue('name',
'user_pwd');
this.inputvalue('name',
'user_pwd',
psd);
Thread.sleep(1000);
this.clickitem('classname',
'zc');
Thread.sleep(5000);
}
public
void logout()
throws Exception
{
this.geturl('http://www.zhongchou.cn/usernew-loginout');
}
}
代码讲解:
Ø
首先我们对具体的操作,如click,clear,input等进行了相应的封装,函数中我们已加上了大量的注释,不难理解。
Ø
编写登录函数login(),退出函数logout(),获取元素文本函数gettext()等。
Ø
这些儿函数就像我们小时候玩的积木,下面我们就可以利用这些儿函数来组织我们的测试用例。
(3)准备测试数据。在package:/src/TestData下创建xml文件LoginTest.xml(对应的我们也会创建测试用例文件LoginTest.java),在文件中存放我们需要用到的测试数据。
内容如下:

(4)编写测试用例。下面我们编写对应的测试用例文件,在package:/src/TestCases下创建测试用例文件LoginTest.java,在文件中编写具体的测试步骤。
具体代码如下:
package TestCases;
import org.w3c.dom.*;
import
org.testng.annotations.Test;
import
org.testng.annotations.BeforeTest;
import
org.testng.annotations.AfterTest;
import
CommonFunction.CommonFunctions;
import
CommonFunction.DataProvide;
import
CommonFunction.DataReader;
public class
LoginTest extends
DataProvide{
public
CommonFunctions
comfun;
public
DataReader dr;
@BeforeTest
public
void setup()
throws Exception{
String
url =
'http://www.zhongchou.cn';
comfun=new
CommonFunctions(url);
dr=new
DataReader();
//设置数据源
init('src/TestData/LoginTest.xml');
}
@Test(dataProvider='Test_xml_dataprovider')
public
void
testlogin(Document
params) throws
Exception {
comfun.login(dr.readnodevalue(params,
'login',
'username'),
dr.readnodevalue(params,
'login',
'password'));
comfun.checkequal(comfun.gettext('css',
dr.readnodevalue(params,
'login',
'checkpoint1')),
dr.readnodevalue(params,
'login',
'value1'));
//退出登录
comfun.logout();
}
@AfterTest
public
void teardown() {
comfun.teardown();
}
}
(5)运行测试用例。此时运行一下这个测试用例文件,可以看到和第四章的一样结果。而测试函数中的代码其实就三行,而且在其他的测试用例中也可以去调用登录和退出函数,从而实现了代码重用。如果网站有变化,我们只需要修改一下测试用例数据文件LoginTest.xml,简化了用例维护工作。
(6)测试用例的添加。当我们把测试用例工程规划完成后,以后要做的工作就是在公用类中添加公用函数,添加具体的测试用例文件及对应的测试数据。
5.4
测试用例的转化
到目前为止,我们已经可以在漂亮的架构下编写具体的自动化测试用例了。可是还有一个问题影响着我们自动化测试用例的实施,如何将手工测试用例转化成自动化测试用例?
(1)用例的收集。自动化要测试的必须是成熟的功能,完成日常的回归测试。在一个比较重视质量的公司里,测试用例的收集是必须要做的工作,如果有相应的手工测试用例,转化成自动化测试用例就比较容易。如果没有对应的手工测试用例,我们需要补充手工测试用例,不能在没用用例的情况下,直接编写自动化测试用例,这样容易漏测试。
(2)用例评审。并不是所有的手工测试用例都能转化成自动化测试用例的,而且也没有必要。自动化测试主要的工作就是回归测试,一个回归测试你不可能将方方面面都测试一遍,保证主功能没有问题就可以了。所以在编写自动化测试用例之前,评审一下测试用例,哪些儿需要自动化,哪些儿不需要。
(3)从用例中抽出公用函数。在评审完测试用例后,我们就可以抽出哪些儿操作是所有测试用例都用到的,哪些儿是一部分测试用例中用到的,哪些儿是个别用到的?对这些儿有了一定的概念,就可以编写相应的公用函数。
(4)灵活运用各种检测技巧。计算机不能像人工测试那样灵活,只能通过代码进行对比,所以要灵活设置各种检测点儿,或是灵活执行操作。比如:如果我们要退出网站,人工是点击退出按钮。可是在退出按钮不容易定位的时候,我们可以直接打开退出对应的链接即可。
5.5
本章小结
本章我们讲解了如何规划一个测试用例工程,TestNG
DataProvider数据驱动的使用。通过合理的规划测试代码结构,利用TestNG的数据驱动功能,我们可以实现测试用例和测试数据的分离,实现代码重用,使用测试用例的维护变的更加容易。接着又讲到了如何从手工测试用例转化成自动化测试用例,这是我们编写自动化测试用例的基本功。接下来我们将深入讲解如何使用testng.xml文件组织测试用例,以及测试报告的生成。