OO Unit3 总结

一、测试过程分析与测试策略

1. 测试体系分层实践
在本单元的作业中,我们构建了多层次测试体系:
• 单元测试:针对每个JML规格方法编写独立测试用例,同时包装addPerson、addRelation等原子操作

• 功能测试:只需考虑需要方法的功能,不需要考虑内部结构及代码。

  @Test
//验证pure
  public void testPureProperty() throws Exception {
      Network network = createSampleNetwork();
      // 记录初始状态
      PersonInterface[] before = network.getPersons();
      // 调用方法
      network.queryCoupleSum();
      // 验证状态未改变
      PersonInterface[] after = network.getPersons();
      assertArrayEquals("Data modified after pure method call", before, after);
  }

• 集成测试:验证模块间协作。在本单元中,我们有时需要对一些值进行维护,以加快查找速度,以queryTagValueSum方法为例,构建跨标签的关系网络,测试添加/删除人员时多个标签的数值同步更新逻辑

• 压力测试:通过自动化脚本生成超大规模数据测试程序的性能和正确性,包括可能的tle以及wa

• 回归测试:每次迭代后运行历史测试集,我在测试时候并未采用该方法

2. 数据构造策略

白箱+黑箱策略提升测试覆盖率:

  • 白箱

  • 基础场景
    构造基础特征数据组合,如:

    // 五种图结构
    EMPTY_GRAPH, SINGLE_NODE, TWO_NODES, TRIANGLE, COMPLEX_GRAPH
    
  • 边界值构造
    重点关注空图、完全图、最大节点数等边界场景:

    // 测试网络容量边界
    for (int i=0; i<MAX_PERSON; i++) {
        network.addPerson(new Person(i, "Test", 20));
    }
    

-黑箱

  • 随机化测试
    开发自动化数据生成工具,数据构造器来随机生成数据

二、大模型辅助开发实践

JML规格解析
本单元大模型在写代码过程中最大的作用是读取jml信息并以自然语言描述出来辅助我们的理解,加快jml阅读速度

[用户输入]  
解释JML中的ensures子句:  
@ ensures \result == (\sum int i; 0<=i<people.length; people[i].getAge());

[模型输出]
该规格要求方法返回值等于people数组中所有人员年龄的总和

但是往往直接将jml以及作业要求喂给AI,其写出来的方法很容易出现tle或者wrong answer
同样的,在ai给出的代码基础上自己进行修改工作量大,对于条件容易遗漏

三、图模型构建与优化

在这里插入图片描述

在本单元中,社交网络可以抽象为一个无向图,其中人员表示为图中的节点,人员之间的关系表示为图中的边,边的权重表示关系的数值。具体实现时,使用 Network 类中的 persons 列表来存储所有的人员节点,每个 Person 类实例中使用 acquaintance 数组和 value 数组来存储其相邻节点和对应的边权重。

图模型维护
  • 添加人员:当调用 Network 类的 addPerson 方法时,会检查人员 ID 的唯一性
  • 添加关系:当调用 Network 类的 addRelation 方法时,会检查两个人员是否存在以及关系是否已经存在。如果人员存在且关系不存在,则在两个人员的 acquaintance 数组和 value 数组中添加相应的信息。
  • 修改关系:当调用 Network 类的 modifyRelation 方法时,会检查两个人员是否存在、关系是否存在以及修改后的权重是否大于 0。如果满足条件,则更新关系的权重;如果权重小于等于 0,则删除该关系,并从相关标签中移除对应的人员。

存储person时我采用的是

private final ArrayList<Person> persons = new ArrayList<>();

但是性能不佳 可以采用邻接表+哈希索引:

private Map<Integer, Person> personMap = new HashMap<>();
private Map<Integer, List<Edge>> adjacencyList = new HashMap<>();
四、性能问题与修复

典型问题与解决方案
第十一次未出现问题,第九次和第十次作业问题如下:

问题根因分析优化方案
queryTripleSum超时三重循环遍历所有三元组使用bitset
qtvs缓存失效未及时更新关系变更对Tag的影响实现增量更新

五、JUnit测试实践

1. 基于规格的测试设计

// 验证后置条件
@Test
public void testAddRelation_EnsureSum() {
    int initialSum = network.queryValueSum(tagId);
    network.addRelation(1, 2, 100);
    assertEquals(initialSum + 200, network.queryValueSum(tagId));
}

// 异常场景测试
@Test(expected = RelationNotFoundException.class)
public void testModifyRelation_RemoveNonExist() {
    network.modifyRelation(1, 2, -150); 
}

2. 覆盖率控制
外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传


六、JML与JUnit协同测试
一、测试逻辑

JML的三种核心结构(ensures、invariant、signals)与JUnit的断言机制形成对应:

  1. 后置条件验证ensures 子句直接转化为 assertEquals
    // JML: ensures \result == size;
    assertEquals(size, collection.size());
    
  2. 不变式检查:类的不变式(如社交值与金额的关系)在每次操作后进行验证,确保对象状态的一致性
  3. 异常处理signals 子句通过 try-catch 结构验证异常的类型和内容
二、测试策略

基于JML的测试具有以下策略优势:

  • 黑盒测试:测试者只需关注规格描述,无需了解具体实现细节,有效分离了设计与验证。
  • 边界条件:JML中的量化表达式(如\forall\exists)自然引导测试用例覆盖各种边界情况和特殊值。
  • 状态维护:通过检查,确保类的内部状态在任何操作后都保持合法,有效预防状态泄露和数据不一致问题。
七、学习收获与展望
  1. 规格规范开发:JML规范成为设计与实现的桥梁,有效提升代码质量,还记得上OOpre时感叹助教代码写的怎么如此规范
  2. JML是一个优秀的规格化语言,可以帮助我们避免一些通用语言表达上的二义性问题
  3. 这本质上是契约式设计的实践,通过明确的前置条件、后置条件和不变式,在代码层面实现了设计文档与测试用例的同步更新
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值