当前位置: 首页 > news >正文

对博客系统基本功能进行自动化测试(Junit + Selenium)

环境搭建:

  1. 浏览器:
    1. 本次测试使用Chrome浏览器
    2. 在jdk的bin目录下安装对应浏览器驱动(尽量选择与浏览器版本相近的驱动)chromedriver.storage.googleapis.com/index.html
  2. Junit依赖:
             <!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api --><dependency><groupId>org.junit.jupiter</groupId><!--编写用例的基本注解--><artifactId>junit-jupiter-api</artifactId><version>5.9.1</version></dependency><dependency><!--参数化测试依赖--><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-params</artifactId><version>5.9.1</version></dependency><dependency><!--这个库提供JUnit平台的核心功能,比如共享的测试接口、注解和工具类--><groupId>org.junit.platform</groupId><artifactId>junit-platform-commons</artifactId><version>1.9.1</version> <!-- 请根据需要调整为与JUnit 5.9.1兼容的版本 --></dependency><!-- https://mvnrepository.com/artifact/org.junit.platform/junit-platform-suite --><dependency><groupId>org.junit.platform</groupId><artifactId>junit-platform-suite</artifactId><version>1.9.1</version><scope>test</scope></dependency><dependency><groupId>org.junit.platform</groupId><artifactId>junit-platform-suite-api</artifactId><version>1.9.1</version></dependency><!--JUnit Jupiter的测试引擎,实现了JUnit Platform的TestEngine接口。它负责发现和执行使用JUnit Jupiter API编写的测试。--><dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-engine</artifactId><version>5.9.1</version><scope>test</scope></dependency>
  3. Selenium依赖
        <dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-java</artifactId><version>3.141.59</version></dependency><dependency><groupId>org.seleniumhq.selenium</groupId><artifactId>selenium-support</artifactId><version>3.141.59</version></dependency>

测试用例:

网站:登陆页面

项目结构:

InitAndQuit进行测试初始化和收尾工作

TestItem包含对各个页面基本功能的自动化测试用例

初始化以及资源关闭:

/*** @ClassName InitAndQuit* @Description 初识化测试相关以及测试结束资源关闭* @Author 86153* @Date 2024/4/30 10:20* @Version 1.0**/
public class InitAndQuit {static WebDriver webDriver;@BeforeAllstatic void init() {webDriver = new ChromeDriver();}@AfterAllstatic void quit() {webDriver.quit();}
}

登录页面测试用例:

  • 输入给定邮箱点击获取验证码:
