Android单元测试实践 (成功运行)

上一篇 / 下一篇  2009-12-01 21:22:44 / 个人分类:Android

我的栏目
  • 栏目:Android

 

e8ya^g:S e0

个人实际测试过,成功。(环境:SDK1.6, Windows Eclipse 及仿真板上均运行成功。原作者的 “两个测试方法,Tests run却显示了3”的问题不存在了。 由于此处Blog字数似乎有限,一些内容省去。)

1s"MZh+o [0

51Testing软件测试网9q0{g:H+hEG
51Testing软件测试网/a9vT(e[3ED5S+U

;JCt9zc0任何程序的开发都离不开单元测试来保证其健壮和稳定。Android的程序自然也不例外。从Android SDK 0.9开始,就有了比较成熟的测试框架,但是直到目前最新的1.1版本,也没有详细的文档介绍这个内容,只是简单的给了一个Api Demos里的几个单元测试代码。因此,我在这里对此内容做一下梳理和总结:

@"_+q:Oes0

JUnit还能用么?

51Testing软件测试网;@%J*ZDr.E

Java下做单元测试必然用到JUnit。这里说的JUnit是指从Apache基金会下载的junit.jar里提供的一系列单元测试功能。这些功能显然是运行在JDK之上的。在Android下已经没有了JDK,自然也无法运行JUnit。但是这并不妨碍我们利用JUnit编写单元测试。只不过在运行单元测试时,一定要用JDK来运行,利用java命令来启动JUnit的某个Runner。如果是用Eclipse的话,可以在Run Configuration里新建一个JUnit。但是一定要记得在Classpath选项卡里将Bootstrap Entries中的Android Library改成JRE,并且添加junit.jar。

Rk I@:e6As051Testing软件测试网)Jx7H NXh%P)uty

J?`R+vQ?;Bya051Testing软件测试网+cxS9PB*C} C

很明显的,这种测试就是正规的Java单元测试,和Android没有任何关系。你无法测试任何关于Android系统中的API,你写的Activity,人机界面等等。所以,如果你想测试仅仅是一些封装数据的对象,或者是纯粹的数值计算,还是可以用这种方法的。

x5T7b!_0Yn0

Android里面的junit.framework包是怎么回事?

8? a+Go+S&m V0很多人看到这个包的时候,第一反应是Android是不是已经完整集成了JUnit。很遗憾这不是事实。如果你按照JUnit的运行方法,却不像上面那样改用JDK,就一定会得到一个异常:

IP[a9H0J#? {0

4Gm4o\L0#
e&^_W!E0q a0# An unexpected error has been detected by Java Runtime Environment:
Y C*A&X3q S4[Ym0#
g`+S)L/y"i C C I0# Internal Error (classFileParser.cpp:2924), pid=4900, tid=447651Testing软件测试网},Fc(pD+y3d,ne"~
#Error: ShouldNotReachHere()
kxQ'b;VS%Sg \c-[0#51Testing软件测试网~6IA!{S'Pl
# Java VM: Java HotSpot(TM) Client VM (10.0-b19 mixed mode windows-x86)51Testing软件测试网1uA't R5j7E8C5E-Z
# An error report file with more information is saved as:51Testing软件测试网T-|Y${Ey-r
# E:\Mydoc\EclipseWorkspace\TestAndroid\hs_err_pid4900.log
h9A{@;_I'k5Q0#51Testing软件测试网|3~p(n x%Wuu7p
# If you would like to submit a bug report, please visit:51Testing软件测试网*LA)ho_'_l(xV J
# http://java.sun.com/webapps/bugreport/crash.jsp
kUro0P6m[0#

*pVJ mne0N)u:V0

CLj,o-~0L0实际上,TestCase这个类用于在Android担当所有独特的TestCase的基类的作用,它是一个Abstract Class。Android单元测试类继承关系图如下所示:

"cf6xV&^he051Testing软件测试网#}nwP7?mQ~ {'Ix

51Testing软件测试网d0n"~.~)z$s@%E,s

51Testing软件测试网EO _#\UY3Y

之所以有那么多XXXTestCase主要是为了简化工作。例如当你想对一个访问数据库的功能进行测试时,首先需要自己启动并初始化数据库。在这里是类似的,如果你想测试一个Activity,首先要启动它。而ActivityTestCase就会自动帮你做完这些事情。而ActivityUnitTestCase会更注重测试的独立性,它会让测试与Android底层的联系降到最低。其余的类可以查看相关的Javadoc来按需挑选。要编写测试,就是找到合适的XXXTestCase作为基类来继承,并且编写自己的测试方法。51Testing软件测试网b _6Q`(qOGV1H9vp

51Testing软件测试网2p*K \5q!Y6Cs

很明显的,最简单的编写测试的方法就是继承AndroidTestCase写一个自己的TestCase。然后为自己的一组TestCase写一个Activity界面,由界面控制TestCase的启动,运行和结果报告。但是,你很快会发现,为何要给测试写一个界面呢?这太诡异了。这时就需要一种技术,它可以利用命令行(Shell)来启动一组测试,并且通过命令行的形式给出结果。这就是所谓的Instrumentation。

I:i u0s}#[*M0

什么是Instrumentation?

P*b*?]z(k aXI0一般在开发Android程序的时候,需要写一个manifest文件,其结构是:

U;S8~]d\7d a&}051Testing软件测试网9u#G b};Ds W"T$|

<application android:icon="@drawable/icon" android:label="@string/app_name">51Testing软件测试网&V:k v-[1k h|

51Testing软件测试网P3EX#M|

<activity android:name=".TestApp" android:label="@string/app_name">

[e:x;{M8g"^+mib051Testing软件测试网[\.ciw9DT'p

……51Testing软件测试网 soO7P(I b5}H

51Testing软件测试网;v0X3B(Qm A0AJg

</activity>

~ HJvB7X-|w051Testing软件测试网[.qF9U$D!A9C v9N

</application>

v7\TA Pm&?-w051Testing软件测试网*?uA}1fg-V

这样,在启动程序的时候就会先启动一个Application,然后在此Application运行过程中根据情况加载相应的Activity,而Activity是需要一个界面的。但是Instrumentation并不是这样的。你可以将Instrumentation理解为一种没有图形界面的,具有启动能力的,用于监控其他类(用Target Package声明)的工具类。任何想成为Instrumentation的类必须继承android.app.Instrumentation。下面是这个类的解释:

9A2{)wX'[w;f051Testing软件测试网-J^dG wIX-t

Base class for implementing application instrumentation code. When running with instrumentation turned on, this class will be instantiated for you before any of the application code, allowing you to monitor all of the interaction the system has with the application. An Instrumentation implementation is described to the system through an AndroidManifest.xml's <instrumentation> tag.51Testing软件测试网d#c tr9Kr

51Testing软件测试网Eow?;q#P3d I4U KP

对于单元测试,我们需要认真了解的就是android.test.InstrumentationTestRunner类。这是Android单元测试的主入口。它相当于JUnit当中TestRunner的作用。51Testing软件测试网&|/r zXIJ |*L

^"Kx%Dvm0那么如何加载它呢,首先要在manifest文件中加入一行关于Instrumentation的声明。比如Android Api Demos中的测试里的manifest是这么写的(我滤掉了所有的注释):51Testing软件测试网2eg!h9C#y k0s

$q E(g },lNd0<manifest xmlns:android="http://schemas.android.com/apk/res/android"

4Wt/b S#V,C)Y]$X?7B051Testing软件测试网p v9w_q*]2x

package="com.example.android.apis.tests">51Testing软件测试网Gln&C9P o$Y

51Testing软件测试网e/A"K+dK~1o L$K8k

<application>

J;@ Q-?'IZ;O^[0

a%` V/D3R[:O0<uses-library android:name="android.test.runner" />51Testing软件测试网.z!\Zm0NpwkU

51Testing软件测试网/xj:qFI+VTZ\#C

</application>51Testing软件测试网sSl1C1RXetHZ

51Testing软件测试网oc!C*C)r&P

<instrumentation android:name="android.test.InstrumentationTestRunner"51Testing软件测试网 J P3Xa[T4iT

&m8Zr(i.kI1w+P2D t'O d0android:targetPackage="com.example.android.apis"

jJ3K.D?J0D tpx}051Testing软件测试网 p)IBE&?

android:label="Tests for Api Demos."/>51Testing软件测试网G8D$IXmg

51Testing软件测试网et4S"yM b

</manifest>

.LIwWHjT0

:~;XV ~'fT1I|0如果用Eclipse的ADT插件(0.8版本以上),也可以用图形界面来添加,如下图:

~~j1dQ051Testing软件测试网*I0\3{,](t

51Testing软件测试网 d/o BylB

MJQF iy0编辑好manifest,就可以打包(build,可以用Eclipse ADT来做,也可以用aapt命令手工完成),然后安装到虚拟机上(用adb install命令)。之后就可以利用命令行的方式来加载你的单元测试了。在Android Shell中加载一个Instrumentation的方法是利用以下命令:

8H"e5v"e0F U%w0O-U uD051Testing软件测试网g P7Qy[^1M0K

adb shell am instrument –w XXXXXX

+|F V {j*oD0

Y6L[wc0其中-w是指定Instrumentation类的参数标志。一个简单的例子是:

e&V7_+Y,rZ!B0

iRXu)p s0adb shell am instrument -w com.android.foo/android.test.InstrumentationTestRunner

D sg4k^PuY4P Y0

PTSvA zl0当然,也可以利用adb shell先进入android命令行模式,再直接写am instrument –w XXXXXXX。下面将具体介绍如何将根据需要加载一组单元测试。51Testing软件测试网E5}Z1K`h

如何在Android中利用Instrumentation来进行测试?

51Testing软件测试网&[ MO*DE:{K

在介绍具体的命令之前,我们先理解一下单元测试的层次。一组单元测试可以被组织成若干个TestSuite。每个TestSuite包含若干TestCase(某个继承android.jar的junit.framework.TestCase的类)。每个TestCase又包含若干个Test(具体的test方法)。

L5azxa5Xz G0

s]5}r V] s$f0如果假设com.android.foo是你的测试代码的包的根。当执行以下命令时,会执行所有的TestCase的所有Test。测试的对象就是在Target Package中指定的包中的代码:51Testing软件测试网3n;vm |6a+K(hl?nW

9{ B#I\m-kuI#`0adb shell am instrument -w com.android.foo/android.test.InstrumentationTestRunner51Testing软件测试网 I5_!\-^H]!{ nQ

J'AD` y*s/ZW0如果你想运行一个TestSuite,首先继承android.jar的junit.framework.TestSuite类,实现一个TestSuite(比如叫com.android.foo.MyTestSuite),然后执行以下命令执行此TestSuite

S ANEa EK1pH*f6^051Testing软件测试网&p-sL&XW v[:o!\?

adb shell am instrument -e class com.android.foo.MyTestSuite -w com.android.foo/android.test.InstrumentationTestRunner51Testing软件测试网7JWI2]5`l

51Testing软件测试网6y[ Rq(rNNu#b

其中的-e表示额外的参数,语法为-e [arg1] [value1] [arg2] [value2] …这里用到了class参数。

JR-\#vwk0

v;lE5x re;nc0如果仅仅想运行一个TestCase(比如叫com.android.foo.MyTestCase),则用以下命令:51Testing软件测试网4G ZwP3B&H4] R"{

51Testing软件测试网c S3Ax%e.|

adb shell am instrument -e class com.android.foo.MyTestCase -w com.android.foo/android.test.InstrumentationTestRunner

%{ U)n)[`'s N4x051Testing软件测试网8i`c]o.R

如果仅仅想运行一个Test(比如就是上面MyTestCase的testFoo方法),很类似的,就这样写:51Testing软件测试网;xE5eAO%o:A{

r6i!RZQ!{0adb shell am instrument -e class com.android.foo.MyTestCase#testFoo -w com.android.foo/android.test.InstrumentationTestRunner51Testing软件测试网&~.H-S4Ftw

kk4T O*i I2a0然后,所有的测试结果会输出到控制台,并会做一系列统计,如标记为E的是Error,标记为F的是Failure,Success的测试则会标记为一个点。这和JUnit的语义一致。如果希望断点调试你的测试,只需要直接在代码上加上断点,然后将运行命令参数的-e后边附加上debug true后运行即可。更加详细的内容可以看InstrumentationTestRunner的Javadoc。我希望Android能尽快有正式的文档来介绍这个内容。51Testing软件测试网DN,U?4c2p

如何在Android的单元测试中做标记?

51Testing软件测试网R~vu&g8ES

在android.test.annotation包里定义了几个annotation,包括@LargeTest,@MediumTest,@SmallTest,@Smoke,和@Suppress。你可以根据自己的需要用这些annotation来对自己的测试分类。在执行单元测试命令时,可以在-e参数后设置“size large”/ “size medium”/ “size small”来执行具有相应标记的测试。特别的@Supperss可以取消被标记的Test的执行。51Testing软件测试网?!z/KM,hd3O

完整的操作过程

51Testing软件测试网 d:~j0VTm4Z

总结以上所有的内容,编写并运行完整的测试需要以下的步骤:51Testing软件测试网6s)^,I2](\o"T_

6BM0`kk.Y,Q)Z]v0

P+t'X{1zJ4E051Testing软件测试网y eVi4_

以上步骤中,在Android自带的例子中,我发现它有两个manifest.xml。也就是说在步骤3中源代码和测试代码分别生成了两个不同的包。然后步骤4利用adb install命令安装到了虚拟机上。由于我没有找到Eclipse ADT有办法可以为一个只有Instrumentation,没有Activity的Application打包并安装,于是采用了略微不同的办法完成了这个工作。下面将一一详细介绍整个过程。51Testing软件测试网"`W!S c2iXP"\

1. 编写程序

51Testing软件测试网_u3P'r+_"e1Sdo

我新建了一个项目TestApp,参数为:51Testing软件测试网)S$I H1I(k7?DY,E.O

8CN,t)PW0Package Name: com.android.testapp

}[$CN}w0

|6[/t~"cI'u"vX8xy0Activity Name: MainActivity

QPl3ukn~G051Testing软件测试网/Z0O6u1PN

Application Name: TestApp

8gDmyM&m0

d+[W4Yi'RD0以下是MainActivity的源代码:51Testing软件测试网6@4`,q#t5b/N@V

51Testing软件测试网4~ni,V\H

;Mw9?!H"l/i0

r(Z` ae/[Rd(s/Wq0packagecom.android.testapp;51Testing软件测试网tc U%Y`;J"a

x'c'T!]l.I(? x0importandroid.app.Activity;

bX O0O/tL051Testing软件测试网-JF ]+w_ oM I

importandroid.os.Bundle;

7I}c'g;iJ0

Rj4t-k;|i0publicclassMainActivityextendsActivity {51Testing软件测试网o,w'H B``

51Testing软件测试网 m7c%f!V/? hk

/** Called when the activity is first created. */51Testing软件测试网3XPO Lc(k

51Testing软件测试网\8g\+_|F9_/Hl

@Override51Testing软件测试网(\D e6NVr t5cX;_&Pz

51Testing软件测试网9TW#IZ:x!|Z n

publicvoidonCreate(Bundle savedInstanceState) {51Testing软件测试网.T9?-| C+AwxM+i

51Testing软件测试网 E4O5}|\g` ~

super.onCreate(savedInstanceState);51Testing软件测试网"E$D{8?O6@x

51Testing软件测试网S&wg5Wy$v+e

setContentView(R.layout.main);51Testing软件测试网ks B4e[+Tq \W

51Testing软件测试网$J` v_8je

}

\ez&bS:}0

f l}JHV0k0publicintsum(inta,intb) {

lO h|"M2Cb%gh0

FS:\-_f:E0i#c0returna + b;

9Jg3U/Y&D2bx051Testing软件测试网s z&T9{4J

}

%G.AWT m5b'R6r3}051Testing软件测试网T#HcxN8~Yl

publicintsubstract(inta,intb) {51Testing软件测试网Q#z|&\(?,FI

51Testing软件测试网)p?ev6b ~|

returnb - a;

#?1hi&~2q$Opg"X/e0

+]tUYL!TJ0}

1w8z/V KhEMM,R3rA051Testing软件测试网$D2y3\y?*f+I

}51Testing软件测试网 U0P!QF2@&RA

51Testing软件测试网4B|WmaftkG

其中,我故意将减法的a – b写成了b – a。

/_!C)`X1`._0

