اسپرسو وب

Espresso-Web یک نقطه ورود برای کار با کامپوننت‌های رابط کاربری Android WebView است. Espresso-Web از اتم‌های API محبوب WebDriver برای بررسی و کنترل رفتار یک WebView استفاده مجدد می‌کند.

چه زمانی از Espresso-Web استفاده کنیم؟

از Espresso-Web برای آزمایش برنامه‌های ترکیبی خود، به ویژه ادغام اجزای رابط کاربری بومی برنامه خود با اجزای رابط کاربری WebView آن، استفاده کنید. می‌توانید از Espresso-Web API در کنار سایر Espresso APIها برای تعامل کامل با عناصر وب درون اشیاء WebView استفاده کنید.

اگر نیاز دارید که فقط خود WebView آزمایش کنید، و نه تعاملات بین WebView و اجزای بومی در برنامه خود، نوشتن یک تست وب عمومی را با استفاده از چارچوبی مانند WebDriver در نظر بگیرید. اگر از یک چارچوب تست وب استفاده می‌کنید، نیازی به استفاده از دستگاه اندروید یا ماشین مجازی جاوا ندارید، که باعث می‌شود تست‌های شما سریع‌تر و قابل اعتمادتر اجرا شوند. با این اوصاف، Espresso-Web به شما امکان می‌دهد از اتم‌های WebDriver سفارشی خود دوباره استفاده کنید، که انعطاف‌پذیری زیادی به شما می‌دهد، به خصوص هنگام نوشتن تست‌هایی که قصد دارید هم در برابر برنامه‌های وب مستقل و هم در برابر برنامه‌هایی که شامل رابط کاربری اندروید هستند، اجرا کنید.

چگونه کار می‌کند؟

مشابه متد onData() در Espresso، یک تعامل WebView شامل چندین اتم است. تعاملات WebView از ترکیبی از زبان برنامه‌نویسی جاوا و یک پل جاوااسکریپت برای انجام کار خود استفاده می‌کنند. از آنجا که هیچ شانسی برای ایجاد شرایط رقابتی با افشای داده‌ها از محیط جاوااسکریپت وجود ندارد - هر چیزی که Espresso در سمت مبتنی بر جاوا می‌بیند یک کپی ایزوله است - بازگشت داده‌ها از اشیاء Web.WebInteraction کاملاً پشتیبانی می‌شود و به شما امکان می‌دهد تمام داده‌هایی را که از یک درخواست برگردانده می‌شوند، تأیید کنید.

وب درایور اتم چیست؟

چارچوب WebDriver از Atoms برای یافتن و دستکاری عناصر وب به صورت برنامه‌نویسی‌شده استفاده می‌کند. Atoms توسط WebDriver برای امکان دستکاری مرورگر استفاده می‌شوند. یک Atom از نظر مفهومی شبیه به ViewAction است، یک واحد مستقل که عملی را در رابط کاربری شما انجام می‌دهد. شما Atoms را با استفاده از لیستی از متدهای تعریف‌شده، مانند findElement() و getElement() ، در معرض دید کاربر قرار می‌دهید تا مرورگر را از دیدگاه کاربر هدایت کند. با این حال، اگر مستقیماً از چارچوب WebDriver استفاده کنید، Atoms باید به درستی تنظیم شوند و به منطقی کاملاً طولانی نیاز دارند.

در Espresso، کلاس‌های Web و Web.WebInteraction این الگوی کلی را در بر می‌گیرند و به تعامل با اشیاء WebView احساسی شبیه به Espresso می‌دهند. بنابراین در چارچوب یک WebView ، اتم‌ها به عنوان جایگزینی برای ViewMatchers و ViewActions سنتی Espresso استفاده می‌شوند.

سپس API کاملاً ساده به نظر می‌رسد:

کاتلین

onWebView()
    .withElement(Atom)
    .perform(Atom)
    .check(WebAssertion)

جاوا

onWebView()
    .withElement(Atom)
    .perform(Atom)
    .check(WebAssertion);

برای کسب اطلاعات بیشتر، مستندات سلنیوم در مورد اتم‌ها را مطالعه کنید.

پیاده‌سازی وب ویو

برای کار با WebView در تست‌های برنامه خود، راهنمایی‌های نشان داده شده در بخش‌های زیر را دنبال کنید.

بسته‌ها

