• BUAAOO Unit3 JML形式化方法


    JML(Java modeling language) 是一种利用形式化描述对数据、方法进行约束的语言,包含数据规格、方法规格、迭代器规格。通过JML的形式化描述,建立功能、开发者、程序之间的契约,可以对程序扩展时的稳定性、测试时的全面性产生较大的提高。

    作为一种形式化方法,其理论基础是形式语言,通过约束条件,可以将软件运行空间内的行为转化为可判定的数理逻辑问题,并通过形式化验证的方法加以检验。形式化验证的方法包括:定理证明、模型检测和等价性验证。

    JML工具链

    OpenJML

    • 包含Eclipse编辑插件、静态检查工具、运行时断言检查工具、反例浏览

    JMLUnitNG & Sireum / Kiasan for Java & JMLUnit

    • 自动化测试样例生成工具

    TACO & SMT Solver

    • 对Java代码与形式化表述的等价性进行验证

    JMLUnitNG 测试数据

    输入指令:

    java -jar testjmlunitng.jar -v srcimplMyGroup.java srccomoocoursespec3mainGroup.java srccomoocoursespec3mainPerson.java srcimplMyPerson.java
    

    MyGroup依赖的类也需要加入地址表中。

    然后将jmlunitng.jar加入编译依赖,运行MyPerson_JML_Test.java。结果如下:

    [TestNG] Running:
      Command line suite
    
    Failed: racEnabled()
    Passed: constructor MyGroup(-2147483648)
    Passed: constructor MyGroup(0)
    Passed: constructor MyGroup(2147483647)
    Failed: <<impl.MyGroup@44e81672>>.addPerson(null)
    Failed: <<impl.MyGroup@60215eee>>.addPerson(null)
    Failed: <<impl.MyGroup@65e579dc>>.addPerson(null)
    Failed: <<impl.MyGroup@61baa894>>.delPerson(null)
    Failed: <<impl.MyGroup@b065c63>>.delPerson(null)
    Failed: <<impl.MyGroup@768debd>>.delPerson(null)
    Passed: <<impl.MyGroup@490d6c15>>.equals(null)
    Passed: <<impl.MyGroup@7d4793a8>>.equals(null)
    Passed: <<impl.MyGroup@449b2d27>>.equals(null)
    Passed: <<impl.MyGroup@5479e3f>>.equals(java.lang.Object@27082746)
    Passed: <<impl.MyGroup@66133adc>>.equals(java.lang.Object@7bfcd12c)
    Passed: <<impl.MyGroup@42f30e0a>>.equals(java.lang.Object@24273305)
    Passed: <<impl.MyGroup@5b1d2887>>.getAgeMean()
    Passed: <<impl.MyGroup@46f5f779>>.getAgeMean()
    Passed: <<impl.MyGroup@18e8568>>.getAgeMean()
    Passed: <<impl.MyGroup@33e5ccce>>.getAgeVar()
    Passed: <<impl.MyGroup@5a42bbf4>>.getAgeVar()
    Passed: <<impl.MyGroup@270421f5>>.getAgeVar()
    Passed: <<impl.MyGroup@52d455b8>>.getConflictSum()
    Passed: <<impl.MyGroup@4f4a7090>>.getConflictSum()
    Passed: <<impl.MyGroup@18ef96>>.getConflictSum()
    Passed: <<impl.MyGroup@6956de9>>.getId()
    Passed: <<impl.MyGroup@769c9116>>.getId()
    Passed: <<impl.MyGroup@6aceb1a5>>.getId()
    Passed: <<impl.MyGroup@ba4d54>>.getRelationSum()
    Passed: <<impl.MyGroup@12bc6874>>.getRelationSum()
    Passed: <<impl.MyGroup@de0a01f>>.getRelationSum()
    Passed: <<impl.MyGroup@4c75cab9>>.getSize()
    Passed: <<impl.MyGroup@1ef7fe8e>>.getSize()
    Passed: <<impl.MyGroup@6f79caec>>.getSize()
    Passed: <<impl.MyGroup@67117f44>>.getValueSum()
    Passed: <<impl.MyGroup@5d3411d>>.getValueSum()
    Passed: <<impl.MyGroup@2471cca7>>.getValueSum()
    Failed: <<impl.MyGroup@5fe5c6f>>.hasPerson(null)
    Failed: <<impl.MyGroup@6979e8cb>>.hasPerson(null)
    Failed: <<impl.MyGroup@763d9750>>.hasPerson(null)
    Passed: <<impl.MyGroup@5c0369c4>>.notifyPeopleRelated(null, null)
    Passed: <<impl.MyGroup@2be94b0f>>.notifyPeopleRelated(null, null)
    Passed: <<impl.MyGroup@d70c109>>.notifyPeopleRelated(null, null)
    
    

    可以看到,JMLUnitNG对整型调用进行了测试,并对int边界数据进行了测试,但不支持对象的递归嵌套生成以完成测试。

    因此,为方便测试,可以考虑使用建立纯基础数据类型的替代方法。

    如: addPersonByDat(int id, String name, int character, int age)

    测试结果:

    Passed: <<impl.MyGroup@2b80d80f>>.addPersonByDat(2147483647, null, 2147483647, 0)
    Passed: <<impl.MyGroup@3ab39c39>>.addPersonByDat(2147483647, null, 2147483647, 0)
    Passed: <<impl.MyGroup@2eee9593>>.addPersonByDat(2147483647, null, 2147483647, 0)
    Passed: <<impl.MyGroup@7907ec20>>.addPersonByDat(-2147483648, , 2147483647, 0)
    Passed: <<impl.MyGroup@546a03af>>.addPersonByDat(-2147483648, , 2147483647, 0)
    Passed: <<impl.MyGroup@721e0f4f>>.addPersonByDat(-2147483648, , 2147483647, 0)
    Passed: <<impl.MyGroup@28864e92>>.addPersonByDat(0, , 2147483647, 0)
    Passed: <<impl.MyGroup@6ea6d14e>>.addPersonByDat(0, , 2147483647, 0)
    

    仍然仅测试了边际数据,效果好了一些,但数据组数只有205组,没有随机性测试,对于JML规格性质引发的特殊bug仍然无法覆盖。还应单独构建更多随机/针对性的测试用例。

    实际上实现一个支持对象递归嵌套测试系统是十分困难的,如果出现循环依赖,便无法完成测试。

    架构设计

    这次主要是一个社交网络图论模型,架构较为简单。由MyPerson类负责管理Person节点数据,MyGroup类负责管理分组统计信息,MyNetwork类负责管理图论相关算法及算法缓存。

    MyNetwork类:在关联连通性和连通块数量判定上采用了并查集算法,在点双连通判定上使用了剪枝后的Targan算法。

    MyPerson类:数据管理,不负责算法实现。

    MyGroup类:数据&统计信息管理。统计信息管理时采用了动态规划的方法。每次新增Person节点/新连边时,检索可能的关联边,更新关联统计数据。新增Person节点时,更新年龄统计数据。

    特别的,Person节点相关数据存储时均使用节点id + HashMap进行索引,使得存取复杂度最高不超过O(log n)。

    Bug分析

    这次作业中测、强测、互测中均没有出现bug...

    自测的过程中,第二次作业查看讨论区后发现有的地方按照实际功能理解,没有仔细看JML,导致出现了偏差。最后核对JML后修复了Bug。

    第三次作业Targan算法一开始没有理解透彻,在大数据下出现了问题。仔细和网上资料、模板核对后修复了bug,主要是找到双联通分量后压栈的过程。

    总结

    To be honest... 确实觉得JML形式化方法还有很多不足,比如造成开发效率下降、理解效率下降。

    在实际应用中,应将JML形式化方法、更抽象更易理解的数学语言描述、实际功能描述相结合,分别在工具链测试&验证、开发者形式化理解、产品与程序对接方面互相补充。

    一百年前希尔伯特曾经有形式化证明一切数学定理的理想,虽然破灭了,但形式化验证程序从某种意义上是另一种继承,形式化一切程序似乎也可以构建一个数学上自洽的世界。

  • 相关阅读:
    Codeforces Round #270 solution
    Codeforces Round #269 (Div. 2) solution
    Codeforces Round #268 (Div. 1) solution(upd div 1 C,div 2 A, B
    Codeforces Round #267 (Div. 2) solution
    Unity 绘制多边形
    DOTween 模仿NGUI Tween
    图像混合模式 正片叠底、滤色、叠加
    一只羊的四个月可以生一只小羊,小羊四个月后又可以生一只小羊 问50个月后有多少只羊(羊不会死)
    Unity CCTween UGUI 动画插件
    Unity UGUI 使用 CCTween 实现 打字效果
  • 原文地址:https://www.cnblogs.com/jim00/p/12944681.html
Copyright © 2020-2023  润新知