BUAA-OO-第三单元总结

对本单元测试过程的梳理

黑箱测试和白箱测试

黑箱测试也称功能测试或数据驱动测试。它是在已知产品所应具有的功能的情况下,通过测试来检验每个功能是否能够正常使用。

在测试中,把程序看作一个不能打开的黑盒子,在完全不考虑程序内部结构和内部特性的情况下,在程序接口处进行测试,它只检查程序功能是否按照需求规格说明书的规定正常使用,程序是否能适当地接收输入数据而产生正确的输出信息。

黑箱测试是以用户的角度,从输入数据与输出数据的对应关系出发进行测试的。黑箱测试着眼于程序外部结构,主要针对软件功能进行测试。构造测试样例时需要重点考虑数据的全面性。

白箱测试又称为结构测试或逻辑驱动测试,它是把测试对象看成一个透明的盒子,它允许测试人员利用程序内部的逻辑结构设计测试用例,对程序所有逻辑路径进行测试。白箱测试的测试对象是基于被测试程序的源代码,而不是软件规格说明书。白箱测试要求测试人员全面了解程序内部逻辑结构,了解软件功能该如何实现,进而发现测试代码的逻辑失误。

单元测试

单元测试在软件开发的早期阶段进行,被设计用来检查代码的功能是否按预期工作,一遍及早发现和纠正错误,其目的是验证代码中最小可测试单元(通常是函数、方法或类)的正确性,其核心思想是将代码划分为独立的、可测试的部分,并测试其在各种情况下的行为和输出。

单元测试同时面对单元的功能和代码结构进行测试。单元测试既需要保证功能的正确性,也需要保证行覆盖率、分支覆盖率等覆盖率情况。

单元测试应该是重复执行,可自动化的,并且易于维护的。

功能测试

功能测试是测试软件的功能是否符合需求,通常采用黑箱测试方法。通过构造全面而充分的测试样例,保证程序功能的正确实现。

集成测试

集成测试也称联合测试、组装测试,将程序模式采用适当的集成策略组装起来,对系统的接口及集成后的功能进行正确性检测的测试工作。集成主要目的是检查软件单位之间的接口是否正确。其测试内容是模块之间数据传输,模块之间功能冲突、模块组装功能正确性、全局数据结构、单模块缺陷对系统的影响。它涉及到多个单元或模块的集成和测试,可以检测到集成问题和接口问题,以确保整个系统的正确性、一致性和可靠性。

压力测试

压力测试是一种软件测试,用于验证软件应用程序的稳定性和可靠性。压力测试的目标是在极其沉重的负载条件下测量软件的健壮性和错误处理能力,并确保软件在危机情况下不会崩溃,它甚至可以测试超过正常工作点的测试,并评估软件在极端条件下的工作情况。

压力测试的目标是分析系统发生故障后的行为,确保系统在故障后能够恢复。

回归测试

回归测试是一个系统的质量控制过程,用于验证最近对软件的更改或更新是否无意中引入了新错误或对以前的功能方面产生了负面影响。其主要目标是确保旨在改进的修改不会破坏软件的既定性能和可靠性。回归测试是软件开发过程质量控制措施的一个重要方面。每次进行更改时,都会将其付诸实践,以确保它不会无意中导致任何功能或性能问题。

将新功能或增强功能部署到现有代码库或应用程序时,需要进行回归测试。它确保现有应用程序的任何新功能或更新都能正常工作,而不会出现任何错误或缺陷。在OO作业中,回归测试应该在新增作业后进行,测试上一次的功能不会受到影响。

架构设计,图模型构建和维护策略

第九次作业,主要实现Network,Person两个主要类,和四个异常计数类。network的重点功能是,判断两个人是否相连,获得blockSum的数量,和三元环的数量。

第十次作业,新增Tag类和四个异常计数类。在这次作业,Tag类仅仅返回了内部的AgeVar,和ValueSum,network类实现了对Tag的添加工作,和计算最短路径的工作(不带权值)。

