在android浓咖啡检查吐司消息

Hum*_*ana 65 android toast android-espresso

有谁知道如何在android浓缩咖啡中测试Toast消息的外观?在机器人中它很容易和我使用,但开始在浓缩咖啡工作,但没有得到确切的命令.

kow*_*cj0 107

这个稍长的陈述对我有用:

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.is;
import static org.hamcrest.Matchers.not;
....
onView(withText(R.string.TOAST_STRING)).inRoot(withDecorView(not(is(getActivity().getWindow().getDecorView())))).check(matches(isDisplayed()));
Run Code Online (Sandbox Code Playgroud)

  • 使用ActivityTestRule:`onView(withText(R.string.toast_text)).inRoot(withDecorView(not(mActivityRule.getActivity().getWindow().getDecorView()))).check(matches(isDisplayed()));` (23认同)
  • @John:您可能正在使用带有`ActivityTestRule`的新[基于JUnit规则的测试](https://code.google.com/p/android-test-kit/wiki/JUnit4RulesInATSL).您可以使用[`ActivityTestRule#getActivity()`](https://android-test-kit.googlecode.com/git/docs/android-support-test-javadocs-0.2/reference/android)从该规则获取活动/support/test/rule/ActivityTestRule.html#getActivity()). (8认同)
  • `is()`方法是多余的 (6认同)
  • @Slava是正确的,它可以通过删除is:onView(withText(R.string.TOAST_STRING)).inRoot(withDecorView(not(getActivity().getWindow().getDecorView()))).check(匹配(被展示())); (5认同)
  • 获取无法解析方法getActivity()错误如何解决这个问题 (4认同)
  • @Brontes:请注意:当使用“targetSdkVersion 30”和“compileSdkVersion 30”时,此方法(以及大多数其他答案)不适用于 Android 11 API 30。请参阅:https://github.com/android/android-test/issues/803 (3认同)
  • 我正在使用 ActivityScenario.launch(MainActivity::class.java) 启动我的活动。我如何获得“getActivity()”? (2认同)
  • 还有其他人在 Android 11 上测试 toast 时遇到问题吗?我就是无法让它发挥作用。但在低版本上却可以完美运行。 (2认同)

Tho*_* R. 45

接受的答案是好的,但对我不起作用.所以我搜索了一下,发现了这篇博客文章.这让我知道如何做到这一点,我更新了上面的解决方案.

首先我实现了Toa​​stMatcher:

import android.os.IBinder;
import android.support.test.espresso.Root;
import android.view.WindowManager;
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;

public class ToastMatcher extends TypeSafeMatcher<Root> {

  @Override
  public void describeTo(Description description) {
    description.appendText("is toast");
  }

  @Override
  public boolean matchesSafely(Root root) {
    int type = root.getWindowLayoutParams().get().type;
    if (type == WindowManager.LayoutParams.TYPE_TOAST) {
        IBinder windowToken = root.getDecorView().getWindowToken();
        IBinder appToken = root.getDecorView().getApplicationWindowToken();
        if (windowToken == appToken) {
            // windowToken == appToken means this window isn't contained by any other windows.
            // if it was a window for an activity, it would have TYPE_BASE_APPLICATION.
            return true;
        }
    }
    return false;
  }

}
Run Code Online (Sandbox Code Playgroud)

然后我实现了我的检查方法:

public void isToastMessageDisplayed(int textId) {
    onView(withText(textId)).inRoot(MobileViewMatchers.isToast()).check(matches(isDisplayed()));
}
Run Code Online (Sandbox Code Playgroud)

MobileViewMatchers是用于访问匹配器的容器.在那里我定义了静态方法isToast().

public static Matcher<Root> isToast() {
    return new ToastMatcher();
}
Run Code Online (Sandbox Code Playgroud)

这对我来说就像一个魅力.

  • 在 API 30 (Android 11) 之前,这个解决方案对我来说一直很有效。尽管我可以在屏幕上看到吐司,但这段代码并没有捕捉到它。我已经完全不再验证吐司了;值得庆幸的是,它们对我的申请并不重要。 (4认同)
  • 这对我不起作用,因为测试不断循环。唯一有效的是,如果我在吐司打开时触摸屏幕,它似乎会停止空闲,然后就会工作。有任何想法吗? (2认同)
  • “ MobileViewMatchers”来自哪里?无法将其导入或在代码中找到 (2认同)
  • WindowManager.LayoutParams.TYPE_TOAST 现已弃用。 (2认同)
  • 只有当屏幕上出现toast时,我才能使用此代码验证Toast消息.但如果存在以下结果的条件:a)msg1 b)msg2 c)根本没有吐司.然后验证选项a和b,但代码卡在选项c中.什么是可能的解决方案? (2认同)

