Android單元測試全解
自動化測試麻煩嗎?說實在,麻煩!有一定的學習成本。但是,自動化測試有以下優點:
- 節省時間:可以指定測試某一個activity,不需要一個個自己點
- 單元測試:既然Java可以進行單元測試,Android為什麼就不可以呢?
- 一鍵適配:不解釋
Android自動化測試框架主要有:Espresso、UI Automator以及Robolectric。滴滴~~ 開車開車!
1、Java單元測試
Android studio(以下簡稱as)可以跑純Java程式碼,這個想必大家都知道。這裡就簡單介紹一下as如何跑Java程式碼,作為熱身運動吧!
首先開啟測試包,在app->src->test目錄下,如下圖所示,其中AndroidTest包是針對Android工作的測試,先不管他。
這裡as為我們建立了一個測試類,直接開啟,as中採用Junit4的測試包,主要程式碼如下。
@RunWith(JUnit4.class)
public class ExampleUnitTest {
@Before
public void before(){
//在測試前的工作
}
@After
public void after()
{
// 測試完成後的工作
}
@Test
public void addition_isCorrect() {
//主要工作
}
}
這就是最簡單的Java測試,預熱完畢,接下來進入本文的主角
2、Android單元測試——Espresso
AndroidJUnitRunner類是一個JUnit測試執行器,它允許您在Android裝置上執行JUnit 3或JUnit 4樣式測試類,包括使用Espresso和UI Automator測試框架的測試類。
測試執行器與您的JUnit 3和JUnit 4(高達JUnit 4.10)測試相容。 但是,您應該避免將JUnit 3和JUnit 4測試程式碼混合在同一個包中,因為這可能會導致意外的結果。 如果您正在建立一個測試JUnit 4測試類以在裝置或模擬器上執行,那麼您的測試類必須以@RunWith(AndroidJUnit4.class)註釋為字首。
先看應用程式的模組級build.gradle依賴:
dependencies {
androidTestCompile 'com.android.support:support-annotations:25.4.0'
androidTestCompile 'com.android.support.test:runner:1.0.0'
androidTestCompile 'com.android.support.test:rules:1.0.0'
androidTestCompile 'com.android.support.test.espresso:espresso-core:3.0.2'
}
android {
defaultConfig {
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
}
如果依賴衝突,請加入以下程式碼:
androidTestImplementation('com.android.support.test.espresso:espresso-core:3.0.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
2.1獲取application
最常見的應用案例就是,在進行網路測試的時候,如果您的專案很大,編譯的時間很長,那麼單單為看一個請求結果就要花費相當長的時間,這是不能容忍的,我們可以通過Android的單元測試來模擬請求,如下程式碼所示。
@RunWith(AndroidJUnit4.class)
public class ExampleInstrumentedTest {
@Before
public void init() {
Context appContext = InstrumentationRegistry.getTargetContext();
x.Ext.init((Application) appContext.getApplicationContext());
}
@Test
public void useAppContext() {
// Context of the app under test.
RequestParams requestParams = new RequestParams("https://www.baidu.com/");
String str = x.http().getSync(requestParams, String.class);
System.out.println("\n"+str+"\n");
}
}
通過InstrumentationRegistry,我們就可以獲取到context物件,再通過context就可以獲取application物件,之後就可以構建一個網路請求,請注意,在測試方法中,必須使用同步請求,否則測試用例會直接忽略回撥方法,直接結束程式,導致無法獲取到請求結果。
Android單元測試分為:小型測試、中型測試,大型測試,他們的區別如下。
- 小型測試(SmallTest):與系統隔離執行,執行時間較短,最長執行時間為200ms
- 中型測試(MediumTest):集成了多個元件,並可以在模擬器或者真機上執行,最長執行時間為1000ms
- 大型測試(LargeTest):可以執行UI流程的測試工作,確保APP按照預期在模擬器或實際裝置上工作。最長執行時間為1000ms
在Android單元測試中可以使用斷言來判斷變數值是否符合預期,常用的有assertThat、assertEquals、assertNotSame等
2.2獲取對應元件
該框架提供ActivityTestRule來管理被測試的activity,例如MainActivity對應的佈局檔案如下
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<EditText
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text=""
android:id="@+id/main_text"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>
MainActivity的程式碼這裡就不貼出來了,直接看測試程式碼:
@RunWith(AndroidJUnit4.class)
@LargeTest
public class MainTest {
@Rule
public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(
MainActivity.class);
@Test
public void Run() {
onView(withId(R.id.main_text)).perform(
typeText("Hello MainActivity!"), closeSoftKeyboard());
}
}
這裡簡單說明一下:
- withId(R.id.main_text):通過ID找到對應的元件,並將其封裝成一個Matcher
- onView():將視窗焦點給某個元件,並返回ViewInteraction例項
- perform():該元件需要執行的任務,傳入ViewAction的例項,可以有多個,意味著使用者的多種操作
- typeText():輸入字串任務,還有replaceText方法也可以實現類似的效果,不過沒有輸入動畫
- closeSoftKeyboard():關閉軟鍵盤
以上就是最基本的自動化測試程式碼。點選Run方法邊上的執行按鈕,直接執行在裝置上即可,效果如下所示。
類似的還有點選事件:
onView(withId(R.id.main_text)).perform(click());
雙擊事件:
onView(withId(R.id.main_text)).perform(doubleClick());
判斷是否符合預期
onView(withId(R.id.main_text)).check(matches(withText("Hello MainActivity!")));
2.3模擬listView的點選事件
以上是針對唯一ID的事件,那麼如果有多個元件的ID是一樣的呢?例如模擬 listView的item點選事件,是如何區分每一個item呢?先看如何處理多個元件ID相同的情況。
大家知道可以通過ID來查詢對應的檢視,這裡也可以通過顯示的文字來查詢檢視:
onView(withText("Hello MainActivity!"));
那麼,如果通過ID和顯示的文字不就可以定位唯一的檢視了嗎?如下
onView(allOf(withId(R.id.main_text), withText("Hello MainActivity!")));
或者這樣來篩選不匹配的檢視
onView(allOf(withId(R.id.button_signin), not(withText("Sign-out"))));
接下來看如何模擬listview(GridView和Spinner均適用)的點選事件
我們先建立一個SecondActivity
public class ListActivity extends AppCompatActivity {
private ListView listView ;
private List<HashMap<String ,String>> data = new ArrayList<>();
public static final String KEY = "key";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_second);
listView = findViewById(R.id.list_view);
initDate();
listView.setAdapter(new SimpleAdapter(this,data,
R.layout.item_list,
new String[]{KEY},
new int[]{R.id.item_list_text}));
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Toast.makeText(ListActivity.this,data.get(position).get(KEY),Toast.LENGTH_LONG).show();
}
});
}
private void initDate() {
for(int i =0 ;i < 90 ;i++){
HashMap<String,String> map = new HashMap<>();
map.put(KEY,"第"+(1+i)+"列");
data.add(map);
}
}
}
對應的佈局檔案就是一個listView,item對應的佈局是一個textView,這裡就不貼出來了,主要看測試類:
@RunWith(AndroidJUnit4.class)
@LargeTest
public class ListViewTest {
private static final String TAG = "ListViewTest ";
@Rule
public ActivityTestRule<ListActivity> mActivityRule = new ActivityTestRule<>(
ListActivity.class);
@Before
public void init() {
mActivityRule.getActivity();
}
@Test
public void Run() {
onData(allOf(is(instanceOf(Map.class)),
hasEntry(equalTo(ListActivity.KEY), is("第10列")))).perform(click());
}
}
這裡選擇資料為第10行的item,並執行點選動作,這裡著重講一下hasEntry() 這個方法,該方法需要傳兩個Matcher,也就是map的鍵名和對應的值。通過map的鍵、值來唯一確定一個item,拿到對應的item就可以類似於檢視一樣去執行動作了,效果如下。
動畫比較快,但是可以看到listview先是滾到第10行,然後才執行點選事件,這是因為Espresso負責滾動目標元素,並將元素放在焦點上。
有同學馬上就提出了,recycleView才是主流,用listview的很少了~~,沒事,我們來看如何進行recycleView的自動化測試
2.4模擬recycleView點選事件
對recyclerView進行自動化測試需要再新增以下依賴,注意,是在之前的依賴基礎上新增以下程式碼。
androidTestCompile 'com.android.support.test.espresso:espresso-contrib:3.0.0'
androidTestCompile 'com.android.support:recyclerview-v7:25.4.0'
我們建立一個RecyclerActivity,內容如下:
public class RecyclerActivity extends AppCompatActivity {
private RecyclerView recyclerView;
private RecyclerAdapter<String> adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_recycler);
recyclerView = findViewById(R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new RecyclerAdapter<>(this, R.layout.item_list);
recyclerView.setAdapter(adapter);
List<String> list = new ArrayList<>();
for(int i =0 ;i < 50 ;i++){
list.add("第"+(1+i)+"列");
}
adapter.setData(list);
}
}
對應的佈局檔案就是一個recyclerview,item的佈局只有一個textView,這裡也就不貼出來了,adapter也很簡單,給textView一個點選事件,如下:
public class RecyclerAdapter<T> extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private List<T> data = new ArrayList<>();
private Context context ;
private int layout;
public RecyclerAdapter(Context context, int layout) {
this.context = context;
this.layout = layout;
}
public void setData(List<T> data) {
this.data.clear();
this.data.addAll(data);
notifyDataSetChanged();
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
return new Holder(LayoutInflater.from(context)
.inflate(layout,null,false));
}
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
Holder holder1 = (Holder) holder;
holder1.textView.setText(data.get(position).toString());
holder1.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Toast.makeText(context,data.get(position).toString(),Toast.LENGTH_LONG).show();
}
});
}
@Override
public int getItemCount() {
return data.size();
}
private class Holder extends RecyclerView.ViewHolder{
TextView textView ;
public Holder(View itemView) {
super(itemView);
textView = itemView.findViewById(R.id.item_list_text);
}
}
}
接下來看測試類:
@RunWith(AndroidJUnit4.class)
@LargeTest
public class RecycleViewTest {
private static final String TAG = "ExampleInstrumentedTest";
@Rule
public ActivityTestRule<RecyclerActivity> mActivityRule = new ActivityTestRule<>(
RecyclerActivity.class);
@Test
public void Run() {
onView(ViewMatchers.withId(R.id.recycler_view))
.perform(RecyclerViewActions.actionOnItemAtPosition(10, click()));
}
}
在run方法中我們可以看到基本與之前的類似,不同的是需要通過RecyclerViewActions類提供的API來執行任務,其中actionOnItemAtPosition的第一個引數是recycleview的item位置,第二個引數是對應的動作,效果與listView的一致,這裡就不貼了。
這裡可以看出,recycleview的測試類要優於listView,listView通過item的值來查詢對應的item,而recycleview直接通過位置來查詢
2.5 模擬使用者點選actionbar
新建一個MenuActivity,主要程式碼如下
public class MenuActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_menu);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.menu_test, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
Toast.makeText(this,item.getTitle(),Toast.LENGTH_SHORT).show();
return super.onOptionsItemSelected(item);
}
}
menu佈局程式碼如下:
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android1="http://schemas.android.com/apk/res-auto">
<item
android:id="@+id/nav_1"
android:title="item1"
android1:showAsAction="never" />
<item
android:id="@+id/nav_2"
android:title="item2"
android1:showAsAction="never" />
</menu>
測試程式碼如下:
@RunWith(AndroidJUnit4.class)
@LargeTest
public class MenuTest {
@Rule
public ActivityTestRule<MenuActivity> mActivityRule = new ActivityTestRule<>(
MenuActivity.class);
@Test
public void test(){
//開啟menu
openContextualActionModeOverflowMenu();
//模擬點選item2
onView(withText("item2"))
.perform(click());
}
}
效果如下:
3、Android單元測試——Robolectric
如果您的應用的測試環境需要單元測試與Android框架進行更廣泛的互動,則可以使用Robolectric。 該工具可讓您在工作站上或常規JVM中的持續整合環境中執行測試,而無需模擬器,幾乎與Android裝置執行測試的完全保真度相匹配,但仍比執行裝置測試更快,支援Android平臺的以下幾個方面。
- Android4.1以及更高
- Android Gradle 外掛2.4以及更高
- 元件生命週期
- 事件迴圈
- 所有資源:SDK, Resources, Native Method
grade配置:
testImplementation "org.robolectric:robolectric:3.8"
android {
testOptions {
unitTests {
includeAndroidResources = true
}
}
}
基本用法如下所示。
@RunWith(RobolectricTestRunner.class)
public class MyActivityTest {
@Test
public void clickingButton_shouldChangeResultsViewText() throws Exception {
MyActivity activity = Robolectric.setupActivity(MyActivity.class);
Button button = (Button) activity.findViewById(R.id.button);
TextView results = (TextView) activity.findViewById(R.id.results);
button.performClick();
assertThat(results.getText().toString()).isEqualTo("Robolectric Rocks!");
}
}
4、Android測試——UI Automator
先配置依賴
dependencies {
androidTestCompile 'com.android.support:support-annotations:25.4.0'
androidTestCompile 'com.android.support.test:runner:1.0.0'
androidTestImplementation 'com.android.support.test.uiautomator:uiautomator-v18:2.1.3'
androidTestCompile 'org.hamcrest:hamcrest-integration:1.3'
}
注意,UI Automator最低支援Android 4.3 (API level 18)
在MainActivity中有四個元件editText、textView和button,佈局就不貼出來了,在MainActivity的Java程式碼中主要是點選方法中,如下:
@Override
public void onClick(View view) {
// Get the text from the EditText view.
final String text = mEditText.getText().toString();
final int changeTextBtId = R.id.changeTextBt;
final int activityChangeTextBtnId = R.id.activityChangeTextBtn;
if (view.getId() == changeTextBtId) {
//將edit中的text內容顯示到textView中
mTextView.setText(text);
} else if (view.getId() == activityChangeTextBtnId) {
//啟動新的activity,並將text傳給新的activity顯示
Intent intent = ShowTextActivity.newStartIntent(this, text);
startActivity(intent);
}
}
主要看測試程式碼,這裡建立一個ChangeTextBehaviorTest測試類:
@RunWith(AndroidJUnit4.class)
@SdkSuppress(minSdkVersion = 18)
public class ChangeTextBehaviorTest {
private static final String BASIC_SAMPLE_PACKAGE
= "com.example.android.testing.uiautomator.BasicSample";
private static final int LAUNCH_TIMEOUT = 5000;
private static final String STRING_TO_BE_TYPED = "UiAutomator";
private UiDevice mDevice;
@Before
public void startMainActivityFromHomeScreen() {
// 獲取UiDevice的例項
mDevice = UiDevice.getInstance(InstrumentationRegistry.getInstrumentation());
// 模擬使用者點選home鍵
mDevice.pressHome();
//獲取要載入的包名
final String launcherPackage = getLauncherPackageName();
//判斷是否為空
assertThat(launcherPackage, notNullValue());
//等待目標包 的資訊
mDevice.wait(Until.hasObject(By.pkg(launcherPackage).depth(0)), LAUNCH_TIMEOUT);
// 啟動目標activity,也就是MainActivity
Context context = InstrumentationRegistry.getContext();
final Intent intent = context.getPackageManager()
.getLaunchIntentForPackage(BASIC_SAMPLE_PACKAGE);
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); // Clear out any previous instances
context.startActivity(intent);
// Wait for the app to appear
mDevice.wait(Until.hasObject(By.pkg(BASIC_SAMPLE_PACKAGE).depth(0)), LAUNCH_TIMEOUT);
}
@Test
public void testChangeText_sameActivity() {
//將 STRING_TO_BE_TYPED 內容填充到edittext中
mDevice.findObject(By.res(BASIC_SAMPLE_PACKAGE, "editTextUserInput"))
.setText(STRING_TO_BE_TYPED);
//給ID為changeTextBt 的元件模擬使用者的點選事件
mDevice.findObject(By.res(BASIC_SAMPLE_PACKAGE, "changeTextBt"))
.click();
// 等待獲取MainActivity中ID為textToBeChanged的textView的內容,等待時間為500ms
UiObject2 changedText = mDevice
.wait(Until.findObject(By.res(BASIC_SAMPLE_PACKAGE, "textToBeChanged")),
500 /* wait 500ms */);
//判斷是否正確
assertThat(changedText.getText(), is(equalTo(STRING_TO_BE_TYPED)));
}
@Test
public void testChangeText_newActivity() {
// 同上
mDevice.findObject(By.res(BASIC_SAMPLE_PACKAGE, "editTextUserInput"))
.setText(STRING_TO_BE_TYPED);
mDevice.findObject(By.res(BASIC_SAMPLE_PACKAGE, "activityChangeTextBtn"))
.click();
// Verify the test is displayed in the Ui
UiObject2 changedText = mDevice
.wait(Until.findObject(By.res(BASIC_SAMPLE_PACKAGE, "show_text_view")),
500 /* wait 500ms */);
assertThat(changedText.getText(), is(equalTo(STRING_TO_BE_TYPED)));
}
/**
* 獲取包名
*/
private String getLauncherPackageName() {
// Create launcher Intent
final Intent intent = new Intent(Intent.ACTION_MAIN);
intent.addCategory(Intent.CATEGORY_HOME);
// Use PackageManager to get the launcher package name
PackageManager pm = InstrumentationRegistry.getContext().getPackageManager();
ResolveInfo resolveInfo = pm.resolveActivity(intent, PackageManager.MATCH_DEFAULT_ONLY);
return resolveInfo.activityInfo.packageName;
}
}
該框架的邏輯是模擬使用者在使用APP的過程,這個測試用例的主要流程是:使用者在桌面點選目標APP,進去,輸入字串,使用者點選activityChangeTextBtn元件,跳轉到ShowTextActivity,並傳入內容,讓其顯示出來。然後點選changeTextBt元件,顯示使用者輸入內容;
效果如下
該測試類有三個方法,其中在測試前需要獲取 UiDevice的例項,步驟如下:
- 通過呼叫getInstance()方法並將Instrumentation物件作為引數傳遞,獲取UiDevice物件以訪問要測試的裝置。
- 通過呼叫UiDevice例項的findObject()方法,獲取UiObject物件以訪問裝置上顯示的UI元件(例如,前景中的當前檢視)。
- 可以通過呼叫UiObject方法模擬要在該UI元件上執行的特定使用者互動;例如,呼叫performMultiPointerGesture()來模擬多點觸控手勢,呼叫setText()來編輯文字欄位。
- 在執行這些使用者互動之後,檢查UI是否反映了預期的狀態或行為。
顯然該框架需要從MainActivity開始,整個的模擬使用者使用過程,好處是不會繫結特定的activity,資源具有全域性性。原始碼見GitHub
當然,也可以通過以下的方式拿到對應的元件:
UiObject okButton = mDevice.findObject(new UiSelector()
.text("OK")
.className("android.widget.Button"));
// Simulate a user-click on the OK button, if found.
if(okButton.exists() && okButton.isEnabled()) {
okButton.click();
}
如果要訪問應用程式中的特定UI元件,請使用UiSelector類。 此類表示當前顯示的UI中特定元素的查詢。
如果找到多個匹配元素,則佈局層次結構中的第一個匹配元素將作為目標UiObject返回。 構建UiSelector時,可以將多個屬性連結在一起以優化搜尋。 如果未找到匹配的UI元素,則丟擲UiAutomatorObjectNotFoundException。
我們可以使用childSelector()方法巢狀多個UiSelector例項。 例如,以下程式碼示例顯示了測試如何指定搜尋以在當前顯示的UI中查詢第一個ListView,然後在該ListView中搜索以查詢具有文字屬性Apps的UI元素
UiObject appItem = new UiObject(new UiSelector()
.className("android.widget.ListView")
.instance(0)
.childSelector(new UiSelector()
.text("Apps")));
一旦您的測試獲得了UiObject物件,您就可以呼叫UiObject類中的方法來對該物件所表示的UI元件執行使用者互動。您可以指定以下操作:
- click():單擊UI元素可見邊界的中心。
- dragTo():將此物件拖動到任意座標。
- setText():在清除欄位內容後,在可編輯欄位中設定文字。相反,clearTextField()方法清除可編輯欄位中的現有文字。
- swipeUp():對UiObject執行向上滑動操作。類似地,swipeDown(),swipeLeft()和swipeRight()方法執行相應的操作。
如果測試FrameLayout內容,則需要構建UiCollection,例如以下程式碼:
UiCollection videos = new UiCollection(new UiSelector()
.className("android.widget.FrameLayout"));
// 檢索此集合中的視訊數量
int count = videos.getChildCount(new UiSelector()
.className("android.widget.LinearLayout"));
// 查詢特定視訊並模擬使用者單擊它
UiObject video = videos.getChildByText(new UiSelector()
.className("android.widget.LinearLayout"), "Cute Baby Laughing");
video.click();
// 模擬選擇與視訊關聯的複選框
UiObject checkBox = video.getChild(new UiSelector()
.className("android.widget.Checkbox"));
if(!checkBox.isSelected()) checkbox.click();
對於可滑動檢視,可以使用UiScrollable類模擬顯示屏上的垂直或水平滾動。 當UI元素位於螢幕外並且您需要滾動以將其置於檢視中時,此技術很有用。
以下程式碼段顯示瞭如何模擬向下滾動“設定”選單並單擊“關於”平板電腦選項
UiScrollable settingsItem = new UiScrollable(new UiSelector()
.className("android.widget.ListView"));
UiObject about = settingsItem.getChildByText(new UiSelector()
.className("android.widget.LinearLayout"), "About tablet");
about.click();
5、總結
舒服!終於把爛尾的文章寫完了~~附上程式碼連結
相關推薦
Android單元測試全解
自動化測試麻煩嗎?說實在,麻煩!有一定的學習成本。但是,自動化測試有以下優點: 節省時間:可以指定測試某一個activity,不需要一個個自己點 單元測試:既然Java可以進行單元測試,Android為什麼就不可以呢? 一鍵適配:不解釋 Androi
通過JUnit進行Android單元測試
2個 nvi frame oncreate protected [] 命令 lib 是我 要了解android單元測試,首先必須了解junit 什麽是 JUnit ? JUnit是采用測試驅動開發的方式,也就是說在開發前先寫好測試代碼,主要用來說明被測試的代碼會被如
太白---落燕紛飛第一重 Android單元測試Instrumentation和irobotium
tom 先來 otto 重現 size sim 個人 思想 pack PS:叫太白---落燕紛飛純粹好玩(天涯明月遊戲畫面感,打擊感,碰撞盡管做的不盡人意,可是太白這個職業還是不錯,用作開頭,,做個旁白而已)。 這裏的單元測試不管是instrumenta
android單元測試框架Mockito使用
null 修改 分享 log hone 技術 pro 我們 ext 單元測試,早些年時常聽到這個概念,真的有去做的確實少,基本都是自己功能上的測試,開發完測試跑一邊沒啥問題就發布了。這幾天花了點心思看了下MockIto框架,記錄博文。 MockIto官網文檔在https:
Android單元測試實踐
為什麼要引入單元測試 一般來說我們都不會寫單元測試,為什麼呢?因為要寫多餘的程式碼,而且還要進行一些學習,入門有些門檻,所以一般在工程中都不會寫單元測試。那麼為什麼我決定要寫單元測試。因為兩個條件 我很懶:我每次改完都很懶測試 我很慫:我要是不測試,沒有一次通過的信心,於是我還
深入淺出Android單元測試(一):單元測試基礎
想學習單元測試無從下手,本文對以最易懂的方式介紹單元測試。 若有錯漏,煩請斧正。轉載請註明出處。歡迎關注程式引力 作者:程式引力 | 謝一 (Evan Xie) 郵箱:[email protected] 軟體測試作為軟體質量的保障,有著十分重要的意義。按照不同
android 單元測試cmd 命令集
對app進行單元測試時,或使用robotium進行黑盒測試時,需要把測試apk安裝到模擬器或者android真機上,然後用命令去驅動測試 1.執行測試程式命令-執行測試工程中所有test方法: >adb shell am instrument -w 測試程式packageName/an
Android單元測試(一):JUnit框架的使用
1.前言 網上有許多關於單元測試的好處,這裡我就不去說了。我寫單元測試的理由很簡單粗暴,就是圖一個方便。試想一下這個場景:我們在寫一個新功能,每寫一部分,我們就安裝到手機上檢視一下,這個過程中你要點選到對應的頁面,做對應的操作,最後才能反饋給你結果。如果達到了預
Android單元測試(五):網路介面測試
溫馨提示:如果你不太熟悉單元測試,可以先看下之前四篇基礎框架使用。便於你更好的理解下面的內容。 在平日的開發中,我們用後臺寫好給我們介面去獲取資料。雖然我們有一些請求介面的工具,可以快速的拿到返回資料。但是在一些異常情況的處理上就不太方便了。我列出以下
Android單元測試(6):使用dagger2來做依賴注入
注: 1. 程式碼中的 //<= 表示新加的、修改的等需要重點關注的程式碼 2. Class#method表示一個類的instance method,比如 LoginPresenter#login 表示 LoginPresenter的login(非靜態)方法。 問題
蘑菇街支付金融Android單元測試實踐
本文為『移動前線』群在4月23日的分享總結整理而成,轉載請註明來自『移動開發前線』公眾號。 嘉賓介紹 鄒勇(網名小創)蘑菇街支付金融資深安卓開發工程師。自畢業以來一直從事Android開發工作,先後工作於創新工廠、微策略以及蘑菇街。對單元測試和TDD情有獨鍾。
Android單元測試中AndroidJUnit4獲取context
在AndroidJUnit4直接通過getContext()獲取到的context並不是當前APP的context,而是instrumentation的context,應使用以下方法來獲取context。 InstrumentationRegistry.getInstrum
android 單元測試脫坑
說明 本文描述的是Junit4,筆者是android 兩年的搬運工,寫專案很少寫單元測試。 但有時候測一段邏輯或者網路請求需要把工程跑一遍,再操作一遍。 接觸單元測試才認識到它的強大,它能省去很多麻煩和時間。 我們雖然不是測試,也應該知道怎麼去簡單使用它
Android單元測試:使用本地資料測試Retrofit
簡述 在日常專案開發中,基本沒有什麼機會用到Kotlin,幾個月前學習的語法,基本上都忘光了,於是自己強迫自己在寫Demo中使用Kotlin,同時,在目前開發的專案中開了一個測試分支,用來補全之前沒有寫的測試程式碼。 筆者的Android單元測試相關係列
二.Android單元測試 Mockito的更多用法
相對於上篇文章,這篇介紹了更多mockito的用法,對照著MeetingPresenterImp.java和MeetingPresenterImpTest.java大家可以看看Android單元測試用例怎麼寫. public class MeetingP
Android單元測試(九):查漏補缺篇
最近抽時間檢查了一下年前有關單元測試的八篇部落格,查漏補缺了一下。後面如果有更多關於單元測試的心得收穫,也會繼續補充。 1.AssertJ 在Android單元測試(一):JUnit框架的使用中,我們介紹瞭如何使用JUnit來進行斷言。不多說實話
安卓開發-尺寸單位+Logcat的使用+Android單元測試+安卓系統中資料的讀寫
知識檢視: 《一:尺寸單位》 1.px:電腦 電視上的解析度的尺寸單位。畫素是構成數碼影像的基本單元。例如300x300解析度,即表示水平方向與垂直方向上每英寸長度上的像 素數都是300,也
springboot單元測試詳解和實戰
單元測試是檢測程式碼嚴密性的最好方式,不僅能減少和預防bug的產生,還能自己二次檢查程式碼或者考慮review必要,如果你還沒有養成這個習慣,可要開始關注了。 上節以 springboot快速實戰搭建篇 快速入門,本節主要講述單元測試使用以及多環境配置 maven依賴
Android單元測試初探——JunitTest
學習Android有一段時間了,雖然前段時間對軟體測試有了一些瞭解,不過接觸android的單元測試卻是頭一次。這幾天在物流大賽上也用了不少時間,所以對於android的單元測試沒有太深入的研究,所以先寫個基本入門吧! 首先,我們來了解一下android的測試類的層次結構: 可以看
Spring Boot 單元測試詳解+實戰教程
Spring Boot 的測試類庫 Spring Boot 提供了許多實用工具和註解來幫助測試應用程式,主要包括以下兩個模組。 spring-boot-test:支援測試的核心內容。 spring-boot-test-autoconfigure:支援測試的