Uçtan uca TF testi örneği

Bu eğitim, bir "merhaba dünya" Ticaret Federasyonu (Tradefed veya TF) test yapılandırması oluşturma konusunda size rehberlik eder ve TF çerçevesine uygulamalı bir giriş sağlar. Bir geliştirme ortamından başlayarak basit bir yapılandırma oluşturacak ve özellikler ekleyeceksiniz.

Öğretici, test geliştirme sürecini, yapılandırmanızı nasıl oluşturacağınızı ve kademeli olarak iyileştireceğinizi gösteren, her biri birkaç adımdan oluşan bir dizi alıştırma olarak sunar. Test yapılandırmasını tamamlamak için ihtiyacınız olan tüm örnek kodlar sağlanmıştır ve her alıştırmanın başlığı, o adımdaki rolleri açıklayan bir harfle açıklanmıştır:

  • Geliştirici için D
  • Entegratör için ben
  • Test Çalıştırıcısı için R

Eğitimi tamamladıktan sonra işleyen bir TF yapılandırmasına sahip olacak ve TF çerçevesindeki birçok önemli kavramı anlayacaksınız.

Ticaret Federasyonu'nu kurun

TF geliştirme ortamını ayarlamaya ilişkin ayrıntılar için bkz. Makine Kurulumu . Bu eğitimin geri kalanında, TF ortamına başlatılmış açık bir kabuğunuz olduğu varsayılmaktadır.

Basitlik açısından bu eğitimde, bir konfigürasyonun ve sınıflarının TF çerçeve çekirdek kütüphanesine eklenmesi gösterilmektedir. Bu, ticari olarak beslenen JAR'ın derlenmesi ve ardından modüllerinizin bu JAR'a göre derlenmesi yoluyla kaynak ağacın dışında modüller geliştirmeye kadar genişletilebilir.

Bir test sınıfı oluşturun (D)

Stdout'a mesaj gönderen bir merhaba dünya testi oluşturalım. Ticareti yapılan bir test genellikle IRemoteTest arayüzünü uygular. İşte HelloWorldTest için bir uygulama:

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!");
    }
}

Bu örnek kodu <tree>/tools/tradefederation/core/src/com/android/tradefed/example/HelloWorldTest.java dosyasına kaydedin ve tradefed'i kabuğunuzdan yeniden oluşturun:

m -jN

Yukarıdaki örnekte CLog.i çıktıyı konsola yönlendirmek için kullanıldığını unutmayın. Ticaret Federasyonu'nda oturum açma hakkında daha fazla bilgi Günlüğe Kaydetme (D, I, R) bölümünde açıklanmıştır.

Derleme başarılı olmazsa, hiçbir adımı kaçırmadığınızdan emin olmak için Makine Kurulumu'na başvurun.

Bir konfigürasyon oluşturun (I)

Ticaret Federasyonu testleri, tradefed'e hangi testin (veya testlerin) çalıştırılacağı ve diğer hangi modüllerin hangi sırayla çalıştırılacağı konusunda talimat veren bir XML dosyası olan bir Yapılandırma oluşturularak yürütülebilir hale getirilir.

HelloWorldTest'imiz için yeni bir Konfigürasyon oluşturalım (HelloWorldTest'in tam sınıf adını not edin):

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

Bu verileri yerel dosya sisteminizin herhangi bir yerindeki helloworld.xml dosyasına kaydedin (örn /tmp/helloworld.xml ). TF, Yapılandırma XML dosyasını (diğer adıyla config ) ayrıştıracak, yansımayı kullanarak belirtilen sınıfı yükleyecek, somutlaştıracak, IRemoteTest aktaracak ve run yöntemini çağıracaktır.

Yapılandırmayı çalıştırın (R)

Kabuğunuzdan takas edilen konsolu başlatın:

tradefed.sh

Bir cihazın ana makineye bağlı olduğundan ve takas için görünür olduğundan emin olun:

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

Yapılandırmalar run <config> konsol komutu kullanılarak yürütülebilir. Denemek:

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!

"Merhaba, TF Dünyası!" görmelisiniz. terminaldeki çıktı.

Konsol komut isteminde list invocations veya li kullanarak bir komutun çalışmasının tamamlandığını doğrulayabilirsiniz ve komut hiçbir şey yazdırmamalıdır. Komutlar şu anda çalışıyorsa aşağıdaki gibi görüntülenirler:

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

Yapılandırmayı sınıf yoluna ekleyin (D, I, R)

Dağıtım kolaylığı için, yapılandırmaları ticareti yapılan JAR'ların kendisinde de paketleyebilirsiniz. Tradefed, sınıf yolundaki yapılandırma klasörlerine yerleştirilen tüm yapılandırmaları otomatik olarak tanır.

Örnek olarak helloworld.xml dosyasını ticari beslenen çekirdek kitaplığa ( <tree>/tools/tradefederation/core/res/config/example/helloworld.xml ) taşıyın. Tradefed'i yeniden oluşturun, tradefed konsolunu yeniden başlatın ve ardından tradefed'den sınıf yolundaki yapılandırmaların listesini görüntülemesini isteyin:

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

Artık helloworld yapılandırmasını aşağıdakileri kullanarak çalıştırabilirsiniz:

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!

Bir cihazla etkileşim kurun (D, R)

Şu ana kadar HelloWorldTest'imiz ilginç bir şey yapmıyor. Tradefed'in uzmanlığı Android cihazları kullanarak testler yürütmektir, bu yüzden teste bir Android cihazı ekleyelim.

Testler, IRemoteTest#run yöntemi çağrıldığında çerçeve tarafından sağlanan TestInformation kullanılarak bir Android cihazına referans alabilir.

Cihazın seri numarasını görüntülemek için HelloWorldTest yazdırma mesajını değiştirelim:

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

Şimdi tradefed'i yeniden oluşturun ve cihazların listesini kontrol edin:

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

Mevcut olarak listelenen seri numarasını not edin; HelloWorld'e tahsis edilmesi gereken cihaz budur:

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

Cihazın seri numarasını gösteren yeni yazdırma mesajını görmelisiniz.

Test sonuçlarını gönder (D)

IRemoteTest #run yöntemine sağlanan ITestInvokasyonListener örneğindeki yöntemleri çağırarak sonuçları raporlar. TF çerçevesinin kendisi, her Çağrının başlangıcını ( ITestInvokasyonListener#invokasyonStarted aracılığıyla) ve sonunu ( ITestInvokasyonListener#invokasyonEnded aracılığıyla) raporlamaktan sorumludur.

Test çalıştırması , testlerin mantıksal bir koleksiyonudur. Test sonuçlarını raporlamak için IRemoteTest , bir test çalışmasının başlangıcını, her testin başlangıcını ve bitişini ve test çalışmasının sonunu raporlamaktan sorumludur.

Tek bir başarısız test sonucuyla HelloWorldTest uygulamasının nasıl görünebileceği aşağıda açıklanmıştır.

@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, kendi uygulamanızı sıfırdan yazmak yerine yeniden kullanabileceğiniz çeşitli IRemoteTest uygulamalarını içerir. Örneğin InstrumentationTest , bir Android uygulamasının testlerini bir Android cihazında uzaktan çalıştırabilir, sonuçları ayrıştırabilir ve bu sonuçları ITestInvocationListener iletebilir. Ayrıntılar için bkz. Test Türleri .

Test sonuçlarını saklayın (I)

Bir TF yapılandırması için varsayılan test dinleyicisi uygulaması, bir çağrının sonuçlarını stdout'a döken TextResultReporter'dır . Örnek olarak önceki bölümdeki HelloWorldTest yapılandırmasını çalıştırın:

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

Bir çağrının sonuçlarını başka bir yerde, örneğin bir dosyada saklamak için, yapılandırmanızdaki result_reporter etiketini kullanarak özel bir ITestInvocationListener uygulaması belirtin.

TF ayrıca, test sonuçlarını JUnit XML yazıcısının kullandığı formata benzer bir formatta bir XML dosyasına yazan XmlResultReporter dinleyicisini de içerir. Sonuç_raporlayıcısını yapılandırmada belirtmek için …/res/config/example/helloworld.xml yapılandırmasını düzenleyin:

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

Şimdi tradefed'i yeniden oluşturun ve merhaba dünya örneğini yeniden çalıştırın:

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

Bir XML dosyasının oluşturulduğunu belirten günlük mesajına dikkat edin; oluşturulan dosya şöyle görünmelidir:

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

Ayrıca kendi özel çağrı dinleyicilerinizi de yazabilirsiniz; onların yalnızca ITestInvokasyonListener arayüzünü uygulaması yeterlidir.

Tradefed birden fazla çağrı dinleyicisini destekler, böylece test sonuçlarını birden fazla bağımsız hedefe gönderebilirsiniz. Bunu yapmak için yapılandırmanızda birden fazla <result_reporter> etiketi belirtmeniz yeterlidir.

Günlük kaydı olanakları (D, I, R)