برای اضافه کردن Espresso-Web به پروژه خود، مراحل زیر را انجام دهید:

  1. فایل build.gradle برنامه خود را باز کنید. این معمولاً فایل سطح بالای build.gradle نیست، بلکه app/build.gradle است.
  2. خط زیر را درون dependencies اضافه کنید:

    گرووی

        androidTestImplementation 'androidx.test.espresso:espresso-web:3.6.1'
        

    کاتلین

        androidTestImplementation('androidx.test.espresso:espresso-web:3.6.1')
        
  3. Espresso-Web فقط با Espresso 2.2 یا بالاتر و نسخه 0.3 یا بالاتر از کتابخانه آزمایشی سازگار است، بنابراین مطمئن شوید که آن خطوط را نیز به‌روزرسانی می‌کنید:

    گرووی

        androidTestImplementation 'androidx.test:runner:1.6.1'
        androidTestImplementation 'androidx.test:rules:1.6.1'
        androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
        

    کاتلین

        androidTestImplementation('androidx.test:runner:1.6.1')
        androidTestImplementation('androidx.test:rules:1.6.1')
        androidTestImplementation('androidx.test.espresso:espresso-core:3.6.1')
        

کاربردهای رایج API

متد onWebView() نقطه ورود اصلی هنگام کار با WebView در اندروید با استفاده از Espresso است. شما از این متد برای انجام تست‌های Espresso-Web مانند موارد زیر استفاده می‌کنید:

کاتلین

onWebView()
    .withElement(findElement(Locator.ID, "link_2")) // similar to onView(withId(...))
    .perform(webClick()) // Similar to perform(click())

    // Similar to check(matches(...))
    .check(webMatches(getCurrentUrl(), containsString("navigation_2.html")))

جاوا

onWebView()
    .withElement(findElement(Locator.ID, "link_2")) // similar to onView(withId(...))
    .perform(webClick()) // Similar to perform(click())

    // Similar to check(matches(...))
    .check(webMatches(getCurrentUrl(), containsString("navigation_2.html")));

در این مثال، Espresso-Web یک عنصر DOM با شناسه "link_2" را پیدا کرده و روی آن کلیک می‌کند. سپس این ابزار تأیید می‌کند که WebView یک درخواست GET حاوی رشته "navigation_2.html" ارسال می‌کند.

پشتیبانی از جاوا اسکریپت

هنگام اجرای تست‌های شما، سیستم تمام تعاملات WebView را با استفاده از جاوا اسکریپت انجام می‌دهد. بنابراین، برای پشتیبانی از ارزیابی جاوا اسکریپت، WebView تحت آزمایش باید جاوا اسکریپت را فعال کند.

شما می‌توانید با فراخوانی تابع forceJavascriptEnabled() به عنوان یک اکشن در activity تحت تست خود ، همانطور که در قطعه کد زیر نشان داده شده است، جاوا اسکریپت را مجبور به فعال شدن کنید.

@RunWith(AndroidJUnit4::class)
class MyTestSuite {
    @get:Rule val activityScenarioRule =
        activityScenarioRule<MyWebViewActivity>()

    @Test fun testWebViewInteraction() {
        onWebView().forceJavascriptEnabled()
    }
}

تعاملات رایج وب