2. 编写测试程序

51Testing软件测试网mY6_/X;_Zc

然后,我新建了一个Source Folder,名为test,并在里面新建了包com.android.testapp.test。并定义了一个TestCase,名为TestMainActivity,源代码如下:51Testing软件测试网Y7V6aO%Yq wtQ j;Z

51Testing软件测试网t"mw9G5d.~%p

packagecom.android.testapp.test;

IeVIi:k0

JV5K(T kH;ZhQ0importcom.android.testapp.MainActivity;

] N#sy'wZ#p051Testing软件测试网{pKS&UE B{

importandroid.test.ActivityInstrumentationTestCase2;

O,l^6{ P051Testing软件测试网?1r`X4p#e%~I9mB

importandroid.test.suitebuilder.annotation.MediumTest;

3N*T&@.bS051Testing软件测试网'ak E}O _$|o5s+H

publicclassTestMainActivityextendsActivityInstrumentationTestCase2<MainActivity> {51Testing软件测试网5D)S@#o]O"r-c'k

\bru Z7bc8C9^0Z0publicTestMainActivity() {

?_V7T)O4r/N051Testing软件测试网)TCM+m;T/~Y|XG

super("com.android.testapp", MainActivity.class);

@H9jc"}051Testing软件测试网s8f\%j9u1M9X5d"M

}51Testing软件测试网+rEt(['pca5pI

51Testing软件测试网TT(RA9xH*Oz

publicTestMainActivity(String pkg, Class<MainActivity> activityClass) {51Testing软件测试网B I*Y(^Ivh

4G%s/oN2XY's0super(pkg, activityClass);

0[ nM b/c*fdd d051Testing软件测试网O\F:`4y!} `hu+F3l

}

)tq1X'Qv|;D)g|051Testing软件测试网*Px5D.k0E0dAd(\8oN8{

@MediumTest51Testing软件测试网(J]Yx.dlX

51Testing软件测试网})E _,JK'A

publicvoidtestSum() {51Testing软件测试网GFo|!O'H/`%{GW

51Testing软件测试网)M ]q_HG9K

