هدف‌یابی کردن نمونه برنامه

این دسته از آزمایش ابزار دقیق تفاوت چندانی با آزمایش‌های هدف‌گیری برنامه‌های Android معمولی ندارد. شایان ذکر است که برنامه آزمایشی که شامل ابزار دقیق است باید با همان گواهی برنامه هدف امضا شود.

توجه داشته باشید که این راهنما فرض می‌کند شما ازقبل با گردش کار درخت منبع پلاتفرم آشنایی دارید. اگر این‌طور نیست، لطفاً به الزامات مراجعه کنید. نمونه‌ای که در اینجا پوشش داده شده است نوشتن یک آزمایش ابزار دقیق جدید با بسته هدف تنظیم‌شده در بسته برنامه آزمایشی خودش است. اگر با این مفهوم آشنا نیستید، لطفاً مقدمه آزمایش پلاتفرم را بخوانید.

این راهنما از آزمون زیر به‌عنوان نمونه استفاده می‌کند:

  • frameworks/base/packages/Shell/tests

توصیه می‌شود ابتدا کد را مرور کنید تا پیش‌از ادامه دادن، تصوری کلی از آن داشته باشید.

درباره مکان منبع تصمیم بگیرید

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

در مثال سرتاسر برای آزمایش‌های خودابزاربندی، بحث‌های بیشتری درباره مکان منبع ببینید.

فایل مانیفست

درست مثل یک برنامه معمولی، هر واحد آزمایشی ابزاربندی به یک فایل مانیفست نیاز دارد. اگر نام فایل را AndroidManifest.xml بگذارید و آن را در کنار Android.mk برای واحد آزمونتان ارائه دهید، به‌طور خودکار در فایل ساختار اصلی BUILD_PACKAGE گنجانده خواهد شد.

قبل‌از ادامه دادن، اکیداً توصیه می‌شود ابتدا نمای کلی مانیفست برنامه را بررسی کنید.

این بخش نمای کلی از اجزای اصلی فایل مانیفست و عملکردهای آن‌ها ارائه می‌دهد.

جدیدترین نسخه فایل مانیفست برای تغییر نمونه gerrit را می‌توانید در اینجا ببینید: https://android.googlesource.com/platform/frameworks/base/+/android17-release/packages/Shell/tests/AndroidManifest.xml

برای راحتی، نماگرفتی در اینجا ارائه شده است:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.shell.tests">

    <application>
        <uses-library android:name="android.test.runner" />

        <activity
            android:name="com.android.shell.ActionSendMultipleConsumerActivity"
            android:label="ActionSendMultipleConsumer"
            android:theme="@android:style/Theme.NoDisplay"
            android:noHistory="true"
            android:excludeFromRecents="true">
            <intent-filter>
                <action android:name="android.intent.action.SEND_MULTIPLE" />
                <category android:name="android.intent.category.DEFAULT" />
                <data android:mimeType="*/*" />
            </intent-filter>
        </activity>
    </application>

    <instrumentation android:name="android.support.test.runner.AndroidJUnitRunner"
        android:targetPackage="com.android.shell"
        android:label="Tests for Shell" />

</manifest>

برخی‌از نظرات انتخاب‌شده درباره فایل مانیفست:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.android.shell.tests">

مشخصه package نام بسته برنامه است: این شناسه متمایزی است که چارچوب برنامه Android برای شناسایی برنامه (یا در این زمینه: برنامه آزمایشی شما) استفاده می‌کند. هر کاربر در سیستم فقط می‌تواند یک برنامه با آن نام بسته نصب کند.

ازآنجایی‌که این بسته برنامه آزمایشی است و مستقل از بسته برنامه تحت آزمایش است، باید از نام بسته متفاوتی استفاده شود: یک قرارداد رایج، افزودن پسوند .test است.

علاوه‌براین، این مشخصه package همان چیزی است که ComponentName#getPackageName() برمی‌گرداند، و همچنین همان چیزی است که برای تعامل با زیرفرمان‌های مختلف pm ازطریق adb shell استفاده می‌کنید.

