MAJOR 使用教程

简介

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按照你的实际情况调整;

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,907评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,987评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,298评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,586评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,633评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,488评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,275评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,176评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,619评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,819评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,932评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,655评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,265评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,871评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,994评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,095评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,884评论 2 354

推荐阅读更多精彩内容