如何在Android Studio中進(jìn)行android單元測試和UI測試

1.概述

這里你將學(xué)習(xí)如何在Android Studio中配置工程用于測試师抄,在開發(fā)機(jī)器上編寫并運(yùn)行單元測試,以及如何在手機(jī)上做功能UI測試湖蜕。

你會(huì)學(xué)到什么

更新包含JUnit和Android Testing Support Library的Gradle構(gòu)建文件

編寫運(yùn)行在本機(jī)Java虛擬機(jī)上的單元測試

編寫運(yùn)行在手機(jī)或者虛擬機(jī)上的Espresso測試

你需要什么

Android Studiov1.2+

Android 4.0+的測試設(shè)備


2.創(chuàng)建新的Android Studio工程


如果是第一次啟動(dòng)Android Studio逻卖,從歡迎頁選擇“Start a new Android Studio project”。如果已經(jīng)打開了一個(gè)工程昭抒,選擇File>New>New Project...

Create new project”向?qū)?huì)指導(dǎo)整個(gè)過程评也,在第一頁輸入如下內(nèi)容:

Setting | Value |

------------ | ------------- | ------------

Application Name| TestingExample

Company demain| testing.example.com

這樣會(huì)保證你的代碼同codelab講解的內(nèi)容具有一致的命名。其他的選項(xiàng)都設(shè)置為默認(rèn)灭返,一路點(diǎn)擊Next直到工程創(chuàng)建完畢仇参。

點(diǎn)擊Run按鈕檢查app是否運(yùn)行正常,要么從模擬器列表中選擇一個(gè)啟動(dòng)婆殿,要么確認(rèn)開啟了debug模式的設(shè)備通過USB同電腦正確連接。

app目前沒有做任何事情罩扇,但是屏幕上應(yīng)該顯示“Hello world!”和app的名字婆芦。


3.配置支持單元測試的工程

在寫測試之前,讓我們做下簡單的檢查喂饥,確保工程配置正確消约。

首先,確認(rèn)在Build Variants窗口內(nèi)的Test Artifact中選擇了"Unit Tests"员帮。

然后或粮,在工程的src文件夾內(nèi)創(chuàng)建test和test/java文件夾。需要注意的是捞高,你不能在Android視圖下進(jìn)行這些操作氯材,要么在系統(tǒng)的文件管理器內(nèi)創(chuàng)建渣锦,要么在工程窗口左上方點(diǎn)擊下拉菜單選擇Project視圖。最終的工程結(jié)構(gòu)應(yīng)該是這樣的:

(在codelab的剩余部分氢哮,你可以返回繼續(xù)使用Android工程視圖)

最后袋毙,打開工程的build.gradle(Module:app)文件,添加JUnit4依賴冗尤,點(diǎn)擊Gradle sync按鈕听盖。

build.gradle

dependencies {

compile fileTree(dir: 'libs', include: ['*.jar'])

compile 'com.android.support:appcompat-v7:22.1.1'

testCompile 'junit:junit:4.12'

}

當(dāng)你同步Gradle配置時(shí),可能需要聯(lián)網(wǎng)下載JUnit依賴裂七。

4.創(chuàng)建第一個(gè)單元測試

現(xiàn)在皆看,萬事俱備,讓我們開始寫第一個(gè)測試吧背零。首先腰吟,創(chuàng)建一個(gè)非常簡單的被測類:Calculator類。

然后捉兴,向類中添加一些基本的算術(shù)運(yùn)算方法蝎困,比如加法和減法。將下列代碼復(fù)制到編輯器中倍啥。不用擔(dān)心實(shí)際的實(shí)現(xiàn)禾乘,暫時(shí)讓所有的方法返回0。

Calculator.java

package com.example.testing.testingexample;

public class Calculator {

public double sum(double a, double b){

return 0;

}

public double substract(double a, double b){

return 0;

}

public double divide(double a, double b){

return 0;

}

public double multiply(double a, double b){

return 0;

}

}

Android Studio提供了一個(gè)快速創(chuàng)建測試類的方法虽缕。只需在編輯器內(nèi)右鍵點(diǎn)擊Calculator類的聲明始藕,選擇Go to > Test,然后"Create a new test…"