//验证码private static String emailCode;//在注册页面点击获取验证码按钮@ParameterizedTest@CsvFileSource(resources = "login.csv")@Order(0)void loginTest(String account) throws InterruptedException {webDriver.get("http://8.130.70.131:8080/login.html");webDriver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);webDriver.findElement(By.cssSelector("#username")).sendKeys(account);WebDriverWait wait = new WebDriverWait(webDriver,10);//这里 获取验证码 和 提交按钮为俩个一样的button,所以需要进行按钮的选择WebElement clickElement = wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#submit")));List<WebElement> elements = webDriver.findElements(By.cssSelector("#submit"));elements.get(0).click();}
  • 从邮箱中拿到验证码
 /*邮箱登录拿到验证码*/@Test@Order(1)void getCaptcha() throws InterruptedException {webDriver.get("https://www.baidu.com/");webDriver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);webDriver.findElement(By.cssSelector(".s_ipt")).sendKeys("https://mail.qq.com/");webDriver.findElement(By.cssSelector("#su")).click();webDriver.manage().timeouts().implicitlyWait(5, TimeUnit.SECONDS);//保存当前窗口的句柄String originalWindow = webDriver.getWindowHandle();webDriver.findElement(By.cssSelector("#\\31  > div > div:nth-child(1) > h3 > a")).click();//切换窗口Set<String> set = webDriver.getWindowHandles();for(String cur : set) {if(!cur.equals(originalWindow)) {webDriver.switchTo().window(cur);}}//登录邮箱//注意这里切换frame时要先去选择获取到frameWebElement iframe = webDriver.findElement(By.cssSelector("#QQMailSdkTool_login_loginBox_qq > iframe"));webDriver.switchTo().frame(iframe);WebElement iframe1 = webDriver.findElement(By.cssSelector("#ptlogin_iframe"));webDriver.switchTo().frame(iframe1);//点击用户头像进行登录(电脑登陆了QQ)webDriver.findElement(By.cssSelector("#img_out_3224881242")).click();sleep(10000);//进入对应邮件webDriver.findElement(By.cssSelector("#mailMainApp > div.frame_main.mail_app > div > div > div > div.mailList_listWrapper > div.mailList_group > div:nth-child(1) > div.mailList_group_item_cnt > table > tbody > tr:nth-child(1)")).click();//拿到验证码WebElement element = webDriver.findElement(By.cssSelector("#readmail_content_html > span"));String text = element.getText();emailCode = text;}
  • 登录
 //登陆页面测试@ParameterizedTest@CsvFileSource(resources = "login.csv")@Order(2)void loginTest(String account,String password) throws InterruptedException {//进入登陆页面webDriver.get("http://8.130.70.131:8080/login.html");//隐式等待webDriver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);//输入账号密码验证码webDriver.findElement(By.cssSelector("#username")).sendKeys(account);webDriver.findElement(By.cssSelector("#password")).sendKeys(password);webDriver.findElement(By.cssSelector("#captcha")).sendKeys(emailCode);//显示等待WebDriverWait wait = new WebDriverWait(webDriver,10);//这里 获取验证码 和 提交按钮为俩个一样的button,所以需要进行按钮的选择WebElement clickElement = wait.until(ExpectedConditions.elementToBeClickable(By.cssSelector("#submit")));List<WebElement> elements = webDriver.findElements(By.cssSelector("#submit"));elements.get(1).click();//显示等待,等待弹窗出现//注意这里是个坑,弹窗不属于页面内的元素,不能使用隐式等待wait.until(ExpectedConditions.alertIsPresent());//弹窗选择webDriver.switchTo().alert().accept();//等待进入新页面webDriver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);//校验urlString currentURL = webDriver.getCurrentUrl();Assertions.assertEquals("http://8.130.70.131:8080/myblog_list.html",currentURL);}

列表页测试用例:

 //列表页自动化测试/*** 如果列表页博客数量不为0表示测试通过**/@Test@Order(3)void listTest() {webDriver.get("hhttp://8.130.70.131:8080/blog_list.html");webDriver.manage().timeouts().implicitlyWait(5,TimeUnit.SECONDS);int size = webDriver.findElements(By.cssSelector(".title")).size();System.out.println(size);Assertions.assertNotEquals(0,size);}

个人列表页测试用例:

//个人列表页测试@Test@Order(4)void selfListTest() {webDriver.get("http://8.130.70.131:8080/myblog_list.html");//文章数量不为0测试List<WebElement> list = webDriver.findElements(By.cssSelector(".title"));int size = webDriver.findElements(By.cssSelector(".title")).size();System.out.println(size);Assertions.assertNotEquals(0,list.size());//测试“主页”按钮webDriver.findElement(By.cssSelector("body > div.nav > a:nth-child(4)")).click();webDriver.manage().timeouts().implicitlyWait(5,TimeUnit.SECONDS);String curUrl = webDriver.getCurrentUrl();Assertions.assertEquals("http://8.130.70.131:8080/blog_list.html",curUrl);//回退到个人主页webDriver.navigate().back();//测试“写博客按钮”webDriver.findElement(By.cssSelector("body > div.nav > a:nth-child(5)")).click();webDriver.manage().timeouts().implicitlyWait(5,TimeUnit.SECONDS);curUrl = webDriver.getCurrentUrl();Assertions.assertEquals("http://8.130.70.131:8080/blog_add.html",curUrl);webDriver.navigate().back();/* //测试“注销”按钮webDriver.findElement(By.cssSelector("body > div.nav > a:nth-child(6)")).click();webDriver.manage().timeouts().implicitlyWait(5,TimeUnit.SECONDS);curUrl = webDriver.getCurrentUrl();Assertions.assertEquals("http://8.130.70.131:8080/login.html",curUrl);*/}

