Android自動化測試框架Espresso(二)——測試Toast彈出內容
阿新 • • 發佈:2019-01-10
Android中的Toast是我們經常會使用的,能夠方便的在介面上彈出一個提示語句,還可以控制顯示的時長,十分方便。使用Espresso測試Toast的彈出內容不是很好操作,主要由於Toast的佈局並不是屬於我們當前應用的,而是通過另一個Sevice控制的,這個原理可以看看相關的一些博文,我這裡不再詳細說明。當時為了測試Toast是否顯示正確,也是查了不少文章,最後在Stack Overflow找到了解決的辦法,這裡給大家介紹一下,但是並不是很完美,後面會詳細說明。
我們採用TDD的模式做我們的簡單Demo,我們希望介面上有一個文字為點選的按鈕,點選該按鈕,會彈出一個文字為clicked的Toast,按照這個說明,編寫我們的測試程式碼(專案的Gradle配置見上一篇文章)
package com.yjp.toasttest; import android.support.test.rule.ActivityTestRule; import android.support.test.runner.AndroidJUnit4; import android.widget.Button; 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.assertion.ViewAssertions.matches; import static android.support.test.espresso.matcher.RootMatchers.withDecorView; import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; import static android.support.test.espresso.matcher.ViewMatchers.withText; import static org.hamcrest.Matchers.allOf; import static org.hamcrest.Matchers.instanceOf; import static org.hamcrest.Matchers.not; @RunWith(AndroidJUnit4.class) public class MainActivityTest { @Rule public ActivityTestRule<MainActivity> mActivityRule = new ActivityTestRule<>(MainActivity.class); @Test public void testClickButtonToast() throws Exception { //介面上有一個文字為點選的按鈕並點選按鈕 onView(allOf(withText(R.string.click), instanceOf(Button.class))) .check(matches(isDisplayed())) .perform(click()); //會彈出一個文字為clicked的Toast Thread.sleep(1000); onView(withText(R.string.clicked_en)) .inRoot(withDecorView(not(mActivityRule.getActivity().getWindow().getDecorView()))) .check(matches(isDisplayed())); } }
首先,我們使用withText和instanceOf兩個View Matcher選擇出了我們的Button,檢查該Button是否顯示,執行了click()操作(View Action)。然後我們sleep了1s,這個就是我上面提到的不太完美的地方,如果不加延時,可能Toast會檢測不到。休眠1s後,找到Toast的佈局,這裡通過withText找到對應的Toast的檢視,但這無法保證就是Toast,也有可能在我們的介面中會有其他的控制元件使用了clicked這個文字,所以,我們還需要保證我們找的Toast檢視不在主介面的DecorView中,這裡使用了withDecorView和not兩個Matcher。最後,通過check檢查是否顯示。
上面的程式碼中,我們將點選和clicked兩個文字定義為了兩個字串資源,可以看到withText可以直接傳遞字串資源。
<string name="click">點選</string>
<string name="clicked_en">clicked</string>
現在執行測試,會報錯,錯誤不貼了,意思就是找不到滿足條件的按鈕,畢竟我們的MainActivity還沒有完成。我們完成我們的佈局,新增一個按鈕,文字為點選(R.string.click)。
<?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="com.yjp.toasttest.MainActivity">
<Button
android:id="@+id/click_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/click"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.501" />
</android.support.constraint.ConstraintLayout>
佈局我只是基於專案自動生成的,修改TextView為Button,text設定為點選,我們再次執行測試,這次報錯變了,告訴我們找不到Toast的佈局。我們新增程式碼
package com.yjp.toasttest;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button clickButton = (Button) findViewById(R.id.click_button);
clickButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String toast = getString(R.string.clicked_en);
Toast.makeText(MainActivity.this, toast, Toast.LENGTH_SHORT).show();
}
});
}
}
再次執行測試,這次測試通過,說明為我們的程式碼已經滿足了需求的要求。