275
社区成员
发帖
与我相关
我的任务
分享一、测试过程分析与测试策略
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. 数据构造策略
白箱+黑箱(AI)策略提升测试覆盖率:
// 五种图结构
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<>();
第十一次未出现问题,第九次和第十次作业问题如下:

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 testhttps://i-blog.csdnimg.cn/communtity/862a345317964cafabda7109a6496346.png "#left")
ModifyRelation_RemoveNonExist() {
network.modifyRelation(1, 2, -150);
}
2. 覆盖率控制

JML的三种核心结构(ensures、invariant、signals)与JUnit的断言机制形成对应:
ensures 子句直接转化为 assertEquals:// JML: ensures \result == size;
assertEquals(size, collection.size());
signals 子句通过 try-catch 结构验证异常的类型和内容基于JML的测试具有以下策略优势:
\forall、\exists引导测试用例覆盖各种边界情况和特殊值。1. 规格规范开发:记得上OOpre时感叹助教代码写的怎么如此规范,现在能向其一步步靠拢了
2. JML本质上是契约式设计的实践,明确前置条件、后置条件和不变式
3. JML是一个优秀的规格化语言,可以帮助我们避免一些通用语言表达上的二义性问题
4. 在小规模开发上为什么要编写jml?编写jml的功夫不是已经把代码写完了吗?私以为有点过于消耗时间,且jml的正确性又由谁来保证呢?