TF'nin kayıt olanakları şunları içerir:

  1. Cihazdan günlükleri yakalayın (diğer adıyla cihaz logcat'i)
  2. Ana makinede çalışan Ticaret Federasyonu çerçevesindeki günlükleri kaydedin (ana bilgisayar günlüğü olarak da bilinir)

TF çerçevesi, tahsis edilen cihazdan logcat'i otomatik olarak yakalar ve işlenmek üzere çağrı dinleyicisine gönderir. XmlResultReporter daha sonra yakalanan cihazın logcat'ını bir dosya olarak kaydeder.

TF ana bilgisayar günlükleri, ddmlib Log sınıfı için CLog sarmalayıcısı kullanılarak raporlanır. HelloWorldTest'teki önceki System.out.println çağrısını bir CLog çağrısına dönüştürelim:

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

CLog String.format benzer şekilde dize enterpolasyonunu doğrudan işler. TF'yi yeniden oluşturup yeniden çalıştırdığınızda stdout'ta günlük mesajını görmelisiniz:

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

Varsayılan olarak, tradefed ana bilgisayar günlük mesajlarını stdout'a çıkarır . TF ayrıca mesajları bir dosyaya yazan bir günlük uygulamasını da içerir: FileLogger . Dosya günlüğü eklemek için yapılandırmaya FileLogger tam sınıf adını belirten bir logger etiketi ekleyin:

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

Şimdi helloworld örneğini yeniden oluşturun ve çalıştırın:

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
…

Günlük mesajı, görüntülendiğinde HelloWorldTest günlük mesajınızı içermesi gereken ana bilgisayar günlüğünün yolunu belirtir:

more /tmp/0/inv_6390011618174565918/host_log_4255420317120216614.txt

Örnek çıktı:

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

Kullanım seçenekleri (D, I, R)

TF Yapılandırmasından yüklenen nesneler (diğer adıyla Yapılandırma nesneleri ), @Option ek açıklamasını kullanarak komut satırı bağımsız değişkenlerinden de veri alabilir.

Katılmak için bir Yapılandırma nesne sınıfı, @Option ek açıklamasını bir üye alanına uygular ve ona benzersiz bir ad sağlar. Bu, üye alan değerinin bir komut satırı seçeneği aracılığıyla doldurulmasını sağlar (ve ayrıca bu seçeneği otomatik olarak yapılandırma yardım sistemine ekler).

Not: Tüm alan türleri desteklenmez. Desteklenen türlerin açıklaması için bkz. OptionSetter .

HelloWorldTest'e bir @Option ekleyelim:

@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";

Daha sonra, seçeneğin değerini HelloWorldTest'te görüntülemek için bir günlük mesajı ekleyelim, böylece seçeneğin doğru şekilde alındığını gösterebiliriz:

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

Son olarak TF'yi yeniden oluşturun ve helloworld'ü çalıştırın; my_option varsayılan değerine sahip bir günlük mesajı görmelisiniz:

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

Değerleri komut satırından iletin

my_option için bir değer girin; my_option bu değerle doldurulduğunu görmelisiniz:

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

TF yapılandırmaları ayrıca @Option alanları için yardım metnini otomatik olarak görüntüleyen bir yardım sistemi içerir. Şimdi deneyin; my_option için yardım metnini görmelisiniz:

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.

"Yalnızca önemli seçeneklerin yazdırılması" hakkındaki iletiye dikkat edin. Seçenek yardım karmaşasını azaltmak için TF, --help belirtildiğinde belirli bir @Option alanı yardım metninin gösterilip gösterilmeyeceğini belirlemek için Option#importance özelliğini kullanır. --help-all önemi ne olursa olsun her zaman tüm @Option alanları için yardımı gösterir. Ayrıntılar için bkz . Option.Importance .

Bir konfigürasyondan değerleri iletme

Ayrıca, bir <option name="" value=""> öğesi ekleyerek yapılandırma içinde bir Option değeri de belirleyebilirsiniz. helloworld.xml kullanarak test edin:

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

Helloworld'ü yeniden oluşturmak ve çalıştırmak artık şu çıktıyı üretmelidir:

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

Yapılandırma yardımının da my_option öğesinin varsayılan değerini gösterecek şekilde güncellenmesi gerekir:

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

Helloworld yapılandırmasında yer alan FileLogger gibi diğer yapılandırma nesneleri de seçenekleri kabul eder. --log-level-display seçeneği ilginçtir çünkü stdout'ta görünen günlükleri filtreler. Eğitimin başlarında, FileLogger kullanmaya geçtikten sonra "Merhaba, TF Dünyası! Cihazım var…' günlük mesajının stdout'ta görüntülenmediğini fark etmiş olabilirsiniz --log-level-display arg.

Bunu şimdi deneyin; bir dosyada oturum açmanın yanı sıra 'Cihazım var' günlük mesajının stdout'ta yeniden göründüğünü görmelisiniz:

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

Hepsi bu kadar millet!

Bir hatırlatma olarak, eğer bir konuda takılıp kalırsanız, Ticaret Federasyonu kaynak kodunda belgelerde gösterilmeyen birçok yararlı bilgi bulunur. Her şey başarısız olursa, mesaj konusuna "Ticaret Federasyonu" yazarak android platformundaki Google Grubuna sormayı deneyin.