assertEquals(3, getActivity().sum(1, 2));51Testing软件测试网1\ TRqa(n:U1@

~&L}4B4_PO0}

(oL4|(^ Z0?Q J v4t I0

*]gKR9Z0U#D0@MediumTest51Testing软件测试网(R:QF_Y Ne%V^

eE|&Rf y0publicvoidtestSubstract() {

/{!q\4r0ja0@y0

*a K|:X6S0assertEquals(-1, getActivity().substract(1, 2));

8\U&VZ'j,k${0

&mouG2os!H0}

a4X.@U"y&N{051Testing软件测试网*]$] ]aA

}51Testing软件测试网p!Q/I NhS|!X%u+K

bwX$y]0我继承了ActivityInstrumentationTestCase2。这个TestCase在执行时会自动帮我启动相应的Activity。51Testing软件测试网[5p y7bU*U+P!k^

Fw0u,Xb7O?0接下来就是程序的Manifest:51Testing软件测试网 oB}6dpAFK n HAy

51Testing软件测试网7\uU2Cm

<?xml version="1.0"encoding="utf-8"?>

SlNmZ_K r051Testing软件测试网%Y8hJE_3h2qQ

<manifest xmlns:android="http://schemas.android.com/apk/res/android"51Testing软件测试网'z6D*`-f5X

