【实战】电子商务产品实战-PO优化篇

1、image
2、代码结构

image

3、代码
1)BasePage01类,用于存放公共方法
package com.po01;

import io.qameta.allure.Allure;
import org.openqa.selenium.*;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.support.ui.FluentWait;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.commons.io.FileUtils;

import javax.swing.text.Element;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.time.Duration;
import java.time.LocalDate;
import java.util.List;

public class BasePage01 {
public WebDriver driver;
public Logger logger = LoggerFactory.getLogger(“BasePage01.class”);

public BasePage01(String baseUrl) {
    //当传入String类型的url,我们认为是用例的开始也就是一个初始页面,
    driver = new ChromeDriver();
    logger = LoggerFactory.getLogger(LoginPage01.class);
    driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(5));
    logger.debug("开始自动化测试");
    driver.get(baseUrl);
    driver.manage().window().maximize();

}

public BasePage01(WebDriver baseDriver) {
        driver = baseDriver;

}
//大量的driver find:
//1、每次查找元素添加日志--解决方法:不对外暴露driver,直接封装basepage
public WebElement find(By by){
    System.out.println("sout查找元素为 =>"+by);
    logger.debug("查找元素为 =>"+by);
    return driver.findElement(by);
}

public List<WebElement> finds(By by){
    logger.debug("查找元素为 =>"+by);
    return driver.findElements(by);
}

public FluentWait<WebDriver> getFluentWait(){
    FluentWait<WebDriver> fluentWait = new FluentWait<>(driver)
            .withTimeout(Duration.ofSeconds(10))
            .pollingEvery(Duration.ofMillis(500))
            .ignoring(ElementClickInterceptedException.class);
    return fluentWait;
}

public void getUrl(String url){
    logger.debug("跳转页面到 =>" + url);
    driver.get(url);
}
public void quitDriver(){
    driver.quit();
}
//页面截图
public void saveScreenShot() throws IOException {
    LocalDate time = LocalDate.now();
    File screenshot = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
    FileUtils.copyFile(screenshot,new File("src/test/resources/imgs/"+time+".png"));
    Allure.addAttachment("页面截图","image/png",new FileInputStream("src/test/resources/imgs/"+time+".png"),".png");

}

//错误信息
public void saveErrorInfo(String error){
    Allure.addAttachment("报错信息",error);
}

}

2)登录页面LoginPage01

package com.po01;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;

public class LoginPage01 extends BasePage01{
//问题:driver 初始化和具体的业务操作结合了,比如测试用例一量没有登录步骤,那么就无法进行打开浏览器以及页面等待操作
//解决方法:将 driver 初始化,在一开始就完成,也就是构造函数

//所有初始页面都需要添加这个方法
//问题:元素定位没有统一维护,一但页面发生变化,那么相关的位置都要改
private final By usernameInputBy = By.name("username");
private final By passwordInputBy = By.name("password");
private final By loginButtonBy = By.cssSelector("button");

public LoginPage01(String baseUrl){
    super(baseUrl);
}


public LoginPage01(WebDriver baseDriver) {
    super(baseDriver);
}

public MainPage01 login(String username,String password){
    find(usernameInputBy).clear();
    find(usernameInputBy).sendKeys(username);
    find(passwordInputBy).clear();
    find(passwordInputBy).sendKeys(password);
    find(loginButtonBy).click();

    return new MainPage01(driver);


}

}

3)主页面MainPage01
package com.po01;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;

import java.time.Duration;

public class MainPage01 extends BasePage01{
//问题:虽然继承了,但是依然一直重复的打开浏览器,每次new一个新的page,只要继承了base page 就会不这的重复打开浏览器
//解决方法:添加带参的BasePage构造函数

private final By manageMarketButton = By.xpath("//*[text()='商场管理']");
private final By produceCategoryButton = By.xpath("//ul//*[text()='商品类目']");

public MainPage01(WebDriver baseDriver) {
    super(baseDriver);

}

public CategoryPage01 gotoCategoryPage()  {
    driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(3));
    getFluentWait().until(ExpectedConditions.elementToBeClickable(manageMarketButton)).click();
    find(produceCategoryButton).click();
    return new CategoryPage01(driver);

}

}

