2024 BUAA OO UNIT3

林舒雅-22371132 学生 2024-05-16 11:31:38

HW12-BLOG

目录

  • HW12-BLOG
  • 测试过程
  • 黑箱测试和白箱测试
  • 对单元测试、功能测试、集成测试、压力测试、回归测试的理解
  • 数据构造策略
  • 基础测试
  • 针对性测试
  • 架构设计
  • 第一次作业
  • 第二次作业
  • 第三次作业
  • 性能问题
  • 规格与实现分离
  • Junit测试
  • 利用规格信息设计
  • 检验代码实现与规格的一致性的效果
  • 学习体会

测试过程

黑箱测试和白箱测试

  • 黑箱测试也称功能测试、数据驱动测试或基于规格说明的测试。测试者只知道程序的输入、输出和系统的功能,这是从使用者的角度针对软件的接口、功能及外部结构进行的测试,不考虑程序内部实现逻辑。
  • 白箱测试也称结构测试、逻辑驱动测试或基于程序本身的测试,测试程序内部结构或运行。在白箱测试时,从程序设计语言的角度来设计测试样例。测试者输入数据并验证数据在程序中的流动路径,并确定适当的输出,类似测试电路中的节点。

img

对单元测试、功能测试、集成测试、压力测试、回归测试的理解

  • 单元测试是针对软件的最小功能模块进行测试的方法。在这种测试中,开发人员会编写针对每个函数或方法的测试用例,以验证其在各种输入条件下的正确性。单元测试的目的是尽早发现和解决代码中的错误和缺陷,以确保软件的各个功能模块能够独立地正常工作。

  • 功能测试是对整个软件系统的功能进行测试的方法。在功能测试中,测试人员会根据需求规格说明书编写测试用例,并通过输入不同的数据或操作软件的不同功能来验证软件是否满足设计要求。功能测试的目的是确保软件能够按照用户需求的要求正常运行,并能够正确地处理各种情况。

  • 集成测试是在单元测试之后,将各个功能模块组装在一起进行测试的方法。在集成测试中,测试人员会验证各个模块之间的接口和交互是否正常,并且整个系统能够正常协作。集成测试的目的是确保各个模块之间的集成能够正常工作,不会产生冲突和错误。

  • 压力测试是对软件系统在高负载和大并发情况下进行测试的方法。在压力测试中,测试人员会模拟大量用户同时访问系统,并且增加系统负载,以评估系统的性能和稳定性。压力测试的目的是找出系统的瓶颈和性能问题,并且确定系统在高负载情况下的性能指标。

  • 回归测试是在软件系统进行修改或升级后,重新运行之前的测试用例以验证修改是否引入新的错误或导致原有功能出现问题的方法。回归测试的目的是确保在对软件进行修改或升级后,原有的功能和性能没有受到影响。回归测试一般会在每次修改或升级后进

数据构造策略

基础测试

以稠密图为基础,尽量覆盖jml描述里的每一个分支,举个简单的例子,对于ap指令,可以设置异常概率为0.2,使得random到概率区间时,add网络中已经存在的人。同时适当提高查询指令的比例。

def add_relation(self, designated1, designated2):
        seed = random.random()
        id1 = 0
        id2 = 0
        value = random.randint(-3, 3)
        if(designated1!=None and designated2!=None):
            # 指定
            id1 = designated1
            id2 = designated2
        elif(self.cur_person_index == 0):
            id1 = self.persons[random.randint(0, command_limit + 30)]
            id2 = self.persons[random.randint(0, command_limit + 30)]
        elif(seed < ar_id1_exc_prob):
            # person1 异常
            id1 = self.persons[random.randint(self.cur_person_index, command_limit + 30)]
            if(random.random() < 0.5) :
                id2 = self.persons[random.randint(0, self.cur_person_index - 1)]
            else :
                id2 = self.persons[random.randint(self.cur_person_index, command_limit + 30)]
        elif(seed < ar_id2_exc_prob):
            # person2 异常
            if(random.random() < 0.5) :
                id1 = self.persons[random.randint(0, self.cur_person_index - 1)]
            else :
                id1 = self.persons[random.randint(self.cur_person_index, command_limit + 30)]
            id2 = self.persons[random.randint(self.cur_person_index, command_limit + 30)]
        else:   
            id1 = self.persons[random.randint(0, self.cur_person_index - 1)]
            if(random.random() < 0.1):
                id2 = id1
            else :
                if(random.random() < 0.5 and len(self.relation_dict) != 0):
                    keys = random.sample(list(self.relation_dict.keys()), 1)
                    id1_1 = keys[0][0]
                    id1_2 = keys[0][1]
                    if(len(self.double_edges_dict.get(id1_1).keys() & self.double_edges_dict.get(id1_2).keys())==0 and self.add_relation_dirty==0):
                        # 增加三元组概率
                        self.add_relation_dirty = 1
                        self.inputs.append(self.add_relation(id1_1, self.persons[random.randrange(0, self.cur_person_index)]))
                        self.inputs.append(self.add_relation(id1_2, self.persons[random.randrange(0, self.cur_person_index)]))
                        self.add_relation_dirty = 0
                id2 = self.persons[random.randint(0, self.cur_person_index - 1)]
                if(id1 != id2):
                    edge = tuple((min(id1, id2), max(id1, id2)))
                    if(edge not in self.relation_dict):
                        self.add_edge(edge, value, id1, id2)
                else :
                    id2 = id1 + 1
        return f'add_relation {id1} {id2} {value}'

