端對端 TF 測試範例

本教學課程會逐步引導您建立「Hello World」貿易聯盟 測試設定,並提供實作簡介 這個架構的重點在於從開發環境開始,您會建立簡單的 設定及新增功能

本教學課程以一組練習的形式呈現測試開發程序 也包含數個步驟 修正您的設定您需要完成測試的所有程式碼範例 並在每個運動的標題中加註 說明步驟中提及的角色:

  • D 適用於開發人員
  • 整合商的 I
  • 測試執行者的 R

完成教學課程後,即可正常運作 TF 設定 並瞭解 TF 架構中的許多重要概念

設定貿易聯盟

如要進一步瞭解如何設定 TF 開發環境,請參閱 機器 設定。本教學課程的其餘部分假設您已開啟殼層開啟 初始化為 TF 環境。

為簡單起見,本教學課程說明如何新增設定及其設定 放入 TF 架構核心程式庫的類別這可延伸至 編譯 JAR, 針對該 JAR 建立模組

建立測試類別 (D)

讓我們建立僅傾印訊息至 stdout 的 hello World 測試。A 罩杯 進行貿易測試時,通常會將 IRemoteTest 存取 API以下是 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 是用來將輸出內容導向控制台。更多內容 如需商業聯盟的登入詳細資訊,請參閱 Logging (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 檔案 (又稱 config),使用以下程式碼載入指定類別: 反射、執行個體化、投放至 IRemoteTest,然後呼叫 run 方法。

執行設定 (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 invocationsl 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)。 重新建立交易、重新啟動交易控制台,然後要求商討顯示 類別路徑中的設定清單:

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 裝置 進行測試。

測試可以使用 TestInformation (如果已提供),取得 Android 裝置的參照 從架構中移除。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 提供給 #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 檔案 (由 ant JUnit XML 寫入者使用)。如何在 設定,編輯 …/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>

現在重新建構換購項目,然後重新執行 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 存取 API

Tradefed 支援多個叫用事件監聽器,因此您可以傳送測試結果 多個獨立的目的地。方法是指定多個 配置中的 <result_reporter> 標記。

日誌設施 (D、I、R)

TF 的記錄設施包括:

  1. 擷取裝置記錄 (又稱裝置 logcat)
  2. 記錄在主體機器上執行的貿易聯盟架構記錄 (又稱主機記錄)

TF 架構會自動從分配的裝置擷取 logcat 並傳送給叫用事件監聽器進行處理 接著,XmlResultReporter 會將擷取的裝置 logcat 儲存為檔案。

系統會使用 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 註解。

如要加入計畫,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 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 上在先前的教學課程中,您可能已註意到「Hello, TF」 全世界!我的裝置是...」在我們定義的 stdout 內停止顯示記錄訊息 已切換為使用「FileLogger」。如果想要提高 傳入 --log-level-display 引數以登入 stdout。

立即嘗試,您應會看到「我有裝置」再次顯示記錄訊息 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」有關。