דוגמה לבדיקת TF מקצה לקצה

מדריך זה מנחה אותך דרך יצירת תצורת מבחן של "שלום עולם" (Tradefed או TF) ומעניק לך היכרות מעשית למסגרת TF. החל מסביבת פיתוח, תיצור תצורה פשוטה ותוסיף תכונות.

ההדרכה מציגה את תהליך פיתוח המבחן כסט של תרגילים, שכל אחד מהם מורכב ממספר שלבים, המדגימים כיצד לבנות ולחדד את התצורה שלך בהדרגה. כל הקוד לדוגמה שאתה צריך כדי להשלים את תצורת הבדיקה מסופק, והכותרת של כל תרגיל מסומנת באות המתארת ​​את התפקידים המעורבים באותו שלב:

  • D למפתחים
  • אני עבור אינטגרטור
  • R עבור רץ מבחן

לאחר השלמת המדריך, תהיה לך תצורת TF מתפקדת ותבין מושגים חשובים רבים במסגרת TF.

הגדר את פדרציית הסחר

לפרטים על הגדרת סביבת הפיתוח של TF, ראה הגדרת מכונה . שאר המדריך הזה מניח שיש לך מעטפת פתוחה שאותחלה לסביבת 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 ובנה מחדש את tradefed מהמעטפת שלך:

m -jN

שים לב ש- CLog.i בדוגמה שלמעלה משמש להפניית פלט לקונסולה. מידע נוסף על התחברות ב- Trade Federation מתואר ברישום (D, I, R) .

אם הבנייה לא מצליחה, עיין בהגדרת המכונה כדי לוודא שלא פספסת שלב.

צור תצורה (I)

בדיקות Trade Federation נעשות לניתנות להפעלה על ידי יצירת Configuration , קובץ 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 של Configuration (aka 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!

אתה אמור לראות "שלום, 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}'

הוסף את התצורה לנתיב הכיתה (D, I, R)

לנוחות הפריסה, אתה יכול גם לאגד הגדרות לתוך ה-JARs המוזנים במסחר עצמם. Tradefed מזהה אוטומטית את כל התצורות המוצבות בתיקיות תצורה ב-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 היא הפעלת בדיקות באמצעות מכשירי אנדרואיד, אז בואו נוסיף מכשיר אנדרואיד לבדיקה.

בדיקות יכולות לקבל הפניה למכשיר אנדרואיד על ידי שימוש 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 יכול להריץ בדיקות של אפליקציית אנדרואיד מרחוק במכשיר אנדרואיד, לנתח את התוצאות ולהעביר תוצאות אלו ל- 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 בפורמט דומה לזה המשמש את כותב ה- Ant JUnit XML. כדי לציין את ה-Result_reporter בתצורה, ערוך את התצורה …/res/config/example/helloworld.xml :

<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 כוללים את היכולת:

  1. לכידת יומנים מהמכשיר (המכונה Device logcat)
  2. הקלט יומנים ממסגרת ה- Trade Federation הפועלת על המחשב המארח (המכונה יומן מארח)

מסגרת ה-TF לוכדת אוטומטית את ה-logcat מהמכשיר המוקצה ושולחת אותו למאזין הפניות לעיבוד. לאחר מכן, XmlResultReporter שומר את logcat המכשיר שנלכד כקובץ.

יומני מארח TF מדווחים באמצעות המעטפת CLog עבור המחלקה ddmlib Log. בואו נמיר את הקריאה 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 (המכונה גם Configuration objects ) יכולים לקבל נתונים מארגומנטים של שורת הפקודה באמצעות ההערה @Option .

כדי להשתתף, מחלקת אובייקט Configuration מחילה את ההערה @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 בתוך התצורה על ידי הוספת אלמנט <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

זה הכל, אנשים!

כזכור, אם נתקעתם במשהו, לקוד המקור של Trade Federation יש הרבה מידע שימושי שלא נחשף בתיעוד. אם כל השאר נכשל, נסה לשאול בקבוצת Google של פלטפורמת אנדרואיד , עם "פדרציית סחר" בנושא ההודעה.