测试技能提升:Junit,Knife4J和JMeter使用指南

测试技能提升:Junit,Knife4J和JMeter使用指南及模块搭建规范

​ 单元测试、接口测试和压力(并发测试)都是与软件测试和开发密切相关的工具和框架,但它们在测试方面有不同的应用和重点。以下是它们的简要解释:

  1. JUnit:
    • JUnit是一个Java编程语言的单元测试框架,用于编写和执行单元测试。
    • 开发人员使用JUnit来编写测试用例,测试不同的代码单元,如方法和类。
    • JUnit提供了各种断言(assert)和测试运行器,以验证代码单元的行为是否与预期一致。
    • 单元测试是为了确保代码的功能性和正确性,通常在开发过程中频繁运行,以捕获和修复问题。
  2. Swagger:
    • Swagger是一种API文档工具和规范,用于描述和定义 RESTful Web服务的接口。
    • 它允许开发人员为他们的API创建文档,以便其他开发人员能够了解API的用法和参数。
    • Swagger也提供了交互式API测试工具,允许开发人员直接在文档中测试API端点,以确保其正确性和可用性。
  3. JMeter:
    • JMeter是一个开源的性能测试工具,用于模拟多用户并发访问来测试 Web 应用程序、Web服务和数据库等的性能。
    • JMeter不同于JUnit和Swagger,它侧重于测试应用程序的性能、吞吐量、响应时间和并发性。
    • JMeter可以模拟大量用户同时访问应用程序,以确定应用程序在高负载下的性能表现,有助于发现性能问题和瓶颈。

综合而言,JUnit用于单元测试,Swagger用于API文档和接口测试,而JMeter用于性能测试。这三个工具都在不同方面支持软件测试和开发,有助于确保软件的质量、功能和性能。

单元测试

​ 单元测试是对对象所属模块的后台 进行测试,对业务层进行测试,在Spring Boot项目中,我们常用Junit进行单元测试,以下是单元测试的基本流程:

<1> 在pom.xml文件中引入单元测试依赖

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
    <groupId>junit</groupId>
    <artifactId>junit</artifactId>
    <scope>test</scope>
</dependency>

<2> 编写测试用例

@SpringBootTest
@RunWith(SpringJUnit4ClassRunner.class)
public class EatImplTest {
    @
    private IEat ie;
    @Test
    public void eat() {
        int sum = ie.eat();
        assertEquals(5050,sum);
    }
}

<3> 运行测试程序

接口测试

​ 对软件系统的接口进行测试,即验证不同模块之间的通信是否正常、参数传递是否正确、错误处理是否正确等。

Knife4j(Swagger的本地增强解决方案)

image-20230628112011921

knife4j与springboot的兼容性

Spring Boot版本Knife4j Swagger2规范Knife4j OpenAPI3规范
1.5.x~2.0.0<Knife4j 2.0.0>=Knife4j 4.0.0
2.0~2.2Knife4j 2.0.0 ~ 2.0.6>=Knife4j 4.0.0
2.2.x~2.4.0Knife4j 2.0.6 ~ 2.0.9>=Knife4j 4.0.0
2.4.0~2.7.x>=Knife4j 4.0.0>=Knife4j 4.0.0
>= 3.0>=Knife4j 4.0.0>=Knife4j 4.0.0

springboot项目引入Knife4j依赖

<dependency>
    <groupId>com.github.xiaoymin</groupId>
    <artifactId>knife4j-openapi2-spring-boot-starter</artifactId>
    <version>4.1.0</version>
</dependency>

配置

knife4j:
  enable: true                 #此项必配置,否则knife4j运行有问题
  openapi:
    title: knife4j项目的名称
    description: knife4j项目的描述
    email: 项目邮箱
    concat: 贡献者名称
    url: 项目的地址
    license: Apache 2.0
    license-url: http://www.apache.org/licenses/LICENSE-2.0
    terms-of-service-url: https://www.bilibili.com/video/BV1tK411y7Uf/

tips: 配置除enable,其它测试阶段可以省略。

Knife4j常用注解

在返回队对象上使用

在HttpResp(用户封装返回对象的类)

序列注解作用
1@ApiModel用对象来接收参数
2@ApiModelProperty用对象接收参数时,描述对象的一个字段

在Controller类和方法上使用

序列注解作用
1@Api(tags = “Knife4jController接口类”)
2@Api修饰整个类,描述api(Controller)的作用
3@ApiOperation描述一个类的一个方法,或者说一个接口
4@ApiImplicitParam多个请求参数的描述信息
5@ApiImplicitParam(name = “name”,value=”请求的名称”,required = true)单个参数的描述信息
6@ApiIgnore使用该注解忽略这个API
7@ApiError发生错误返回的信息

@ApiImplicitParm的属性

序列属性作用
1paramType查询参数类型
path以地址形式提交数据
query直接跟参数完成映射赋值
body以流的形式提交 仅支持POST
header参数在request headers里面提交
form以form表单的形式提交,仅支持POST
2dataType参数的数据类型 只为标志说明 并没有实际验证
Long
String
3name接收参数名
4value接收参数的意义描述
5required参数是否必填
true必填
false非比填
6defaultValue默认值
示例

ResultCode

