文章目录
测试过程
黑盒测试与白盒测试
黑盒测试是一种基于用户界面的功能测试。
使用黑盒测试我们不必关注代码的具体实现过程。比如下载下互测房间的代码,却不进行阅读,直接输入数据进行评测,这就是一种黑盒测试。
白盒测试是一种基于代码的功能测试。
白盒测试是基于对代码的内部结构和实现细节的了解设计测试用例执行的测试。比如在查找自己的bug时,我会用到白盒测试的方法,根据具体代码实现构造覆盖各个分支的数据,从而精准定位bug的位置。
综上,我认为黑盒测试是一种广泛的测试方式,但是精度不算很高,针对性不强;白盒测试是一种精确的测试方式,但是消耗的时间精力较多。
其他各种测试
- 单元测试:是指对软件中的最小可测试单元进行检查和验证,比如junit中对一个特定方法的测试。
- 功能测试:功能性测试是根据功能要求对软件进行的测试,确保程序按照预期的方式运行。黑盒测试和百盒测试都是功能测试的手段。
- 集成测试:主要是测试多个组件或模块在整个系统中的集成和交互是否正常。它通常在单元测试和系统测试之间进行,可以检测到集成问题和接口问题,以确保整个系统的正确性、一致性和可靠性。
- 压力测试:压力测试不是在常规条件下运行手动或自动测试,而是在计算机数量较少或系统资源匮乏的条件下运行测试。通常要进行软件压力测试的资源包括内存、CPU、磁盘等。
- 回归测试:回归测试是指修改了旧代码后,重新进行测试以确认修改没有引入新的错误或导致其他代码产生错误,是一个系统的质量控制过程。
数据构造
由于没有搭建评测机,我自己构造数据主要在万不得已或junit的时候进行,在下面提到。
架构设计和性能优化
本单元的每个方法都提供了jml,因此没有进行什么特别的架构设计。但是为了不出现CTLE,本单元需要在性能优化上下一定功夫。包括但不限于容器选择、数据动态维护、图论算法等性能优化,下面是几个经典的采用了性能优化的方法。
isCircle
并查集
并查集是一种树型的数据结构,用于处理一些不相交集合的合并及查询问题,isCircle函数为查询两结点的连通性,可以用并查集来实现。针对并查集的基本操作有:
-
增加结点
新增加的结点自成一个连通块,fa指针指向自己
-
增加关系
-
若两结点已在一个连通块中
不需要做修改
-
若两结点不在一个连通块中
将其中一个连通块的代表元的fa指针指向另一个连通块的代表元,实现连通块的合并
-
-
查找代表元
通过fa指针不断寻找祖先,直到查找到某一结点的fa指针指向自己,说明它就是这个连通块的代表元
优化方法
路径压缩
当查询代表元时,我们可以顺便更新这条查询路径上所有结点的fa指针为最终查询到的代表元,来减少下一次查询消耗的时间。
按秩合并
在增加关系连通块合并时,由于我们希望树的高度尽可能小(树的高度与查询时间正相关),因此在每次合并时我们将“小”树的fa指针挂在“大”树的根节点上。
删除关系时的并查集重置
可以围绕删除关系的两个结点,采用DFS或BFS进行图的重置,这时可能会涉及到连通块的分裂。
queryShortestPath
Dijkstra算法
迪杰斯特拉算法用于计算一个源结点到其它结点的最短路径,适用于本单元的queryShortestPath。
算法思想:贪心,即在每一步选择中,都采取在当前状态下最好或最优的选择,希望最终能得到全局最优解。
算法核心:
- 目前已知的最短距离dis[]
- 已求出最短路径的节点vis[]
- 从u出发,松弛与u相连的每个未被访问的结点
带优化的Dijkstra算法
在找一个权值最小的结点时,需要遍历所有与该结点直接相连的结点,时间复杂度为O(n)。为此可以用堆对这些结点进行排序,查找权值最小的时间复杂度降至O(logn)。堆可以用优先队列实现,而优先队列在java中可以用Priority Queue类实现:
PriorityQueue<Node> heap = new PriorityQueue<>();
public class Node implements Comparable<Node> {
// ...
}
queryTagAgeVar
这个方法需要计算tag中所有人年龄的方差,优化体现在动态维护年龄和与年龄平方和,这样在每次查询时不必遍历相加,这是Unit3中常采用的优化方法。
junit测试
忠于规格
jml与junit有很高的契合度,所以基于jml的junit测试关键就是要忠于规格。比如以下jml的关键字都要在junit测试中有所体现。
pure
\result
\not_assigned
\exists
...
虽然像pure这种的检验很容易忽视,但总体来说jml为junit提供了标准,所以编写单元测试变得更加容易。
针对性数据构造
本单元要求对三种方法编写junit,根据它们方法的特点,可以针对性进行数据构造,避免出现数据看似量大但有效性不高,强度不够的情况。
- queryTripleSum:查询图里的三联通分量个数,因此构造数据中图的稠密度要高。比较简单粗暴的方法是加成完全图再删成零图,过程中不停进行断言。
- queryCoupleSum:查找关系网中互为最佳熟人的个数,因此构造数据应侧重于关系值的调整,这样才能使CoupleSum常处于变化中。
- deleteColdEmoji:删除冷门表情,因此构造数据要体现各种表情消息的热度梯度,并且混入非表情消息,这样才能使测试更加全面。
学习体会
本单元的官方主题是jml,但我的体会是看jml理解该函数的作用或者对着jml写junit并不算太困难,相比于真正写jml来说。
第三单元对性能有硬性要求没有性能分性能不够直接0分,所以学习了一些数据结构和算法的相关知识,也算是很有收获。并且由于我们这一届对junit进行了改革,我还被迫学会了真正的junit,而不是像oopre那样利用无效断言提高覆盖率通过中测。
由于自己一个小的疏忽bug修复只用加2行就能解决,本单元没能取得特别满意的成绩,有点遗憾,希望下一单元继续加油。