目录
测试框架
测试用例编写
痛点
设想
方案设计
技术手段
为啥不用testng的@BeforeMethod
参考
测试框架
junit
testing
测试用例编写
示例:测试订单的提交方法
- 准备Product商品对象
- 准备OrderItem行项对象,并赋值Product
- 创建Order对象,并给赋值OrderItem
- Order对象进行提交,并生成OrderNo
- 查询Order数据并Assert
- 调用Order对象的delete方法
- 调用OrderItem的delete方法
- 调用Product的delete方法
如下图所示:
正真核心的逻辑只要就是提交一下,但这个逻辑会依赖其他逻辑。所以需要编写很多辅助逻辑,并在测试完成(成功或者失败)都需要清理生成的垃圾对象。
按照模型驱动DDD,UML的思路:
- 订单依赖 商品:没有商品就不可能生成订单
- 每个类都有一个生命周期,起点是创建,终点是删除
- 对象生命周期各阶段会有一个依赖关系:如人会经历“出生”“幼儿”“儿童”“少年”“青年”“中年”“老年”“拜拜”
痛点
编写测试用例会创建很多依赖对象,这些对象都需要在结束后回收,很容易遗漏,写起来工作量也挺大。
设想
- 依赖的对象:在方法钱,添加配置(实体,方法,几个)就可以获取到对象
- 对象回收:创建的对象可以自动回收,不需要手动调用方法或者接口来清除
测试如果是下面的就好了:
// 或者使用这种方式使用,注册后使用的方法不同罢了
@Service("Order")
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations= "classpath:bean.xml")
public class Order extends BaseObject {
// 注册实体类信息
protected Order(String objectName) {
super("Order",Order.class);
}
@DependentObjects(objects = [
/**
* 依赖OrderItem实体,创建一个对象,名称前缀item,变量名位:item001,item002
* 至于OrderItem依赖啥就在OrderItem.create方法中配置
*/
{entity="OrderItem",objectNum=1,namePre="item"}
})
@Test
public void create(){
/**
* 1. 根据名称或者Product类型获取
* 2. 创建Order,并赋值item和product
* 3. create的对象,在destroy方法中删除
*/
}
// 依赖的对象是Product,OrderItem
@DependentObjects(objects = {"Product","OrderItem"})
// 依赖的订单状态是create方法,即在create执行后再执行该方法
@DependentOperate("Order.create")
@Test
public void commnit(){
/**
* 1. 根据名称或者Product类型获取
* 2. 执行操作
* 3. 执行后自动回收依赖的对象和使用规范中创建的对象
*/
}
// 清除对象
@Test
// 依赖的订单状态是create方法,即在create执行后再执行该方法
@DependentOperate("Order.create")
public void destroy(){
}
}
public class OrderItem extends BaseObject {
@DependentObjects(objects = [
// 依赖Product实体,创建两个对象,名称前缀pro,变量名位:pro001,pro002
{entity="Product",objectNum=2,namePre="pro"}
})
@Test
public void create() {
}
@Test
public void destroy() {
}
}
方案设计
- 实体和测试类对应:按照实体和测试类对应方式,确定每个实体都有一个创建和删除的方法,这些方法都可能是调用后端接口实现
- 测试方法依赖类:通过主键的方法配置。
- 实体内状态依赖:配置依赖的上一个方法
- 测试用例启动时加载配置
- 在每个Case方法执行的时候,使用AOP创建根据配置的注解执行前置方法
- 前置方法产生的数据对象放在线程缓存中
- 方法执行后清理线程缓存中的方法
技术手段
配置加载
springboot+junit:@SpringBootTest @BeforeAll,或者使用构造方法
testng:@BeforeSuite
AOP切面
junit+spring:配置注解类型的AOP即可
testng:Ihookable监听器
对象创建和删除
每个对象都实现一个create方法,并存储到缓存中
执行完成后有AutoGc组件调用destroy方法进行回收
垃圾回收
根据依赖创建对象的顺序栈,回收
在当前方法执行完就开始执行
为啥不用testng的@BeforeMethod
- 方法级别和业务抽象不同:testing 可以实现代码级别beforeMethod,即:在这个方法之前执行啥,而咱们的组件更侧重于抽象到实体的相互依赖。
- 体现了领域驱动设计的方法论,对开发者的约束更强
- 实现了自动回收辅助的垃圾对象机制,而testng只是方法级别支持你每个方法之后预留锚点接口,没有实现自动垃圾回收机制