针对性测试

针对每次作业中实现复杂度可能较高的方法,手捏测试点。比如对valueSum的处理,也许有的同学处理得不好,可以在大量投放queryValueSum指令。

架构设计

架构设计如下:

img

总体架构已经由JML给出,因此接下来描述架构实现细节和图的策略。

第一次作业

对连通块:使用并查集维护,通过按秩合并和路径压缩提升效率。删边时,采用用时重建+dfs染色的方法,局部重建并查集。用时重建意味着用空间换取时间,需要注意增删边之间的关系,在重建的时候采用visited数组记录下已经完成的点,避免无脑反复重建。

对三元组:在关系变化的时候,进行动态维护。

第二次作业

对最短路径,使用BFS方法。图是无权图,所以不必使用Dijkstra算法。

对ValueSum,可以采用动态维护的方法。在MyPerson中增加成员变量includedTags,代表着该成员所在的Tag(不包括成员掌控的Tag),在关系变动的时候,在通知includedTags中的所有Tag进行ValueSum的维护。

第三次作业

对BestAccquaince,采用动态维护的方法,在MyNetwork中维护HashMap: bestIds,在关系变动时,记录下双方此时的BestId。

性能问题

使用ArrayList的Contains方法,却没有意识到它和HashMap的ContainsKey方法的不同。只需更换数据结构就能解决这个问题,但这也提醒了我在使用方法之前要先查看源码,确认时间复杂度。除此之外,还有偷懒导致的ValueSum维护问题,上文已提及修复方法。

规格与实现分离

如果按照JML规格实现,可能会出现多重循环等复杂度极高的算法。事实上,为了规格的清晰性和准确性,其表述往往采用朴素的方法,实现可行性极低。

因此实现时要做的是,理解规格,找到高效的同义替换方法。

Junit测试

利用规格信息设计

逐行比对规格进行测试,不能遗漏任何一个分支变化或者不变

具体表现在:

  • 检查assignable的对象
  • 检查ensures的内容
  • 检查exception
  • 检查result的值

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

由于Junit直接面向规格编写测试,在测试数据有一定的强度的背景下,个人认为Junit检验代码实现与规格的一致性的效果是不错的。

学习体会

面向JML编程时,满目是规格表述细节,这时需要特别注意形成自己的设计总览(CO精髓。必须足够细心并且考虑全面,不能忘记自己增加的部分。

在Junit测试时,用户代码完全不可见使得我的多疑心加重,导致在检查成员变量不变性时束手束脚。第一次接触黑箱测试的体验不甚顺利,确实引发了我对规格与实现之间的思考。

...全文
93 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复
内容概要:本文围绕“新型电力系统下多分布式电源接入配电网承载力评估方法”的研究,系统性地介绍了基于Matlab的仿真建模与代码实现方案,旨在评估高比例分布式电源(如光伏、风电等)接入背景下配电网的接纳能力。研究融合了智能优化算法(如蜣螂优化、灰狼优化、遗传算法)、多目标优化、鲁棒优化及双层优化模型,结合潮流计算、稳定性分析与故障仿真,构建了完整的承载力评估体系。文档不仅提供核心算法实现,还拓展至微电网调度、储能配置、电氢耦合系统、电动汽车协同等前沿方向,强调“复现+创新”相结合的科研路径,助力研究者快速掌握高水平论文复现技巧并激发原创思路。; 适合人群:具备电力系统、自动化或相关专业背景,熟悉Matlab/Simulink仿真环境,正在从事科研或工程应用的研究生及初级科研人员(工作1-3年);; 使用场景及目标:①复现高水平期刊中关于配电网承载力的优化模型;②开展高比例可再生能源接入下的配电网规划与运行研究;③学习并应用智能优化算法解决复杂电力系统问题;④获取完整科研资源包以加速课题进展与论文撰写; 阅读建议:建议读者关注公众号“荔枝科研社”获取网盘资源,下载全套代码与模型文件,按照文档结构循序渐进学习,重点理解算法设计逻辑与仿真建模细节,结合所提供的复现案例深化对优化模型与工程应用场景的理解,提升科研效率与创新能力。

301

社区成员

发帖
与我相关
我的任务
社区描述
2023年北航面向对象设计与构造
学习 高校
社区管理员
  • YannaZhang
  • CajZella
  • C_ecelia
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