基于SSM实现软件测试管理系统

引言

Hello,大家好,本周博主为大家带来一个基于SSM的软件测试管理系统,系统分为两大模块,用户与bug模块

其中管理员管理用户,为用户分配角色,分为开发或测试,用户管理bug模块,其中,测试提交bug,写好bug信息,进行提交,开发人员对bug进行修改,直至测试确认bug修改完成后,结束对话。

文字表达难免表达不清楚,下面看效果图效果图时长3分钟,要耐心看下去哦

效果图

基于SSM+MVC三层架构实现软件测试管理系统_java技术栈

  1. 后端:Java、Spring、Spring MVC、 MyBatis
  2. 前端:bootstrap、jsp

软件测试管理系统

系统支持防跳墙,利用Spring MVC Interceptor拦截器实现,实体类采用lombok插件系统采用三层架构完成

数据表准备

****

t_user用户表

CREATE TABLE `t_user` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`username` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`userpwd` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`realname` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL,
`usertype` int(11) DEFAULT NULL COMMENT '账号类型,1:开发,2:测试',
PRIMARY KEY (`id`)
)

t_bug_topic bug主题表

CREATE TABLE `t_bug_topic` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`bug_title` varchar(32) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'bug主题',
`bug_detail` varchar(256) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT 'bug详细信息',
`bug_level` int(11) DEFAULT NULL COMMENT 'bug级别:1:功能优化、2:一般异常、3:重大异常',
`test_user_id` varchar(64) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '测试用户id',
`create_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '当前日期',
`bug_status` int(11) DEFAULT '0' COMMENT '当前bug状态,1 未处理 2 修改完成待确认 3 修改被驳回 4 修改完成已确认',
PRIMARY KEY (`id`)
)

t_bug_trace bug跟踪表

CREATE TABLE `t_bug_trace` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`topic_id` int(11) DEFAULT NULL COMMENT 'bugid',
`send_user_id` int(11) DEFAULT NULL COMMENT '发送人员id',
`send_time` timestamp NULL DEFAULT CURRENT_TIMESTAMP COMMENT '当前日期',
`detail_info` varchar(256) COLLATE utf8mb4_unicode_ci DEFAULT NULL COMMENT '详细信息',
`bug_status` int(11) DEFAULT NULL COMMENT '当前状态:0 普通沟通 2 修改完成,提交确认 3 修改驳回 4 修改完成已确认',
PRIMARY KEY (`id`)
)

项目结构

基于SSM+MVC三层架构实现软件测试管理系统_spring_02

Java源码

基于SSM+MVC三层架构实现软件测试管理系统_spring_03

配置文件

基于SSM+MVC三层架构实现软件测试管理系统_java_04

前端结构

基于SSM+MVC三层架构实现软件测试管理系统_xml_05

搭建项目

​以Maven方式创建Web项目​

​整合SSM​


pom依赖文件

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>org.example</groupId>
<artifactId>APPTestManagerSystem</artifactId>
<version>1.0-SNAPSHOT</version>


<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework/spring-aop -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.aspectj/aspectjweaver -->
<dependency>
<groupId>org.aspectj</groupId>
<artifactId>aspectjweaver</artifactId>
<version>1.9.4</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-context -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>

<!-- mybatis依赖的坐标 -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis</artifactId>
<version>3.5.4</version>
</dependency>

<!-- java连接mysql的驱动坐标 -->
<!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>5.1.47</version>
</dependency>

<!-- https://mvnrepository.com/artifact/com.mchange/c3p0 -->
<dependency>
<groupId>com.mchange</groupId>
<artifactId>c3p0</artifactId>
<version>0.9.5.2</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-jdbc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-jdbc</artifactId>
<version>5.2.4.RELEASE</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.mybatis/mybatis-spring -->
<dependency>
<groupId>org.mybatis</groupId>
<artifactId>mybatis-spring</artifactId>
<version>2.0.4</version>
</dependency>

<!-- https://mvnrepository.com/artifact/org.springframework/spring-webmvc -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.1.9.RELEASE</version>
</dependency>

<dependency>
<groupId>javax.servlet</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>

<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.3.1</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>

<!-- https://mvnrepository.com/artifact/javax.servlet/javax.servlet-api -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>3.1.0</version>
<scope>provided</scope>
</dependency>

<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<dependency>
<groupId>commons-lang</groupId>
<artifactId>commons-lang</artifactId>
<version>2.6</version>
</dependency>
</dependencies>

<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<include>**/*.properties</include>
<include>**/*.xml</include>
</includes>
<filtering>true</filtering>
</resource>
</resources>
</build>

</project>

核心源码

bean层

User用户类

package com.wanshi.bean;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class TUser {

private Integer id;
private String username;
private String userpwd;
private String realname;
private Integer usertype;
}

BugTopic Bug主题类

package com.wanshi.bean;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class BugTopic {

private Integer id;
private String bug_title;
private String bug_detail;
private Integer bug_level;
private Integer test_user_id;
private Date create_time;
private Integer bug_status;

private String testUsername;

private String createTime;

}

BugTrace Bug跟踪类

package com.wanshi.bean;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.util.Date;

@Data
@NoArgsConstructor
@AllArgsConstructor
public class BugTrace {

private Integer id;
private Integer topic_id;
private Integer send_user_id;
private Date send_time;
private String detail_info;
private Integer bug_status;

private String sendUserName;
private String sendTime;
private String userType;
}

Page 分页类

package com.wanshi.bean;

import java.util.ArrayList;
import java.util.List;

/**
* 分页类,使用该类需传入3个参数,
* currPage:当前页数
* pageSize:每页显示的记录数
* rowCount:总共的记录数
*
* 注意::初始化该类后,使用该类的currPageFirstRowIndex属性传入数据访问层进行分页
* 分页完成后返回list集合,需要将返回的list集合通过该类的setList方法存入数据即可完成
*
* @author 王会称
*
* @param <T>
*/
public class Page<T> {

/**
* 当前页前面的页数
*/
private static final int BeforePageNumbCount = 4;

/**
* 当前页后面的页数
*/
private static final int AfterPageNumbCount = 3;

/**
* 当前页
*/
private int currPage;
/**
* 总记录数
*/
private int rowCount;
/**
* 分页的第二个参数,用于展示每页显示几条数据
* limit arg1, arg2 arg2
*
*/
private int pageSize;
/**
* 总页数
*/
private int pageCount;
/**
* 前一页
*/
private int prevPageNumb;
/**
* 后一页
*/
private int nextPageNumb;

/**
* 从第几条开始截取,分页的第一个参数
* limit arg1, arg2 arg1
*
*/
private int currPageFirstRowIndex;
/**
* 当前页的集合
*/
private List<T> list;
/**
* 当前显示的按钮数,前4后3
*/
private List<Integer> pageButtonNumbs ;

/**
* 初始化分页类,传入当前页,每页的记录数,总记录数
* @param _currPage
* @param _pageSize
* @param _rowCount
*/
public Page(int _currPage, int _pageSize, int _rowCount){

//初始化固定数据,每页的数据记录数,总记录数
this.pageSize = _pageSize;
this.rowCount = _rowCount;

// 计算出当前共有多少页
this.pageCount = this.rowCount / this.pageSize;
if(this.rowCount% this.pageSize !=0 ){
this.pageCount ++ ;
}

// 修正当前页
this.currPage = _currPage ;
if(this.currPage< 1 ){
this.currPage = 1;
}

if(this.currPage > this.pageCount ){
this.currPage = this.pageCount;
}

// 计算limit分页的第一个参数
this.currPageFirstRowIndex = (this.currPage-1)* this.pageSize ;

//如果小于0,那就从0开始截取
if (this.currPageFirstRowIndex < 0) {
this.currPageFirstRowIndex = 0;
}

// 计算前一页与后一页
this.prevPageNumb = this.currPage - 1;
this.nextPageNumb = this.currPage + 1;

//修正前一页
if(this.prevPageNumb<1){
this.prevPageNumb = 1;
}

//修正后一页
if(this.nextPageNumb >1 && this.nextPageNumb > this.pageCount){
this.nextPageNumb = this.pageCount;
}

// 计算当前的按钮数
this.pageButtonNumbs = new ArrayList();
for( int i = this.currPage - BeforePageNumbCount ; i <= this.currPage+AfterPageNumbCount ;i++){
if(i<1 || i> this.pageCount ){
continue;
}
this.pageButtonNumbs.add(i);
}

}

public List<T> getList() {
return list;
}

public void setList(List<T> list) {
this.list = list;
}

public int getCurrPage() {
return currPage;
}

public int getRowCount() {
return rowCount;
}

public int getPageSize() {
return pageSize;
}

public int getPageCount() {
return pageCount;
}

public int getPrevPageNumb() {
return prevPageNumb;
}

public int getNextPageNumb() {
return nextPageNumb;
}

public List<Integer> getPageButtonNumbs() {
return pageButtonNumbs;
}

public int getCurrPageFirstRowIndex() {
return currPageFirstRowIndex;
}

@Override
public String toString() {
return "Page [currPage=" + currPage + ", rowCount=" + rowCount + ", pageSize=" + pageSize + ", pageCount="
+ pageCount + ", prevPageNumb=" + prevPageNumb + ", nextPageNumb=" + nextPageNumb
+ ", currPageFirstRowIndex=" + currPageFirstRowIndex + ", list=" + list + ", pageButtonNumbs="
+ pageButtonNumbs + "]";
}
}

controller层

RouteController 路由跳转类,用于携带数据跳转到指定jsp页面进行渲染

package com.wanshi.controller;

import com.wanshi.bean.BugTopic;
import com.wanshi.bean.TUser;
import com.wanshi.service.BugTopicService;
import com.wanshi.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;

@Controller
@RequestMapping("/route")
public class RouteController {

@Autowired
private UserService userService;

@Autowired
private BugTopicService bugTopicService;

@GetMapping("/index")
public String index() {
return "index";
}

@GetMapping("/addUser")
public String userAdd() {
return "user/add";
}

@GetMapping("/updateUser")
public String updateUser(String id, Model model) {
TUser tUser = userService.get(Integer.valueOf(id));
model.addAttribute("user", tUser);
return "user/edit";
}

@GetMapping("/addBug")
public String addBug() {
return "bug/add";
}

@GetMapping("/updateBug")
public String updateBug(String id, Model model) {
BugTopic bugTopic = bugTopicService.get(Integer.valueOf(id));
model.addAttribute("bug", bugTopic);
return "bug/edit";
}

@GetMapping("/disposeBug")
public String disposeBug(String id, HttpServletRequest request) {
BugTopic bugTopic = bugTopicService.get(Integer.valueOf(id));
request.getSession().setAttribute("bug", bugTopic);
return "redirect:/bug_trace/list";
}

}

BugTopicController bug主题控制器类

package com.wanshi.controller;

import com.wanshi.bean.BugTopic;
import com.wanshi.bean.Page;
import com.wanshi.service.BugTopicService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import java.util.List;

@Controller
@RequestMapping("/bug_topic")
public class BugTopicController {


@Autowired
private BugTopicService bugTopicService;

private static final Integer PageSize = 2;

@GetMapping("/page")
public String page(HttpServletRequest request, Model model) {
String bugTitle = request.getParameter("bug_title");
String bugLevel = request.getParameter("bug_level");
String testUsername = request.getParameter("test_username");
String pageNumb = request.getParameter("pageNumb");
Integer currPage = 1;
if (pageNumb != null && !pageNumb.equals("")) {
currPage = Integer.valueOf(pageNumb);
}
Page<BugTopic> page = bugTopicService.page(bugTitle, bugLevel, testUsername, currPage, PageSize);
model.addAttribute("pager", page);
model.addAttribute("bugTitle", bugTitle);
model.addAttribute("bugLevel", bugLevel);
model.addAttribute("testUsername", testUsername);
return "bug/list";
}

@PostMapping("/addHandle")
public String addHandle(BugTopic bugTopic) {
bugTopicService.insert(bugTopic);
return "redirect:/bug_topic/page";
}

@PostMapping("/editHandle")
public String editHandle(BugTopic bugTopic) {
System.out.println(bugTopic);
bugTopicService.update(bugTopic);
return "redirect:/bug_topic/page";
}

}

service层

BugTopicService

package com.wanshi.service;

import com.wanshi.bean.BugTopic;
import com.wanshi.bean.Page;

import java.util.List;

public interface BugTopicService {

Page<BugTopic> page(String bugTitle, String bugLevel, String testUsername, Integer currPage, Integer pageSize);

void update(BugTopic bugTopic);

void insert(BugTopic bugTopic);

BugTopic get(Integer id);
}

BugServiceImpl 实现类

package com.wanshi.service.impl;

import com.wanshi.bean.BugTopic;
import com.wanshi.bean.Page;
import com.wanshi.mapper.BugTopicMapper;
import com.wanshi.service.BugTopicService;

import java.text.SimpleDateFormat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

public class BugTopicServiceImpl implements BugTopicService {

private BugTopicMapper bugTopicMapper;

private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm");

public void setBugTopicMapper(BugTopicMapper bugTopicMapper) {
this.bugTopicMapper = bugTopicMapper;
}

public Page<BugTopic> page(String bugTitle, String bugLevel, String testUsername, Integer currPage, Integer pageSize) {
Map<String, Object> maps = new HashMap<String, Object>();
maps.put("bugTitle", bugTitle);
maps.put("bugLevel", bugLevel);
maps.put("testUsername", testUsername);
Integer rowCount = bugTopicMapper.getTotal(maps);
Page<BugTopic> page = new Page<BugTopic>(currPage, pageSize, rowCount);
maps.put("currPage", page.getCurrPageFirstRowIndex());
maps.put("pageSize", pageSize);
List<BugTopic> bugTopicList = bugTopicMapper.page(maps);
for (BugTopic bugTopic : bugTopicList) {
bugTopic.setCreateTime(sdf.format(bugTopic.getCreate_time()));
}
page.setList(bugTopicList);
return page;
}

public void update(BugTopic bugTopic) {
bugTopicMapper.update(bugTopic);
}

public void insert(BugTopic bugTopic) {
bugTopicMapper.insert(bugTopic);
}

public BugTopic get(Integer id) {
BugTopic bugTopic = bugTopicMapper.get(id);
bugTopic.setCreateTime(sdf.format(bugTopic.getCreate_time()));
return bugTopic;
}
}

mapper层

BugTopicMapper

package com.wanshi.mapper;

import com.wanshi.bean.BugTopic;

import java.util.List;
import java.util.Map;

public interface BugTopicMapper {

List<BugTopic> page(Map<String, Object> maps);

void update(BugTopic bugTopic);

void insert(BugTopic bugTopic);

BugTopic get(Integer id);

Integer getTotal(Map<String, Object> maps);
}

BugTopicMapper.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wanshi.mapper.BugTopicMapper">

<select id="page" resultType="com.wanshi.bean.BugTopic">
SELECT bug.*, user.`realname` testUsername FROM t_bug_topic bug JOIN t_user1105 USER ON user.id = bug.test_user_id
<where>
<if test="bugTitle != null and bugTitle != ''">
bug_title like concat('%',#{bugTitle},'%')
</if>
<if test="bugLevel != null and bugLevel != ''">
and bug_level = #{bugLevel}
</if>
<if test="testUsername != null and testUsername != ''">
and test_user_id = (SELECT u.`id` FROM t_user1105 u WHERE realname LIKE concat('%',#{testUsername},'%'))
</if>
</where>
limit #{currPage}, #{pageSize}
</select>

<insert id="insert">
insert into t_bug_topic (bug_title, bug_detail, bug_level,test_user_id)
values (#{bug_title}, #{bug_detail}, #{bug_level}, #{test_user_id})
</insert>

<update id="update">
update t_bug_topic
<set>
<if test="bug_title != null and bug_title != ''">bug_title = #{bug_title},</if>
<if test="bug_detail != null and bug_detail != ''">bug_detail = #{bug_detail},</if>
<if test="bug_level != null and bug_level != ''">bug_level = #{bug_level},</if>
<if test="test_user_id != null and test_user_id != ''">test_user_id = #{test_user_id},</if>
<if test="bug_status != null and bug_status != ''">bug_status = #{bug_status},</if>
create_time = now()
</set>
where id = #{id}
</update>

<select id="get" resultType="com.wanshi.bean.BugTopic">
SELECT bug.*, user.`realname` testUsername FROM t_bug_topic bug JOIN t_user1105 USER ON user.id = bug.test_user_id where bug.`id` = #{id}
</select>

<select id="getTotal" resultType="int">
select count(*) from t_bug_topic
<where>
<if test="bugTitle != null and bugTitle != ''">
bug_title like concat('%',#{bugTitle},'%')
</if>
<if test="bugLevel != null and bugLevel != ''">
and bug_level = #{bugLevel}
</if>
<if test="testUsername != null and testUsername != ''">
and test_user_id = (SELECT u.`id` FROM t_user1105 u WHERE realname LIKE concat('%',#{testUsername},'%'))
</if>
</where>
</select>

</mapper>

项目源码就分享到此,由于文件太多,本博客只介绍核心类,若对本项目感兴趣的老铁,可在下方链接获取完整项目

结语

本博客到此结束,系统还是有些逻辑性的,建议多练习,巩固知识,提示自己的逻辑思维能力

有任何问题均可在评论区留言或私信我只求您能留下您宝贵的足迹,等啥呢,都看到这啦,还不来个一键三连嘛(收藏+关注+评论)感谢您的支持,我们下篇见~