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.mzph.cn/news/626317.shtml

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

相关文章

【分布式技术】监控技术zabbix实操

目录 一、脚本监控nginx的连接状态 步骤一&#xff1a;做好nginx的配置 步骤二&#xff1a;完成监控数据脚本编写&#xff0c;并使用zabbix_get测试 步骤三&#xff1a;在zabbix agent配置目录中&#xff0c;编写以conf结尾的用户参数文件 步骤四&#xff1a;在zabbix web…

Python 网络编程之TCP详细讲解

【一】传输层 【1】概念 传输层是OSI五层模型中的第四层&#xff0c;负责在网络中的两个端系统之间提供数据传输服务主要协议包括**TCP&#xff08;传输控制协议&#xff09;和UDP&#xff08;用户数据报协议&#xff09;** 【2】功能 **端到端通信&#xff1a;**传输层负责…

HackerGPTWhiteRabbitNeo的使用及体验对比

1. 简介 WhiteRabbitNeo&#xff08;https://www.whiterabbitneo.com/&#xff09;是基于Meta的LLaMA 2模型进行特化的网络安全AI模型。通过专门的数据训练&#xff0c;它在理解和生成网络安全相关内容方面具有深入的专业能力&#xff0c;可广泛应用于教育、专业培训和安全研究…

什么是非电离辐射与电离辐射?

摘要: 非电离辐射和电离辐射是两种不同类型的辐射&#xff0c;它们主要区别在于能量水平和与物质相互作用的方式。 非电离辐射 非电离辐射是指能量较低&#xff0c;不足以使原子或分子的电子脱离其原子核束缚而产生电离现象的电磁波。这类辐射不 ... 非电离辐射和电离辐射是两…

Centos 更换内核

文章目录 一、查看/更换系统内核1.1 查看当前运行环境的内核1.2 查看系统上所有可用内核1.3 切换内核方法一&#xff1a;通过启动菜单更换内核方法二&#xff1a;更换默认启动内核 二、安装内核2.1 使用ELRepo安装2.2 安装指定内核版本参考资料 一、查看/更换系统内核 1.1 查看…

docker搭建SSH镜像、systemctl镜像、nginx镜像、tomcat镜像

目录 一、SSH镜像 二、systemctl镜像 三、nginx镜像 四、tomcat镜像 五、mysql镜像 一、SSH镜像 1、开启ip转发功能 vim /etc/sysctl.conf net.ipv4.ip_forward 1sysctl -psystemctl restart docker 2、 cd /opt/sshd/vim Dockerfile 3、生成镜像 4、启动容器并修改ro…

面试题:你知道 Spring lazy-init 懒加载的原理吗?

文章目录 前言一、先睹为快二、原理分析三、总结 前言 普通的bean的初始化是在容器启动初始化阶段执行的&#xff0c;而被lazy-init修饰的bean 则是在从容器里第一次进行context.getBean(“”)时进行触发。 Spring 启动的时候会把所有bean信息(包括XML和注解)解析转化成Spring…

这可能是最全面的Java并发编程八股文了

内容摘自我的学习网站&#xff1a;topjavaer.cn 分享50道Java并发高频面试题。 线程池 线程池&#xff1a;一个管理线程的池子。 为什么平时都是使用线程池创建线程&#xff0c;直接new一个线程不好吗&#xff1f; 嗯&#xff0c;手动创建线程有两个缺点 不受控风险频繁创…

SpringBoot基础:一步步创建SpringBoot工程

摘要 本文介绍了&#xff0c;从零开始创建SpringBoot工程&#xff0c;且在每一步给出分析和原因。创建maven – 转Springboot – 引入jdbc – 引入数据库操作框架&#xff0c;最后给出了不同场景指定不同配置文件的方案。 背景 为什么要使用SpringBoot工程&#xff1f; 使用Sp…

Python 网络编程之粘包问题

【一】粘包问题介绍 【1】粘包和半包 粘包&#xff1a; 定义&#xff1a; 粘包指的是发送方发送的若干个小数据包被接收方一次性接收&#xff0c;形成一个大的数据包。原因&#xff1a; 通常是因为网络底层对数据传输的优化&#xff0c;将多个小数据包组合成一个大的数据块一次…