lmi*_*asf 12

首先确保导入:

import static android.support.test.espresso.Espresso.onView;
import static android.support.test.espresso.matcher.ViewMatchers.withText;
import static android.support.test.espresso.matcher.RootMatchers.withDecorView;
import static android.support.test.espresso.assertion.ViewAssertions.matches;
Run Code Online (Sandbox Code Playgroud)

在课堂上你可能有这样的规则:

@Rule
public ActivityTestRule<MyNameActivity> activityTestRule =
            new ActivityTestRule<>(MyNameActivity.class);
Run Code Online (Sandbox Code Playgroud)

在测试中:

MyNameActivity activity = activityTestRule.getActivity();
onView(withText(R.string.toast_text)).
    inRoot(withDecorView(not(is(activity.getWindow().getDecorView())))).
    check(matches(isDisplayed()));
Run Code Online (Sandbox Code Playgroud)

这对我有用,而且很容易使用.

  • 请注意:当使用“targetSdkVersion 30”和“compileSdkVersion 30”时,此方法(以及大多数其他答案)不适用于 Android 11 API 30。请参阅:https://github.com/android/android-test/issues/803 (4认同)

Akb*_*SSS 12

如果您使用的是Jetpack最新的Android 测试工具,您知道,它已被弃用,您应该使用or (其中包含第一个)。ActivityTestRuleActivityScenarioActivityScenarioRule

先决条件。创建decorView变量并在测试前赋值;

@Rule
public ActivityScenarioRule<FeedActivity> activityScenarioRule = new ActivityScenarioRule<>(FeedActivity.class);

private View decorView;

