Android studio 中單元測試和 UI 測試
這系列文章翻譯自google的程式碼實驗室
1.目錄如下:
1、在android studio 中建立一個新的android 應用
2、配置你的專案可以支援單元測試
3、建立你的第一個單元測試
4、把你的測試專案跑起來
5、配置你的專案進行真機測試
6、新增一些簡單的測試指令到你的應用中
7、建立並執行一個Espresso(這是一個代號,名稱而已)測試
8、恭喜你,你學到東西啦!
2.預覽(Over view):
在這篇文章裡頭呢,你可以學到如何在Android studio中建立一個測試專案,編寫測試單元跑在你的開發機器上,並且用真機進行介面測試。
那你會學到什麼呢?
- 升級Gradle讓它支援單元測試和測試依賴庫
- 編寫在Java虛擬機器上跑的單元測試
- 編寫Espresso測試,讓它跑在真機或者模擬器上
我們需要什麼環境呢?
Android studio 版本1.2以上
測試裝置的版本要4.0以上
3.在android studio 中建立一個新的android 應用
如果你是第一次開啟Android studio,那麼就可以點選歡迎介面上的:Start a new Android Studio project
把名字和域名填寫上,然後就可以點選next進行下一步操作:
那麼接下來呢,一直保持預設的設定即可,直接可以一路next下去就好了。
建立完成之後呢,你可以點選執行的按鈕把程式跑起來,就會出現hello world的介面了
到這裡的話,說明你建立一個Android studio 專案成功了!來,給自己一點掌聲吧!
4.配置你的專案可以支援單元測試
原文的話,沒什麼好看的。因為在現在的Android studio裡頭,當你建立專案的時候 ,會自動地給你新增測試依賴的,不需要手動新增。
所以,只要看看Gradle裡頭有依賴,並且資料夾有三個嘛,一個是普通的程式碼資料夾,一個JVM裡頭的測試的,一個是真機或者模擬器的測試資料夾:
5.建立你的第一個單元測試
環境一般都是有已經配置好的,我們直接建立測試單元即可。在測試之前,我們是不是要有東西測試呀,那麼我們先要建立一個用於測試的類:
package com.sunofbeaches.testtingexample;
/**
* Created by trillgates on 16/12/15.
*/
public class Caculation {
public double sum(double numA, double numB) {
return numA + numB;
}
public double multiply(double numA, double numB) {
return numA * numB;
}
}
這個類呢,很簡單,只有兩個方法。一個是做加法運算,一個做乘法運算。我們直接右鍵,如圖所示:
點選建立就可以啦,然後你選擇有Unit測試那個資料夾,也就是跑在JVM上測試的那個,就會在那裡建立的了。
package com.sunofbeaches.testtingexample;
import org.junit.Before;
import org.junit.Test;
import static junit.framework.Assert.assertEquals;
/**
* Created by trillgates on 16/12/15.
*/
public class CaculationTest {
private Caculation mCaculation;
@Before
public void setUp() throws Exception {
//Here we should new a instance
mCaculation = new Caculation();
}
@Test
public void testSum() throws Exception {
assertEquals(2,mCaculation.sum(1,1),0);
}
@Test
public void testMultiply() throws Exception {
assertEquals(10,mCaculation.multiply(2,5),0);
}
}
程式碼很簡單,僅僅是幾個方法而已。在之前的話,需要建立物件嘛,這個可以理解吧,所以先建立一個物件,後面的就用斷言的方式來測試即可。
6.把你的測試專案跑起來
編寫好測試程式碼之後,怎麼樣才能跑起來呢,這個也很簡單哈,小手一抖,對吧,就可以了!
點選注可以跑起來啦,結果如下:如果是綠條哈,那麼說明測試通過,紅色,則是程式碼邏輯有總是,輸入得到的結果不是你所斷言的,所以邏輯有總是了。
7.配置你的專案進行真機測試
原文的配置如下,有些要注意的地方請看後面的說明:
apply plugin: 'com.android.application'
android {
compileSdkVersion 22
buildToolsVersion "22.0.1"
defaultConfig {
applicationId "com.example.testing.testingexample"
minSdkVersion 15
targetSdkVersion 22
versionCode 1
versionName "1.0"
//ADD THIS LINE:
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
//ADD THESE LINES:
packagingOptions {
exclude 'LICENSE.txt'
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.0.0' //← MAKE SURE IT’S 22.0.0
testCompile 'junit:junit:4.12'
//ADD THESE LINES:
androidTestCompile 'com.android.support.test:runner:0.2'
androidTestCompile 'com.android.support.test:rules:0.2'
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.1'
}
這是我機器上的程式碼:
apply plugin: 'com.android.application'
android {
compileSdkVersion 25
buildToolsVersion "25.0.0"
defaultConfig {
applicationId "com.sunofbeaches.testtingexample"
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
//ADD THIS LINE:
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
//ADD THESE LINES:
packagingOptions {
exclude 'LICENSE.txt'
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:25.0.0'
//ADD THESE LINES:
androidTestCompile 'com.android.support.test:runner:0.2'
androidTestCompile 'com.android.support.test:rules:0.2'
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.1'
androidTestCompile 'com.android.support:support-annotations:25.0.0'
}
這裡的話,大家要靈活地新增到自己的開發工具中了,因為不同的版本可能不一樣。這個要知道哈,注意的地方就是要版本對得上,否則是不能通過編譯的。
8.新增一些簡單的測試指令到你的應用中
接下來呢,就是新增一些簡易的測試指令。先是複製下面的佈局到activity_main.xml裡
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context=".MainActivity">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="hello world!"/>
<EditText
android:id="@+id/editText"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/textView"
android:hint="Enter your name here"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@+id/editText"
android:onClick="sayHello"
android:text="Say hello!"/>
</RelativeLayout>
它看起來就這個樣子的哈:
以下是MainActivity的程式碼:
package com.sunofbeaches.testtingexample;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.EditText;
import android.widget.TextView;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void sayHello(View v){
TextView textView = (TextView) findViewById(R.id.textView);
EditText editText = (EditText) findViewById(R.id.editText);
textView.setText("Hello, " + editText.getText().toString() + "!");
}
}
9.建立並執行一個Espresso(這是一個代號,名稱而已)測試
到這裡的話,我們已經準備好了要測試的內容,於是我們就可以愉快地建立一個測試類了:
package com.sunofbeaches.testtingexample;
/**
* Created by trillgates on 16/12/15.
*/
import android.support.test.rule.ActivityTestRule;
import android.support.test.runner.AndroidJUnit4;
import android.test.suitebuilder.annotation.LargeTest;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.action.ViewActions.click;
import static android.support.test.espresso.action.ViewActions.closeSoftKeyboard;
import static android.support.test.espresso.action.ViewActions.typeText;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
import static android.support.test.espresso.matcher.ViewMatchers.withId;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
@RunWith(AndroidJUnit4.class)
@LargeTest
public class MainActivityInstrumentationTest {
private static final String STRING_TO_BE_TYPED = "Peter";
@Rule
public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(
MainActivity.class);
@Test
public void sayHello() {
onView(withId(R.id.editText)).perform(typeText(STRING_TO_BE_TYPED), closeSoftKeyboard()); //line 1
onView(withText("Say hello!")).perform(click()); //line 2
String expectedText = "Hello, " + STRING_TO_BE_TYPED + "!";
onView(withId(R.id.textView)).check(matches(withText(expectedText))); //line 3
}
}
執行一下,你就會發現,這個應用跑起來,然後會自動地輸入想著的內容,接著就消失了。綠條表示測試通過哈: