Java个人博客系统--基于Springboot的设计与实现
目录
一、项目概述
应用技术
接口实现:
数据库定义:
数据库建表:
博客表数据库相关操作:
添加项⽬公共模块
加密MD5
页面展示:http://121.41.168.121:8080/blog_login.html
项目源码:https://gitee.com/li-dot/blogs
二、对博客系统进行自动化测试
测试用例图Docs
使用Selenium进行测试
一、项目概述
应用技术
接口实现:
数据库定义:
数据库建表:
--建表SQL
create database if not exists `java_blog_spring` charset utf8mb4;
--⽤户表
drop table if exists `java_blog_spring`.`user`;
CREATE TABLE `java_blog_spring`.`user` (`id` INT NOT NULL AUTO_INCREMENT,`user_name` VARCHAR(128) NOT NULL,`password` VARCHAR(128) NOT NULL,`github_url` VARCHAR(128) NULL,`delete_flag` TINYINT(4) NULL DEFAULT 0,`create_time` TIMESTAMP NULL DEFAULT current_timestamp(),PRIMARY KEY (`id`),UNIQUE INDEX `user_name_UNIQUE` (`user_name` ASC))
ENGINE = InnoDB DEFAULT CHARACTER SET = utf8mb4 COMMENT = '⽤户表';
--博客表
drop table if exists `java_blog_spring`.`blog`;
CREATE TABLE `java_blog_spring`.`blog` (`id` INT NOT NULL AUTO_INCREMENT,`title` VARCHAR(200) NULL,`content` TEXT NULL,`user_id` INT(11) NULL,`delete_flag` TINYINT(4) NULL DEFAULT 0,`create_time` TIMESTAMP NULL DEFAULT current_timestamp(),PRIMARY KEY (`id`))
ENGINE = InnoDB DEFAULT CHARSET = utf8mb4 COMMENT = '博客表';
--新增⽤户信息
insert into `java_blog_spring`.`user` (`user_name`, `password`,`github_url
`)values("zhangsan","123456","https://gitee.com");
insert into `java_blog_spring`.`user` (`user_name`, `password`,`github_url
`)values("lisi","123456","https://gitee.com");
insert into `java_blog_spring`.`blog` (`title`,`content`,`user_id`) values
("第⼀篇博客","111我是博客正⽂我是博客正⽂我是博客正⽂",1);
insert into `java_blog_spring`.`blog` (`title`,`content`,`user_id`) values
("第⼆篇博客","222我是博客正⽂我是博客正⽂我是博客正⽂",2);
博客表数据库相关操作:
......
添加项⽬公共模块
加密MD5