@Before
public void setUp() {
    activityScenarioRule.getScenario().onActivity(new ActivityScenario.ActivityAction<FeedActivity>() {
        @Override
        public void perform(FeedActivityactivity) {
            decorView = activity.getWindow().getDecorView();
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

测试自己

@Test
public void given_when_thenShouldShowToast() {
    String expectedWarning = getApplicationContext().getString(R.string.error_empty_list);
    onView(withId(R.id.button))
            .perform(click());

    onView(withText(expectedWarning))
            .inRoot(withDecorView(not(decorView)))// Here we use decorView
            .check(matches(isDisplayed()));
}
Run Code Online (Sandbox Code Playgroud)

getApplicationContext()可以取自androidx.test.core.app.ApplicationProvider.getApplicationContext;


anu*_*ain 8

首先创建一个我们可以在我们的测试用例中使用的 cutom Toast Matcher -

public class ToastMatcher extends TypeSafeMatcher<Root> {
    
        @Override    public void describeTo(Description description) {
            description.appendText("is toast");
        }
    
        @Override    public boolean matchesSafely(Root root) {
            int type = root.getWindowLayoutParams().get().type;
            if ((type == WindowManager.LayoutParams.TYPE_TOAST)) {
                IBinder windowToken = root.getDecorView().getWindowToken();
                IBinder appToken = root.getDecorView().getApplicationWindowToken();
                if (windowToken == appToken) {
                  //means this window isn't contained by any other windows. 
                  return true;
                }
            }
            return false;
        }
}
Run Code Online (Sandbox Code Playgroud)

1.测试是否显示Toast消息

onView(withText(R.string.mssage)).inRoot(new ToastMatcher())
.check(matches(isDisplayed()));
Run Code Online (Sandbox Code Playgroud)

2.测试是否不显示Toast消息

onView(withText(R.string.mssage)).inRoot(new ToastMatcher())
.check(matches(not(isDisplayed())));
Run Code Online (Sandbox Code Playgroud)

3. 测试 id Toast 包含特定的文本消息

onView(withText(R.string.mssage)).inRoot(new ToastMatcher())
.check(matches(withText("Invalid Name"));
Run Code Online (Sandbox Code Playgroud)

谢谢,阿努贾

注意 - 这个答案来自这个帖子。


yas*_*asd 5

尽管问题的答案是可以接受的-BTW对我不起作用-我想在Kotlin中添加我的解决方案,该解决方案是我从Thomas R.的答案中得出的:

package somepkg

import android.support.test.espresso.Espresso.onView
import android.support.test.espresso.Root
import android.support.test.espresso.matcher.ViewMatchers.withText
import android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
import android.view.WindowManager.LayoutParams.TYPE_TOAST
import org.hamcrest.Description
import org.hamcrest.Matcher
import org.hamcrest.TypeSafeMatcher

/**
 * This class allows to match Toast messages in tests with Espresso.
 *
 * Idea taken from: /sf/answers/2337158631/
 *
 * Usage in test class:
 *
 * import somepkg.ToastMatcher.Companion.onToast
 *
 * // To assert a toast does *not* pop up:
 * onToast("text").check(doesNotExist())
 * onToast(textId).check(doesNotExist())
 *
 * // To assert a toast does pop up:
 * onToast("text").check(matches(isDisplayed()))
 * onToast(textId).check(matches(isDisplayed()))
 */
class ToastMatcher(private val maxFailures: Int = DEFAULT_MAX_FAILURES) : TypeSafeMatcher<Root>() {

    /** Restrict number of false results from matchesSafely to avoid endless loop */
    private var failures = 0

    override fun describeTo(description: Description) {
        description.appendText("is toast")
    }

    public override fun matchesSafely(root: Root): Boolean {
        val type = root.windowLayoutParams.get().type
        @Suppress("DEPRECATION") // TYPE_TOAST is deprecated in favor of TYPE_APPLICATION_OVERLAY
        if (type == TYPE_TOAST || type == TYPE_APPLICATION_OVERLAY) {
            val windowToken = root.decorView.windowToken
            val appToken = root.decorView.applicationWindowToken
            if (windowToken === appToken) {
                // windowToken == appToken means this window isn't contained by any other windows.
                // if it was a window for an activity, it would have TYPE_BASE_APPLICATION.
                return true
            }
        }
        // Method is called again if false is returned which is useful because a toast may take some time to pop up. But for
        // obvious reasons an infinite wait isn't of help. So false is only returned as often as maxFailures specifies.
        return (++failures >= maxFailures)
    }

    companion object {

        /** Default for maximum number of retries to wait for the toast to pop up */
        private const val DEFAULT_MAX_FAILURES = 5

        fun onToast(text: String, maxRetries: Int = DEFAULT_MAX_FAILURES) = onView(withText(text)).inRoot(isToast(maxRetries))!!

        fun onToast(textId: Int, maxRetries: Int = DEFAULT_MAX_FAILURES) = onView(withText(textId)).inRoot(isToast(maxRetries))!!

        fun isToast(maxRetries: Int = DEFAULT_MAX_FAILURES): Matcher<Root> {
            return ToastMatcher(maxRetries)
        }
    }

}
Run Code Online (Sandbox Code Playgroud)

我希望这对以后的读者有所帮助-用法在注释中进行了描述。


a_s*_*ber 5

我写了我的自定义吐司匹配器:

import android.view.WindowManager
import androidx.test.espresso.Root
import org.hamcrest.Description;
import org.hamcrest.TypeSafeMatcher;
class ToastMatcher : TypeSafeMatcher<Root>() {

    override fun describeTo(description: Description) {
        description.appendText("is toast")
    }

    override fun matchesSafely(root: Root): Boolean {
        val type = root.getWindowLayoutParams().get().type
        if (type == WindowManager.LayoutParams.TYPE_TOAST) {
            val windowToken = root.getDecorView().getWindowToken()
            val appToken = root.getDecorView().getApplicationWindowToken()
            if (windowToken === appToken) {
                return true
            }
        }
        return false
    }
}
Run Code Online (Sandbox Code Playgroud)

并像这样使用:

onView(withText(R.string.please_input_all_fields)).inRoot(ToastMatcher()).check(matches(isDisplayed()))
Run Code Online (Sandbox Code Playgroud)


Ste*_*ing 5

对于 kotlin,我必须使用 apply 扩展函数,这对我有用。

1-在 androidTest 文件夹中声明您的 ToastMatcher 类:

class ToastMatcher : TypeSafeMatcher<Root?>() {

override fun matchesSafely(item: Root?): Boolean {
        val type: Int? = item?.windowLayoutParams?.get()?.type
        if (type == WindowManager.LayoutParams.FIRST_APPLICATION_WINDOW) {
            val windowToken: IBinder = item.decorView.windowToken
            val appToken: IBinder = item.decorView.applicationWindowToken
            if (windowToken === appToken) { // means this window isn't contained by any other windows.
                return true
            }
        }
        return false
    }

    override fun describeTo(description: Description?) {
        description?.appendText("is toast")
    }
}
Run Code Online (Sandbox Code Playgroud)

2-然后你像这样使用来测试toast消息是否实际显示

onView(withText(R.string.invalid_phone_number))
        .inRoot(ToastMatcher().apply {
            matches(isDisplayed())
        });
Run Code Online (Sandbox Code Playgroud)

归因于 ToastMatcher 类:

/**
 * Author: http://www.qaautomated.com/2016/01/how-to-test-toast-message-using-espresso.html
 */
Run Code Online (Sandbox Code Playgroud)

  • 这是误报,你可以匹配任何字符串 (5认同)