號外:
http://blog.csdn.net/zjujoe/article/details/5673469 這位大牛太牛了,都記錄下來點滴,感動!
Android CTS 測試---自己編譯CTS方法
准備 Android 環境 : Android 代碼、 jdk1.6 、 git及相應的編譯環境
1 命令行輸入
$ sudo apt-get install git-core gnupg sun-java5-jdk flex bison gperf libsdl-dev libesd0-dev libwxgtk2.6-dev build-essential zip curl libncurses5-dev zlib1g-dev valgrind
2.ubuntu10.04 不包含jdk1.6,
sudo add-apt-repository "deb http://archive.canonical.com/ lucid partner"
sudo add-apt-repository "deb-src http://archive.canonical.com/ubuntu lucid partner"
sudo apt-get update
sudo apt-get install sun-java6-jdk
要下載其源碼,先要安裝一個Android的構建工具 repo。repo只是google用Python腳本寫的調用git的一個腳本,主要是用來下載、管理Android項目的軟件倉庫。
$ curl http://android.git.kernel.org/repo > ~/bin/repo
$ chmod a+x ~/bin/repo
然后再建立一個存放源碼的目錄
$ mkdir ~/android ; cd ~/android
之后使用這個repo工具,來初始化這個源碼倉庫:
$ repo init -u git://android.git.kernel.org/platform/manifest.git // 這是主線上的代碼,也可以用 //$ repo init -u git://android.git.kernel.org/platform/manifest.git -b cupcake來指定某一版本的source 提交之后,Google會讓你提交用戶信息什么的,按照要求就OK了。(–b android-2.1_r2)
片刻等待之后,倉庫初始化完成。此時,這個倉庫只是更新了repo這個構建工具本身,並下載了整個Android源碼倉庫的一個清單的版本庫, 在~/android/.repo下面能夠看到這些文件。其中 ~/android/.repo/repo 目錄是構建工具的全部代碼,基於Python寫成,稍后再看。 其次是 ~/android/.repo/manifests/default.xml文件,這個是整個Android源碼庫的清單文件,之后repo這個工具會 根據這個清單依次下載所有的代碼。而~/android/.repo/manifest.git則是這個清單文件的版本庫 :) 。
Git有一個有意思的特性,就是可以制定存放版本庫版本信息的目錄的位置,因而可以將存放版本信息的目錄和實際的項目文件放置於不同的目錄下,而不 是像以前的cvs或者Subversion一樣在每一個目錄下都有一個討厭的.xxx隱藏目錄。這也從某種程度上減少了冗余信息。
經過上述步驟之后,可以開始進行源碼倉庫的下載了,對於repo來說,稱之為“同步”——sync。
$ repo sync
下載過程中隨時可以終斷,中斷后重新執行同步即可更新到最新的源碼倉庫。
切記,切記
這個同步下來的東西是在當前目錄下的,而且是一個因此文件夾.repo 用 ls -al 能看到
所以,你一定要自己建立一個目錄,比如/home/android,進入這個目錄再執行這個命令,要不然就會生成很多多余的文件,你還不知道到底在哪里。
我第一次就是這個,執行了N次,沒有看到一個代碼,還好,我用find -name 查找,才把他們揪出來了。
repo 補充
repo 是一個同步命令,如果輸入repo 就是同步所有的代碼吧,如果加個參數就是同步某個包的代碼。
既然有全部同步的命令,為什么我們要自己那么麻煩去同步其它的呢?因為在同步的過程,經常會出現網絡錯誤。
所以,網上有高人指點說,對於比較大的包,加參數同步,其它的,就不加參數。
在執行初始化好,就是第三步的目錄下,我們 cd .repo,就會看到project.list文件,我們可以看到所有project,總共116個。比如 repo sync build、 repo sync external/apache-http等
據個人記憶,好像build 、bionic、dalvik、prebuilt、frameworks/base這幾個包比較大,建議單獨同步。
(據網上高人說,repo服務器,每個終端最多支持3個線程,也就是我們可以同時開三個repo)
同步過程網絡失敗太正常了,多試幾次就好了,全部下來大概1.3個G,具體時間,看個人網速。
4、下載CTS http://source.android.com/compatibility/cts-intro.html
在手機或者模擬器上安裝CtsDelegatingAccessibilityService.apk
$sudo ./adb install -r /cts/android-cts/repository/testcases/CtsDelegatingAccessibilityService.apk
手機或者模擬器設置
Settings->Accessibility->兩個選項都選上;
Settings > Application > Development 三個選項都選上;
Settings > Sound & Display > Screen Timeout should be set to "Never Timeout";
5.編譯篇
#make(這個編譯比較長)
#make sdk
代碼下載完成后,進入代碼目錄,這里就以/home/android/為例
里面有一個build/envsetup.sh ,執行.(這個是配置編譯環境的,具體細節我目前還不清楚)
$ make cts //android源碼編譯好后,在編譯cts
6、編譯好cts后生成的文件位置如下
- Package CTS: out/host/linux-x86/cts/android-cts.zip
- cts make file: mydroid/build/core/tasks/cts.mk
- run cts program: mydroid/out/host/linux-x86/bin/cts
- test plans: mydroid/out/host/linux-x86/cts/android-cts/repository/plans
- test packages: mydroid/out/host/linux-x86/cts/android-cts/repository/testcases
- test results: mydroid/out/host/linux-x86/cts/android-cts/repository/results
- CTS program settings value: mydroid/cts/tools/utils/host_config.xml
運行測試時,在CTS運行界面能看到測試報告與運行狀況。測試完成后可在android-cts/repository/results/下生成詳細的測 試報告和一些附加信息,其中用日期和時間命名的文件夾下為所有的測試結果,同時文件夾也會被打成一個對應的.zip包方便提交。用瀏覽器打開.xml文件 (默認就是,直接雙擊)就可以查看所用的測試報告了
從各種渠道了解到 Android CTS 測試, 是一種類似於 Windows Mobile LTK 的測試。
大體 Google 一下, 發現關於 CTS 的信息非常至少, 只說它有兩萬多個測試用例。
然后它只對 OHA 成員開發。
本着不拋棄,不放棄的原則,繼續 Google...
終於發現了參考1:Cezary Statkiewicz's blog。
搞笑的是該 Blog 的前言部分還寫着 CTS 不開放。 后面又糾正了 Google 剛剛開放 CTS 信息(見參考2)。
大喜!
先學習¶
原來 Google 定義了一個兼容性規范(Compatibility Definition), 而 CTS 就是用於確保某個測試符合該規范。
從而基於 Android 的應用程序能夠在基於同一 API 版本的各種設備上運行。
由於我們使用Android 2.1 (Eclair), 所以從參考2下載到 Android 2.1 的
Compatibility Definition, 大體閱讀一下, 它定義了一些需求:
數據: 必須實現一種無線連接, 速率達到 200Kbit/Sec
Camera: 至少 2M pixels
重力加速: 必須有, 3維, >50Hz
指南針: 必須有, 3緯, >10Hz
GPS: 必須有
內存: 至少 92M (不包括專用內容)
Nand: /data 分區至少 290M
性能: 啟動時間: 瀏覽器 < 1300ms
MMS/SMS < 700ms
AlarmClock < 650ms
第二次啟動一個應用的時間不能超過第一次啟動時間。
CTS 測試: 必須通過最新的 CTS
升級: 必須有一種辦法可以升級全系統。 可以為:
OTA
USB
SD 卡
看來 Android 是在不斷往高端方向走。 不過想想也正常,今天的高端就是明天的低端!
Quick Start¶
參考2 的 User Manual 似乎是針對 1.6 的, 其中提到 CTS 是單獨下載的一個包。
而參考1 則說從 source code 中編譯而來。
先按照參考1簡單運行一下。
1) 獲取 2.1 代碼, 並先做一個基本的編譯(不知是否需要)
2) 編譯 cts:
cd ~/mydroid
. build/evnsetup.sh
make cts
3) 啟動 emulator (或者 device, 不過可能需要按照 User Manual 設置一下)
4) 將 ~/mydroid/out/host/linux-x86/bin 加到路徑
5) adb start-server
6) cts
進入 cts 交互環境, 可以敲入 help 看各種命令:cts_host > help
這里是quick start,所以不詳解。
7) 在 shell 下直接以非交互模式運行一下:
$ cts start --plan Signature
該測試用例比較少,發現兩分鍾可以運行通過。 像 Android 測試方案就比較耗時間了。
參考¶
1. 某大牛的 Blog 文章
http://bitbar.com/blog/44/using-androids-compatibility-test-suite
2. Android 官方論壇:
http://source.android.com/compatibility/downloads.html
前言
繼續較深入了解 CTS 的細節
先研究一下具體用法
命令行下敲 cts 進入命令行 ,
先看一下幫助
Help 一下
cts_host > help
Usage: command options
Avaiable commands and options:
Host:
help: show this message
exit: exit cts command line
Plan:
ls --plan: list available plans
ls --plan plan_name: list contents of the plan with specified name
add --plan plan_name: add a new plan with specified name
add --derivedplan plan_name -s/--session session_id -r/--result result_type: derive a plan from the given session
rm --plan plan_name/all: remove a plan or all plans from repository
start --plan test_plan_name: run a test plan
start --plan test_plan_name -d/--device device_ID: run a test plan using the specified device
start --plan test_plan_name -t/--test test_name: run a specific test
start --plan test_plan_name -p/--package java_package_name: run a specific java package
start --plan test_plan_name -t/--test test_name -d/--device device_ID: run a specific test using the specified device
start --plan test_plan_name -p/--package java_package_name -d/--device device_ID: run a specific java package using the specified device
Package:
ls -p/--package: list available packages
ls -p/--package package_name: list contents of the package with specified name
add -p/--package root: add packages from root to repository
rm -p/--package package_name/all: remove a package or all packages from repository
Result:
ls -r/--result: list all result of sessions
ls -r/--result -s/--session session_id: list detail case result of a specified session
ls -r/--result [pass/fail/notExecuted/timeout] -s/--session session_id: list detail cases of a specified session by the specified result.
History:
history/h: list all commands in command history
history/h count: list the latest count records in command history
history/h -e num: run the command designated by 'num' in command history
Device:
ls -d/--device: list available devices
列出所有的 plan
cts_host > ls --plan
List of plans (8 in total):
CTS
Signature
AppSecurity
Performance
RefApp
Java
VM
Android
查看某 plan 的內容
cts_host > ls --plan Android
Packages of plan Android (29 in total):
=================================
android.apidemos.cts
android.accessibilityservice
android.accounts
android.app
android.bluetooth
android.content
android.database
android.dpi
android.dpi2
android.example
android.gesture
android.graphics
android.hardware
android.jni
android.location
android.media
android.net
android.os
android.permission2
android.permission
android.provider
android.speech
android.telephony
android.text
android.util
android.view
android.webkit
android.widget
android.tests.appsecurity
添加一個新的 plan
cts_host > add --plan marvell
[Choose package] SignatureTest: select[Y], reject[n], or choose suite in it[m]? [Y/n/m] Y
Invalid input. Please chose 'y', 'n', or 'm' (default is 'y')
[Choose package] SignatureTest: select[Y], reject[n], or choose suite in it[m]? [Y/n/m] y
[Choose package] android.accessibilityservice: select[Y], reject[n], or choose suite in it[m]? [Y/n/m] y
[Choose package] android.accounts: select[Y], reject[n], or choose suite in it[m]? [Y/n/m] y
[Choose package] android.apidemos.cts: select[Y], reject[n], or choose suite in it[m]? [Y/n/m]
[Choose package] android.app: select[Y], reject[n], or choose suite in it[m]? [Y/n/m] y
。。。。
[Choose package] android.widget: select[Y], reject[n], or choose suite in it[m]? [Y/n/m]
cts_host > ls --plan marvell
The following package(s) contained in plan marvell have been removed:
SignatureTest
Packages of plan marvell (55 in total):
=================================
android.accessibilityservice
android.accounts
android.apidemos.cts
android.app
。。。
android.widget
刪除一個 plan
cts_host > rm --plan marvell
執行一個 plan
cts_host > start --plan Performance
start test plan Performance
==============================================================
Test package: android.performance2
android.performance2.cts.AppStartup#testStartup........................................................................................................................................................(timeout)
==============================================================
CTS_INFO >>> Max ADB operations reached. Restarting ADB...
CTS_INFO >>> Restarting device ...
CTS_INFO >>> Restart complete.
==============================================================
Test package: android.performance3
android.performance3.cts.AppStartup#testStartup..............(pass)
CTS_INFO >>> Max ADB operations reached. Restarting ADB...
CTS_INFO >>> Restarting device ...
CTS_INFO >>> Restart complete.
==============================================================
Test package: android.performance4
android.performance4.cts.AppStartup#testStartup.......(pass)
CTS_INFO >>> Max ADB operations reached. Restarting ADB...
CTS_INFO >>> Restarting device ...
CTS_INFO >>> Restart complete.
==============================================================
Test package: android.performance5
android.performance5.cts.AppStartup#testStartup........(fail)
junit.framework.AssertionFailedError: App Took too long to startup: 715 650 at android.performance5.cts.AppStartup.testStartup(AppStartup.java:67)
at android.performance5.cts.AppStartup.testStartup(AppStartup.java:67)
at java.lang.reflect.Method.invokeNative(Native Method)
at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:205)
at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:195)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:430)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1447)
at android.performance5.cts.AppStartup.testStartup(AppStartup.java:67)
at java.lang.reflect.Method.invokeNative(Native Method)
at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:205)
at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:195)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:430)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1447)
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1404)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1378)
at android.app.ApplicationContext.startActivity(ApplicationContext.java:555)
at android.performance.cts.MultiAppStartupTest.launchActivity(MultiAppStartupTest.java:52)
at android.performance.cts.MultiAppStartupTest.testMultipleApps(MultiAppStartupTest.java:89)
at java.lang.reflect.Method.invokeNative(Native Method)
at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:205)
at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:195)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:430)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1447)
Test summary: pass=2 fail=2 timeOut=1 notExecuted=0 Total=5
Time: 635.927s
查看有多少個包
cts_host > ls -p
Available packages (56 in total):
android.util
android.hardware
。。。
android.core.tests.luni.net
android.jni
android.core.vm-tests
查看某個包
cts_host > ls -p android.net
Test suites (3 in total):
android.net.cts
android.net.wifi.cts
android.net.http.cts
查看測試結果
cts_host > ls -r
List of all results:
Session Test result Start time End time Test plan name
Pass Fail Timeout NotExecuted
1 2 2 1 0 2010.06.01 16:18:03 2010.06.01 16:28:39 Performance
2 1 0 0 0 2010.06.01 16:39:38 2010.06.01 16:41:33 Signature
研究 cts 生成文件
cts 腳本文件位於: ~/mydroid/out/host/linux-x86/bin ,它是一個 100 行不到的腳本,最終執行:
java -Xmx512M
-cp ./../framework/ddmlib.jar:./../framework/junit.jar:./../framework/hosttestlib.jar:./../framework/cts.jar:./cts.jar
-DHOST_CONFIG=./../cts/android-cts/repository/host_config.xml
com.android.cts.TestHost
可見, CTS 的 Java 主程序為: com.android.cts.TestHost ,同時使用了配置文件: host_config.xml.
兩個 cts.jar: ./out/host/linux-x86/cts/android-cts/tools/cts.jar ./out/host/linux-x86/framework/cts.jar 相同。
cts 使用的目錄則為: ~/mydroid/out/host/linux-x86/cts
文件列表 1
songlixin @zjujoe-desktop:~/mydroid/out/host/linux-x86/cts$ tree -L 3
.
├── all_cts_core_files_stamp
├── all_cts_files_stamp
├── android-cts
│ ├── docs
│ ├── repository
│ │ ├── host_config.xml
│ │ ├── log_2010.06.01_16.02.21_.txt
│ │ ├── log_2010.06.01_16.12.22_.txt
│ │ ├── log_2010.06.01_16.38.30_.txt
│ │ ├── log_2010.06.01_16.59.50_.txt
│ │ ├── plans
│ │ ├── results
│ │ └── testcases
│ └── tools
│ ├── cts.jar
│ ├── hosttestlib.jar
│ ├── junit.jar
│ └── startcts
├── android-cts.zip
└── temp
└── description.xml
我們關心的主要是 repository 目錄。
文件列表 2
songlixin @zjujoe-desktop:~/mydroid/out/host/linux-x86/cts$ tree android-cts/repository/
android-cts/repository/
├── host_config.xml
├── plans
│ ├── Android.xml
│ ├── AppSecurity.xml
│ ├── CTS.xml
│ ├── Java.xml
│ ├── Performance.xml
│ ├── RefApp.xml
│ ├── Signature.xml
│ └── VM.xml
├── results
│ ├── 2010.06.01_16.18.03
│ │ ├── cts_result.css
│ │ ├── cts_result.xsl
│ │ ├── logo.gif
│ │ ├── newrule-green.png
│ │ └── testResult.xml
│ ├── 2010.06.01_16.18.03.zip
│ ├── 2010.06.01_16.39.38
│ │ ├── cts_result.css
│ │ ├── cts_result.xsl
│ │ ├── logo.gif
│ │ ├── newrule-green.png
│ │ └── testResult.xml
│ ├── 2010.06.01_16.39.38.zip
│ ├── cts_result.css
│ ├── cts_result.xsl
│ ├── logo.gif
│ └── newrule-green.png
└── testcases
├── android.core.tests.annotation.apk
├── android.core.tests.annotation.xml
├── android.core.tests.archive.apk
。。。。。。。。。。。。。。。。。。
├── CtsWidgetTestCases.xml
├── SignatureTest.apk
├── SignatureTest.xml
└── TestDeviceSetup.apk
5 directories, 156 files
可見 plans 目錄下為以 xml 格式定義的測試方案
results 目錄為 測試結果。
testcases 目錄則為一個個測試用例包
host_config.xml 為配置文件
研究 cts 源文件
從根目錄開始
Cts 的 source 包位於 android 根目錄下:
songlixin @zjujoe-desktop:~/mydroid/cts$ tree -L 2
.
├── Android.mk
├── tests
│ ├── accessibilityservice
│ ├── AndroidManifest.xml
│ ├── Android.mk
│ ├── ApiDemosReferenceTest
│ ├── appsecurity-tests
│ ├── assets
│ ├── config_demo
│ ├── core
│ ├── ProcessTest
│ ├── res
│ ├── SignatureTest
│ ├── src
│ ├── tests
│ └── vm-tests
└── tools
├── Android.mk
├── annotation-helper
├── cts-reference-app-lib
├── dasm
├── device-setup
├── dex-tools
├── dx-tests
├── host
├── signature-tools
├── spec-progress
├── test-progress
├── test-progress-new
├── utils
└── vm-tests
根目錄下的 make file 非常簡單:
songlixin @zjujoe-desktop:~/mydroid/cts$ cat Android.mk
include $(call all-subdir-makefiles)
看來主要內容在兩個子目錄下。
子目錄 1 : tools
根目錄下的 Android.mk 與其父目錄相同。
各子目錄代表不同的工具,比如 dasm 編譯后的位置是: ./out/host/linux-x86/bin/dasm
這里就不仔細分析這些工具了。
子目錄 2 : tests
看一下根目錄下的 Android.mk:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE_TAGS := tests
LOCAL_SRC_FILES := $(call all-java-files-under, src)/
$(call all-java-files-under, core/runner/src)/
src/android/app/cts/ISecondary.aidl/
src/android/os/cts/IEmptyService.aidl
LOCAL_JAVA_LIBRARIES := android.test.runner
# Resource unit tests use a private locale and some densities
LOCAL_AAPT_FLAGS = -c xx_YY -c cs -c 32dpi -c 240dpi -c 160dpi
LOCAL_PACKAGE_NAME := CtsTestStubs
include $(BUILD_PACKAGE)
# Build the test APK using its own makefile, and any other CTS-related packages
include $(call all-makefiles-under,$(LOCAL_PATH))
所有 src 及 core/runner/src 下的 java 文件被編譯成:
./out/host/linux-x86/cts/android-cts/repository/testcases/CtsTestStubs.apk
剩下的就是很多子目錄以及子目錄的子目錄會被編譯成 *.apk
Tests 目錄下每個子目錄包括一個 test suite.
songlixin @zjujoe-desktop:~/mydroid/cts/tests/tests$ tree -L 1
.
├── accessibilityservice
├── accounts
├── Android.mk
。。。
├── webkit
└── widget
Core 目錄下每個子目錄包含一個 test suite, 但是他們的代碼在其他地方
songlixin @zjujoe-desktop:~/mydroid/cts/tests/core$ tree -L 2
.
├── Android.mk
├── annotation
│ ├── AndroidManifest.xml
│ └── Android.mk
├── archive
│ ├── AndroidManifest.xml
│ └── Android.mk
。。。
├── text
│ ├── AndroidManifest.xml
│ └── Android.mk
├── xml
│ ├── AndroidManifest.xml
│ └── Android.mk
└── xnet
├── AndroidManifest.xml
└── Android.mk
appsecurity-tests/test-apps 目錄下每個子目錄包括一個 test case. 都特別簡單 .
songlixin @zjujoe-desktop:~/mydroid/cts/tests/appsecurity-tests/test-apps$ tree -L 1
.
├── Android.mk
├── AppAccessData
├── AppWithData
├── InstrumentationAppDiffCert
├── PermissionDeclareApp
├── SharedUidInstall
├── SharedUidInstallDiffCert
├── SimpleAppInstall
├── SimpleAppInstallDiffCert
├── TargetInstrumentationApp
└── UsePermissionDiffCert
總結
Cts 其實就是基於 instrumentation test, Test case 有很多類型,不同的實現方式。 對我們來說,需要:
1 ) 能夠執行現有的 test case
2 ) 能夠模仿 api demo test case 寫一些比較簡單的:
可以參考: http://www.netmite.com/ /
android/mydroid/cupcake/development/pdk/docs/instrumentation_testing.html
繼續
前言
前面都是研究 CTS 面上的東西, 這兩天認真學習了一下 Android Instrumentation Test 的相關內容,深切體會到其強大的功能!( UI 控制,生命周期控制,偽環境對象提供等等), 回過頭來,我們再來看看 CTS 的細節內容。
和前面的內容區分開,我們從具體測試用例的角度來看。
首先選擇文檔中經常提起的 apidemo 作為研究對象。
例子一: apidemo
從 test plan 開始研究
~/mydroid/out/host/linux-x86/cts/android-cts/repository/plans$ cat CTS.xml
<?xml version="1.0" encoding="UTF-8"?>
<TestPlan version="1.0">
<Entry uri="android.apidemos.cts"/>
<Entry uri="android.accessibilityservice"/>
。。。
<Entry uri="android.core.vm-tests"/>
<Entry uri="android.tests.appsecurity"/>
</TestPlan>
可見,某個 test plan 只需要包括一個到具體測試用例的 uri 申明即可。
該 uri 的定義在 test cases 子目錄下:
~/mydroid/out/host/linux-x86/cts/android-cts/repository/testcases$ cat ApiDemosReferenceTest.xml
<?xml version="1.0" encoding="UTF-8"?>
<TestPackage AndroidFramework="Android 1.0" apkToTestName="ApiDemos" appNameSpace="android.apidemos.cts" appPackageName="android.apidemos.cts" jarPath="" name="ApiDemosReferenceTest" packageToTest="com.example.android.apis" referenceAppTest="true" runner="android.test.InstrumentationTestRunner" targetBinaryName="" targetNameSpace="" version="1.0">
<TestSuite name="android">
<TestSuite name="apidemos">
<TestSuite name="cts">
<TestCase name="ApiDemosTest">
<Test name="testNumberOfItemsInListView"/>
</TestCase>
</TestSuite>
</TestSuite>
</TestSuite>
</TestPackage>
可見 , CTS 在 Android 的 Instrumentation Test 上又包了一層。該 xml 文件的格式說明沒有找到,只能先望文生義了。
照字面理解,它要測試 ApiDemo, 測試的代碼是 ApiDemoReferenceTest, 使用的 Test runner 是:android.test.InstrumentationTestRunner. ( 其它的 test runner 還有: android.test.InstrumentationCtsTestRunner, android.test.InstrumentationCoreTestRunner)
該 Test 一共只有一個 test: testNumberOfItemsInListView
以下是相關文件:
songlixin@zjujoe-desktop:~/mydroid/out/host/linux-x86/cts/android-cts/repository/testcases$ ls -l ApiDemo*
-rw-r--r-- 1 songlixin songlixin 2106161 2010-06-16 09:38 ApiDemos.apk
-rw-r--r-- 1 songlixin songlixin 5526 2010-06-16 09:38 ApiDemosReferenceTest.apk
-rw-r--r-- 1 songlixin songlixin 657 2010-06-16 09:38 ApiDemosReferenceTest.xml
現在看看這些位於 out 目錄下的文件是如何生成的。
再看源碼樹
根據參考, 要在 cts 中添加一個 test package, 必須將其加入: build/core/tasks/cts.mk.
查看一下,果然 , 其中包含:
ApiDemos /
ApiDemosReferenceTest /
ApiDemos 位於:
~/mydroid/development/samples/ApiDemos$ tree -L 2
.
├── AndroidManifest.xml
├── Android.mk
├── assets
│ ├── fonts
│ └── read_asset.txt
├── _index.html
├── res
│ ├── anim
│ ├── drawable
。。。
│ ├── layout
│ ├── menu
│ ├── raw
│ ├── values
。。。
│ └── xml
├── src
│ └── com
└── tests
├── AndroidManifest.xml
├── Android.mk
├── build.properties
└── src
其中, make file 中包含 tests tag:
LOCAL_MODULE_TAGS := samples tests
ApiDemosReferenceTest 位於:
~/mydroid/cts/tests/ApiDemosReferenceTest$ tree
.
├── AndroidManifest.xml
├── Android.mk
└── src
└── android
└── apidemos
└── cts
├── AllTests.java
└── ApiDemosTest.java
其 make file 沒有包含 tests tag, 但是父目錄的 Android.mk 中包含了。並且它使用所有子目錄的源碼。
兩個疑問
1) ApiDemosReferenceTest.xml 是從哪里來的?
猜測: 從 /mydroid/cts/tests/ApiDemosReferenceTest 生成
2) ApiDemosReferenceTest 中提供了兩個 testcase, 而 ApiDemosReferenceTest.xml 只用了一個?
從代碼上看, ~/mydroid/cts/tools/utilsbuildCts.py 是用來生成 test description 以及 test plan 的。它在~/mydroid/build/core/tasks/cts.mk 中被調用。
例子二: CtsExample
CTS test plan 中有:
<Entry uri="android.example"/>
這對應:
~/mydroid/out/host/linux-x86/cts/android-cts/repository/testcases$ ls -l CtsExampleTestCases.*
-rw-r--r-- 1 songlixin songlixin 3294 2010-06-16 10:58 CtsExampleTestCases.apk
-rw-r--r-- 1 songlixin songlixin 1257 2010-06-16 10:59 CtsExampleTestCases.xml
看它的 xml 文件:
<?xml version="1.0" encoding="UTF-8"?><TestPackage AndroidFramework="Android 1.0" appNameSpace="com.android.cts.example" appPackageName="android.example " name="CtsExampleTestCases" runner="android.test.InstrumentationTestRunner" version="1.0">
<TestSuite name="android">
<TestSuite name="example">
<TestSuite name="cts">
<TestCase name="ExampleTest">
<Test name="testBlort">
<Description> Test {@link Example#blort}. </Description>
</Test>
</TestCase>
<TestCase name="ExampleSecondaryTest">
<Test name="testZorch">
<Description> Test {@link Example#zorch}. </Description>
</Test>
</TestCase>
</TestSuite>
</TestSuite>
</TestSuite>
</TestPackage>
其中包含了兩個 test case.
我們再看 build/core/tasks/cts.mk :
CtsExampleTestCases /
該 package 位於:
~/mydroid/cts/tests/tests/example$ tree
.
├── AndroidManifest.xml
├── Android.mk
└── src
└── android
└── example
├── cts
│ ├── ExampleSecondaryTest.java
│ └── ExampleTest.java
└── Example.java
該 package 的特殊之處在於它的測試代碼以及被測試代碼都在同一個包內。
兩個 TestCase 都是從 TestCase 繼承,因為它不需要更復雜的功能。
可以發現, 相比較 ApiDemo 而言,這是一個更典型的 CTS 測試的例子。如果您想寫自己的 cts 測試用例,不凡模仿它。更進一步說, cts/tes/tests 下的那些例子更適合我們用來參考。比如: performance 目錄下的MultiAppStartupTest, 繼承了 InstrumentationTestCase. 也是一個很好的例子。
另外,還發現每個例子其包的最后一段總是 cts, 不知是不是硬性要求。這也可以說明 CTS 是基於instrumentation test, 但是又不等同。
疑問
AndroidManifest.xml 中定義的 package name 為: com.andoid.cts.example
Example 類屬於:
package android.example;
public class Example
ExampleTest 類屬於:
package android.example.cts;
public class ExampleTest extends TestCase
非常奇怪!
單個運行 CTS 測試用例
安裝
~/mydroid/out/host/linux-x86/cts/android-cts/repository/testcases$ adb install CtsPerformanceTestCases.apk
70 KB/s (4518 bytes in 0.062s)
pkg: /data/local/tmp/CtsPerformanceTestCases.apk
Success
查看一下已經安裝的 instrumentation
~/mydroid/out/host/linux-x86/cts/android-cts/repository/testcases$ adb shell pm list instrumentation
instrumentation:com.android.cts.performance/android.test.InstrumentationTestRunner (target=com.android.calculator2)
instrumentation:com.android.example.spinner.test/android.test.InstrumentationTestRunner (target=com.android.example.spinner)
instrumentation:com.example.android.apis/.app.LocalSampleInstrumentation (target=com.example.android.apis)
instrumentation:com.example.helloandroid.test/android.test.InstrumentationTestRunner (target=com.example.helloandroid)
運行(失敗)
:~/mydroid/out/host/linux-x86/cts/android-cts/repository/testcases$ adb shell am instrument -w -r com.android.cts.performance/android.test.InstrumentationTestRunner
INSTRUMENTATION_STATUS: id=InstrumentationTestRunner
INSTRUMENTATION_STATUS: current=1
INSTRUMENTATION_STATUS: class="android".performance.cts.MultiAppStartupTest
INSTRUMENTATION_STATUS: stream=
android.performance.cts.MultiAppStartupTest:
INSTRUMENTATION_STATUS: numtests=1
INSTRUMENTATION_STATUS: test=testMultipleApps
INSTRUMENTATION_STATUS_CODE: 1
INSTRUMENTATION_STATUS: id=InstrumentationTestRunner
INSTRUMENTATION_STATUS: current=1
INSTRUMENTATION_STATUS: class="android".performance.cts.MultiAppStartupTest
INSTRUMENTATION_STATUS: stream=
Error in testMultipleApps:
android.content.ActivityNotFoundException: Unable to find explicit activity class {com.android.calendar/com.android.calendar.LaunchActivity}; have you declared this activity in your AndroidManifest.xml?
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1404)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1378)
at android.app.ApplicationContext.startActivity(ApplicationContext.java:555)
at android.performance.cts.MultiAppStartupTest.launchActivity(MultiAppStartupTest.java:52)
at android.performance.cts.MultiAppStartupTest.testMultipleApps(MultiAppStartupTest.java:89)
at java.lang.reflect.Method.invokeNative(Native Method)
at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:205)
at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:195)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:430)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1447)
INSTRUMENTATION_STATUS: numtests=1
INSTRUMENTATION_STATUS: stack=android.content.ActivityNotFoundException: Unable to find explicit activity class {com.android.calendar/com.android.calendar.LaunchActivity}; have you declared this activity in your AndroidManifest.xml?
at android.app.Instrumentation.checkStartActivityResult(Instrumentation.java:1404)
at android.app.Instrumentation.execStartActivity(Instrumentation.java:1378)
at android.app.ApplicationContext.startActivity(ApplicationContext.java:555)
at android.performance.cts.MultiAppStartupTest.launchActivity(MultiAppStartupTest.java:52)
at android.performance.cts.MultiAppStartupTest.testMultipleApps(MultiAppStartupTest.java:89)
at java.lang.reflect.Method.invokeNative(Native Method)
at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:205)
at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:195)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:169)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:154)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:430)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1447)
INSTRUMENTATION_STATUS: test=testMultipleApps
INSTRUMENTATION_STATUS_CODE: -1
INSTRUMENTATION_RESULT: stream=
Test results for InstrumentationTestRunner=.E
Time: 6.729
FAILURES!!!
Tests run: 1, Failures: 0, Errors: 1
INSTRUMENTATION_CODE: -1
songlixin@zjujoe-desktop:~/mydroid/out/host/linux-x86/cts/android-cts/repository/testcases$
修改
出錯信息說是找不到:calendar
修改代碼,使其不啟動 calendar:
//launchActivity("com.android.calendar", "LaunchActivity", true);
//Thread.sleep(ACTIVITY_STARTUP_WAIT_TIME);
重新編譯: make cts
重新安裝
重新安裝用:adb install -r CtsPerformanceTestCases.apk
運行(成功)
~/mydroid/out/host/linux-x86/cts/android-cts/repository/testcases$
adb shell am instrument -w -r com.android.cts.performance/android.test.InstrumentationTestRunner
INSTRUMENTATION_STATUS: id=InstrumentationTestRunner
INSTRUMENTATION_STATUS: current=1
INSTRUMENTATION_STATUS: class="android".performance.cts.MultiAppStartupTest
INSTRUMENTATION_STATUS: stream=
android.performance.cts.MultiAppStartupTest:
INSTRUMENTATION_STATUS: numtests=1
INSTRUMENTATION_STATUS: test=testMultipleApps
INSTRUMENTATION_STATUS_CODE: 1
INSTRUMENTATION_STATUS: id=InstrumentationTestRunner
INSTRUMENTATION_STATUS: current=1
INSTRUMENTATION_STATUS: class="android".performance.cts.MultiAppStartupTest
INSTRUMENTATION_STATUS: stream=.
INSTRUMENTATION_STATUS: numtests=1
INSTRUMENTATION_STATUS: test=testMultipleApps
INSTRUMENTATION_STATUS_CODE: 0
INSTRUMENTATION_RESULT: stream=
Test results for InstrumentationTestRunner=.
Time: 7.389
OK (1 test)
總結
至此,我們大體知道如何運行 cts, 配置 cts, 擴充 cts, 下一步就看具體實踐了!
參考鏈接里有如何添加一個 cts 測試、修改 test plan 的信息,所以本文就沒有重復。
參考
Android CTS (Compatibility Test Suite) introduction
http://androidboss.com/android-cts-compatibility-test-suite-introduction-2/