在打開的對(duì)話窗口中氮趋,選擇JUnit4和"setUp/@Before"伍派,同時(shí)為所有的計(jì)算器運(yùn)算生成測試方法。

這樣剩胁,就會(huì)在正確的文件夾內(nèi)(app/src/test/java/com/example/testing/testingexample)生成測試類框架诉植,在框架內(nèi)填入測試方法即可。下面是一個(gè)示例:

Calculator.java

package com.example.testing.testingexample;

import org.junit.Before;

import org.junit.Test;

import static org.junit.Assert.*;

public class CalculatorTest {

private Calculator mCalculator;

@Before

public void setUp() throws Exception {

mCalculator = new Calculator();

}

@Test

public void testSum() throws Exception {

//expected: 6, sum of 1 and 5

assertEquals(6d, mCalculator.sum(1d, 5d), 0);

}

@Test

public void testSubstract() throws Exception {

assertEquals(1d, mCalculator.substract(5d, 4d), 0);

}

@Test

public void testDivide() throws Exception {

assertEquals(4d, mCalculator.divide(20d, 5d), 0);

}

@Test

public void testMultiply() throws Exception {

assertEquals(10d, mCalculator.multiply(2d, 5d), 0);

}

}

請(qǐng)將代碼復(fù)制到編輯器或者使用JUnit框架提供的斷言來編寫自己的測試昵观。

5.運(yùn)行單元測試

終于到運(yùn)行測試的時(shí)候了晾腔!右鍵點(diǎn)擊CalculatorTest類,選擇Run > CalculatorTest啊犬。也可以通過命令行運(yùn)行測試灼擂,在工程目錄內(nèi)輸入:

./gradlew test

無論如何運(yùn)行測試,都應(yīng)該看到輸出顯示4個(gè)測試都失敗了觉至。這是預(yù)期的結(jié)果剔应,因?yàn)槲覀冞€沒有實(shí)現(xiàn)運(yùn)算操作。

讓我們修改Calculator類中的sum(double a, double b)方法返回一個(gè)正確的結(jié)果,重新運(yùn)行測試峻贮。你應(yīng)該看到4個(gè)測試中的3個(gè)失敗了席怪。

Calculator.java

public double sum(double a, double b){

return a + b;

}

作為練習(xí),你可以實(shí)現(xiàn)剩余的方法使所有的測試通過月洛。

可能你已經(jīng)注意到了Android Studio從來沒有讓你連接設(shè)備或者啟動(dòng)模擬器來運(yùn)行測試何恶。那是因?yàn)椋挥趕rc/tests目錄下的測試是運(yùn)行在本地電腦Java虛擬機(jī)上的單元測試嚼黔。編寫測試细层,實(shí)現(xiàn)功能使測試通過,然后再添加更多的測試...這種工作方式使快速迭代成為可能唬涧,我們稱之為測試驅(qū)動(dòng)開發(fā)疫赎。

值得注意的是,當(dāng)在本地運(yùn)行測試時(shí)碎节,Gradle為你在環(huán)境變量中提供了包含Android框架的android.jar包捧搞。但是它們功能不完整(所以,打個(gè)比方狮荔,你不能單純調(diào)用Activity的方法并指望它們生效)胎撇。推薦使用Mockito等mocking框架來mock你需要使用的任何Android方法。對(duì)于運(yùn)行在設(shè)備上殖氏,并充分利用Android框架的測試晚树,請(qǐng)繼續(xù)閱讀本篇教程的下個(gè)部分。

6.配置支持Instrumentation測試的工程

雖然在Android框架內(nèi)支持運(yùn)行instrumentation測試雅采,但是目前開發(fā)重心主要集中在剛剛發(fā)布的作為Android Testing Support Library一部分的新的AndroidJUnitRunner爵憎。測試庫包含Espresso,用于運(yùn)行功能UI測試的框架婚瓜。讓我們通過編輯build.gradle的相關(guān)部分來把它們添加進(jìn)我們的工程宝鼓。

build.gradle

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'

}