页面展示:http://121.41.168.121:8080/blog_login.html
用户名:zhangsan/lisi
密码:123456
博客登录界面:
博客列表页:
博客详情页:
写博客页:
项目源码:https://gitee.com/li-dot/blogs
二、对博客系统进行自动化测试
测试用例图Docs
使用Selenium进行测试
package BlogTest;import org.junit.jupiter.api.*;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvFileSource;
import org.junit.jupiter.params.provider.CsvSource;
import org.junit.jupiter.params.provider.ValueSource;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.remote.RemoteWebDriverBuilder;import java.util.concurrent.TimeUnit;import static java.lang.Thread.sleep;/*** @author Dian* Description* Date:2023/8/5:23:47*/
@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
public class BlogCases extends InitAndEnd{/*** 登录*/@Order(1)@ParameterizedTest //参数化@CsvSource("zhangsan,123456")void Login(String userName,String password) throws InterruptedException {System.out.println(userName);System.out.println(password);//打开登陆页面webDriver.get("http://121.41.168.121:8080/blog_login.html");//输入用户名webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);webDriver.findElement(By.cssSelector("#userName")).sendKeys(userName);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);//输入密码webDriver.findElement(By.cssSelector("#password")).sendKeys(password);webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);//点击提交webDriver.findElement(By.cssSelector("#submit")).click();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);sleep(2000);//校验当前登录的用户是不是zhangsan,如果是则测试通过,否则测试不通过String user_name = webDriver.findElement(By.cssSelector("h3")).getText();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);Assertions.assertEquals(userName,user_name);}/***博客列表*/@Order(2)
@Testvoid BlogList(){webDriver.get("http://121.41.168.121:8080/blog_list.html");webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);int blog_num = webDriver.findElements(By.cssSelector(".title")).size();Assertions.assertNotEquals(0,blog_num);String page_title = webDriver.getTitle();Assertions.assertEquals(page_title,"博客列表页");}
/*** 博客详情页校验*/
@Order(3)
@Test
void BlogDetail(){//打开列表页webDriver.get("http://121.41.168.121:8080/blog_list.html");webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);//找到查看全文按钮webDriver.findElement(By.xpath("/html/body/div[2]/div[2]/div[1]/a")).click();webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);//获取博客标题String blog_title = webDriver.findElement(By.cssSelector("body > div.container > div.right > div:nth-child(1) > div.title")).getText();//如果博客正文不为空,测试通过//否则测试不通过
Assertions.assertNotNull(blog_title);
}/*** 写博客*/
@Order(4)
@Testvoid EditBlog() throws InterruptedException {// 找到写博客按钮,点击webDriver.findElement(By.cssSelector("body > div.nav > a:nth-child(5)")).click();webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);// 执行js(选中标题输入框,输入字符串)((JavascriptExecutor)webDriver).executeScript("document.querySelector(\"#title\").value =\"自动化测试\"");webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);webDriver.findElement(By.cssSelector("#submit")).click();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 校验页面跳转到列表页sleep(3000);String cur_url = webDriver.getCurrentUrl();// 校验第一条博客标题是不是刚刚发布的博客标题String first_blog_title = webDriver.findElement(By.cssSelector("body > div.container > div.right > div:nth-child(6) > div.title")).getText();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);Assertions.assertEquals("自动化测试",first_blog_title);
}/*** 删除博客*/@Order(5)@Testvoid DeleteBlog(){// 找到查看全文按钮并且点击webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);webDriver.findElement(By.xpath("/html/body/div[2]/div[2]/div[1]/a")).click();webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);// 找到删除按钮,点击webDriver.findElement(By.cssSelector("body > div.container > div.right > div > div.operating > button:nth-child(2)")).click();// 校验当前页面是否跳转到博客列表页面webDriver.manage().timeouts().implicitlyWait(3,TimeUnit.SECONDS);String cur_url = webDriver.getCurrentUrl();Assertions.assertEquals("http://121.41.168.121:8080/blog_list.html",cur_url);// 获取博客发布是时间String blog_release_time = webDriver.findElement(By.xpath("/html/body/div[2]/div[2]/div/div[2]")).getText();// 如果博客发布时间 包括2023-06-02测试 不通过if(blog_release_time.contains("2023-08-04 15:49:49")){System.out.println("博客发布时间:" + blog_release_time);System.out.println("测试不通过");}else{System.out.println("测试通过");}}/*** 退出博客*/@Order(6)@Testvoid LogOut() throws InterruptedException {webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 找到退出按钮,点击webDriver.findElement(By.cssSelector("body > div.nav > a:nth-child(6)")).click();webDriver.manage().timeouts().implicitlyWait(3, TimeUnit.SECONDS);// 校验页面是否有登录文案String login_text= webDriver.findElement(By.cssSelector("body > div.container-login > div > h3")).getText();// 如果有登录文案,退出成功(测试用例通过)// 否则,退出失败(测试不通过)sleep(3000);if(login_text.equals("登录")){System.out.println("测试通过");}else{System.out.println("测试不通过");}}
}
相关文章:

Java个人博客系统--基于Springboot的设计与实现
目录 一、项目概述 应用技术 接口实现: 数据库定义: 数据库建表: 博客表数据库相关操作: 添加项⽬公共模块 加密MD5 页面展示:http://121.41.168.121:8080/blog_login.html 项目源码:https://gitee…...
在jupyter中下载数据集失败及解决方法(以IMDB为例)
在IMDB数据集下载时,由于网络原因下载失败,报错如下: Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/imdb.npz ConnectionResetError Traceback (most recent call last) … Exception: URL fetch f…...
【设计模式】-工厂方法模式
工厂方法模式(Factory Method Pattern)是一种创建型设计模式,它通过定义一个用于创建对象的接口,但是将具体对象的创建推迟到子类中。这样,子类可以决定要实例化的对象类型。工厂方法模式提供了一种方式,通…...

