BUAA-OO-UNIT3 JML规格化设计

BUAA-OO-UNIT3 JML规格化设计

测试过程

测试方法

首先谈一谈我对各种测试方法的理解。

黑箱测试

黑箱测试主要关注的是测试程序的外部行为,而不关注程序实现的内部代码和逻辑,意即为将测试的程序当作一个黑箱,我们给定一个输入后,所获取的只有对应的输出,而看不到内部是怎么计算得到输出的,我们要做的就是把所得到的输出和期望输出进行对比,看是否符合我们的需求。课程的评测机便是黑箱测试。

白箱测试

对应黑箱测试,白箱测试就很好理解了,就是主要关注测试系统是如何实现的,其实现的代码逻辑、算法细节是否符合规格。当我们给定一个输入后,白箱测试应根据输入对代码的每一部分逻辑细节进行测试,并将是否符合规格通过输出告知我们。在这一单元中,我们写的OKtest方法便是对自己写下程序的白箱测试。

单元测试

单元测试是指对程序的可测试单元模块进行测试,譬如对一个特定函数的代码测试,它在我们定位到具体的错误后会被用到。单元测试跟白箱测试一样,都需要测试代码的细节,但单元测试聚焦的代码范围更小,针对性更强。在本单元作业中,我通过单元测试对一些特定函数,比如modifyRelation进行了测试。

功能测试

功能测试指对程序的功能进行测试,来验证程序是否满足需求。功能测试又有点像黑盒测试,但黑盒测试强调了不注重代码内部细节,并且黑盒测试关注了程序的各个方面,譬如性能、安全性等,而功能测试只注重于检查代码的功能是否符合需求。

集成测试

集成测试是指将程序中的多个已经通过单元测试的单元组合起来进行测试,来验证这些单元是否能够实现接口对齐,集成形成的模块能够正常运行。在本单元作业中,我将addPerson, addRelation, modifyRelation和多个query函数组合起来,进行了模块测试。

压力测试

压力测试指通过大规模、高负荷的数据对程序进行测试,来测试程序的性能,验证程序在数据规模较大的情况下仍能保持运行效率和稳定性。在本单元作业中,有多个涉及到算法复杂度的函数,比如第三次作业的queryLeastMoment函数,我通过大量的addPerson和addRelation构建了规模很大的社交图,从而对每个Person对象形成了数量较多的环,再对一些Person对象调用queryLeastMoments函数,来测试该函数在数据压力较大情况下的运行效率。

回归测试

回归测试指找到程序的bug并将其修复后,再构造bug对应的数据以及其他针对性强的数据,对程序进行测试,以验证修改过的程序是否已妥善地处理了bug并正常运行,并且不会导致额外的bug。回归测试是我每一次写代码都会经历的过程。

测试流程

测试的大致流程如下:

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Ao14t9wI-1684329927219)(E:\Study\2023春\OO\测试流程.png)]

测试工具

在本单元我并没有使用测试工具如JUnit进行测试,因为对每个单元的编写JUnit进行测试确实比较麻烦(逃),因此对于大多数函数方法,我采用的还是手动构造数据进行测试。除此之外,我也使用了部分同学搭建的评测机,对程序进行了测试。

数据构造

由于本单元的任务主要是根据规格完成方法代码,其中的一些方法比较好实现,并不需要进行特殊的数据构造,只需确认正确性即可;但也有一些方法,如第二次作业中的modifyRelation,涉及到删除边的操作,其与queryBlockSum, queryTripleSum指令混合在一起就容易出现错误,因此在这次作业中,我就构造了许多组modifyRelation删除边与queryBlockSum, queryTripleSum指令组合的数据,构建出一个较为简单的关系图,并对预期输出进行判断,然后放到程序中得到输出,这帮助我找到了一些bug。

此外,还需要对规格要求中涉及到的边界数据进行构造,如在第二次作业中,queryReceivedMessage指令涉及到前五条信息,如果构造普通数据的话难以找到在这个地方发生的错误,因此要构造多于五条信息的情况,观察取得的五条信息是否为接收到的前五条信息。

这一单元的作业还涉及到异常的处理和计数,这也要求我们对异常数据进行构造,测试程序对异常情况的处理能力,并对计数进行判断,这有助于验证程序在面对不合理或异常情况时的鲁棒性和错误处理能力。

最后就是增大数据强度,进行混合测试,可以通过python生成若干条输入语句,对程序进行测试,可以与其他同学的程序进行对拍,找到不同并发现错误。

架构设计