博客详情页测试用例:

    //博客详情页测试@ParameterizedTest@Order(5)@CsvFileSource(resources = "detail.csv")void detailTest(String destUrl,String destPageTitle,String destBlogTitle) {//进入列表页webDriver.get("http://8.130.70.131:8080/blog_list.html");//点击文章详情按钮,进入博客详情页webDriver.findElement(By.cssSelector("#artListDiv > div:nth-child(1) > a")).click();//校验页面url,页面title,博客题目webDriver.manage().timeouts().implicitlyWait(5,TimeUnit.SECONDS);String url = webDriver.getCurrentUrl();String pageTitle = webDriver.getTitle();String blogTitle = webDriver.findElement(By.cssSelector("#title")).getText();Assertions.assertEquals(destUrl,url);Assertions.assertEquals(destPageTitle,pageTitle);Assertions.assertEquals(destBlogTitle,blogTitle);}

编辑页测试用例:

//博客编辑页测试@ParameterizedTest@Order(6)@CsvFileSource(resources = "edit.csv")void editTest(String data,String title) {webDriver.get("http://8.130.70.131:8080/blog_add.html");webDriver.manage().timeouts().implicitlyWait(5,TimeUnit.SECONDS);/* //直接使用通过js设置文章标题((JavascriptExecutor)webDriver).executeScript("document.getElementById(\"title\").value=\"自动化测试\"");*/webDriver.findElement(By.cssSelector("#title")).sendKeys("自动化测试");//发布文章webDriver.findElement(By.cssSelector("body > div.blog-edit-container > div.title > button")).click();//这里有一个”是否继续添加博客“的弹窗,进行选择后才跳转WebDriverWait wait = new WebDriverWait(webDriver,5);wait.until(ExpectedConditions.alertIsPresent());webDriver.switchTo().alert().dismiss();webDriver.manage().timeouts().implicitlyWait(5,TimeUnit.SECONDS);//校验url跳转String cur_url = webDriver.getCurrentUrl();Assertions.assertEquals("http://8.130.70.131:8080/myblog_list.html",cur_url);//校验第一篇博客的发布时间,标题String publishDate = webDriver.findElement(By.cssSelector("#artListDiv > div:nth-child(1) > div.date")).getText();String publishTitle = webDriver.findElement(By.cssSelector("#artListDiv > div:nth-child(1) > div.title")).getText();Assertions.assertEquals(title,publishTitle);if(publishDate.contains(data)) {System.out.println("测试通过");}else {System.out.println("发布时间错误");}//删除博客webDriver.findElement(By.cssSelector("#artListDiv > div:nth-child(1) > a:nth-child(6)")).click();webDriver.manage().timeouts().implicitlyWait(5,TimeUnit.SECONDS);//弹窗选择wait.until(ExpectedConditions.alertIsPresent());webDriver.switchTo().alert().accept();//校验第一篇博客是否被删除WebElement after_delete_title = webDriver.findElement(By.cssSelector("#artListDiv > div:nth-child(1) > div.title"));Assertions.assertNotEquals(title,after_delete_title);}

注销:

   //注销@Test@Order(7)void login_out() {webDriver.manage().timeouts().implicitlyWait(5,TimeUnit.SECONDS);//点击注销按钮webDriver.findElement(By.cssSelector("body > div.nav > a:nth-child(6)")).click();//显示等待alter弹窗出现WebDriverWait wait = new WebDriverWait(webDriver,5);wait.until(ExpectedConditions.alertIsPresent());//选择弹框并进行确定webDriver.switchTo().alert().accept();webDriver.manage().timeouts().implicitlyWait(5,TimeUnit.SECONDS);String cur_url = webDriver.getCurrentUrl();Assertions.assertEquals("http://8.130.70.131:8080/login.html",cur_url);}

