BUAA OO Unit3 总结

钟昊翔-21231025 学生 2024-05-16 11:34:21

OO Unit3 总结

分析测试过程

黑箱测试

黑箱测试也称为功能测试或基于需求的测试,测试人员不需要了解软件的内部结构和代码实现,只关注输入和输出。测试的目的是验证软件的功能是否符合需求规格说明书的要求。不需要深入了解代码实现,测试人员可以是非开发人员。但是覆盖范围有限,无法检测到代码中的所有可能缺陷。并且可能会忽略内部实现导致的潜在问题。

白箱测试

白箱测试也称为结构测试或基于代码的测试,测试人员需要了解软件的内部结构和实现细节,通过检查代码逻辑、路径覆盖等来设计测试用例。需要深入了解代码,测试人员通常是开发人员。但是测试覆盖面容易局限于代码逻辑,忽略系统的整体功能。

单元测试

对软件系统的最小可测试单元进行测试,通常是单个函数或方法。目的是验证每个单元的功能是否正确,确保单元按照预期工作。

集成测试

将多个单元模块集成后进行测试,验证它们之间的接口和交互是否正确。 目的是发现模块之间的接口和交互问题,确保集成后的系统能够正常运行。

压力测试

在超出正常工作负荷的条件下测试系统,评估其在极端条件下的性能和稳定性。 目的是确定系统的最大承受能力和性能瓶颈,确保在高负载下系统仍能稳定运行。

回归测试

在软件修改后重新测试系统,确保新代码没有引入新的错误或影响现有功能。 目的是验证新版本的系统是否仍然符合预期,未破坏原有功能。

数据构造的过程

在Homework 9中,需要对NetWork.queryTripleSum()方法进行单元测试,我构造数据的方法是构造了500条随机操作数据(包括添加一个未出现过的Person,在两个已经添加过的Person间添加Relation,删除一个存在的Relation,以及在三个人之间两两添加关系(这个是为了保证能有三角形出现))。每一步操作之后都对JML规格规定的结果和要求确保无错误的进行检查。

@Test
    public void myTest() {
        Assert.assertEquals(0, myNetwork.queryTripleSum());
        addPerson();
        while (numberOfCommands < 500){
            int op = random.nextInt(4);
            if (op == 0) {
                addPerson();
            } else if (op == 1) {
                addRelation();
            } else if (op == 2){
                deleteRelation();
            } else {
                addTriple();
            }
            test();
        }
        test();
    }

在Homework 10中,需要对NetWork.queryCoupleSum()方法进行单元测试,和上次作业一样,构造方法中只是去掉了构造三角形的关系,还是每进行一次操作进行一次结果检查。

@Test
    public void myTest() {
        Assert.assertEquals(0, myNetwork.queryCoupleSum());
        addPerson();
        while (numberOfCommands < 500){
            int op = random.nextInt(3);
            if (op == 0) {
                addPerson();
            } else if (op == 1) {
                addRelation();
            } else {
                deleteRelation();
            }
            test();
        }
        test();
    }

在前两次作业中,每一步操作都在Test类中存有备份完整的NetWork.persons[]NewWork.relations[]备份,方便后面进行修改检查。

在Homework 11中,需要对NewWork.deleteColdEmoji()方法进行单元测试,这次在构造数据的时候也是随机操作,只是操作变为了添加消息、发送消息和deleteColdEmoji()这三个。这次构造了2000~20000条随机数据。

@Test
    public void myTest() {
        Assert.assertEquals(0, myNetwork.deleteColdEmoji(Integer.MAX_VALUE));
        for (int i = 0; i < 1000; i++) {
            int times = random.nextInt(20);
            for (int t = 0; t < times; t++) {
                addAndSendMessage();
            }
            test();
        }
    }

架构设计

类分析

NetWork可以看做是图,里面包含了所有的点和边以及其他附加属性

Person可以看做是点

Tag可以当做标签或者分组,是一个点的属性,其中包含图中点的子集(不含自己)

addRelation方法为在两个点之间添加一条无向边(权值为正)

因此我的构建是:

NetWork里面存储点,即Person[],由于需要根据Person.id快速查询,所以使用了HashMap<Person.id, Person>

Person里面存储对应边的邻接表,即acquaintances[],也是用了HashMap维护

Person里面存储对应的Tag,由于需要根据Tag.id获取,因此使用了HashMap<Tag.id, Tag>

queryBlocksSum()方法需要查询联通块个数,使用了并查集维护。

queryBestAcquaintance()方法需要找到Person对应邻接表的最长边,因此在操作的时候实时维护了这个值,并且使用了懒标记,只有在修改后查询才会更新。

性能问题

在第一次作业的时候,在NetWork.getPerson()方法中直接按照JML的写法,将整个Person[]数组遍历了一遍,这个过程是O(n)的,又由于NetWork.queryShortestPath()本身是O(n)的,并且每一步都需要getPerson(),因此整体就是O(n^2)的,导致超时。后来改为了HashMap就不会了。

如何利用规格信息来设计Junit测试

我的做法是直接照搬JML的写法,计算标准答案的时候不采用任何优化,这样能保证结果和JML的预期相同。并且对JML中每一条ensure都进行检查。也要检查是否抛出了signal对应的异常。最后检查没有出现在assignalbe中的属性是否未被修改。

学习体会

这个单元大大的考验了我对规格的理解能力和建模能力,并且JML的约束也让我养成了不随便修改引用的好习惯。不过阅读JML真的是个不简单的事情。

...全文
47 回复 打赏 收藏 转发到动态 举报
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

301

社区成员

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

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