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

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

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

  • D למפתחים
  • I למטמיע
  • R להרצת בדיקה

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

הגדרת איחוד שירותי הסחר

לפרטים על הגדרת סביבת הפיתוח של TF: מכונה הגדרה. המשך המדריך הזה מניח שיש לכם מעטפת פתוחה מאותחל בסביבת TF.

כדי לשמור על פשטות, המדריך הזה מדגים הוספת מערך הגדרות אישיות לספריית הליבה של framework של TF. אפשר להרחיב את התהליך הזה של המודולים מחוץ לעץ המקור על ידי הידור של ה-JAR המוזנים, ולאחר מכן הידור. למודולים נפרדים מול ה-JAR הזה.

יצירת כיתת בדיקה (ד)

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

m -jN

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

אם ה-build לא מצליח, יש להתייעץ מכונה הגדרה כדי להבטיח שלא פספסת אף שלב.

יצירת הגדרות אישיות (I)

הבדיקות של Federation (איחוד המסחר) הופכות להפעלה על ידי יצירת הגדרה, קובץ XML שמורה להזין נתונים מסוג ecommerce לבדוק (או בדיקות) להריץ, וגם אילו מודולים אחרים להפעיל ובאילו הזמנה.

נאפשר ליצור הגדרה חדשה בשביל 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), טוענים את המחלקה שצוינה באמצעות השתקפות, ליצור ממנו מופע, להפעיל Cast שלו אל IRemoteTest, ה-method run.

הרצת ההגדרות (R)

מהמעטפת, מפעילים את המסוף המיועד למסחר אלקטרוני:

tradefed.sh

מוודאים שמכשיר מחובר למכונה המארחת וגלוי ל-Trends:

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!

אמורה להופיע ההודעה 'שלום, עולם שלם!' בטרמינל.

אפשר לוודא שהרצת הפקודה הסתיימה באמצעות 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}'

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

לנוחיות הפריסה, אפשר גם לקבץ הגדרות JAR בעצמם. פרוטוקול המסחר האלקטרוני מזהה באופן אוטומטי את כל ההגדרות שממוקמות תיקיות config בנתיב הכיתה.

כדי להמחיש זאת, צריך להעביר את הקובץ helloworld.xml לתוך שדה המסחר ספריית ליבה (<tree>/tools/tradefederation/core/res/config/example/helloworld.xml). בונים מחדש את ה- לרשת ההסדר, מפעילים מחדש את המסוף ואז מבקשים מ-Tredified להציג את רשימת ההגדרות האישיות מה-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. שמתמחה בהרצת בדיקות באמצעות מכשירי Android, אז כדאי להוסיף מכשיר Android כדי לבדוק את זה.

במסגרת הבדיקות אפשר לקבל הפניה למכשיר Android באמצעות TestInformation, בתנאי במסגרת ה-framework, כשמתבצעת קריאה ל-method 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.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 שסופקה ל-method #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 שניתן לעשות בהן שימוש חוזר במקום לכתוב מאפס. לדוגמה, בדיקת אינסטרומנטציה להריץ מרחוק בדיקות של אפליקציה ל-Android במכשיר Android, לנתח את של התוצאות, ולהעביר אותן אל ITestInvocationListener). פרטים נוספים זמינים במאמר בדיקה סוגים.

תוצאות הבדיקה בחנות (I)

הטמעת ברירת המחדל של האזנה לבדיקה עבור הגדרת TF היא TextresultsReporter, שמעביר ל-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 כולל גם את XmlProductReporter ל-listener, שכותב תוצאות בדיקה לקובץ XML בפורמט שדומה לזה. משמש את כותב ה-XML של ant ב-JUnit. כדי לציין את 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>

עכשיו בונים מחדש את המסחר האלקטרוני ומריץים מחדש את דוגמת הלולאה:

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 גרפי.

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

מתקני רישום ביומן (D, I, R)

מתקני הרישום ביומן של TF כוללים את היכולת:

  1. תיעוד יומנים מהמכשיר (שנקרא גם מכשיר Logcat)
  2. תיעוד יומנים מ-framework של Federation (Commerce Federation) שפועלים במחשב המארח (נקרא גם יומן מארח)

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

יומני המארח של TF מדווחים באמצעות wrapper של 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
…

כברירת מחדל, נסחרו הנתונים יומן המארח של משתני הפלט הודעות ל-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 בתוך ההגדרה על ידי הוספת רכיב <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. מוקדם יותר במדריך, אולי הבחנתם בכיתוב "שלום, עולם! יש לי מכשיר...' הודעת היומן הפסיקה להופיע ב-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

זה הכול, חבר'ה!

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