结构
common
package com.sa.testng.common;
import com.sa.testng.test.TestConfig;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
/**
* 描述:excel事件处理
*
* @author Keyba
*/
@Component
public class ExcelTool {
/**
* 读取excel文件中的数据,并生成数组
*/
private final TestConfig testConfig;
@Autowired
public ExcelTool(TestConfig testConfig) {
this.testConfig = testConfig;
}
/**
* @SuppressWarnings("deprecation")
*/
public Object[][] readExcel(String sheetName) throws IOException {
// 读数据
InputStream fileInputStream = new FileInputStream(testConfig.getFilePath());
XSSFWorkbook workbook = new XSSFWorkbook(fileInputStream);
//读取指定标签页的数据
XSSFSheet sheet = workbook.getSheet(sheetName);
//获取行数(获取的是物理行数,也就是不包括那些空行(隔行)的情况)
int rowNum = sheet.getPhysicalNumberOfRows();
//获取列数
int columnNum = sheet.getRow(0).getPhysicalNumberOfCells();
//因为第一行作为字段名,不需要记录,所以只有[rowNum-1]行
Object[][] data = new Object[rowNum - 1][columnNum];
for (int i = 1; i < rowNum; i++) {
for (int h = 0; h < columnNum; h++) {
//先把类型设置为string
sheet.getRow(i).getCell(h).setCellType(Cell.CELL_TYPE_STRING);
//填充数组
data[i - 1][h] = sheet.getRow(i).getCell(h).getStringCellValue();
}
}
workbook.close();
return data;
}
}
ScreenShotOnFailure
package com.sa.testng.common;
import java.io.File;
import java.io.IOException;
import java.nio.file.Paths;
import org.apache.commons.io.FileUtils;
import org.openqa.selenium.OutputType;
import org.openqa.selenium.TakesScreenshot;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
class ScreenShotOnFailure {
private final static String SCREEN_SHOT_PATH = "test-output/screen-shot";
private static String SCREEN_SHOT_NAME = null;
private static TestWebDriver testWebDriver;
@Autowired
public ScreenShotOnFailure(TestWebDriver testWebDriver) {
ScreenShotOnFailure.testWebDriver = testWebDriver;
}
static void takeScreenShot() throws IOException {
File screenShotDir = new File(SCREEN_SHOT_PATH);
if (!screenShotDir.exists()) {
screenShotDir.mkdirs();
}
SCREEN_SHOT_NAME = System.currentTimeMillis() + ".jpg";
File screenFile = ((TakesScreenshot) testWebDriver.getWebDriver()).getScreenshotAs(OutputType.FILE);
File savedFile = new File(Paths.get(SCREEN_SHOT_PATH, SCREEN_SHOT_NAME).toString());
FileUtils.copyFile(screenFile, savedFile);
testWebDriver.stopWebDrover();
}
static String getScreenShotPath() {
return SCREEN_SHOT_PATH;
}
static String getScreenShotName() {
return SCREEN_SHOT_NAME;
}
}
TestNGRetryListener
package com.sa.testng.common;
import org.springframework.stereotype.Component;
import org.testng.ITestContext;
import org.testng.ITestListener;
import org.testng.ITestResult;
import java.io.IOException;
/**
* @author Keyba
*/
@Component
public class TestNGRetryListener implements ITestListener {
@Override
public void onTestFailure(ITestResult result) {
try {
ScreenShotOnFailure.takeScreenShot();
System.out.println(result.getMethod().getMethodName() + " failed, the screenshot saved in "
+ ScreenShotOnFailure.getScreenShotPath() + " screenshot name : "
+ ScreenShotOnFailure.getScreenShotName());
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void onTestStart(ITestResult result) {
// TODO Auto-generated method stub
}
@Override
public void onTestSuccess(ITestResult result) {
// TODO Auto-generated method stub
}
@Override
public void onTestSkipped(ITestResult result) {
// TODO Auto-generated method stub
}
@Override
public void onTestFailedButWithinSuccessPercentage(ITestResult result) {
// TODO Auto-generated method stub
}
@Override
public void onFinish(ITestContext iTestContext) {
}
@Override
public void onStart(ITestContext context) {
// TODO Auto-generated method stub
}
}
TestWebDriver
package com.sa.testng.common;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.springframework.stereotype.Component;
/**
* @author Keyba
*/
@Component
public class TestWebDriver {
private static WebDriver driver;
TestWebDriver() {
}
public WebDriver getWebDriver() {
System.setProperty("webdriver.chrome.driver", "D:\\dl\\chromedriver.exe");
driver = new ChromeDriver();
driver.manage().window().maximize();
driver.navigate().to("http://www.baidu.com");
return driver;
}
void stopWebDrover() {
driver.quit();
}
}
config
package com.sa.testng.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @author Keyba
*/
@Configuration
@ConfigurationProperties(prefix = "url")
public class UrlConfig {
private String loginUrl;
public String getLoginUrl() {
return loginUrl;
}
}
action
BaseAction
package com.sa.testng.config;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @author Keyba
*/
@Configuration
@ConfigurationProperties(prefix = "url")
public class UrlConfig {
private String loginUrl;
public String getLoginUrl() {
return loginUrl;
}
}
LoginPageAction
package com.sa.testng.libarary.action;
import com.sa.testng.libarary.base.mall.MallType;
import com.sa.testng.libarary.base.user.User;
import com.sa.testng.libarary.page.login.LoginPage;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author Keyba
*/
@Service
public class LoginPageAction extends BaseAction {
private final LoginPage loginPage;
@Autowired
public LoginPageAction(LoginPage loginPage) {
this.loginPage = loginPage;
}
public void login(User user, MallType mallType) throws Exception {
loginPage.chooseMall(mallType);
loginPage.inputUser(user.getName());
loginPage.inputPassword(user.getPassword());
loginPage.inputCaptcha("888888");
loginPage.clickLoginButton();
}
}
page
LoginPage
package com.sa.testng.libarary.page.login;
import com.sa.testng.config.UrlConfig;
import com.sa.testng.libarary.base.mall.MallType;
import com.sa.testng.libarary.page.BasePage;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.CacheLookup;
import org.openqa.selenium.support.FindBy;
import org.openqa.selenium.support.PageFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
/**
* @author Keyba
*/
@Repository
public class LoginPage extends BasePage {
private final
UrlConfig urlConfig;
@Autowired
LoginPage(UrlConfig urlConfig) {
super();
this.urlConfig = urlConfig;
PageFactory.initElements(driver, this);
driver.navigate().to(this.urlConfig.getLoginUrl());
}
@FindBy(xpath = "//div[@class=\"el-radio-group\"]/label[1]")
@CacheLookup
private WebElement productMallRadio;
@FindBy(xpath = "//div[@class=\"el-radio-group\"]/label[2]")
@CacheLookup
private
WebElement materivalMallRadio;
@FindBy(xpath = "//div[@class=\"el-radio-group\"]/label[3]")
@CacheLookup
private
WebElement thirdPartyRadio;
@FindBy(xpath = "//*[@id=\"app\"]/div/main/div/div[2]/div[5]/div/div/div[2]/input")
@CacheLookup
private
WebElement userName;
@FindBy(xpath = "//div[@class=\"password\"]/input")
@CacheLookup
private
WebElement password;
@FindBy(xpath = "//input[@class=\"digital-patchca-input\"]")
@CacheLookup
private
WebElement captcha;
@FindBy(linkText = "登录")
@CacheLookup
private
WebElement loginButton;
public void chooseMall(MallType mallType) throws Exception {
switch (mallType) {
case ThreeParties:
thirdPartyRadio.click();
break;
case Material:
materivalMallRadio.click();
break;
case Product:
productMallRadio.click();
break;
default:
throw new Exception("商城类型错误");
}
}
public void inputUser(String userName) {
this.userName.sendKeys(userName);
}
public void inputPassword(String password) {
this.password.sendKeys(password);
}
public void inputCaptcha(String captcha) {
this.captcha.sendKeys(captcha);
}
public void clickLoginButton() {
this.loginButton.click();
}
}
BasePage
package com.sa.testng.libarary.page;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.springframework.stereotype.Repository;
import java.util.concurrent.TimeUnit;
/**
* @author Keyba
*/
@Repository
public class BasePage {
public WebDriver driver;
public BasePage() {
System.setProperty("webdriver.chrome.driver", "E:\\CODE\\SaTestNG\\src\\main\\java\\com\\sa\\testng\\libarary\\tools\\chromedriver.exe");
driver = new ChromeDriver();
driver.manage().window().maximize();
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
driver.manage().deleteAllCookies();
}
}
test
TestConfig
package com.sa.testng.test;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @author Keyba
*/
@Configuration
@ConfigurationProperties(prefix = "app")
public class TestConfig {
public int getConfig() {
return config;
}
public void setConfig(int config) {
this.config = config;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
private int config;
private String filePath;
}
TestService
package com.sa.testng.test;
/**
* @author Keyba
*/
public interface TestService {
/**
* invokeService
* @return int
*/
int invokeService();
}
TestServieImpl
package com.sa.testng.test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@Service
public class TestServiceImpl implements TestService {
private final TestConfig testConfig;
@Autowired
public TestServiceImpl(TestConfig testConfig) {
this.testConfig = testConfig;
}
@Override
public int invokeService() {
System.out.println("invokeService");
return testConfig.getConfig();
}
}
Appication
package com.sa;
import com.sa.testng.test.TestConfig;
import com.sa.testng.config.UrlConfig;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
@SpringBootApplication
@EnableConfigurationProperties({UrlConfig.class, TestConfig.class})
public class Application {
public static void main(String[] args) {
// 程序启动入口
// 启动嵌入式的 Tomcat 并初始化 Spring 环境及其各 Spring 组件
SpringApplication.run(Application.class, args);
}
}
application.properties
app.config=1
excelFile=E:\\CODE\\JAVA\\SaTestNGProj\\src\\main\\resources\\test01.xlsx
test
testng.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Default suite">
<listeners>
<listener class-name="com.sa.testng.common.TestNGRetryListener"/>
</listeners>
<test verbose="2" name="Default test">
<groups>
<define name="testGroup01">
<include name="P1"/>
<include name="P2"/>
</define>
<run>
<include name="testGroup01"/>
</run>
</groups>
<classes>
<class name="com.sa.testng.TestServiceTest"/>
</classes>
</test> <!-- Default test -->
</suite> <!-- Default suite -->
TestServiceTest
package com.sa.testng;
import com.sa.Application;
import com.sa.testng.common.ExcelTool;
import com.sa.testng.libarary.action.LoginPageAction;
import com.sa.testng.libarary.base.mall.MallType;
import com.sa.testng.libarary.base.user.Supplier;
import com.sa.testng.libarary.base.user.User;
import com.sa.testng.test.TestService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.testng.AbstractTestNGSpringContextTests;
import org.testng.Assert;
import org.testng.annotations.*;
import java.io.IOException;
@SpringBootTest(classes = {Application.class})
public class TestServiceTest extends AbstractTestNGSpringContextTests {
@Autowired
private TestService testServiceImpl;
@Autowired
private ExcelTool excelTool;
@Autowired
private LoginPageAction loginPageAction;
@Autowired
private User user;
@Autowired
private Supplier supplier;
@DataProvider(name = "testExcelData")
public Object[][] getExcelData() throws IOException {
return excelTool.readExcel("Sheet1");
}
@Test(groups = "P1", description = "登录商城", dataProvider = "testExcelData")
public void testLoginProductMall() throws Exception {
supplier.setName("admin");
supplier.setPassword("password");
loginPageAction.login(supplier, MallType.Product);
}
@Test(groups = "TestP1", description = "用户登录", dataProvider = "testExcelData")
public void test1(String result, String param1, String param2) {
System.out.println(String.join(",", result, param1, param2));
Assert.assertEquals(testServiceImpl.invokeService(), 2);
}
@Test(groups = "TestP1")
public void test2() {
Assert.assertEquals(testServiceImpl.invokeService(), 3);
}
@Test(groups = "TestP1")
public void test3() {
System.out.println("in test3");
}
}
TestServiceTest01.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE suite SYSTEM "http://testng.org/testng-1.0.dtd">
<suite name="Suite1" parallel="classes" thread-count="1">
<test verbose="1" name="test">
<groups>
<define name="testGroup01">
<include name="P1"/>
</define>
<run>
<include name="testGroup01"/>
</run>
</groups>
<classes>
<!-- 可以多个 -->
<class name="com.sa.testng.TestServiceTest"/>
</classes>
</test>
</suite>
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sa</groupId>
<artifactId>testNG</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>jar</packaging>
<name>SaTestNGProj</name>
<description>Use TestNG for sa test</description>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.0.3.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-configuration-processor</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
<version>6.9.10</version>
</dependency>
<!-- 依赖reportNg 关联testNg -->
<dependency>
<groupId>org.uncommons</groupId>
<artifactId>reportng</artifactId>
<version>1.1.4</version>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.testng</groupId>
<artifactId>testng</artifactId>
</exclusion>
</exclusions>
</dependency>
<!-- 依赖Guice -->
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
<version>3.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.seleniumhq.selenium</groupId>
<artifactId>selenium-java</artifactId>
<version>2.52.0</version>
<scope>compile</scope>
<!--
scope标签中对应值的解释:
* compile,缺省值,适用于所有阶段,会随着项目一起发布。
* provided,类似 compile,期望 JDK、容器或使用者会提供这个依赖。如 servlet.jar。
* runtime,只在运行时使用,如 JDBC 驱动,适用运行和测试阶段。
* test,只在测试时使用,用于编译和运行测试代码。不会随项目发布。
* system,类似 provided,需要显式提供包含依赖的 jar, Maven 不会在 Repository 中查找它。
-->
</dependency>
<!-- ***************************** poi ***************************** -->
<!-- poi HSSF is our port of the Microsoft Excel 97(-2007) file format (BIFF8) to pure Java. -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.14</version>
</dependency>
<!-- poi-ooxml XSSF is our port of the Microsoft Excel XML (2007+) file format (OOXML) to pure Java -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.14</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml-schemas</artifactId>
<version>3.14</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<!-- 添加插件 关联testNg.xml -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.5</version>
<configuration>
<suiteXmlFiles>
<suiteXmlFile>src/test/java/com/sa/testng/testng.xml</suiteXmlFile>
</suiteXmlFiles>
<properties>
<property>
<name>usedefaultlisteners</name>
<value>false</value>
</property>
<property>
<name>listener</name>
<value>org.uncommons.reportng.HTMLReporter</value>
</property>
</properties>
</configuration>
</plugin>
</plugins>
</build>
</project>