相关文章:

对博客系统基本功能进行自动化测试(Junit + Selenium)

环境搭建&#xff1a; 浏览器&#xff1a; 本次测试使用Chrome浏览器在jdk的bin目录下安装对应浏览器驱动&#xff08;尽量选择与浏览器版本相近的驱动&#xff09;chromedriver.storage.googleapis.com/index.htmlJunit依赖&#xff1a; <!-- https://mvnreposit…...

《换你来当爹》:AI驱动的养成游戏,探索虚拟亲子关系的新模式

AI技术如何重塑我们对游戏互动的认知 在人工智能技术的浪潮下&#xff0c;一款名为《换你来当爹》的AI养成游戏&#xff0c;以其创新的互动模式和个性化体验&#xff0c;吸引了游戏爱好者的目光。这款游戏利用了先进的LLM技术&#xff0c;通过AI实时生成剧情和图片&#xff0c…...

在idea中使用vue

一、安装node.js 1、在node.js官网&#xff08;下载 | Node.js 中文网&#xff09;上下载适合自己电脑版本的node.js压缩包 2、下载完成后进行解压并安装&#xff0c;一定要记住自己的安装路径 一直点击next即可&#xff0c;这部选第一个 3、安装成功后&#xff0c;按住winR输入…...

Linux系统编程:进程控制

1.进程创建 1.1 fork函数 fork&#xff08;&#xff09;通过复制调用进程来创建一个新进程。新进程称为子进程&#xff0c;是调用进程的精确副本 进程&#xff0c;但以下几点除外&#xff1a; 子进程有自己的PID&#xff0c;此PID与任何现有进程组的ID不匹配子进程的父进程ID…...

Android 异常开机半屏重启代码分析

Android 的稳定性是 Android 性能的一个重要指标&#xff0c;它也是 App 质量构建体系中最基本和最关键的一环&#xff1b;如果应用经常崩溃&#xff0c;或者关键功能不可用&#xff0c;那显然会对我们的留存产生重大影响所以为了保障应用的稳定性&#xff0c;我们首先应该树立…...

Kafka从0到消费者开发

安装ZK Index of /zookeeper/zookeeper-3.9.2 下载安装包 一定要下载-bin的&#xff0c;不带bin的是源码&#xff0c;没有编译的&#xff0c;无法执行。-bin的才可以执行。 解压 tar -zxvf apache-zookeeper-3.9.2-bin.tar.gz 备份配置 cp zoo_sample.cfg zoo_sample.cfg-b…...

01-项目功能,架构设计介绍

稻草快速开发平台 开发背景就是通过此项目介绍使用SpringBoot Vue3两大技术栈开发一个拥有动态权限、路由的前后端分离项目&#xff0c;此项目可以继续完善&#xff0c;成为一个模板为将来快速开发做铺垫。 实现功能 开发流程 通过命令构建前端项目在VSCode中开发&#xff…...

bvh 好用强大的播放器源码

目录 效果图&#xff1a; 显示旋转角度&#xff1a; 显示骨骼名称 下载链接&#xff1a; 可以显示骨骼名称&#xff0c;旋转角度&#xff0c;自适应大小&#xff0c;支持3维npz数据可视化 python实现&#xff0c;提供源代码&#xff0c;修改和完善很方便。 根据3维npz生成…...

安阳在线知识付费系统,培训机构如何进行课程体系的设置?

校外培训不管是从招生还是课程体系都是截然不同的&#xff0c;在课程体系设置上&#xff0c;不同的层次设计也就不同。课程体系设计在功能诉求上可以分为入门课、核心课、高利润课、种子课四个类别。下面为大家介绍一下。 1、入门课 “入门课”就是最易、最省、最少障碍的满足家…...

