1. 程式人生 > >Android單元測試全解

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:支援測試的