7s/Y R5@@'^0package="com.android.testapp"

qKvLR0

S?-R+s5c,~K0android:versionCode="1"51Testing软件测试网 H[7w0m ]7Z;Y

)|.H v }:x2vT0android:versionName="1.0.0">

3T|)am5C b {f051Testing软件测试网JFH~RIiu

<application android:icon="@drawable/icon"android:label="@string/app_name">51Testing软件测试网V;y:q/xg9Yp

51Testing软件测试网uQ)JRiL$n

<activity android:name=".MainActivity"

/{7| |"TF6A2r*H%Mq051Testing软件测试网RWAvV;w j

android:label="@string/app_name">

$z*` O-Z k[r:x0

Vt;L4zI8J,R3?p0<intent-filter>51Testing软件测试网4x8riI\$g

T!}v(rSU}j0<action android:name="android.intent.action.MAIN"/>

l0fL'V,zsv)l S051Testing软件测试网6]E`L5j9E4am

<category android:name="android.intent.category.LAUNCHER"/>

t*t3Ut4a051Testing软件测试网x2D:d-?r9q0?

</intent-filter>51Testing软件测试网(C I3L\!Kd0W#P:Z

51Testing软件测试网}u9Alt-GJ#?_

</activity>51Testing软件测试网0f vkQ-B4sXzI

} I del(J0<uses-library android:name="android.test.runner"/>

*q0Q%a(\-M;T5fU051Testing软件测试网-\`*l,p)v#Wg ` L!a

</application>

$T eLmJ i"vqOh\:i7A051Testing软件测试网jOc;kx%rT1x-Ug

<instrumentation android:targetPackage="com.android.testapp"android:name="android.test.InstrumentationTestRunner"android:label="Test Unit Tests"></instrumentation>51Testing软件测试网;bvXJ}

51Testing软件测试网;j]k%L2B1k\u8d

