Ví dụ về thử nghiệm TF toàn diện

Đây là phần hướng dẫn bạn cách tạo lời chào "hello world" (Xin chào mọi người) Liên đoàn Thương mại Cấu hình kiểm tra (Trao đổi hoặc TF) và cung cấp cho bạn giới thiệu thực tế về TF khung. Bắt đầu từ môi trường phát triển, bạn sẽ tạo một định cấu hình và thêm tính năng.

Hướng dẫn này trình bày quy trình phát triển thử nghiệm dưới dạng một tập hợp các bài tập, mỗi chiến dịch bao gồm một số bước minh hoạ cách xây dựng và tinh chỉnh cấu hình của bạn. Tất cả mã mẫu bạn cần để hoàn tất kiểm thử cấu hình được cung cấp và tiêu đề của mỗi bài tập được chú thích bằng thư mô tả các vai trò liên quan trong bước đó:

  • D cho Nhà phát triển
  • I cho Trình tích hợp
  • R cho Người chạy thử nghiệm

Sau khi hoàn tất phần hướng dẫn, bạn sẽ có một cấu hình TF hoạt động được và nắm được nhiều khái niệm quan trọng trong bộ khung TF.

Thành lập Liên đoàn thương mại

Để biết chi tiết về cách thiết lập môi trường phát triển TF, hãy xem Máy Thiết lập. Phần còn lại của hướng dẫn này giả định rằng bạn có một vỏ đang mở được khởi tạo sang môi trường TF.

Để đơn giản hoá, hướng dẫn này minh hoạ cách thêm cấu hình và vào thư viện lõi khung TF. Quá trình này có thể mở rộng sang việc phát triển các mô-đun bên ngoài cây nguồn bằng cách biên dịch JAR trao đổi, sau đó biên dịch mô-đun của bạn dựa trên tệp JAR đó.

Tạo một lớp kiểm thử (D)

Hãy tạo một chương trình kiểm thử Hello world chỉ kết xuất một thông báo vào stdout. Đáp thử nghiệm thương mại thường triển khai IRemoteTest . Dưới đây là cách triển khai cho 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!");
    }
}

Lưu mã mẫu này vào <tree>/tools/tradefederation/core/src/com/android/tradefed/example/HelloWorldTest.java và tạo lại giao dịch được tạo từ shell:

m -jN

Lưu ý: CLog.i trong ví dụ trên dùng để chuyển dữ liệu đầu ra đến bảng điều khiển. Xem thêm thông tin về cách ghi nhật ký trong Liên đoàn thương mại được mô tả trong Ghi nhật ký (D, I, R).

Nếu bản dựng không thành công, hãy tham khảo Máy Thiết lập để đảm bảo bạn không bỏ lỡ bước nào.

Tạo cấu hình (I)

Các kiểm thử của Liên đoàn Thương mại được thiết kế để có thể thực thi bằng cách tạo một Cấu hình, một tệp XML hướng dẫn trao đổi thông tin trên kiểm thử (hoặc các bài kiểm thử) để chạy, cũng như những mô-đun khác cần thực thi và mô-đun nào đơn đặt hàng.

Hãy tạo một Cấu hình mới cho HelloWorldTest (lưu ý toàn bộ lớp tên của HelloWorldTest):

<configuration description="Runs the hello world test">
    <test class="com.android.tradefed.example.HelloWorldTest" />
</configuration>

Lưu dữ liệu này vào một tệp helloworld.xml ở bất cứ đâu trên thiết bị của bạn hệ thống tệp (ví dụ: /tmp/helloworld.xml). TF sẽ phân tích cú pháp Tệp XML cấu hình (còn gọi là config), tải lớp được chỉ định bằng cách sử dụng phản chiếu, tạo thực thể, truyền nó đến IRemoteTest và gọi run.

Chạy cấu hình (R)

Từ shell, hãy khởi chạy bảng điều khiển trao đổi:

tradefed.sh

Đảm bảo thiết bị được kết nối với máy chủ và hiển thị với giao dịch:

tf> list devices
Serial            State      Product   Variant   Build   Battery
004ad9880810a548  Available  mako      mako      JDQ39   100

Có thể thực thi cấu hình bằng run <config> bảng điều khiển. Hãy thử:

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!

