บทแนะนำนี้จะแนะนำการสร้างการกำหนดค่าการทดสอบ "Hello World" ของ Trade Federation (Tradefed หรือ TF) และแนะนำการใช้งานเฟรมเวิร์ก TF คุณจะเริ่มต้นจากสภาพแวดล้อมการพัฒนาเพื่อสร้างการกำหนดค่าง่ายๆ และเพิ่มฟีเจอร์
บทแนะนําจะแสดงกระบวนการพัฒนาการทดสอบเป็นชุดแบบฝึกหัด ซึ่งแต่ละแบบฝึกหัดประกอบด้วยหลายขั้นตอนที่สาธิตวิธีสร้างและปรับแต่งการกําหนดค่าทีละน้อย เรามีตัวอย่างโค้ดทั้งหมดที่จําเป็นในการกําหนดค่าการทดสอบให้เสร็จสมบูรณ์ และชื่อของแบบฝึกหัดแต่ละรายการจะมีคำอธิบายประกอบด้วยตัวอักษรที่อธิบายบทบาทที่เกี่ยวข้องในขั้นตอนนั้นๆ
- D สำหรับนักพัฒนาแอป
- I สำหรับผู้ผสานรวม
- R สำหรับ Test Runner
หลังจากทําตามบทแนะนําเสร็จแล้ว คุณจะมีการกำหนดค่า TF ที่ใช้งานได้และเข้าใจแนวคิดสําคัญหลายประการในเฟรมเวิร์ก TF
ตั้งค่าสหพันธ์การค้า
โปรดดูรายละเอียดเกี่ยวกับการตั้งค่าสภาพแวดล้อมการพัฒนา TF ที่หัวข้อการตั้งค่าเครื่อง ส่วนที่เหลือของบทแนะนำนี้จะถือว่าคุณเปิดเชลล์ที่เริ่มต้นค่าเป็นสภาพแวดล้อม TF แล้ว
บทแนะนํานี้จะแสดงการใส่การกําหนดค่าและคลาสของการกำหนดค่าลงในคลังหลักของเฟรมเวิร์ก TF เพื่อให้เข้าใจง่าย ซึ่งสามารถขยายการทำงานเพื่อพัฒนาโมดูลนอกสคีมาซอร์สโค้ดได้โดยคอมไพล์ JAR ของ Tradefed จากนั้นคอมไพล์โมดูลกับ JAR นั้น
สร้างชั้นเรียนทดสอบ (D)
มาสร้างการทดสอบ Hello World ที่แสดงข้อความไปยัง 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
และสร้าง tradefed อีกครั้งจากเชลล์
m -jN
โปรดทราบว่า CLog.i
ในตัวอย่างด้านบนใช้เพื่อส่งเอาต์พุตไปยังคอนโซล ดูข้อมูลเพิ่มเติมเกี่ยวกับการบันทึกใน Trade Federation ได้ที่การบันทึก (D, I, R)
หากบิลด์ไม่สำเร็จ โปรดดูหัวข้อการตั้งค่าเครื่องเพื่อให้แน่ใจว่าคุณไม่ได้พลาดขั้นตอนใดไป
สร้างการกำหนดค่า (I)
การทดสอบของ Trade Federation จะทําให้เรียกใช้ได้โดยการสร้างการกําหนดค่า ซึ่งเป็นไฟล์ XML ที่บอกให้ TradeFed ทราบการทดสอบ (หรือการทดสอบ) ที่จะเรียกใช้ รวมถึงโมดูลอื่นๆ ที่จะเรียกใช้และลําดับการเรียกใช้
มาสร้างการกําหนดค่าใหม่สําหรับ HelloWorldTest (โปรดสังเกตชื่อคลาสแบบเต็มของ HelloWorldTest)
<configuration description="Runs the hello world test"> <test class="com.android.tradefed.example.HelloWorldTest" /> </configuration>
บันทึกข้อมูลนี้ลงในไฟล์ helloworld.xml
ได้ทุกที่ในระบบไฟล์ในเครื่อง (เช่น /tmp/helloworld.xml
) TF จะแยกวิเคราะห์ไฟล์ XML การกำหนดค่า (หรือที่เรียกว่า config) โหลดคลาสที่ระบุโดยใช้การสะท้อน สร้างอินสแตนซ์ แคสต์เป็น IRemoteTest
และเรียกใช้เมธอด run
เรียกใช้การกําหนดค่า (R)
จากเชลล์ ให้เปิดคอนโซล TradeFed โดยทำดังนี้
tradefed.sh
ตรวจสอบว่าอุปกรณ์เชื่อมต่อกับเครื่องโฮสต์และแสดงใน TradeFed
tf> list devices Serial State Product Variant Build Battery 004ad9880810a548 Available mako mako JDQ39 100
คุณสามารถเรียกใช้การกําหนดค่าได้โดยใช้คําสั่ง run <config>
console โดยคุณสามารถลองทำสิ่งต่อไปนี้
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
หรือ
l i
ในพรอมต์คอนโซล และไม่ควรมีสิ่งใดแสดง หากมีคำสั่งที่ทำงานอยู่ ระบบจะแสดงคำสั่งดังกล่าวดังนี้
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)
นอกจากนี้ คุณยังรวมการกําหนดค่าไว้ในไฟล์ JAR ของ Tradefed โดยตรงเพื่อความสะดวกในการทําให้ใช้งานได้ Tradefed จะจดจําการกําหนดค่าทั้งหมดที่อยู่ในโฟลเดอร์ config ใน classpath โดยอัตโนมัติ
ตัวอย่างเช่น ให้ย้ายไฟล์ helloworld.xml
ไปยังไลบรารีหลักของ TradeFed (<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
)
ดูรายละเอียดได้ที่ประเภทการทดสอบ
ผลการทดสอบ Store (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 ในรูปแบบที่คล้ายกับที่ant JUnit XML Writer ใช้ หากต้องการระบุ 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 มีความสามารถในการดำเนินการต่อไปนี้
- บันทึกจากอุปกรณ์ (หรือที่เรียกว่า Logcat ของอุปกรณ์)
- บันทึกบันทึกจากเฟรมเวิร์ก Trade Federation ที่ทำงานบนเครื่องโฮสต์ (หรือที่เรียกว่าบันทึกของโฮสต์)
เฟรมเวิร์ก TF จะบันทึก Logcat จากอุปกรณ์ที่จัดสรรโดยอัตโนมัติ และส่งไปยัง Invocation Listener เพื่อประมวลผล
XmlResultReporter
จะบันทึกบันทึก Logcat ของอุปกรณ์ที่บันทึกไว้เป็นไฟล์
ระบบจะรายงานบันทึกของโฮสต์ TF โดยใช้ CLog wrapper สำหรับคลาสบันทึก 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
เพื่อพิจารณาว่าจะแสดงข้อความความช่วยเหลือของช่อง @Option
รายการใดเมื่อมีการระบุ --help
หรือไม่ เพื่อลดความกระจัดกระจายของความช่วยเหลือเกี่ยวกับตัวเลือก --help-all
จะแสดงความช่วยเหลือสำหรับฟิลด์ @Option
ทั้งหมดเสมอ ไม่ว่าจะสำคัญหรือไม่สำคัญ โปรดดูรายละเอียดที่ Option.Importance
ส่งค่าจากการกําหนดค่า
นอกจากนี้ คุณยังระบุค่าตัวเลือกภายในการกําหนดค่าได้โดยการเพิ่มองค์ประกอบ <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
ลองทำตอนนี้ คุณควรเห็นข้อความบันทึก "ฉันมีอุปกรณ์" ปรากฏขึ้นอีกครั้งใน stdout นอกเหนือจากการบันทึกลงในไฟล์
tf> run example/helloworld --log-level-display info … 05-24 18:53:50 I/HelloWorldTest: Hello, TF World! I have device 004ad9880810a548
เท่านี้ก่อนนะ
โปรดทราบว่าหากพบปัญหา ซอร์สโค้ดของ Trade Federation มีข้อมูลที่เป็นประโยชน์มากมายที่ไม่ได้แสดงในเอกสารประกอบ หากวิธีอื่นไม่ได้ผล ให้ลองถามใน Google Group ของ android-platform โดยใส่ "Trade Federation" ในหัวเรื่องข้อความ