4)CategoryPage01 商品类目页面

package com.po01;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;

import java.util.List;

public class CategoryPage01 extends BasePage01{
//添加按钮
private final By categoryButton = By.cssSelector(“.el-icon-edit”);
//删除按钮
// private final By deleteButton = By.xpath(“//[text()=‘123’]/…/…//[text()=‘删除’]”);

public CategoryPage01(WebDriver baseDriver) {
    super(baseDriver);
}


//进入添加页面
public CreatCategoryPage01 gotoCreateCategoryPage(){
    find(categoryButton).click();

    return new CreatCategoryPage01(driver);

}

//获取结果列表
public List<WebElement> getResult(String categoryName){
    List<WebElement> eles = finds(By.xpath("//*[text()='"+categoryName+"']"));
    return eles;
}

public void deleteCategory(String categoryName){
    find(By.xpath("//*[text()='"+categoryName+"']/../..//*[text()='删除']")).click();

}

}

5)CreatCategoryPage01创建商品类目页

package com.po01;

import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;

public class CreatCategoryPage01 extends BasePage01{

private final By produceNameInput = By.cssSelector(".el-form-item:nth-child(1) input");
private final By prodeceSubmitButton = By.cssSelector(".el-dialog__footer .el-button--primary");
private final By popInfo = By.cssSelector(".el-notification__title");

// private final By producesList = By.xpath(“//*[text()=‘测试添加商品’]”);
private final By errorMessage = By.cssSelector(“.el-form-item__error”);

public CreatCategoryPage01(WebDriver baseDriver) {
    super(baseDriver);
}

public CategoryPage01 createCategory(String categoryName){

    find(produceNameInput).sendKeys(categoryName);
    getFluentWait().until(driver1 -> {
        driver1.findElement(prodeceSubmitButton).click();
        return find(popInfo);
    });
    return new CategoryPage01(driver);

}

public String createCategoryfail(){

    find(produceNameInput).sendKeys("");
    getFluentWait().until(ExpectedConditions.elementToBeClickable(prodeceSubmitButton)).click();
    return find(errorMessage).getText();


}

}

6)测试方法

package com.po01;

import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.openqa.selenium.WebElement;

import java.io.IOException;
import java.util.List;

import static org.junit.jupiter.api.Assertions.*;

class CreatCategoryPage01Test {
public static LoginPage01 loginPage01;
public static CategoryPage01 categoryPage01;

@BeforeAll
public static void setUp(){
    loginPage01 = new LoginPage01("http://litemall.hogwarts.ceshiren.com/#/login");
    categoryPage01 = loginPage01.login("manage","manage123").gotoCategoryPage();

}
//问题:上一个用例的结束会影响下一个用例
//解决方法:使用url跳转的方式,回退到用例执行之前的初始状态,保证下一个用例仍然能够正常执行
@AfterEach
void tearDowns(){
    categoryPage01.getUrl("http://litemall.hogwarts.ceshiren.com/#/mall/category");
}


@ParameterizedTest(name = "商品类目参数化" )
@ValueSource(strings = {"测试商品hogwarts01", "测试商品hogwarts02"})
void createCategory(String categoryName)  {
    try {
    categoryPage01
            .gotoCreateCategoryPage()
            .createCategory(categoryName);
    //1、在商品列表页获取结果信息
    List<WebElement> lists = categoryPage01.getResult(categoryName);
    assertEquals(1,lists.size());

        categoryPage01.saveScreenShot();

    //2、在商品列表页删除操作
    categoryPage01.deleteCategory(categoryName);
    categoryPage01.saveScreenShot();
    } catch (IOException e) {
        categoryPage01.saveErrorInfo(e.toString());
    }
}
//异常的场景
@Test
void createCategoryFail()  {

    String errorInfo = categoryPage01
            .gotoCreateCategoryPage()
            .createCategoryfail();
    assertEquals("类目名不能为空",errorInfo);
    try {
        categoryPage01.saveScreenShot();
    } catch (IOException e) {
        categoryPage01.saveErrorInfo(e.toString());
    }

}

@AfterAll
public static void tearDown(){
    loginPage01.quitDriver();

}

}