لطفاً توجه داشته باشید که اگرچه نام بسته معمولاً به سبک نام بسته Java است، اما درواقع ارتباط بسیار کمی با آن دارد. به‌عبارت دیگر، بسته برنامه (یا آزمایش) شما می‌تواند حاوی کلاس‌هایی با هر نام بسته‌ای باشد، هرچند از طرف دیگر، می‌توانید سادگی را انتخاب کنید و نام بسته Java سطح بالای خود را در برنامه یا آزمایش با نام بسته برنامه یکسان کنید.

<uses-library android:name="android.test.runner" />

این مورد برای همه آزمایش‌های «ابزار دقیق» الزامی است زیرا کلاس‌های مرتبط در فایل کتابخانه jar چارچوب جداگانه‌ای بسته‌بندی شده‌اند، بنابراین وقتی بسته آزمایش توسط چارچوب برنامه فراخوانی می‌شود، به ورودی‌های مسیر کلاس اضافی نیاز دارد.

android:targetPackage="com.android.shell"

این کار بسته هدف ابزار را روی com.android.shell تنظیم می‌کند. وقتی ابزارگری ازطریق فرمان am instrument فراخوانی می‌شود، چارچوب فرایند com.android.shell را بازراه‌اندازی می‌کند و کد ابزارگری را به فرایند برای اجرای آزمایش تزریق می‌کند. این همچنین به این معنی است که کد آزمایش به همه نمونه‌های کلاس درحال اجرا در برنامه تحت آزمایش دسترسی خواهد داشت و بسته به قلاب‌های آزمایش نمایان‌شده، ممکن است بتواند وضعیت را دستکاری کند.

فایل پیکربندی ساده

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

فایل پیکربندی پیچیده

برای آزمایش‌های پیچیده‌تر، باید فایل پیکربندی آزمایشی برای ابزار آزمایش Android،‏ Trade Federation، نیز بنویسید.

پیکربندی آزمایش می‌تواند گزینه‌های راه‌اندازی دستگاه ویژه و آرگومان‌های پیش‌فرض را برای ارائه کلاس آزمایش مشخص کند.

جدیدترین نسخه فایل پیکربندی برای تغییر gerrit نمونه در اینجا قابل‌دسترسی است: frameworks/base/packages/Shell/tests/AndroidTest.xml

برای راحتی شما، عکس آنی در اینجا گنجانده شده است:

<configuration description="Runs Tests for Shell.">
    <target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
        <option name="test-file-name" value="ShellTests.apk" />
    </target_preparer>

    <option name="test-suite-tag" value="apct" />
    <option name="test-tag" value="ShellTests" />
    <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
        <option name="package" value="com.android.shell.tests" />
        <option name="runner" value="android.support.test.runner.AndroidJUnitRunner" />
    </test>
</configuration>

چند نکته درباره فایل پیکربندی آزمایشی:

<target_preparer class="com.android.tradefed.targetprep.TestAppInstallSetup">
  <option name="test-file-name" value="ShellTests.apk"/>
</target_preparer>

این دستور به Trade Federation می‌گوید که ShellTests.apk را بااستفاده از target_preparer مشخص‌شده روی دستگاه هدف نصب کند. آماده‌سازهای هدف زیادی در «فدراسیون تجارت» برای توسعه‌دهندگان دردسترس است و می‌توان از آن‌ها برای اطمینان از راه‌اندازی صحیح دستگاه قبل‌از اجرای آزمایش استفاده کرد.

<test class="com.android.tradefed.testtype.AndroidJUnitTest">
  <option name="package" value="com.android.shell.tests"/>
  <option name="runner" value="android.support.test.runner.AndroidJUnitRunner"/>
</test>

این کلاس آزمایشی «فدراسیون تجارت» را که برای اجرای آزمون استفاده می‌شود مشخص می‌کند و بسته را در دستگاه برای اجرا و چارچوب اجراکننده آزمون که در این مورد JUnit است ارسال می‌کند.

برای اطلاعات بیشتر درباره پیکربندی‌های ماژول آزمایشی، اینجا را ببینید

ویژگی‌های JUnit4