</manifest>

s5^7E.E#\o.?051Testing软件测试网8j/u$Ag7c%Q%B

在这个文件中,我将Activity和Instrumentation的声明写到了一起,而没有像Apis Demo那样分开。请注意里面的<uses-library>标签。如果没有那句,在运行测试时会报告找不到TestRunner。这是由于Android在build的时候只把需要的东西打包,所以你必须明确的告诉Android Builder这一点。

nM1a)yni0

3. Build和Install

51Testing软件测试网r[| L%j:onq;^

在Eclipse上,这两个步骤是一起完成的。只要点一下Run即可。只不过如果你不在Run Configuration里将安装后的Launch Action设为“Do Nothing”,就会自动运行一下你的MainActivity。对于我们,设为Do Nothing即可。如下图:

%Jw#Q J7i0

4?Sne.^&Wx0

Q5x1A&C ye!z0

"O.dd-g^-]W0完成后,利用命令

6Z$T ps}0

-v\gv-`6`2ieUr0adb shell pm list packages

9HUCW t0K(}c%k(@#]051Testing软件测试网Uv7x}_8v1a

可以在已经安装的pkg列表里看到com.android.testapp。

'm/_:Q|jz0

4. 运行测试,查看结果

51Testing软件测试网%j0NKA2l7yWOI }

