序言
當程序業務邏輯也越來越複雜的時候,測試當中出了業務邏輯的bug是最難改了。如果說你有寫單元測試的習慣,通過業務邏輯的單元測試可以很容易找到出錯的代碼塊,然後解決掉。今天來給大家介紹下android中的單元測試基本使用
What android的單元測試可以幹些什麼事
android的framework中提供有關單元測試的api,首先我們先來看一下api的架構體系圖
由此可以見系統已經支持 android中重要組件的單元測試(activity,Service,ContentProvider和Application)的單元測試
在實際工作當中可能對於業務邏輯測試和接口測試會偏多一些
比如mock一些業務流程 然後去寫TODO僞代碼,測試是否符合預期,然後去做UI實現。首先保證我們的業務邏輯不會出錯,這樣才能保證我們的程序不會出大的bug
How 如何使用
測試業務邏輯的單元測試
當測試不需要對app內部資源引用的時候,我們可以用org.junit.Test,此方式不會安裝app到手機中
1.我們新建一個OperationServiceUnitTest
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Created by qinwei on 16/5/6 下午3:15
*/
public class OperationServiceUnitTest {
private OperationService service;
@Before
public void setUp() throws Exception {
// TODO 做一些測試配置
service=new OperationService();
}
@Test
public void testAdd() throws Exception {
assertEquals(1,service.add(1,1)) ;
}
@Test
public void testMultiplicative() throws Exception {
assertEquals(2,service.multiplicativ(1,1)) ;
}
@After
public void tearDown() throws Exception {
// TODO 測試結束調用
}
2.寫一個方法testAdd 方法用@Test註解修飾
@Test
public void testAdd() throws Exception {
service=new OperationService();
//對測試結果做一個預期判斷
assertEquals(2,service.add(1,1)) ;
}
測試通過後我們可以看到這個界面
測試不通過
當涉及到app內部資源的單元測試,此方式會安裝app到手機中
1.創建AndroidTestCase子類
/**
* Created by qinwei on 16/5/6 下午3:48
*/
public class LoginTest extends AndroidTestCase {
public void testLogin() throws Exception {
String username = getContext().getString(R.string.username);
String password = getContext().getString(R.string.password);
LoginBiz biz = new LoginBiz();
assertEquals(true, biz.doLogin(username, password));
}
}
可用通過getContext方法拿到上下文對象,有了上下文我們就可以對數據庫,sp操作,得到String.xml文件數據等等
-------------activity的單元測試待續------
activity的單元測試
可用來測試UI邏輯,比如模擬登錄,用戶輸入校驗,活動之間跳轉
下面來看一個登錄場景的單元測試
LoginActivity.java
public class LoginActivity extends AppCompatActivity implements View.OnClickListener {
private EditText mLoginUsernameEdt;
private EditText mLoginPasswordEdt;
private Button mLoginCommitBtn;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mLoginUsernameEdt=(EditText) findViewById(R.id.mLoginUsernameEdt);
mLoginPasswordEdt=(EditText) findViewById(R.id.mLoginPasswordEdt);
mLoginCommitBtn=(Button) findViewById(R.id.mLoginCommitBtn);
mLoginCommitBtn.setOnClickListener(this);
}
@Override
public void onClick(View v) {
String uname=mLoginUsernameEdt.getText().toString();
String pwd=mLoginPasswordEdt.getText().toString();
Toast.makeText(LoginActivity.this, "uname:"+uname+",pwd "+pwd, Toast.LENGTH_SHORT).show();
}
}
LoginBiz.java
/**
* Created by qinwei on 16/5/6 下午3:50
*/
public class LoginBiz {
public boolean doLogin(String uname,String password){
//用的硬編碼
return uname.equals("123456")&&password.equals("123456");
}
}
步驟:
1.創建ActivityInstrumentationTestCase2< T > 子類,這裏的T指的是測試的activity類名
2.編寫模擬用戶操作的代碼
/**
* Created by qinwei on 16/5/6 下午4:44
*/
public class LoginActivityTest extends ActivityInstrumentationTestCase2<LoginActivity>{
public LoginActivityTest(Class<LoginActivity> activityClass) {
super(activityClass);
}
public LoginActivityTest(){
super(LoginActivity.class);
}
private EditText mLoginUsernameEdt;
private EditText mLoginPasswordEdt;
private Button mLoginCommitBtn;
@Override
protected void setUp() throws Exception {
super.setUp();
LoginActivity activity=getActivity();
mLoginUsernameEdt=(EditText) activity.findViewById(R.id.mLoginUsernameEdt);
mLoginPasswordEdt=(EditText) activity.findViewById(R.id.mLoginPasswordEdt);
mLoginCommitBtn=(Button) activity.findViewById(R.id.mLoginCommitBtn);
}
public void testCheckInit() throws Exception {
assertNotNull(mLoginUsernameEdt);
assertNotNull(mLoginPasswordEdt);
assertNotNull(mLoginCommitBtn);
}
public void testInput() throws Exception {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mLoginUsernameEdt.requestFocus();//獲取焦點
mLoginUsernameEdt.performClick();//模擬點擊
}
});
/*由於測試用例在單獨的線程上執行,所以此處需要同步application,
* 調用waitForIdleSync等待測試線程和UI線程同步,才能進行輸入操作。
* waitForIdleSync和sendKeys不允許在UI線程裏運行
*/
getInstrumentation().waitForIdleSync();
//調用sendKeys方法,輸入用戶名
sendKeys(KeyEvent.KEYCODE_P, KeyEvent.KEYCODE_H,
KeyEvent.KEYCODE_I, KeyEvent.KEYCODE_C,
KeyEvent.KEYCODE_O, KeyEvent.KEYCODE_M,
KeyEvent.KEYCODE_M);
getActivity().runOnUiThread(new Runnable()
{
@Override
public void run()
{
// TODO 獲取焦點,模擬點擊彈出輸入法
mLoginPasswordEdt.requestFocus();
mLoginPasswordEdt.performClick();
}
});
//調用sendKeys方法,輸入密碼
sendKeys(KeyEvent.KEYCODE_1, KeyEvent.KEYCODE_2,
KeyEvent.KEYCODE_3, KeyEvent.KEYCODE_4);
}
public void testLogin() throws Exception {
getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
mLoginCommitBtn.requestFocus();
mLoginCommitBtn.performClick();
int j=10;
try {
for (int i = 0; i < j; i++) {
Thread.sleep(400);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
});
}
@Override
protected void tearDown() throws Exception {
super.tearDown();
}
}
嗯哼,今天就講到這裏,博客我會繼續堅持寫下去,我會定期給大家分享一些開發技巧,以及優質的視頻教程
結束語
文中有講到不對的地方還請大家斧正。