تنظيم صفحاتك في مجموعات
يمكنك حفظ المحتوى وتصنيفه حسب إعداداتك المفضّلة.
توضّح هذه الصفحة المبادئ الأساسية لاختبار تطبيقات Android، بما في ذلك أفضل الممارسات الأساسية وفوائدها.
مزايا الاختبار
تعد مرحلة الاختبار جزءًا لا يتجزأ من عملية تطوير التطبيقات. ويمكنك التحقّق من سلامة تطبيقك وفعالية وظائفه وسهولة استخدامه قبل إصداره للعلن من خلال إجراء سلسلة من الاختبارات على التطبيق بشكل منتظم.
يمكنك اختبار تطبيقك يدويًا من خلال التنقّل فيه. يمكنك استخدام أجهزة ومحاكيات مختلفة، وتغيير لغة النظام، ومحاولة إنشاء كل خطأ يواجهه المستخدم أو الانتقال إلى كل مسار مستخدم.
ومع ذلك، لا يمكن توسيع نطاق الاختبار اليدوي بشكل جيد، وقد يكون من السهل إغفال حالات تراجع في سلوك تطبيقك. يتضمّن الاختبار الآلي استخدام أدوات
تُجري الاختبارات نيابةً عنك، ما يتيح لك الحصول على نتائج أسرع وأكثر تكرارًا، كما يقدّم لك بشكل عام
ملاحظات أكثر قابلية للتنفيذ حول تطبيقك في مرحلة مبكرة من عملية التطوير.
أنواع الاختبارات في Android
تتسم تطبيقات الأجهزة الجوّالة بالتعقيد ويجب أن تعمل بشكل جيد في العديد من البيئات. وبالتالي، هناك أنواع عديدة من الاختبارات.
الموضوع
على سبيل المثال، هناك أنواع مختلفة من الاختبارات حسب الموضوع:
الاختبار الوظيفي: هل يؤدي تطبيقي الوظائف المطلوبة منه؟
اختبار الأداء: هل يتم إجراؤه بسرعة وكفاءة؟
اختبار إمكانية الوصول: هل يعمل التطبيق بشكل جيد مع خدمات تسهيل الاستخدام؟
اختبار التوافق: هل يعمل التطبيق بشكل جيد على كل جهاز ومستوى واجهة برمجة تطبيقات؟
النطاق
تختلف الاختبارات أيضًا حسب الحجم أو درجة العزل:
لا تتحقّق اختبارات الوحدات أو الاختبارات الصغيرة إلا من جزء صغير جدًا من التطبيق، مثل طريقة أو فئة.
تتحقّق اختبارات التكامل أو الاختبارات الكبيرة من أجزاء أكبر من التطبيق في الوقت نفسه، مثل شاشة كاملة أو مسار المستخدم.
الاختبارات المتوسطة هي بين الاختبارات الصغيرة والكبيرة، وتتحقّق من التكامل بين وحدتَين أو أكثر.
الشكل 1: نطاقات الاختبار في تطبيق نموذجي.
هناك العديد من الطرق لتصنيف الاختبارات. ومع ذلك، فإنّ أهم فرق
بالنسبة إلى مطوّري التطبيقات هو مكان تنفيذ الاختبارات.
الاختبارات المزوّدة بأدوات مقابل الاختبارات المحلية
يمكنك إجراء الاختبارات على جهاز Android أو على جهاز كمبيوتر آخر:
يتم تنفيذ الاختبارات المبرمَجة على جهاز Android، سواء كان جهازًا فعليًا أو محاكيًا.
يتم إنشاء التطبيق وتثبيته إلى جانب تطبيق اختبار يدرج الأوامر ويقرأ الحالة. عادةً ما تكون الاختبارات المزوّدة بأدوات هي اختبارات واجهة مستخدم، حيث يتم تشغيل تطبيق ثم التفاعل معه.
يتم تنفيذ الاختبارات المحلية على جهاز التطوير أو الخادم، لذا تُعرف أيضًا باسم الاختبارات من جهة المضيف. وعادةً ما تكون صغيرة وسريعة، وتعمل على عزل العنصر الخاضع للاختبار عن بقية التطبيق.
الشكل 2: أنواع مختلفة من الاختبارات حسب مكان تنفيذها.
ليست كل اختبارات الوحدات محلية، وليست كل الاختبارات الشاملة يتم تشغيلها على جهاز. على سبيل المثال:
الاختبار المحلي الكبير: يمكنك استخدام محاكي Android يعمل محليًا، مثل Robolectric.
الاختبار الصغير الذي يتضمّن أدوات: يمكنك التأكّد من أنّ الرمز البرمجي يعمل بشكل جيد مع إحدى ميزات إطار العمل، مثل قاعدة بيانات SQLite. يمكنك إجراء هذا الاختبار على أجهزة متعددة للتحقّق من عملية الدمج مع إصدارات متعددة من SQLite.
أمثلة
توضّح المقتطفات التالية كيفية التفاعل مع واجهة المستخدم في اختبار واجهة مستخدم مزوَّد بأدوات ينقر على أحد العناصر ويتأكّد من عرض عنصر آخر.
Espresso
// When the Continue button is clickedonView(withText("Continue")).perform(click())// Then the Welcome screen is displayedonView(withText("Welcome")).check(matches(isDisplayed()))
واجهة مستخدم الإنشاء
// When the Continue button is clickedcomposeTestRule.onNodeWithText("Continue").performClick()// Then the Welcome screen is displayedcomposeTestRule.onNodeWithText("Welcome").assertIsDisplayed()
يعرض هذا المقتطف جزءًا من اختبار وحدة لـ ViewModel (اختبار محلي على الجهاز المضيف):
// Given an instance of MyViewModelvalviewModel=MyViewModel(myFakeDataRepository)// When data is loadedviewModel.loadData()// Then it should be exposing dataassertTrue(viewModel.data!=null)
بنية قابلة للاختبار
في بنية التطبيق القابلة للاختبار، يتّبع الرمز البرمجي بنية تتيح لك اختبار أجزاء مختلفة منه بسهولة بشكل منفصل. تتضمّن التصاميم المعمارية القابلة للاختبار مزايا أخرى، مثل تحسين قابلية القراءة والصيانة والتوسّع وإعادة الاستخدام.
تؤدي البنية غير القابلة للاختبار إلى ما يلي:
اختبارات أكبر وأبطأ وأكثر تقطعًا قد تحتاج الفئات التي لا يمكن إجراء اختبارات الوحدة لها إلى تغطيتها باختبارات دمج أو اختبارات واجهة مستخدم أكبر.
فرص أقل لاختبار سيناريوهات مختلفة تستغرق الاختبارات الأكبر وقتًا أطول،
لذا قد يكون اختبار جميع الحالات المحتملة للتطبيق أمرًا غير واقعي.
إذا كان بإمكانك استخراج جزء من دالة أو فئة أو وحدة من الباقي، يصبح اختبارها أسهل وأكثر فعالية. تُعرف هذه الممارسة باسم الفصل، وهي المفهوم الأكثر أهمية في البنية القابلة للاختبار.
تشمل تقنيات الفصل الشائعة ما يلي:
قسِّم التطبيق إلى طبقات، مثل العرض التقديمي والنطاق والبيانات. يمكنك أيضًا تقسيم التطبيق إلى وحدات، واحدة لكل ميزة.
تجنَّب إضافة منطق إلى الكيانات التي تتضمّن تبعيات كبيرة، مثل الأنشطة واللقطات. استخدِم هذه الفئات كنقاط دخول إلى إطار العمل، وانقل واجهة المستخدم ومنطق النشاط التجاري إلى مكان آخر، مثل Composable أو ViewModel أو طبقة النطاق.
تسهيل عملية استبدال التبعيات على سبيل المثال، استخدِم الواجهات بدلاً من عمليات التنفيذ المحدّدة. استخدِم تضمين التبعية حتى إذا كنت لا تستخدم إطار عمل لتضمين التبعية.
بدلاً من ذلك، إذا كنت تريد إنشاء اختبارك الأول والتعلم من خلال التجربة، يمكنك الاطّلاع على الدروس التطبيقية حول الاختبار.
يخضع كل من المحتوى وعيّنات التعليمات البرمجية في هذه الصفحة للتراخيص الموضحّة في ترخيص استخدام المحتوى. إنّ Java وOpenJDK هما علامتان تجاريتان مسجَّلتان لشركة Oracle و/أو الشركات التابعة لها.
تاريخ التعديل الأخير: 2025-08-08 (حسب التوقيت العالمي المتفَّق عليه)
[[["يسهُل فهم المحتوى.","easyToUnderstand","thumb-up"],["ساعَدني المحتوى في حلّ مشكلتي.","solvedMyProblem","thumb-up"],["غير ذلك","otherUp","thumb-up"]],[["لا يحتوي على المعلومات التي أحتاج إليها.","missingTheInformationINeed","thumb-down"],["الخطوات معقدة للغاية / كثيرة جدًا.","tooComplicatedTooManySteps","thumb-down"],["المحتوى قديم.","outOfDate","thumb-down"],["ثمة مشكلة في الترجمة.","translationIssue","thumb-down"],["مشكلة في العيّنات / التعليمات البرمجية","samplesCodeIssue","thumb-down"],["غير ذلك","otherDown","thumb-down"]],["تاريخ التعديل الأخير: 2025-08-08 (حسب التوقيت العالمي المتفَّق عليه)"],[],[],null,["# Fundamentals of testing Android apps\n\nThis page outlines the core tenets of testing Android apps, including the\ncentral best practices and their benefits.\n\nBenefits of testing\n-------------------\n\nTesting is an integral part of the app development process. By running tests\nagainst your app consistently, you can verify your app's correctness, functional\nbehavior, and usability before you release it publicly.\n\nYou can *manually* test your app by navigating through it. You might use\ndifferent devices and emulators, change the system language, and try to generate\nevery user error or traverse every user flow.\n\nHowever, manual testing scales poorly, and it can be easy to overlook\nregressions in your app's behavior. *Automated testing* involves using tools\nthat perform tests for you, which is faster, more repeatable, and generally\ngives you more actionable feedback about your app earlier in the development\nprocess.\n\nTypes of tests in Android\n-------------------------\n\nMobile applications are complex and must work well in many environments. As\nsuch, there are many types of tests.\n\n### Subject\n\nFor example, there are different types of tests depending on the *subject*:\n\n- **Functional testing**: does my app do what it's supposed to?\n- **Performance testing**: does it do it quickly and efficiently?\n- **Accessibility testing**: does it work well with accessibility services?\n- **Compatibility testing**: does it work well on every device and API level?\n\n### Scope\n\nTests also vary depending on *size* , or *degree of isolation*:\n\n- **Unit tests** or **small tests** only verify a very small portion of the app, such as a method or class.\n- **End-to-end** tests or **big tests** verify larger parts of the app at the same time, such as a whole screen or user flow.\n- **Medium tests** are in between and check the **integration** between two or more units.\n\n**Figure 1**: Test scopes in a typical application.\n\nThere are many ways to classify tests. However, the most important distinction\nfor app developers is where tests run.\n\nInstrumented versus local tests\n-------------------------------\n\nYou can run tests on an Android device or on another computer:\n\n- **Instrumented tests** run on an Android device, either physical or emulated. The app is built and installed alongside a *test app* that injects commands and reads the state. Instrumented tests are usually UI tests, launching an app and then interacting with it.\n- **Local tests** execute on your development machine or a server, so they're also called *host-side tests*. They're usually small and fast, isolating the subject under test from the rest of the app.\n\n**Figure 2**: Different types of tests depending on where they run.\n\nNot all unit tests are local, and not all end-to-end tests run on a device. For\nexample:\n\n- **Big local test** : You can use an Android simulator that runs locally, such as [Robolectric](/training/testing/local-tests/robolectric).\n- **Small instrumented test**: You can verify that your code works well with a framework feature, such as a SQLite database. You might run this test on multiple devices to check the integration with multiple versions of SQLite.\n\n### Examples\n\nThe following snippets demonstrate how to interact with the UI in an\n*instrumented UI test* that clicks on an element and verifies that another\nelement is displayed. \n\n### Espresso\n\n // When the Continue button is clicked\n onView(withText(\"Continue\"))\n .perform(click())\n\n // Then the Welcome screen is displayed\n onView(withText(\"Welcome\"))\n .check(matches(isDisplayed()))\n\n### Compose UI\n\n // When the Continue button is clicked\n composeTestRule.onNodeWithText(\"Continue\").performClick()\n\n // Then the Welcome screen is displayed\n composeTestRule.onNodeWithText(\"Welcome\").assertIsDisplayed()\n\nThis snippet shows part of a *unit test* for a ViewModel (local, host-side\ntest): \n\n // Given an instance of MyViewModel\n val viewModel = MyViewModel(myFakeDataRepository)\n\n // When data is loaded\n viewModel.loadData()\n\n // Then it should be exposing data\n assertTrue(viewModel.data != null)\n\nTestable architecture\n---------------------\n\nWith a testable app architecture, the code follows a structure that allows you\nto easily test different parts of it in isolation. Testable architectures have\nother advantages, such as better readability, maintainability, scalability, and\nreusability.\n\nAn architecture that is *not testable* produces the following:\n\n- Bigger, slower, more flaky tests. Classes that can't be unit-tested might have to be covered by bigger integration tests or UI tests.\n- Fewer opportunities for testing different scenarios. Bigger tests are slower, so testing all possible states of an app might be unrealistic.\n\nTo learn more about architecture guidelines, see the [guide to app\narchitecture](/jetpack/guide).\n\n### Approaches to decoupling\n\nIf you can extract part of a function, class, or module from the rest, testing\nit is easier, and more effective. This practice is known as decoupling, and it\nis the concept most important to testable architecture.\n\nCommon decoupling techniques include the following:\n\n- Split an app into *layers* such as Presentation, Domain, and Data. You can also split an app into *modules*, one per feature.\n- Avoid adding logic to entities that have large dependencies, such as activities and fragments. Use these classes as entry points to the framework and move *UI and business logic* elsewhere, such as to a Composable, ViewModel, or domain layer.\n- Avoid direct *framework dependencies* in classes containing business logic. For example, [don't use Android Contexts in ViewModels](https://medium.com/androiddevelopers/locale-changes-and-the-androidviewmodel-antipattern-84eb677660d9).\n- Make dependencies easy to *replace* . For example, use [interfaces](https://en.wikipedia.org/wiki/Interface_segregation_principle) instead of concrete implementations. Use [Dependency injection](/training/dependency-injection) even if you don't use a DI framework.\n\nNext steps\n----------\n\nNow that you know why you should test and the two main types of tests, you can\nread [What to test](/training/testing/fundamentals/what-to-test) or learn about [Testing strategies](/training/testing/fundamentals/strategies)\n\nAlternatively, if you want to create your first test and learn by doing, check\nout the [Testing codelabs](/codelabs/advanced-android-kotlin-training-testing-basics)."]]