我主要采用并查集对图进行构建和维护。每当加入一个Person时,将其添加到并查集中;加入一个Relation时,通过并查集的merge方法对Person的祖先进行修改。

对于queryTripleSum和queryBlockSum,我也直接在并查集的维护中进行计算,每加入一个Person时,对blockSum进行自增;加入关系时,对tripleSum进行动态维护,若加入的关系会导致新的三元环产生,就增加tripleSum。在调用queryTripleSum和queryBlockSum指令时,直接返回tripleSum和blockSum的值即可,不需要再次重复计算。

此外,若modifyRelation将两人的关系删除,我采用的方法是重建并查集,将所有关系全部删除,再进行重新添加,此处要注意对blockSum和tripleSum的维护修改。

对于queryLeastMoments指令,寻找最小环,我采用的方法是讨论区中同学提出的方法,对于起点 i,假如点 j 与 i 直接相连,则删掉此边后查询 i 和 j 之间是否仍然存在路径。若存在路径,则一个可能的最短环值就是 路径的最短值(通过dijkstra算法进行计算)加上 i,j 直接相连的路径值。重复此操作遍历所有与起点直接相连的点即可得到最短环值。但这种方法在强测中超时了两个点,还需要进一步改进。

性能问题

在本单元作业中,我出现的性能问题如下:

在第一次作业中,我对规格化设计的认识不清,错误地以为只需要将规格转化为代码,不需要考虑内在的代码逻辑和算法,因此将规格直接翻译为代码,没有考虑时间复杂度的问题,也没有构建任何的数据结构。这导致我的queryTripleSum时间复杂度为O(n^3),在强测中扣了一些分数。在第一次作业结束后,我才将并查集引入到我的程序中。

在第二次作业中,我并没有出现性能问题,但是在一些JML规格的细节理解上出了问题,如queryCoupleSum中,value相同时应取最小的用户ID作为bestAcquaintance,然而我理解为取先加入关系的用户ID作为bestAcquaintance。这也是因为我对JML规格不够熟悉,阅读的不够仔细。

在第三次作业中,我在queryLeastMoments指令上出现了性能问题,使用Dijkstra算法计算最小环会导致超时,需要通过优先队列等方法进行优化,或者修改为spfa算法。

规格与实现分离

在第一次作业的惨痛教训下,我对规格与实现分离有了很深刻的认识。

所谓“规格与实现”,可以将其与物理中的“位移与路程”做对比。规格描述了我们应该完成的事情,即代码执行完后对象的状态,并提供对应的输入输出接口供我们调用;这正如同位移描述了一个质点在运动完后位置的变化。实现过程是我们去编写代码自己完成的,是去使用算法等知识去降低时间复杂度,让程序的性能更优秀;同理,路程是各种从起点到终点的方法,有长有短,有快有慢,要选择合适的路程来完成位移。

因此,通过规格与实现分离,可以增强软件开发和测试的灵活性、可维护性和可扩展性。

OK测试

在三次作业中,我们被要求分别对三个方法写出OKtest测试程序。编写OKtest能够根据规格说明中定义的功能要求,验证代码的实现是否符合规格的要求。

并且规格中可能包含了对边界条件的描述,而通过使用Oktest编写测试用例,可以验证代码在边界情况下的行为是否与规格一致。

此外,通过设计和执行全面的样例数据,可以发现代码实现中可能存在的潜在问题或遗漏的功能点,从而提高代码与规格一致性的可靠性。

虽然在第二次作业中对modifyRelation的OKtest写起来让人很头疼,繁琐的要求过于多,但没有繁琐的要求也没有正确的结果,这也是可以理解的。

学习体会

在本单元的学习中,我了解并大致掌握了JML规格语言,并且我还学习到了规格化设计,以及规格与实现分离的一些思想。此外,我还学习到了并查集,求最小环等特殊的数据结构和算法。

在被算法难住的时候,我确实对这一单元的设计有一些异议,心想,为什么在规格化设计这一单元中我们需要自主学习其他的算法;但转念一想,其实这一单元就有点像将来工作,课程组是甲方,而我们是乙方,课程组提出的要求如果不具有难度梯度,那也并不符合常理,而且提出的要求正是需要我们去查阅资料,独自寻找解决方案,以完成甲方提出的任务。我也在这个过程中学到了很多的并查集,Dijkstra,spfa等优秀的的数据结构和算法。

这一单元由于自己的多次大意,成绩并不理想,希望自己在第四单元以及以后编写代码时认真读题,看清需求,谨慎写码。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值