其他分享
首页 > 其他分享> > OO第三单元——很缺钱的社交网络

OO第三单元——很缺钱的社交网络

作者:互联网

一、JML理论基础和工具链

基于规格的设计可以使开发人员能高效准确地完成开发,也能够使代码测试变得十分的轻松。

1.1 原子表达式
1.2 量化表达式
1.3 集合表达式

一般形式为new ST {T x|R(x)&&P(x)},其中的R(x)对应集合中x的范围,P(x)对应x取值的约束。

1.4 操作符
1.5 方法的规格

方法的规格有三种

方法的行为可以分为两种

如果一个方法中有多种行为,可以用also来连接。子类重写的方法的规格也可以用also来连接。

抛出异常的方法

1.6 类型规格
1.7 jml工具链

关于下文的openjml和JMLUnitNG这两个工具我均没有在代码作业中使用。我也没有用过其他的jml工具链。

二、SMT Solver验证

费尽九牛二虎之力终于配置好openjml,然后对Person.java魔改一番,测试结果如下。

D:\openjml>openjml Person.java
请按任意键继续. . .

D:\openjml>openjml -esc -prove Person.java
Person.java:7: 警告: The prover cannot establish an assertion (NullField) in method Person
      @ public instance model non_null String name;
                                              ^
Person.java:8: 警告: The prover cannot establish an assertion (NullField) in method Person
      @ public instance model non_null BigInteger character;
                                                  ^
Person.java:10: 警告: The prover cannot establish an assertion (NullField) in method Person
      @ public instance model non_null Person[] acquaintance;
                                                ^
Person.java:11: 警告: The prover cannot establish an assertion (NullField) in method Person
      @ public instance model non_null int[] value;
                                             ^
Person.java:103: 警告: The prover cannot establish an assertion (ExceptionalPostcondition: Person.java:99: 注: ) in method compareTo
        return this.getName().compareTo(p2.getName());
                           ^
Person.java:99: 警告: Associated declaration: Person.java:103: 注:
      @ public normal_behavior
               ^
Person.java:103: 警告: The prover cannot establish an assertion (Postcondition: Person.java:100: 注: ) in method compareTo
        return this.getName().compareTo(p2.getName());
        ^
Person.java:100: 警告: Associated declaration: Person.java:103: 注:
      @ ensures \result == name.compareTo(p2.getName());
        ^
Person.java:63: 警告: The prover cannot establish an assertion (ExceptionalPostcondition: Person.java:52: 注: ) in method equals
        return obj instanceof Person && this.getId() == ((Person) obj).getId();
                                                                            ^
Person.java:52: 警告: Associated declaration: Person.java:63: 注:
      @ public normal_behavior
               ^
Person.java:63: 警告: The prover cannot establish an assertion (ExceptionalPostcondition: D:\openjml\openjml.jar(specs/java/lang/Object.jml):76: 注: ) in method equals
        return obj instanceof Person && this.getId() == ((Person) obj).getId();
                                                                            ^
D:\openjml\openjml.jar(specs/java/lang/Object.jml):76: 警告: Associated declaration: Person.java:63: 注:
      @   public normal_behavior
                 ^
Person.java:111: 警告: The prover cannot establish an assertion (Postcondition: Person.java:110: 注: ) in method getAcquaintance
        return null;//pvalue;
        ^