第十一次作业新增四种类型的信息,增加network内Person的交互,和四个异常计数类。network实现的重点功能是sendMessage(),即实现一个人对另一个人或者Tag内的人发消息的功能。Message类之间实现了继承关系。Tag类的物理意义在这次作业得以体现。

本单元,各个类之间通过network类建立联系,又彼此分离,降低了类之间的耦合性,增强类自身的内聚性。同时本单元的功能实现主要是通过图模型来实现的,通过这种设计(Person内维护和自己直接相连的Person,network类维护总的Person数组),实际上network类也自带了一个邻接矩阵的图表示。

图模型的构建和维护:network类维护自身的Person数组,维护所有的点,每个Person自己维护与之直接相连的边,进而维护整个邻接矩阵。本单元,处于对JML设计的图模型表示方法的尊重,我并没有重新构建一个以边为导向的图模型。实际上,如果不对并查集进行额外的操作是不需要再建图模型的。

作业中出现的性能问题,对规格与实现分离的理解

虽然我的程序设计在强测中并没有出现CTLE的情况,但还是有地方出现了性能不足,还打了一次复活赛。
Network类的isCircle()方法判断两个点在图中是否连通,我采用了并查集的方法去快速获得两点之间的连通性,但是并查集并不支持删边的操作,因此在每次删边后我采用了重建并查集的方法,这会极大拖慢程序运行的速度,导致了一次CTLE,可以采用延迟重建的方法增加一点效率。其次,在获得Tag内的valueSum时,也是一个极易产生性能问题的事情,如果不动态维护,每次n^2的时间复杂度是不能忍受的,但是如果动态维护,每次加边、删边又会导致额外的时间消耗,但是,由于Tag内的Person的特殊性,加边或删边时只需要遍历其中一个点的所有直接相连点的所有Tag。并不需要遍历所有的Tag。这样虽然没有构造额外的方法去减轻操作数,也没有导致超时。

JML规格只是为了保证程序功能的正确性和全面性,保证设计层面程序的正确性,(实质上)并没有规定程序的实现手段,实现效率。因此如果严格按照规格要求的去实现代码,有时候会导致程序效率极低,比如本单元就出现了三层循环的规格说明,有时候根本没有说要怎么得到结果,只是规定了结果要满足的约束,比如最短路径的实现。同时,属性所需的容器也没有严格定义,需要我们自己去选择。规格为了严格保证设计和功能实现的正确性,会采用一些比较基础甚至极端简单的说明方法去描述程序的实现,我们当然不可能采用这些叙述去实现我们的代码。因此,规格与实现分离,就是要求我们要在满足规格的约束条件的情况下,自己确定合理的实现方法,正确实现程序的功能。

Junit测试

简单来说,利用规格的require要求,针对性的构造测试样例。使用规格的ensure,pure等语句实现junit测试的assertEqual()断言。
根据规格的描述,重新计算数据,验证自己的实现方法的结果正确性。

Junit测试检验代码实现与规格的一致性的效果

关于我三次Junit测试的编写,我没有一次不出错误。问题有:Junit测试样例的不充分,不全面,数据量不够。Junit测试代码写错。印象深刻的一次错误是,第一次作业,我先运行Network类的计算方法,然后在测试中根据JML实现正确的结果,这个顺序错误产生了问题。关于测试样例的生成,我们不仅要保证样例的随机性,还要保证样例的充分性。最后一次测试deleteColdEmoji()方法正确性,这个方法本身不直接处理红包信息。因此我没有生成RedEnvelopeMessage,这也导致了错误。

学习体会

通过本单元的学习,我学会了根据JML规格编写程序,也学会了编写简单的JML规格。这增强了我阅读理解JML规格的能力,也锻炼我对程序性能的把控。虽然JML把设计的工作完成了,但是我们还是要选择恰当的实现方式解决问题。
这是我第一次接触契约式编程思想,同时本单元带我体验了一个严谨的程序应该如何编写,既需要判断各种边界条件,实现各种前置条件,也要选择合适的容器和实现方法。这种编程思想和编程经历会极大的影响我。可以看作“武学总纲”或“经典样式”。同时,我也认识到了设计的重要性和自己在设计方面的不足。

  • 24
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值