مشخصات مقاله
-
5387
-
0.0
-
5453
-
0
-
0
آزمایش برنامه های کاربردی android- اندروید- اجرا و راه اندازی تست ها
آزمایش برنامه های کاربردی android- اندروید- اجرا و راه اندازی تست ها
مبحث پیش رو شما را با نحوه ی راه اندازی و تست برنامه های کاربردی اندروید با استفاده از چهارچوب های نرم افزاری مختلف تست اپلیکیشن در اندروید آشنا می سازد .
فهرست محتوا
1. تست برنامه های اندروید به صورت خودکار
- تست اپلیکیشن های اندروید پیش از توزیع
- چگونه باید برنامه هایی که برای سیستم عامل اندروید نوشته شده باشد را تست کرد ؟
- Unit test(تست برنامه بر حسب یک مولفه یا واحد( در مقابل integration test (تست کل برنامه)
- اندروید و JUnit 3
- کدام اجزإ را باید در اپلیکیشن های متعارف اندروید تست کرد
- تست پیش شرط ها
- تست رابط کاربری (UI)
- اجرای تست روی یک سرویس دهنده (یا سرور) بدون صفحه نمایش (Display) / headless
2. کدام دسته از تست ها باید روی سیستم اندروید انجام شوند ؟
- تست کلاس های متعارف و استاندارد جاوا
- تست کلاس هایی که از رابط برنامه سازی کاربردی اندروید (API) بهره می گیرند
3. پروژه های آزمایشی اندروید – اجرا و راه اندازی تست ها
- ایجاد پروژه ی آزمایشی با استفاده از ابزار توسعه و برنامه سازی اندروید (ADT)
- راه اندازی فرایند تست اندروید
4. اشیإ یا کلاس های ساختگی و شبیه سازی شده برای تست (Mock objects)
- استفاده از کلاس MockContext (شبیه سازی بستر برنامه)
5. تمرین : نوشتن یک روال یا روتین مجازی ((stub شبیه سازی دسترسی به فایل (mocking file access)
- ایجاد برنامه ی کاربردی اندروید
- ساخت پروژه ی آزمایشی, تست
- نتیجه
6. تست اپلیکیشن
7. تست سرویس
8. تست Content Provider
9. تست loader
10. نقاط شروع تست در اندروید (test hooks into android framework
- کلاس instrumentation
- چگونگی اجرا ی تست ها توسط سیستم اندروید
11. تست activity برنامه
- چرخه ی حیات activity ها و کلاس instrumentation
- استفاده از (unit test) تست بر حسب مولفه برای آزمایش کردن activity ها
- بکارگیری integration test (تست کلی) جهت تست activity ها
- آزمایش حالت اولیه
- نوشتن و طراحی تست هایی ویژه ی آزمایش کردن حالت ها
12. تمرین : تست بر حسب مولفه برای یک activity
- ایجاد پروژه
- ساخت پروژه ی آزمایشی و کلاس
- طراحی تست
- اعتبار سنجی
13. تمرین : طراحی تست های عملیاتی برای activity ها
14. مطالبی اضافه بر سازمان درباره ی تست برنامه ها در اندروید
- کلاس های اضافی رابط برنامه سازی کاربردی تست برنامه های اندروید
- android test group
- استفاده از تست های Flaky (حاشیه نویسی @FlakyTest)
15. تمرین : اجرای تست به وسیله ی Apache ant (حاشیه نویسی Apache)
16. تست پردازش ناهمگام (asynch processing)
17. تست رابط کاربری (UI)
- تست تمامی مولفه های (cross-component) برنامه مورد نظر
- بهره گیری از کتابخانه ی uiautomator زبان جاوا برای ایجاد تست های رابط کاربری
- استفاده از ابزار uiautomatorviewer جهت تحلیل رابط کاربری برنامه
18. Monkey
19. Monkeyrunner
- انجام تست با استفاده از ابزار Monkeyrunner
- مثالی از کاربرد monkeyrunner
20 . ملزومات معمول تست در اندروید و رویکردهای مختلف حل مشکلات
- ثبت وقایع (logging) در سرویس دهنده یا سرور
- اعمال تغییرات در سیستم از طریق تست
21. چهارچوب کاری Espresso
22. دیگر testing framework های منبع آزاد
تست برنامه های اندروید به صورت خودکار
تست اپلیکیشن های اندروید پیش از توزیع
تست خودکار برنامه های اندروید به دلیل وجود تعداد زیاد و تنوع دستگاه های اندروید موجود در بازار از اهمیت بالایی برخوردار است . از آن جایی که امکان تست برنامه های کاربردی اندروید بر روی تمامی دستگاه های اندروید با نحوه پیکربندی های گوناگون امکان پذیر نیست, برنامه نویس ها غالباً برنامه های خود را روی دستگاه های با پیکربندی های مشخص و معمول آزمایش می کنند .
تست و اجرای برنامه پیش از توزیع آن به بهبود کارایی و پشتیبانی هرچه بهتر برنامه ی تولید شده اندروید کمک می کند .
چگونه باید برنامه هایی که برای سیستم عامل اندروید نوشته شده باشد را تست کرد ؟
تست برنامه های اندروید مبتنی بر JUnit صورت می گیرد . در کل می توان تست برنامه های اندروید را در دو طبقه یا رده ی کلی جای داد : تست هایی که فقط به JVM (دستگاه مجازی جاوا / Java virtual machine) نیاز دارند و تست هایی که به سیستم اندروید نیاز دارند .
در صورت امکان باید unit test (به شما این امکان را می دهد که کیفیت کد را پس از نوشتن آن چک کنید) را مستقیماً روی ماشین مجازی جاوا (JVM) اجرا کرد, به این خاطر که اجرای پروسه ی تست بر روی دستگاه مجازی جاوا به خصوص در مقایسه با زمانی که برای راه اندازی و اجرای فرایند تست بر روی دستگاه اندروید نیاز است به طور قابل چشم گیری سریع تر است .
خاصیت های Border به شما این مکان را می دهند که style، اندازه و رنگ حاشیه ی یک المان را تغییر دهید.
برنامه ی که هم اکنون فرایند تست روی آن پیاده می شود معمولاً تحت عنوان application under test شناخته می شود .
Unit test(تست برنامه بر حسب یک مولفه یا واحد( در مقابل integration test (تست کل برنامه)
unit test تنها قابلیت و کارایی یک مولفه ی معین را تست می کند .
فرض کنیم یک دکمه در activity داریم که با زدن آن activity ی دیگری راه اندازی می شود . Unit test بررسی می کند آیا intent مربوطه صادر شده یا نه و به اجرای activity دوم توجهی ندارد. این در حالی است که integration test علاوه بر بررسی intent, activity را نیز در نظر گرفته و چک می کند .
اندروید چندین کلاس متعدد ویژه ی هر دو تست فوق ارائه می دهد .
اندروید و JUnit 3
در حال حاضر API تست برنامه های اندروید مبتنی بر JUnit 3 و نه بر پایه ی JUnit 4 .
نکته : گوگل در حال حاضر تلاش های خود را بر روی بروز رسانی testing framework (چهارچوب کاری تست) متمرکز کرده . این تلاش عبارتند از جدا سازی و تفکیک testing framework از android application framework (چهارچوب کاری نرم افرازی اندروید) . همچنین گوگل سعی دارد طی این فرایند بروز رسانی testing framework را به JUnit4ارتقإ دهد .
JUnit 3 مستلزم این است کلاس های آزمایشی شما از کلاس JUnit 3 junit.framework.TestCase به ارث ببرد.
در JUnit 3, متدهای آزمایشی (test method) ها باید با پیشوند test آغاز شوند . متد نصب و راه اندازی (setup method) طبیعتاً باید () setup و متد پاک سازی (cleanup method) نهایی نیز باید teardown () خوانده شود .
کدام اجزإ را باید در اپلیکیشن های متعارف اندروید تست کرد
جدول ذیل تمامی نواحی مهم که باید در اپلیکیشن اندروید چک را فهرست کرده است .
جدول 1.
تست پیش شرط ها
در فرایند تست کردن اندروید توصیه می شود که متد () testPreconditions فراخوانی کنید زیرا که تابع مذکور همه ی پیش شرط های لازم برای دیگر تست ها را بررسی و آزمایش می کند . چنانچه این عملیات (method) با شکست مواجه شد, شما به سرعت متوجه خواهید شد که ملزومات یا پیش شرط ها نقض شده اند .
تست رابط کاربری (UI)
اندروید تنها به نخ اصلی (main thread) اجازه ی اصلاح (modify) رابط کاربری را می دهد . در صورت لزوم اجرای تست در نخ اصلی, می توان تست مورد نظر را با سیستم علامت گذاری (annotation) @UIThreadTest حاشیه نویسی (annotate) کرد . از این تست ها نمی توان برای کنترل چرخه ی حیات (مرتبط با) مولفه ها استفاده کرد, به این خاطر که تست های ذکر شده در همان نخی اجرا می شوند که برنامه ی کاربردی تحت آزمایش در آن اجرا می شود . در صورت داشتن چنین تست هایی و همچنین در صورت نیاز به اصلاح (modify) رابط کاربری, از تابع Activity.runOnUiThread(Runnable) بهره بگیرید .
اجرای تست روی یک سرویس دهنده (یا سرور) بدون صفحه نمایش (Display) / headless
جهت انجام پروسه ی تست بدون صفحه نمایش (headless), کافی است پارامتر -no-window adb را تخصیص دهید .
کدام دسته از تست ها باید روی سیستم اندروید انجام شوند ؟
تست کلاس های متعارف و استاندارد جاوا
اگر کلاس های مورد نظر API اندروید را صدا نمی زنند, در آن صورت می توانید از JUnit (یا هر چهارچوب تستی دیگر جاوا) بدون هیچ گونه محدودیت استفاده کنید .
مزایای استفاده از روش فوق این است که می توان از هر هرگونه ابزار و چهارچوب تستی جاوا بر حسب مولفه (Java unit testing framework) استفاده کرد . گفتنی است که سرعت اجرای این نوع تست (test unit) در مقایسه با تست هایی که ملزم سیستم اندروید هستند به طور چشمگیری بالاتر است .
تست کلاس هایی که از رابط برنامه سازی کاربردی اندروید (API) بهره می گیرند
چنانچه قصد دارید کدی را تست کنید که از API اندروید بهره می گیرد, در آن صورت ملزوم به اجرای تست بر روی دستگاه اندروید هستید . متأسفانه, این امر باعث می شود فرایند اجرای تست زمان بیشتری را به خود اختصاص دهد, زیرا که فایل android.jar دربردارنده ی کد چهارچوب کاری اندروید (Android framework code) نبوده و تنها حاوی test stub هایی است ویژه ی حاشیه نویسی یا امضإ نوع (type signature), نوع و متدها می باشد . فایل کتابخانه ی جاوا JAR (java archive) فقط برای مترجم یا کامپایلر جاوا پیش از اجرا و راه اندازی بر روی دستگاه اندروید مورد استفاده قرار می گیرد و به صورت پیش فرض به برنامه ی کاربردی شما اضافه نمی شود . پس از اینکه برنامه ی کاربردی بر روی دستگاه پیاده شد, فایل android.jar نیز روی دستگاه اجرا می شود . فراخوانی توابع از فایل android.jar (کتابخانه ی جاوا) یک RuntimeException("Stub!") پرتاب (throw) می کند .
این امر تقریباً تست کلاس های چهارچوب کاری اندروید (android framework classes) را روی ماشین مجازی جاوا (JVM) بدون کتابخانه های اضافی غیر ممکن می سازد .
پروژه های آزمایشی اندروید – اجرا و راه اندازی تست ها
ایجاد پروژه ی آزمایشی با استفاده از ابزار توسعه و برنامه سازی اندروید (ADT)
نحوه ی صحیح سازمان دهی تست ها این است که آن ها را در پروژه های تستی اندروید یا پوشه ی منبع (source folder) جداگانه جای گذاری کنید . افزونه ی (plug-in) ابزار توسعه و برنامه سازی اندروید (ADT) ویژه ی محیط برنامه نویسی Eclipse بر استفاده از اشیإ مجزا تاکیید دارد .
به جای مولفه های اندروید (android component), برنامه ی آزمایشی اندروید (android test application) دربردارنده ی چندین کلاس آزمایشی (test class) است .
پروژه ی تحت آزمایش باید به عنوان وابستگی (dependency = وضعیتی که شئی از تابع شئ دیگری بهره می گیرد) به پروژه ی آزمایشی اضافه شود . فایل AndroidManifest.xml باید مشخص کند که پروژه ی آزمایشی (test project) از کتابخانه ی android.test.runner استفاده کرده و اجرا کننده ی تست (test runner) را برای unit test تعیین کند .
یک پروژه ی آزمایشی همچنین پکیج برنامه ی کاربردی را که باید مورد تست قرار گیرد در فایل AndroidManifest.xml تحت خصیصه ی android:targetPackage آزمایش کند . لیستینگ ذیل مثالی برای پروژه ی آزمایشی ارائه می دهد .
ایجاد پروژه ی آزمایشی با استفاده از ابزار توسعه و برنامه سازی اندروید (ADT)
تجهیزاتی که در ابزار طراحی و برنامه سازی اندروید (ADT) عرضه می شود از ایجاد پروژه های آزمایشی اندروید به وسیله ی برنامه ی راهنما ایجاد پروژه (project creation wizard) پشتیبانی می کند . می توان با مراجعه به مسیر File → New → Other... → Android → Android Test Project در فهرست گزینش به ویزارد دسترسی پیدا کرد.
توصیه می شود که اسم پروژه ی تحت تست را مورد استفاده قرار داده و Test یا پسوند .test را به آن اضافه کنید, در این مقاله ی آموزشی از علامت گذاری (notation) .test استفاده می کنیم .
ویزارد dependency های لازم و ورودی (enrty) ها را به صورت خودکار در فایل AndroidManifest.xml ایجاد می کند .
راه اندازی فرایند تست اندروید
جهت اجرا و راه اندازی تست, روی کلاس آزمایشی راست کلیک کرده و گزینه ی As → Android JUnit Test را انتخاب کنید .
اشیإ یا کلاس های ساختگی و شبیه سازی شده برای تست (Mock objects)
اندروید کلاس های ساختگی یا شبیه سازی شده ای (mock classes) را برای چهارچوب کاری اندروید (Android framework) در پکیج های android.test و android.test.mock فراهم می کند . کلاس های نام برده به برنامه نویس اجازه می دهند تست ها را از سیستم در حال اجرا با باطل کردن (override) عملیات معمولی جدا کند .
زیر مهمترین و کارامدترین این اشیإ که می توان از آن ها برای تست برنامه در اندروید کمک گرفت فهرست شده است .
MockContext
MockResources
MockContentProvider
MockContentResolver
MockPackageManager
تمامی متدهایی که در روی اشیإ فوق بکار گرفته می شوند, استثنإ (exception) پرتاب / throw می کنند . در صورت لزوم می توانید این اشیإ را بسط داده یا به ارث برده (extend) و متدهای لازمه را بازنویسی (override) کنید .
استفاده از کلاس MockContext (شبیه سازی بستر برنامه)
می توان از MockContext به عنوان Context استفاده کرد .
نماینده های کلاس (class delegates) RenamingDelegatingContext یک زمینه معین (کانتکست) را صدا زده و با افزودن یک پیشوند به کلیه ی اسم فایل ها از عملیات مربوط به فایل و پایگاه داده پشتیبانی می کند . از این طریق شما می توانید مولفه یا کامپوننت های خود را بدون دستکاری پایگاه داده سیستم فایل روی دستگاه اندروید تست کنید .
تمرین : نوشتن یک روال یا روتین مجازی ((stub ویژه ی شبیه سازی دسترسی به فایل (mocking file access)
ایجاد برنامه ی کاربردی اندروید
در وهله ی اول یک اپلیکیشن جدید اندروید به نام com.vogella.android.test.fileaccess ایجاد کنید, سپس کلاس زیر را به این پروژه اضافه کنید .
public class Util {
public static void writeConfiguration(Context ctx) {
BufferedWriter writer = null;
try {
FileOutputStream openFileOutput = ctx.openFileOutput("config.txt", Context.MODE_PRIVATE);
openFileOutput.write("This is a test1.".getBytes());
openFileOutput.write("This is a test2.".getBytes());
} catch (Exception e) {
throw new RuntimeException(e);
} finally {
if (writer != null) {
try {
writer.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
نیازی نیست این کلاس را در اپلیکیشن اندروید خود بکار ببرید, زیرا که کلاس مزبور را بعداً به صورت جداگانه با استفاده از unit test آزمایش می کنیم .
ساخت پروژه ی آزمایشی, تست
در این بخش از تمرین به نوشتن یک تست برای کلاس می پردازیم (این تست با استفاده از چهارچوب شبیه سازی اندروید / Android mock framework به سیستم فایل اندروید write می کند) .
ابتدا FileOutputStream سفارشی که FileOutputStream را به ارث می برد بنویسید (رایت کنید) . FileOutputStream باید در تابع write() بخاطر داشته باشد که در کل چند مرتبه این متد فراخوانده شده است, هیچ نیازی نیست داخل این متد چیزی بنویسد .
public class StubOutputStream extends FileOutputStream {
public StubOutputStream() throws FileNotFoundException {
super(FileDescriptor.out);
}
// count number of calls, don't bother to really write something
@Override
public void write(byte[] buffer) throws IOException {
fileWrites++;
}
}
MockContext سفارشی خود را نوشته و متد openFileOutput() را بازنویسی کنید .
// this methods belong into your class which extends TestCase
MockContext context = new MockContext() {
public java.io.FileOutputStream openFileOutput(String name, int mode)
throws java.io.FileNotFoundException {
return new StubOutputStream();
};
};
اگرچه سیستم اندروید از واژه ی Mock استفاده می کند, مطابق با ادبیات تست در حقیقت این کلاس یک stub است .
برای نوشتن تست از mock های خود کمک بگیرید و همچنین اطمینان حاصل کنید متد write() دوبار صدا زده می شود .
public void testWriteConfigurationShouldAccessFileSystemTwice() {
assertEquals("No file writes yet", fileWrites, 0);
Util.writeConfiguration(context);
assertEquals("Failed to write twice", 2, fileWrites);
}
متأسفانه نوشتن stub برای چهارچوب شبیه سازی اندروید (Android mocking framework) مستلزم کدنویسی سنگین و است . تا حد امکان باید از mocking framework هایی مثل Mockito استفاده کنید .
تست اپلیکیشن
کلاس اپلیکیشن (app class) دربردانده ی منطق, داده و تنظیماتی (settings) است که به کل برنامه ی کاربردی مربوط می شود, به همین دلیل هم هست که باید شئ مزبور را امتحان کرده و از کارکرد صحیح آن اطمینان حاصل کنید .
به منظور تست شئ برنامه (android application object) از کلاس ApplicationTestCaseکمک می گیریم .
نکته : اجراگر تست های اندروید ( InstrumentationTestRunner ) به صورت خودکار یک نمونه از اپلیکیشن را طی مرحله یا پروسه ی مقداردهی اولیه آن ایجاد می کند . در صورت انجام پردازش ناهمگام در متد onCreate باید به این موضوع توجه داشته باشید .
تست سرویس
به منظور تست یک سرویس لازم است از کلاس ServiceTestCase استفاده کنید . کلاس ذکر شده جهت تعامل با سرویس مورد نظر توابع bindService() و startService() را ارائه می دهد . متد bindService() بلافاصله یک شئ IBinder بدون بازفراخوان (callback) برمی گرداند . توجه داشته باشید که باید تنها یک intent به عنوان ورودی ارسال کنید .
از آنجایی که طول مدت پردازش متفاوت است, تست و آزمایش پردازش ناهمگام در سرویس ها یک چالش محسوب می شود .
توصیه می شود این را هم بررسی کنید آیا سرویس توانایی این را دارد که چندیدن فراخوانی را از تابع startService() به درستی مدیریت کند . این فقط اولین فراخوانی تابع startService() است که متد onCreate() سرویس را فعال سازی می کند, اما تمام فراخوانی ها منجر به فعال سازی onStartCommand() سرویس می شوند .
تست Content Provider
جهت آزمودن Content Provider, معمولاً از کلاس ProviderTestCase2 استفاده می شود . کلاس مزبور به صورت خودکار provider تحت آزمایش را مقداردهی اولیه کرده و یک شئ IsolatedContext را که از سیستم اندروید جداسازی شده ولی هنوز اجازه ی دسترسی به فایل و پایگاه داده را می دهد, درج می کند .
استفاده از شئ IsolatedContext باعث می شود تستی که روی provider انجام می گیرد خود دستگاه را تحت تاثیر قرار ندهد .
ProviderTestCase2 همچنین دسترسی به MockContentResolver را با فراخوانی متد getMockCOnktentResolver() امکان پذیر می سازد .
برنامه نویس باید تمامی عملیات provider را تست کند, همچنین بررسی کند در صورت فراخوانی provider با URI(شناسه ی یکنواخت منبع) یا projection نامعتبر چه اتفاقی رخ می دهد .
تست Loader
به منظور تست loader, لازم است از کلاس LoaderTestCase استفاده کنید .
نقاط شروع تست در اندروید (test hooks into android framework) کلاس instrumentation
رابط برنامه سازی کاربردی تست اندروید (android testing API) نقاط شروعی برای تست (test hook) در مولفه و چرخه ی حیات اپلیکیشن اندروید فراهم می کند . این hook ها مصطلح به instrumentation API هستند و به تست ها این اجازه را می دهند که چرخه ی حیات و رخدادهای مربوط به تعامل کاربر (user interaction) را کنترل و اداره کنند .
تحت شرایط عادی اپلیکیشن شما تنها می تواند به رخدادهای مربوط به تعامل کاربر و چرخه ی حیات واکنش نشان دهد . به عنوان مثال زمانی که اندروید برنامه ی مورد نظر را ایجاد می کند, متد onCreate () روی activity شما فراخوانی می شود و یا هنگامی که کاربر یک دکمه یا کلید را فشار می دهد, کد مربوطه فراخوانی می شود . با استفاده از instrumentation شما می توانید این رویدادها را از طریق تست کنترل کنید .
تنها کلاس های آزمایشی مبتنی بر instrumentation (instrumentation-based test class), به برنامه نویس امکان می دهد که رویدادهای مربوط به کلید (key events یا touch events) را به برنامه ی کاربردی تحت تست ارسال کند .
به طور مثال, تستی که برنامه نویس راه اندازی می کند قادر است تابع getActivity () را صدا بزند که activity را راه اندازی کرده و activity تحت آزمایش را بازمی گرداند, پس از آن برنامه نویس می تواند متد finish () را صدا زده و به دنبال آن بار دیگر تابع getActivity() را فراخوانی کند . سپس برنامه نویس می تواند بررسی کند آیا اپلیکیشن حالت خود را به درستی احیإ می کند یا خیر .
رابط برنامه سازی کاربردی Android instrumentation به برنامه نویس این امکان را می دهد که هر دو پروژه ی آزمایشی و اصلی اندروید را در یک فرایند اجرا کند تا از این طریق پروژه ی آزمایشی بتواند متدهای پروژه ی اندروید را مستقیماً فراخوانی کند .
چگونگی اجرا ی تست ها توسط سیستم اندروید
InstrumentationTestRunner در واقع test runner پایه برای تمامی تست های اندروید محسوب می شود. این test runner متدهای آزمایشی را راه اندازی و بارگذاری می کند و به وسیله ی instrumentation API با سیستم اندروید ارتباط برقرار می کند . InstrumentationTestRunnerاز طریق instrumentation API با سیستم اندروید ارتباط برقرار می کند. در صورت راه اندازی پروسه ی تست ویژه ی اپلیکیشن اندروید, سیستم اندروید کلیه ی فرایندهای برنامه که در حال تست شدن هستند را ناگهان متوقف (kill) کرده و یک نمونه (instance) جدید بارگذاری می کند . لازم به ذکر است که راه اندازی برنامه ی کاربردی وظیفه ی test method (متدهای آزمایشی) هست . test method ها چرخه ی حیات (life-cycle) مولفه (component) های برنامه را کنترل می کنند .
Test runner همچنین متد onCreate() برنامه و activity تحت آزمایش را حین مقداردهی اولیه آن فرا می خواند .