PO模式:
以页面为单位独立建模,隐藏实现的细节,本质是面向接口编程。
封装基础类,driver调用、元素操作方法等的封装
创建页面返回类,用于返回各个页面,所以可不设方法
创建相应page类,用于元素定位、封装业务操作方法
创建测试类
关于奶茶工作台的WebUI自动化的实现
需求须知:奶茶点单微信小程序的工作台。主要模块:登陆、修改密码、订单管理、配料管理、财务管理、退出登录
框架选取:Junit5+Selenium
设计用例组织结构:page【页面封装】+driver【对Web驱动】+testcase【调用page完成业务流程并做断言】+data【数据驱动】+utils【其他工具封装】
测试分析:
- 登陆–验证码处理:(1)去掉验证码,线上不安全;(2)程序开“后门”,设置万能验证码,测试人员获取即可。–采用
- Cookie获取:
driver.manage().getCookies();
- 数据驱动:
@ParameterizedTest
@CsvFileSource(resources = "1.csv")
public void addIngredient(String name,double price){
//todo
}
- 测试步骤驱动:
public static App app;
public static IngredientPage ingredientPage;
@BeforeAll
public static void beforeAll(){
app = new App();
ingredientPage= new IngredientPage ();
app.LoginWithCookies();
}
@AfterAll
public static void quit(){
app.quit();
}
@RunWith(Suite.class)
@Suite.SuiteClasses({
testcase.TestIngredient.class
})
常用Selenium方法:
定义WebDriver对象,且结束测试时需要关闭
public static WebDriver driver;
public void quit(){
driver.quit();
}
请求页面
driver.get("https://***/");
登陆完成后,获取cookies
public Cookie getCookie(){
//todo:完成登陆操作
return driver.manage().getCookieNamed("wwrtx.sid");
}
在相应Page层中添加cookies
driver.manage().addCookie(new Cookie("cookie","***"));
定位元素节点
public WebElement findElement(By by){
return driver.findElement(by);
}
public List<WebElement> findElements(By by){
return driver.findElements(by);
}
定位方法:ID、CSS、Xpath
元素节点交互:
.click()
.clear()
.sendKeys("")
网页交互
navigate().to() //打开指定的网页
navigate().back() //后退
navigate().forward() //前进
navigate().refresh() //刷新
动作链action,比如:拖拽
Actions action = new Actions(webdriver);
//source-要拖动的元素A,target-拖动元素A到达的目标元素
action.dragAndDrop(source, target);
//source-要拖动的元素A,拖动元素移动多少,标准以元素A左上角为准,拖动元素相对元素A移到右边是x是正值,左边是负值,拖动元素相对元素A移到上边是y是负值,下边是正值,
action.dragAndDropBy(source, xOffset, yOffset);
执行js:指定页面滚动
String js = "document.documentElement.scrollTop=2000";
((JavascriptExecutor)driver).executeScript(js);
获取节点信息
.getText(); //获取文本信息
.getAttribute(""); //获取属性信息
.getCssValue(""); //css信息
.getLocation(); //位置信息
.getTagName(); //标签名称
.getSize(); //节点大小
切换frame
driver.switchTo().frame(0);
切换handle
driver.switchTo().window((String)driver.getWindowHandles().toArray()[1]);
隐式等待(设置等待#s)
driver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);
显式等待(持续等待*s,知道出现可使用的元素)
new WebDriverWait(driver,5)
.until(ExpectedConditions.elementToBeClickable(By.name("q")));
截图
File file = ((TakesScreenshot)driver).getScreenshotAs(OutputType.FILE);
选项卡管理
Set<String> windowsHandles = driver.getWindowHandles();
for (String s : windowsHandles) {
if (s.equals("111")){
driver.switchTo().window(s);
break;
}
}
文件导入
public ContactPage importFromFile(String path){
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
findElement(By.partialLinkText("批量导入/导出"),0).click();
findElement(By.linkText("文件导入"),2).click();
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
findElement(By.id("js_upload_file_input")).sendKeys(path);
findElement(By.id("submit_csv")).click();
return this;
}
弹窗类型
1)ajax:直接定位即可、2)iframe:switchTo、3)打开新窗口switchTo、4)alert或Confirm:先定义窗口,再定位关键字。
上传图片
testcase逻辑:
业务流程处理
断言
assertThat(msgTitlekjukj,hasItem(title));
Assert.assertTrue("登录失败,密码错误", webdriver.getCurrentUrl().contains("staffLogin"));
Assert.assertFalse("密码修改失败",webDriver.getCurrentUrl().contains("staffLogin"));
assertEqual(a,b,[msg='测试失败时打印的信息']): 断言a和b是否相等,相等则测试用例通过。
assertNotEqual(a,b,[msg='测试失败时打印的信息']): 断言a和b是否相等,不相等则测试用例通过。
assertTrue(x,[msg='测试失败时打印的信息']): 断言x是否True,是True则测试用例通过。
assertFalse(x,[msg='测试失败时打印的信息']): 断言x是否False,是False则测试用例通过。
assertIs(a,b,[msg='测试失败时打印的信息']): 断言a是否是b,是则测试用例通过。
assertNotIs(a,b,[msg='测试失败时打印的信息']): 断言a是否是b,不是则测试用例通过。
assertIsNone(x,[msg='测试失败时打印的信息']): 断言x是否None,是None则测试用例通过。
assertIsNotNone(x,[msg='测试失败时打印的信息']): 断言x是否None,不是None则测试用例通过。
assertIn(a,b,[msg='测试失败时打印的信息']): 断言a是否在b中,在b中则测试用例通过。
assertNotIn(a,b,[msg='测试失败时打印的信息']): 断言a是否在b中,不在b中则测试用例通过。
assertIsInstance(a,b,[msg='测试失败时打印的信息']): 断言a是是b的一个实例,是则测试用例通过。
assertNotIsInstance(a,b,[msg='测试失败时打印的信息']): 断言a是是b的一个实例,不是则测试用例通过。
数据清理:可以借助数据驱动,可以在testcase
针对add、alter数据进行清理
add–>delete
alter–>再alter
时间控件的设计:借助js
String js = "document.getElementById(日期输入框ID).value='" +"2020"+ "'";
((JavascriptExecutor)driver).executeScript(js);
设计测试用例:参考ui用例逻辑
1.输入参数的组合,前端判断逻辑校验;
2.正常流程校验是否可以通过,此处可以不过多做数据层面的校验
关于Junit的功能
1.参数化测试
@ParameterizedTest
@CsvFileSource(resources = "TestUserApi.csv")
2.注解:测试用例整理
@Test
@BeforeAll:举例在所有的testcase执行前需要进行登录获取cookie操作。
@AfterAll:举例在所有testcase执行结束需要调用driver.quit方法。
@RepeatedTest(#)重复执行#遍
@displayName()展示名称
@Nested 先执行主类,再将后面的倒序执行
@Disabled 跳过但提示执行完成
3.suite体系管理用例的顺序
@RunWith(JUnitPlatform.class)
@SelectPackages({"TestcaseSuite"})
@IncludePackages({
"TestcaseSuite.case1.TestRun1",
"TestcaseSuite.case2.TestRun2"
})
@RunWith(Suite.class)
@Suite.SuiteClasses({
TestcaseSuite.case1.TestRun1.class
})