结构

common

ExcelTool

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>
posted on 2019-08-07 01:28  liehen2046  阅读(170)  评论(0编辑  收藏  举报