H7-TOOL的高速DAPLINK用于新版STM32CubeIDE V1.13及其以上版本的超简单实现方法(2023-08-08)
之前分享了一个方法,太繁琐了,H7-TOOL群的群友提供了一个方法,实现非常简单。1、使用STM32CubeMX或者自己创建一个STM32CubeIDE工程后,设置这两个地方即可: 配置调试器,设置完毕记得点击右下角的Apply 2、然…...

成功解决ubuntu-22.04的sudo apt-get update一直卡在【0% [Waiting for headers]】
成功解决ubuntu-22.04的sudo apt-get update一直卡在【0% [Waiting for headers]】 问题描述解决方案 问题描述 在下载安装包的时候一直卡在0% [Waiting for headers],报错信息如下: Get:1 file:/var/cudnn-local-repo-ubuntu1804-8.5.0.96 InRelease […...
openLayers实战(一):vue项目中的离线地图引入
最近的项目涉及到离线地图的操作,查阅社区文章,决定使用openLayersvue离线地图的方式进行开发,前期基础引入操作完全参考掘金文章,非常优秀全面的文章。 openlayers 实战离线地图 - 掘金 此外,开发过程的地图操作可参考…...

如何构造一个安全的单例?
为什么要问这个问题? 我们知道,单例是一种很常用的设计模式,主要作用就是节省系统资源,让对象在服务器中只有一份。但是实际开发中可能有很多人压根没有写过单例这种模式,只是看过或者为了面试去写写demo熟悉一下。那…...

单片机开发 esp8266
一、固件界面 二、项目介绍 固件名称:esp8266-universalboard v1.0 提供商: 半条虫(466814195) 下载:esp8266-universalboard.bin 源码地址:Gitlab...
Linux 查看版本和用户权限提升实践心得
文章目录 linux (Ubuntu内核)查看版本版本信息解释内置yum工具?用户权限提升操作步骤 查看deepin系统的版本和其debian的版本遇到的问题:deepin-release文件不存在 linux (Ubuntu内核)查看版本 使用lsb_release命令: lsb_release -a该命令将…...
多线程编程5:线程同步和进程通信(C++11和linux)
常见的线程同步 linux: 互斥锁:实现共享资源的串行访问,有三个版本普通锁(默认属性),检错锁(可以防止相同线程重复加锁)和递归锁(相同线程可以重复加锁)条件变量:配合互斥锁使用,实现线程之间的通信&#…...
tensorrt官方int8量化方法汇总
原理及操作 量化的基本原理及流程可参看懂你的神经网络量化教程:第一讲、量化番外篇、TensorRT中的INT8、tensorRT int8量化示例代码 Tensorrt 方式1:trtexec(PTQ的一种) int8量化 trtexec --onnxXX.onnx --saveEnginemodel.…...

21、p6spy输出执行SQL日志
文章目录 1、背景2、简介3、接入3.1、 引入依赖3.2、修改database参数:3.3、 创建P6SpyLogger类,自定义日志格式3.4、添加spy.properties3.5、 输出样例 4、补充4.1、参数说明 1、背景 在开发的过程中,总希望方法执行完了可以看到完整是sql语…...

实力认证!TDengine 入选 Gartner 中国数据分析与人工智能技术成熟度曲线
近日,国际权威研究机构 Gartner 发布了《2023 年中国数据分析及人工智能技术成熟度曲线》(即《Hype Cycle for Data, Analytics and AI in China, 2023》)报告,TDengine 成功入选实时数据管理领域代表产品。 作为评估全球新技术成…...

如何将jar包部署到宝塔
尝试多种方式上传,但启动一直失败,这种方式亲测是好使的 项目内修改位置 在pom.xml文件中将mysql的scope改成provided,如果是固定的版本号会出现问题 之后就可以打包啦,直接点击maven中的package 找到打包文件的位置ÿ…...

el-tree-select那些事
下拉菜单树形选择器 用于记录工作及日常学习涉及到的一些需求和问题 vue3 el-tree-select那些事 1、获取el-tree-select选中的任意层级的节点对象 1、获取el-tree-select选中的任意层级的节点对象 1-1数据集 1-2画面 1-3代码 1-3-1画面代码 <el-tree-selectv-model"s…...
分布式任务调度框架之开山鼻祖:Quartz
1.简介 最近我司上线使用了分布式任务调度框架:XXL-JOB,方便对任务的管理控制。本来一开始就想讲述一下该框架,但是在学习了解过程中发现该框架式基于Quartz思想开发实现的,Quartz 是一个很火的开源任务调度框架,完全…...

Django实现音乐网站 ⑺
使用Python Django框架制作一个音乐网站, 本篇主要是后台对歌手原有实现功能的基础上进行优化处理。 目录 新增编辑 表字段名称修改 隐藏单曲、专辑数 姓名首字母 安装xpinyin 获取姓名首字母 重写保存方法 列表显示 图片显示处理 引入函数 路径改为显示…...
PO、DTO和VO的区别
PO:Persistence Object,是持久化对象,也叫实体对象(Entity),是对象到关系表的映射。在关系型数据库中,每张表对应着一个PO,PO 中的属性值与表中数据一一对应,通过数据访问…...
ReadableStream流的js处理
需求 今天接了一个gpt的项目。需要对接接口。后端返回的数据是ReadableStream类型的。记录下如何处理ReadableStream类型的数据 代码 const response ... // response 是服务端返回的数据// 创建了一个数据读取器 const reader response.getReader(); // 创建了一个文本解…...

图扑软件入选 2023 中国信通院“铸基计划”全景图
7 月 27 日,由中国信通院主办的“2023 数字生态发展大会”暨中国信通院“铸基计划”年中会议在北京召开。本次大会重磅发布了《高质量数字化转型产品及服务全景图(2023 上半年度)》。图扑软件凭借自研 HT for Web 数字孪生可视化产品成功入选…...
web vue 项目 Docker化部署
Web 项目 Docker 化部署详细教程 目录 Web 项目 Docker 化部署概述Dockerfile 详解 构建阶段生产阶段 构建和运行 Docker 镜像 1. Web 项目 Docker 化部署概述 Docker 化部署的主要步骤分为以下几个阶段: 构建阶段(Build Stage):…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互
物理引擎(Physics Engine) 物理引擎 是一种通过计算机模拟物理规律(如力学、碰撞、重力、流体动力学等)的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互,广泛应用于 游戏开发、动画制作、虚…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...
AI编程--插件对比分析:CodeRider、GitHub Copilot及其他
AI编程插件对比分析:CodeRider、GitHub Copilot及其他 随着人工智能技术的快速发展,AI编程插件已成为提升开发者生产力的重要工具。CodeRider和GitHub Copilot作为市场上的领先者,分别以其独特的特性和生态系统吸引了大量开发者。本文将从功…...

k8s业务程序联调工具-KtConnect
概述 原理 工具作用是建立了一个从本地到集群的单向VPN,根据VPN原理,打通两个内网必然需要借助一个公共中继节点,ktconnect工具巧妙的利用k8s原生的portforward能力,简化了建立连接的过程,apiserver间接起到了中继节…...
【JavaSE】绘图与事件入门学习笔记
-Java绘图坐标体系 坐标体系-介绍 坐标原点位于左上角,以像素为单位。 在Java坐标系中,第一个是x坐标,表示当前位置为水平方向,距离坐标原点x个像素;第二个是y坐标,表示当前位置为垂直方向,距离坐标原点y个像素。 坐标体系-像素 …...
什么?连接服务器也能可视化显示界面?:基于X11 Forwarding + CentOS + MobaXterm实战指南
文章目录 什么是X11?环境准备实战步骤1️⃣ 服务器端配置(CentOS)2️⃣ 客户端配置(MobaXterm)3️⃣ 验证X11 Forwarding4️⃣ 运行自定义GUI程序(Python示例)5️⃣ 成功效果
mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包
文章目录 现象:mysql已经安装,但是通过rpm -q 没有找mysql相关的已安装包遇到 rpm 命令找不到已经安装的 MySQL 包时,可能是因为以下几个原因:1.MySQL 不是通过 RPM 包安装的2.RPM 数据库损坏3.使用了不同的包名或路径4.使用其他包…...
.Net Framework 4/C# 关键字(非常用,持续更新...)
一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

Unity | AmplifyShaderEditor插件基础(第七集:平面波动shader)
目录 一、👋🏻前言 二、😈sinx波动的基本原理 三、😈波动起来 1.sinx节点介绍 2.vertexPosition 3.集成Vector3 a.节点Append b.连起来 4.波动起来 a.波动的原理 b.时间节点 c.sinx的处理 四、🌊波动优化…...