之后就打开命令行,运行以下命令51Testing软件测试网@:a4j*{)X3\4R

"t#q YZU;Tc0adb shell am instrument –e class com.android.testapp.test.TestMainActivity –w com.android.testapp/android.test.InstrumentationTestRunner51Testing软件测试网 I*v+Rfn~{

AE&f1j0t&|"s3M^0即可看到如下的结果:51Testing软件测试网3K4w1G T:ipSM@

# am instrument -e class com.android.testapp.test.TestMainActivity -w com.android.testapp/android.test.InstrumentationTestRunner

6h8B&RA uN\!wD0

am instrument -e class com.android.testapp.test.TestMainActivity -w com.android.testapp/android.test.InstrumentationTestRunner51Testing软件测试网2T-j S&R N[)o#s

 51Testing软件测试网ip4o/P*hM$H

com.android.testapp.test.TestMainActivity:51Testing软件测试网E!K ]Z5CLn&C|

Failure in testSubstract:51Testing软件测试网9v D9u(dS1r\+Zgv

junit.framework.AssertionFailedError: expected:<-1> but was:<1>

qn&k _6C0

       at com.android.testapp.test.TestMainActivity.testSubstract(TestMainActivity.java:27)

f V$D_@7R0

........................51Testing软件测试网^}CI!^pa.h*]

51Testing软件测试网1W.~!Us.D+XN

Y[0C'rw5Q@E0Test results for InstrumentationTestRunner=.F.51Testing软件测试网DejR z^

51Testing软件测试网T;z1I#GZ_.l _

Time: 2.693

+r!Q9xIC9| i,t bm0

 51Testing软件测试网}t)g0ox(FYk

FAILURES!!!

0[7U'uz,Jwd|mT$B9q0

Tests run: 2, Failures: 1, Errors: 051Testing软件测试网b1Ce-Z6XH0SzW/V6q

9FVU {DxtU051Testing软件测试网*Om^+A{'|:O y

-U@!cx8@(X,^/OU V0可以看到,单元测试正确的找到了减法中的错误。结果中的成功的测试显示为”.”,一个失败的显示为”F”。

yMO L ZC;{$\*q p0

TAG: Android JUnit Junit

引用 删除 denwien9   /   2012-08-22 00:38:51
引用 删除 denwien9   /   2012-08-22 00:38:40
5
引用 删除 xiaoler   /   2010-08-23 16:29:18
多谢楼主分享,楼主知道一个叫Jtest工具吗,专门针对Java的单元测试工具,当然还包含其他一些强大功能,建议看看C++test专业测试博客上面关于单元测试的一些论述:www.mytestlife.com
 

评分:0

我来说两句

Open Toolbar