این دسته از تستهای ابزار دقیق تفاوت چندانی با تستهایی که برنامههای معمولی اندروید را هدف قرار میدهند، ندارند. شایان ذکر است که برنامه آزمایشی که شامل ابزار دقیق است، باید با همان گواهی برنامهای که هدف آن است، امضا شده باشد.
توجه داشته باشید که این راهنما فرض میکند که شما از قبل در مورد گردش کار درخت منبع پلتفرم دانش دارید. در غیر این صورت، لطفاً به بخش الزامات مراجعه کنید. مثالی که در اینجا پوشش داده شده است، نوشتن یک تست ابزار دقیق جدید با مجموعه بسته هدف در بسته برنامه تست خود است. اگر با این مفهوم آشنا نیستید، لطفاً مقدمه تست پلتفرم را مطالعه کنید.
این راهنما از آزمون زیر به عنوان نمونه استفاده میکند:
- چارچوبها/پایه/بستهها/پوسته/تستها
توصیه میشود قبل از ادامه، ابتدا کد را مرور کنید تا یک تصور کلی از آن داشته باشید.
در مورد محل منبع تصمیم بگیرید
از آنجا که تست ابزار دقیق یک برنامه را هدف قرار میدهد، قرارداد این است که کد منبع تست را در یک دایرکتوری tests زیر ریشه دایرکتوری منبع کامپوننت شما در درخت منبع پلتفرم، قرار دهید.
بحثهای بیشتر در مورد مکان منبع را در مثال سرتاسری برای آزمایشهای خود-ابزارسنجی ببینید.
فایل مانیفست
درست مانند یک برنامه معمولی، هر ماژول تست ابزار دقیق به یک فایل مانیفست نیاز دارد. اگر نام فایل را AndroidManifest.xml بگذارید و آن را در کنار Android.mk برای tmodule تست خود قرار دهید، به طور خودکار توسط فایل makefile هسته BUILD_PACKAGE اضافه میشود.
قبل از ادامهی مطلب، اکیداً توصیه میشود که ابتدا مروری بر مانیفست اپلیکیشن (App Manifest Overview) داشته باشید.
این یک مرور کلی از اجزای اساسی یک فایل مانیفست و عملکردهای آنها ارائه میدهد.
آخرین نسخه فایل مانیفست برای تغییر نمونه gerrit را میتوانید از طریق آدرس زیر دریافت کنید: https://android.googlesource.com/platform/frameworks/base/+/android16-qpr1-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 ، نام بسته برنامه است: این شناسه منحصر به فردی است که چارچوب برنامه اندروید برای شناسایی یک برنامه (یا در این زمینه: برنامه آزمایشی شما) از آن استفاده میکند. هر کاربر در سیستم فقط میتواند یک برنامه با آن نام بسته نصب کند.
از آنجایی که این یک بسته برنامه آزمایشی است و مستقل از بسته برنامه تحت آزمایش است، باید از نام بسته متفاوتی استفاده شود: یک قرارداد رایج، اضافه کردن پسوند .test است.
علاوه بر این، این ویژگی package همان چیزی است که ComponentName#getPackageName() برمیگرداند، و همچنین همان چیزی است که شما برای تعامل با دستورات مختلف pm sub از طریق adb shell استفاده میکنید.
لطفاً توجه داشته باشید که اگرچه نام بسته معمولاً به همان سبک نام بسته جاوا است، اما در واقع ارتباط بسیار کمی با آن دارد. به عبارت دیگر، بسته برنامه (یا تست) شما ممکن است شامل کلاسهایی با هر نام بستهای باشد، اگرچه از طرف دیگر، میتوانید سادگی را انتخاب کنید و نام بسته جاوای سطح بالای خود را در برنامه یا تست خود با نام بسته برنامه یکسان داشته باشید.
<uses-library android:name="android.test.runner" />
این برای همه تستهای Instrumentation الزامی است زیرا کلاسهای مرتبط در یک فایل جداگانه کتابخانه jar فریمورک بستهبندی شدهاند، بنابراین هنگام فراخوانی بسته تست توسط فریمورک برنامه، به ورودیهای classpath اضافی نیاز است.
android:targetPackage="com.android.shell"
این، بستهی هدف instrumentation را روی com.android.shell تنظیم میکند. هنگامی که instrumentation از طریق دستور am instrument فراخوانی میشود، فریمورک، فرآیند com.android.shell را مجدداً راهاندازی میکند و کد instrumentation را برای اجرای تست به فرآیند تزریق میکند. این همچنین بدان معنی است که کد تست به تمام نمونههای کلاس در حال اجرا در برنامهی تحت تست دسترسی خواهد داشت و ممکن است بتواند وضعیت را بسته به قلابهای تستِ در معرض نمایش، دستکاری کند.
فایل پیکربندی ساده
هر ماژول تست جدید باید یک فایل پیکربندی داشته باشد تا سیستم ساخت را با ابردادههای ماژول، وابستگیهای زمان کامپایل و دستورالعملهای بستهبندی هدایت کند. در بیشتر موارد، گزینه فایل Blueprint مبتنی بر Soong کافی است. برای جزئیات بیشتر به Simple Test Configuration مراجعه کنید.
فایل پیکربندی پیچیده
برای تستهای پیچیدهتر، باید یک فایل پیکربندی تست برای ابزار تست اندروید، 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 مشخص شده روی دستگاه هدف نصب کند. آمادهسازهای هدف زیادی در Trade Federation برای توسعهدهندگان در دسترس است و میتوان از آنها برای اطمینان از راهاندازی صحیح دستگاه قبل از اجرای تست استفاده کرد.
<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>
این، کلاس تست Trade Federation را که برای اجرای تست استفاده میشود، مشخص میکند و پکیج را روی دستگاهی که قرار است اجرا شود و چارچوب اجراکننده تست که در این مورد 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 این است که تستها دیگر نیازی به ارثبری از یک کلاس تست پایه مشترک ندارند؛ در عوض، شما تستها را در کلاسهای ساده جاوا مینویسید و از حاشیهنویسی برای نشان دادن تنظیمات و محدودیتهای خاص تست استفاده میکنید. در این مثال، ما دستور میدهیم که این کلاس باید به عنوان یک تست JUnit4 اندروید اجرا شود.
حاشیهنویسی @SmallTest یک اندازه تست برای کل کلاس تست مشخص کرده است: تمام متدهای تست اضافه شده به این کلاس تست، این حاشیهنویسی اندازه تست را به ارث میبرند. setup کلاس تست قبل از تست، tear down کلاس تست بعد از تست، و tear down کلاس تست بعد از تست: مشابه متدهای setUp و tearDown در JUnit4. حاشیهنویسی Test برای حاشیهنویسی تست واقعی استفاده میشود.
@Before
public void setup() {
...
@Test
public void testGetProvider_shouldCacheProvider() {
...
حاشیهنویسی @Before در متدهای JUnit4 برای انجام تنظیمات پیش از تست استفاده میشود. اگرچه در این مثال استفاده نشده است، اما @After نیز برای جداسازی پس از تست وجود دارد. به طور مشابه، حاشیهنویسیهای @BeforeClass و @AfterClass میتوانند در متدهای JUnit4 برای انجام تنظیمات قبل از اجرای تمام تستها در یک کلاس تست و جداسازی پس از آن استفاده شوند. توجه داشته باشید که متدهای setup و teardown مربوط به محدوده کلاس باید استاتیک باشند.
در مورد متدهای تست، برخلاف نسخههای قبلی JUnit، دیگر نیازی نیست نام متد با test شروع شود، در عوض، هر یک از آنها باید با @Test حاشیهنویسی شوند. طبق معمول، متدهای تست باید عمومی باشند، هیچ مقدار بازگشتی را اعلام نکنند، هیچ پارامتری نگیرند و ممکن است استثناهایی را ایجاد کنند.
Context context = InstrumentationRegistry.getTargetContext();
از آنجا که تستهای JUnit4 دیگر به یک کلاس پایه مشترک نیاز ندارند، دیگر نیازی به دریافت نمونههای Context از طریق getContext() یا getTargetContext() از طریق متدهای کلاس پایه نیست؛ در عوض، اجراکننده تست جدید آنها را از طریق InstrumentationRegistry مدیریت میکند که در آن تنظیمات زمینهای و محیطی ایجاد شده توسط چارچوب instrumentation ذخیره میشود. از طریق این کلاس، میتوانید موارد زیر را نیز فراخوانی کنید:
-
getInstrumentation(): نمونهای از کلاسInstrumentation -
getArguments(): آرگومانهای خط فرمان از طریق-e <key> <value>بهam instrumentارسال میشوند.
ساخت و آزمایش به صورت محلی
برای رایجترین موارد استفاده، از Atest استفاده کنید.
برای موارد پیچیدهتر که نیاز به سفارشیسازی سنگینتری دارند، دستورالعملهای ابزار دقیق را دنبال کنید.