junit在android中的使用
来源:互联网 发布:神雕侠侣湖南卫视源码 编辑:程序博客网 时间:2024/06/07 06:14
Android Junit
Junit 是在Android SDK 1.5 中引入进来 。
JUnit是采用测试驱动开发的方式,也就是说在开发前先写好测试代码,主要用来说明被测试的代码会被如何使用,错误处理等;然后开始写代码,并在测试代码中逐步测试这些代码,直到最后在测试代码中完全通过。
在开发中长使用Junit 可以让人养成良好的变成习惯,让你的代码更清晰,更独立,达到松耦合的目的。
Android SDK中包含的JUnit数据包功能说明:
• junit.framework JUnit测试框架
• junit.runner 实用工具类支持JUnit测试框架
• android.test Android 对JUnit测试框架的扩展包
• android.test.mock Android的一些辅助类
• android.test.suitebuilder 实用工具类,支持类的测试运行
Junit包结构
其中常用的assertEquals和assertSame方法有所不同
1) 提供的接口数量不完全相同。
assertEquals支持boolean,long,int等等java primitiveType变量。
assertSame只支持Object
2) 比较的逻辑不同,结果可能不同。
assertSame是对象直接比较。assertEquals能利用被比较对象提供的比较逻辑来进行比较。
使得同样的条件下,两者的运行结果不一定相同。
简单解释如下:
assertEquals(Object A, Object B) 的比较逻辑:
如果 A,B都是Null,返回true。否则调用 A.equals(B)来判断。
assertSame(ObjectA, Object B)的比较逻辑:
以A == B运算的结果来判断。
A.equals(B)和 A==B 的差别在于。
如果A没有重写java.lang.Object的equals方法,
那么就是两个java对象的内存地址比较,比较结果和 A==B的结果相同。
如果A重写了equals方法(比如GregorianCalendar,BigDecimal类),
那么比较的结果不一定和A==B的结果相同
类的继承关系:
• Test—TestCase—AndroidTestCase
• Test—TestCase—InstrumentationTestCase
• Test—TestSuite—InstrumentationTestSuite
• TestListener——BaseTestRunner—AndroidTestRunner
• Instrumentation—InstrumentationTestRunner
上面介绍了一些关于junit的结构和 继承关系,下面举例说明一下junit测试
代码如下
package aexp.junit;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.database.Cursor;
import android.net.Uri;
import android.provider.Contacts;
import android.util.Log;
import android.test.AndroidTestCase;
//第一步,创建一个ContactTest类 该类继承AndroidTestCase 实现里面的setUp和 tearDown方法
//setUp方法是用来做一些数据的初始化,例如你在调用某个要测试的方法中需要一些对象//的初始化工作就可以在setUp方法中进行初始,tearDown方法是用类做资源释放的,当在//setUp方法中完的数据,就可以在tearDown中释放掉,在这个类里面 还有一些以test开都//的方法 例如:testInsertContact(), 这个方法就是你自己写的测试方法,我个人理解为在这个类中 方法执行的顺序是setUp -à testInsertContact-àtearDown 是这么个过程。
你自己写的测试方法一定要已test开头
public class ContactTest extendsAndroidTestCase
{
static final String LOG_TAG = "ContactTest";
static final String TESTUSER_NAME = "Test User";
static final String TESTUSER_NOTES = "Test note";
ContentResolver contentResolver;
Uri newPerson;
public void setUp()
{
contentResolver = getContext().getContentResolver();
ContentValues person = new ContentValues();
person.put(Contacts.People.NAME, TESTUSER_NAME );
person.put(Contacts.People.NOTES, TESTUSER_NOTES );
newPerson = contentResolver.insert(
Contacts.People.CONTENT_URI,person);
}
public void testInsertContact()
{
Log.d( LOG_TAG, "testInsertContact" );
assertNotNull( newPerson );
}
public void testQueryContact()
{
Log.d( LOG_TAG, "testQueryContact" );
String columns[] = { Contacts.People.NAME,
Contacts.People.NOTES };
Cursor c = contentResolver.query( Contacts.People.CONTENT_URI,
columns,
Contacts.People.NAME+"=?",
new String[] {TESTUSER_NAME },
null );
assertNotNull( c );
int hits = 0;
while( c.moveToNext() )
{
int nameColumnIndex = c.getColumnIndex( Contacts.People.NAME );
int notesColumnIndex = c.getColumnIndex( Contacts.People.NOTES );
String name = c.getString(nameColumnIndex );
String notes = c.getString( notesColumnIndex );
Log.d( LOG_TAG,"retrieved name: "+name );
Log.d( LOG_TAG,"retrieved notes: "+notes );
assertEquals( TESTUSER_NAME,name );
assertEquals( TESTUSER_NOTES, notes );
++hits;
}
assertEquals( hits,1 );
c.close();
}
public void tearDown()
{
contentResolver.delete( newPerson, null, null );
}
}
//第二部,创建ExampleSuite类 继承TestSuite
package aexp.junit;
import junit.framework.TestSuite;
public class ExampleSuite extends TestSuite
{
public ExampleSuite()
{
addTestSuite( MathTest.class );
addTestSuite( ContactTest.class );
addTestSuite(SomeTest.class);
}
}
在这里说说TestSuite
自己定义的TestCase,并使用TestRunner来运行测试,事实上TestRunner并不直接运行 TestCase上的单元方法,而是透过TestSuite,TestSuite可以将数个TestCase在一起,而让每个TestCase保持简单。
来看看一个例子:
MathToolTest.java
package onlyfun.caterpillar.test;
import onlyfun.caterpillar.MathTool;
import junit.framework.TestCase;
public class MathToolTest extendsTestCase {
public MathToolTest(String testMethod) {
super(testMethod);
}
public void testGcd() {
assertEquals(5, MathTool.gcd(10, 5));
}
public static void main(String[] args) {
junit.textui.TestRunner.run(MathToolTest.class);
}
}
在这个例子中,您并没有看到任何的TestSuite,事实上,如果您没有提供任何的TestSuite,TestRunner会自己建立一个,然後这个TestSuite会使用反射(reflection)自动找出testXXX()方法。
如果您要自行生成TestSuite,则在继承TestCase之後,提供静态的(static)的suite()方法,例如:
publicstatic Test suite() {
return new TestSuite(MathTool.class);
}
如果您没有提供任何的TestSuite,则TestRunner就会像上面这样自动为您建立一个,并找出testXXX()方法,您也可以如下面定义 suite()方法:
publicstatic Test suite() {
TestSuite suite = new TestSuite(MathTool.class);
suite.addTest(new MathToolTest("testGcd"));
return suite;
}
JUnit并没有规定您一定要使用testXXX()这样的方式来命名您的测试方法,如果您要提供自己的方法(当然JUnit 鼓励您使用testXXX()这样的方法名称),则可以如上撰写,为了要能够使用建构函式提供测试方法名称,您的TestCase必须提供如下的建构函 式:
publicMathToolTest(String testMethod) {
super(testMethod);
}
如果要加入更多的测试方法,使用addTest()就可以了,suite()方法传回一个TestSuite物件,它与 TestCase都实作了Test介面,TestRunner会调用TestSuite上的run()方法,然後TestSuite会将之委托给 TestCase上的run()方法,并执行每一个testXXX()方法。
除了组合TestCase之外,您还可以将数个TestSuite组合在一起,例如:
publicstatic Test suite() {
TestSuite suite= new TestSuite();
suite.addTestSuite(TestCase1.class);
suite.addTestSuite(TestCase2.class);
return suite;
}
如此之来,您可以一次运行所有的测试,而不必个别的运行每一个测试案例,您可以写一个运行全部测试的主测试,而在使用TestRunner时呼叫 suite()方法,例如:
junit.textui.TestRunner.run(TestAll.suite());
TestCase与TestSuite都实作了Test介面,其运行方式为 Command 模式 的一个实例,而TestSuite可以组合数个TestSuite或TestCase,这是 Composite 模式 的一个实例。
第三步,修改清单文件(AndroidManifest.xml)
如果你要使用Junit 并且是在eclipse中使用的话
就必须在AndroidManifest.xml中加上
<?xml version="1.0"encoding="utf-8"?>
<manifestxmlns:android="http://schemas.android.com/apk/res/android"
package="aexp.junit"
android:versionCode="1"
android:versionName="1.0.0">
<uses-permissionandroid:name="android.permission.WRITE_CONTACTS"/>
<uses-permissionandroid:name="android.permission.READ_CONTACTS"/>
<application android:label="@string/app_name">
<uses-libraryandroid:name="android.test.runner"/>
<activityandroid:name=".JUnit"
android:label="@string/app_name">
<intent-filter>
<actionandroid:name="android.intent.action.MAIN" />
<categoryandroid:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<instrumentationandroid:targetPackage="aexp.junit"android:name="android.test.InstrumentationTestRunner"
android:label="AndroidJUnit测试" />
<uses-sdk android:minSdkVersion="4" />
</manifest>
红色文字的地方是要加上的代码,注意instrumentationandroid:targetPackage指向的是你当前应用的包。
在附上一个关于activity的代码
package aexp.junit;
import android.app.Activity;
import android.os.Bundle;
import android.test.AndroidTestCase;
import android.test.AndroidTestRunner;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import android.view.View;
import android.util.Log;
import junit.framework.TestListener;
import junit.framework.Test;
importjunit.framework.AssertionFailedError;
public class JUnit extends Activity {
static final String LOG_TAG = "junit";
Thread testRunnerThread = null;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Button launcherButton = (Button)findViewById( R.id.launch_button );
launcherButton.setOnClickListener( new View.OnClickListener() {
public void onClick( View view ) {
startTest();
}
} );
}
private synchronized void startTest()
{
if( ( testRunnerThread != null ) &&
!testRunnerThread.isAlive() )
testRunnerThread = null;
if( testRunnerThread == null ) {
testRunnerThread = new Thread( new TestRunner( this ) );
testRunnerThread.start();
} else
Toast.makeText(
this,
"Test is stillrunning",
Toast.LENGTH_SHORT).show();
}
}
class TestDisplay implements Runnable
{
public enum displayEvent{START_TEST,END_TEST,ERROR,FAILURE,}
displayEvent ev;
String testName;
int testCounter;
int errorCounter;
int failureCounter;
TextView statusText;
TextView testCounterText;
TextView errorCounterText;
TextView failureCounterText;
public TestDisplay( displayEvent ev,
String testName,
int testCounter,
int errorCounter,
int failureCounter,
TextView statusText,
TextViewtestCounterText,
TextViewerrorCounterText,
TextViewfailureCounterText )
{
this.ev = ev;
this.testName = testName;
this.testCounter = testCounter;
this.errorCounter = errorCounter;
this.failureCounter = failureCounter;
this.statusText = statusText;
this.testCounterText = testCounterText;
this.errorCounterText = errorCounterText;
this.failureCounterText = failureCounterText;
}
public void run()
{
StringBuffer status = new StringBuffer();
switch( ev ) {
case START_TEST:
status.append( "Starting" );
break;
case END_TEST:
status.append("Ending" );
break;
case ERROR:
status.append( "Error:" );
break;
case FAILURE:
status.append("Failure: " );
break;
}
status.append( ": " );
status.append( testName );
statusText.setText( new String( status ) );
testCounterText.setText( "Tests: "+testCounter );
errorCounterText.setText( "Errors: "+errorCounter );
failureCounterText.setText( "Failure: "+failureCounter );
}
}
class TestRunner implementsRunnable,TestListener
{
static final String LOG_TAG = "TestRunner";
int testCounter;
int errorCounter;
int failureCounter;
TextView statusText;
TextView testCounterText;
TextView errorCounterText;
TextView failureCounterText;
Activity parentActivity;
public TestRunner( Activity parentActivity )
{
this.parentActivity = parentActivity;
}
public void run()
{
testCounter = 0;
errorCounter = 0;
failureCounter = 0;
statusText = (TextView)parentActivity.
findViewById( R.id.status );
testCounterText = (TextView)parentActivity.
findViewById( R.id.testCounter );
errorCounterText = (TextView)parentActivity.
findViewById( R.id.errorCounter );
failureCounterText = (TextView)parentActivity.
findViewById( R.id.failureCounter );
Log.d( LOG_TAG, "Test started" );
AndroidTestRunner testRunner = new AndroidTestRunner();
testRunner.setTest( new ExampleSuite() );
testRunner.addTestListener( this);
testRunner.setContext( parentActivity );
testRunner.runTest();
Log.d( LOG_TAG, "Test ended" );
}
// TestListener
public void addError(Test test, Throwable t)
{
Log.d( LOG_TAG, "addError: "+test.getClass().getName() );
Log.d( LOG_TAG, t.getMessage(), t );
++errorCounter;
TestDisplay td = new TestDisplay(
TestDisplay.displayEvent.ERROR,
test.getClass().getName(),
testCounter,
errorCounter,
failureCounter,
statusText,
testCounterText,
errorCounterText,
failureCounterText);
parentActivity.runOnUiThread( td );
}
public void addFailure(Test test, AssertionFailedError t)
{
Log.d( LOG_TAG, "addFailure: "+test.getClass().getName() );
Log.d( LOG_TAG, t.getMessage(), t );
++failureCounter;
TestDisplay td = new TestDisplay(
TestDisplay.displayEvent.FAILURE,
test.getClass().getName(),
testCounter,
errorCounter,
failureCounter,
statusText,
testCounterText,
errorCounterText,
failureCounterText );
parentActivity.runOnUiThread( td );
}
public void endTest(Test test)
{
Log.d( LOG_TAG, "endTest: "+test.getClass().getName() );
TestDisplay td = new TestDisplay(
TestDisplay.displayEvent.END_TEST,
test.getClass().getName(),
testCounter,
errorCounter,
failureCounter,
statusText,
testCounterText,
errorCounterText,
failureCounterText );
parentActivity.runOnUiThread( td );
}
public void startTest(Test test)
{
Log.d( LOG_TAG, "startTest: "+test.getClass().getName() );
++testCounter;
TestDisplay td = new TestDisplay(
TestDisplay.displayEvent.START_TEST,
test.getClass().getName(),
testCounter,
errorCounter,
failureCounter,
statusText,
testCounterText,
errorCounterText,
failureCounterText );
parentActivity.runOnUiThread( td );
}
}
这是个人简单的对android中 junit的一些使用上的理解。
- junit在android中的使用
- Junit 在 android 中的基本使用
- JUNIT在Eclipse中的使用
- 在android中使用junit
- Spring注解在Junit中的使用问题
- 在android中使用junit(2)
- 在Android中使用Junit测试注意事项
- 在Android Studio中使用JUNIT测试
- Android中的Junit单元测试
- Android中的junit单元测试
- Android中的Junit单元测试
- Android中的Junit测试
- Android中的junit测试
- 在Android Studio中使用Android Tests(Junit)
- Android下使用JUnit
- Android下使用JUnit
- android 使用Junit测试
- Android使用Junit测试
- WinCE系统的编译过程
- getopt 详解 linux
- 根据查询更新JTable显示
- 国际化开
- premiere定时采集视频
- junit在android中的使用
- bash 命令行的编辑方式设置
- linux虚拟机的时候经常发现要在XP和VM之间的光标切换
- 转载一篇关于 接口和抽象类 的文章,写的很好
- Assembly Manifest
- VC中树形控件(CTreeCtrl)的使用
- ireport中文手册3.7版(无图)
- Ctrl+Alt+Fn不能切换到字符界面
- VC++6.0 转 VS2005以上版本(1)