重要:由于一些依賴版本沖突,你需要確認(rèn)com.android.support:appcompat-v7庫的版本號(hào)是22.0.0巴刻,像上面的代碼片段一樣愚铡。

另外,Android Studio可能會(huì)提醒你Build Tools 22.0.1沒有安裝胡陪。你應(yīng)該接受修復(fù)建議茂附,Studio會(huì)為你安裝Build Tools或者在build.gradle中把這行修改成已經(jīng)安裝在你電腦的版本。

上面的工作完成后督弓,在Build Variants窗口內(nèi)切換成Android Instrumentation Tests,你的工程應(yīng)該自動(dòng)同步乒验。如果沒有愚隧,點(diǎn)擊Gradle sync按鈕。

7.為app添加簡單的交互

在使用Espresso進(jìn)行UI測試前,讓我們?yōu)閍pp添加一些Views和簡單的交互狂塘。我們使用一個(gè)用戶可以輸入名字的EditText录煤,歡迎用戶的Button和用于輸出的TextView。打開res/layout/activity_main.xml荞胡,粘貼如下代碼:

activity_main.xml

xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"

android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"

android:paddingRight="@dimen/activity_horizontal_margin"

android:paddingTop="@dimen/activity_vertical_margin"

android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

android:id="@+id/textView"

android:text="@string/hello_world" android:layout_width="wrap_content"

android:layout_height="wrap_content" />

android:hint="Enter your name here"

android:id="@+id/editText"

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:layout_below="@+id/textView"/>

android:layout_width="match_parent"

android:layout_height="wrap_content"

android:text="Say hello!"

android:layout_below="@+id/editText"

android:onClick="sayHello"/>

還需要在MainActivity.java中添加onClick handler:

MainActivity.java

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() + "!");

}

現(xiàn)在可以運(yùn)行app并確認(rèn)一切工作正常妈踊。在點(diǎn)擊Run按鈕之前,確認(rèn)你的Run Configuration沒有設(shè)置為運(yùn)行測試泪漂。如需更改廊营,點(diǎn)擊下拉選項(xiàng),選擇app萝勤。

8.創(chuàng)建并運(yùn)行Espresso測試

在工程的整體視圖上露筒,找到以(androidTest)后綴結(jié)尾的包名并創(chuàng)建一個(gè)新的Java類〉凶浚可以將它命名為MainActivityInstrumentationTest慎式,將如下代碼粘貼過去。

*** MainActivityInstrumentationTest.java*

package com.example.testing.testingexample;

import android.support.test.InstrumentationRegistry;

import android.support.test.espresso.action.ViewActions;

import android.support.test.rule.ActivityTestRule;

import android.support.test.runner.AndroidJUnit4;

import android.test.ActivityInstrumentationTestCase2;

import android.test.suitebuilder.annotation.LargeTest;

import org.junit.After;

import org.junit.Before;

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 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

}

}

測試類通過AndroidJUnitRunner運(yùn)行趟径,并執(zhí)行sayHello()方法瘪吏。下面將逐行解釋都做了什么:

1.首先,找到ID為editText的view蜗巧,輸入Peter掌眠,然后關(guān)閉鍵盤;

2.接下來惧蛹,點(diǎn)擊Say hello!的View扇救,我們沒有在布局的XML中為這個(gè)Button設(shè)置id,因此香嗓,通過搜索它上面的文字來找到它迅腔;

3.最后,將TextView上的文本同預(yù)期結(jié)果對(duì)比靠娱,如果一致則測試通過沧烈;

你也可以右鍵點(diǎn)擊域名運(yùn)行測試,選擇Run>MainActivityInstrume...(第二個(gè)帶Android圖標(biāo)的)

這樣就會(huì)在模擬器或者連接的設(shè)備上運(yùn)行測試像云,你可以在手機(jī)屏幕上看到被執(zhí)行的動(dòng)作(比如在EditText上打字)锌雀。最后會(huì)在Android Studio輸出通過和失敗的測試結(jié)果。