استفاده از کتابخانه android-support-test به‌عنوان اجراکننده آزمایش امکان پذیرش کلاس‌های آزمایش سبک JUnit4 جدید را فراهم می‌کند، و تغییر نمونه gerrit حاوی برخی‌از استفاده‌های بسیار ابتدایی از ویژگی‌های آن است.

جدیدترین کد منبع برای تغییر نمونه gerrit را می‌توانید در اینجا ببینید: frameworks/base/packages/Shell/tests/src/com/android/shell/BugreportReceiverTest.java

اگرچه الگوهای آزمایش معمولاً مختص تیم‌های مؤلفه است، اما برخی‌از الگوهای استفاده به‌طور کلی مفید هستند.

@SmallTest
@RunWith(AndroidJUnit4.class)
public final class FeatureFactoryImplTest {

تفاوت قابل‌توجه در JUnit4 این است که دیگر لازم نیست آزمایش‌ها از کلاس آزمایش پایه مشترک ارث ببرند؛ درعوض، آزمایش‌ها را در کلاس‌های ساده Java می‌نویسید و از شرح برای نشان دادن تنظیمات و محدودیت‌های آزمایش خاص استفاده می‌کنید. در این مثال، دستور می‌دهیم که این کلاس باید به‌عنوان آزمایش Android JUnit4 اجرا شود.

حاشیه‌نویسی @SmallTest اندازه آزمایشی را برای کل کلاس آزمایشی مشخص کرد: همه روش‌های آزمایشی اضافه‌شده به این کلاس آزمایشی، این حاشیه‌نویسی اندازه آزمایشی را به ارث می‌برند. راه‌اندازی کلاس پیش‌آزمون، تخریب پس‌آزمون، و تخریب کلاس پس‌آزمون: مشابه روش‌های setUp و tearDown در JUnit4. از حاشیه‌نویسی Test برای حاشیه‌نویسی آزمایش واقعی استفاده می‌شود.

    @Before
    public void setup() {
    ...
    @Test
    public void testGetProvider_shouldCacheProvider() {
    ...

از گزارمان @Before در روش‌های JUnit4 برای انجام تنظیمات پیش‌آزمایش استفاده می‌شود. اگرچه در این مثال استفاده نشده است، @After نیز برای جداسازی پس‌از آزمایش وجود دارد. به‌همین ترتیب، از حاشیه‌نویسی‌های @BeforeClass و @AfterClass می‌توان در روش‌های JUnit4 برای انجام تنظیمات قبل‌از اجرای همه آزمایش‌ها در کلاس آزمایش، و حذف پس‌از آن استفاده کرد. توجه داشته باشید که روش‌های راه‌اندازی و برچیدن حوزه کلاس باید ایستا باشند.

درخصوص روش‌های آزمایش، برخلاف نسخه‌های قبلی JUnit، دیگر نیازی نیست نام روش با test شروع شود، بلکه هریک از آن‌ها باید با @Test حاشیه‌نویسی شود. طبق معمول، روش‌های آزمایش باید عمومی باشند، مقدار برگشتی نداشته باشند، پارامتری نداشته باشند، و ممکن است استثناهایی ایجاد کنند.

        Context context = InstrumentationRegistry.getTargetContext();

ازآنجایی‌که آزمایش‌های JUnit4 دیگر به کلاس پایه مشترک نیاز ندارند، دیگر لازم نیست نمونه‌های Context را ازطریق getContext() یا getTargetContext() را ازطریق روش‌های کلاس پایه دریافت کنید؛ درعوض، اجراکننده آزمایش جدید آن‌ها را ازطریق InstrumentationRegistry مدیریت می‌کند که در آن راه‌اندازی زمینه‌ای و محیطی ایجادشده توسط چارچوب ابزار دقیق ذخیره می‌شود. ازطریق این کلاس، می‌توانید این موارد را نیز فراخوانی کنید:

  • getInstrumentation(): نمونه کلاس Instrumentation
  • ‫getArguments(): آرگومان‌های خط فرمان که ازطریق -e <key> <value> به am instrument ارسال شده است

ساختن و آزمایش کردن به‌صورت محلی

برای رایج‌ترین موارد استفاده، از Atest استفاده کنید.

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