网络编程:服务器模型-并发服务器-多进程

并发服务器概念&#xff1a; 并发服务器同一时刻可以处理多个客户机的请求 设计思路&#xff1a; 并发服务器是在循环服务器基础上优化过来的 &#xff08;1&#xff09;每连接一个客户机&#xff0c;服务器立马创建子进程或者子线程来跟新的客户机通信 &#xff08;accept之后…...

React 基础案例

React的特点&#xff1a; 1、声明式编程 2、组件化开发 3、多平台适配yuan 原生实现&#xff1a; <h2 class"title"></h2><button class"btn">改变文本</button><script>let msg "Hello World";const titleEl d…...

【Python探索之旅】选择结构(条件语句)

文章目录 条件结构&#xff1a; 1.1 if单分支结构 1.2 if-else 多分支结构 1.3 if-elif 多重结构&#xff1a; 完结撒花​ 前言 Python条件语句是通过一条或多条语句的执行结果&#xff08;True或者False&#xff09;来决定执行的代码块。 Python提供了顺序、选择、循环三…...

Recommender ~ Collaborative filtering

Using per-item features User j 预测 movie i&#xff1a; Cost Function: 仅求和用户投票过的电影。 常规规范化&#xff08;usual normalization&#xff09;&#xff1a;1/2m 正则化项&#xff1a;阻止过拟合 在知晓X的前提下&#xff0c;如何学习w&#xff0c;b参数…...

我觉得POC应该贴近实际

今天我看到一位老师给我一份测试数据。 这是三个国产数据库。算是分布式的。其中有两个和我比较熟悉&#xff0c;但是这个数据看上去并不好。看上去第一个黄色的数据库数据是这里最好的了。但是即使如此&#xff0c;我相信大部分做数据库的人都知道。MySQL和PostgreSQL平时拿出…...

AI 情感聊天机器人工作之旅 —— 与复读机问题的相遇与别离

前言&#xff1a;先前在杭州的一家大模型公司从事海外闲聊机器人产品&#xff0c;目前已经离职&#xff0c;文章主要讨论在闲聊场景下遇到的“复读机”问题以及一些我个人的思考和解决方案。文章内部已经对相关公司和人员信息做了去敏&#xff0c;如仍涉及到机密等情况&#xf…...

如何使用ArcGIS Pro进行选房分析

无论是研究城市规划布局还是寻找理想的住房&#xff0c;都需要综合考虑购物、医疗、教育和休闲等多方面因素&#xff0c;此时我们的GIS软件就可以派上用场了&#xff0c;这里为大家介绍一下如何使用 ArcGIS Pro 进行选房分析&#xff0c;希望能对你有所帮助。 数据来源 教程所…...

android图标底色问题,debug与release不一致

背景 在android 8&#xff08;sdk 26&#xff09;之前的版本&#xff0c;直接使用图片文件作为图标&#xff0c;开发时比较容易控制图标&#xff0c;但是不同的安卓定制版本就不容易统一图标风格了。 在android 8及之后的版本&#xff0c;图标对应的是ic_launcher.xml&#x…...

如何提高自己的全局视野?

以下是一些可以帮助提高全局视野的方法&#xff1a; 1. 广泛学习不同领域知识&#xff1a;包括但不限于技术相关的各个领域、业务知识、行业动态等&#xff0c;拓宽知识面。 2. 参与大型项目&#xff1a;积极投身到复杂的、规模较大的项目中&#xff0c;在实践中感受和理解系…...

element ui的确认提示框文字样式修改

修改确认提示框文字样式修改&#xff0c;使用message属性修改&#xff1a; 例&#xff1a; js代码&#xff1a; this.$msgbox({title: 确定要删除吗?,message: this.$createElement(p, null, [this.$createElement(span, { style: color: red }, 该素材一旦删除&#xff0c;…...