Linux搭建和使用redis

官网地址&#xff1a;http://redis.io/download 文件上传到服务器 tar包解压 tar zxvf redis-5.0.14.tar.gz安装 进入解压目录下&#xff0c;找到Makefile所在目录&#xff0c;执行make命令 make执行之后&#xff0c;会产生src等目录&#xff0c;进入执行make install命令…

locust快速入门--使用分布式提高测试压力

背景&#xff1a; 使用默认的locust启动命令进行压测时&#xff0c;尽管已经将用户数设置大比较大&#xff08;400&#xff09;&#xff0c;但是压测的时候RPS一直在100左右。需要增加压测的压力。 问题原因&#xff1a; 如果你是通过命令行启动的或者参考之前文章的启动方式…

【论文阅读】Speech Driven Video Editing via an Audio-Conditioned Diffusion Model

DiffusionVideoEditing&#xff1a;基于音频条件扩散模型的语音驱动视频编辑 code&#xff1a;GitHub - DanBigioi/DiffusionVideoEditing: Official project repo for paper "Speech Driven Video Editing via an Audio-Conditioned Diffusion Model" paper&#…

第十讲 单片机驱动彩色液晶屏 控制RA8889软件:图像运算

单片机驱动TFT彩色液晶屏系列讲座 目录 第一讲 单片机最小系统STM32F103C6T6通过RA8889驱动彩色液晶屏播放视频 第二讲 单片机最小系统STM32F103C6T6控制RA8889驱动彩色液晶屏硬件框架 第三讲 单片机驱动彩色液晶屏 控制RA8889软件:如何初始化 第四讲 单片机驱动彩色液晶屏 控…

大模型理论基础1

大模型理论基础1 第一章&#xff1a;引言 语言模型 自回归语言模型 概率的链式法则&#xff1a; 在自回归语言模型 p 中生成整个序列 X1:L&#xff0c;我们需要一次生成一个令牌(token)&#xff0c;该令牌基于之前以生成的令牌进行计算获得&#xff1a; 其中T≥0 是一个控…

Java 日志体系泣血总结

目录 一. 前言 二. Log 日志体系 2.1. 背景/发展史 2.2. 关系/依赖 2.2.1. JCL&#xff08;Jakarta Commons Logging&#xff09; 2.2.2. SLF4J 2.2.3. SLF4J 的适配 2.2.4. Spring 统一输出 三. 总结 一. 前言 本文的目的是搞清楚 Java 中各种日志 Log 之间是怎样的关…

【深入理解 ByteBuf 之三 接口类拆解】2. Recycler 接口设计真正的回收机制

Recycler 回收器接口设计 本节接着 ObjectPool 的设计脉络&#xff0c;具体看看其具体实现 RecyclerObjectPool 中引用的 Recycler 究竟是怎么实现的 这一张图基本已经说明白了&#xff0c;我再做个总结&#xff0c;对细节感兴趣的可以看看我下面带源码的注释。 对于 Recycle…

2023.1.15 关于 Redis 持久化 RDB 策略详解

目录 Redis 持久化 Redis 实现持久化的两大策略 RDB 策略 手动触发 save 命令 bgsave 命令 bgsave 命令执行流程 自动触发 rdb 文件 实例演示一 实例演示二 实例演示三 实例演示四 RDB 策略的优缺点 Redis 持久化 什么是持久化&#xff1f; 回答&#xff1a; 将数据存…

SeaTunnel 海量数据同步工具的使用(连载中……)

一、概述 SeaTunnel 是一个非常易用&#xff0c;高性能、支持实时流式和离线批处理的海量数据处理产品&#xff0c;前身是 WaterDrop &#xff08;中文名&#xff1a;水滴&#xff09;&#xff0c;自 2021年10月12日更名为 SeaTunnel 。2021年12月9日&#xff0c;SeaTunnel 正式…

【Linux】Linux系统编程——pwd命令

文章目录 1.命令概述2.命令格式3.常用选项4.相关描述5.参考示例 1.命令概述 pwd&#xff08;Print Working Directory&#xff09;命令用于显示用户当前工作目录的完整路径。这是一个常用的命令&#xff0c;帮助用户确定他们目前所在的目录位置。 2.命令格式 基本的 pwd 命令…