تعاملات رایج با اشیاء Web.WebInteraction شامل موارد زیر است:

  • withElement() به یک عنصر DOM درون WebView اشاره می‌کند.

    مثال:

    کاتلین

    onWebView().withElement(findElement(Locator.ID, "teacher"))

    جاوا

    onWebView().withElement(findElement(Locator.ID, "teacher"));
  • withContextualElement() به یک عنصر DOM با دامنه مشخص در WebView، نسبت به یک عنصر DOM دیگر، اشاره می‌کند. شما باید ابتدا withElement() را برای ایجاد شیء مرجع Web.WebInteraction (عنصر DOM) فراخوانی کنید.

    مثال:

    کاتلین

    .withElement(findElement(Locator.ID, "teacher"))
        .withContextualElement(findElement(Locator.ID, "person_name"))

    جاوا

    .withElement(findElement(Locator.ID, "teacher"))
        .withContextualElement(findElement(Locator.ID, "person_name"));
  • check() یک شرط را ارزیابی می‌کند و مطمئن می‌شود که نتیجه‌ی آن true باشد.

    مثال:

    کاتلین

    onWebView()
        .withElement(findElement(Locator.ID, "teacher"))
        .withContextualElement(findElement(Locator.ID, "person_name"))
        .check(webMatches(getText(), containsString("Socrates")))

    جاوا

    onWebView()
        .withElement(findElement(Locator.ID, "teacher"))
        .withContextualElement(findElement(Locator.ID, "person_name"))
        .check(webMatches(getText(), containsString("Socrates")));
  • perform() یک عمل را درون یک وب‌ویو اجرا می‌کند، مانند کلیک کردن روی یک عنصر.

    مثال:

    کاتلین

    onWebView()
        .withElement(findElement(Locator.ID, "teacher"))
        .perform(webClick())

    جاوا

    onWebView()
        .withElement(findElement(Locator.ID, "teacher"))
        .perform(webClick());
  • reset() وب‌ویو را به حالت اولیه‌اش برمی‌گرداند. این تابع زمانی ضروری است که یک اقدام قبلی، مانند کلیک، باعث تغییر ناوبری شود که اشیاء ElementReference و WindowReference را غیرقابل دسترس کند.

    نکته: اگرچه استفاده از reset() هنگام ایجاد assertion در گردش‌های کاری چند صفحه‌ای، مانند ارسال فرم، مفید است، اما تست‌های شما معمولاً باید از نظر دامنه محدود باشند و روی یک صفحه واحد تمرکز کنند.

    مثال:

    کاتلین

    onWebView()
        .withElement(...)
        .perform(...)
        .reset()

    جاوا

    onWebView()
        .withElement(...)
        .perform(...)
        .reset();

مثال

مثال زیر بررسی می‌کند که آیا پس از وارد کردن متن در یک WebView و انتخاب دکمه ارسال ، همان متن در یک عنصر متفاوت در همان WebView ظاهر می‌شود یا خیر:

کاتلین

const val MACCHIATO = "Macchiato"

@RunWith(AndroidJUnit4::class)
class MyEspressoWebTestSuite {

    @Test fun typeTextInInput_clickButton_SubmitsForm() {
        // Create an intent that displays a web form.
        val webFormIntent = Intent()
        // ...

        // Lazily launch the Activity with a custom start Intent per test.
        ActivityScenario.launchActivity(webFormIntent)

        // Selects the WebView in your layout. If you have multiple WebView
        // objects, you can also use a matcher to select a given WebView,
        // onWebView(withId(R.id.web_view)).
        onWebView()
            // Find the input element by ID.
            .withElement(findElement(Locator.ID, "text_input"))

            // Clear previous input and enter new text into the input element.
            .perform(clearElement())
            .perform(DriverAtoms.webKeys(MACCHIATO))

            // Find the "Submit" button and simulate a click using JavaScript.
            .withElement(findElement(Locator.ID, "submitBtn"))
            .perform(webClick())

            // Find the response element by ID, and verify that it contains the
            // entered text.
            .withElement(findElement(Locator.ID, "response"))
            .check(webMatches(getText(), containsString(MACCHIATO)))
    }
}

جاوا

public static final String MACCHIATO = "Macchiato";

@Test
public void typeTextInInput_clickButton_SubmitsForm() {
    // Create an intent that displays a web form.
    Intent webFormIntent = new Intent();
    // ...

    // Lazily launch the Activity with a custom start Intent per test.
    ActivityScenario.launchActivity(webFormIntent);

    // Selects the WebView in your layout. If you have multiple WebView objects,
    // you can also use a matcher to select a given WebView,
    // onWebView(withId(R.id.web_view)).
    onWebView()
        // Find the input element by ID.
        .withElement(findElement(Locator.ID, "text_input"))

        // Clear previous input and enter new text into the input element.
        .perform(clearElement())
        .perform(DriverAtoms.webKeys(MACCHIATO))

        // Find the "Submit" button and simulate a click using JavaScript.
        .withElement(findElement(Locator.ID, "submitBtn"))
        .perform(webClick())

        // Find the response element by ID, and verify that it contains the
        // entered text.
        .withElement(findElement(Locator.ID, "response"))
        .check(webMatches(getText(), containsString(MACCHIATO)));
}

منابع اضافی

برای اطلاعات بیشتر در مورد استفاده از Espresso-Web در تست‌های اندروید، به منابع زیر مراجعه کنید.

نمونه‌ها

  • WebBasicSample : از Espresso-Web برای تعامل با اشیاء WebView استفاده کنید.