北航面对对象编程第三单元博客作业
黑箱测试与白箱测试
黑箱测试,又称为功能测试,是一种不考虑内部结构和实现机制的测试方法。测试者只需要关注程序的输入输出是否达到预期的效果。这种测试方法适用于任何级别的软件测试,如单元测试、集成测试和系统测试。
白箱测试,又称为结构测试或透明盒测试,侧重于检查软件内部的逻辑结构。在白箱测试中,测试者需要了解程序内部的代码结构,通过设计测试用例来覆盖代码中的各个分支、循环和条件判断等。这种方法有助于确保代码的每个部分都被执行到,并且正确实现了预定功能。
我们的强测、中测都是属于黑箱测试,互测属于白箱测试,互测中我们可以互相检查对方代码内部逻辑,进而寻找出错误和bug。
测试的范围和目的
- 单元测试主要针对程序中的最小可测试单元进行测试。我们的作业中,主要使用Junit4在完成弱测时进行单元测试,确保能够检查出课程组给出的错误代码。
- 功能测试则关注软件的业务需求是否得到满足。通过黑箱测试方法,测试者模拟用户的操作,检查软件的功能是否符合用户的需求。
- 集成测试关注多个单元、模块或组件如何协同工作。这类测试检查接口间的数据流和功能协调,确保组件间的集成符合设计规范。
- 压力测试旨在评估软件在超出正常操作或极端条件下的表现。通过模拟高负荷情况,可以发现软件的性能瓶颈和稳定性问题。
- 回归测试是在软件修改后进行的测试,确保新的更改没有引入新的错误,并且原有功能仍然正常工作。这种测试通常在软件开发的每个阶段后都会进行,特别是在修复缺陷或更新功能后。
数据构造策略
针对时间复杂度可能比较高的方法专门构造测试样例,提高样例强度。
架构设计和组件交互
- Person类
- 负责存储个人信息如:D、姓名、年龄、社交价值和金钱。
- 与其他人物维护社交关系,这些关系可以用图中的边来表示,边的权值表示社交关系的强度或价值。
- 可以拥有多个标签(Tag),并接收不同类型的消息。
- Network类
- 作为整个社交网络的核心,管理所有的Person实例和消息。
- 提供方法来添加和删除人物,处理人与人之间的关系,以及消息的传递。
- 维护一个图模型,其中节点是Person对象,边代表人与人之间的关系。
- Message及其子类
- 抽象基类Message定义了所有消息的共通属性和方法。
- EmojiMessage、NoticeMessage、RedEnvelopeMessage等继承自Message,每种消息处理其特定的数据和行为。
- Tag类
- 用于标记具有共同特征的Person,如兴趣、活动等。
- 在图模型中,Tag可以视为一个聚类的标识,将一组具有共同标签的Person聚集在一起。
图模型构建和维护策略
- 图的构建
- 图的节点由Person实例构成,每个节点通过它的唯一ID标识。
- 边表示人际存在关系,根据社交动态变化,本次作业的边为无向边
- 边的权重表示关系友好度。
- 维护策略
- 当添加或删除人物时,相应地更新图的节点和边。
- 更新人物间关系时,调整边的存在性或权重。
- 标签变动(添加或删除Tag)时,更新与人物节点相关联的标签信息。
- 消息传递影响图的动态,如通过消息改变社交价值或金钱状态。
- 性能和优化
- 对于频繁的查询操作,如查找最短路径或查询社交圈,使用缓存(我的代码使用了cache)和预计算策略以提高性能。
- 同时对于题目中要求的数据存储,选择合适的数据结构,比如使用HashMap完成ID到数组的映射,加快数组的提取
- 使用JAVA1.8自带的标准库,set取交集加快遍历速度。
作业中出现的性能问题和修复措施
- 第九次作业:
- 出现的问题:没有使用cache
- 修复方法:使用cache,防止反复查询复杂方法,降低时间复杂度
- 第十次作业:
- 出现的问题:强测中qtvs速度不足
- 修复方法:原来的方法是在tag中的person中遍历这个person中的acquaintance集合,来判断两个集合相同的元素,时间复杂度为O(mn),现在使用把两个集合使用HashSet的retainAll方法取得交集,实际复杂度为O(m + n)
- 第十一次作业:未出现性能问题
规格与实现分离
规格:通过JML,确保每个组件都严格按照预定义的规格行事
分离的好处:
- 可读性和维护性:当规格和实现分离时,其他开发者可以仅通过查看规格来理解组件的用途和行为,无需深入到实现细节中。这对于维护和修改代码非常有用,特别是在大型项目中。
- 可测试性:规格提供了一个明确的测试目标,开发者可以针对这些规格编写测试用例,而不是基于实现的假设。这有助于更系统地覆盖各种测试情况。
- 设计清晰:分离强迫开发者在编码之前思考需求和设计,从而可能发现潜在的设计问题或不一致。
- 重用性:良好定义的接口和清晰的规格使得组件可以在不同的项目中重用,而无需改变内部实现。
- 形式化验证:特别是在使用如JML这类工具时,规格可以用于形式化验证,即通过自动化工具检查代码是否符合规格。
利用规格信息来更好的设计实现Junit测试
我在实现junit时主要通过2种方法检查
- 检查不变性:确保那些不变性的语句不会遭到破坏
- 检查副作用,检查结果是否严格按照ensure后置条件,以及其他未被提及的条件是否被改变
同时在构造数据时,确保数据严格满足前置条件
这样就能确保Junit测试检验代码实现与规格的一致性
本单元学习体会
本单元学习起来有如下几点感受:
- 作业完成时间变短,因为jml已经给好了代码的实现框架,同时代码实现算法难度降低
- 作业学习曲折度增加,jml由于编写困难,产生课程组多次修正jml的情况
- 严谨化编程是必须的,通过学习jml的规范化测试我的代码bug明显较前两个单元减少
- 不要自作主张:在红包消息,我认为发出者扣的钱应当是message里的,没有按照课程组要求实现,造成money出错