Person.java:110: 警告: Associated declaration: Person.java:111: 注:
    public HashMap<Person, Integer> getAcquaintance() {
                                    ^
Person.java:95: 警告: The prover cannot establish an assertion (Postcondition: Person.java:92: 注: ) in method getAcquaintanceSum
        return pacquaintance.length;
        ^
Person.java:92: 警告: Associated declaration: Person.java:95: 注:
    //@ ensures \result == acquaintance.length;
        ^
Person.java:48: 警告: The prover cannot establish an assertion (Postcondition: Person.java:46: 注: ) in method getAge
        return page;
        ^
Person.java:46: 警告: Associated declaration: Person.java:48: 注:
    //@ ensures \result == age;
        ^
Person.java:43: 警告: The prover cannot establish an assertion (Postcondition: Person.java:41: 注: ) in method getCharacter
        return pcharacter;
        ^
Person.java:41: 警告: Associated declaration: Person.java:43: 注:
    //@ ensures \result.equals(character);
        ^
Person.java:33: 警告: The prover cannot establish an assertion (Postcondition: Person.java:31: 注: ) in method getId
        return this.pid;
        ^
Person.java:31: 警告: Associated declaration: Person.java:33: 注:
    //@ ensures \result == id;
        ^
Person.java:38: 警告: The prover cannot establish an assertion (Postcondition: Person.java:36: 注: ) in method getName
        return pname;
        ^
Person.java:36: 警告: Associated declaration: Person.java:38: 注:
    //@ ensures \result.equals(name);
        ^
Person.java:72: 警告: The prover cannot establish an assertion (Postcondition: Person.java:68: 注: ) in method isLinked
        return person.getId() == this.getId();// || pvalue.containsKey(person);
        ^
Person.java:68: 警告: Associated declaration: Person.java:72: 注:
      @ ensures \result == (\exists int i; 0 <= i && i < acquaintance.length;
        ^
Person.java:72: 警告: The prover cannot establish an assertion (ExceptionalPostcondition: Person.java:66: 注: ) in method isLinked
        return person.getId() == this.getId();// || pvalue.containsKey(person);
                                           ^
Person.java:66: 警告: Associated declaration: Person.java:72: 注:
    /*@ public normal_behavior
               ^
Person.java:89: 警告: The prover cannot establish an assertion (Postcondition: Person.java:79: 注: ) in method queryValue
        return 0;
        ^
Person.java:79: 警告: Associated declaration: Person.java:89: 注:
      @ ensures (\exists int i; 0 <= i && i < acquaintance.length;
        ^
30 个警告

弹出来一堆莫名的警告。似乎openjml支持能测的范围很小啊。

三、JMLUnitNG自动生成测试样例

这个工具也把我整的够呛。网上相关的教程也不多。搞了很久Group没有跑通,只跑通了阉割版Person。

[TestNG] Running:
  Command line suite

Passed: racEnabled()
Failed: constructor Person(-2147483648, null, null, -2147483648)
Failed: constructor Person(0, null, null, -2147483648)
Failed: constructor Person(2147483647, null, null, -2147483648)
Failed: constructor Person(-2147483648, , null, -2147483648)
Failed: constructor Person(0, , null, -2147483648)
Failed: constructor Person(2147483647, , null, -2147483648)
Failed: constructor Person(-2147483648, null, null, 0)
Failed: constructor Person(0, null, null, 0)
Failed: constructor Person(2147483647, null, null, 0)
Failed: constructor Person(-2147483648, , null, 0)
Failed: constructor Person(0, , null, 0)
Failed: constructor Person(2147483647, , null, 0)
Failed: constructor Person(-2147483648, null, null, 2147483647)
Failed: constructor Person(0, null, null, 2147483647)
Failed: constructor Person(2147483647, null, null, 2147483647)
Failed: constructor Person(-2147483648, , null, 2147483647)
Failed: constructor Person(0, , null, 2147483647)
Failed: constructor Person(2147483647, , null, 2147483647)
Skipped: <<null>>.addAcquaintance(null, -2147483648)
Skipped: <<null>>.addAcquaintance(null, 0)
Skipped: <<null>>.addAcquaintance(null, 2147483647)
Skipped: <<null>>.compareTo(null)
Skipped: <<null>>.equals(null)
Skipped: <<null>>.equals(java.lang.Object@4fccd51b)
Skipped: <<null>>.getAcquaintanceSum()
Skipped: <<null>>.getAcquaintance()
Skipped: <<null>>.getAge()
Skipped: <<null>>.getCharacter()
Skipped: <<null>>.getId()
Skipped: <<null>>.getName()
Skipped: <<null>>.hashCode()
Skipped: <<null>>.isLinked(null)
Skipped: <<null>>.queryValue(null)
test
Passed: static main(null)
test
Passed: static main({})

===============================================
Command line suite
Total tests run: 36, Failures: 18, Skips: 15
===============================================

从测试数据上看,似乎只会使用一些极端数据来进行测试。跟我想象中的测试用例差远了。而且并没有常规情况下的测试样例。

四、架构设计梳理

三次作业整体的架构没有变,都是直接照搬接口,而且每个方法实现起来也比较简单,所以也就只有那三个类了。最后一次作业因为tarjan实现起来相对复杂一些,而且需要额外的临时空间,所以多了一个Tarjan类来处理。后来反思一下,觉得我应该也为并查集和最短路这些图的算法抽出一个类,这样的话可以对具体算法解耦合,Network的功能也更加专一。

第九次作业
第十次作业
第十一次作业

五、Bug与测试

三次作业强测均是满分,互测安全通过。说明充分的测试才能有好的结果。

跟前两个单元的作业不同,本单元作业的输出与输入一一对应,所以测试使用的是对拍器

Junit如果使用得很好,确实能够保证很高的覆盖度。但是Junit宛如自己出题给自己做然后自己改,这样的话万一自己的想法本来就有偏差就测不出来了。而且Junit需要人去写测试样例,还有考虑指令的各种组合,很容易就漏掉情况。另外,由于本次作业结构简单,而且每次询问只会调用一个主要方法,得到的结果立刻转化为输出,所以对拍器就相当于单元测试了。大数据量覆盖面是有保证的,可以帮你找到绝大多数的bug。(当然tle是找不出来的)

在互测中,

第九次作业未能找到他人的bug。(断刀了)

第十次作业发现3人有bug。

第十一次作业仅发现1人的bug,就是没有判断除0。错过了两个人的bug,都是算法过于暴力导致。原因是这一次互测我没有好好地读代码,写极端数据,以为不会有tle的情况。看来每次的极端数据制造都不能少。

六、心得与体会

这个单元的作业相对之前的作业来说简单了很多,不需要自己设计架构,只需要自己填空就行了。也就只有一些算法比较难一点。听说不少的人翻了车,我认为还是测试没有做到位。俗话说:浅水浸死人。即使简单,也要进行充分的测试,才能有无惧翻车的底气。

这个单元学习了JML。个人认为JML虽然确实能够很清晰地描述行为,但是对于一些方法有篇幅过长的情况,表达效果甚至不如自然语言。而且,设计JML也是一个痛苦的过程。所以,形式化还有很长一段路要走。

关于JML工具链,感觉相当鸡肋啊。openjml配置了相当长的时间,终于跑通了,但是只能测一些最简单直接的方法,而且还经常报错。JMLUnitNG只能生成一些边界数据,而且很多情况下这些边界数据都不会出现。对于组合出现的bug则无法测试。总的来说,体验极差而且没有什么用。JML工具链还需要慢慢发展才行啊。

虽然说这个单元成绩不错,但是我对JML没有太多的好感,而且没有很好地引导我们用合理的架构。希望下一个单元有更好的游戏体验。

标签:OO,...,java,MyNetwork,int,Person,null,社交,缺钱
来源: https://www.cnblogs.com/kxqt/p/12944620.html