BUAA——第三单元博客作业

黄拓远-22371180 学生 2024-05-16 11:04:59

测试过程

1、黑箱测试

黑箱测试是软件测试中的一种方法,它通过在不考虑程序内部结构的情况下,根据程序的需求和规格进行测试。这意味着测试人员不需要了解程序的内部代码或设计,而是关注程序的输入和输出,以验证程序是否按照预期工作。

在黑箱测试中,测试人员通常依据需求规格、用户文档或其他可用的文档,设计测试用例并执行测试。测试用例涵盖了各种情况,包括正常情况下的输入、边界情况、异常情况等,以确保程序在各种情况下都能正确地运行。

黑箱测试的优点之一是它与具体的编程语言或技术无关,因此测试人员不需要具备特定的编程技能。然而,它也有一些局限性,例如无法发现程序内部的逻辑错误或代码缺陷。

总的来说,黑箱测试在软件开发过程中扮演着重要的角色,帮助确保软件符合用户需求并具有良好的功能性。

2、白箱测试

白箱测试是软件测试中的另一种方法,与黑箱测试相对。白箱测试也被称为结构测试或透明盒测试,它关注的是测试软件的内部结构、逻辑和代码。

在白箱测试中,测试人员会深入了解软件的内部工作原理,包括代码逻辑、数据结构、变量和函数等。然后,测试人员设计测试用例,以验证代码是否按照设计规范和预期进行了实现。白箱测试通常涵盖的内容包括路径覆盖、语句覆盖、分支覆盖等,以确保代码的每个部分都被有效地测试到。

与黑箱测试相比,白箱测试的优点之一是可以更深入地检查软件的内部逻辑,发现潜在的编程错误和缺陷。然而,它也需要测试人员具备更深的技术和编程知识,并且可能受到代码变更的影响。

总的来说,白箱测试和黑箱测试通常结合使用,以确保软件在功能和结构上都达到高质量的标准。

3、其余多种测试

1、单元测试

单元测试是软件开发中的一种测试方法,用于验证程序中最小可测试单元的功能是否按照预期工作。这些最小可测试单元通常是函数、方法或类等代码片段。单元测试的目的是在开发过程中尽早地发现和修复代码中的错误,以确保每个单元都能独立地、正确地运行。

2、功能测试

功能测试是软件测试的一种类型,它旨在验证软件的各项功能是否按照需求和规格说明正常工作。功能测试关注的是软件的外部行为,而不涉及其内部实现细节。

3、集成测试

集成测试是软件测试中的一种测试方法,其主要目的是验证不同软件模块之间的交互和集成是否正常工作。在软件开发过程中,通常会将各个模块独立开发和测试,而集成测试则是在将这些模块组装在一起后进行的测试。

4、压力测试

压力测试是软件测试的一种类型,旨在评估系统在正常或极限负载下的性能表现。它通常用于确定系统在各种条件下的稳定性和可靠性,以及在达到或超过预期负载时的表现情况。

5、回归测试

回归测试是软件测试中的一种测试方法,其主要目的是确保对软件进行更改或修复后,已有的功能仍然能够正常运行,不会因为新的更改而引入新的错误或破坏已有的功能。回归测试旨在验证软件的稳定性和一致性,以确保对软件的修改不会对现有功能产生负面影响。

4、数据构造策略

数据构造采用了全随机的办法,主要是使用java自带的Random类,比如一个图中的人数设置为100-200个人可以采用如下语句。

int peoplenumber = random.nextInt(100);
        for (int i = 0;i < peoplenumber + 100;i++) { // 随机添加100-200个人
            Person person = new MyPerson(i,String.valueOf(i), random.nextInt(200));
            if (!net.containsPerson(i)) {
                try {
                    net.addPerson(person);
                } catch (EqualPersonIdException e) {
                    throw new RuntimeException(e);
                }
            }
        }

然后两个人之间有没有关系也采用随机的方法。

