`

java单元测试篇:使用clover为junit单元测试做覆盖率分析

阅读更多

本人最近在研究java单元测试技术,有点心得,这里分享给测试同行朋友!那么,今天我们研究的主题是使用cenqua公司的clover框架来分析java程序的单元测试覆盖率!关于clover的更多信息呢,请大家去http://www.cenqua.com/clover 去查询。我们这里,将会通过一个实例来演示如何使用junitclover一起,来分析java代码的覆盖率。我们将会使用ant来编译一个junit单元测试实例项目,然后修改build.xml文件,加上clover的覆盖率分析任务target;而且我们还要通过三部分来学习clover超级无敌的地方:current报告、历史报告以及高级特征!

    那么最开始呢,我们要做的就是从http://www.cenqua.com/clover下载clover程序包clover.jar(它是clover的主要包)、clover.licenseclover的试用license,需要到官方网站下载一个月的试用注册文件,否则不能使用clover!)、velocity.jar(用来创建html报告的扩展包),将它们拷贝到antant你已经安装好了,并且设置了junit.jar以及ANT_HOME之类的初始化工作;我们这里不讲ant的基本使用,它都流行这么多年了,这里假设你都懂啦!)的lib目录下,这样下来,我们在antbuild.xml文件里才可以使用clover任务!

    当然,现在很多朋友不喜欢配置一些环境变量,想把这些jar文件放在任意的地方,例如直接放在项目文件里,那么可以通过在build.xml文件里指定这些扩展包的位置也是可以的;如果在build文件里加入扩展包的路径,需要在build文件里这样写:

1) 我们把下载来的clover.jarcenquatasks.jar拷贝到你的项目目录的lib路径下

2) build.xml下添加如下代码:

<taskdef resource="com/cenqua/ant/antlib.xml" classpath="lib/cenquatasks.jar"/>
<extendclasspath path="lib/clover.jar"/>
<taskdef resource="clovertasks" classpath="lib/clover.jar"/>

之后你就可以在ant任务里构建clover的任务啦!

 

    其实最简单的办法呢,就是把clover.jarclover.licensevelocity.jarcenquatasks.jarjunit.jar这些包都拷贝到antlib目录里,省得麻烦,不然将来你加入什么新功能,就会提示你找不到相应的包,你还得去网上搜,特不爽!

我们的学习过程是:

  • 先使用junit创建完java代码的测试代码,之后编译运行,完成junitjava代码的单元测试;
  • 之后,我们在ant里构建测试任务,自动完成企业集的单元测试工作
  • 然后,我们修改build文件,加入clover任务,来完整对单元测试过程的覆盖率分析工作
  • 最后开始重构代码,提高代码的单元测试覆盖率

一、 构建java源代码与junit单元测试代码

    先在你的电脑里的某个比较顺眼的盘下建立一个目录,例如叫sincky,这个就是我们的学习项目目录,再在sincky里创建一个src文件夹,用来放置所有的代码;之后在src里新建一个java类的源文件,名字叫做IMoney.java,代码内容如下:

public interface IMoney {

/**

* Adds a money to this money.

*/

public abstract IMoney add(IMoney m);

/**

* Adds a simple Money to this money. This is a helper method for

* implementing double dispatch

*/

public abstract IMoney addMoney(Money m);

/**

* Adds a MoneyBag to this money. This is a helper method for

* implementing double dispatch

*/

public abstract IMoney addMoneyBag(MoneyBag s);

/**

* Tests whether this money is zero

*/

public abstract boolean isZero();

/**

* Multiplies a money by the given factor.

*/

public abstract IMoney multiply(int factor);

/**

* Negates this money.

*/

public abstract IMoney negate();

/**

* Subtracts a money from this money.

*/

public abstract IMoney subtract(IMoney m);

/**

* Append this to a MoneyBag m.

*/

public abstract void appendTo(MoneyBag m);

}

 这里我们定义一个java接口,表示了“金钱”这个神奇东西的一些美妙的抽象方法!早年有首迟志强的歌叫《钞票》:是谁制造的钞票,你在世上逞霸道,有人为你愁眉苦脸啊有人为你哈哈笑;姑娘为你走错了路,小伙子为你受改造!东奔又西跑,点头又哈腰,钞票!人人为你离不了钱哪!你这杀人不见血的刀形象无比,不扯了,跑题啦!I am back!

之后我们实现这个接口,在src文件夹下定义一个叫做Money.java的类:

public class Money implements IMoney {


private int fAmount;

private String fCurrency;


/**

* Constructs a money from the given amount and currency.

*/

public Money(int amount, String currency) {

fAmount= amount;

fCurrency= currency;

}

/**

* Adds a money to this money. Forwards the request to the addMoney helper.

*/

public IMoney add(IMoney m) {

return m.addMoney(this);

}

public IMoney addMoney(Money m) {

if (m.currency().equals(currency()) )

return new Money(amount()+m.amount(), currency());

return MoneyBag.create(this, m);

}

public IMoney addMoneyBag(MoneyBag s) {

return s.addMoney(this);

}

public int amount() {

return fAmount;

}

public String currency() {

return fCurrency;

}

public boolean equals(Object anObject) {

if (isZero())

if (anObject instanceof IMoney)

return ((IMoney)anObject).isZero();

if (anObject instanceof Money) {

Money aMoney= (Money)anObject;

return aMoney.currency().equals(currency())

&& amount() == aMoney.amount();

}

return false;

}

public int hashCode() {

return fCurrency.hashCode()+fAmount;

}

public boolean isZero() {

return amount() == 0;

}

public IMoney multiply(int factor) {

return new Money(amount()*factor, currency());

}

public IMoney negate() {

return new Money(-amount(), currency());

}

public IMoney subtract(IMoney m) {

return add(m.negate());

}

public String toString() {

StringBuffer buffer = new StringBuffer();

buffer.append("["+amount()+" "+currency()+"]");

return buffer.toString();

}

public /*this makes no sense*/ void appendTo(MoneyBag m) {

m.appendMoney(this);

}

}

 这个接口实现了IMoney接口的方法,具体语法就不讲了,很简单!之后,我们又用另一个类实现IMoney接口,为什么呢?你可以认为我贪心,但你不可以这么说,因为喜欢编程的人绝对不是为了贪婪代码!我们在src下建立另一个类MoneyBag.java

 

import java.util.*;

class MoneyBag implements IMoney {

private Vector fMonies= new Vector(5);


static IMoney create(IMoney m1, IMoney m2) {

MoneyBag result= new MoneyBag();

m1.appendTo(result);

m2.appendTo(result);

return result.simplify();

}

public IMoney add(IMoney m) {

return m.addMoneyBag(this);

}

public IMoney addMoney(Money m) {

return MoneyBag.create(m, this);

}

public IMoney addMoneyBag(MoneyBag s) {

return MoneyBag.create(s, this);

}

void appendBag(MoneyBag aBag) {

for (Enumeration e= aBag.fMonies.elements(); e.hasMoreElements(); )

appendMoney((Money)e.nextElement());

}

void appendMoney(Money aMoney) {

if (aMoney.isZero()) return;

IMoney old= findMoney(aMoney.currency());

if (old == null) {

fMonies.addElement(aMoney);

return;

}

fMonies.removeElement(old);

IMoney sum= old.add(aMoney);

if (sum.isZero())

return;

fMonies.addElement(sum);

}

public boolean equals(Object anObject) {

if (isZero())

if (anObject instanceof IMoney)

return ((IMoney)anObject).isZero();


if (anObject instanceof MoneyBag) {

MoneyBag aMoneyBag= (MoneyBag)anObject;

if (aMoneyBag.fMonies.size() != fMonies.size())

return false;


for (Enumeration e= fMonies.elements(); e.hasMoreElements(); ) {

Money m= (Money) e.nextElement();

if (!aMoneyBag.contains(m))

return false;

}

return true;

}

return false;

}

private Money findMoney(String currency) {

for (Enumeration e= fMonies.elements(); e.hasMoreElements(); ) {

Money m= (Money) e.nextElement();

if (m.currency().equals(currency))

return m;

}

return null;

}

private boolean contains(Money m) {

Money found= findMoney(m.currency());

if (found == null) return false;

return found.amount() == m.amount();

}

public int hashCode() {

int hash= 0;

for (Enumeration e= fMonies.elements(); e.hasMoreElements(); ) {

Object m= e.nextElement();

hash^= m.hashCode();

}

return hash;

}

public boolean isZero() {

return fMonies.size() == 0;

}

public IMoney multiply(int factor) {

MoneyBag result= new MoneyBag();

if (factor != 0) {

for (Enumeration e= fMonies.elements(); e.hasMoreElements(); ) {

Money m= (Money) e.nextElement();

result.appendMoney((Money)m.multiply(factor));

}

}

return result;

}

public IMoney negate() {

MoneyBag result= new MoneyBag();

for (Enumeration e= fMonies.elements(); e.hasMoreElements(); ) {

Money m= (Money) e.nextElement();

result.appendMoney((Money)m.negate());

}

return result;

}

private IMoney simplify() {

if (fMonies.size() == 1)

return (IMoney)fMonies.elements().nextElement();

return this;

}

public IMoney subtract(IMoney m) {

return add(m.negate());

}

public String toString() {

StringBuffer buffer = new StringBuffer();

buffer.append("{");

for (Enumeration e= fMonies.elements(); e.hasMoreElements(); )

buffer.append(e.nextElement());

buffer.append("}");

return buffer.toString();

}

public void appendTo(MoneyBag m) {

m.appendBag(this);

}

}

 

之后,我们创建一个junit测试代码MoneyTest.java,来测试Money.javaMoneyBag.java类,这里我也把它放在src目录下;如果企业应用,你就要把目录分析的详细些,例如src子目录下放所有的java源代码,test子目录下放所有的junit测试代码:

import junit.framework.*;

public class MoneyTest extends TestCase {

private Money f12CHF;

private Money f14CHF;

private Money f7USD;

private Money f21USD;


private IMoney fMB1;

private IMoney fMB2;


public static void main(String args[]) {

junit.textui.TestRunner.run(MoneyTest.class);

}

protected void setUp() {

f12CHF= new Money(12, "CHF");

f14CHF= new Money(14, "CHF");

f7USD= new Money( 7, "USD");

f21USD= new Money(21, "USD");


fMB1= MoneyBag.create(f12CHF, f7USD);

fMB2= MoneyBag.create(f14CHF, f21USD);

}

public void testBagMultiply() {

// {[12 CHF][7 USD]} *2 == {[24 CHF][14 USD]}

IMoney expected= MoneyBag.create(new Money(24, "CHF"), new Money(14, "USD"));

assertEquals(expected, fMB1.multiply(2));

assertEquals(fMB1, fMB1.multiply(1));

assertTrue(fMB1.multiply(0).isZero());

}

public void testBagNegate() {

// {[12 CHF][7 USD]} negate == {[-12 CHF][-7 USD]}

IMoney expected= MoneyBag.create(new Money(-12, "CHF"), new Money(-7, "USD"));

assertEquals(expected, fMB1.negate());

}

public void testBagSimpleAdd() {

// {[12 CHF][7 USD]} + [14 CHF] == {[26 CHF][7 USD]}

IMoney expected= MoneyBag.create(new Money(26, "CHF"), new Money(7, "USD"));

assertEquals(expected, fMB1.add(f14CHF));

}

public void testBagSubtract() {

// {[12 CHF][7 USD]} - {[14 CHF][21 USD] == {[-2 CHF][-14 USD]}

IMoney expected= MoneyBag.create(new Money(-2, "CHF"), new Money(-14, "USD"));

assertEquals(expected, fMB1.subtract(fMB2));

}

public void testBagSumAdd() {

// {[12 CHF][7 USD]} + {[14 CHF][21 USD]} == {[26 CHF][28 USD]}

IMoney expected= MoneyBag.create(new Money(26, "CHF"), new Money(28, "USD"));

assertEquals(expected, fMB1.add(fMB2));

}

public void testIsZero() {

assertTrue(fMB1.subtract(fMB1).isZero());

assertTrue(MoneyBag.create(new Money (0, "CHF"), new Money (0, "USD")).isZero());

}

public void testMixedSimpleAdd() {

// [12 CHF] + [7 USD] == {[12 CHF][7 USD]}

IMoney expected= MoneyBag.create(f12CHF, f7USD);

assertEquals(expected, f12CHF.add(f7USD));

}

public void testBagNotEquals() {

IMoney bag= MoneyBag.create(f12CHF, f7USD);

assertFalse(bag.equals(new Money(12, "DEM").add(f7USD)));

}

public void testMoneyBagEquals() {

assertTrue(!fMB1.equals(null));


assertEquals(fMB1, fMB1);

IMoney equal= MoneyBag.create(new Money(12, "CHF"), new Money(7, "USD"));

assertTrue(fMB1.equals(equal));

assertTrue(!fMB1.equals(f12CHF));

assertTrue(!f12CHF.equals(fMB1));

assertTrue(!fMB1.equals(fMB2));

}

public void testMoneyBagHash() {

IMoney equal= MoneyBag.create(new Money(12, "CHF"), new Money(7, "USD"));

assertEquals(fMB1.hashCode(), equal.hashCode());

}

public void testMoneyEquals() {

assertTrue(!f12CHF.equals(null));

Money equalMoney= new Money(12, "CHF");

assertEquals(f12CHF, f12CHF);

assertEquals(f12CHF, equalMoney);

assertEquals(f12CHF.hashCode(), equalMoney.hashCode());

assertTrue(!f12CHF.equals(f14CHF));

}

public void testMoneyHash() {

assertTrue(!f12CHF.equals(null));

Money equal= new Money(12, "CHF");

assertEquals(f12CHF.hashCode(), equal.hashCode());

}

public void testSimplify() {

IMoney money= MoneyBag.create(new Money(26, "CHF"), new Money(28, "CHF"));

assertEquals(new Money(54, "CHF"), money);

}

public void testNormalize2() {

// {[12 CHF][7 USD]} - [12 CHF] == [7 USD]

Money expected= new Money(7, "USD");

assertEquals(expected, fMB1.subtract(f12CHF));

}

public void testNormalize3() {

// {[12 CHF][7 USD]} - {[12 CHF][3 USD]} == [4 USD]

IMoney ms1= MoneyBag.create(new Money(12, "CHF"), new Money(3, "USD"));

Money expected= new Money(4, "USD");

assertEquals(expected, fMB1.subtract(ms1));

}

public void testNormalize4() {

// [12 CHF] - {[12 CHF][3 USD]} == [-3 USD]

IMoney ms1= MoneyBag.create(new Money(12, "CHF"), new Money(3, "USD"));

Money expected= new Money(-3, "USD");

assertEquals(expected, f12CHF.subtract(ms1));

}

public void testPrint() {

assertEquals("[12 CHF]", f12CHF.toString());

}

public void testSimpleAdd() {

// [12 CHF] + [14 CHF] == [26 CHF]

Money expected= new Money(26, "CHF");

assertEquals(expected, f12CHF.add(f14CHF));

}

public void testSimpleBagAdd() {

// [14 CHF] + {[12 CHF][7 USD]} == {[26 CHF][7 USD]}

IMoney expected= MoneyBag.create(new Money(26, "CHF"), new Money(7, "USD"));

assertEquals(expected, f14CHF.add(fMB1));

}

public void testSimpleMultiply() {

// [14 CHF] *2 == [28 CHF]

Money expected= new Money(28, "CHF");

assertEquals(expected, f14CHF.multiply(2));

}

public void testSimpleNegate() {

// [14 CHF] negate == [-14 CHF]

Money expected= new Money(-14, "CHF");

assertEquals(expected, f14CHF.negate());

}

public void testSimpleSubtract() {

// [14 CHF] - [12 CHF] == [2 CHF]

Money expected= new Money(2, "CHF");

assertEquals(expected, f14CHF.subtract(f12CHF));

}

}

 

 

之后,我们在sincky目录下,创建一个build.xml文件,完成它的编译和测试任务,这里我为build.xml文件加了注释,供大家参考:

<!—build的项目名称叫money_demo,默认执行的任务是compile,根目录指当前目录,也就是sincky文件夹 -->

<project name="money_demo" default=" compile " basedir=".">

<description>

moneytest build file

</description>

<!—定义一个属性src,指向src目录-->

<property name="src" location="src"/>

<!—定义一个属性build,指向build目录,这个目录放置所有的编译后class文件,该目录目前没有创建-->

<property name="build" location="build"/>

<!—定义一个buildclasspath,里边放置后边任务里需要的依赖库和依赖路径-->

<path id="build.classpath">

<pathelement path="${ant.home}/lib/junit.jar"/>

<pathelement path="${build}"/>

</path>

<!--构建编译任务,先创建build文件夹,之后将srcdir里的java文件编译到build目录里-->

<target name="compile" >

<mkdir dir="${build}"/>

<javac srcdir="${src}" destdir="${build}"/>

</target>

<!--运行junit测试,运行的是MoneyTest,该运行依赖于build.classpath定义的路径 -->

<target name="test">

<java classname="MoneyTest" fork="yes">

<classpath refid="build.classpath"/>

</java>

</target>

<!--删除build文件夹的任务-->

<target name="clean">

<delete dir="${build}"/>

</target>

</project>

之后,我们开始运行build文件,开始编译任务:打开cmd命令行,进入sincky文件夹下,执行ant命令,会看见类似下列内容的效果:

C:cloversincky>ant

Buildfile: build.xml

compile:

[mkdir] Created dir: C:cloversinckybuild

[javac] Compiling 4 source files to C:cloversinckybuild

BUILD SUCCESSFUL

Total time: 4 seconds

现在你会在sincky目录下发现多了一个build目录,进入build目录,看见里边编译好的4class文件,恭喜你,这个任务胜利完成!

下面我们来运行单元测试任务:

C:cloversincky>ant test

Buildfile: build.xml

test:

[java] ......................

[java] Time: 0.016

[java] OK (22 tests)

BUILD SUCCESSFUL

Total time: 1 second

可以通过结果看出,22个测试用例全部通过;junit里边测试通过是.表示,测试失败是.F表示。关于ant的命令帮助,你可以输入ant –h查看。

二、编写ant文件自动运行java单元测试

三、修改build.xml文件添加clover任务

    现在我们开始修改build.xml文件,添加clover任务,以实现junit测试覆盖率的分析。首先,我们添加clover任务的配置任务;在build.xml文件里添加如下代码:

 

 

    这两行定义了能够在ant文件里使用clover任务的配置工作。然后再添加一个clover任务,用来启动clover构建任务:

 

 

 

    这里的initString定义了clover覆盖数据库的信息,它会在执行clover任务时自动创建,里边保存了源路径执行测试任务时候的全部信息,clover通过这个demo_coverage.db来创建覆盖率分析报告。如果这个demo_coverage.db存在,clover在每次运行时自动覆盖,如果不存在,clover自动创建它。

   我们这里使用clover,是为了搜集junit测试时候的覆盖率信息,所以呢,junit测试过程中,我们需要使用clover.jar包,所以我们还需要把clover.jar文件作为junit运行的依赖库,因此修改build.classpath代码成如下所示:

 

 

 

 

    这里顺便我们也把path的值说明一下,省得有人不懂哦!这里的ant.home是在计算机里创建的环境变量ANT_HOME,它的值应该是你的ant的安装路径,例如c:ant,所以前两行代码的意思,就是把c:antlibclover.jarc:antlibjunit.jar作为依赖库。当然,事先你一定要拷贝这两个jar文件到你的lib目录。

好了,我们现在开始重新使用clover任务来运行junit测试!

C:cloversincky>ant clean

Buildfile: build.xml

clean:

[delete] Deleting directory C:cloversinckybuild

BUILD SUCCESSFUL

Total time: 0 seconds

C:cloversincky>ant clover compile

Buildfile: build.xml

clover:

[clover-setup] Clover Version 1.3.8, built on May 18 2005

[clover-setup] loaded from: C:cloverlibclover.jar

[clover-setup] 30 day Evaluation License registered to sinckyzhang@163.com

[clover-setup] You have 10 day(s) before your Evaluation License expires.

[clover-setup] Clover is enabled with initstring 'C:cloversinckydemo_coverage.db'

compile:

[mkdir] Created dir: C:cloversinckybuild

[javac] Compiling 4 source files to C:cloversinckybuild

[clover] Clover Version 1.3.8, built on May 18 2005

[clover] loaded from: C:cloverlibclover.jar

[clover] 30 day Evaluation License registered to sinckyzhang@163.com

[clover] You have 10 day(s) before your Evaluation License expires.

[clover] No coverage database 'C:cloversinckydemo_coverage.db' fou

nd. Creating a fresh one.

[clover] Clover all over. Instrumented 4 files.

BUILD SUCCESSFUL

Total time: 2 seconds

我们会发现在sincky目录下多了一个demo_coverage.db文件;之后我们再执行测试任务:

C:cloversincky>ant test

Buildfile: build.xml

test:

[java] ......................

[java] Time: 0

[java] OK (22 tests)

BUILD SUCCESSFUL

Total time: 0 seconds

我们会看到又多了一个关于junit测试的.db文件!现在,我们已经使用clover统计完了覆盖率信息,之后创建clover报告,以直观方式来查看具体的覆盖率结果!这个任务需要在build.xml里创建任务。Clover的报告有多种方式:htmlpdfxml以及swingview的图形化报告,当然与eclipsejavaIDE集成,也会在IDE里创建报告;这里我们只演示html类型的报告!我们修改build.xml文件,添加如下任务:

 

 

 

 

 

 

 

这里的元素指产生的报告类型是当前的测试报告,还有历史报告,我们在后边讲解!这个报告是html格式,创建后的报告放在一个叫做clover_html的文件夹里,报告标题叫做Clover demo

我们现在给出完整的修改后的build.xml文件:

 

 

moneytest build file

 

 

 

 

 

 

 

 

 

 

 

 

 

 

fork="yes">

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

现在我们执行report这个任务:

C:cloversincky>ant report

Buildfile: build.xml

clover:

[clover-setup] Clover Version 1.3.8, built on May 18 2005

[clover-setup] loaded from: C:cloverlibclover.jar

[clover-setup] 30 day Evaluation License registered to sinckyzhang@163.com

[clover-setup] You have 10 day(s) before your Evaluation License expires.

[clover-setup] Clover is enabled with initstring 'C:cloversinckydemo_coverage.db'

report:

[clover-report] Clover Version 1.3.8, built on May 18 2005

[clover-report] loaded from: C:cloverlibclover.jar

[clover-report] 30 day Evaluation License registered to sinckyzhang@163.com

[clover-report] You have 10 day(s) before your Evaluation License expires.

[clover-report] Loaded results from 1 coverage recording.

[clover-report] Writing report to 'C:cloversinckyclover_html'

[clover-report] Done. Processed 1 packages.

BUILD SUCCESSFUL

Total time: 1 second

现在你可以打开sincky下的clover_html文件夹下的index.html文件,如下所示:

 

报告最左边是包名,以及包下边的类;右边是主窗口,显示当前这个Money类的测试覆盖率,我们可以通过行号来查看到151617行执行了156次,下边还会有两行一次也没有执行过,所以造成这个类整体的测试覆盖率不是100%。

四、重构测试代码实现百分百测试覆盖率

我们总是希望做单元测试的时候,让代码的测试覆盖率尽可能的达到100%,所以我们需要重构测试代码。从分析得知,第40行虽然执行了27次,但是从来没有测试if的判断条件为true的情况,所以我们要添加测试用例,测试isZero()返回为true的情况!因此,我们修改测试代码MoneyTest.java文件,在前边初始化地方加上一个Money实例,如下:

public class MoneyTest extends TestCase {
   private Money f12CHF;
   private Money f14CHF;
   private Money f7USD;
   private Money f21USD;
   private Money f0USD;

setup方法里添加:

protected void setUp() {

f12CHF= new Money(12, "CHF");

f14CHF= new Money(14, "CHF");

f7USD= new Money( 7, "USD");

f21USD= new Money(21, "USD");

f0USD = new Money(0, "USD"); //sincky

 

在最后加上一个测试用例:

public void testMoneyEqualsZero() {

assertTrue(!f0USD.equals(null));

IMoney equalMoney = new Money(0, "CHF");

assertTrue(f0USD.equals(equalMoney));

}

之后,我们重新编译,测试,创建报告,即执行下列命令:

>ant clean

>ant clover compile

>ant test

>ant report

这时候再打开新的html报告,看到如下效果覆盖率已经到达100%:

完毕,如果能进展到这一步,相信你已经对使用junitantcloverjava的单元测试,已经到了一个新的飞越!如果有兴趣,你还可以把junit报告和clover报告一并输出,以更好的为企业开发中使用这种工作模式!

文章源码均来自clover网站,本人稍做修改。

写在后面的话:目前国内单元测试尚在起步阶段,由于工作量大,耗时耗成本,很多公司都省去该环节;但是使用一些先进的技术,对源代码一些关键的类进行单元测试是可行的,也是必要的;希望本文对测试与java开发界朋友有所收获,Sincky在来日会写一些关于clover高级应用的文章,分享给大家!(20059月于上海 台风暴雨夜)

分享到:
评论

相关推荐

    java单元测试篇:使用clover为java代码的junit测试做覆盖率分析.pdf

    Java 单元测试篇:使用 Clover 为 Java 代码的 JUnit 测试做覆盖率分析 Java 单元测试是软件测试的重要组成部分,对于 Java 开发者来说,单元测试是必不可少的。今天,我们将学习使用 Clover 框架来分析 Java 代码...

    java代码覆盖率测试工具Clover3.0.365+Junit4.1

    Java代码覆盖率测试是软件开发...总的来说,Clover 3.0.365和JUnit 4.1的结合使用,可以帮助开发者更有效地进行单元测试,确保代码的质量,并提供了一种强大的手段来监控和改进代码覆盖率,从而提升整体的软件质量。

    Clover 是一个基本的Java代码覆盖测试分析工具,提供内部测试,即时IDE反馈,交互报告等。

    2. **内部测试**:Clover支持集成JUnit、TestNG等流行的测试框架,使得在编写和运行单元测试时可以无缝地获取代码覆盖率数据。它可以在测试执行的同时收集覆盖率信息,这样开发者在编写测试时就能立即看到测试的效果...

    代码覆盖率插件 eclipse clover3

    Clover 是 Atlassian 公司开发的一款强大的代码覆盖率工具,尤其适用于 Java 开发环境。在 Eclipse 中,Clover3 是一个非常受欢迎的插件版本,特别适用于那些需要与较旧版本 Eclipse 集成的项目。 **1. 安装 Clover...

    clover-ant-2.4.2 版本安装包

    Clover Ant扩展了Ant的功能,添加了对代码覆盖率度量的支持,帮助开发者了解单元测试覆盖了多少源代码,从而提高测试质量。 在Clover-ant-2.4.2.zip这个压缩包中,我们可以期待找到以下组件和资源: 1. **clover....

    seng6245-junit-examples:使用 JUnit 的简单示例,用于单元测试的讲座材料

    JUnit 是一个广泛使用的 Java 编程语言的单元测试框架,它允许开发者编写可自动化执行的测试用例,以确保代码的正确性和稳定性。在“seng6245-junit-examples”项目中,我们看到的是一系列针对 JUnit 使用的实例,这...

    代码覆盖率eclipse插件

    Eclipse作为一款广泛使用的Java集成开发环境,提供了一些插件来支持代码覆盖率的分析。本篇文章将深入探讨“代码覆盖率Eclipse插件”,并介绍如何利用这些工具提升测试效率。 首先,我们提到的“代码覆盖率Eclipse...

    1-Junit-Counter-计算器.rar

    5. **测试覆盖率**:使用 JUnit 运行测试后,可以结合其他工具(如 JaCoCo 或 Clover)评估测试覆盖率,以确保大部分代码都经过了测试。 6. **Mocking 和 Stubbing**:如果 Counter 类依赖于其他组件,如日志服务或...

    测试驱动开发 英文参考书

    - **Clover**:一个用于代码覆盖率分析的工具。 - **Eclipse**:集成开发环境(IDE),支持JUnit测试的集成。 - **IntelliJ IDEA**:另一个流行的IDE,也支持JUnit测试。 - **第七章:MockObjects** - **定义**...

    接口测试白皮书--淘宝(中国)软件有限公司

    Clover 是一个代码覆盖率工具,用于测量测试覆盖了多少代码。在接口测试中,Clover 可以帮助团队了解测试用例的完整性和有效性。 ##### 5.8 Mock Mock 是一种测试技术,用于模拟接口或类的行为,以帮助隔离被测对象...

    Java持续集成工具.doc

    3. **JUnit**: JUnit是Java开发者广泛使用的单元测试框架,它为编写和运行可重复的测试提供了便利。 4. **JUnitPerf或Eclipse TPTP**: 这两个工具用于执行单元测试的性能分析,帮助开发者找出代码中的性能瓶颈。 5...

    sohva-testing_2.9.3-0.4.zip

    Clover则是Atlassian公司开发的一款代码覆盖率工具,它能够测量单元测试对代码的覆盖程度,帮助开发者了解哪些代码部分还未被测试到,从而提升软件质量。 【标签】"开源项目" 暗示了这个插件可能是开放源代码的,...

    cobertura-1.9.4.1-bin.zip

    Cobertura 是一个用于 Java 代码覆盖率测试的工具,它能够帮助开发者测量和跟踪他们的源代码有多少被单元测试覆盖。 在描述 "cobertura-1.9.4.1-bin.zip" 中,没有额外的具体信息,但我们可以推断这可能是一个 ZIP ...

    inflearn-the-java-test

    2. Clover:Atlassian的代码覆盖率工具,提供更详细的分析。 七、TDD(测试驱动开发) TDD是一种开发模式,先编写测试用例,再编写满足这些测试的代码。这种做法有助于确保代码满足需求,同时提高代码质量。 总结...

    spring-test-demo-1.zip

    使用 JaCoCo 或 Clover 等工具可以生成代码覆盖率报告,帮助评估测试的全面性。 10. **持续集成与测试** 在持续集成环境中,如 Jenkins 或 Travis CI,可以自动化运行测试并监控测试结果,确保每次代码变更后都能...

    unit-testing-examples

    JUnit 是一个广泛使用的 Java 语言的单元测试框架,它为开发者提供了方便、高效的测试工具。在这个名为 "unit-testing-examples" 的项目中,我们可以找到一系列使用 JUnit 进行单元测试的实例,这对于学习和掌握单元...

Global site tag (gtag.js) - Google Analytics