Selenium Web 自动化 - 项目实战(三)
Selenium Web 自动化 - 项目实战(三)
2016-08-10
1 关键字驱动概述
2 框架更改总览
3 框架更改详解
3.1 解析新增页面目录
3.2 解析新增测试用例目录
3.3 解析自动生成代码
3.4 读取用例excel数据,定位元素,并进行操作
3.5 更改SeleniumUtil.java
1 关键字驱动概述
关键字驱动测试(Keyword-driven testing),也叫做表格驱动测试或者基于行为词的测试。
关键字驱动到底是什么样的?
见图3,动作也就是关键字,比如你选择了“点击”操作,就意味着这步骤会执行一个元素点击操作。
关键子驱动是如何实现的:
问:那么如何定义动作?
答:在框架设计的时候会专门设计一个类,来实现各种“动作”的具体内容。当你在excel中读取了一个“动作”之后,框架会自动解析这个“动作”背后的事情。在测试框架中这个类的名字叫做:SuperAction.java。
问:如何定义和解析元素定位?
答:见图2,每个页面是一个excel,所有元素的定位方式和定位值都保存在里面
问:如何用例存储?
答:见图3,一个excel就是一个模块,然后这个excel文件中一个sheet就是这个模块中的一条用例
问:Excel文件如何执行测试?
答:excel文件存储用例,但excel只是文件,如何调用测试入口呢?其实在关键字驱动框架中,有一个用例生成类(TestCaseFactoryForSingle.java,TestCaseFactoryForAll.java),它可以遍历所有excel的所有sheet,生产一条条用例类,见图6
关键字优缺点:
- 优点:只需要自动化测试人员封装好相关关键字操作,就可以提供给黑盒测试人员用,黑盒测试人员只需要掌握元素定位的方式以及对关键字框架的使用即可·条理清晰,很容易上手使用
- 缺点:需要自动化测试人员花费大量时间提前把关键字框架中的操作提前封装好对于复杂的测试需求,关键字框架对于操作的封装难度较大
2 框架更改总览
图1 关键子驱动与数据驱动比较
3 框架更改详解
在原来的框架下更改,如下图所示
3.1 解析新增页面目录
page: 存储页面元素的目录,在此目录下每个页面是一个excel,会替换原先框架的com.demo.test.pages包,如图1所示。
图2 page 元素定位excel
3.2 解析新增测试用例目录
testcase:存储测试用例的目录,每个模块一个excel文件,每个excel文件中的sheet是一条测试用例,会替换原先框架的com.demo.test.pageshelper包和data目录,如图4所示。
图3 用例Login的Actions
测试用例excel是用于存储测试用例步骤(如图4所示)、步骤中涉及的动作(如图3所示)和测试数据(如图4所示)等内容,命名规则如下:
- excel文件命名规则为:“模块名称.xlsx”;
- excel中第二个sheet命名规则:“001_LoginSuccessFunction”来自原框架测试代码中的部分内容(如图4所示),也就是省略了“页面名称_”:HomePage_和尾部的“_Test”部分:_Test,这两部分省略的部分在生成代码的时候会自动添加。
注意:测试用例excel文件sheet“001_LoginSuccessFunction”中的“动作”列(如图4所示),这列是通过sheet“Actions”中的“动作名称”列来赋值的:
- 选择“动作”列,如下图所示,整列已经变灰色,表明整列已经被选中。
- 点击excel顶部的“数据”tab -> 数据验证:在数据验证-设置中选择验证条件为:序列并勾选“忽略空值”和“提供下拉箭头”,点击来源最右边的带箭头的按钮,点击sheet 'Actions',选择A2到A26(鼠标左键先点击A2不放,然后拖拽至A26),此时注意数据验证框的变化:=Actions!$A$2:$A$26,点击回车键。
图5 用例excel替换pagehelper类和data excel
3.3 解析自动生成代码
自动生成代码TestCaseFactoryForSingle.java代码如下
package com.demo.test.utils; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileWriter; import java.io.IOException; import java.util.Scanner; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.testng.Assert; import jxl.read.biff.BiffException; /** * * @author xy-incito-wy * @Description 自动生成测试代码的工具类,生成指定模块的用例 * */ public class TestCaseFactoryForSingle { public static void main(String[] args) { //测试代码包路径,如果你的测试代码目录不一样请在这里修改 final String caseFolder = "src/com/demo/test/testcases/"; //源文件 File sourceFile = null; //sheet的名字 String sheetName = null; //功能模块名字 String functionName = null; //sheet的号码 int sheetNum = 0; try { @SuppressWarnings("resource") //从控制台可以输入 Scanner s = new Scanner(System.in); System.out.println("请输入模块名称(不要按回车键,输入完成之后请再按回车键):"); functionName = s.nextLine();// 输入模块名字 functionName = functionName.replaceFirst( functionName.substring(0, 1), functionName.substring(0, 1).toLowerCase()); // 如果包名不存在,就新建 File functionPackage = new File(caseFolder + "/" + functionName); if (functionPackage.exists()) { System.out.println(functionName + "包已经存在,自动跳过!"); System.out.println("正在生成用例到" + functionName + "包下,请稍等..."); } else { functionPackage.mkdir(); System.out.println(functionName + "包已创建!"); System.out.println("正在生成用例到" + functionName + "包下,请稍等..."); } for (int j = 0; j < getSheetNum(getExcelRelativePath(functionName)); j++) { // 根据传入的模块文件路径获得模块中sheet数量 也就是用例个数 if (j == getSheetNum(getExcelRelativePath(functionName)) - 1) { //如果只有一个sheet的时候(只有Value的情况下),跳出循环不进行自动生成代码操作,因为没有可以生成的。 break; } try { sheetName = getSheetName(j + 1, getExcelRelativePath(functionName)); // 取得sheetName,由于第一个sheet是values,所以从j+1开始 sheetNum = getSheetNum(getExcelRelativePath(functionName)); } catch (BiffException e1) { e1.printStackTrace(); } sourceFile = new File(caseFolder + functionName.toLowerCase() + File.separator + functionName.replaceFirst(functionName.substring( 0, 1), functionName.substring(0, 1) .toUpperCase()) + "Page_" + sheetName + "_Test.java");// 创建测试用例源码,指定存放路径 FileWriter writer = new FileWriter(sourceFile); // 生成测试用例代码的头文件 writer.write("package com.demo.test.testcases." + functionName + "; \n" + "import org.testng.annotations.Test; \n" + "import com.demo.test.base.BaseParpare; \n " + "import com.demo.test.utils.SuperAction; \n" + "public class " + functionName.replaceFirst(functionName.substring( 0, 1), functionName.substring(0, 1) .toUpperCase()) + "Page_" + sheetName + "_Test extends BaseParpare{ \n"); // @Test的主体部分,也就是测试用例的方法 String firstLetter = sheetName.substring( sheetName.indexOf("_") + 1).substring(0, 1); String others = sheetName.substring( sheetName.indexOf("_") + 1).substring(1); String function = firstLetter.toLowerCase() + others; writer.write("@Test \n" + " public void" + " " + function + "() { \n" + "SuperAction.parseExcel(\"" + functionName.replaceFirst(functionName.substring( 0, 1), functionName.substring(0, 1) .toUpperCase()) + "\",\"" + sheetName + "\",seleniumUtil);\n" + " }\n"); // 代码结尾大括号 writer.write("}"); writer.close(); } } catch (IOException e) { Assert.fail("IO异常", e); } System.out.println("模块[" + functionName + "] 的用例已经生成完毕,共计:" + (sheetNum - 1) + "条,请到" + caseFolder + functionName.toLowerCase() + "路径下查阅!"); } /** * 获得excel的相对路径 * * @param 循环模块名称的角标 * @return 得到对应index的模块名字 */ public static String getExcelRelativePath(String functionName) { String dir = "res/testcase"; String path = ""; // get file list where the path has File file = new File(dir+File.separator+functionName+".xlsx"); // get the folder list path = file.getPath(); return path; } /** * 获得当前excel的sheet数量 - 每个模块的用例数 * * @param filePath * 文件路径 * @return 获得excel的sheet数量 * @throws FileNotFoundException * @throws IOException */ public static int getSheetNum(String filePath) throws FileNotFoundException, IOException { int casesNum = 0; XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream(new File( filePath))); casesNum = workbook.getNumberOfSheets(); return casesNum; } /** * * @param sheetIndex * sheet的位置 * @param filePath * excel文件路径相对的 * @return 返回sheet的名字 * @throws BiffException * @throws IOException */ public static String getSheetName(int sheetIndex, String filePath) throws BiffException, IOException { String casesName = ""; XSSFWorkbook workbook = new XSSFWorkbook(new FileInputStream(filePath)); casesName = workbook.getSheetName(sheetIndex); return casesName; } }
TestCaseFactoryForSingle.java这个类,这个类主要是用于生成指定模块的测试用例,这个类有一个main方法,当你执行之后,会提示你输入要生成测试代码的模块。这里的模块的名字就是testcase目录下的excel文件名字(不包含后缀),然后回车,
此时回到src/com/demo/test/testcases/login包下查看,一条用例生成了 LoginPage_001_LoginSuccessFunction_Test.java,如图5所示.
在pom.xml中,添加jar依赖
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>3.10-FINAL</version> </dependency>
图6 自动生成代码
3.4 读取用例excel数据,定位元素,并进行操作
SuperAction.java代码如下:
package com.demo.test.utils; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Iterator; import org.apache.log4j.Logger; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.openqa.selenium.Alert; import org.openqa.selenium.By; import org.testng.Assert; /** * * @Description 把Selenium操作的变成关键字操作 * */ public class SuperAction { public static Logger logger = Logger.getLogger(SuperAction.class.getName()); //static String pageFilePath = "res/page/PageElements.xlsx"; static String pageFileDir = "res/page/"; public static Alert a = null; /** * * @param locateWay 定位方式 * @param locateValue 定位的方式的具体值 * @return 定位的方式(By) */ public static By getLocateWay(String locateWay,String locateValue){ By elementLocator=null; if(locateWay.equalsIgnoreCase("xpath")){ elementLocator=By.xpath(locateValue); } else if(locateWay.equalsIgnoreCase("className")){ elementLocator=By.className(locateValue); } else if(locateWay.equalsIgnoreCase("id")){ elementLocator=By.id(locateValue); } else if(locateWay.equalsIgnoreCase("linktext")){ elementLocator=By.linkText(locateValue); } else if(locateWay.equalsIgnoreCase("name")){ elementLocator=By.name(locateValue); } else if(locateWay.equalsIgnoreCase("css")){ elementLocator=By.cssSelector(locateValue); } else if(locateWay.equalsIgnoreCase("tagname")){ elementLocator=By.tagName(locateValue); } else{ Assert.fail("你选择的定位方式:["+locateWay+"] 不被支持!"); } return elementLocator; } /** * * @param sheet - 测试用例表中的sheet * @param rowIndex - 测试用例表中的行index * @param locateColumnIndex - 测试用例表中的定位列的index * @return 从page表中 返回定位方式和定位值 * @Description 根据testcase中的元素定位列,去取得page页中的 定位方式和定位值 */ public static String[] getPageElementLocator(Sheet sheet,int rowIndex,int locateColumnIndex,String pageName){ XSSFWorkbook pageBook = null; //定位方式 String elementLocatorWay = null; //定位值 String elementLocatorValue = null; //sheet表 Sheet pageSheet = null; //page excel路径 String pageFilePath = pageFileDir+pageName+".xlsx"; //获取定位列的值 String locator = sheet.getRow(rowIndex).getCell(locateColumnIndex).getStringCellValue(); //用.分割开元素定位值 String locatorSplit[] = locator.split("\\."); try { pageBook = new XSSFWorkbook(new FileInputStream(new File(pageFilePath))); } catch (FileNotFoundException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } pageSheet = pageBook.getSheetAt(0); //取得第一个sheet int pageRowNum = pageSheet.getPhysicalNumberOfRows();//获得这个sheet的实际有效行数 for (int j = 0; j < pageRowNum; j++) { //如果获取到的别名和指定的别名相同,就存储当前行的定位值和定位方式 if(pageSheet.getRow(j).getCell(0).getStringCellValue().equalsIgnoreCase(locatorSplit[1])){ elementLocatorWay = pageSheet.getRow(j).getCell(1).getStringCellValue(); elementLocatorValue = pageSheet.getRow(j).getCell(2).getStringCellValue(); break; } } return new String[]{elementLocatorWay,elementLocatorValue}; } /** * @param founction * excel文件的名字 * @param caseName * excel中sheet的名字 * @param seleniumUtil * 引用seleniumUtil * @Description 读取excel中每个sheet的操作步骤,进而生成测试用例 * */ public static void parseExcel(String founction, String caseName, SeleniumUtil seleniumUtil) { FileInputStream filePath = null; XSSFWorkbook workbook = null; String locateSplit[] = null;//页面sheet中的定位方式和定位值拆解 String locator = null;//用例页面的定位列 String file = "res/testcase/" + founction + ".xlsx"; try { filePath = new FileInputStream(file);// 读取功能模块 } catch (FileNotFoundException e) { logger.error("文件:" + file + "不存在"); Assert.fail("文件:" + file + "不存在"); } try { workbook = new XSSFWorkbook(filePath); } catch (IOException e) { logger.error("IO异常"); Assert.fail("IO异常"); } /**取得指定的case名字*/ Sheet sheet = workbook.getSheet(caseName); /**获得的实际行数*/ int rows = sheet.getPhysicalNumberOfRows(); /** excel中的测试数据*/ String testData = null; //获取首行的单元格数 int cellsNumInOneRow = sheet.getRow(0).getPhysicalNumberOfCells(); //声明一个数组存储列值的角标 String column[] = new String[cellsNumInOneRow]; //声明一个迭代器 Iterator<Cell> cell = sheet.getRow(0).iterator(); int ii =0; while(cell.hasNext()){ column[ii]= String.valueOf(cell.next()); ii++; } //定义动作列的角标 int actionColumnIndex =0; //定义元素定位列的角标 int locateColumnIndex = 0; //定义测试数据列的角标 int testDataColumnIndex = 0; //动态获取这几个关键列所在位置 for (int i = 0; i < column.length; i++) { if(column[i].equals("动作")){ actionColumnIndex = i; } if(column[i].equals("元素定位")){ locateColumnIndex = i; } if(column[i].equals("测试数据")){ testDataColumnIndex = i; } } // 循环每行的操作,根据switch来判断每行的操作是什么,然后转换成具体的代码,从第二行开始循环,因为第一行是列的说明数据。 for (int i = 1; i < rows; i++) { logger.info("正在解析excel:["+founction+".xlsx]中的sheet(用例):["+caseName+"]的第"+i+"行步骤..."); String action = sheet.getRow(i).getCell(actionColumnIndex).getStringCellValue(); Row row = sheet.getRow(i); if (row != null) { switch (action) { case "打开链接": testData = sheet.getRow(i).getCell(testDataColumnIndex).getStringCellValue(); seleniumUtil.get(testData); break; case "导航链接": testData = sheet.getRow(i).getCell(testDataColumnIndex).getStringCellValue(); seleniumUtil.get(testData); break; case "输入": //先设置Cell的类型,然后就可以把纯数字作为String类型读进来了 sheet.getRow(i).getCell(testDataColumnIndex).setCellType(Cell.CELL_TYPE_STRING); testData = sheet.getRow(i).getCell(testDataColumnIndex).getStringCellValue(); //测试数据 locator = sheet.getRow(i).getCell(locateColumnIndex).getStringCellValue();//获取步骤中的元素定位 //locator.split("\\.")[0]分离出页面名称,比如HomePage.我的单据,提取出HomePage locateSplit = getPageElementLocator(sheet, i, locateColumnIndex,locator.split("\\.")[0]); //找到定位方式、定位值 seleniumUtil.type(getLocateWay(locateSplit[0], locateSplit[1]), testData); break; case "点击": locator = sheet.getRow(i).getCell(locateColumnIndex).getStringCellValue();//获取步骤中的定位 //locator.split("\\.")[0]分离出页面名称,比如HomePage.我的单据,提取出HomePage locateSplit = getPageElementLocator(sheet, i, locateColumnIndex,locator.split("\\.")[0]); seleniumUtil.click(getLocateWay(locateSplit[0], locateSplit[1])); break; case "暂停": //先设置Cell的类型,然后就可以把纯数字作为String类型读进来了 sheet.getRow(i).getCell(testDataColumnIndex).setCellType(Cell.CELL_TYPE_STRING); testData = sheet.getRow(i).getCell(testDataColumnIndex).getStringCellValue(); seleniumUtil.pause(Integer.parseInt(testData)); break; case "等待元素": //先设置Cell的类型,然后就可以把纯数字作为String类型读进来了 sheet.getRow(i).getCell(testDataColumnIndex).setCellType(Cell.CELL_TYPE_STRING); testData = sheet.getRow(i).getCell(testDataColumnIndex).getStringCellValue(); locator = sheet.getRow(i).getCell(locateColumnIndex).getStringCellValue();//获取步骤中的定位 //locator.split("\\.")[0]分离出页面名称,比如HomePage.我的单据,提取出HomePage locateSplit = getPageElementLocator(sheet, i, locateColumnIndex,locator.split("\\.")[0]); seleniumUtil.waitForElementToLoad(Integer.parseInt(testData), getLocateWay(locateSplit[0], locateSplit[1])); break; case "查找元素(尝试3次)": //先设置Cell的类型,然后就可以把纯数字作为String类型读进来了 sheet.getRow(i).getCell(testDataColumnIndex).setCellType(Cell.CELL_TYPE_STRING); testData = sheet.getRow(i).getCell(testDataColumnIndex).getStringCellValue(); locator = sheet.getRow(i).getCell(locateColumnIndex).getStringCellValue();//获取步骤中的定位 //locator.split("\\.")[0]分离出页面名称,比如HomePage.我的单据,提取出HomePage locateSplit = getPageElementLocator(sheet, i, locateColumnIndex,locator.split("\\.")[0]); seleniumUtil.FindElementUtil3TimesTry(Integer.parseInt(testData), getLocateWay(locateSplit[0], locateSplit[1])); break; case "清除": locator = sheet.getRow(i).getCell(locateColumnIndex).getStringCellValue();//获取步骤中的定位 //locator.split("\\.")[0]分离出页面名称,比如HomePage.我的单据,提取出HomePage locateSplit = getPageElementLocator(sheet, i, locateColumnIndex,locator.split("\\.")[0]); seleniumUtil.clear(getLocateWay(locateSplit[0], locateSplit[1])); break; case "进入iFrame": locator = sheet.getRow(i).getCell(locateColumnIndex).getStringCellValue();//获取步骤中的定位 //locator.split("\\.")[0]分离出页面名称,比如HomePage.我的单据,提取出HomePage locateSplit = getPageElementLocator(sheet, i, locateColumnIndex,locator.split("\\.")[0]); seleniumUtil.switchFrame(getLocateWay(locateSplit[0], locateSplit[1])); break; case "跳出iFrame": seleniumUtil.outFrame(); break; case "选择下拉列表 - Text": //先设置Cell的类型,然后就可以把纯数字作为String类型读进来了 sheet.getRow(i).getCell(testDataColumnIndex).setCellType(Cell.CELL_TYPE_STRING); testData = sheet.getRow(i).getCell(testDataColumnIndex).getStringCellValue(); locator = sheet.getRow(i).getCell(locateColumnIndex).getStringCellValue();//获取步骤中的定位 //locator.split("\\.")[0]分离出页面名称,比如HomePage.我的单据,提取出HomePage locateSplit = getPageElementLocator(sheet, i, locateColumnIndex,locator.split("\\.")[0]); seleniumUtil.selectByText(getLocateWay(locateSplit[0], locateSplit[1]), testData); break; case "选择下拉列表 - Index": //先设置Cell的类型,然后就可以把纯数字作为String类型读进来了 sheet.getRow(i).getCell(testDataColumnIndex).setCellType(Cell.CELL_TYPE_STRING); testData = sheet.getRow(i).getCell(testDataColumnIndex).getStringCellValue(); locator = sheet.getRow(i).getCell(locateColumnIndex).getStringCellValue();//获取步骤中的定位 //locator.split("\\.")[0]分离出页面名称,比如HomePage.我的单据,提取出HomePage locateSplit = getPageElementLocator(sheet, i, locateColumnIndex,locator.split("\\.")[0]); seleniumUtil.selectByIndex(getLocateWay(locateSplit[0], locateSplit[1]), Integer.parseInt(testData)); break; case "选择下拉列表 - Value": //先设置Cell的类型,然后就可以把纯数字作为String类型读进来了 sheet.getRow(i).getCell(testDataColumnIndex).setCellType(Cell.CELL_TYPE_STRING); testData = sheet.getRow(i).getCell(testDataColumnIndex).getStringCellValue(); locator = sheet.getRow(i).getCell(locateColumnIndex).getStringCellValue();//获取步骤中的定位 //locator.split("\\.")[0]分离出页面名称,比如HomePage.我的单据,提取出HomePage locateSplit = getPageElementLocator(sheet, i, locateColumnIndex,locator.split("\\.")[0]); seleniumUtil.selectByValue(getLocateWay(locateSplit[0], locateSplit[1]),testData ); break; case "检查文本 - 属性": testData = sheet.getRow(i).getCell(testDataColumnIndex).getStringCellValue(); locator = sheet.getRow(i).getCell(locateColumnIndex).getStringCellValue();//获取步骤中的定位 //locator.split("\\.")[0]分离出页面名称,比如HomePage.我的单据,提取出HomePage locateSplit = getPageElementLocator(sheet, i, locateColumnIndex,locator.split("\\.")[0]); String[] Datas = testData.split(","); seleniumUtil.isTextCorrect(seleniumUtil.getAttributeText(getLocateWay(locateSplit[0], locateSplit[1]), Datas[0]),Datas[1]); break; case "获得网页标题": testData = sheet.getRow(i).getCell(testDataColumnIndex).getStringCellValue(); seleniumUtil.isTextCorrect(seleniumUtil.getTitle(),testData); break; case "页面的URL是否正确": testData = sheet.getRow(i).getCell(testDataColumnIndex).getStringCellValue(); seleniumUtil.isTextCorrect(seleniumUtil.getPageURL(), testData); break; case "检查文本": testData = sheet.getRow(i).getCell(testDataColumnIndex).getStringCellValue(); locator = sheet.getRow(i).getCell(locateColumnIndex).getStringCellValue();//获取步骤中的定位 //locator.split("\\.")[0]分离出页面名称,比如HomePage.我的单据,提取出HomePage locateSplit = getPageElementLocator(sheet, i, locateColumnIndex,locator.split("\\.")[0]); seleniumUtil.isTextCorrect(seleniumUtil.getText(getLocateWay(locateSplit[0], locateSplit[1])), testData); break; case "进入Tab": //需要改进,第二个窗口的driver问题 locator = sheet.getRow(i).getCell(locateColumnIndex).getStringCellValue();//获取步骤中的定位 //locator.split("\\.")[0]分离出页面名称,比如HomePage.我的单据,提取出HomePage locateSplit = getPageElementLocator(sheet, i, locateColumnIndex,locator.split("\\.")[0]); seleniumUtil.switchNewWindow(getLocateWay(locateSplit[0], locateSplit[1])); break; case "跳出Tab": seleniumUtil.backToOriginalWindow(); break; case "接受alert弹窗": //先设置Cell的类型,然后就可以把纯数字作为String类型读进来了 sheet.getRow(i).getCell(testDataColumnIndex).setCellType(Cell.CELL_TYPE_STRING); testData = sheet.getRow(i).getCell(testDataColumnIndex).getStringCellValue(); a = seleniumUtil.switchToPromptedAlertAfterWait(Long.parseLong(testData)); a.accept(); break; case "取消alert弹窗": //先设置Cell的类型,然后就可以把纯数字作为String类型读进来了 sheet.getRow(i).getCell(testDataColumnIndex).setCellType(Cell.CELL_TYPE_STRING); testData = sheet.getRow(i).getCell(testDataColumnIndex).getStringCellValue(); a = seleniumUtil.switchToPromptedAlertAfterWait(Long.parseLong(testData)); a.dismiss(); break; case "执行JS点击": locator = sheet.getRow(i).getCell(locateColumnIndex).getStringCellValue();//获取步骤中的定位 //locator.split("\\.")[0]分离出页面名称,比如HomePage.我的单据,提取出HomePage locateSplit = getPageElementLocator(sheet, i, locateColumnIndex,locator.split("\\.")[0]); seleniumUtil.executeJS("arguments[0].click();", seleniumUtil.findElementBy(getLocateWay(locateSplit[0], locateSplit[1]))); break; case "刷新页面": seleniumUtil.refresh(); break; case "前进页面": seleniumUtil.back(); break; case "后退页面": seleniumUtil.forward(); break; case "上传文件": testData = sheet.getRow(i).getCell(testDataColumnIndex).getStringCellValue(); String uploadValues[] = testData.split(","); seleniumUtil.handleUpload(uploadValues[0], new File(uploadValues[1])); break; case "元素被启用": locator = sheet.getRow(i).getCell(locateColumnIndex).getStringCellValue();//获取步骤中的定位 //locator.split("\\.")[0]分离出页面名称,比如HomePage.我的单据,提取出HomePage locateSplit = getPageElementLocator(sheet, i, locateColumnIndex,locator.split("\\.")[0]); if(seleniumUtil.isEnabled(getLocateWay(locateSplit[0], locateSplit[1]))){ logger.info(getLocateWay(locateSplit[0], locateSplit[1])+"元素被启用"); }else{ Assert.fail(getLocateWay(locateSplit[0], locateSplit[1])+":没有被启用"); } break; case "元素未启用": locator = sheet.getRow(i).getCell(locateColumnIndex).getStringCellValue();//获取步骤中的定位 //locator.split("\\.")[0]分离出页面名称,比如HomePage.我的单据,提取出HomePage locateSplit = getPageElementLocator(sheet, i, locateColumnIndex,locator.split("\\.")[0]); if(seleniumUtil.isEnabled(getLocateWay(locateSplit[0], locateSplit[1]))){ Assert.fail(getLocateWay(locateSplit[0], locateSplit[1])+"元素被启用"); }else{ logger.info(getLocateWay(locateSplit[0], locateSplit[1])+":没有被启用"); } break; case "验证首页菜单栏文本": locator = sheet.getRow(i).getCell(locateColumnIndex).getStringCellValue();//获取步骤中的定位 //locator.split("\\.")[0]分离出页面名称,比如HomePage.我的单据,提取出HomePage locateSplit = getPageElementLocator(sheet, i, locateColumnIndex,locator.split("\\.")[0]); testData = sheet.getRow(i).getCell(testDataColumnIndex).getStringCellValue(); String menus[] = testData.split(","); for (int i1 = 0; i1 < menus.length; i1++) { seleniumUtil.isTextCorrect(seleniumUtil.findElementsBy(getLocateWay(locateSplit[0], locateSplit[1])).get(i1).getText().trim().toLowerCase(), menus[i1].toLowerCase()); } break; default: logger.error("你输入的操作:["+action+"]不被支持,请自行添加"); Assert.fail("你输入的操作:["+action+"]不被支持,请自行添加"); } } } } }
3.5 更改SeleniumUtil.java
SeleniumUtil.java代码如下:
package com.demo.test.utils; import java.awt.AWTException; import java.awt.Robot; import java.awt.event.KeyEvent; import java.io.File; import java.util.Calendar; import java.util.Iterator; import java.util.List; import java.util.Set; import java.util.concurrent.TimeUnit; import org.apache.log4j.Logger; import org.openqa.selenium.Alert; import org.openqa.selenium.By; import org.openqa.selenium.Cookie; import org.openqa.selenium.Dimension; import org.openqa.selenium.JavascriptExecutor; import org.openqa.selenium.Keys; import org.openqa.selenium.NoAlertPresentException; import org.openqa.selenium.NoSuchElementException; import org.openqa.selenium.StaleElementReferenceException; import org.openqa.selenium.TimeoutException; import org.openqa.selenium.WebDriver; import org.openqa.selenium.WebElement; import org.openqa.selenium.interactions.Actions; import org.openqa.selenium.support.ui.ExpectedCondition; import org.openqa.selenium.support.ui.Select; import org.openqa.selenium.support.ui.WebDriverWait; import org.testng.Assert; import org.testng.ITestContext; import org.testng.ITestResult; /** * @Description 包装所有selenium的操作以及通用方法,简化用例中代码量 * */ public class SeleniumUtil { /** 使用Log4j,第一步就是获取日志记录器,这个记录器将负责控制日志信息 */ public static Logger logger = Logger.getLogger(SeleniumUtil.class.getName()); public ITestResult it = null; public WebDriver driver = null; public WebDriver window = null; public String current_handles=""; /*** * 启动浏览器并打开页面 * */ public void launchBrowser(String browserName, ITestContext context,String webUrl,int timeOut) { SelectBrowser select = new SelectBrowser(); driver = select.selectExplorerByName(browserName, context); try { maxWindow(browserName); waitForPageLoading(timeOut); get(webUrl); } catch (TimeoutException e) { logger.warn("注意:页面没有完全加载出来,刷新重试!!"); refresh(); JavascriptExecutor js = (JavascriptExecutor)driver; String status= (String)js.executeScript("return document.readyState"); logger.info("打印状态:"+status); } } /** * 最大化浏览器操作 * */ public void maxWindow(String browserName) { logger.info("最大化浏览器:" + browserName); driver.manage().window().maximize(); } /** * 设定浏览器窗口大小: 设置浏览器窗口的大小有下面两个比较常见的用途:<br> * 1、在统一的浏览器大小下运行用例,可以比较容易的跟一些基于图像比对的工具进行结合 * ,提升测试的灵活性及普遍适用性。比如可以跟sikuli结合,使用sikuli操作flash;<br> * 2、在不同的浏览器大小下访问测试站点,对测试页面截图并保存,然后观察或使用图像比对工具对被测页面的前端样式进行评测。 * 比如可以将浏览器设置成移动端大小(320x480),然后访问移动站点,对其样式进行评估;<br> * */ public void setBrowserSize(int width, int height) { driver.manage().window().setSize(new Dimension(width, height)); } /** * 包装查找元素的方法 element * */ public WebElement findElementBy(By by) { return driver.findElement(by); } /** * 包装查找元素的方法 elements * */ public List<WebElement> findElementsBy(By by) { return driver.findElements(by); } /**导航链接到url*/ public void navigateTargetUrl(String url){ driver.navigate().to(url); logger.info("导航到:"+url); } /** * 包装点击操作- By * */ public void click(By byElement) { try { clickTheClickable(byElement, System.currentTimeMillis(), 2500); } catch (StaleElementReferenceException e) { logger.error("The element you clicked:[" + byElement + "] is no longer exist!"); Assert.fail("The element you clicked:[" + byElement + "] is no longer exist!"); } catch (Exception e) { logger.error("Failed to click element [" + byElement + "]"); Assert.fail("Failed to click element [" + byElement + "]",e); } logger.info("点击元素 [" + byElement + "]"); } public boolean isEnabled(By by){ return driver.findElement(by).isEnabled(); } /**提交*/ public void submit(WebElement w){ try{ w.submit(); }catch(Exception e){ logger.error("在元素:"+w+"做的提交操作失败"); Assert.fail("在元素:"+w+"做的提交操作失败"); } logger.info("在元素:"+w+"做了提交操作"); } /** * 包装点击操作 -webelment * */ public void click(WebElement element) { try { element.click(); } catch (StaleElementReferenceException e) { logger.error("The element you clicked:[" + element.toString() + "] is no longer exist!"); Assert.fail("The element you clicked:[" + element.toString() + "] is no longer exist!"); } catch (Exception e) { logger.error("Failed to click element [" + element.toString() + "]"); Assert.fail("Failed to click element [" + element.toString() + "]",e); } logger.info("点击元素 [" + element.toString() + "]"); } /** 不能点击时候重试点击操作 */ public void clickTheClickable(By byElement, long startTime, int timeOut) throws Exception { try { findElementBy(byElement).click(); } catch (Exception e) { if (System.currentTimeMillis() - startTime > timeOut) { logger.warn(byElement+ " is unclickable"); throw new Exception(e); } else { Thread.sleep(500); logger.warn(byElement + " is unclickable, try again"); clickTheClickable(byElement, startTime, timeOut); } } } /** * 获得页面的标题 * */ public String getTitle() { return driver.getTitle(); } /** * 获得元素的文本 * */ public String getText(By elementLocator) { return driver.findElement(elementLocator).getText().trim(); } /** * 获得元素 属性的文本 * */ public String getAttributeText(By elementLocator, String attribute) { return driver.findElement(elementLocator).getAttribute(attribute).trim(); } /** * 包装清除操作 * */ public void clear(By byElement) { try { findElementBy(byElement).clear(); } catch (Exception e) { logger.error("清除元素 [" + byElement + "] 上的内容失败!"); } logger.info("清除元素 [" + byElement + "]上的内容"); } /** * 向输入框输入内容 * */ public void type(By byElement, String key) { try { findElementBy(byElement).sendKeys(key); } catch (Exception e) { e.printStackTrace(); logger.error("输入 [" + key + "] 到 元素[" + byElement + "]失败"); Assert.fail("输入 [" + key + "] 到 元素[" + byElement + "]失败",e); } logger.info("输入:[" + key + "] 到 [" + byElement + "]"); } /** * 模拟键盘操作的,比如Ctrl+A,Ctrl+C等 参数详解:<br> * 1、WebElement element - 要被操作的元素 <br> * 2、Keys key- 键盘上的功能键 比如ctrl ,alt等 <br> * 3、String keyword - 键盘上的字母 * */ public void pressKeysOnKeyboard(WebElement element, Keys key, String keyword) { element.sendKeys(Keys.chord(key, keyword)); } /** * 在给定的时间内去查找元素,如果没找到则超时,抛出异常 * */ public void waitForElementToLoad(int timeOut, final By By) { logger.info("开始查找元素[" + By + "]"); try { (new WebDriverWait(driver, timeOut)).until(new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver driver) { WebElement element = driver.findElement(By); return element.isDisplayed(); } }); } catch (TimeoutException e) { logger.error("超时!! " + timeOut + " 秒之后还没找到元素 [" + By + "]"); Assert.fail("超时!! " + timeOut + " 秒之后还没找到元素 [" + By + "]"); } logger.info("找到了元素 [" + By + "]"); } /** * 在给定的时间内查询元素,共尝试三次,如果第三次还是找不到就报错,这就可能是网页性能问题了,响应速度不够 * */ public void FindElementUtil3TimesTry(int timeOut, final By By ) { int find=0; int notFindTimes = 0; boolean flag = true; while(flag){ if(notFindTimes==3){ logger.error("尝试了3次查找都未查找到元素:"+By+"请检查是不是网络或者网站性能问题(响应速度不够)"); Assert.fail("尝试了3次查找都未查找到元素:"+By+"请检查是不是网络或者网站性能问题(响应速度不够)"); } logger.info("开始第"+(notFindTimes+1)+"次查找元素[" + By + "]"); try { (new WebDriverWait(driver, timeOut)).until(new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver driver) { WebElement element = driver.findElement(By); return element.isDisplayed(); } }); find++; } catch (TimeoutException e) { logger.warn("超时!! " + timeOut + " 秒之后还没找到元素 [" + By + "],这是第"+(notFindTimes+1)+"次查找!"); notFindTimes++; if(notFindTimes<3){ refresh(); } } if(notFindTimes>0&find!=1){ flag = true; }else{ flag = false; } } logger.info("找到了元素 [" + By + "]"); } /** * 判断文本是不是和需求要求的文本一致 * **/ public void isTextCorrect(String actual, String expected) { try { Assert.assertEquals(actual, expected); } catch (AssertionError e) { logger.error("期望的文字是 [" + expected + "] 但是找到了 [" + actual + "]"); Assert.fail("期望的文字是 [" + expected + "] 但是找到了 [" + actual + "]"); } logger.info("找到了期望的文字: [" + expected + "]"); } /** * 判断编辑框是不是可编辑 * */ public void isInputEdit(WebElement element) { } /** * 等待alert出现 * */ public Alert switchToPromptedAlertAfterWait(long waitMillisecondsForAlert) throws NoAlertPresentException { final int ONE_ROUND_WAIT = 200; NoAlertPresentException lastException = null; long endTime = System.currentTimeMillis() + waitMillisecondsForAlert; for (long i = 0; i < waitMillisecondsForAlert; i += ONE_ROUND_WAIT) { try { Alert alert = driver.switchTo().alert(); return alert; } catch (NoAlertPresentException e) { lastException = e; } try { Thread.sleep(ONE_ROUND_WAIT); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } if (System.currentTimeMillis() > endTime) { break; } } throw lastException; } /** * 暂停当前用例的执行,暂停的时间为:sleepTime * */ public void pause(int sleepTime) { if (sleepTime <= 0) { return; } try { TimeUnit.SECONDS.sleep(sleepTime); logger.info("暂停:"+sleepTime+"秒"); } catch (InterruptedException e) { e.printStackTrace(); } } /** * 退出 * */ public void quit() { driver.quit(); } /** * 切换frame - 根据String类型(frame名字) * */ public void inFrame(String frameId) { driver.switchTo().frame(frameId); } /** * 切换frame - 根据frame在当前页面中的顺序来定位 * */ public void inFrame(int frameNum) { driver.switchTo().frame(frameNum); } /** * 切换frame - 根据页面元素定位 * */ public void switchFrame(By byElement) { try { logger.info("Start switching to frame [" + byElement + "]"); driver.switchTo().frame(findElementBy(byElement)); } catch (Exception e) { logger.info("Switch to frame [" + byElement + "] failed"); Assert.fail("Switch to frame [" + byElement + "] failed"); } logger.info("Switch to frame [" + byElement + "] successed"); } /** * 选择下拉选项 -根据value * */ public void selectByValue(By by, String value) { Select s = new Select(driver.findElement(by)); s.selectByValue(value); } /** * 选择下拉选项 -根据index角标 * */ public void selectByIndex(By by, int index) { Select s = new Select(driver.findElement(by)); s.selectByIndex(index); } /** 检查checkbox是不是勾选 */ public boolean doesCheckboxSelected(By elementLocator) { if (findElementBy(elementLocator).isSelected() == true) { logger.info("CheckBox: " + getLocatorByElement(findElementBy(elementLocator), ">") + " 被勾选"); return true; } else logger.info("CheckBox: " + getLocatorByElement(findElementBy(elementLocator), ">") + " 没有被勾选"); return false; } /** * 选择下拉选项 -根据文本内容 * */ public void selectByText(By by, String text) { Select s = new Select(driver.findElement(by)); s.selectByVisibleText(text); logger.info("你选择了:"+text); } /** * 获得当前select选择的值 * */ public String getCurrentSelectValue(By by){ Select s = new Select(driver.findElement(by)); WebElement e = s.getFirstSelectedOption(); return e.getText().trim(); } /** * 获取下拉列表的所有选项 * @param By:By元素对象 * @return 返回所有下拉列表中的选项,如option1,option2,…… * */ public String getSelectOption(By by) { String value = null; Select s = new Select(driver.findElement(by)); List<WebElement> options = s.getOptions(); for(int i = 0 ; i< options.size() ; i++){ value = value + "," + options.get(i).getText(); } return value.replace("null,",""); } /** * 执行JavaScript 方法 * */ public void executeJS(String js) { ((JavascriptExecutor) driver).executeScript(js); logger.info("执行JavaScript语句:[" + js + "]"); } /** * 获得输入框的值 这个方法 是针对某些input输入框 没有value属性,但是又想取得input的 值得方法 * */ public String getInputValue(String chose,String choseValue) { String value = null; switch(chose.toLowerCase()){ case "name": String jsName = "return document.getElementsByName('"+choseValue+"')[0].value;"; //把JS执行的值 返回出去 value = (String)((JavascriptExecutor) driver).executeScript(jsName); break; case "id": String jsId = "return document.getElementById('"+choseValue+"').value;"; //把JS执行的值 返回出去 value = (String)((JavascriptExecutor) driver).executeScript(jsId); break; default: logger.error("未定义的chose:"+chose); Assert.fail("未定义的chose:"+chose); } return value; } /** * 执行JavaScript 方法和对象 * 用法:seleniumUtil.executeJS("arguments[0].click();", seleniumUtil.findElementBy(MyOrdersPage.MOP_TAB_ORDERCLOSE)); * */ public void executeJS(String js, Object... args) { ((JavascriptExecutor) driver).executeScript(js, args); logger.info("执行JavaScript语句:[" + js + "]"); } /** * get方法包装 * */ public void get(String url) { driver.get(url); logger.info("打开测试页面:[" + url + "]"); } /** * close方法包装 * */ public void close() { driver.close(); } /** * 刷新方法包装 * */ public void refresh() { driver.navigate().refresh(); logger.info("页面刷新成功!"); } /** * 后退方法包装 * */ public void back() { driver.navigate().back(); } /** * 前进方法包装 * */ public void forward() { driver.navigate().forward(); } /** * 包装selenium模拟鼠标操作 - 鼠标移动到指定元素 * */ public void mouseMoveToElement(By by) { Actions builder = new Actions(driver); Actions mouse = builder.moveToElement(driver.findElement(by)); mouse.perform(); } /** * 包装selenium模拟鼠标操作 - 鼠标移动到指定元素 * */ public void mouseMoveToElement(WebElement element) { Actions builder = new Actions(driver); Actions mouse = builder.moveToElement(element); mouse.perform(); } /** * 包装selenium模拟鼠标操作 - 鼠标右击 * */ public void mouseRightClick(By element) { Actions builder = new Actions(driver); Actions mouse = builder.contextClick(findElementBy(element)); mouse.perform(); } /** * 添加cookies,做自动登陆的必要方法 * */ public void addCookies(int sleepTime) { pause(sleepTime); Set<Cookie> cookies = driver.manage().getCookies(); for (Cookie c : cookies) { System.out.println(c.getName() + "->" + c.getValue()); if (c.getName().equals("logisticSessionid")) { Cookie cook = new Cookie(c.getName(), c.getValue()); driver.manage().addCookie(cook); System.out.println(c.getName() + "->" + c.getValue()); System.out.println("添加成功"); } else { System.out.println("没有找到logisticSessionid"); } } } /** 获得CSS value */ public String getCSSValue(WebElement e, String key) { return e.getCssValue(key); } /** 使用testng的assetTrue方法 */ public void assertTrue(WebElement e, String content) { String str = e.getText(); Assert.assertTrue(str.contains(content), "字符串数组中不含有:" + content); } /** 跳出frame */ public void outFrame() { driver.switchTo().defaultContent(); } // webdriver中可以设置很多的超时时间 /** implicitlyWait。识别对象时的超时时间。过了这个时间如果对象还没找到的话就会抛出NoSuchElement异常 */ public void implicitlyWait(int timeOut) { driver.manage().timeouts().implicitlyWait(timeOut, TimeUnit.SECONDS); } /** setScriptTimeout。异步脚本的超时时间。webdriver可以异步执行脚本,这个是设置异步执行脚本脚本返回结果的超时时间 */ public void setScriptTimeout(int timeOut) { driver.manage().timeouts().setScriptTimeout(timeOut, TimeUnit.SECONDS); } /** * pageLoadTimeout。页面加载时的超时时间。因为webdriver会等页面加载完毕在进行后面的操作, * 所以如果页面在这个超时时间内没有加载完成,那么webdriver就会抛出异常 */ public void waitForPageLoading(int pageLoadTime) { driver.manage().timeouts().pageLoadTimeout(pageLoadTime, TimeUnit.SECONDS); } /** 根据元素来获取此元素的定位值 */ public String getLocatorByElement(WebElement element, String expectText) { String text = element.toString(); String expect = null; try { expect = text.substring(text.indexOf(expectText) + 1, text.length() - 1); } catch (Exception e) { e.printStackTrace(); logger.error("failed to find the string [" + expectText + "]"); } return expect; } /** * 获取当前页面的URL * */ public String getPageURL(){ return driver.getCurrentUrl(); } /** * 这是一堆相同的elements中 选择 其中方的 一个 然后在这个选定的中 继续定位 * */ public WebElement getOneElement(By bys, By by, int index) { return findElementsBy(bys).get(index).findElement(by); } /** * 上传文件,需要点击弹出上传照片的窗口才行 * * @param brower * 使用的浏览器名称 * @param file * 需要上传的文件及文件名 */ public void handleUpload(String browser, File file) { String filePath = file.getAbsolutePath(); String executeFile = "res/script/autoit/Upload.exe"; String cmd = "\"" + executeFile + "\"" + " " + "\"" + browser + "\"" + " " + "\"" + filePath + "\""; try { Process p = Runtime.getRuntime().exec(cmd); p.waitFor(); } catch (Exception e) { e.printStackTrace(); } } /** * @Description 对于windows GUI弹出框,要求输入用户名和密码时, * seleniumm不能直接操作,需要借助http://modifyusername:modifypassword@yoururl 这种方法 * * */ public void loginOnWinGUI(String username, String password, String url) { driver.get(username + ":" + password + "@" + url); } /** 检查元素是否显示 */ public boolean isDisplayed(WebElement element) { boolean isDisplay = false; if (element.isDisplayed()) { logger.info("The element: [" + getLocatorByElement(element, ">") + "] is displayed"); isDisplay = true; } else if (element.isDisplayed() == false) { logger.warn("The element: [" + getLocatorByElement(element, ">") + "] is not displayed"); isDisplay = false; } return isDisplay; } /**检查元素是不是存在*/ public boolean doesElementsExist(By byElement){ try{ findElementBy(byElement); return true; }catch(NoSuchElementException nee){ return false; } } /** 检查元素是否被勾选 */ public boolean isSelected(WebElement element) { boolean flag = false; if (element.isSelected() == true) { logger.info("The element: [" + getLocatorByElement(element, ">") + "] is selected"); flag = true; } else if (element.isSelected() == false) { logger.info("The element: [" + getLocatorByElement(element, ">") + "] is not selected"); flag = false; } return flag; } /** * 判断实际文本时候包含期望文本 * * @param actual * 实际文本 * @param expect * 期望文本 */ public void isContains(String actual, String expect) { try { Assert.assertTrue(actual.contains(expect)); } catch (AssertionError e) { logger.error("The [" + actual + "] is not contains [" + expect + "]"); Assert.fail("The [" + actual + "] is not contains [" + expect + "]"); } logger.info("The [" + actual + "] is contains [" + expect + "]"); } /** * 判断实际文本,不包含期望文本 * * @param actual * 实际文本 * @param expect * 期望文本 */ public void isNotContains(String actual, String expect) { try { Assert.assertFalse(actual.contains(expect)); } catch (AssertionError e) { logger.error("The [" + actual + "] is contains [" + expect + "]"); Assert.fail("The [" + actual + "] is contains [" + expect + "]"); } logger.info("The [" + actual + "] is not contains [" + expect + "]"); } /** 获得屏幕的分辨率 - 宽 */ public double getScreenWidth() { return java.awt.Toolkit.getDefaultToolkit().getScreenSize().getWidth(); } /**进入新窗口*/ public void switchNewWindow(By byElement){ //获取当前页面句柄 current_handles = driver.getWindowHandle(); //点击某个链接会弹出一个新窗口 click(byElement); //接下来会有新的窗口打开,获取所有窗口句柄 Set<String> all_handles = driver.getWindowHandles(); //循环判断,把当前句柄从所有句柄中移除,剩下的就是你想要的新窗口 Iterator<String> it = all_handles.iterator(); while(it.hasNext()){ if(current_handles == it.next()) continue; //跳入新窗口,并获得新窗口的driver - newWindow window = driver.switchTo().window(it.next()); } } /**回到原始窗口*/ public void backToOriginalWindow(){ window.close(); driver.switchTo().window(current_handles); } /**停止页面加载*/ public void stopLoad(){ pause(1); Robot r; try { r = new Robot(); r.keyPress(KeyEvent.VK_ESCAPE); logger.info("按下了Esc键"); r.keyRelease(KeyEvent.VK_ESCAPE); logger.info("松开了Esc键"); } catch (AWTException e) { e.printStackTrace(); } logger.info("正在停止页面加载..."); } /**获取系统时间*/ public int getDate(String getOption){ Calendar a=Calendar.getInstance(); int result=0; switch(getOption){ case "年": result = a.get(Calendar.YEAR); break; case "月": result = a.get(Calendar.MONTH)+1; break; case "日": result = a.get(Calendar.DATE); break; default: Assert.fail("只支持输入年、月、日。你输入了:"+getOption); } return result; } /**判断alert是否出现*/ public boolean isAlertPresent(){ try { driver.switchTo().alert(); logger.info("alert出现"); return true; } catch (NoAlertPresentException Ex) { logger.warn("alert没有出现"); return false; } } /**CMP干部绩效管理系统登录操作*/ public void loginCMP(String username,String password){ FindElementUtil3TimesTry(30, By.id("account")); FindElementUtil3TimesTry(30, By.id("password")); FindElementUtil3TimesTry(30, By.id("bLogin")); type(By.id("account"),username); type(By.id("password"),password); click(By.id("bLogin")); } /** * 在多个相同元素中,定位到指定的元素 * @param by * @param index * @return */ public WebElement getOneElement(By by, int index) { List<WebElement> element = driver.findElements(by); return element.get(index); } /** * 获取指定table某一整列的值 */ public String getColumnText(By by){ String values = null; List<WebElement> elements = findElementsBy(by); for(WebElement e: elements){ String value = e.getText(); if(value.length() > 0){ values = values + "," + value; } } return values.replace("null,", ""); } /** * 获取指定table某一行的值 * @param index:行号,行号从1开始(0代表table的表头) */ public String getRowText(By by, int index){ String values = null; List<WebElement> rows = findElementsBy(by); //tr对象 WebElement row = rows.get(index); if(row.findElements(By.tagName("td")).size()>0){ List<WebElement> cells = row.findElements(By.tagName("td")); //td对象 for(WebElement cell:cells){ String value = cell.getText(); if(value.length() > 0){ values = values + "," + value; } } } return values.replace("null,", ""); } /** * 获取指定table个单元格的值 * @param index:行号,行号从1开始(0代表table的表头) */ public String getCellText(By by, int RowID, int ColID){ String value = null; //得到table元素对象 WebElement table = driver.findElement(by); //得到table表中所有行对象,并得到所要查询的行对象。 List<WebElement> rows = table.findElements(By.tagName("tr")); WebElement theRow = rows.get(RowID); //调用getCell方法得到对应的列对象,然后得到要查询的文本。 value = getCell(theRow, ColID).getText(); return value.replace("null,", ""); } /** * * @param Row: 一行的对象 * @param ColID:对应列 * @return */ private WebElement getCell(WebElement Row,int ColID){ List<WebElement> cells; WebElement target = null; //列里面有"<th>"、"<td>"两种标签,所以分开处理。 if(Row.findElements(By.tagName("th")).size()>0){ cells = Row.findElements(By.tagName("th")); target = cells.get(ColID); } if(Row.findElements(By.tagName("td")).size()>0){ cells = Row.findElements(By.tagName("td")); target = cells.get(ColID); } return target; } /** * 在给定的时间内去查找元素,如果没找到则超时,抛出异常 * */ public boolean isShown(int timeOut, final By By) { boolean flag = true; logger.info("开始查找元素[" + By + "]"); try { (new WebDriverWait(driver, timeOut)).until(new ExpectedCondition<Boolean>() { public Boolean apply(WebDriver driver) { WebElement element = driver.findElement(By); return element.isDisplayed(); } }); } catch (TimeoutException e) { flag = false; } return flag; } /**页面过长时候滑动页面 window.scrollTo(左边距,上边距); */ public void scrollPage(int x,int y){ String js ="window.scrollTo("+x+","+y+");"; ((JavascriptExecutor)driver).executeScript(js); } }