
ظهر نمط كائن الصفحة في اختبار الويب وأثبت أنه جيد جدًا هناك. عندما بدأت في أتمتة الاختبارات لتطبيقات Android ، كان أول ما فكرت فيه. بحثت عن معلومات على الشبكة ، سألت زملائي ، ومن حيث المبدأ ، لم أجد أسبابًا لعدم المحاولة. أقترح أن أرى ما جاء منها.
يتضمن كائن الصفحة الكلاسيكي مستويين من التجريد: عناصر الصفحة والاختبارات. أسلط الضوء على واحد آخر - منطق الأعمال. ألاحظ أن الطريقة التي تبني بها إطار العمل الخاص بك ستؤثر بشكل كبير على سهولة اختبارات الكتابة في المستقبل ، بالإضافة إلى دعمها. أحاول أن أجعل رمز الاختبار يبدو وكأنه حالة اختبار عادية كتبها اختبار عادي. على سبيل المثال أبدأ من النهاية:
- أنا أكتب رمز حالة اختبار جميل وواضح ،
- أقوم بتطبيق طرق من حالة الاختبار في طبقة منطق الأعمال ،
- أصف العناصر اللازمة للاختبار.
هذا النهج جيد لأننا لا نفعل أي شيء إضافي - الإطار مبني على قدر الحاجة حتى تعمل الاختبارات. يمكننا أن نقول أن هذا هو مفهوم MVP في الاختبار: لقد صنعوا قطعة بسرعة ، وقد بدأ بالفعل في جلب الفوائد. إذا قمت أولاً بكتابة آلاف الأسطر ، واصفةً صفحات تطبيقك وكيفية التفاعل معها ، وبعد ثلاثة أشهر تخرج من "الحفرة" للنقرة الأولى وتدرك أنه كان عليك القيام بكل شيء بشكل مختلف ، فإن معظم إبداعاتك ستحكم عليها إلى الأبد " جمع الغبار "في الطوابق السفلية لـ git ... المختبر الحقيقي يعرف أنه كلما تم العثور على خلل في وقت أقرب ، كان إصلاحه أرخص. استخدم هذا النهج في كل شيء - كتب اختبارًا في غضون ساعتين ، جربه ، لم يعجبه - ألقى به ، تعلم الدرس ، قاد.
لذا فإن المدخلات هي:
- تطبيق Android للتداول في البورصة ؛
- Java للعمل في نفس المكدس مع المطورين ؛
- الإطار الأساسي لواجهة مستخدم واجهة المستخدم ؛
- تحتاج إلى كتابة اختبار تسجيل دخول في التطبيق.
إعداد المشروع
نظرًا لأنني حاولت الاندماج قدر الإمكان في عملية التطوير ، لم أبدأ في إنشاء مشروع جديد. وفقًا
للوثائق ، يجب وضع اختبارات مفيدة في المجلد
src/androidTest/java
. في حالتي ، تم تكوين المجمع بالفعل ، إذا كان لديك شيء خاطئ ، فاقرأ عن
تكوين البناء . نحتاج أيضًا إلى بيئة تطوير و Android SDK و Emulator والأدوات وأدوات النظام الأساسي والمنصات اللازمة للمحاكي. إذا كنت تستخدم Android Studio ، فيمكن تثبيت كل هذا بسرعة من خلال مدير SDK:

طبقة اختبار
كما كتبت أعلاه ، سنقوم بأتمتة اختبار تسجيل الدخول في التطبيق. تذكر أن الرمز يجب أن يبدو كحالة اختبار عادية:
شرط مسبق: قم بتشغيل التطبيق.
الخطوة 1: قم بتسجيل الدخول باستخدام حساب myLogin / myPassword.
الخطوة 2: تحقق من اسم المستخدم الحالي.
النتيجة المتوقعة: المستخدم الحالي هو Ivan Ivanov.
إخلاء مسؤولية صغير: وفقًا لأفضل ممارسات اختبار التصميم ، في الشرط المسبق ، تحتاج إلى إنشاء / العثور على حساب. لقد أغفلت هذه اللحظة لبساطة المثال.سيبدو الفصل لدينا كما يلي:
@RunWith(AndroidJUnit4.class) public class LoginTests { private TestApplication myApp; @Before public void setUp() { myApp = new TestApplication(); } @Test public void testLogin() { myApp.login("myLogin","myPassword"); String currentUser = myApp.getCurrentUserName(); assertEquals("Wrong name", " ", currentUser); } @After public void tearDown() { myApp.close(); } }
منطق الأعمال
يستخدم الاختبار فئة
TestApplication()
getCurrentUserName()
:
login()
و
getCurrentUserName()
. بالإضافة إلى ذلك ، تحتاج إلى مُنشئ فئة (يشغل التطبيق فيه) وأسلوب
close()
. الواجهة واضحة:
public class TestApplication { private UiDevice device; private PageObject page; public TestApplication() { } public void login(String login, String password) { } public String getCurrentUserName() { return "" } public void close() { } }
سيتضمن مثيل لفصلنا متغيرين:
device
ينتمي إلى فئة android.support.test.uiautomator.UiDevice
- من خلاله نتفاعل مع جهازنا ؛page
، فئة PageObject
، التي PageObject
في القسم التالي.
لنبدأ بالمنشئ. في ذلك ، قم بإنشاء مثيلات من متغيراتنا وتشغيل التطبيق:
public TestApplication() {
بعض النصائح حول تشغيل التطبيقلمزيد من التحكم في التطبيق قيد الاختبار ، يمكنك إضافة توقعات لبدء المشغل (إذا قمت بتشغيل المحاكي "على البارد") والتطبيق نفسه. ينصح هذا أيضا في
الوثائق .
ملاحظة: لا يعد تشغيل التطبيق من خلال android.content.Context.getTargetContext()
مناسبًا إلا إذا كانت اختباراتك في نفس مشروع التطبيق نفسه. إذا كان بشكل منفصل ، سيكون من الضروري تشغيل القائمة.منطق العمل في الاختبار هو الخطوات المحددة التي يجب على المستخدم اتخاذها للحصول على أي نتيجة ذات مغزى (للمستخدم). يعد تسجيل الدخول تحت الموجات فوق الصوتية الخاصة بك نتيجة مهمة. الخطوات: انقر على زر "تسجيل الدخول" ، وأدخل اسم المستخدم في حقل "تسجيل الدخول" ، وأدخل كلمة المرور في حقل "كلمة المرور" ، وانقر فوق الزر "تسجيل الدخول". وبالتالي ، فإن طريقتنا مليئة بالخطوات:
public void login(String login, String password) { page.login().click(); page.loginEntry().setText(login); page.passwordEntry().setText(password); page.signIn().click(); }
للحصول على المستخدم الحالي ، كل شيء أبسط ، ما عليك سوى الحصول على قيمة الحقل:
public String getCurrentUserName() { return page.currentUserName().getText(); } }
ولإغلاق التطبيق ، ما عليك سوى النقر على زر الصفحة الرئيسية:
public void close() { device.pressHome(); }
وصف عناصر الصفحة
مفهوم هذه الطبقة هو أنه يجب أن ترجع العناصر جاهزة للاستخدام (في سياقنا ، هذه هي فئة
android.support.test.uiautomator.UiObject2
). أي أنه لا يجب على المستهلك القلق بشأن حالة الكائن ، إذا عاد ، فيمكنك التفاعل معه على الفور: انقر على النص أو املأه أو اقرأه. هذه نتيجة مهمة - في هذه الطبقة سنحقق التوقعات:
private UiObject2 getUiObject(BySelector selector) { return device.wait(Until.findObject(selector), 10000); }
سيتم استخدام الطريقة المحددة أعلاه من خلال الواجهة العامة لفئة
PageObject
بنا. مثال لحقل تسجيل الدخول:
public UiObject2 loginEntry() { return getUiObject(loginEntrySelector()); }
يبقى تحديد المحدد الذي سنجد به الحقل. يتم الحصول على مثيل
android.support.test.uiautomator.BySelector
ملائم باستخدام الأساليب الثابتة للفئة
android.support.test.uiautomator.By
. اتفقت مع التطور القائل بأنه في كل مكان ، كلما أمكن ، سيكون هناك معرف مورد فريد:
private BySelector loginEntrySelector() { return By.res(packageName, "login"); }
من السهل فحص الواجهة في أداة uiautomatorviewer المضمنة في حزمة الأدوات (مثبتة في قسم التحضير):

حدد العنصر المطلوب وفي قسم تفاصيل العقدة ، نلقي نظرة على معرف المورد. يتكون من اسم الحزمة ، وفي الواقع ، المعرف. حصلنا على اسم الحزمة في مُنشئ فئة
TestApplication
واستخدمناه عند إنشاء
PageObject
.
الكود الكامل:
فئة PageObject public class PageObject { private UiDevice device; private final String packageName; private BySelector loginButtonSelector() { return By.res(packageName, "user_view"); } private BySelector loginEntrySelector() { return By.res(packageName, "login"); } private BySelector passwordEntrySelector() { return By.res(packageName, "password"); } private BySelector signInSelector() { return By.res(packageName, "btnLogin"); } private BySelector userNameSelector() { return By.res(packageName, "user_name"); } public PageObject(UiDevice device, String packageName) { this.device = device; this.packageName = packageName; } public UiObject2 login() { return getUiObject(loginButtonSelector()); } public UiObject2 loginEntry() { return getUiObject(loginEntrySelector()); } public UiObject2 passwordEntry() { return getUiObject(passwordEntrySelector()); } public UiObject2 signIn() { return getUiObject(signInSelector()); } public UiObject2 currentUserName() { return getUiObject(userNameSelector()); } private UiObject2 getUiObject(BySelector selector) { return device.wait(Until.findObject(selector), 10000); } }
الاختبارات الجارية
هذا كل شيء ، يبقى للتشغيل. أولاً ، قم بتوصيل الجهاز أو بدء تشغيل المحاكي. تحقق من الاتصال بأمر
adb devices
(أداة adb المساعدة جزء من أدوات النظام الأساسي):
List of devices attached emulator-5554 device
إذا كان لديك درجة ، فقم بذلك
gradlew.bat connectedAndroidTest
والاستمتاع بكيفية "الروبوتات المحقونة ، وليس البشر" (ج).