4、pom信息

<?xml version="1.0" encoding="UTF-8"?>

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”>
4.0.0

<groupId>org.example</groupId>
<artifactId>hogwarts24advence</artifactId>
<version>1.0-SNAPSHOT</version>

<properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <java.version>11</java.version>
    <!-- 使用 Java 11 语言特性 ( -source 11 ) 并且还希望编译后的类与 JVM 11 ( -target 11 )兼容,您可以添加以下两个属性,它们是默认属性插件参数的名称-->
    <maven.compiler.target>11</maven.compiler.target>
    <maven.compiler.source>11</maven.compiler.source>
    <!-- 对应junit Jupiter的版本号;放在这里就不需要在每个依赖里面写版本号,导致对应版本号会冲突-->
    <junit.jupiter.version>5.8.2</junit.jupiter.version>

    <maven.compiler.version>3.8.1</maven.compiler.version>
    <maven.surefire.version>3.0.0-M5</maven.surefire.version>
    <!-- plugins -->
    <maven-surefire-plugin.version>3.0.0-M5</maven-surefire-plugin.version>
    <poi.version>5.2.2</poi.version>
</properties>

<!--    物料清单 (BOM)-->
<dependencyManagement>
    <dependencies>
        <!--当使用 Gradle 或 Maven 引用多个 JUnit 工件时,此物料清单 POM 可用于简化依赖项管理。不再需要在添加依赖时设置版本-->
        <dependency>
            <groupId>org.junit</groupId>
            <artifactId>junit-bom</artifactId>
            <version>${junit.jupiter.version}</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

<dependencies>
    <dependency>
        <groupId>org.junit.jupiter</groupId>
        <artifactId>junit-jupiter</artifactId>
        <!--            对应添加的依赖的作用范围-->
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.junit.platform</groupId>
        <artifactId>junit-platform-suite</artifactId>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.junit.vintage</groupId>
        <artifactId>junit-vintage-engine</artifactId>
        <!--            <version>${junit.jupiter.version}</version>-->
    </dependency>

    <dependency>
        <groupId>org.hamcrest</groupId>
        <artifactId>hamcrest-all</artifactId>
        <version>1.3</version>
        <scope>test</scope>
    </dependency>

    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-api</artifactId>
        <version>4.2.1</version>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-java</artifactId>
        <version>4.2.1</version>
    </dependency>
    <dependency>
        <groupId>io.qameta.allure</groupId>
        <artifactId>allure-junit5</artifactId>
        <version>2.13.6</version>
    </dependency>
    <dependency>
        <groupId>commons-io</groupId>
        <artifactId>commons-io</artifactId>
        <version>2.11.0</version>
    </dependency>
    <dependency>
        <groupId>org.seleniumhq.selenium</groupId>
        <artifactId>selenium-support</artifactId>
        <version>4.2.1</version>
    </dependency>
</dependencies>

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>${maven-surefire-plugin.version}</version>
            <configuration>
                <!--                    <includes>-->
                <!--                        <include>top/testeru/group/*_Test.class</include>-->
                <!--                    </includes>-->
            </configuration>
            <dependencies>
                <dependency>
                    <groupId>org.junit.jupiter</groupId>
                    <artifactId>junit-jupiter-engine</artifactId>
                    <version>${junit.jupiter.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.junit.vintage</groupId>
                    <artifactId>junit-vintage-engine</artifactId>
                    <version>${junit.jupiter.version}</version>
                </dependency>

            </dependencies>
        </plugin>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>${maven.compiler.version}</version>
        </plugin>
    </plugins>
</build>

5、logback.xml配置信息

<?xml version="1.0" encoding="UTF-8" ?> %d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36}.%M\(%line\) -- %msg%n
<logger name="po01" level="DEBUG" />
<logger name="litemall" level="DEBUG" />
<logger name="com.ceshiren" level="DEBUG" />
<logger name="com" level="DEBUG" />
<logger name="ceshiren" level="DEBUG" />
<logger name="org" level="DEBUG"/>


<root level="INFO">
    <appender-ref ref="STDOUT"/>
</root>
1 个赞