一、JML 基础及工具链
JML语法
行注释://@annotation
块注释:/*@ annotation @*/
JML表达式
(1)原子表达式
\result表达式:表示一个非 void 类型的方法执行所获得的结果,即方法执行后的返回值。
\old(expr)表达式:用来表示一个表达式expr在相应方法执行前的取值。
\not_assigned(x,y,…)表达式:用来表示括号中的变量是否在方法执行过程中被赋值。
\not_modified(x,y,…)表达式:限制括号中的变量在方法执行期间的取值未发生变化。
\nonnullelements(container)表达式:表示container对象中存储的对象不会有null。
(2)量化表达式
\forall表达式:全称量词修饰的表达式,表示对于给定范围内的元素,每个元素都满足相应的约束。
\exists表达式:与forall表达式使用结构类似,为存在量词修饰的表达式,表示对于给定范围内的元素,存在某个元素满足相应的约束。
\sum表达式:返回给定范围内的表达式的和。
\product表达式:返回给定范围内的表达式的连乘结果。
\max表达式:返回给定范围内的表达式的最大值。
\min表达式:返回给定范围内的表达式的最小值。
\num_of表达式:返回指定变量中满足相应条件的取值个数。
应用工具链
OpenJML
::openjml.bat @echo off set java=java -jar "%~dp0openjml.jar" -noPurityCheck set prove=-prover cvc4 -exec "%~dp0Solvers-windows\cvc4-1.6.exe" set runtime=-cp %~dp0jmlruntime.jar; set allparam= set rac= :param set str=%1 if "%str%"=="" ( goto end ) if "%str%"=="-rac" ( set rac=rac ) if "%str%"=="-prove" ( set str=%prove% ) set allparam=%allparam% %str% shift /0 goto param :end if "%allparam%"=="" ( goto eof ) rem remove left right blank :intercept_left if "%allparam:~0,1%"==" " set "allparam=%allparam:~1%"&goto intercept_left :intercept_right if "%allparam:~-1%"==" " set "allparam=%allparam:~0,-1%"&goto intercept_right :eof %java% %allparam% set filename= if "%rac%"=="rac" ( :input set /p filename=Input file name: if "%filename%"=="" ( goto input ) java %runtime% %filename% ) pause
这是从讨论区分享的一篇博客看到的。可以将上述代码拷贝到解压后的文件夹中,然后将该文件夹加入环境变量,即可通过命令行调用openjml
命令了。当然也可以用
java -jar .\openjml.jar -exec .\z3-4.7.1.exe -esc Person.java调用。
这是对一个功能特别简单的Person类检查后的结果,没有问题就不会有显示
JMLUnitNG
JMLUnit
它的配置在实验课的PPT就有。使用也比较简单。我觉得以下几种断言一般就够用了。
• assertEquals(int expected, int actual) 是否相等(输入参数的类型还可以为long、float、double、Object)
• assertTrue(boolean condition) 是否为真
• assertFalse(boolean condition) 是否为假
• assertNotNull(Object object) 是否非null
• assertNull(Object object) 是否为null
下面是我的测试程序片段和运行结果
总结:
1)OpenJML:用于检查JML文档规格语法,不过使用起来很麻烦而且效果不好
2)JMLUnitNG:基于JML的单元测试工具,能够自动生成测试用例,主要是边界条件的测试
3)Junit:单元测试,可用于编写和可重复运行的一些测试用例,测试用例是自己编写的