Typescript 哲学 - ts模块使用最佳实践

ts的作用域 默认是全局&#xff08;global&#xff09;&#xff0c;这也是为什么在 两个ts文件声明同一个变量报错变量名冲突&#xff0c;解决方法是使某个文件以模块的形式存在&#xff08;文件顶层使用 export 、import &#xff09; In TypeScript, just as in ECMAScript 2…...

Linux应用开发之网络套接字编程(实例篇)

服务端与客户端单连接 服务端代码 #include <sys/socket.h> #include <sys/types.h> #include <netinet/in.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <arpa/inet.h> #include <pthread.h> …...

C++实现分布式网络通信框架RPC(3)--rpc调用端

目录 一、前言 二、UserServiceRpc_Stub 三、 CallMethod方法的重写 头文件 实现 四、rpc调用端的调用 实现 五、 google::protobuf::RpcController *controller 头文件 实现 六、总结 一、前言 在前边的文章中&#xff0c;我们已经大致实现了rpc服务端的各项功能代…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

CRMEB 框架中 PHP 上传扩展开发:涵盖本地上传及阿里云 OSS、腾讯云 COS、七牛云

目前已有本地上传、阿里云OSS上传、腾讯云COS上传、七牛云上传扩展 扩展入口文件 文件目录 crmeb\services\upload\Upload.php namespace crmeb\services\upload;use crmeb\basic\BaseManager; use think\facade\Config;/*** Class Upload* package crmeb\services\upload* …...

如何在网页里填写 PDF 表格?

有时候&#xff0c;你可能希望用户能在你的网站上填写 PDF 表单。然而&#xff0c;这件事并不简单&#xff0c;因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件&#xff0c;但原生并不支持编辑或填写它们。更糟的是&#xff0c;如果你想收集表单数据&#xff…...

TSN交换机正在重构工业网络,PROFINET和EtherCAT会被取代吗?

在工业自动化持续演进的今天&#xff0c;通信网络的角色正变得愈发关键。 2025年6月6日&#xff0c;为期三天的华南国际工业博览会在深圳国际会展中心&#xff08;宝安&#xff09;圆满落幕。作为国内工业通信领域的技术型企业&#xff0c;光路科技&#xff08;Fiberroad&…...

【Linux】自动化构建-Make/Makefile

前言 上文我们讲到了Linux中的编译器gcc/g 【Linux】编译器gcc/g及其库的详细介绍-CSDN博客 本来我们将一个对于编译来说很重要的工具&#xff1a;make/makfile 1.背景 在一个工程中源文件不计其数&#xff0c;其按类型、功能、模块分别放在若干个目录中&#xff0c;mak…...

绕过 Xcode?使用 Appuploader和主流工具实现 iOS 上架自动化

iOS 应用的发布流程一直是开发链路中最“苹果味”的环节&#xff1a;强依赖 Xcode、必须使用 macOS、各种证书和描述文件配置……对很多跨平台开发者来说&#xff0c;这一套流程并不友好。 特别是当你的项目主要在 Windows 或 Linux 下开发&#xff08;例如 Flutter、React Na…...

LangChain 中的文档加载器(Loader)与文本切分器(Splitter)详解《二》

&#x1f9e0; LangChain 中 TextSplitter 的使用详解&#xff1a;从基础到进阶&#xff08;附代码&#xff09; 一、前言 在处理大规模文本数据时&#xff0c;特别是在构建知识库或进行大模型训练与推理时&#xff0c;文本切分&#xff08;Text Splitting&#xff09; 是一个…...

游戏开发中常见的战斗数值英文缩写对照表

游戏开发中常见的战斗数值英文缩写对照表 基础属性&#xff08;Basic Attributes&#xff09; 缩写英文全称中文释义常见使用场景HPHit Points / Health Points生命值角色生存状态MPMana Points / Magic Points魔法值技能释放资源SPStamina Points体力值动作消耗资源APAction…...