@JsonFormat(shape = JsonFormat.Shape.OBJECT)
@ApiModel(value = "ResultCode",description = "返回代码的枚举类")
public enum ResultCode {
    BOOKTYPE_OPERATION_SUCCESS(21000,"图书类型操作成功"),
    PUBLISHER_OPERATION_SUCCESS(22000,"出版社操作成功"),
    BOOK_OPERATION_SUCCESS(23000,"图书成功"),
    USER_LOGIN_SUCCESS(25000,"用户登录成功"),
    USER_QUERY_SUCCESS(25100,"用户查询成功"),
    USER_NOT_LOGIN_ERROR(45000,"用户没有登录异常"),
    USER_LOGIN_TOKEN_EXPIRED_ERROR(45001,"token已过期异常"),
    USER_PRIVILEGES_ERROR(45002,"权限异常")
    ;
    @ApiModelProperty(name = "code",notes = "返回代码")
    private int code;
    @ApiModelProperty(name = "msg",notes = "返回信息")
    private String msg;
     ResultCode(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }
    public int getCode() {
        return code;
    }
    public String getMsg() {
        return msg;
    }
}

HttpResp

package com.wnhz.bm.common.result;
import com.fasterxml.jackson.annotation.JsonFormat;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.*;
import java.io.Serializable;
import java.util.Date;
@ApiModel(value = "HttpResp",description = "返回类型对象")
@Getter@ToString@Setter
public class HttpResp<T> implements Serializable {
    @ApiModelProperty(name = "resultCode",notes = "返回代码")
    private ResultCode resultCode;
    @ApiModelProperty(name = "time",notes = "返回接口调用的结果返回时间")
    @JsonFormat(timezone = "GMT+8")
    private Date time;
    @ApiModelProperty(name = "results",notes = "返回后台数据")
    private T results;
    private HttpResp(){}
    public static <T> HttpResp <T> result(ResultCode resultCode, Date time,T results){
        HttpResp<T> httpResp = new HttpResp<>();
        httpResp.setResultCode(resultCode);
        httpResp.setTime(time);
        httpResp.setResults(results);
        return httpResp;
    }
}

controller

@Api(tags = "图书类型接口")
@RestController
@RequestMapping("/type")
@Slf4j
public class BookController {
    private int total =0;
    @ApiOperation(value = "findAll", notes = "图书类型查询")
    @GetMapping("/findAll")
//    public HttpResp<List<Type>> findAll() {
    public HttpResp<Integer> findAll() {
//        List<Type> types = new LinkedList();
//        for (int i = 0; i < 100; i++) {
//            types.add(new Type(i, "type_" + i, "admin", new Date(), new Date()));
//        }
        total += 1;
        log.debug("total-->{}", total);
        return new HttpResp<>(200, "成功", total, new Date());
    }

    @ApiOperation(value = "addType", notes = "添加新的图书接口类型")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "name", value = "请输入新的图书类型名称", required = true)
    })
    @PostMapping("/addType")
    public HttpResp<String> addType(String name) {
        log.debug("添加新的类型:{}", name);
        return new HttpResp<>(200, "success", name, new Date());
    }

    @ApiOperation(value = "excel", notes = "上传excel文件进行解析")
//    @ApiImplicitParam(value = "上传文件", required = true)
    @PostMapping("/uploadExcel")
    public HttpResp<String> uploadExcel(@RequestPart @RequestParam("excel") MultipartFile excel){
        String originalFilename = excel.getOriginalFilename();
        log.debug("上传文件名称:{}", originalFilename);
        return new HttpResp<>(200,"success",originalFilename+"上传成功",new Date());
    }
}
效果图

在这里插入图片描述

并发测试

​ 并发测试是对系统或网络在高负载和大并发访问情况下的性能和稳定性进行测试,常用工具为JMeter。

  1. 下载完成后,双击 bin->ApacheJMeter.jar 运行程序。

  2. 右键测试程序,选择添加->线程用户->线程组在这里插入图片描述

  3. 配置线程数时间以及循环次数等参数。

    线程数:配置几个就代表有几个虚拟用户

    Ramp-Up 时间(秒):表示从第一个虚拟用户开始生成直到最后一个虚拟用户开始生成的时间,假如配置了5个虚拟用户,Ramp-Up 设置成10s,那么 JMeter 会每隔2s生成1个虚拟用户,Ramp-Up设置成0,那么所有用户将会同时立即产生

    循环数:要么是N次,要么是永远

    调度器:就是定时执行的设置方式。我们可以设置在未来的某个时间开始执行也可以设置多少秒后开始执行。

    注意:你只有在按下执行按钮后,调度器才生效
    在这里插入图片描述

  4. 添加 HTTP 请求配置在这里插入图片描述

  5. 配置 HTTP 请求在这里插入图片描述

  6. 添加查看结果树在这里插入图片描述

  7. 启动测试在这里插入图片描述

  8. 查看测试结果

    在这里插入图片描述

在这里插入图片描述

​ 在测试过程中发现,存在一张票被两个线程同时购买的情况,可以在方法上+synchronized 来保证线程安全,但是会导致效率下降的问题。

在这里插入图片描述

多模块搭建规范

先搭建出多模块

在这里插入图片描述

然后开始加入pom依赖,父项目这样加,加这三个
在这里插入图片描述

然后在要运行的项目主体模块中这样加,先连接兄弟模块

在这里插入图片描述

再加测试类(test、单元测和接口测)
在这里插入图片描述

再加打包文件,注意这里是要运行的模块所以这样加

在这里插入图片描述

这部分的打包依赖要加到非运行部分的模块里(如上面common,domain模块)

  <build>
        <plugins>
            <!-- 编译源代码插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.8.0</version>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>${project.build.sourceEncoding}</encoding>
                </configuration>
            </plugin>

            <!-- 打包源代码插件 -->
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-source-plugin</artifactId>
                <version>2.2.1</version>
                <configuration>
                    <attach>true</attach>
                </configuration>
                <executions>
                    <execution>
                        <phase>compile</phase>
                        <goals>
                            <goal>jar</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>

以上多模块间的基本依赖就配置好了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值