Web自动化测试构建学习小结(一)
Web自动化测试的框架:Selenium+JAVA+TestNG
Selenium
1.使用Selenium IDE(firefox的组件,可以在firefox上加载安装)录制初步的脚本,可转换成自己需要的编码。(选择了JAVA):要熟悉Selenium定位页面元素的相关知识
2.使用Selenium 2优化脚本:1>eclipse下加载Selenium 2的jar包
2>实现测试数据、页面元素、测试逻辑三部分的分离(测试数据用excel保存、页面元素用xml保存并分别封装处理类)
测试数据处理类:
public class DataHelper {
//获取xls表格的里面的表
public static Sheet DataOpen(String urlSource) throws BiffException, IOException{
File file=new File(urlSource);
Workbook workbook=Workbook.getWorkbook(file);
Sheet sheet=workbook.getSheet(0);
return sheet;
}
//按行、列获取表格里的数据
public static String getString(int index1,int index2,Sheet sheet) throws BiffException, IOException{
Cell cell=sheet.getCell(index1, index2);
return cell.getContents();
}
}
页面元素处理类:
public class PostElement {
static int row=1;
static int Column=1;
static boolean acceptNextAlert = true;
static Log log=LogFactory.getLog(PostElement.class);
//获取XML文件中需要遍历的节点
public static NodeList doc(String str) throws ParserConfigurationException, SAXException, IOException{
DocumentBuilderFactory factory=DocumentBuilderFactory.newInstance();
DocumentBuilder db=factory.newDocumentBuilder();
InputStream is = new FileInputStream(new File(str));
Document doc=db.parse(is);
Element root=doc.getDocumentElement();//取得根节点
NodeList nodes=root.getElementsByTagName("node");
return nodes;
}
//获取Element的操作并执行
public static void operator(WebDriver driver,WebElement element,Node node,Sheet sheet) throws BiffException, IOException{
if(node.getAttributes().getNamedItem("type").getNodeValue().equals("text"))
{
element.clear();
element.sendKeys(DataHelper.getString(Column, row,sheet));
log.info("第"+row+"行"+"第"+Column+"列"+"数据:"+DataHelper.getString(Column, row,sheet));
//System.out.println("第"+row+"行"+"第"+Column+"列"+"数据:"+DataHelper.getString(Column, row,sheet));
Column++;
if(Column==sheet.getColumns()){
Column=1;
row++;
}
if(row==sheet.getRows()){
row=1;
}
//System.out.println("最后的行"+row);
//System.out.println("最后的列"+Column);
}
if(node.getAttributes().getNamedItem("type").getNodeValue().equals("button")||node.getAttributes().getNamedItem("type").getNodeValue().equals("submit")){
try{
Thread.sleep(1000);//解决click不响应的问题
}catch(InterruptedException e){
e.printStackTrace();
}
element.click();
try{
Thread.sleep(3000);//解决click不响应的问题
}catch(InterruptedException e){
e.printStackTrace();
}
if(isAlertPresent(driver)){
closeAlertAndGetItsText(driver);
}
}
}
//自动捕获弹出框
private static boolean isAlertPresent(WebDriver driver) {
try {
driver.switchTo().alert();
return true;
} catch (NoAlertPresentException e) {
return false;
}
}
private static void closeAlertAndGetItsText(WebDriver driver) {
try {
Alert alert = driver.switchTo().alert();
String alertText = alert.getText();
if (acceptNextAlert) {
alert.accept();
} else {
alert.dismiss();
}
} finally {
acceptNextAlert = true;
}
}
//判断页面元素是否可操作
//按ID遍历节点
public static WebElement getID(WebDriver driver,Node node) throws ParserConfigurationException, SAXException, IOException, BiffException{
WebElement element=null;
if(node.getNodeType()==Node.ELEMENT_NODE){
if(node.getAttributes().getNamedItem("id")!=null){
element=driver.findElement(By.id(node.getAttributes().getNamedItem("id").getNodeValue()));
}
}
return element;
}
//按name遍历节点
public static WebElement getName(WebDriver driver,Node node) throws ParserConfigurationException, SAXException, IOException, BiffException{
WebElement element=null;
if(node.getNodeType()==Node.ELEMENT_NODE){
if(node.getAttributes().getNamedItem("name")!=null){
element=driver.findElement(By.name(node.getAttributes().getNamedItem("name").getNodeValue()));
}
}
return element;
}
//按class遍历节点
public static WebElement getClass(WebDriver driver,Node node) throws ParserConfigurationException, SAXException, IOException, BiffException{
WebElement element=null;
if(node.getNodeType()==Node.ELEMENT_NODE){
if(node.getAttributes().getNamedItem("class")!=null){
element=driver.findElement(By.className(node.getAttributes().getNamedItem("class").getNodeValue()));
}
}
return element;
}
//按css遍历节点
public static WebElement getcssSelector(WebDriver driver,Node node) throws ParserConfigurationException, SAXException, IOException, BiffException{
WebElement element=null;
if(node.getNodeType()==Node.ELEMENT_NODE){
if(node.getAttributes().getNamedItem("css")!=null){
element=driver.findElement(By.cssSelector(node.getAttributes().getNamedItem("css").getNodeValue()));
}
}
return element;
}
//按linkText遍历节点
public static WebElement getlinkText(WebDriver driver,Node node) throws ParserConfigurationException, SAXException, IOException, BiffException{
WebElement element=null;
if(node.getNodeType()==Node.ELEMENT_NODE){
if(node.getAttributes().getNamedItem("linkText")!=null){
element=driver.findElement(By.linkText(node.getAttributes().getNamedItem("linkText").getNodeValue()));
}
}
return element;
}
//按xpath遍历节点
public static WebElement getXpath(WebDriver driver,Node node) throws ParserConfigurationException, SAXException, IOException, BiffException{
WebElement element=null;
if(node.getNodeType()==Node.ELEMENT_NODE){
if(node.getAttributes().getNamedItem("xpath")!=null){
element=driver.findElement(By.xpath(node.getAttributes().getNamedItem("xpath").getNodeValue()));
}
}
return element;
}
public static WebElement getTagName(WebDriver driver,Node node){
WebElement element=null;
if(node.getNodeType()==Node.ELEMENT_NODE){
if(node.getAttributes().getNamedItem("tagName")!=null){
element=driver.findElement(By.tagName(node.getAttributes().getNamedItem("tagName").getNodeValue()));
}
}
return element;
}
}
测试数据与页面元素的同步:
public class PostElementFactory {
//获取XML节点的属性
public static void showElement(WebDriver driver,Node node,Sheet sheet) throws ParserConfigurationException, SAXException, IOException, BiffException{
//每一次访问就遍历了一次节点的该属性
if(node.getNodeType()==Node.ELEMENT_NODE){
WebElement element1=null;//PostElement.getID(driver, node);
WebElement element2=null;//PostElement.getName(driver, node);
WebElement element3=null;//PostElement.getClass(driver, node);
WebElement element4=null;//PostElement.getlinkText(driver, node);
WebElement element5=null;//PostElement.getcssSelector(driver, node);
WebElement element6=null;//PostElement.getXpath(driver, node);
WebElement element7=null;
if((element1=PostElement.getID(driver, node))!=null)
PostElement.operator(driver,element1, node,sheet);
else if(element1==null&&(element2=PostElement.getName(driver, node))!=null)
PostElement.operator(driver,element2, node,sheet);
else if(element1==null&&element2==null&&(element3=PostElement.getClass(driver, node))!=null)
PostElement.operator(driver,element3, node,sheet);
else if(element1==null&&element2==null&&element3==null&&(element4=PostElement.getlinkText(driver, node))!=null)
PostElement.operator(driver,element4, node,sheet);
else if(element1==null&&element2==null&&element3==null&&element4==null&&(element5=PostElement.getcssSelector(driver, node))!=null)
PostElement.operator(driver,element5, node,sheet);
else if(element1==null&&element2==null&&element3==null&&element4==null&&element5==null&&(element6=PostElement.getXpath(driver, node))!=null)
PostElement.operator(driver,element6, node,sheet);
else if(element1==null&&element2==null&&element3==null&&element4==null&&element5==null&&element6==null&&(element7=PostElement.getTagName(driver, node))!=null)
PostElement.operator(driver,element7, node,sheet);
}
}
//对于Data和Element交互的处理
public static void dealDataAndElement(WebDriver driver,String xml,String xls) throws BiffException, IOException, ParserConfigurationException, SAXException{
Sheet sheet=DataHelper.DataOpen(xls);
NodeList nodes=PostElement.doc(xml);
for(int row=1;row<sheet.getRows();row++){
for (int i = 0, j = nodes.getLength(); i < j; i++) {
Node node = nodes.item(i);
PostElementFactory.showElement(driver, node, sheet);
}
}
}
}
3>常用的逻辑类封装
页面元素table处理类的封装:
public class DealTable {
//tablexpath="//table[@class='table table-bordered table-striped table-hover']";
//trxpath="/html/body/form[2]/table/thead/tr"
static Log log = LogFactory.getLog(OSSMedCheck.class);
//表格对象
public static List<WebElement> dealwithTable(WebDriver driver,String tablexpath,String trxpath){
WebElement element=driver.findElement(By.xpath(tablexpath));//先定位到table
List<WebElement> rows = element.findElements(By.xpath(trxpath));//定位到table的每行
return rows;
}
//行对象
public static List<WebElement> dealwithRow_TD(WebElement theRow){
List<WebElement> cells=null;
if(theRow.findElements(By.tagName("td")).size()>0){
cells = theRow.findElements(By.tagName("td"));
}
return cells;
}
public static List<WebElement> dealwithRow_TH(WebElement theRow){
List<WebElement> cells=null;
if(theRow.findElements(By.id("th")).size()>0){
cells = theRow.findElements(By.tagName("th"));
}
return cells;
}
//单元格
public static void dealwithCell(){
}
public static boolean checktablewithTD(WebElement cell,String TDText){
boolean flag=false;
flag=cell.getText().equals(TDText);
return flag;
}
public static boolean checktablewithTH(WebElement cell,String THText){
boolean flag=false;
flag=cell.getText().equals(THText);
return flag;
}
public static boolean OperateAboutTH(WebDriver driver,String xpathtable,String xpathtr,String THText[]){
boolean flag=false;
List<WebElement> rows=dealwithTable(driver,xpathtable,xpathtr);//定位到table
WebElement theRow=rows.get(0);
List<WebElement> cells=dealwithRow_TH(theRow);
for(int cel=0;cel<cells.size();cel++){
flag=cells.get(cel).getText().equals(THText[cel]);
}
return flag;
}
public static boolean OperateAboutTD(WebDriver driver,String xpathtable,String xpathtr,String TDText,int cel){
boolean flag=false;
List<WebElement> rows=dealwithTable(driver,xpathtable,xpathtr);
for(int row=0;row<rows.size();row++){
WebElement theRow=rows.get(row);
if(theRow!=null){
List<WebElement> cells=dealwithRow_TD(theRow);
if(cells.size()>1){
flag=cells.get(cel).getText().equals(TDText);
if(flag==false){
break;
}
}
else {
log.info("按照状态"+TDText+"查询的记录为空");
flag=true;
}
}
}
return flag;
}
}
类似处理稍后再贴吧,有点多了。
TestNG
1.TestNG来有规律地重整测试脚本,需要掌握的基础有:TestNG的标签的使用、testng.xml文件的使用
TestNG推荐文档:http://liulinxia02.blog.163.com/blog/static/268687720098713253574/
testng.xml的使用简单示范:
<?xml version="1.0" encoding="UTF-8"?>
<!-- 测试用例一:按照时间条件查询列表 -->
<suite name="Suite1" parallel="false">
<test name="test1" >
<classes>
<class name="cases.OSSLogin">
<methods>
<include name="setUp"/>
<include name="testOSSLogin"/>
</methods>
</class>
<class name="cases.OSSMedCheck">
<methods>
<include name="testOSSMedCheckOne"/>
<include name="testOSSMedCheckTwo"/>
<include name="testOSSMedCheckThree"/>
<include name="searchByDate"/>
</methods>
</class>
</classes>
</test>
<!-- 测试用例二:按照ID条件查询 -->
<test name="test2">
<classes>
<class name="cases.OSSLogin">
<methods>
<include name="setUp"/>
<include name="testOSSLogin"/>
</methods>
</class>
<class name="cases.OSSMedCheck">
<methods>
<include name="testOSSMedCheckOne"/>
<include name="testOSSMedCheckTwo"/>
<include name="testOSSMedCheckThree"/>
<include name="searchByID"/>
</methods>
</class>
</classes>
</test>
<!-- 测试用例三:按照状态条件查询 -->
<test name="test3">
<classes>
<class name="cases.OSSLogin">
<methods>
<include name="setUp"/>
<include name="testOSSLogin"/>
</methods>
</class>
<class name="cases.OSSMedCheck">
<methods>
<include name="testOSSMedCheckOne"/>
<include name="testOSSMedCheckTwo"/>
<include name="testOSSMedCheckThree"/>
<include name="searchByStatus"/>
</methods>
</class>
</classes>
</test>
<!-- 测试用例四:导出提现审批列表 -->
<test name="test4">
<classes>
<class name="cases.OSSLogin">
<methods>
<include name="setUp"/>
<include name="testOSSLogin"/>
</methods>
</class>
<class name="cases.OSSMedCheck">
<methods>
<include name="testOSSMedCheckOne"/>
<include name="testOSSMedCheckTwo"/>
<include name="testOSSMedCheckThree"/>
<include name="downloadFolder"/>
</methods>
</class>
</classes>
</test>
</suite> <!-- Suite -->
对于测试脚本的执行应该注意的是:
1.为增强代码的可重用性,脚本编码尽量模块化,这样在testng.xml中可自由组合成不同的测试用例
2.对于测试用例的起始,要注意driver对象的初始化,定义在BeforeTest标签处初始化会比较好,这样driver的开始和结束就是一个测试用例的开始和结束,比较有清晰