云端笔记系统-自动化测试
文章目录
- 1. 思维导图编写 Web 自动化测试用例
- 2. 创建测试项目
- 3. 根据思维导图设计【云端笔记】自动化测试用例
- 3.1. 准备工具类
- 3.2. 测试注册页面
- 3.3. 测试登陆页面
- 3.4. 测试添加博客页
- 3.5. 测试我的博客列表页
- 3.6. 测试修改博客页
- 3.7. 测试博客列表页
- 3.8. 测试博客详情页
- 3.9. 测试未登录状态
- 4. 自动化测试项目总结
- 4.1 自动化测试项目实现步骤
- 4.2 当前项目测试亮点
----------------------【云端笔记】自动化测试代码-----------------------
1. 思维导图编写 Web 自动化测试用例
2. 创建测试项目
- 创建 Maven 项目
- 在 test 包下编写相关测试代码
- 导入自动化测试需要的相关依赖
在 pom.xml 中引入自动化测试相关依赖:
<dependencies><dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId><version>4.0.0</version></dependency><!-- 保存屏幕截图文件需要用到的包--><dependency><groupId>commons-io</groupId><artifactId>commons-io</artifactId><version>2.6</version></dependency><!-- Junit 中 参数化测试 --><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter</artifactId><version>5.8.2</version><scope>test</scope></dependency><!-- junit 中 测试套件 --><dependency><groupId>org.junit.platform</groupId><artifactId>junit-platform-suite</artifactId><version>1.8.2</version><scope>test</scope></dependency></dependencies>
3. 根据思维导图设计【云端笔记】自动化测试用例
3.1. 准备工具类
在 common 包下创建 AutoTestUtils 类,该类需要提供以下功能:
- 创建驱动对象,提供给页面使用。
- 创建隐式等待,作用于驱动对象的整个生命周期。
- 提供屏幕截图方法,以及保存截图的格式。
/*** @Description: 创建驱动对象;提供屏幕截图方法* @Date 2023/9/3 9:03* @Author:*/
public class AutoTestUtils {public static EdgeDriver driver;/*** @param :* @return EdgeDriver* @description 创建驱动对象*/public static EdgeDriver createDriver() {EdgeOptions options = new EdgeOptions();options.addArguments("-remote-allow-origins=*");// 驱动对象没有创建if (driver == null) {// 创建隐式等待driver.manage().timeouts().implicitlyWait(Duration.ofSeconds(10));}// 驱动对象已经创建好了return driver;}/*** @param str: 类名* @return void* @description 获取屏幕截图,把所有的用例执行的结果都保存下来*/public void getScreenShot(String str) throws IOException {List<String> list = getTime();// ./src/test/java/com/usermanagerWebAutoTest/日期/类名_日期_时间.pngString filename = "./src/test/java/com/usermanagerWebAutoTest/" + list.get(0) +"/" + str + "_" + list.get(1) + ".png";// 进行屏幕截图File srcFile = driver.getScreenshotAs(OutputType.FILE);// 将屏幕截图生成的图片放到指定路径下FileUtils.copyFile(srcFile,new File(filename));}public List<String> getTime() {// 文件格式 2023-04-15/2023-04-15_12:36:00SimpleDateFormat sim1 = new SimpleDateFormat("yyyy-MM-dd");SimpleDateFormat sim2 = new SimpleDateFormat("yyyyMMdd-HHmmssSS");// 以天的维度按文件夹进行保存String dirname = sim1.format(System.currentTimeMillis());String filename = sim2.format(System.currentTimeMillis());List<String> list = new ArrayList<>();list.add(dirname);list.add(filename);return list;}
}
在 Tests 包下创建 DriverQuitTest 类,该类的主要作用是用来释放驱动
/*** @Description: 释放驱动* @Date 2023/9/3 9:12* @Author:*/
public class DriverQuitTest extends AutoTestUtils {public static EdgeDriver driver = createDriver();@Testvoid driverQuit() {driver.quit();}
}
在 Tests 包下创建 runSuite 类,该类的就是测试套件
/*** @Description: 测试套件* @Date 2023/9/3 9:13* @Author:*/
@Suite
@SelectClasses({DriverQuitTest.class})
public class runSuite {
}
3.2. 测试注册页面
创建 UserRegTest 类,该类的测试用例有 6 个。
- 页面是否可以正常打开
- 输入合法的用户名、密码、确认密码,点击注册
- 输入不合法的用户名、密码,点击注册
- 输入的密码和确认密码不一致,点击注册
- 输入用户名、密码、确认密码都为空,点击注册
- 输入用户名/密码/确认密码任意为空,点击注册
/*** @Description: 测试注册页面* @Date 2023/9/3 9:45* @Author:*/
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class UserRegTest extends AutoTestUtils {// 1. 访问浏览器对象 2. 访问登录页面的 URLpublic static EdgeDriver driver = createDriver();@BeforeAllstatic void baseControl() {driver.get("http://47.108.57.239:7070/reg.html");}/*** @param :* @return void* @description 检查页面是否可以正常打开*/@Test@Order(1)void regPageLoadRight() throws IOException {driver.findElement(By.cssSelector("#username"));driver.findElement(By.cssSelector("#password"));driver.findElement(By.cssSelector("#password2"));driver.findElement(By.cssSelector("#submit"));getScreenShot(getClass().getName());}/*** @param username: 用户名* @param password: 密码* @param password2: 确认密码* @return void* @description 注册失败:密码,确认密码不一致*/@ParameterizedTest@CsvSource({"lisi,111,222"})@Order(2)void regFailIllegalNameOrPass(String username, String password, String password2) throws InterruptedException, IOException {driver.findElement(By.cssSelector("#username")).clear(); // 先清空一下driver.findElement(By.cssSelector("#password")).clear();driver.findElement(By.cssSelector("#password2")).clear();driver.findElement(By.cssSelector("#username")).sendKeys(username);driver.findElement(By.cssSelector("#password")).sendKeys(password);driver.findElement(By.cssSelector("#password2")).sendKeys(password2);driver.findElement(By.cssSelector("#submit")).click();// 登录失败结果检测Thread.sleep(2000);// 切换到弹窗进行处理Alert alert = driver.switchTo().alert();// 点击确认alert.accept();getScreenShot(getClass().getName());}/*** @param username: 用户名* @return void* @description 注册失败:用户名不为null,其他注册信息为null*/@ParameterizedTest@ValueSource(strings = {"111","2222","3333"})@Order(3)void regFaiPasswordNull(String username) throws InterruptedException, IOException {driver.findElement(By.cssSelector("#username")).clear(); // 先清空一下driver.findElement(By.cssSelector("#password")).clear();driver.findElement(By.cssSelector("#password2")).clear();driver.findElement(By.cssSelector("#username")).sendKeys(username);driver.findElement(By.cssSelector("#submit")).click();// 登录失败结果检测Thread.sleep(2000);// 切换到弹窗进行处理Alert alert = driver.switchTo().alert();// 点击确认alert.accept();}/*** @param password: 密码* @param password2: 确认密码* @return void* @description 注册失败:用户名为null,其他注册信息不为null*/@ParameterizedTest@CsvSource({"111,111","222,222"})@Order(4)void regFailUsernameNull(String password, String password2) throws InterruptedException, IOException {driver.findElement(By.cssSelector("#username")).clear(); // 先清空一下driver.findElement(By.cssSelector("#password")).clear();driver.findElement(By.cssSelector("#password2")).clear();driver.findElement(By.cssSelector("#password")).sendKeys(password);driver.findElement(By.cssSelector("#password2")).sendKeys(password2);driver.findElement(By.cssSelector("#submit")).click();// 登录失败结果检测Thread.sleep(1000);// 切换到弹窗进行处理Alert alert = driver.switchTo().alert();// 点击确认alert.accept();getScreenShot(getClass().getName());}/*** @param username: 用户名* @param password: 密码* @return void* @description 注册失败:用户名,密码不为null,确认密码为null*/@ParameterizedTest@CsvSource({"lisi,111,222"})@Order(5)void regFailIllegalNameOrPass(String username, String password) throws InterruptedException, IOException {driver.findElement(By.cssSelector("#username")).clear(); // 先清空一下driver.findElement(By.cssSelector("#password")).clear();driver.findElement(By.cssSelector("#password2")).clear();driver.findElement(By.cssSelector("#username")).sendKeys(username);driver.findElement(By.cssSelector("#password")).sendKeys(password);driver.findElement(By.cssSelector("#submit")).click();// 登录失败结果检测Thread.sleep(2000);// 切换到弹窗进行处理Alert alert = driver.switchTo().alert();// 点击确认alert.accept();getScreenShot(getClass().getName());}/*** @param username: * @param password: * @param password2: * @return void* @description 注册成功*/@ParameterizedTest@CsvSource({"wangwu,123456,123456"})@Order(6)void regSucced(String username, String password, String password2) throws InterruptedException, IOException {driver.findElement(By.cssSelector("#username")).clear(); // 先清空一下driver.findElement(By.cssSelector("#password")).clear();driver.findElement(By.cssSelector("#password2")).clear();driver.findElement(By.cssSelector("#username")).sendKeys(username);driver.findElement(By.cssSelector("#password")).sendKeys(password);driver.findElement(By.cssSelector("#password2")).sendKeys(password2);driver.findElement(By.cssSelector("#submit")).click();// 登录成功结果检测Thread.sleep(1000);// 切换到弹窗进行处理Alert alert = driver.switchTo().alert();// 点击确认alert.accept();Thread.sleep(1000);alert.accept();Thread.sleep(1000);driver.findElement(By.cssSelector("body > div.login-container > div > h3"));getScreenShot(getClass().getName());// 注册完成,重新返回到注册页面driver.navigate().back();}
}
3.3. 测试登陆页面
创建 UserLoginTest 类,该类的测试用例有 4 个。
- 页面是否可以正常打开
- 输入正确的用户名、密码,点击登录
- 输入错误的用户名/密码,点击登录
- 用户名/密码任意为空,点击登录
/*** @Description: 测试登陆页面* @Date 2023/9/3 11:25* @Author:*/
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class UserLoginTest extends AutoTestUtils {// 1. 访问浏览器对象 2. 访问登录页面的 URLpublic static EdgeDriver driver = createDriver();@BeforeAllstatic void baseControl() {driver.get("http://47.108.57.239:7070/login.html");}/*** @param :* @return void* @description 检查页面是否可以正常打开*/@Test@Order(1)void LoginPageLoadRight() throws IOException {driver.findElement(By.cssSelector("#username"));driver.findElement(By.cssSelector("#password"));driver.findElement(By.cssSelector("#submit"));getScreenShot(getClass().getName());}/*** @param username: 用户名* @return void* @description 注册失败:密码为null*/@ParameterizedTest@ValueSource(strings = {"wangwu"})@Order(2)void regFailPasswordNUll(String username) throws InterruptedException, IOException {driver.findElement(By.cssSelector("#username")).clear(); // 先清空一下driver.findElement(By.cssSelector("#password")).clear();driver.findElement(By.cssSelector("#username")).sendKeys(username);driver.findElement(By.cssSelector("#submit")).click();// 登录失败结果检测Thread.sleep(1000);// 切换到弹窗进行处理Alert alert = driver.switchTo().alert();// 点击确认alert.accept();getScreenShot(getClass().getName());}/*** @param password: 密码* @return void* @description 注册失败:用户名为null*/@ParameterizedTest@ValueSource(strings = {"123456"})@Order(3)void regFailUsernameNUll(String password) throws InterruptedException, IOException {driver.findElement(By.cssSelector("#username")).clear(); // 先清空一下driver.findElement(By.cssSelector("#password")).clear();driver.findElement(By.cssSelector("#username")).sendKeys(password);driver.findElement(By.cssSelector("#submit")).click();// 登录失败结果检测Thread.sleep(1000);// 切换到弹窗进行处理Alert alert = driver.switchTo().alert();// 点击确认alert.accept();getScreenShot(getClass().getName());}/*** @param username: 用户名* @param password: 密码* @return void* @description 登录成功*/@ParameterizedTest@CsvSource({"wangwu,123456"})@Order(4)void regSucced(String username, String password) throws InterruptedException, IOException {driver.findElement(By.cssSelector("#username")).clear(); // 先清空一下driver.findElement(By.cssSelector("#password")).clear();driver.findElement(By.cssSelector("#username")).sendKeys(username);driver.findElement(By.cssSelector("#password")).sendKeys(password);driver.findElement(By.cssSelector("#submit")).click();Thread.sleep(3000);getScreenShot(getClass().getName());driver.findElement(By.cssSelector("#username"));}
}
3.4. 测试添加博客页
创建 BlogAddTest 类,该类的测试用例有 4 个。
登录状态下:
- 页面内容显示是否正常(markdown编辑器、导航栏、发布文章按钮)
- 导航栏链接是否跳转正常
- markdown编辑及显示功能是否正常
- 发布文章的功能是否正常
/*** @Description: 添加博客页* @Date 2023/9/3 11:59* @Author:*/
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BlogAddTest extends AutoTestUtils {// 1. 访问浏览器对象 2. 访问登录页面的 URLpublic static EdgeDriver driver = createDriver();@BeforeAllstatic void baseControl() {driver.get("http://47.108.57.239:7070/blog_add.html");}/*** @param :* @return void* @description 检查页面是否可以正常打开*/@Test@Order(1)void BlogAddPageLoadRight() throws IOException {driver.findElement(By.cssSelector("#editorDiv > div.editormd-toolbar > div > ul > li:nth-child(12) > a > i"));driver.findElement(By.cssSelector("#editorDiv > div.editormd-toolbar > div > ul > li:nth-child(17) > a > i"));driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)"));driver.findElement(By.cssSelector("body > div.blog-edit-container > div.title > button"));getScreenShot(getClass().getName());}/*** @param :* @return void* @description 链接跳转正常*/@Test@Order(2)void AddLinkJump() throws InterruptedException, IOException {driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)")).click();Thread.sleep(1000);driver.findElement(By.cssSelector("#username"));getScreenShot(getClass().getName());driver.navigate().back();}/*** @param :* @return void* @description 发布文章的功能是否正常*/@Test@Order(3)public void PublishArticleSucced() throws InterruptedException, IOException {driver.findElement(By.cssSelector("#title")).sendKeys("测试发布文章");Thread.sleep(2000);driver.findElement(By.cssSelector("body > div.blog-edit-container > div.title > button")).click();Thread.sleep(2000);// 切换到弹窗进行处理Alert alert = driver.switchTo().alert();// 点击确认发布文章alert.accept();// 点击取消继续发布alert.dismiss();Thread.sleep(2000);String str = driver.findElement(By.cssSelector("#artlistDiv > div:nth-child(1) > div.title")).getText();Assertions.assertEquals("测试发布文章", str);getScreenShot(getClass().getName());}
}
3.5. 测试我的博客列表页
创建 MyblogListTest 类,该类的测试用例有 5 个。
登录状态下:
- 页面内容显示是否正常(导航栏、左侧个人信息、右侧博客信息)
- 测试链接跳转是否正常(导航栏链接)
- 我的博客列表页存在博客时,测试查看博客详情和修改博客链接是否跳转正常
- 我的博客列表页存在博客时,测试删除博客功能是否正常
- 登录状态下,测试注销功能是否正常
/*** @Description: 测试我的博客列表页* @Date 2023/9/3 12:34* @Author:*/
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class MyblogListTest extends AutoTestUtils {// 1. 访问浏览器对象 2. 访问登录页面的 URLpublic static EdgeDriver driver = createDriver();@BeforeAllstatic void baseControl() {driver.get("http://47.108.57.239:7070/myblog_list.html");}/*** @param :* @return void* @description 检查页面是否可以正常打开*/@Test@Order(1)void BlogAddPageLoadRight() throws IOException {driver.findElement(By.cssSelector("#username")).getText();driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)"));String str1 = driver.findElement(By.cssSelector("#artlistDiv > div:nth-child(1) > div.title")).getText();Assertions.assertEquals("测试发布文章", str1);getScreenShot(getClass().getName());}/*** @param :* @return void* @description 测试链接跳转:导航栏;查看全文;修改文章*/@Test@Order(2)void LinkJump() throws InterruptedException, IOException {// 1. 导航栏driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)")).click();String str = driver.findElement(By.cssSelector("#listDiv > div:nth-child(1) > div.title")).getText();Assertions.assertEquals("测试发布文章", str);getScreenShot(getClass().getName());driver.navigate().back();Thread.sleep(1000);// 2. 查看全文driver.findElement(By.cssSelector("#artlistDiv > div:nth-child(1) > a:nth-child(4)")).click();driver.findElement(By.cssSelector("#title"));driver.navigate().back();Thread.sleep(1000);// 3. 修改文章driver.findElement(By.cssSelector("#artlistDiv > div:nth-child(1) > a:nth-child(5)")).click();String str1 = driver.findElement(By.cssSelector("body > div.blog-edit-container > div.title > button")).getText();Assertions.assertEquals("修改文章", str1);driver.navigate().back();Thread.sleep(1000);getScreenShot(getClass().getName());}/*** @param :* @return void* @description 测试删除博客功能是否正常*/@Test@Order(3)void DeleteBlog() throws InterruptedException, IOException {// wangwu此时只有一篇测试博客driver.findElement(By.cssSelector("#artlistDiv > div:nth-child(1) > a:nth-child(6)")).click();Alert alert = driver.switchTo().alert();alert.accept();Thread.sleep(1000);alert.accept();Thread.sleep(1000);// 删除完成后,右边博客列表栏就会显示:暂无文章String str = driver.findElement(By.cssSelector("#artlistDiv > h3")).getText();Assertions.assertEquals("暂无文章", str);Thread.sleep(1000);getScreenShot(getClass().getName());}/**
// * @param :
// * @return void
// * @description 测试注销功能(账号退出)
// */
// @Test
// @Order(4)
// void WriteOff() throws InterruptedException, IOException {
// driver.findElement(By.cssSelector("body > div.nav > a:nth-child(6)")).click();
// Alert alert = driver.switchTo().alert();
// alert.accept();
// // 注销完成后,跳转到登录页面
// driver.findElement(By.cssSelector("#submit"));
// Thread.sleep(1000);
// getScreenShot(getClass().getName());
// }
}
3.6. 测试修改博客页
创建 BlogEditTest 类,该类的测试用例有 4 个。
登录状态下:
- 页面内容显示是否正常(markdown编辑器、导航栏、修改文章按钮、原始博客内容显示)
- 导航栏链接是否跳转正常
- markdown编辑及显示功能是否正常
- 修改文章功能是否正常
/*** @Description: 测试修改博客页* @Date 2023/9/3 13:17* @Author:*/
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BlogEditTest extends AutoTestUtils {// 1. 访问浏览器对象 2. 访问登录页面的 URLpublic static EdgeDriver driver = createDriver();@BeforeAllstatic void baseControl() {// 因为在 myblogList 中已经将测试添加的博客删除了,所以需要重新添加一次driver.get("http://47.108.57.239:7070/blog_add.html");}/*** @param :* @return void* @description 页面内容显示是否正常(markdown编辑器、导航栏、修改文章按钮、原始博客内容显示)*/@Test@Order(1)void BlogEditPageLoadRight() throws InterruptedException, IOException {// 重新发布一篇测试博客后,此时页面在我的博客列表页PublishArticleSucced();Thread.sleep(1000);// 当前在我的博客列表页,需要跳转到修改博客页driver.findElement(By.cssSelector("#artlistDiv > div > a:nth-child(5)")).click();Thread.sleep(1000);driver.findElement(By.cssSelector("#title"));// 其他内容是否显示正常driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)"));String str1 = driver.findElement(By.cssSelector("body > div.blog-edit-container > div.title > button")).getText();Assertions.assertEquals("修改文章", str1);getScreenShot(getClass().getName());}/*** @param :* @return void* @description 测试导航栏链接跳转正常*/@Test@Order(2)void LinkJump() throws InterruptedException, IOException {driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)")).click();Thread.sleep(1000);driver.findElement(By.cssSelector("#username"));driver.navigate().back();Thread.sleep(1000);getScreenShot(getClass().getName());}/*** @param :* @return void* @description 修改文章功能是否正常*/@Test@Order(3)void EditBlog() throws InterruptedException, IOException {// 双击选中文章标题框,获取标题框中文本内容WebElement ele = driver.findElement(By.cssSelector("#title"));Actions actions = new Actions(driver);actions.doubleClick(ele).perform();ele.clear();ele.sendKeys("测试修改文章");Thread.sleep(1000);driver.findElement(By.cssSelector("body > div.blog-edit-container > div.title > button")).click();Thread.sleep(1000);Alert alert = driver.switchTo().alert();alert.accept();Thread.sleep(1000);String str = driver.findElement(By.cssSelector("#artlistDiv > div > div.title")).getText();Assertions.assertEquals("测试修改文章", str);Thread.sleep(1000);getScreenShot(getClass().getName());}public void PublishArticleSucced() throws InterruptedException, IOException {driver.findElement(By.cssSelector("#title")).sendKeys("测试发布文章");Thread.sleep(2000);driver.findElement(By.cssSelector("body > div.blog-edit-container > div.title > button")).click();Thread.sleep(2000);// 切换到弹窗进行处理Alert alert = driver.switchTo().alert();// 点击确认发布文章alert.accept();// 点击取消继续发布Thread.sleep(1000);alert.dismiss();Thread.sleep(2000);String str = driver.findElement(By.cssSelector("#artlistDiv > div:nth-child(1) > div.title")).getText();Assertions.assertEquals("测试发布文章", str);Thread.sleep(1000);getScreenShot(getClass().getName());}
}
3.7. 测试博客列表页
创建 BlogListTest 类,该类的测试用例有 3 个。
- 页面内容显示是否正常(博客信息、分页按钮、导航栏)
- 导航栏链接是否跳转正常(导航栏、查看全文)
- 存在博客时,博客分页展示功能是否正常
/*** @Description: 测试博客列表页* @Date 2023/9/3 13:16* @Author:*/
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BlogListTest extends AutoTestUtils {// 1. 访问浏览器对象 2. 访问登录页面的 URLpublic static EdgeDriver driver = createDriver();@BeforeAllstatic void baseControl() {driver.get("http://47.108.57.239:7070/blog_list.html");}/*** @param :* @return void* @description 检查页面是否可以正常打开*/@Test@Order(1)void BlogEditPageLoadRight() throws IOException, InterruptedException {driver.findElement(By.cssSelector("#listDiv > div:nth-child(1) > a"));driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)"));driver.findElement(By.cssSelector("body > div.container > div > div.blog-pagnation-wrapper > button:nth-child(1)"));getScreenShot(getClass().getName());}/*** @param :* @return void* @description 测试链接是否跳转正常*/@Test@Order(2)void LinkJump() throws InterruptedException, IOException {// 导航栏driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)")).click();String str = driver.findElement(By.cssSelector("#artlistDiv > div > div.title")).getText();Assertions.assertEquals("测试修改文章", str);Thread.sleep(1000);driver.navigate().back();Thread.sleep(1000);// 查看全文链接driver.findElement(By.cssSelector("#listDiv > div:nth-child(1) > a")).click();Thread.sleep(1000);driver.findElement(By.cssSelector("#title"));getScreenShot(getClass().getName());}/*** @param :* @return void* @description 测试博客列表页的分页展示*/@Test@Order(3)void BlogPaging() throws InterruptedException, IOException {// 点击下一页,params=2driver.findElement(By.cssSelector("body > div.container > div > div.blog-pagnation-wrapper > button:nth-child(3)")).click();Thread.sleep(1000);// 获取当前网页的URLString currentUrl = driver.getCurrentUrl();// 解析URL参数,得到pindex=1,params=1String params = currentUrl.split("\\?")[1].split("=")[1];Assertions.assertEquals("2", params);getScreenShot(getClass().getName());}
}
3.8. 测试博客详情页
创建 BlogContentTest 类,该类的测试用例有 2 个。
- 当前对应 blog_id 的博客的内容信息展示是否正常
- 导航栏及个人信息展示是否正常
/*** @Description: 测试博客详情页* @Date 2023/9/3 14:38* @Author:*/
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BlogContentTest extends AutoTestUtils {// 1. 访问浏览器对象 2. 访问登录页面的 URLpublic static EdgeDriver driver = createDriver();@BeforeAllstatic void baseControl() {driver.get("http://47.108.57.239:7070/blog_list.html");}/*** @param :* @return void* @description 博客详情信息校验测试*/@Test@Order(1)void BlogContentSucced() throws InterruptedException, IOException {// 当前在博客列表页,需要点击某个博客的查看全文,跳转至对应博客详情页String str = driver.findElement(By.cssSelector("#listDiv > div:nth-child(1) > div.title")).getText();driver.findElement(By.cssSelector("#listDiv > div:nth-child(1) > a")).click();Thread.sleep(1000);String str1 = driver.findElement(By.cssSelector("#title")).getText();Assertions.assertEquals(str, str1);driver.findElement(By.cssSelector("body > div.container > div.container-right > div > div.date"));getScreenShot(getClass().getName());}/*** @param :* @return void* @description 导航栏及个人信息展示是否正常*/@Test@Order(2)void BlogEditPageLoadRight() throws IOException{// 当前在博客列表页driver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)"));driver.findElement(By.cssSelector("#username"));getScreenShot(getClass().getName());}
}
3.9. 测试未登录状态
创建 UserNoLoginTest 类,该类的测试用例有 3 个。
- 跳转到我的博客列表页
- 跳转到添加博客页
- 跳转到博客列表页
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class UserNoLogin extends AutoTestUtils {// 1. 访问浏览器对象 2. 访问登录页面的 URLpublic static EdgeDriver driver = createDriver();@BeforeAllstatic void baseControl() {driver.get("http://47.108.57.239:7070/myblog_list.html");}/*** @param :* @return void* @description 测试注销功能(账号退出)*/@Test@Order(1)void WriteOff() throws InterruptedException, IOException {driver.findElement(By.cssSelector("body > div.nav > a:nth-child(6)")).click();Alert alert = driver.switchTo().alert();alert.accept();// 注销完成后,跳转到登录页面driver.findElement(By.cssSelector("#submit"));Thread.sleep(1000);getScreenShot(getClass().getName());}/*** @param :* @return void* @description 测试未登录状态下*/@Test@Order(2)void UserNoLogin1() throws InterruptedException, IOException {// 跳转到添加博客页driver.get("http://47.108.57.239:7070/blog_add.html");Thread.sleep(2000);String str1 = driver.findElement(By.cssSelector("body > div.login-container > div > h3")).getText();Assertions.assertEquals("登陆", str1);getScreenShot(getClass().getName());// 跳转到博客列表页driver.get("http://47.108.57.239:7070/blog_list.html");Thread.sleep(1000);String str2 = driver.findElement(By.cssSelector("#listDiv > div:nth-child(1) > div.title")).getText();Assertions.assertEquals("测试修改文章", str2);getScreenShot(getClass().getName());}
}
4. 自动化测试项目总结
4.1 自动化测试项目实现步骤
- 根据自己的项目,用思维导图的方式设计出UI自动化测试用例;
- 结合自己编写的测试用例,使用 Selenium4 自动化测试工具和 Junit5 单元测试框框架,实现 Web 自动化测试;
- 然后就是进行模块划分,主要是按照两个包划分,一个是工具类包,用来创建驱动对象和提供屏幕截图方法,还有一个包是测试用例包,这个包下面的类是按照以页面为单位编写的测试代码,避免了每个方法都要创建驱动对象的麻烦,最后将这些测试类加入到测试套件中;
- 注意不要等项目整个代码写完后再进行测试,最好是写一部分代码测试一下。比如我编写代码时写完一个页面的测试用例后,再进行测试;
4.2 当前项目测试亮点
- 只创建一次驱动对象,避免每个用例重复创建驱动对象造成时间和资源的浪费;
- 使用了 Junit5 中提供的注解:避免生成过多的对象,造成资源和时间的浪费,提高了自动化的执行效率;
- 测试套件:降低了测试人员的工作量,通过套件一次执行所有要运行的测试用例
- 使用了等待:隐式等待+强制等待(提高了自动化运行效率,提高了自动化的稳定性);
- 使用屏幕截图:方便问题的追溯以及问题的解决;
- 使用参数化:保持用例的简洁,提高代码的可读性;
相关文章:

云端笔记系统-自动化测试
文章目录 1. 思维导图编写 Web 自动化测试用例2. 创建测试项目3. 根据思维导图设计【云端笔记】自动化测试用例3.1. 准备工具类3.2. 测试注册页面3.3. 测试登陆页面3.4. 测试添加博客页3.5. 测试我的博客列表页3.6. 测试修改博客页3.7. 测试博客列表页3.8. 测试博客详情页3.9. …...

将帅要避免五个方面的弱点:蛮干、怕死、好名、冲动、溺爱民众
将帅要避免五个方面的弱点:蛮干、怕死、好名、冲动、溺爱民众 【安志强趣讲《孙子兵法》第28讲】 【原文】 是故屈诸侯者以害,役诸侯者以业,趋诸侯者以利。 【注释】 趋:归附、依附。 【趣讲白话】 所以,用祸患威逼诸侯…...

2023开学礼《乡村振兴战略下传统村落文化旅游设计》许少辉八一新书成都理工大学图书馆
2023开学礼《乡村振兴战略下传统村落文化旅游设计》许少辉八一新书成都理工大学图书馆...

vue的第3篇 第一个vue程序
一 vue的mvvm实践者 1.1 介绍 Model:模型层, 在这里表示JavaScript对象 View:视图层, 在这里表示DOM(HTML操作的元素) ViewModel:连接视图和数据的中间件, Vue.js就是MVVM中的View Model层的实现者 在M…...

线性求逆元
先暴力求出 1 n ! \frac 1 {n!} n!1往回推出 1 i ! \frac 1 {i!} i!1 1 i ( i − 1 ) ! i ! \Large \frac 1 i\frac{(i-1)!}{i!} i1i!(i−1)!...

第一章 USB应用笔记之USB初步了解
USB应用笔记之USB初步了解 文章目录 USB应用笔记之USB初步了解前言USB的优点:USB版本发展USB速度以及电气接口USB传输过程USB开发抓包工具:USB传输方式1.控制传输特点:2.中断传输的特点3. 批量传输的特点4.实时传输(同步传输)的特…...

小白入门python
建议用vscode进行代码学习 vscode下载地址:Download Visual Studio Code - Mac, Linux, Windows 左侧点击扩展安装python,右下角选择python版本,记得配置系统环境变量,python在系统(cmd)的版本由环境变量优先级决定,在编程软件中由自己选择解释器...

《Kubernetes部署篇:Ubuntu20.04基于containerd部署kubernetes1.24.17集群(多主多从)》
一、架构图 如下图所示: 二、环境信息 1、部署规划主机名K8S版本系统版本内核版本IP地址备注k8s-master-631.24.17Ubuntu 20.04.5 LTS5.15.0-69-generic192.168.1.63master节点 + etcd节点k8s-master-641.24.17Ubuntu 20.04.5 LTS5.15.0-69-generic192.168.1.64master节点 + …...

Adobe Illustrator 2023 for mac安装教程,可用。
Adobe Illustrator 是行业标准的矢量图形应用程序,可以为印刷、网络、视频和移动设备创建logos、图标、绘图、排版和插图。数以百万计的设计师和艺术家使用Illustrator CC创作,从网页图标和产品包装到书籍插图和广告牌。此版本是2023版本,适配…...

ElasticSearch(一)数据类型
ElasticSearch(一)数据类型 1.简述 Es数据类型分为基础数据类型和复杂类型数据,掌握ES数据类型才能进一步使用ES检索数据内容。 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot…...

Spark-Core核心算子
文章目录 一、数据源获取1、从集合中获取2、从外部存储系统创建3、从其它RDD中创建4、分区规则—load数据时 二、转换算子(Transformation)1、Value类型1.1 map()_1.2 mapPartitions()1.3 mapPartitionsWithIndex(不常用)1.4 filterMap()_扁平化(合并流)…...

Linux和Windows下防火墙、端口和进程相关命令
🚀1 防火墙 1.1 firewall systemctl stop firewalld.service # 关闭防火墙 systemctl start firewalld.service # 开启防火墙 systemctl restart firewalld.service # 重启防火墙 systemctl status firewalld.service # 防火墙状态 firewall-cmd --reload # 重…...

2021年09月 C/C++(六级)真题解析#中国电子学会#全国青少年软件编程等级考试
C/C++编程(1~8级)全部真题・点这里 第1题:双端队列 定义一个双端队列,进队操作与普通队列一样,从队尾进入。出队操作既可以从队头,也可以从队尾。编程实现这个数据结构。 时间限制:1000 内存限制:65535 输入 第一行输入一个整数t,代表测试数据的组数。 每组数据的第一…...

【算法】滑动窗口
滑动窗口应用场景 关键词: 满足xxx条件(计算结果,出现次数,同时包含) 最长/最短 子串/子数组/子序列 例如:长度最小的子数组 滑动窗使用思路(寻找最长) 核心:左右双指…...

JS获取Beego渲染模板Temple时传递的数据
如果纯粹的JS调用接口,获取后端数据很直接坦率,JSON解析也就可以了。 如果需要JS获取HTML页面加载时,后端传回来的一些数据,我们也可以通过以下的方式进行获取。范例如下: //通过person_name字段传递参数到html页面中…...

代码随想录训练营第五十二天|300.最长递增子序列、674. 最长连续递增序列、718. 最长重复子数组
300.最长递增子序列 题目链接/文章讲解/视频讲解:代码随想录 1.代码展示 //300.最长递增子序列 int lengthOfLIS(vector<int>& nums) {if (nums.size() 1) {return 1;}//step1 构建dp数组//dp[i]的含义是长度未nums数组中长度为i 1的数组的最长子序列长…...

前端三大Css处理器之Less
Less是Css预处理器之一,分别有Sass、Less、Stylus这三个。 Lesshttps://lesscss.org/ Less是用JavaScript编写的,事实上,Less是一个JavaScript库,他通过混合、变量、嵌套和规则设置循环扩展了原生普通Css的功能。Less的少数…...

Win 教程 Win7实现隔空投送
一直觉得自己写的不是技术,而是情怀,一个个的教程是自己这一路走来的痕迹。靠专业技能的成功是最具可复制性的,希望我的这条路能让你们少走弯路,希望我能帮你们抹去知识的蒙尘,希望我能帮你们理清知识的脉络࿰…...

代码随想录算法训练营Day45 | 70. 爬楼梯 (进阶) | 322. 零钱兑换 | 279. 完全平方数
文章目录 70. 爬楼梯 (进阶)322. 零钱兑换二维数组滚动数组 279. 完全平方数 70. 爬楼梯 (进阶) 题目链接 | 理论基础 以完全背包的思路来解题,正如组合总和 Ⅳ 中提到的一样。在本题中,先背包后物品的思路就显得非常合理明显了。 本题中的物品就是可…...

算法训练营第四十一天(9.2)| 动态规划Part11:最长公共子序列
Leecode 1143.最长公共子序列 题目地址:力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台 题目类型:最长子序列 class Solution { public:int longestCommonSubsequence(string text1, string text2) {int m text1.size(), n t…...

k8s基于rbac权限管理serviceAccount授权管理
测试通过http访问apiServer curl没有证书不能通过https来访问apiServer需要使用kubectl代理 #使用kubectl代理 kubectl proxy --port8111& #curl访问 api/v1 是资源所属群组/版本 即创建资源时定义的apiVersion #后边跟的是要访问的资源 #查看所有命名空间 #查看核心资源用…...

linux URL访问工具
URL访问工具 有时候想在命令行下通过http访问接口/网页,可以使用curl来进行操作 发起请求 curl www.baidu.com 会返回网页内容 参数选项 -i参数 使用-i参数,会返回响应header curl -i www.baidu.com -I参数 使用-I参数,只会返回响应header cu…...

CCF-CSP 29次 第五题【202303-5 施肥】
计算机软件能力认证考试系统 题解(35分): 枚举每个区间,再枚举每个施肥车,看所有的施肥车能不能把这个区间填满 #include<bits/stdc.h> using namespace std; const int N410; int n,m; typedef pair<int,…...

前端基础4——jQuery
文章目录 一、基本了解1.1 导入jQuery库1.2 基本语法1.3 选择器 二、操作HTML2.1 隐藏和显示元素2.2 获取与设置内容2.3 获取、设置和删除属性2.4 添加元素2.5 删除元素2.6 设置CSS样式 三、jQuery Ajax3.1 基本语法3.2 回调函数3.3 常用HTTP方法3.4 案例一3.4.1 准备工作3.4.2…...

测试人:“躺平?不可能的“, 盘点测试人在职场的优势
之前有这么一个段子:有人喜欢创造世界,他们做了程序员;有人喜欢拯救世界,他们做了测试员!近几年,测试工程师在企业究竟是怎么样的发展?随着企业对于用户体验的满意度越来越重视,更加…...

C++:初识类与this指针
文章目录 前言一、类类的定义和实例化类的访问限定符类的作用域计算类的大小 二、类的成员函数的this指针总结 个人主页 : 个人主页 个人专栏 : 《数据结构》 《C语言》《C》 前言 一、类 类的定义和实例化 注意类定义结束时后面分号( ; )不能省略。 类…...

2023应届生java面试紧张失误之一:CAS口误说成开心锁-笑坏面试官
源于:XX网,如果冒犯,表示歉意 面试官:什么是CAS 我:这个简单,开心锁 面试官:WTF? 我:一脸自信,对,就是这个 面试官:哈哈大笑ÿ…...

Excel_VBA程序文件的加密及解密说明
VBA应用技巧及疑难解答 Excel_VBA程序文件的加密及解密 在您看到这个文档的时候,请和我一起念:“唵嘛呢叭咪吽”“唵嘛呢叭咪吽”“唵嘛呢叭咪吽”,为自己所得而感恩,为付出者赞叹功德。 本不想分享之一技术,但众多学…...

Flutter关于StatefulWidget中State刷新时机的一点实用理解
刚入门flutter开发,使用StatefulWidget踩了很多坑,就我遇到典型问题谈谈见解。 1.initState方法只会在控件初始化的时候执行一遍。 2.控件内部执行setState方法,则会每次执行build方法。 3.控件销毁会执行dispose方法,所以一些…...

CS420 课程笔记 P2 - 内存编辑和基础的 GameHacking 尝试
文章目录 IntroductionOperating SystemToolsMemory ScanningMemory ScanExamples!Conclusion Introduction 本节将介绍操作系统的基础知识和内存扫描,这可以说是 game hacking 中最重要的技能,我们不会深入讨论操作系统,因为这本身就是一门…...