本文主要內(nèi)容
- 1仁堪、單元測試介紹
- 2、java單元測試
- 3各吨、android單元測試
- 4枝笨、常用方法介紹
1、單元測試介紹
單元測試揭蜒,是指對軟件中的最小可測試單元進(jìn)行檢查和驗證横浑。
在Java中,最小單元可以是類也可以是方法屉更,比如剛剛開發(fā)完成一個下載的方法徙融,此時可以用單元測試其是否ok。如果不用單元測試瑰谜,用手寫代碼調(diào)用的方式欺冀,則工作量會較大。
使用Android studio進(jìn)行單元測試萨脑,一共有兩種類型隐轩,一種就是普通的java單元測試,另一種就是android單元測試渤早,android單元測試包括對ui測試职车,activity的相關(guān)方法進(jìn)行測試等等,需要context參數(shù)
進(jìn)行單元測試需要引入對應(yīng)的依賴鹊杖。
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)建工程的時候會默認(rèn)加進(jìn)來,最后一個貌似不會默認(rèn)添加骂蓖,需要手動添加积瞒。最后一個依賴包與activity相關(guān)的單元測試有關(guān)。
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選項揩瞪,生成對應(yīng)的單元測試文件。
最后一步中可以選擇為當(dāng)前類中的哪些方法添加單元測試篓冲,也可以勾選before和after兩個選項李破,顧名思義,before和after方法分別在單元測試前后調(diào)用壹将,我們可以在這兩個方法中做一些事情嗤攻,例如初始化、回收等等诽俯。
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 中初始化,在測試方法中使用已經(jīng)初始化過的實例即可仙粱。
Java單元測試運行依賴于 JVM房交,執(zhí)行單元測試方法非常簡單,右鍵單元測試文件執(zhí)行即可伐割,也可以選擇某個方法候味,只執(zhí)行這一個方法。
3隔心、android單元測試
Android單元測試白群,它依賴于Android的執(zhí)行環(huán)境,也就是需要在android機器上運行硬霍。與java單元測試相比帜慢,它有一點點的不同。
前一章中講過java單元測試须尚,提到了 before 和 after 這兩個選項崖堤,有點類似于切面編程,可以在其中做一些初始化的動作耐床。但android中最常用的是activity密幔,如何在activity中也添加一些周期回調(diào)函數(shù)呢?
@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相關(guān)的單元測試周期回調(diào)函數(shù)撩轰。
getActivityIntent 胯甩,顧名思義昧廷,對啟動activity的intent進(jìn)行測試封裝,上例中就添加了相關(guān)的參數(shù)偎箫。值得注意的是木柬,為何 intent 中沒有添加 action 呢?我猜想就是 ActivityTestRule 對象已經(jīng)與MainActivity相關(guān)聯(lián)了淹办,它就是要去啟動MainActivity的眉枕,加不加action都無所謂了。這里也隱含了另一層意思怜森,要對某個activity相關(guān)的任何方法進(jìn)行單元測試速挑,都要添加與之相關(guān)聯(lián)的ActivityTestRule 對象。
beforeActivityLaunched 副硅,就是在activity啟動之前執(zhí)行的函數(shù)
本例中姥宝,有一個EditText,TextView和一個Button恐疲,點擊Button腊满,將EditText中的文字顯示到TextView,同時也會接收Intent中的相關(guān)參數(shù)培己,顯示在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é)一樣生成碳蛋,我們看看詳細(xì)代碼:
@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是可以獲取的省咨。另外最重要的就是理解這幾個生命周期回調(diào)函數(shù)的作用疮蹦。可以在setUp函數(shù)中獲取context茸炒,如果與activity啟動相關(guān)的要改動愕乎,則在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必須在當(dāng)前界面上顯示出來(有且可見)撮竿。
方法名 | 含義 |
---|---|
click() | 點擊view |
clearText() | 清除文本內(nèi)容 |
swipeLeft() | 從右往左滑 |
swipeRight() | 從左往右滑 |
swipeDown() | 從上往下滑 |
swipeUp() | 從下往上滑 |
click() | 點擊view |
closeSoftKeyboard() | 關(guān)閉軟鍵盤 |
pressBack() | 按下物理返回鍵 |
doubleClick() | 雙擊 |
longClick() | 長按 |
scrollTo() | 滾動 |
replaceText() | 替換文本 |
openLinkWithText() | 打開指定超鏈 |