MAJOR 使用教程

2021-04-27  本文已影响0人  慎独墨写

简介

Major 是一个轻量级变异测试工具,其工作原理主要分为两步:

  1. 在编译过程中生成+嵌入变异体
  2. 执行变异体进行变异分析

安装

官网:http://mutation-testing.org/
官方教程:http://mutation-testing.org/doc/major.pdf
参考论文:https://homes.cs.washington.edu/~rjust/publ/major_issta_2014.pdf

  1. 下载
    前往 http://mutation-testing.org/downloads/
    下载新版本的MAJOR, 1.3.0以上的版本已经适配Java8

  2. 环境配置
    安装OpenJDK-8 (Ubuntun 16.04 安装JDK-7会比较繁琐,建议JDK-8;如果想不开想要安装的话,请参考https://segmentfault.com/a/1190000014979994

# 编辑环境变量文件:
sudo gedit /etc/profile
# 在文件末尾输入以下内容
export MAJOR_HOME=MAJOR_PATH
export PATH=${MAJOR_HOME}/bin:$PATH
# 输入以下命令使设置生效:
source /etc/profile
# 验证 Javac 版本:
javac -version
# 输出内容如下:
javac 1.7.0-Major-v1.3.5
# 验证 Ant 版本:
ant -version
# 输出内容应类似于此:
Apache Ant(TM) version 1.8.4-Major-v1.3.5 compiled on July 18 2019

3.编写MML脚本【可选步骤】
为你的类编写MML脚本,在脚本中指定变化文法,变异算子生成方法,和希望被测试的类别;
以程序中自带的作为例子;
当然,你也可以使用自带的“all.mml.bin”甚至利用命令$javac -XMutator:ALL MyFile.java生成更多的变异体,这个步骤是一个optional的一步,这一步在现实中可以用于对MAJOR的变异算子进行复写或者选择,因项目和个人选择而异。

targetOp{
    // Define the replacements for ROR
    BIN(>)->{>=,!=,FALSE};
    BIN(<)->{<=,!=,FALSE};
    BIN(>=)->{>,==,TRUE};
    BIN(<=)->{<,==,TRUE};
    BIN(==)->{<=,>=,FALSE,LHS,RHS};
    BIN(!=)->{<,>,TRUE,LHS,RHS};
    // Define the replacements for COR
    BIN(&&)->{==,LHS,RHS,FALSE};
    BIN(||)->{!=,LHS,RHS,TRUE};
    // Define the type of statement that STD should delete
    DEL(RETURN);

    // Enable the STD, COR, and ROR mutation operators
    STD;
    COR;
    ROR;
}
// Call the defined operator group for the target method
targetOp<"BubbleSort::BubbleSort(int[])">;

之后利用如下命令

$ mmlc BubbleSort.mml BubbleSort.mml.bin

生成编译好的文件。

4.生成变异体
javac -XMutator=BubbleSort.mml.bin -d bin BubbleSort.java
可以从mutants.log文件中读取变异体生成的结果

1:ROR:<(int,int):!=(int,int):BubbleSort@BubbleSort(int[]):6:i < arr.length - 1 |==> i != arr.length - 1
2:ROR:<(int,int):<=(int,int):BubbleSort@BubbleSort(int[]):6:i < arr.length - 1 |==> i <= arr.length - 1
3:ROR:<(int,int):FALSE(int,int):BubbleSort@BubbleSort(int[]):6:i < arr.length - 1 |==> false

如果你想要查看代码,你可以用
$javac -J-Dmajor.export.mutants=true -XMutator:ALL MyFile.java
导出所有的变异体;

5.执行变异体
执行变异体要使用ant,方便起见,我们按照他的目录格式创建文档

BubbleSort -- ant -- src  -- BubbleSort.java
                  -- test -- testBubbleSort.java
                  -- build.xml
                  -- run.sh
                       

src:放入你的待测代码
test:放入你的junit代码
build.xml ant的build配置文件,建议你不要随便修改它。
run.sh 用来执行ant compile以及后续过程的一个脚本文件
你可以利用$MAJOR_HOME\example\ant\build.xml 以及同目录下的run.sh的文件;
【请注意,如果你出现了错误,80%的错误都出在这一步;几乎都是因为你的.java和test.java文件没有放对位置,如果你的.java和test.java文件是在同一个package里面,请自行建一个package文件夹套在外面,并且保证你的package之类的名字都写对】
你只需修改第一行<project name="Triangle" default="compile" basedir=".">
将name改成你的项目名,对本示例而言是BubbleSort, 剩下的不要改。

在build.xml中,援引example的例子,下列三个target最重要,不要随便改动;

<!-- Target to compile the project -->
    <target name="compile" depends="init" description="Compile">
        <javac includeantruntime="true" 
               srcdir="src"
              destdir="bin"
                debug="yes"
                 fork="yes"
           executable="${major}">
            <compilerarg value="${mutator}"/>
        </javac>
    </target>

<!-- Target to compile the test suite -->
    <target name="compile.tests" depends="compile" description="Compile all tests">
        <javac includeantruntime="true" 
               srcdir="test"
              destdir="bin"
                debug="yes">
        </javac>
    </target>

<!-- The adapted mutation test target -->
    <target name="mutation.test" description="Run mutation analysis for all unit test cases">
        <echo message="Running mutation analysis ..."/>
        <junit  printsummary="false" 
                showoutput="false" 
                mutationAnalysis="true"
                resultFile="results.csv" 
                killDetailsFile="killed.csv">
                
            <classpath path="bin"/>
            <batchtest fork="false">
                <fileset dir="test">
                    <include name="**/*Test*.java"/>
                </fileset>
            </batchtest>
        </junit>
    </target>

执行run.sh
会得到类似于如下的report

mutation.test:
     [echo] Running mutation analysis ...
    [junit] MAJOR: Mutation analysis enabled
    [junit] MAJOR: ------------------------------------------------------------
    [junit] MAJOR: Run 1 ordered test to verify independence
    [junit] MAJOR: ------------------------------------------------------------
    [junit] MAJOR: Preprocessing time: 0.07 seconds
    [junit] MAJOR: ------------------------------------------------------------
    [junit] MAJOR: Mutants generated: 35
    [junit] MAJOR: Mutants covered:   35 (100.00%)
    [junit] MAJOR: ------------------------------------------------------------
    [junit] MAJOR: Export test map to testMap.csv
    [junit] MAJOR: ------------------------------------------------------------
    [junit] MAJOR: Run mutation analysis with 1 individual test
    [junit] MAJOR: ------------------------------------------------------------
    [junit] MAJOR: 1/1 - BubbleSortTest (14ms / 35):
    [junit] MAJOR: 250 (28 / 35 / 35) -> AVG-RTPM: 7ms
    [junit] MAJOR: Mutants killed / live: 28 (18-10-0) / 7
    [junit] MAJOR: ------------------------------------------------------------
    [junit] MAJOR: Summary:
    [junit] MAJOR: 
    [junit] MAJOR: Analysis time:  0.3 seconds
    [junit] MAJOR: Mutation score: 80.00% (80.00%)
    [junit] MAJOR: Mutants killed / live: 28 (18-10-0) / 7
    [junit] MAJOR: Mutant executions: 35
    [junit] MAJOR: ------------------------------------------------------------
    [junit] MAJOR: Export summary of results to summary.csv
    [junit] MAJOR: Export run-time results to results.csv
    [junit] MAJOR: Export mutant kill details to killed.csv

当然,如果你现在执行成功了,你就被允许对build.xml进行魔改了;


一些Major-Ant的新功能

你可以尝试使用更多的功能;

【如果你出现了如下错误】
1.我的mutants covered = 0
一个变异体都没有杀死,
要么是你写出了惊世骇俗的测试用例【显然很难】
要么是你的mutation.log在ant compile tests过程中遭到了覆盖;
要么是你的两个.java文件的package出了错,导致编译失败;
要么是你魔改了你的build.xml,或者你的.java命名不带Test,或者.java位置放的不对,导致找文件都没找到;
请你将run.sh的每一步分别来debug;
2.如果你的Java文件不在major的路径下, 不要忘记做一下修改:
run.sh中的:

MAJOR_HOME="../../" 改为 MAJOR_HOME="MAJOR_PATH"

还要修改 build.xml 文件中的 major 属性:

<property name="major" value="../../bin/javac"/> 改为
<property name="major" value="MAJOR_PATH/bin/javac"/>

MAJOR_PATH按照你的实际情况调整;

上一篇下一篇

猜你喜欢

热点阅读