301
社区成员
发帖
与我相关
我的任务
分享黑箱测试就是不考虑被测试程序的具体内容,直接构造测试样例并通过输出判断程序的正确性。
白箱测试就是先分析被测试程序的具体代码,找出其中的bug或可能出错的地方,然后再针对性地构造测试样例进行测试。
单元测试是针对程序的最小模块进行正确性检验的测试,通常情况下是白箱测试。
功能测试是从外部需求的角度,检验程序能否正确实现所有要求的功能而进行的测试,通常是黑箱测试。
集成测试用来测试各个单元之间的接口,在多个单元测试的基础上进行,对象是多个通过单元测试的模块。
压力测试用来测试程序在数据较多,负载较大的情况下的正确性。
回归测试是指修改了旧代码后,重新进行测试以确认修改没有引入新的错误或导致其他代码产生错误。
本单元由于官方包中已给出了各个具体的实现接口,所以我的三次作业的代码架构基本固定,均与官方包中的架构相同,没有发生太大变化。我的代码大致可以分为主类、异常类和具体实现类三种。在具体实现类中,MyNetwork是整个社交网络,其中包含若干个person,每个person中又包含若干个Tag,在第三次作业中还加入了Message,这些元素共同构成了一个完整的社交网络。
对于图模型的构建,MyNetwork可以看做一个带权无向图,其中的person为图中的点,person与person之间的relation为边,而value即为边上的权值。将整个社交网络用图来表示可以使得用JML语言描述的方法更容易理解,也方便了我们从多个角度寻求解决问题的方法来提高性能。
关于维护策略,我主要采取的是动态维护策略,即在修改图的内容时立即进行维护,而不是在查询时才从头开始找。
具体而言:
第二次作业中,对于Tag类中的getValueSum()和getAgeMean()方法,我在Tag添加人和删除人的时候对Tag中的人的年龄总和ageSum进行及时的维护;同理,在Tag中的边发生变动时,我也会维护边的权值之和valueSum。而bestId主要是在加边时将新加的人与原来的bestID对应的人进行比较来选出新的bestId,不过需要注意在删边或者原来的bestId的value值减少的时候要重新遍历寻找新的bestId。至于查找两个点之间的最短路径,我采用的是bfs。
第三次作业没有什么需要优化的算法,唯一特殊的点是我在本次作业中用了链表来存储person中的Message,因为链表的插入和删除操作比较方便,而且是有序的。此外,在循环遍历删除的时候要用迭代器删除,不能直接遍历。
本单元强测和互测均未出现bug。
而对于规格与实现分离,首先规格描述的是程序应该做什么,即程序的功能性需求和约束条件。规格定义了程序的输入、输出、行为等方面的要求,但不涉及具体的实现细节。
而实现指的是根据规格编写的代码和算法,它是程序实现其功能和操作的具体方式。实现是程序开发的核心部分,它负责将规格中的要求转化为可执行的代码。
规格与实现分离可以提高程序的可维护性,增强可扩展性,通过定义清晰的规格文档和接口,不同的实现可以方便地替换或扩展,此外也便于程序的测试。
根据规格信息编写Junit测试,首先要覆盖所有的normal_behavior,其次要确保方法运行之后的结果能够满足所有的ensures所要求的内容。此外,对于pure方法,还要检测调用对象在调用方法前后有没有发生变化,如属性是否改变等。如果方法有返回值,还要检查返回值是否正确。
至于测试效果,除了要严格按照规格来写Junit测试,测试效果还与测试数据的强弱以及合理性有很大关系。如果测试数据足够多、足够强且覆盖的情况比较全面的话,Junit测试检验代码实现与规格是否一致的效果还是不错的。
通过这一单元的学习,我对JML语言有了一定的了解。从最初的看到比较复杂的描述就一头雾水到之后能够较为熟练地看懂JML在说什么,我感觉我对于JML的理解能力有了很大的提升。
JML作为一种规格化语言,确实写起来比较麻烦,读起来也比较晦涩,但它严密的逻辑使得它在某些重要领域仍然具有十分重要的作用。所以我觉得这一个单元的学习对于我们而言还是有很大作用的,也许将来哪一天就会用到JML。
总体而言,本单元的难度比较低,读懂了JML的话就会好很多。不过如何优化某些方法的算法以防止超时也确实要思考一番,在这个过程中我也学习到了一些关于图的算法如并查集等,也算受益匪浅。