UI自动化测试框架

文章目录

    • 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自动化测试框架的作用

  1. 能够有效组织和管理测试用例
  2. 将基础的代码封装,降低测试脚本编写的复杂性和重复性
  3. 提高测试脚本维护和修改的效率
  4. 自动执行测试脚本,并自动发布测试报告,为持续集成的开发方式提供脚本支持
  5. 让不具备编程能力的测试工程师开展自动化测试工作

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;}}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/412909.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

前端框架前置学习Node.js(2)npm使用,Node.js总结

npm - 软件包管理器 定义 npm是Node.js标准的软件包管理器 npm仓库中包含大量软件包,使其成为世界上最大的单一语言代码仓,并且可以确定几乎可用于一切的软件包 最初是为了下载和管理Node.js包依赖的方式,但其现在已成为前端JavaScript中使用的工具 使用: 1.初始化清单文…

【华为 ICT HCIA eNSP 习题汇总】——题目集3

1、&#xff08;多选&#xff09;IEEE 802.11n支持在哪些频率下工作&#xff1f; A、2.5GHz B、2.4GHz C、5GHz D、6GHz 考点&#xff1a;无线局域网 解析&#xff1a;&#xff08;BC&#xff09; IEEE 820.11n 支持双频段&#xff0c;它兼容IEEE 802.11a 与IEEE 820.11b 两种标…

加解密算法整理(对称加密、非堆成加密、散列函数)

加解密算法是现代密码学核心技术&#xff0c;从设计理念和应用场景上可以分为两大基本类型&#xff0c;如下表所示。 算法类型特点优势缺陷代表算法对称加密加解密的密钥相同计算效率高&#xff0c;加密强度高需提前共享密钥&#xff0c;易泄露DES、3DES、AES、IDEA非对称加密…

【vsan数据恢复】vsan逻辑架构出现故障的数据恢复案例

VSAN数据恢复环境&#xff1a; 一套有三台服务器节点的VSAN超融合基础架构&#xff0c;每台服务器节点上配置2块SSD硬盘和4块机械硬盘。 每个服务器节点上配置有两个磁盘组&#xff0c;每个磁盘组使用1个SSD硬盘作为缓存盘&#xff0c;2个机械硬盘作为容量盘。三台服务器节点上…

全面了解SSD,SSD关键术语全面解析

在前文《深入了解一下SSD的相关内容》一文中我们介绍了SSD硬盘的内部结构和存储颗粒的读写特性。本文我们将进一步深入存储颗粒,介绍其中内部的更多细节以及与此相关的一些术语。 我们继续深入到SSD的内部,SSD闪存颗粒分为NAND和NOR等不同的种类,目前SSD硬盘以NAND为主。NA…

多输入多输出 | Matlab实现基于LightGBM多输入多输出预测

多输入多输出 | Matlab实现基于LightGBM多输入多输出预测 目录 多输入多输出 | Matlab实现基于LightGBM多输入多输出预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 Matlab实现基于LightGBM多输入多输出预测&#xff08;完整源码和数据&#xff09; 1.data为数据集&a…

Umi3 创建,配置环境,路由传参(代码示例)

目录 创建项目 配置环境 创建脚手架 项目结构及其目录、 路由 配置路由 嵌套路由 编程式导航和声明式导航 声明式导航 编程式导航 约定式路由 路由传参 query传参&#xff08;问号&#xff09; 接收参数 params传参&#xff08;动态传参&#xff09; 接收参数 创…

领域特定语言(Domain-Specific Language, DSL)在 Visual Studio 2022中的实验——建立领域模型

一、环境 dotnet --version 8.0.101 Microsoft Visual Studio Enterprise 2022 (64 位) - Current 版本 17.8.4 已安装组件 ComponentLinkVisual Studiohttp://go.microsoft.com/fwlink/?LinkId185579Visual Studio SDKhttps://go.microsoft.com/fwlink/?li…

Blender——将模型及其所有纹理与材质导入unity

前期准备 参考视频&#xff1a;7分钟教会你如何将Blender的模型材质导入unity_哔哩哔哩_bilibili 实验模型官网下载地址&#xff1a;Hoi An Ancient House Model free VR / AR / low-poly 3D model CSDN下载链接&#xff1a; 【免费】Blender三维模型-古代房屋模型&#xff…

css实现动态水波纹效果

效果如下&#xff1a; 外层容器 (shop_wrap)&#xff1a; 设置外边距 (padding) 提供一些间距和边距 圆形容器 (TheCircle)&#xff1a; 使用相对定位 (position: relative)&#xff0c;宽度和高度均为 180px&#xff0c;形成一个圆形按钮圆角半径 (border-radius) 设置为 50%&…

Eureka 本机集群实现

距离上次发布博客已经一年多了&#xff0c;主要就是因为考研&#xff0c;没时间学习技术的内容&#xff0c;现在有时间继续完成关于代码方面的心得&#xff0c;希望跟大家分享。 今天在做一个 Eureka 的集群实现&#xff0c;我是在本电脑上跑的&#xff0c;感觉这个挺有意思&a…

网工每日一练(1月15日)

1.某计算机系统由下图所示的部件构成&#xff0c;假定每个部件的千小时可靠度为R&#xff0c;则该系统的千小时的可靠度为 ( D ) 。 2.以下IP地址中&#xff0c;属于网络 201.110.12.224/28 的主机IP是&#xff08; B &#xff09;。 A.201.110.12.224 B.201.110.12.238 C.20…