Android單元測試

本文主要內容

  • 1、單元測試介紹
  • 2、java單元測試
  • 3、android單元測試
  • 4、常用方法介紹

1、單元測試介紹

單元測試,是指對軟件中的最小可測試單元進行檢查和驗證。

在Java中,最小單元可以是類也可以是方法,比如剛剛開發(fā)完成一個下載的方法,此時可以用單元測試其是否ok。如果不用單元測試,用手寫代碼調用的方式,則工作量會較大。

使用Android studio進行單元測試,一共有兩種類型,一種就是普通的java單元測試,另一種就是android單元測試,android單元測試包括對ui測試,activity的相關方法進行測試等等,需要context參數

image.png

進行單元測試需要引入對應的依賴。

testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:1.0.2'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
androidTestImplementation 'com.android.support.test:rules:1.0.2'

前面3個依賴包,在創(chuàng)建工程的時候會默認加進來,最后一個貌似不會默認添加,需要手動添加。最后一個依賴包與activity相關的單元測試有關。

2、java單元測試

以一個最簡單的例子,計算器為例:

public class Util {

public static int add(int a, int b){
    return a + b;
}

public int addInt(int a, int b){
    return a + b;
}
}

Util類中有一個靜態(tài)方法,一個非靜態(tài)方法,都是簡單的相加邏輯。接下來,可以右鍵選中方法,然后點擊goto選項,生成對應的單元測試文件。

最后一步中可以選擇為當前類中的哪些方法添加單元測試,也可以勾選before和after兩個選項,顧名思義,before和after方法分別在單元測試前后調用,我們可以在這兩個方法中做一些事情,例如初始化、回收等等。

public class UtilTest {

Util util;

@Before
public void setUp() throws Exception {
    util = new Util();
    System.out.println("sutup");
}

@After
public void tearDown() throws Exception {
    System.out.println("tearDown");
}

@Test
public void add() {
    assertEquals(2,Util.add(1, 1));
}

@Test
public void addInt() {
    assertEquals(2, util.addInt(1,1));
}
}

Util類中,寫了一個靜態(tài)方法和非靜態(tài)方法,其實就是為了演示 setUp 方法的作用,如果在單元測試中需要初始化一些類,則可以在 setUp 中初始化,在測試方法中使用已經初始化過的實例即可。

Java單元測試運行依賴于 JVM,執(zhí)行單元測試方法非常簡單,右鍵單元測試文件執(zhí)行即可,也可以選擇某個方法,只執(zhí)行這一個方法。

3、android單元測試

Android單元測試,它依賴于Android的執(zhí)行環(huán)境,也就是需要在android機器上運行。與java單元測試相比,它有一點點的不同。

前一章中講過java單元測試,提到了 before 和 after 這兩個選項,有點類似于切面編程,可以在其中做一些初始化的動作。但android中最常用的是activity,如何在activity中也添加一些周期回調函數呢?

@Rule
public ActivityTestRule<MainActivity> rule = new ActivityTestRule<MainActivity>(MainActivity.class){
    @Override
    protected Intent getActivityIntent() {
        Intent intent = new Intent();
        intent.putExtra("data","world");
        return intent;
    }

    @Override
    protected void beforeActivityLaunched() {
        super.beforeActivityLaunched();
        Log.i("okunu","before");
    }
};

通過如上方式添加activity相關的單元測試周期回調函數。

getActivityIntent ,顧名思義,對啟動activity的intent進行測試封裝,上例中就添加了相關的參數。值得注意的是,為何 intent 中沒有添加 action 呢?我猜想就是 ActivityTestRule 對象已經與MainActivity相關聯了,它就是要去啟動MainActivity的,加不加action都無所謂了。這里也隱含了另一層意思,要對某個activity相關的任何方法進行單元測試,都要添加與之相關聯的ActivityTestRule 對象。

beforeActivityLaunched ,就是在activity啟動之前執(zhí)行的函數

本例中,有一個EditText,TextView和一個Button,點擊Button,將EditText中的文字顯示到TextView,同時也會接收Intent中的相關參數,顯示在TextView中

public class MainActivity extends AppCompatActivity {

String mData;
TextView text;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);
    mData = getIntent().getStringExtra("data");
    text = (TextView)findViewById(R.id.text);
    text.setText(mData != null ? mData : "");
}

public void sayHello(View view){
    EditText edit = (EditText)findViewById(R.id.edit);
    String str = "hello  " + mData + " " + edit.getText().toString() + " !";
    text.setText(str);
}
}

它的單元測試類依然可以和第2節(jié)一樣生成,我們看看詳細代碼:

@RunWith(AndroidJUnit4.class)
public class MainActivityTest {

@Rule
public ActivityTestRule<MainActivity> rule = new ActivityTestRule<MainActivity>(MainActivity.class){
    @Override
    protected Intent getActivityIntent() {
        Intent intent = new Intent();
        intent.putExtra("data","world");
        return intent;
    }

    @Override
    protected void beforeActivityLaunched() {
        super.beforeActivityLaunched();
        Log.i("okunu","before");
    }
};

Context appContext;
@Before
public void setUp() throws Exception {
    Log.i("okunu","setUp");
    appContext = InstrumentationRegistry.getTargetContext();
}

@After
public void tearDown() throws Exception {
    Log.i("okunu","tearDown");
}

@Test
public void sayHello() {
    onView(withId(R.id.edit)).perform(typeText("jim"), closeSoftKeyboard()); //line 1
    onView(withText("hello")).perform(click()); //line 2
    String expectedText = "hello  " + "world " + "jim" + " !";
    onView(withId(R.id.text)).check(matches(withText(expectedText))); //line 3
}
}

注意,context是可以獲取的。另外最重要的就是理解這幾個生命周期回調函數的作用。可以在setUp函數中獲取context,如果與activity啟動相關的要改動,則在ActivityTestRule類中修改即可。

4、常用方法介紹

在android單元測試中需要獲取到某個view,如何獲取呢?

  • withText:通過文本來獲取對象,如:ViewInteraction save = onView(withText(“保存”)) ;
  • withId:通過id來獲取對象,如:ViewInteraction save = onView(withId(R.id.save)) ;

通過文本獲取,如上例,如果某個view上的文本是“保存”,則返回此view。通過id獲取就比較容易理解了,建議使用id方式。

那么對view操作的接口又有哪些呢?

使用方式是onView(…).perform() 。也可以執(zhí)行多個操作在一個perform中如:perform(click(),clearText()) 。所有的操作都有一個前提 ———— 就是要執(zhí)行的view必須在當前界面上顯示出來(有且可見)。

方法名 含義
click() 點擊view
clearText() 清除文本內容
swipeLeft() 從右往左滑
swipeRight() 從左往右滑
swipeDown() 從上往下滑
swipeUp() 從下往上滑
click() 點擊view
closeSoftKeyboard() 關閉軟鍵盤
pressBack() 按下物理返回鍵
doubleClick() 雙擊
longClick() 長按
scrollTo() 滾動
replaceText() 替換文本
openLinkWithText() 打開指定超鏈
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容