Github下載測試源碼

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末迅诬,一起剝皮案震驚了整個(gè)濱河市腋逆,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌侈贷,老刑警劉巖惩歉,帶你破解...
    沈念sama閱讀 221,820評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異,居然都是意外死亡撑蚌,警方通過查閱死者的電腦和手機(jī)上遥,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,648評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來争涌,“玉大人粉楚,你說我怎么就攤上這事×恋妫” “怎么了模软?”我有些...
    開封第一講書人閱讀 168,324評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長包警。 經(jīng)常有香客問我撵摆,道長,這世上最難降的妖魔是什么害晦? 我笑而不...
    開封第一講書人閱讀 59,714評(píng)論 1 297
  • 正文 為了忘掉前任特铝,我火速辦了婚禮,結(jié)果婚禮上壹瘟,老公的妹妹穿的比我還像新娘鲫剿。我一直安慰自己,他們只是感情好稻轨,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,724評(píng)論 6 397
  • 文/花漫 我一把揭開白布灵莲。 她就那樣靜靜地躺著,像睡著了一般殴俱。 火紅的嫁衣襯著肌膚如雪政冻。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,328評(píng)論 1 310
  • 那天线欲,我揣著相機(jī)與錄音明场,去河邊找鬼。 笑死李丰,一個(gè)胖子當(dāng)著我的面吹牛苦锨,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播趴泌,決...
    沈念sama閱讀 40,897評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼舟舒,長吁一口氣:“原來是場噩夢(mèng)啊……” “哼!你這毒婦竟也來了嗜憔?” 一聲冷哼從身側(cè)響起秃励,我...
    開封第一講書人閱讀 39,804評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎吉捶,沒想到半個(gè)月后莺治,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體廓鞠,經(jīng)...
    沈念sama閱讀 46,345評(píng)論 1 318
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,431評(píng)論 3 340
  • 正文 我和宋清朗相戀三年谣旁,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片滋早。...
    茶點(diǎn)故事閱讀 40,561評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡榄审,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出杆麸,到底是詐尸還是另有隱情搁进,我是刑警寧澤,帶...
    沈念sama閱讀 36,238評(píng)論 5 350
  • 正文 年R本政府宣布昔头,位于F島的核電站饼问,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏揭斧。R本人自食惡果不足惜莱革,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,928評(píng)論 3 334
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望讹开。 院中可真熱鬧盅视,春花似錦、人聲如沸旦万。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,417評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽成艘。三九已至赏半,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間淆两,已是汗流浹背断箫。 一陣腳步聲響...
    開封第一講書人閱讀 33,528評(píng)論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留琼腔,地道東北人瑰枫。 一個(gè)月前我還...
    沈念sama閱讀 48,983評(píng)論 3 376
  • 正文 我出身青樓,卻偏偏與公主長得像丹莲,于是被迫代替她去往敵國和親光坝。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,573評(píng)論 2 359

推薦閱讀更多精彩內(nèi)容

  • 本文章轉(zhuǎn)載于搜狗測試 本文轉(zhuǎn)自簡書甥材,是作者翻譯Google I/0 2015中關(guān)于測試的codelab盯另。 目錄 1...
    夜境閱讀 1,207評(píng)論 1 0
  • 本篇教程翻譯自Google I/O 2015中關(guān)于測試的codelab,掌握科學(xué)上網(wǎng)的同學(xué)請(qǐng)點(diǎn)擊這里閱讀:Unit...
    TestDevTalk閱讀 140,926評(píng)論 55 485
  • afinalAfinal是一個(gè)android的ioc洲赵,orm框架 https://github.com/yangf...
    passiontim閱讀 15,437評(píng)論 2 45
  • 遠(yuǎn)行的感覺鸳惯,熟悉而又陌生商蕴。 太久的駐足,在一個(gè)地方芝发,走動(dòng)绪商,便成了一件不易的事。其實(shí)辅鲸,我是一個(gè)喜愛閑逛的人格郁,但并不大...
    芳菲菲兮閱讀 463評(píng)論 14 41
  • 二十歲的朝氣是風(fēng) 拖起不扎實(shí)的雙腳 浮于空中 踏在這風(fēng)里 忘卻了初離家的惶恐 感受不到歸根的鄉(xiāng)愁 在這空中向下望 ...
    二胖小子閱讀 154評(píng)論 0 0