اصول تست برنامه های اندروید

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

مزایای آزمایش

تست بخشی جدایی ناپذیر از فرآیند توسعه اپلیکیشن است. با اجرای مداوم آزمایش‌ها بر روی برنامه خود، می‌توانید صحت، رفتار عملکردی و قابلیت استفاده برنامه خود را قبل از انتشار عمومی تأیید کنید.

شما می توانید به صورت دستی برنامه خود را با پیمایش در آن تست کنید. ممکن است از دستگاه ها و شبیه سازهای مختلف استفاده کنید، زبان سیستم را تغییر دهید و سعی کنید هر خطای کاربر را ایجاد کنید یا از هر جریان کاربر عبور کنید.

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

انواع تست در اندروید

برنامه های موبایل پیچیده هستند و باید در بسیاری از محیط ها به خوبی کار کنند. به این ترتیب، انواع مختلفی از آزمون ها وجود دارد.

موضوع

به عنوان مثال، بسته به موضوع ، انواع مختلفی از آزمون ها وجود دارد:

  • تست عملکردی : آیا برنامه من آنچه را که قرار است انجام می دهد؟
  • تست عملکرد : آیا آن را به سرعت و کارآمد انجام می دهد؟
  • تست دسترسی : آیا با خدمات دسترسی به خوبی کار می کند؟
  • تست سازگاری : آیا در هر دستگاه و سطح API به خوبی کار می کند؟

دامنه

آزمایش ها نیز بسته به اندازه یا درجه ایزوله متفاوت است:

  • تست‌های واحد یا تست‌های کوچک فقط بخش بسیار کوچکی از برنامه را تأیید می‌کنند، مانند روش یا کلاس.
  • آزمایش‌های انتها به انتها یا آزمایش‌های بزرگ ، بخش‌های بزرگ‌تری از برنامه را به طور همزمان تأیید می‌کنند، مانند کل صفحه یا جریان کاربر.
  • تست های متوسط ​​در بین هستند و ادغام بین دو یا چند واحد را بررسی می کنند.
آزمون ها می توانند کوچک، متوسط ​​یا بزرگ باشند.
شکل 1 : محدوده آزمایش در یک برنامه معمولی.

روش های زیادی برای طبقه بندی آزمون ها وجود دارد. با این حال، مهم ترین تمایز برای توسعه دهندگان برنامه، محل اجرای آزمایش ها است.

ابزار دقیق در مقابل تست های محلی

می‌توانید آزمایش‌ها را روی دستگاه Android یا رایانه دیگری اجرا کنید:

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

همه تست‌های واحد محلی نیستند و همه تست‌های سرتاسری روی یک دستگاه اجرا نمی‌شوند. به عنوان مثال:

  • آزمایش محلی بزرگ : می‌توانید از شبیه‌ساز اندرویدی استفاده کنید که به صورت محلی اجرا می‌شود، مانند Robolectric .
  • تست ابزار کوچک : می‌توانید تأیید کنید که کد شما با یک ویژگی چارچوب، مانند پایگاه داده SQLite، به خوبی کار می‌کند. برای بررسی ادغام با چندین نسخه SQLite، ممکن است این آزمایش را روی چندین دستگاه اجرا کنید.

نمونه ها

قطعه‌های زیر نحوه تعامل با رابط کاربری را در یک آزمایش UI ابزاردار که روی یک عنصر کلیک می‌کند و تأیید می‌کند که عنصر دیگری نمایش داده می‌شود، نشان می‌دهد.

اسپرسو

// When the Continue button is clicked
onView(withText("Continue"))
    .perform(click())

// Then the Welcome screen is displayed
onView(withText("Welcome"))
    .check(matches(isDisplayed()))

نوشتن رابط کاربری

// When the Continue button is clicked
composeTestRule.onNodeWithText("Continue").performClick()

// Then the Welcome screen is displayed
composeTestRule.onNodeWithText("Welcome").assertIsDisplayed()

این قطعه بخشی از یک تست واحد برای ViewModel (تست محلی، سمت میزبان) را نشان می دهد:

// Given an instance of MyViewModel
val viewModel = MyViewModel(myFakeDataRepository)

// When data is loaded
viewModel.loadData()

// Then it should be exposing data
assertTrue(viewModel.data != null)

تعریف استراتژی تست

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

یک استراتژی تست خوب تعادل مناسبی بین وفاداری یک تست، سرعت آن و قابلیت اطمینان آن پیدا می کند. شباهت محیط تست به یک دستگاه واقعی وفاداری تست را تعیین می کند. تست های وفاداری بالاتر روی دستگاه های شبیه سازی شده یا خود دستگاه فیزیکی اجرا می شود. آزمایش‌های وفاداری کمتر ممکن است در JVM ایستگاه کاری محلی شما اجرا شود. آزمون‌های با وفاداری بالا اغلب کندتر هستند و به منابع بیشتری نیاز دارند، بنابراین هر آزمونی نباید یک آزمون با وفاداری بالا باشد.

تست های پوسته پوسته شدن

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

معماری قابل آزمایش

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

معماری ای که قابل آزمایش نیست موارد زیر را ایجاد می کند:

  • تست های بزرگتر، کندتر، پوسته پوسته تر. کلاس‌هایی که نمی‌توانند واحد تست شوند، ممکن است باید توسط تست‌های یکپارچه‌سازی بزرگ‌تر یا تست‌های UI پوشش داده شوند.
  • فرصت های کمتر برای آزمایش سناریوهای مختلف. آزمایش‌های بزرگ‌تر کندتر هستند، بنابراین آزمایش همه حالت‌های ممکن یک برنامه ممکن است غیرواقعی باشد.

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

رویکردهای جداسازی

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

تکنیک های متداول جداسازی شامل موارد زیر است:

  • یک برنامه را به لایه هایی مانند Presentation، Domain و Data تقسیم کنید. همچنین می‌توانید یک برنامه را به ماژول‌ها تقسیم کنید، یکی در هر ویژگی.
  • از افزودن منطق به موجودیت هایی که وابستگی های زیادی دارند، مانند فعالیت ها و قطعات، خودداری کنید. از این کلاس ها به عنوان نقاط ورود به چارچوب استفاده کنید و رابط کاربری و منطق تجاری را به جای دیگری مانند Composable، ViewModel یا لایه دامنه منتقل کنید.
  • از وابستگی مستقیم به چارچوب در کلاس های حاوی منطق تجاری اجتناب کنید. برای مثال، از Android Contexts در ViewModels استفاده نکنید .
  • جایگزینی وابستگی ها را آسان کنید. به عنوان مثال، به جای پیاده سازی های مشخص، از رابط ها استفاده کنید. حتی اگر از چارچوب DI استفاده نمی کنید ، از تزریق وابستگی استفاده کنید.

مراحل بعدی

اکنون که می‌دانید چرا باید تست کنید و دو نوع اصلی تست را می‌دانید، می‌توانید چه چیزی را تست کنیم .

از طرف دیگر، اگر می‌خواهید اولین آزمون خود را ایجاد کنید و با انجام آن بیاموزید، به Testing codelabs مراجعه کنید.