文章目录
- UI自动化基础
- 什么是UI自动化测试框架
- UI自动化测试框架的模式
- 数据驱动测试框架
- 关键字驱动测试框架
- 行为驱动测试框架
- UI自动化测试框架的作用
- UI自动化测试框架的核心思想
- UI自动化测试框架的步骤
- UI自动化测试框架的构成
- Utils
- Log.java
- ReadProperties.Java
- core
- BaseTest.java打开游览器
- ElementFinder.java元素查找封装类
- SeleniumScreenShot.java截屏封装类
- WebDriverEngine.java游览器操作封装类
- WebTestListener1.java 监听器1,监听所有测试用例执行后的执行结果
- WebTestListener1.java 监听器2,监听所有失败测试用例截屏
- demo-测试用例包
- Front_Login1.java测试用例类
- dataprovider-数据驱动包
- ExcelDataProvider.java-读取excel
- MysqlDataProvider.java-读取sql
- TxtDataProvider.java
- data-数据文件夹
- user.txt-存放用户名和密码
- conf-配置文件夹
- config.properties
- libs-导入jar包
- log4j2.xml日志打印格式
- 常见异常
- UI自动化测试框架的进阶构成
- utils包:实现测试过程中调用的工具类方法,例如:文件操作、mapObject、页面对象的操作方法
- Log.java
- ObjectMap.java
- ReadProperties.java
- appModules包主要用于实现复用的业务逻辑封装方法
- Login_Action.java
- AddMessage_Action.java
- pageObjects包:用于实现被测试的页面对象
- LoginPage.java
- AddMessagePage.java
- testCases 包 :具体的测试方法
- LoginTest.java
- AddMessageTest.java
- dataprovider包:提供数据驱动的类,txt驱动,excel驱动,数据库的驱动
- core:游览器启动、table元素读取
- BaseTest.java
- Table.java
UI自动化基础
http://t.csdnimg.cn/aCCZ5
什么是UI自动化测试框架
UI自动化测试框架是应用于自动化测试的程序框架,它提供了可重用的自动化测试模块,提供最基本的自动化测试功能(打开浏览器,输入文字,点击按钮),或提供自动化测试执行和管理功能的架构模块(例如,TestNG)。它是由一个或多个自动化测试基础模块、自动化测试管理模块、自动化测试统计模块等组成的工具集合。
UI自动化测试框架的模式
- 数据驱动测试框架
- 关键字驱动测试框架
- 混合型测试框架(页面对象+数据驱动+关键字
驱动) - 行为驱动测试框架-Cucumber
数据驱动测试框架
使用数组、文件或者数据库等方式作为测试过程输入的自动化测试框架,此框架可以将所有的测试数据在自动化测试执行的过程中进行自动加载,动态判断测试结果是否符合预期,并自动输出测试报告。
关键字驱动测试框架
被操作的元素对象、操作的方法和操作的数据值作为测试过程输入的自动化测试框架。(存在于UFT工具中)可以保存在数组、文件或数据库中。
例如:输入框,输入,内容name:username, sendKeys, admin
行为驱动测试框架
行为驱动开发是一种敏捷软件开发技术,Behavior
Driven Development。Cucumber是实现BDD开发模式的一种测
试框架,实现了自然语言来执行相关联的测试代码的需求。
https://cucumber.io/ http://repo1.maven.org/maven2/info/cukes/
Cucumber-core.jar 核心包
Cucumber-java.jar 通过 java 编写需要下载这个包
Cucumber-html.jar 生成结果为 html 文件需要下载这个包
Cucumber-testng.jar 使用testng执行测试并生成报告
UI自动化测试框架的作用
- 能够有效组织和管理测试用例
- 将基础的代码封装,降低测试脚本编写的复杂性和重复性
- 提高测试脚本维护和修改的效率
- 自动执行测试脚本,并自动发布测试报告,为持续集成的开发方式提供脚本支持
- 让不具备编程能力的测试工程师开展自动化测试工作
UI自动化测试框架的核心思想
将常用的脚本代码或者测试逻辑进行抽象和总结,然后将这些代码进行面向对象设计,将需要复用的代码封装到可公用的类方法中。通过调用公用的类方法,测试类中的脚本复杂度会被大大降低,让更多脚本能力不强的测试人员来实施自动化测试。
UI自动化测试框架的步骤
1.根据测试业务的手工测试用例,选出需要自动化的用例(例如:冒烟测试)
2.根据可自动化执行的测试用例,分析出测试框架需要模拟的手工操作和重复高的测试流程或逻辑
3.将重复高的测试流程在代码中实现,并进行封装
4.根据业务的类型和本身的技术能力选择数据驱动测试、关键字驱动测试框架、混合型框架还是行为测试框架
5.确定框架类型后,将框架中的常用的浏览器选择、测试数据处理、文件操作、数据库操作、页面元素的原始操作、日志和报告等功能进行方法的封装实现
6.对框架代码进行集成测试和系统测试,采用PO模式和TestNG框架编写测试脚本,使用框架进行自动化测试,验证框架的功能是否可以满足自动化测试的需求。
7.编写自动化测试框架的常用API,以供他人参阅
8.在测试组中内部进行培训和推广
9.不断收集测试过程中的框架使用问题和反馈意见,不断增加和优化自动化框架的功能,不断增强框架中复杂操作的封装效果,尽量降低测试脚本的编写复杂性
10.定期评估测试框架的使用效果,评估自动化测试的投入和产出比,再逐步推广自动化框架的应用范围
UI自动化测试框架的构成
- utils包:实现测试过程中调用的工具类方法,
- core包主要用于实现复用的业务逻辑封装方法
- demo包 :具体的测试用例方法
- dataprovider包:提供数据驱动的类,txt驱动,excel驱动,数据库的驱动
Utils
Log.java
-
共有8个级别,按照从低到高为:All<Trace < Debug < Info < Warn < Error < Fatal <Off
-
<PatternLayout pattern="[%-5p] %d %c %M - %m%n" />
- %-5p表 示日志的级别,输出优先级,即ALL、TRACE,DEBUG,INFO,WARN,ERROR,FATAL、OFF【从低级别到高级别】
- %d 打印日志的年月日时分毫秒信息
- %c 打印类的名称
- %M 输出发出日志请求的方法名
- %m 打印具体的日志信息
- %n 输出一个回车换行符
package com.webtest.utils;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;public class Log {static Logger logger = LogManager.getLogger();public static void startTestCase() {logger.info("----------------------");}public static void endTestCase() {logger.info("----------------------");}public static void fatal(String msg) {logger.fatal(msg);}public static void error(String msg) {logger.error(msg);}public static void warn(String msg) {logger.warn(msg);}public static void info(String msg) {logger.info(msg);}public static void debug(String msg) {logger.debug(msg);}public static void trace(String msg) {logger.trace(msg);}
}
ReadProperties.Java
读取文件属性
package com.webtest.utils;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;import org.testng.annotations.Test;public class ReadProperties {public static final String filePath="conf/config.properties";public static String getPropertyValue(String key) throws IOException {Properties prop = new Properties();FileInputStream fis = new FileInputStream(filePath);prop.load(fis);fis.close();return prop.getProperty(key);}
}
core
BaseTest.java打开游览器
package com.webtest.core;import java.io.IOException;import java.time.Duration;import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.ITestContext;
import org.testng.TestRunner;import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeSuite;import com.webtest.utils.Log;
import com.webtest.utils.ReadProperties;public class BaseTest {public WebDriverEngine webtest;private WebDriver driver;public String driverType;private WebDriver newWebDriver(String driverType) throws IOException {WebDriver driver = null;if (driverType.equalsIgnoreCase("firefox")) {String firefox_driver =ReadProperties.getPropertyValue("gecko_driver");String firefox_path = ReadProperties.getPropertyValue("firefox_path");System.setProperty("webdriver.gecko.driver", firefox_driver);System.setProperty("webdriver.firefox.bin", firefox_path);driver = new FirefoxDriver();Log.info("Using Firefox");} else if (driverType.equalsIgnoreCase("chrome")) {String chrome_path = ReadProperties.getPropertyValue("chrome_path");System.setProperty("webdriver.chrome.driver",chrome_path);driver = new ChromeDriver();Log.info("Using Chrome");}else{return null;}return driver;}/*** *打开浏览器* */@BeforeClasspublic void doBeforeClass() throws Exception {driverType=ReadProperties.getPropertyValue("driverType");driver = this.newWebDriver(driverType);driver.manage().window().maximize();driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));Log.info(driverType);webtest = new WebDriverEngine(driver);}// @AfterClasspublic void doAfterMethod() {if(this.driver != null){this.driver.quit();}Log.info("Quitted Browser");}public WebDriver getDriver() {return driver;}// @BeforeSuite(description = "添加监听器")public void addListener(ITestContext context) {System.out.println("添加监听器");TestRunner runner =(TestRunner)context;runner.addListener(new WebTestListener1());runner.addListener(new WebTestListener2());}}
ElementFinder.java元素查找封装类
package com.webtest.core;import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;import com.webtest.utils.Log;public class ElementFinder {WebDriver driver;public ElementFinder(WebDriver driver){this.driver=driver;}public WebElement findElement(String target) {WebElement element = null;try {element = findElementByPrefix(target);} catch (Exception e) {Log.info(e.toString());}return element;}public WebElement findElementByPrefix(String locator){String target=locator.trim();if(target.startsWith("id=")){locator = locator.substring("id=".length());return driver.findElement(By.id(locator));}else if(target.startsWith("class=")){locator = locator.substring("class=".length());return driver.findElement(By.className(locator));}else if(target.startsWith("name=")){locator = locator.substring("name=".length());return driver.findElement(By.name(locator));}else if(target.startsWith("link=")){locator = locator.substring("link=".length());return driver.findElement(By.linkText(locator));}else if(target.startsWith("partLink=")){locator = locator.substring("partLink=".length());return driver.findElement(By.partialLinkText(locator));}else if(target.startsWith("css=")){locator = locator.substring("css=".length());return driver.findElement(By.cssSelector(locator));}else if(target.startsWith("xpath=")){locator = locator.substring("xpath=".length());return driver.findElement(By.xpath(locator));}else if(target.startsWith("tag=")){locator = locator.substring("tag=".length());return driver.findElement(By.tagName(locator));}else{Log.info(locator+"can't find element by prefix.");return null;}}}
SeleniumScreenShot.java截屏封装类
package com.webtest.core;import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;import com.google.common.io.Files;
import com.webtest.utils.Log;public class SeleniumScreenShot {public WebDriver driver;public SeleniumScreenShot(WebDriver driver) {this.driver = driver;}public void screenShot() {SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd-HHmmss");String nowDateTime = sdf.format(new Date());File s_file = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);try {Files.copy(s_file, new File("D:\\demo\\" + nowDateTime + ".jpg"));} catch (IOException e) {Log.info("bad dir"); }}}
WebDriverEngine.java游览器操作封装类
package com.webtest.core;import java.io.File;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;import org.openqa.selenium.Alert;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.Keys;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.ie.InternetExplorerDriver;
import org.openqa.selenium.interactions.Actions;
import org.openqa.selenium.support.ui.Select;
import org.testng.Assert;
import org.testng.annotations.Test;import com.webtest.utils.Log;
import com.webtest.utils.ReadProperties;public class WebDriverEngine {WebDriver driver = null;ElementFinder finder = null;Actions action =null;public WebDriverEngine(WebDriver driver) {this.driver = driver;finder = new ElementFinder(driver);action = new Actions(driver);}public String[] getAllWindowTitles() {// TODO Auto-generated method stubString current = driver.getWindowHandle();List<String> attributes = new ArrayList<String>();for (String handle : driver.getWindowHandles()) {driver.switchTo().window(handle);attributes.add(driver.getTitle());}driver.switchTo().window(current);return attributes.toArray(new String[attributes.size()]);}public void enterFrame(String frameID) {this.pause(3000);driver.switchTo().frame(frameID);Log.info("Entered iframe " + frameID);}public void enterFrame(int frameID) {this.pause(3000);driver.switchTo().frame(frameID);Log.info("Entered iframe " + frameID);}public void enterFrameLocator(String locator) {WebElement element = finder.findElement(locator);this.pause(3000);driver.switchTo().frame(element);Log.info("Entered iframe " + element);}public void leaveFrame() {driver.switchTo().defaultContent();Log.info("Left the iframe");}public void open(String url) {try {driver.get(ReadProperties.getPropertyValue("base_url")+url);pause(5000);} catch (Exception e) {e.printStackTrace();}Log.info("Opened url " + url);}public String getTitle() {return driver.getTitle();}private void pause(int time) {if (time <= 0) {return;}try {Thread.sleep(time);} catch (InterruptedException e) {e.printStackTrace();}}public boolean isTextPresent(String pattern) {String text = driver.getPageSource();text = text.trim();if (text.contains(pattern)) {return true;}return false;}public void enter() {action.sendKeys(Keys.ENTER);}public void typeAndClear(String locator, String value) {WebElement element = finder.findElement(locator);if (element != null) {element.clear();element.sendKeys(value);}}public void type(String locator, String value) {WebElement element = finder.findElement(locator);if (element != null) {element.sendKeys(value);}}public boolean isChecked(String locator) {WebElement element = finder.findElement(locator);return element.isSelected();}public void click(String locator) {WebElement element = finder.findElement(locator);if (element != null) {element.click();this.pause(3000);}}public void clear(String locator) {WebElement element = finder.findElement(locator);if (element != null) {element.clear();}}public void clickLonger(String locator) {WebElement element = finder.findElement(locator);if (element != null) {runJs("window.scrollTo(0," + element.getLocation().x + ")");element.click();this.pause(3000);}}public void doubleClick(String locator) throws InterruptedException {WebElement element = finder.findElement(locator);action.doubleClick(element).build().perform();}public void actionClick() {action.click().perform();}public boolean isDisplayed(String locator) {WebElement element = finder.findElement(locator);if (element != null) {return element.isDisplayed();}return false;}public String getText(String locator) {return finder.findElement(locator).getText().trim();}public boolean isElementPresent(String locator) {WebElement element = null;try {element = finder.findElement(locator);} catch (Exception e) {Log.info(e.getMessage());}if (element != null) {return true;}{return false;}}public String getValue(String locator) {return finder.findElement(locator).getAttribute("value");}public String getUrl() {return driver.getCurrentUrl();}public void goBack() {driver.navigate().back();}public void goForward() {driver.navigate().forward();}public Alert getAlert() {Alert alert = driver.switchTo().alert();return alert;}public String getAlertTest() {return getAlert().getText();}public void alertAccept() {getAlert().accept();}public Select getSelect(String locator) {Select inputSelect = new Select(finder.findElement(locator));return inputSelect;}public void selectByValue(String locator, String value) {getSelect(locator).selectByValue(value);this.pause(5000);}public void selectByVisibleText(String locator, String value) {getSelect(locator).selectByVisibleText(value);}public void selectByIndex(String locator, int index) {getSelect(locator).selectByIndex(index);}public String getHtmlSource() {return driver.getPageSource();}public void runJs(String js) {JavascriptExecutor j = (JavascriptExecutor) driver;j.executeScript(js);}public void mouseToElement(String locator) throws InterruptedException {action.moveToElement(finder.findElement(locator)).perform();}public void mouseToElementandClick(String locator) throws InterruptedException {action.moveToElement(finder.findElement(locator)).click().perform();}public void switchWidow(int i){List<String> windows = new ArrayList<String>();for (String handle : driver.getWindowHandles()) {windows.add(handle);}driver.switchTo().window(windows.get(i));}public void rightClickMouse(String locator) throws InterruptedException {action.contextClick(finder.findElement(locator)).perform();}public void tapClick(){action.sendKeys(Keys.TAB).perform();;}public void downClick(){action.sendKeys(Keys.DOWN).perform();;}public void tapType(String content){action.sendKeys(content).perform();}public void getWindow(int i){List<String> windows = new ArrayList<String>();for (String handle : driver.getWindowHandles()){windows.add(handle);}driver.switchTo().window(windows.get(i));}}
WebTestListener1.java 监听器1,监听所有测试用例执行后的执行结果
package com.webtest.core;import java.io.IOException;
import java.util.List;import org.testng.ITestContext;
import org.testng.ITestNGMethod;
import org.testng.ITestResult;
import org.testng.TestListenerAdapter;public class WebTestListener1 extends TestListenerAdapter {@Overridepublic void onFinish(ITestContext testContext) {// TODO Auto-generated method stub
// super.onFinish(testContext);
// 打印出所有的测试用例数目ITestNGMethod[] methods=this.getAllTestMethods();System.out.println("一共执行了:"+methods.length);// 成功的/失败的测试用例名称和数目List<ITestResult> failList=this.getFailedTests();int len=failList.size();System.out.println("失败的测试用例:"+len);for(int i=0;i<len;i++) {ITestResult tr=failList.get(i);System.out.println(tr.getInstanceName()+":"+tr.getName()+"失败了");}}
}
WebTestListener1.java 监听器2,监听所有失败测试用例截屏
package com.webtest.core;import java.io.IOException;
import java.util.List;import org.testng.ITestContext;
import org.testng.ITestNGMethod;
import org.testng.ITestResult;
import org.testng.TestListenerAdapter;
/*** 失败的测试用例,进行截屏*/
public class WebTestListener2 extends TestListenerAdapter {@Overridepublic void onTestFailure(ITestResult tr) {// 失败的测试用例截屏BaseTest tb = (BaseTest) tr.getInstance();SeleniumScreenShot screenShot = new SeleniumScreenShot(tb.getDriver());screenShot.screenShot();System.out.println("onTestFailure:" + tr.getInstanceName() + ":" + tr.getName() + "失败了");}}
demo-测试用例包
Front_Login1.java测试用例类
package com.webtest.demo;import static org.testng.Assert.assertTrue;import org.testng.annotations.Test;import com.webtest.core.BaseTest;public class Front_Login1 extends BaseTest {@Testpublic void test_login_success() {webtest.open("/");webtest.click("link=登录");webtest.type("name=username","qingdao01");webtest.type("name=password","123456");webtest.click("xpath=//input[@value='马上登录']");assertTrue(webtest.isDisplayed("link=退出"));}
}
dataprovider-数据驱动包
ExcelDataProvider.java-读取excel
package com.webtest.dataprovider;import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;public class ExcelDataProvider {public Object[][] getTestDataByExcel(String fileName, String sheetName)throws IOException {File file = new File(fileName);FileInputStream inputstream = new FileInputStream(file);Workbook wbook = null;String fileExtensionName = fileName.substring(fileName.indexOf("."));System.out.println(fileExtensionName);if (fileExtensionName.equals(".xlsx")) {wbook = new XSSFWorkbook(inputstream);} else if (fileExtensionName.equals(".xls")) {wbook = new HSSFWorkbook(inputstream);}Sheet sheet = wbook.getSheet(sheetName);int rowCount = sheet.getLastRowNum() - sheet.getFirstRowNum();List<Object[]> records = new ArrayList<Object[]>();for (int i = 1; i < rowCount + 1; i++) {Row row = sheet.getRow(i);String fields[] = new String[row.getLastCellNum()];for (int j = 0; j < row.getLastCellNum(); j++) {fields[j] = row.getCell(j).getStringCellValue();}records.add(fields);}Object[][] results = new Object[records.size()][];for (int i = 0; i < records.size(); i++) {results[i] = records.get(i);}return results;}}
MysqlDataProvider.java-读取sql
package com.webtest.dataprovider;import java.io.IOException;
import java.sql.*;import java.util.ArrayList;
import java.util.List;import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;public class MysqlDataProvider {public Object[][] getTestDataByMysql(String sql) {String url = "jdbc:mysql://127.0.0.1:3306/mymovie";List<Object[]> records = new ArrayList<Object[]>();try {Class.forName("com.mysql.jdbc.Driver");Connection conn = DriverManager.getConnection(url, "root", "123456");if (!conn.isClosed()) {System.out.println("连接数据库");}Statement stmt = conn.createStatement();ResultSet rs = stmt.executeQuery(sql);ResultSetMetaData rsMetaData = rs.getMetaData();int cols = rsMetaData.getColumnCount();System.out.println(cols);while (rs.next()) {String fields[] = new String[cols];int col=0;for (int i = 0; i < cols; i++) {fields[col] = rs.getString(i+1);col++;}records.add(fields);}rs.close();conn.close();} catch (ClassNotFoundException e) {// TODO Auto-generated catch blocke.printStackTrace();} catch (SQLException e) {// TODO Auto-generated catch blocke.printStackTrace();}Object[][] results = new Object[records.size()][];for (int i = 0; i < records.size(); i++) {results[i] = records.get(i);}return results;}}
TxtDataProvider.java
package com.webtest.dataprovider;import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;import org.testng.annotations.DataProvider;
import org.testng.annotations.Test;public class TxtDataProvider {public Object[][] getTxtUser(String fileName) throws IOException {List<String> dataList = new ArrayList<String>();File file = new File(fileName);FileInputStream fis = new FileInputStream(file);InputStreamReader isr= new InputStreamReader(fis);BufferedReader reader = new BufferedReader(isr);int cols=reader.readLine().split("\t").length;String readData;while((readData=reader.readLine())!=null) {dataList.add(readData);}Object [][] result = new Object[dataList.size()][cols];String [] arrays;for(int i=0;i<dataList.size();i++) {arrays=dataList.get(i).split("\t");for(int j=0;j<cols;j++)result[i][j]=arrays[j];}return result;}}
data-数据文件夹
user.txt-存放用户名和密码
username password
qingdao01 123456
qingdao02 123456
conf-配置文件夹
config.properties
gecko_driver=D:\\demo\\demo1\\geckodriver.exe
firefox_path=C:\\Program Files\\Mozilla Firefox\\firefox.exe
chrome_path=D:\\demo\\chromedriver.exe
driverType=firefox
base_url=http://localhost:8032/mymovie
conf_root=conf/
data_root=data/
object_root=object/
host=localhost
port=4444
screen_name=D:\\edutest\\screenshot
ie_path=D:\\demo\\IEDriverServer.exe
output_directory=test-output
enable_email=true
timeout = 3000
tomail=124434@qq.com,232324@qq.com,121213@qq.com
libs-导入jar包
log4j2.xml日志打印格式
<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="warn"><Appenders><Console name="Console" target="SYSTEM_ERR"><PatternLayout pattern="[%-5p] %d %c - %m%n" /></Console><File name="File" fileName="dist/my.log"><PatternLayout pattern="[%-5p] %d %c - %m%n" /></File></Appenders><Loggers><Root level="info"><AppenderRef ref="File" /><AppenderRef ref="Console" /></Root></Loggers>
</Configuration>
常见异常
org.openqa.selenium.NoSuchElementException
- 定位方式是不是写错了?
- 是不是页面还未加载完?使用Thread.sleep(3000);//等待浏览器加载
- 是不是存在多个窗口?使用switchTo().window(s) 尝试切换窗口
- 是不是存在子页面?例如iframe中,使用switchTo(). frame(String nameOrId);进行切换
- div嵌套太多,建议尝试用键盘鼠标事件action.clickAndHold().moveByOffset(x, y).release().perform();
- 是不是页面太长,尝试向下移动滚动条
UI自动化测试框架的进阶构成
- utils包:实现测试过程中调用的工具类方法,例如:文件操作、mapObject、页面对象的操作方法
- appModules包主要用于实现复用的业务逻辑封装方法
- pageObjects包:用于实现被测试的页面对象
- testCases 包 :具体的测试方法
- dataprovider包:提供数据驱动的类,txt驱动,excel驱动,数据库的驱动
utils包:实现测试过程中调用的工具类方法,例如:文件操作、mapObject、页面对象的操作方法
Log.java
package com.edu.utils;import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;public class Log {static Logger logger =LogManager.getLogger();public static void fatal(String msg) {logger.fatal(msg);}public static void error(String msg) {logger.error(msg);}public static void warn(String msg) {logger.warn(msg);}public static void info(String msg) {logger.info(msg);}public static void debug(String msg) {logger.debug(msg);}
}
ObjectMap.java
package com.edu.utils;import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;import org.openqa.selenium.By;
import org.testng.annotations.Test;public class ObjectMap {Properties prop = null;public ObjectMap(String propFile) {prop = new Properties();FileInputStream in;try {in = new FileInputStream(propFile);prop.load(in);in.close();} catch (IOException e) {e.printStackTrace();}}public By getlocator(String ElementNameInProp) throws Exception {String locator = prop.getProperty(ElementNameInProp);System.out.println(locator);String locatorType = locator.split(":")[0];String locatorValue1 = locator.split(":")[1];String locatorValue = new String(locatorValue1.getBytes("ISO8859-1"), "UTF-8");if (locatorType.toLowerCase().equals("id"))return By.id(locatorValue);else if (locatorType.toLowerCase().equals("name"))return By.name(locatorValue);else if (locatorType.toLowerCase().equals("tag"))return By.tagName(locatorValue);else if (locatorType.toLowerCase().equals("class"))return By.className(locatorValue);else if (locatorType.toLowerCase().equals("css"))return By.cssSelector(locatorValue);else if (locatorType.toLowerCase().equals("link"))return By.linkText(locatorValue);else if (locatorType.toLowerCase().equals("xpath"))return By.xpath(locatorValue);elsethrow new Exception("元素找不到" + locatorType);}}
ReadProperties.java
package com.edu.utils;import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.Properties;import org.testng.annotations.Test;public class ReadProperties {public static final String filePath="conf/conf.properties";public static String getPropertyValue(String key) throws IOException {Properties prop = new Properties();FileInputStream fis = new FileInputStream(filePath);prop.load(fis);fis.close();return prop.getProperty(key);}
}
appModules包主要用于实现复用的业务逻辑封装方法
Login_Action.java
package com.edu.appModules;import org.openqa.selenium.WebDriver;import com.edu.pageObjects.AddMessagePage;
import com.edu.utils.ReadProperties;
//test www.baidu-test.com/login.html
//beta www.baidu-beta.com/login.html
//live www.baidu.com/login.html
public class AddMessage_Action {public static void addMessage(WebDriver wd,String message) throws Exception {String base_url=ReadProperties.getPropertyValue("baseUrl");AddMessagePage ap = new AddMessagePage(wd);wd.get(base_url+"/index.php/Detail/index/id/39");ap.getTxtArea().sendKeys(message);ap.getSubmit().click();Thread.sleep(3000);}}
AddMessage_Action.java
package com.edu.appModules;import org.openqa.selenium.WebDriver;import com.edu.pageObjects.AddMessagePage;
import com.edu.utils.ReadProperties;
//test www.baidu-test.com/login.html
//beta www.baidu-beta.com/login.html
//live www.baidu.com/login.html
public class AddMessage_Action {public static void addMessage(WebDriver wd,String message) throws Exception {String base_url=ReadProperties.getPropertyValue("baseUrl");AddMessagePage ap = new AddMessagePage(wd);wd.get(base_url+"/index.php/Detail/index/id/39");ap.getTxtArea().sendKeys(message);ap.getSubmit().click();Thread.sleep(3000);}}
pageObjects包:用于实现被测试的页面对象
LoginPage.java
package com.edu.pageObjects;import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;import com.edu.utils.ObjectMap;public class LoginPage {public WebElement element;public WebDriver driver;ObjectMap objMap = new ObjectMap("ObjectMap/login.properties");public LoginPage(WebDriver wd) {this.driver = wd;}public WebElement getLink() throws Exception {this.element =driver.findElement(objMap.getlocator("login.link"));return element;}public WebElement getUsername() throws Exception {this.element =driver.findElement(objMap.getlocator("login.name"));return element;}public WebElement getPassword() throws Exception {this.element =driver.findElement(objMap.getlocator("login.password"));return element;}public WebElement getSubmitBtn() throws Exception {this.element =driver.findElement(objMap.getlocator("login.submit"));return element;}}
AddMessagePage.java
package com.edu.pageObjects;import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;import com.edu.utils.ObjectMap;public class AddMessagePage {public WebElement element;public WebDriver driver;ObjectMap objMap = new ObjectMap("ObjectMap/addmessage.properties");public AddMessagePage(WebDriver wd) {this.driver = wd;}public WebElement getTxtArea() throws Exception {this.element =driver.findElement(objMap.getlocator("addmessage.textarea"));return element;}public WebElement getSubmit() throws Exception {this.element =driver.findElement(objMap.getlocator("addmessage.submit"));return element;}
}
testCases 包 :具体的测试方法
LoginTest.java
package com.edu.testCases;import org.testng.Assert;
import org.testng.annotations.Test;import com.edu.appModules.Login_Action;
import com.edu.core.BaseTest;
import com.edu.dataprovider.NsDataProvider;
import com.edu.utils.Log;public class LoginTest extends BaseTest{@Test(dataProvider="txt",dataProviderClass=NsDataProvider.class)public void loginSuccess(String u_name,String password) {try {Login_Action.login(driver,u_name,password);Log.info("success");} catch (Exception e) {// TODO Auto-generated catch blocke.printStackTrace();Log.error("fail");}Assert.assertTrue(ifContains("�˳�"));}@Testpublic void loginFail() throws Exception {Login_Action.login(driver,"qingdao01","qing1111");Assert.assertTrue(ifContains("�û����������"));}
}
AddMessageTest.java
package com.edu.testCases;import org.testng.annotations.Test;import com.edu.appModules.AddMessage_Action;
import com.edu.appModules.Login_Action;
import com.edu.core.BaseTest;public class AddMessageTest extends BaseTest{@Testpublic void addMessageSuccess() throws Exception {Login_Action.login(driver, "qingdao01", "123456");String message="增加成功";AddMessage_Action.addMessage(driver, message);}@Testpublic void addMessageFail() throws Exception {Login_Action.login(driver, "qingdao01", "123456");String message="";AddMessage_Action.addMessage(driver, message);}}
dataprovider包:提供数据驱动的类,txt驱动,excel驱动,数据库的驱动
core:游览器启动、table元素读取
BaseTest.java
package com.edu.core;import java.io.IOException;import org.openqa.selenium.WebDriver;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.testng.annotations.AfterClass;
import org.testng.annotations.AfterSuite;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.BeforeSuite;import com.edu.utils.Log;
import com.edu.utils.ReadProperties;public class BaseTest {public WebDriver driver = null;@BeforeClasspublic void startBrowser() throws InterruptedException, IOException {String firefox_driver = ReadProperties.getPropertyValue("gecko_driver");String firefox_path = ReadProperties.getPropertyValue("firefox_path");System.setProperty("webdriver.gecko.driver", firefox_driver);System.setProperty("webdriver.firefox.bin", firefox_path);driver = new FirefoxDriver();Log.info("打开浏览器");driver.get("http://localhost:8032/mymovie");Thread.sleep(3000);}// @AfterSuite
// public void quitBrowser() {
// this.driver.quit();
// }public boolean ifContains(String content) {return driver.getPageSource().contains(content);}
}
Table.java
package com.edu.core;import java.util.List;import org.openqa.selenium.By;
import org.openqa.selenium.WebElement;public class Table {WebElement table;public Table(WebElement table) {this.table=table;}public int getRowCount() {List<WebElement> rows = this.table.findElements(By.tagName("tr"));return rows.size();}public int getCollCount() {List<WebElement> rows = this.table.findElements(By.tagName("tr"));return rows.get(0).findElements(By.tagName("td")).size();}public WebElement getCell(int row,int col){List<WebElement> rows = this.table.findElements(By.tagName("tr"));WebElement currentRow=rows.get(row-1);List<WebElement> cols = currentRow.findElements(By.tagName("td"));WebElement currentCell=cols.get(col-1);return currentCell;}}