这是新开的一个系列的第一篇。在这个系列中,笔者将结合目前流行的测试用例管理平台MeterSphere来介绍如何进行面向开发人员的测试用例,通过编写集成测试和单元测试来完成用例下沉、质量内建的目标。
MeterSphere 是一站式的开源持续测试平台,涵盖测试跟踪、接口测试、性能测试、团队协作等功能,兼容 JMeter 等开源标准,有效助力开发和测试团队充分利用云弹性进行高度可扩展的自动化测试,加速高质量软件的交付。
测试场景,从项目新建到用例执行通过
这是本系列的第一个任务,希望通过完成一段旅程来展示平台的几个基本功能,并实现集成测试级别的冒烟测试。
通过探索,发现MeterSphere从0开始,需要经历过如下的5个步骤已完成用例的执行通过这一极简目标。 测试场景: 0 登录 组织-默认组织 工作空间-默认空间 1 项目 -新创建-demo 模 块 -在新项目中创建模块-module-demo 2 用例 - 新建用例 3 测试计划 - 新建测试计划 测试计划 - 关联测试用例 4 测试评审 - 新建评审 测试评审 - 关联测试用例 测试评审 - 通过 5 测试计划 - 测试用例-执行-通过
我们将从0开始,利用上一案例生成的业务对象来完成后续的操作,最终实现测试用例的执行通过。
集成测试项目配置与测试基类
相对于单元测试,集成测试时会将整个应用启动,对应用形成所谓端到端的质量检测。另外,由于集成测试用例相对来说更偏向于具体业务功能的验证,可以让新接手维护该项目的开发测试人员更容易了解该应用。因此,适当的集成测试也可以扮演系统功能说明书的作用。
项目启动类Application
代码语言:javascript复制 package io.metersphere;
@EnableScheduling
@PropertySource(value = {"file:D:\repo\metersphere\backend\src\main\resources\metersphere.properties"}, encoding = "UTF-8", ignoreResourceNotFound = true)
//@PropertySource(value = {"file:c:\opt\metersphere\conf\metersphere.properties"}, encoding = "UTF-8", ignoreResourceNotFound = true)
//@PropertySource(value = {"file:/opt/metersphere/conf/metersphere.properties"}, encoding = "UTF-8", ignoreResourceNotFound = true)
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
这个项目除了通常使用的application.propertiers配置文件外,还使用了@PropertySource注解来额外提供一个运行环境的配置文件。因此,需要根据开发人员的运行环境配置提供一个私有的配置文件。
引入MariaDB4j
一般管理类的应用都会涉及到数据库。笔者观察到MeterSphere项目采用了Flyway作为数据库版本工具。
image.png
image.png
在应用启动时,Flyway会自动管理目标数据库的版本,默认情况下,会将db.migration下面的所有的数据库版本文件依次部署到目标数据库。在这个过程中,就需要一个数据库供Flyway操作了。集成测试一般会选择使用内存数据库或者数据库容器来提供一个运行时的数据库实例。由于H2内存数据库对MySQL数据库的语法的兼容性上还是存在一些问题,在试用之后就放弃了。以下是一个不兼容的案例,
image.png
image.png
因此,改用MariaDB4J这个MySQL的内存数据库。虽然这个项目目前尚未被SpringBoot项目作为默认支持的内存数据库,但是它提供了Sping的插件,易用性也越来越好。首先是引入依赖,这里使用mariaDB4j-springboot。
代码语言:javascript复制<dependency>
<groupId>ch.vorburger.mariaDB4j</groupId>
<artifactId>mariaDB4j-springboot</artifactId>
<version>2.4.0</version>
<scope>test</scope>
</dependency></pre>
然后是对mariaDB4J进行一个简单的配置。如果采用默认配置的话,如使用3306端口,默认数据库名为test,则mariaDB4J可以实现免配置启动。当然此处有一个问题,在新版本的mariaDB4j-springboot上,databaseName这个参数被去掉了,也就是只能使用默认的数据库名。如果需要自定义的数据库schema,则需要自己写一个mariaDB4JService来初始化数据库。
代码语言:javascript复制# 数据库配置
## mariadb
#Location of db files. delete this directory if you need to recreate from scratch
mariaDB4j.dataDir=target/data/local
#Default is 3306, so using 3307 just in case it is already running on this machine
mariaDB4j.port=3307
mariaDB4j.databaseName=test
#mariaDB4j.dbName=metersphere
spring.datasource.url=jdbc:mysql://localhost:${mariaDB4j.port}/${mariaDB4j.databaseName}?useMysqlMetadata=true&autoReconnect=false&useUnicode=true&serverTimezone=GMT+8&characterEncoding=UTF-8&characterSetResults=UTF-8&zeroDateTimeBehavior=convertToNull&useSSL=false
spring.datasource.username=root
spring.datasource.password=
另外,在启动过程中Springboot曾经报告服务端时区未设置,因此url加上了如下的参数。serverTimezone=GMT+8
logback.xml
这个文件也用到了metersphere.properties,也需要参照application类进行修改。
通过上述的修改,MeterSphere的应用就可以启动了。在SpringBoot应用的启动过程中, 内置的内存数据库MariaDB4J会首先启动,然后Flyway完成数据库版本的初始化和系统基础数据的导入。最后,当内置的Jetty服务器完成启动后,应用就可以对外提供服务了。
image.png
image.png
编写测试基类
由于我们的目标是给MeterSphere编写集成测试用例,因此还需要通过测试基类来完成MeterSpere的启动,以及mockMvc的初始化等工作。
代码语言:javascript复制package io.metersphere;
import com.github.database.rider.junit5.DBUnitExtension;
import com.github.database.rider.junit5.api.DBRider;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.jdbc.DataSourceBuilder;
import org.springframework.boot.test.autoconfigure.jdbc.AutoConfigureTestDatabase;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import javax.sql.DataSource;
@Slf4j
@DBRider
@ExtendWith({SpringExtension.class, DBUnitExtension.class})
@SpringBootTest(classes = {Application.class}, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT)
public class TestApp {
@Autowired
protected WebApplicationContext wac;
protected MockMvc mockMvc;
@BeforeEach
public void setup(){
mockMvc = MockMvcBuilders.webAppContextSetup(wac).build(); //初始化MockMvc对象
SecurityUtils.setSecurityManager((org.apache.shiro.mgt.SecurityManager) wac.getBean("securityManager"));
}
@Test
public void just4run()
{
}
}
另外,在引入SpringBootTest MockMvc来启动Spring容器的过程中会报没有SecurityManager Bean的错误。因此,额外自行注入了一个,见setup()方法中的最后一句。
至此,经过上述系统配置调整和测试准备工作,我们就可以开始着手编写用例了。