يرشدك هذا البرنامج التعليمي خلال إنشاء تكوين اختبار "hello world" Trade Federation (TF) ويمنحك مقدمة عملية عن إطار عمل TF. بدءًا من بيئة التطوير ، ستقوم بإنشاء تكوين بسيط وإضافة ميزات.
يقدم البرنامج التعليمي عملية تطوير الاختبار كمجموعة من التمارين ، تتكون كل منها من عدة خطوات ، توضح كيفية إنشاء التكوين وتحسينه تدريجيًا. يتم توفير جميع نماذج التعليمات البرمجية التي تحتاجها لإكمال تكوين الاختبار ، ويتم تعليق عنوان كل تمرين بحرف يصف الأدوار المتضمنة في هذه الخطوة:
- د للمطور
- أنا من أجل التكامل
- R لاختبار عداء
بعد الانتهاء من البرنامج التعليمي ، سيكون لديك تكوين TF عامل وفهم العديد من المفاهيم المهمة في إطار عمل TF.
إنشاء الاتحاد التجاري
للحصول على تفاصيل حول إعداد بيئة تطوير TF ، راجع إعداد الجهاز . يفترض باقي هذا البرنامج التعليمي أن لديك shell مفتوحًا تمت تهيئته لبيئة TF.
من أجل التبسيط ، يوضح هذا البرنامج التعليمي إضافة تكوين وفئاته إلى مكتبة إطار عمل TF. يمكن أن يمتد هذا إلى تطوير الوحدات النمطية خارج شجرة المصدر عن طريق تجميع JAR المبرمج ، ثم تجميع الوحدات الخاصة بك مقابل JAR.
إنشاء فئة اختبار (D)
لنقم بإنشاء اختبار عالم مرحبًا يقوم فقط بتفريغ رسالة إلى stdout. عادةً ما يتم تنفيذ اختبار tradefed واجهة IRemoteTest. إليك تطبيق لـ HelloWorldTest:
package com.android.tradefed.example; import com.android.tradefed.device.DeviceNotAvailableException; import com.android.tradefed.invoker.TestInformation; import com.android.tradefed.log.LogUtil.CLog; import com.android.tradefed.result.ITestInvocationListener; import com.android.tradefed.testtype.IRemoteTest; public class HelloWorldTest implements IRemoteTest { @Override public void run(TestInformation testInfo, ITestInvocationListener listener) throws DeviceNotAvailableException { CLog.i("Hello, TF World!"); } }
احفظ نموذج الكود هذا في <tree>/tools/tradefederation/core/src/com/android/tradefed/example/HelloWorldTest.java
/core/src/com/android/tradefed/example/HelloWorldTest.java وأعد بناء التجارة من قوقعتك:
m -jN
لاحظ أن CLog.i
في المثال أعلاه يُستخدم لتوجيه الإخراج إلى وحدة التحكم. مزيد من المعلومات حول تسجيل الدخول إلى الاتحاد التجاري موصوفة في التسجيل (D ، I ، R) .
إذا لم ينجح الإصدار ، فاستشر إعداد الجهاز للتأكد من أنك لم تفوت أي خطوة.
إنشاء التكوين (I)
تكون اختبارات الاتحاد التجاري قابلة للتنفيذ من خلال إنشاء تكوين ، وهو ملف XML يرشد التجارة بشأن الاختبار (أو الاختبارات) المطلوب تشغيله ، بالإضافة إلى الوحدات النمطية الأخرى التي يجب تنفيذها وبأي ترتيب.
دعنا ننشئ تكوينًا جديدًا لاختبار HelloWorldTest الخاص بنا (لاحظ اسم فئة HelloWorldTest بالكامل):
<configuration description="Runs the hello world test"> <test class="com.android.tradefed.example.HelloWorldTest" /> </configuration>
احفظ هذه البيانات في ملف helloworld.xml
في أي مكان على نظام الملفات المحلي لديك (على سبيل المثال /tmp/helloworld.xml
). سيقوم TF بتحليل ملف تكوين XML (المعروف أيضًا باسم التكوين ) ، وتحميل الفئة المحددة باستخدام الانعكاس ، وإنشاء مثيل لها ، وإرسالها إلى IRemoteTest
، واستدعاء طريقة run
الخاصة بها.
تشغيل config (R)
من صدفتك ، قم بتشغيل وحدة التحكم التجارية:
tradefed.sh
تأكد من أن الجهاز متصل بالجهاز المضيف وأنه مرئي للتبادل:
tf> list devices Serial State Product Variant Build Battery 004ad9880810a548 Available mako mako JDQ39 100
يمكن تنفيذ التكوينات باستخدام أمر run <config>
. محاولة:
tf> run /tmp/helloworld.xml 05-12 13:19:36 I/TestInvocation: Starting invocation for target stub on build 0 on device 004ad9880810a548 Hello, TF World!
يجب أن ترى "Hello، TF World!" الإخراج على المحطة.
يمكنك التأكد من تنفيذ أمر ما باستخدام list invocations
أو li
في موجه وحدة التحكم ، ويجب ألا يطبع أي شيء. إذا كانت الأوامر قيد التشغيل حاليًا ، فسيتم عرضها على النحو التالي:
tf >l i Command Id Exec Time Device State 10 0m:00 [876X00GNG] running stub on build(s) 'BuildInfo{bid=0, target=stub, serial=876X00GNG}'
إضافة التكوين إلى classpath (D ، I ، R)
لسهولة النشر ، يمكنك أيضًا تجميع التكوينات في JARs التجارية نفسها. يتعرف Tradefed تلقائيًا على جميع التكوينات الموضوعة في مجلدات التكوين على مسار الفصل.
للتوضيح ، انقل ملف helloworld.xml
إلى المكتبة الأساسية tradefederation ( <tree>/tools/tradefederation/core/res/config/example/helloworld.xml
). إعادة بناء tradefed ، إعادة تشغيل وحدة التحكم tradefed ، ثم اطلب من tradefed عرض قائمة التكوينات من classpath:
tf> list configs […] example/helloworld: Runs the hello world test
يمكنك الآن تشغيل تهيئة helloworld باستخدام:
tf> run example/helloworld 05-12 13:21:21 I/TestInvocation: Starting invocation for target stub on build 0 on device 004ad9880810a548 Hello, TF World!
التعامل مع جهاز (D ، R)
حتى الآن ، لا يقوم HelloWorldTest الخاص بنا بأي شيء مثير للاهتمام. إن تخصص Tradefed هو إجراء الاختبارات باستخدام أجهزة Android ، لذلك دعونا نضيف جهاز Android للاختبار.
يمكن أن تحصل الاختبارات على مرجع لجهاز Android باستخدام TestInformation
، التي يوفرها إطار العمل عند استدعاء أسلوب IRemoteTest#run
.
دعنا نعدل رسالة الطباعة HelloWorldTest لعرض الرقم التسلسلي للجهاز:
@Override public void run(TestInformation testInfo, ITestInvocationListener listener) throws DeviceNotAvailableException { CLog.i("Hello, TF World! I have device " + testInfo.getDevice().getSerialNumber()); }
الآن قم بإعادة بناء Tradefed وتحقق من قائمة الأجهزة:
tradefed.sh
tf> list devices Serial State Product Variant Build Battery 004ad9880810a548 Available mako mako JDQ39 100
أخذ علما بالرقم التسلسلي المدرج على أنه متاح ؛ هذا هو الجهاز الذي يجب تخصيصه لـ HelloWorld:
tf> run example/helloworld 05-12 13:26:18 I/TestInvocation: Starting invocation for target stub on build 0 on device 004ad9880810a548 Hello, TF World! I have device 004ad9880810a548
من المفترض أن ترى رسالة الطباعة الجديدة التي تعرض الرقم التسلسلي للجهاز.
إرسال نتائج الاختبار (D)
IRemoteTest
عن النتائج عن طريق استدعاء الأساليب الموجودة على مثيل ITestInvocationListener المتوفر لطريقة #run
. إطار عمل TF نفسه مسؤول عن الإبلاغ عن البداية (عبر ITestInvocationListener # invocationStarted ) والنهاية (عبر ITestInvocationListener # invocationEnded ) لكل استدعاء.
التشغيل التجريبي هو مجموعة منطقية من الاختبارات. للإبلاغ عن نتائج الاختبار ، IRemoteTest
مسؤول عن الإبلاغ عن بدء التشغيل التجريبي ، وبداية ونهاية كل اختبار ، ونهاية التشغيل التجريبي.
إليك ما قد يبدو عليه تطبيق HelloWorldTest مع نتيجة اختبار فاشلة واحدة.
@Override public void run(TestInformation testInfo, ITestInvocationListener listener) throws DeviceNotAvailableException { CLog.i("Hello, TF World! I have device " + testInfo.getDevice().getSerialNumber()); TestDescription testId = new TestDescription("com.example.TestClassName", "sampleTest"); listener.testRunStarted("helloworldrun", 1); listener.testStarted(testId); listener.testFailed(testId, "oh noes, test failed"); listener.testEnded(testId, Collections.emptyMap()); listener.testRunEnded(0, Collections.emptyMap()); }
يتضمن TF العديد من IRemoteTest
التي يمكنك إعادة استخدامها بدلاً من كتابة ما يخصك من البداية. على سبيل المثال ، يمكن لـ InstrumentationTest تشغيل اختبارات تطبيق Android عن بُعد على جهاز Android ، وتحليل النتائج ، وإعادة توجيه هذه النتائج إلى ITestInvocationListener
). للحصول على التفاصيل ، راجع أنواع الاختبارات .
تخزين نتائج الاختبار (I)
تطبيق مستمع الاختبار الافتراضي لتكوين TF هو TextResultReporter ، والذي يفرغ نتائج الاستدعاء إلى stdout. للتوضيح ، قم بتشغيل تهيئة HelloWorldTest من القسم السابق:
./tradefed.sh
tf> run example/helloworld 04-29 18:25:55 I/TestInvocation: Invocation was started with cmd: /tmp/helloworld.xml 04-29 18:25:55 I/TestInvocation: Starting invocation for 'stub' with '[ BuildInfo{bid=0, target=stub, serial=876X00GNG} on device '876X00GNG'] 04-29 18:25:55 I/HelloWorldTest: Hello, TF World! I have device 876X00GNG 04-29 18:25:55 I/InvocationToJUnitResultForwarder: Running helloworldrun: 1 tests 04-29 18:25:55 W/InvocationToJUnitResultForwarder: Test com.example.TestClassName#sampleTest failed with stack: oh noes, test failed 04-29 18:25:55 I/InvocationToJUnitResultForwarder: Run ended in 0 ms
لتخزين نتائج استدعاء في مكان آخر ، مثل ملف ، حدد تنفيذ ITestInvocationListener
مخصصًا باستخدام علامة result_reporter
في التكوين الخاص بك.
يتضمن TF أيضًا مستمع XmlResultReporter ، الذي يكتب نتائج الاختبار إلى ملف XML بتنسيق مشابه للتنسيق الذي يستخدمه كاتب XML ant JUnit. لتحديد result_reporter في التكوين ، قم بتحرير …/res/config/example/helloworld.xml
config:
<configuration description="Runs the hello world test"> <test class="com.android.tradefed.example.HelloWorldTest" /> <result_reporter class="com.android.tradefed.result.XmlResultReporter" /> </configuration>
الآن أعد بناء Tradefed وأعد تشغيل نموذج Hello world:
tf> run example/helloworld 05-16 21:07:07 I/TestInvocation: Starting invocation for target stub on build 0 on device 004ad9880810a548 Hello, TF World! I have device 004ad9880810a548 05-16 21:07:07 I/XmlResultReporter: Saved device_logcat log to /tmp/0/inv_2991649128735283633/device_logcat_6999997036887173857.txt 05-16 21:07:07 I/XmlResultReporter: Saved host_log log to /tmp/0/inv_2991649128735283633/host_log_6307746032218561704.txt 05-16 21:07:07 I/XmlResultReporter: XML test result file generated at /tmp/0/inv_2991649128735283633/test_result_536358148261684076.xml. Total tests 1, Failed 1, Error 0
لاحظ رسالة السجل التي تفيد بأنه تم إنشاء ملف XML ؛ يجب أن يبدو الملف الذي تم إنشاؤه على النحو التالي:
<?xml version='1.0' encoding='UTF-8' ?> <testsuite name="stub" tests="1" failures="1" errors="0" time="9" timestamp="2011-05-17T04:07:07" hostname="localhost"> <properties /> <testcase name="sampleTest" classname="com.example.TestClassName" time="0"> <failure>oh noes, test failed </failure> </testcase> </testsuite>
يمكنك أيضًا كتابة مستمعي الاستدعاء المخصص - فهم ببساطة بحاجة إلى تنفيذ واجهة ITestInvocationListener .
تدعم Tradefed أدوات استماع متعددة للاستدعاء ، بحيث يمكنك إرسال نتائج الاختبار إلى وجهات مستقلة متعددة. للقيام بذلك ، ما عليك سوى تحديد علامات <result_reporter>
متعددة في ملف التكوين الخاص بك.
التسجيل (D ، I ، R)
تشمل مرافق التسجيل في TF القدرة على:
- تسجيل السجلات من الجهاز (المعروف أيضًا باسم Device logcat)
- سجلات السجلات من إطار عمل الاتحاد التجاري التي تعمل على الجهاز المضيف (ويعرف أيضًا باسم سجل المضيف)
يلتقط إطار عمل TF تلقائيًا logcat من الجهاز المخصص ويرسله إلى مستمع الاستدعاء للمعالجة. XmlResultReporter
ثم يحفظ logcat الجهاز الذي تم التقاطه كملف.
تم الإبلاغ عن سجلات مضيف TF باستخدام غلاف CLog لفئة سجل ddmlib. لنحول استدعاء System.out.println
السابق في HelloWorldTest إلى مكالمة CLog
:
@Override public void run(ITestInvocationListener listener) throws DeviceNotAvailableException { CLog.i("Hello, TF World! I have device %s", getDevice().getSerialNumber());
يعالج CLog
استيفاء السلسلة مباشرةً ، على غرار تنسيق String.format
. عند إعادة إنشاء TF وإعادة تشغيله ، يجب أن ترى رسالة السجل على stdout:
tf> run example/helloworld … 05-16 21:30:46 I/HelloWorldTest: Hello, TF World! I have device 004ad9880810a548 …
بشكل افتراضي ، تستضيف النواتج tradefed رسائل السجل إلى stdout . يتضمن TF أيضًا تطبيقًا للسجل يقوم بكتابة الرسائل إلى ملف: FileLogger . لإضافة تسجيل ملف ، أضف علامة logger
إلى التكوين ، مع تحديد اسم الفئة الكاملة لـ FileLogger
:
<configuration description="Runs the hello world test"> <test class="com.android.tradefed.example.HelloWorldTest" /> <result_reporter class="com.android.tradefed.result.XmlResultReporter" /> <logger class="com.android.tradefed.log.FileLogger" /> </configuration>
الآن ، أعد بناء مثال helloworld مرة أخرى:
tf >run example/helloworld … 05-16 21:38:21 I/XmlResultReporter: Saved device_logcat log to /tmp/0/inv_6390011618174565918/device_logcat_1302097394309452308.txt 05-16 21:38:21 I/XmlResultReporter: Saved host_log log to /tmp/0/inv_6390011618174565918/host_log_4255420317120216614.txt …
تشير رسالة السجل إلى مسار سجل المضيف ، والذي ، عند عرضه ، يجب أن يحتوي على رسالة سجل HelloWorldTest الخاصة بك:
more /tmp/0/inv_6390011618174565918/host_log_4255420317120216614.txt
مثال الإخراج:
… 05-16 21:38:21 I/HelloWorldTest: Hello, TF World! I have device 004ad9880810a548
خيارات المناولة (D ، I ، R)
يمكن أيضًا للكائنات التي تم تحميلها من تكوين TF (المعروف أيضًا باسم كائنات التكوين ) تلقي البيانات من وسيطات سطر الأوامر من خلال استخدام التعليق التوضيحي @Option
.
للمشاركة ، تطبق فئة كائن التكوين التعليق التوضيحي @Option
على حقل عضو وتوفر له اسمًا فريدًا. يتيح ذلك ملء قيمة حقل العضو عبر خيار سطر الأوامر (ويضيف أيضًا هذا الخيار تلقائيًا إلى نظام تعليمات التكوين).
ملاحظة: ليست كل أنواع الحقول مدعومة. للحصول على وصف للأنواع المدعومة ، راجع OptionSetter .
دعنا نضيف خيار @Option
إلى HelloWorldTest:
@Option(name="my_option", shortName='m', description="this is the option's help text", // always display this option in the default help text importance=Importance.ALWAYS) private String mMyOption = "thisisthedefault";
بعد ذلك ، دعنا نضيف رسالة سجل لعرض قيمة الخيار في HelloWorldTest حتى نتمكن من إثبات استلامها بشكل صحيح:
@Override public void run(ITestInvocationListener listener) throws DeviceNotAvailableException { … CLog.logAndDisplay(LogLevel.INFO, "I received option '%s'", mMyOption);
أخيرًا ، إعادة بناء TF وتشغيل helloworld ؛ سترى رسالة سجل بالقيمة الافتراضية my_option
:
tf> run example/helloworld … 05-24 18:30:05 I/HelloWorldTest: I received option 'thisisthedefault'
تمرير القيم من سطر الأوامر
تمرير قيمة لـ my_option
؛ يجب أن ترى my_option
بهذه القيمة:
tf> run example/helloworld --my_option foo … 05-24 18:33:44 I/HelloWorldTest: I received option 'foo'
تتضمن تكوينات TF أيضًا نظام مساعدة ، والذي يعرض تلقائيًا نص التعليمات لحقول @Option
. جربه الآن ، وسترى نص المساعدة my_option
:
tf> run example/helloworld --help Printing help for only the important options. To see help for all options, use the --help-all flag cmd_options options: --[no-]help display the help text for the most important/critical options. Default: false. --[no-]help-all display the full help text for all options. Default: false. --[no-]loop keep running continuously. Default: false. test options: -m, --my_option this is the option's help text Default: thisisthedefault. 'file' logger options: --log-level-display the minimum log level to display on stdout. Must be one of verbose, debug, info, warn, error, assert. Default: error.
لاحظ الرسالة حول "طباعة الخيارات المهمة فقط". لتقليل فوضى مساعدة الخيارات ، يستخدم TF السمة Option#importance
لتحديد ما إذا كان سيتم إظهار نص تعليمات حقل --help
معين عند تحديد @Option
. يعرض @Option
--help-all
دائمًا المساعدة لجميع حقولOption ، بغض النظر عن الأهمية. لمزيد من التفاصيل ، انظر الخيار . الأهمية.
تمرير القيم من التكوين
يمكنك أيضًا تحديد قيمة خيار داخل التكوين عن طريق إضافة عنصر <option name="" value="">
. اختبره باستخدام helloworld.xml
:
<test class="com.android.tradefed.example.HelloWorldTest" > <option name="my_option" value="fromxml" /> </test>
يجب أن ينتج عن إعادة بناء helloworld وتشغيله الآن هذا الناتج:
05-24 20:38:25 I/HelloWorldTest: I received option 'fromxml'
يجب أيضًا تحديث تعليمات التكوين للإشارة إلى القيمة الافتراضية لـ my_option
:
tf> run example/helloworld --help test options: -m, --my_option this is the option's help text Default: fromxml.
كائنات التكوين الأخرى المضمنة في تكوين helloworld ، مثل FileLogger
، تقبل أيضًا الخيارات. يعد الخيار --log-level-display
ممتعًا لأنه يقوم بتصفية السجلات التي تظهر على stdout. في وقت سابق من البرنامج التعليمي ، ربما لاحظت أن رسالة السجل "مرحبًا ، TF World! لدي جهاز ..." توقف عرضها على stdout بعد أن قمنا بالتبديل إلى استخدام FileLogger
. يمكنك زيادة الإسهاب في التسجيل إلى stdout عن طريق تمرير --log-level-display
arg.
جرب هذا الآن ، وسترى رسالة سجل "لدي جهاز" تظهر مرة أخرى على stdout ، بالإضافة إلى تسجيلك في ملف:
tf> run example/helloworld --log-level-display info … 05-24 18:53:50 I/HelloWorldTest: Hello, TF World! I have device 004ad9880810a548
هذا كل ما لدي أيها الناس!
للتذكير ، إذا علقت في شيء ما ، فإن كود مصدر الاتحاد التجاري يحتوي على الكثير من المعلومات المفيدة التي لم يتم الكشف عنها في الوثائق. إذا فشل كل شيء آخر ، فحاول طرح السؤال على مجموعة Google التي تعمل بنظام android ، مع وضع "الاتحاد التجاري" في موضوع الرسالة.