一,产品分析
-
产品:Litemall商城系统
- http://litemall.hogwarts.ceshiren.com
- 登陆账号:manage
- 密码:manage123
-
功能:商品上架管理
二,测试用例分析
-
下记是商品类目创建用例,仅做参考用
-
代码实现设计思路:
- 登录页面,首页可以视为一个类
- 用户登陆登步骤设计为对应的方法
- 箭头所指的方向表现为方法的返回值
三, PageObjectModel简介
1,页面对象模型
2,PO模式设计原则
- 不要暴露页面内部的元素给外部
- 不需要建模 UI 内的所有元素
- 要用公共方法代表 UI 所提供的功能
- 同样的行为不同的结果可以建模为不同的方法
- 方法应该返回其他的 PageObject ,或者返回用于断言的数据
- 不要在方法内加断言
3,PO模式改造
四,PO模式代码改造示例
1,新建BasePage类,封装公共方法
package com.hogwarts.page;
import org.openqa.selenium.By;
import org.openqa.selenium.ElementClickInterceptedException;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.openqa.selenium.support.ui.FluentWait;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.time.Duration;
import java.util.List;
public class BasePage {
public static WebDriver driver;
public Logger log = LoggerFactory.getLogger(BasePage.class);
public BasePage(WebDriver webDriver) {
driver = webDriver;
}
public BasePage(String baseUrl) {
ChromeOptions options = new ChromeOptions();
options.addArguments("--remote-allow-origins=*");
driver = new ChromeDriver(options);
driver.get(baseUrl);
driver.manage().window().maximize();
}
public WebElement find(By by){
log.debug("查找的定位元素为=> " + by);
return driver.findElement(by);
}
public List<WebElement> finds(By by){
log.debug("查找的定位元素为=> " + by);
return driver.findElements(by);
}
public FluentWait<WebDriver> getFluentWait(){
FluentWait<WebDriver> fluentWait = new FluentWait(driver)
.withTimeout(Duration.ofSeconds(10))
.pollingEvery(Duration.ofSeconds(2))
.ignoring(ElementClickInterceptedException.class);
return fluentWait;
}
public void getUrl(String url){
log.debug("跳转页面到=> " + url);
driver.get(url);
}
public void deleteProduct(String productName){
find(By.xpath("//*[text()='"+productName+"']//..//..//*[text()='删除']")).click();
}
public void quitDriver(){
driver.quit();
}
}
2,封装页面元素,实现页面方法
(1)登陆页面LoginPage ,返回首页页面
package com.hogwarts.page;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
//登陆页面
public class LoginPage extends BasePage {
//PO设计六原则 - 不要暴露页面内部的元素给外部(适用于元素定位没有统一维护且复用)
public final By usernameBy = By.name("username");
public final By passwordBy = By.name("username");
public final By buttonBy = By.cssSelector("button");
public LoginPage(WebDriver webDriver) {
super(webDriver);
}
public LoginPage(String baseUrl){
super(baseUrl);
}
public MainPage login(String username, String password) {
getFluentWait().until(ExpectedConditions.elementToBeClickable(usernameBy)).clear();
// find(usernameBy).clear();
find(usernameBy).sendKeys(username);
find(passwordBy).clear();
find(passwordBy).sendKeys(password);
find(buttonBy).click();
// po设计六大原则之二:方法应该返回其他的 PageObject ,或者返回用于断言的数据
return new MainPage(driver);
}
}
(2)进入首页MainPage,通过方法进入商品列表页
package com.hogwarts.page;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
//首页
public class MainPage extends BasePage {
public final By productManageBy = By.xpath("//*[text()='商品管理']");
public final By productListBy = By.xpath("//li/*[text()='商品列表']");
public MainPage(WebDriver webDriver) {
super(webDriver);
}
public ProductPage toProductPage() {
getFluentWait().until(ExpectedConditions.elementToBeClickable(productManageBy)).click();
// find(productManageBy).click();
getFluentWait().until(ExpectedConditions.elementToBeClickable(productListBy)).click();
// find(productListBy).click();
return new ProductPage(driver);
}
}
(3)商品列表页ProductPage ,点击添加按钮进入商品上架页面
package com.hogwarts.page;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.ExpectedConditions;
import java.util.List;
public class ProductPage extends BasePage {
public final By addButtonBy = By.xpath("//*[text()='添加']");
public ProductPage(WebDriver webDriver) {
super(webDriver);
}
public AddProductPage toAddProductPage(){
// getFluentWait().until(ExpectedConditions.elementToBeClickable(addButtonBy)).click();
find(addButtonBy).click();
return new AddProductPage(driver);
}
public List<WebElement> getResult(String productName){
List<WebElement> elements = finds(By.xpath("//*[text()='"+productName+"']"));
System.out.println(elements.size());
return elements;
}
}
(4)商品上架页面AddProductPage ,上架商品成功后,返回商品列表页
package com.hogwarts.page;
import org.openqa.selenium.By;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.support.ui.ExpectedConditions;
public class AddProductPage extends BasePage {
public final By productCatBy = By.cssSelector(".el-form-item is-error,.is-required:nth-child(1) input");
public final By productNameBy = By.cssSelector(".el-form-item is-error,.is-required:nth-child(2) input");
public final By addButtonBy = By.cssSelector(".app-container>.op-container button:nth-child(2)");
public AddProductPage(WebDriver webDriver) {
super(webDriver);
}
public ProductPage addProduct(String productCategory, String productName) {
find(productCatBy).sendKeys(productCategory);
find(productNameBy).sendKeys(productName);
getFluentWait().until(ExpectedConditions.elementToBeClickable(addButtonBy)).click();
// find(addButtonBy).click();
return new ProductPage(driver);
}
}
(5)新建测试用例
package com.hogwarts.page;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import org.openqa.selenium.WebElement;
import java.util.List;
import static org.junit.jupiter.api.Assertions.*;
class AddProductPageTest {
public static LoginPage loginPage;
public static MainPage mainPage;
@BeforeAll
static void setUpBeforeClass() {
loginPage = new LoginPage("https://litemall.hogwarts.ceshiren.com/#/login");
mainPage = loginPage.login("manage", "manage123");
}
@AfterAll
static void tearDownAfterClass() throws InterruptedException {
Thread.sleep(3000);
loginPage.quitDriver();
}
//保证在每条用例执行完成之后都会跳转到首页
@AfterEach
void tearDown() throws InterruptedException {
mainPage.getUrl("https://litemall.hogwarts.ceshiren.com/#/dashboard");
Thread.sleep(3000);
}
@ParameterizedTest
@ValueSource(strings = {"651352343","凯喜雅"})
void addProduct(String productCategory, String productName) {
ProductPage productPage = mainPage.toProductPage()
.toAddProductPage()
.addProduct(productCategory, productName);
//获取新增数据的结果集
List<WebElement> result = productPage.getResult(productName);
assertEquals(1, result.size());
//在商品列表页面删除商品信息
productPage.deleteProduct(productName);
}
}