Bạn sẽ thấy thông báo "Hello, TF World!" đầu ra trên thiết bị đầu cuối.

Bạn có thể xác nhận rằng một lệnh đã chạy xong bằng cách sử dụng list invocations hoặc l i trong lời nhắc của bảng điều khiển và không in nội dung gì. Nếu các lệnh hiện đang đang chạy, chúng hiển thị như sau:

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}'

Thêm cấu hình vào đường dẫn lớp (D, I, R)

Để thuận tiện cho việc triển khai, bạn cũng có thể gói các cấu hình vào Chính tệp JAR. Tradefeed sẽ tự động nhận ra tất cả các cấu hình được đặt trong config trên đường dẫn lớp.

Để minh hoạ, hãy chuyển tệp helloworld.xml vào giao dịch thư viện Core (<tree>/tools/tradefederation/core/res/config/example/helloworld.xml). Tạo lại giao dịch đã đổi, khởi động lại bảng điều khiển đã được đổi danh sách các cấu hình của classpath:

tf> list configs
[…]
example/helloworld: Runs the hello world test

Bây giờ, bạn có thể chạy cấu hình helloworld bằng cách sử dụng:

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!

Tương tác với thiết bị (D, R)

Tính đến thời điểm hiện tại, HelloWorldTest chúng tôi chưa thực hiện được bất cứ điều gì thú vị. Thương mại tính năng chuyên biệt đang chạy các thử nghiệm bằng thiết bị Android, vì vậy, hãy thêm một thiết bị Android vào bài kiểm thử.

Kiểm thử có thể tham chiếu đến một thiết bị Android bằng cách sử dụng TestInformation, được cung cấp theo khung khi phương thức IRemoteTest#run được gọi.

Hãy sửa đổi thông báo in HelloWorldTest để hiển thị số sê-ri của thiết bị:

@Override
public void run(TestInformation testInfo, ITestInvocationListener listener) throws DeviceNotAvailableException {
    CLog.i("Hello, TF World! I have device " + testInfo.getDevice().getSerialNumber());
}

Bây giờ, hãy tạo lại giao dịch và kiểm tra danh sách thiết bị:

tradefed.sh
tf> list devices
Serial            State      Product   Variant   Build   Battery
004ad9880810a548  Available  mako      mako      JDQ39   100

Ghi lại số sê-ri được nêu Có sẵn; đó là thiết bị sẽ được phân bổ cho 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

Bạn sẽ thấy thông báo in mới cho thấy số sê-ri của thiết bị.

Gửi kết quả thử nghiệm (D)

IRemoteTest báo cáo kết quả bằng cách gọi các phương thức trên ITestInvocationListener thực thể được cung cấp cho phương thức #run. Bản thân khung TF tự chịu trách nhiệm báo cáo về việc bắt đầu (thông qua ITestInvocationListener#invocationStarted) và kết thúc (qua ITestInvocationListener#invocationOutcome) của mỗi Lời gọi.

Chạy kiểm thử là một tập hợp các bài kiểm thử theo logic. Cách báo cáo kết quả thử nghiệm: IRemoteTest chịu trách nhiệm báo cáo thời điểm bắt đầu chạy kiểm thử, thời điểm bắt đầu và kết thúc mỗi lần kiểm thử, cũng như điểm kết thúc của lần chạy kiểm thử.

Dưới đây là ví dụ về cách triển khai HelloWorldTest với một kết quả thử nghiệm không thành công.

@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 bao gồm một số cách triển khai IRemoteTest mà bạn có thể sử dụng lại thay vì tự viết từ đầu. Ví dụ: InstrumentationTest (Kiểm thử đo lường) có thể chạy bài kiểm thử của ứng dụng Android từ xa trên một thiết bị Android, phân tích cú pháp các kết quả và chuyển tiếp các kết quả đó đến ITestInvocationListener). Để biết thông tin chi tiết, hãy xem Thử nghiệm Loại.

Kết quả thử nghiệm lưu trữ (I)

Phương thức triển khai trình nghe kiểm thử mặc định cho một cấu hình TF là TextResultReporter, sẽ kết xuất kết quả của lệnh gọi đến stdout. Để minh hoạ, hãy chạy Cấu hình HelloWorldTest từ phần trước:

./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

Để lưu trữ kết quả của lệnh gọi ở nơi khác, chẳng hạn như trong một tệp, hãy chỉ định bằng cách sử dụng phương thức triển khai ITestInvocationListener tuỳ chỉnh. Thẻ result_reporter trong cấu hình của bạn.

TF cũng bao gồm Trình báo cáo XmlResultReport trình nghe này, ghi kết quả kiểm thử vào tệp XML ở định dạng tương tự được sử dụng bởi trình viết XML ant JUnit. Để chỉ định results_reporter trong cấu hình, hãy chỉnh sửa …/res/config/example/helloworld.xml cấu hình:

<configuration description="Runs the hello world test">
    <test class="com.android.tradefed.example.HelloWorldTest" />
    <result_reporter class="com.android.tradefed.result.XmlResultReporter" />
</configuration>

Bây giờ, hãy tạo lại giao dịch được cấp và chạy lại mẫu 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

Lưu ý thông điệp nhật ký cho biết một tệp XML đã được tạo; thời gian tệp được tạo sẽ có dạng như sau:

<?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>

Bạn cũng có thể viết trình nghe lời gọi tuỳ chỉnh của riêng mình — chúng chỉ đơn giản là cần triển khai ITestInvocationListener .

Tradefeed hỗ trợ nhiều trình nghe lệnh gọi để bạn có thể gửi kết quả kiểm thử tới nhiều điểm đến độc lập. Để thực hiện việc này, chỉ cần chỉ định nhiều <result_reporter> thẻ trong cấu hình của bạn.

Cơ sở ghi nhật ký (D, I, R)

Cơ sở vật chất ghi nhật ký của TF có thể:

  1. Ghi nhật ký từ thiết bị (còn gọi là logcat thiết bị)
  2. Ghi nhật ký từ khung của Liên đoàn Thương mại đang chạy trên máy chủ lưu trữ (còn gọi là nhật ký máy chủ)

Khung TF sẽ tự động ghi lại logcat từ thiết bị được phân bổ rồi gửi nó đến trình nghe lệnh gọi để xử lý. Sau đó, XmlResultReporter sẽ lưu logcat của thiết bị đã thu thập dưới dạng tệp.

Nhật ký máy chủ TF được báo cáo bằng Trình bao bọc CLog cho lớp Nhật ký ddmlib. Hãy chuyển đổi lệnh gọi System.out.println trước đó trong HelloWorldTest đến một Cuộc gọi CLog:

@Override
public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
    CLog.i("Hello, TF World! I have device %s", getDevice().getSerialNumber());

CLog trực tiếp xử lý nội suy chuỗi, tương tự như String.format Khi tạo lại và chạy lại TF, bạn sẽ thấy thông báo nhật ký trên stdout:

tf> run example/helloworld
…
05-16 21:30:46 I/HelloWorldTest: Hello, TF World! I have device 004ad9880810a548
…

Theo mặc định, được giao dịch nhật ký máy chủ đầu ra nhắn tin tới stdout. TF cũng bao gồm triển khai nhật ký ghi tin nhắn vào một tệp: FileLogger. Để thêm tính năng ghi nhật ký tệp, hãy thêm thẻ logger vào cấu hình, chỉ định tên lớp đầy đủ của 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>

Bây giờ, hãy tạo lại và chạy lại ví dụ 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
…

Thông điệp nhật ký cho biết đường dẫn của nhật ký máy chủ lưu trữ mà khi được xem phải chứa thông điệp nhật ký HelloWorldTest:

more /tmp/0/inv_6390011618174565918/host_log_4255420317120216614.txt

Kết quả điểm dữ liệu:

…
05-16 21:38:21 I/HelloWorldTest: Hello, TF World! I have device 004ad9880810a548

Các phương thức xử lý (D, I, R)

Các đối tượng được tải từ một Cấu hình TF (còn gọi là đối tượng Cấu hình) cũng có thể nhận dữ liệu từ đối số dòng lệnh thông qua việc sử dụng Chú giải @Option.

Để tham gia, một lớp đối tượng Cấu hình sẽ áp dụng @Option chú thích cho trường thành viên và cung cấp tên duy nhất cho trường đó. Điều này cho phép giá trị trường thành viên được điền thông qua tuỳ chọn dòng lệnh (và cũng có thể tự động thêm tuỳ chọn đó vào hệ thống trợ giúp cấu hình).

Lưu ý: Chỉ một số loại trường được hỗ trợ. Đối với mô tả các loại được hỗ trợ, xem OptionSetter.

Hãy thêm @Option vào 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";

Tiếp theo, hãy thêm một thông điệp nhật ký để cho thấy giá trị của tuỳ chọn này trong HelloWorldTest để chúng ta có thể chứng minh thiết bị nhận được chính xác:

@Override
public void run(ITestInvocationListener listener) throws DeviceNotAvailableException {
    …
    CLog.logAndDisplay(LogLevel.INFO, "I received option '%s'", mMyOption);

Cuối cùng, hãy xây dựng lại TF và chạy helloworld; bạn sẽ thấy một thông điệp nhật ký kèm theo Giá trị mặc định của my_option:

tf> run example/helloworld
…
05-24 18:30:05 I/HelloWorldTest: I received option 'thisisthedefault'

Truyền các giá trị qua dòng lệnh

Truyền vào một giá trị cho my_option; bạn sẽ thấy my_option được điền bằng giá trị đó:

tf> run example/helloworld --my_option foo
…
05-24 18:33:44 I/HelloWorldTest: I received option 'foo'

Các cấu hình TF cũng bao gồm một hệ thống trợ giúp, tự động hiển thị văn bản trợ giúp cho các trường @Option. Hãy thử ngay bây giờ và bạn sẽ thấy văn bản trợ giúp cho 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.

Lưu ý thông báo "chỉ in những lựa chọn quan trọng". Để giảm trợ giúp tuỳ chọn lộn xộn, TF sử dụng thuộc tính Option#importance để xác định xem có hiển thị văn bản trợ giúp của trường @Option cụ thể hay không khi --help đã được chỉ định. --help-all luôn hiển thị trợ giúp cho tất cả trường @Option, bất kể mức độ quan trọng. Để biết thông tin chi tiết, hãy xem Lựa chọn.Mức độ quan trọng.

Truyền các giá trị qua một cấu hình

Bạn cũng có thể chỉ định giá trị Tuỳ chọn trong cấu hình bằng cách thêm một Phần tử <option name="" value="">. Kiểm thử bằng helloworld.xml:

<test class="com.android.tradefed.example.HelloWorldTest" >
    <option name="my_option" value="fromxml" />
</test>

Việc tạo lại và chạy helloworld hiện sẽ cho ra kết quả này:

05-24 20:38:25 I/HelloWorldTest: I received option 'fromxml'

Trợ giúp cấu hình cũng sẽ cập nhật để cho biết giá trị mặc định của my_option:

tf> run example/helloworld --help
  test options:
    -m, --my_option      this is the option's help text Default: fromxml.

Các đối tượng cấu hình khác có trong cấu hình helloworld, chẳng hạn như FileLogger, cũng chấp nhận các lựa chọn. Tuỳ chọn --log-level-display rất thú vị vì nó lọc nhật ký hiển thị trên stdout. Ở phần hướng dẫn trước, bạn có thể đã thấy thông báo lỗi "Hello, TF" Thế giới! Tôi có thiết bị ...' thông báo nhật ký đã ngừng được hiển thị trên stdout sau khi chúng tôi đã chuyển sang sử dụng FileLogger. Bạn có thể tăng độ chi tiết của ghi nhật ký vào stdout bằng cách truyền vào đối số --log-level-display.

Thử ngay bây giờ và bạn sẽ thấy thông báo "Tôi có thiết bị" thông điệp nhật ký xuất hiện lại vào stdout, ngoài việc được ghi vào một tệp:

tf> run example/helloworld --log-level-display info
…
05-24 18:53:50 I/HelloWorldTest: Hello, TF World! I have device 004ad9880810a548

Đó là tất cả các bạn!

Xin lưu ý rằng nếu bạn gặp phải vấn đề, Thương mại Mã nguồn liên kết có nhiều thông tin hữu ích không được hiển thị trong tài liệu. Nếu vẫn không được, hãy thử yêu cầu trên nền tảng android Google Group, với "Liên đoàn Thương mại" trong tiêu đề thư.