for (int i = 0;i < peoplenumber - 1;i++) {
            for (int j = i + 1;j < peoplenumber;j++) {
                if (random.nextBo0lean()) {
                    try {
                        net.addRelation(i,j,random.nextInt(200));
                    } catch (PersonIdNotFoundException e) {
                        throw new RuntimeException(e);
                    } catch (EqualRelationException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
}

这样就自然而然的生成了一个完全随机的图,这个图基本上能满足本次测试方法的要求。

架构设计

1、图模型构建

本次作业我主要是采用了hashMap的容器,以ID作为key以类作为value,因为这样可以很好的根据ID取自己想要的值。使时间复杂度为O(1),而不是遍历一遍取想要的值的O(n)。架构与JML的要求基本一样。在此就不继续介绍了。

2、维护策略

本次作业我采用了许多动态维护策略,比如tripleSum,会在每次加边或者修改边的时候遍历维护一遍

for (Integer key : persons.keySet()) {
                    if (key != id1 && key != id2 && persons.get(key).isLinked(persons.get(id1)) &&
                            persons.get(key).isLinked(persons.get(id2))) {
                        tripleNum--; 
                    } 
}

这个时间复杂度为O(n),是可以接受的,如果采用三循环遍历的方法时间复杂度为n的立方,这样就会造成反复调用这个方法的时候出现ctle

还有blockSum,iscircle的获取,我也是采用动态维护的方法,我主要使用了并查集的算法,这样在调用方法的时候就可以直接返回维护好了的数据,而不是递归或者循环,会浪费大量时间。

还有coupleSum的维护,我的维护将时间复杂度将为了O(常数),我认为还是写的比较妙的一个方法。

private void UpDateCoupleNum(int id1,int id2,int beforeOrAfter) {
        int bst1 = ((MyPerson)persons.get(id1)).BestId();
        int bst2 = ((MyPerson)persons.get(id2)).BestId();
        if (!((MyPerson)persons.get(id1)).Empty() &&
                ((MyPerson)persons.get(bst1)).BestId() == id1) {
            coupleNum += beforeOrAfter;
        }
        if (!((MyPerson)persons.get(id2)).Empty() &&
                ((MyPerson)persons.get(bst2)).BestId() == id2) {
            coupleNum += beforeOrAfter;
        }
        if (bst1 == id2 && bst2 == id1) {
            coupleNum -= beforeOrAfter;
        }
    }
·····
UpDateCoupleNum(id1,id2,-1);
((MyPerson)persons.get(id1)).ModifyLink(persons.get(id2),value);
((MyPerson)persons.get(id2)).ModifyLink(persons.get(id1),value);
UpDateCoupleNum(id1,id2,1);
·····

这个UpdateCoupleSum方法只需要在修改前和后调用一下就可以动态维护CoupleSum了,且时间复杂度为O(常数),成本很低。

另外还有BestAcquaintance,valueSUm,ageVar等采用了动态维护等方式,这里就不一一赘述了。

性能问题与BUG修复

一开始我并没有使用动态维护的方法,而是根据JML老老实实的翻译它给的代码,导致整体跑的特别慢,出现了许许多多的性能问题。之后我把能维护的量全部改为动态维护,这样一来就没有再出现超时的情况了。

还有一个小bug就是Integer类不可以使用==比较,而是要用.equals,因为==表示的是这两个变量指向同一个类,而不同类但是数值相等可能也不满足==,所以在一些情况下会出现判断错误的情况,我在一些极端情况下就出现了这种情况。

Junit测试

本单元要求我们实现某些方法的Junit测试,我的做法是先随机生成一些数据以用以测试,然后根据JML用最简单的方法得出要测试方法的结果,然后将这个结果与调用的方法进行比较,另外,还要保证ensures的所有内容我的test中都有涉及,这样,我的test才是完美的。

心得体会

学习JML规格是对软件开发中的一种新思路和方法的探索。JML规格作为一种形式化的规约语言,可以帮助我们更清晰地定义软件系统的行为和约束,从而提高代码的可靠性和可维护性。

通过学习JML规格,我深刻体会到了规范在软件开发中的重要性。通过在代码中嵌入JML规约,我们可以明确地定义函数和类的前置条件、后置条件和类不变式,使得代码的行为更加可预测和可控。这有助于开发人员更好地理解代码的预期行为,并在开发过程中进行验证和测试,从而减少错误和提高代码质量。

另外,学习JML规格也让我意识到了规约驱动设计的思想。通过在设计阶段就明确定义系统的规约和约束,我们可以更加系统地进行软件设计,从而减少后续开发中的迭代和修改。这有助于加快开发周期、降低维护成本,并提高系统的可维护性和可扩展性。

总的来说,学习JML规格是我在软件开发领域的一次新的探索和尝试。我相信通过不断学习和实践,我可以更加熟练地运用JML规格来提高自己的软件开发能力,并为构建高质量的软件系统贡献自己的一份力量。

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

301

社区成员

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

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