دوشنبه , ۱۰ اردیبهشت ۱۴۰۳

آموزش Robolectric-قسمت پانزدهم و پایانی: Shadowها(بخش دوم)

Robolectric Tool
Robolectric Tool

Shadowهای Customize شده

Robolectric یک محصول و کار در حال پیشرفت است و طراحان آن اعتقاد دارند، به همه کسانی که تمایل به مشارکت در مجموعه طراحان Robolectric و رفع باگ‌ها و شکاف‌های موجود در این ابزار دارند، خوش آمد گفته و آنها را برای این همکاری تشویق می‌نماید. با این حال، اگر افرادی می‌خواهند رفتار Shadow را به گونه‌ای تغییر دهند که برای اشتراک‌گذاری مناسب نیست، و یا نمی‌توانند منتظر نسخه جدیدی که اصلاحات ضروری را شامل می‌شود بمانند، تیم طراحان به آنها Custom Shadowها را پیشنهاد می‌دهد.

نوشتن یک Custom Shadow

Custom Shadowها بسیار شبیه Shadow Classهای معمول هستند. آنها باید حاوی حاشیه‌نویسی به صورت ‘(Implements(AndroidClassName.class@’ در تعریف کلاس باشند. شما می‌توانید از گزینه‌های معمول Shadow Implementation استفاده کنید، مانند متدهای Shadow کردن Instanceها با استفاده از ‘Implementation@’ و یا Shadow کردن Constructorها با استفاده از ‘(…)__public void __constructor’. اگر شما تمایل داشته باشید Shadow Class شما می‌تواند یکی از Stock Robolectric Shadow را Extend نماید.

@Implements(Bitmap.class)
public class MyShadowBitmap {
  @RealObject private Bitmap realBitmap;
  private int bitmapQuality = -1;
    
  @Implementation
  public boolean compress(Bitmap.CompressFormat format, int quality, OutputStream stream) {
    bitmapQuality = quality;
    return realBitmap.compress(format, quality, stream);
  }

  public int getQuality() {
    return bitmapQuality;
  }
}

استفاده از یک Custom Shadow

Custom Shadowها با Robolectric با استفاده از ‘Config annotation@’ در Test Class یا با استفاده از Shadows’ Array Attribute’ روی Test Method هوک(Hook) می‌شوند. برای استفاده از کلاس ‘MyShadowBitmap’ همانطور که در قسمت‌های قبلی ذکر شد، شما می‌توانید از حاشیه‌نویسی ‘({Config(shadows={MyShadowBitmap.class@’ بهره ببیرید، و برای گنجاندن چندین Custom Shadow از ‘({Config(shadows={MyShadowBitmap.class, MyOtherCustomShadow.class@’ استفاده نمایید. این باعث می شود Robolectric بتواند Custom Shadow شما را در زمان اجرای کد در مقابل کلاسی که شما آنرا Shadow کرده‌اید شناسایی کرده و استفاده نماید.

اگر شما می‌خواهید Custom Shadowهای خود را به تمام تست‌های موجود سوییتتان اعمال کنید، می‌توانید Shadowها را از طریق فایل robolectric.properties پیکربندی نمایید.

توجه داشته باشید، به طور پیش فرض متد ‘()Shadows.shadowOf’ با Custom Shadowها کار نخواهد کرد. به جای این می‌توانید از ‘()Shadow.extract’ استفاده کنید و مقدار بازگشتی را به کلاس Custom Shadow اعمال کنید.

ساخت یک Library از Custom Shadowها

اگر شما به این نتیجه رسیدید که یک Library از Custom Shadowها ایجاد کنید، باید اجرای پردازشگر حاشیه‌نویسیِ Shadow در Robolectric را روی Shadows Library خود در نظر بگیرید. این مزایای متعددی را شامل می‌شود:

  1. تولید متدهای ‘shadowOf’ برای هر یک از Shadowهای شما.
  2. ایجاد یک ServiceLoader، به طوری که اگر Custom Shadowهای شما را روی Classpath بیابد، به صورت خودکار آنرا اِعمال می‌کند.
  3. با استفاده از هر متد استاتیک ‘Resetter@’ در اشکالزدایی، شما را قادر به ریست کردن وضعیت ‘static’ می‌کند.
  4. انجام اعتبار سنجی تکمیلی بررسی روی Shadowهای شما.
android {
    defaultConfig {
        javaCompileOptions {
            annotationProcessorOptions {
                className 'org.robolectric.annotation.processing.RobolectricProcessor'
                arguments = [ 'org.robolectric.annotation.processing.shadowPackage' : 'com.example.myshadowpackage' ]
            }
        }
    }

}

dependencies {
    annotationProcessor project(":processor")
    ...
}

بهترین شیوه‌ها(Best Practice)

API surface area مربوط به Shadowها را محدود کنید

از آنجا که متدهای ‘Implementation@’ در Robolectric 3.7 مشتمل بر متدهای ‘__constructor__’ می‌توانند به صورت ‘protected’ درج شوند. این مطلوب است، زیرا Test Code هیچ Business برای فراخوانی این متدها ندارد، و به این ترتیب با Protected کردن متدهای ‘Implementation@’ شما باعث تشویق نویسندگان تست به فراخوانی public Android APIها می‌شوید.

از useinheritImplementationMethod استفاده نکنید

useinheritImplementationMethod غالبا غیر ضروریست و در Robolectric 3.8 حذف خواهد شد

equals, hashCode, toString را در Shadowها Override نکنید

از Override کردن موارد مذبور اجتناب کنید، مگر اینکه شما در حال تقلید رفتار در کلاسی باشید که Shadow شده است. برای تست کردن برابری(Equality) برای انجام مقایسه در تست‌ها، Helperها یا assertion library extensionها را ترجیح دهید. به جای Shadow کردن ‘()toString’، یک متد ‘()describe’ اضافه کنید.

Shadowهای باکیفیتی بنویسید که به جای تست پیاده‌سازی، تست کردن رفتار ترویج دهند

Shadowهایی بنویسد که تست رفتار ترویج می‌دهند. به عنوان مثال، متدی ارائه ندهید که Listenerهای ثبت شده را نمایش می‌دهد، بلکه یک ‘Implementation@’ به متدی که این Listenerها را احضار می‌کند، بیفزایید.

زمانیکه کد خود را Shadow می‌کنید از Caution استفاده نمایید

Robolectric قدرت زیادی را فراهم می‌کند که نیازمند استفاده مسئولانه است. Shadowها برای تست کردن تعامل با Android Framework ایده آل هستند، زیرا Framework از تزریق وابستگی(Dependency Injection) پشتیبانی نمی‌کند و استفاده آزادانه از Static Code را باعث می‌شود. قبل از نوشتن Custom Shadowها برای کد خود، در نظر داشته باشید که آیا نمی‌توانید کد خود را بهتر Refactor کرده و از یک Mocking Library مانند Mockito استفاده نمایید.

اگر می‌توانید این Community را پشتیبانی نمایید

لطفا به منظور کمک به Robolectric پیشرفت‌های خودتان را با جامعه Robolectric به اشتراک بگذارید.

 

تمام قسمت‌های آموزش Robolectric، به صورت دسته‌بندی شده از اینجا نیز در دسترس است.

ابوالفضل خواجه دیزجی

همچنین ببینید

Selenium

آموزش Selenium-قسمت هفدهم: Mouse Click Event و Keyboard Event و موضوع Action Class در Selenium WebDriver

در این بخش، ما رویداد کیبورد(Keyboard Event) و ماوس(Mouse Event) را در Selenium Webdriver آموزش …

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *