今天在這里我想回顧一下之前做Android終端專項測試的一些經歷吧。大家都知道移動終端不管現在發展的如何,終歸是一種資源受限的設備,例如電量,內存,流量等等。因此,我們需要專門針對移動終端的App進行一些相關的測試,這樣一定程度上會提升用戶的體驗。下面,我將列出一些專項測試(粗體為我涉及過的):
- Android終端電量測試;
- Android終端流量測試;
- Android終端內存測試;
- 頁面流暢度測試;
- Android終端CPU測試;
- 弱網絡測試;
- Android權限分析測試;
- ...
上述這種類型的測試還有很多,咋一看,感覺有點懵,但是這類測試都是存在一些共性的,也就是存在一種方法論來實施這些測試的,這也是本文重點要討論的。因為只有掌握了方法論,我們才會對不同種類的專項測試應對自如。
好了,現在我們進入正題。首先,我們要明確一點:專項測試與普通的功能測試的區別:對于功能測試,我們一般只要設計測試用例,然后看程序是否符合預期結果,即程序的功能邏輯是否正確。但是對于專項測試,我們的預期結果是什么呢?所以,對于專項測試,我們需要確定一個衡量標準,而這個標準是一種可以量化的東西/數據,例如,在電量測試我們一般使用CPU時間片,Alarm喚醒次數和喚醒時長等。然后,再進行橫向對比:
- 不同測試場景(測試用例)下的對比;
- 相同測試場景下,不同版本之間的對比;
- 相同測試場景下,競品之間的對比;
- 相同測試場景下,不同設備之間的對比。
只有通過量化標準和橫向對比,我們才能從一定程度確定程序是否符合我們的預期。根據上述量化標準,我們要講到終端專項測試的四要素了:
- 檢測工具:一種能夠實時采樣應用的相關(量化)數據的工具,這種工具可以是腳本、apk,反正只要能得到數據就可以了;
- 測試場景:在開始測試前,我們要分析并確定哪些場景下的數據才是我們想要的;
- 自動化腳本:編寫相應的自動化測試腳本,這樣可以避免手工操作對測試數據帶來的一些影響;
- 分析工具:能深入到代碼中進行分析,這個一般可能是由開發人員做,不過,測試人員也是可以涉及的。
一般來說,通過確定量化標準以及四要素的具體內容,我們就可以順利開展專項測試了,當然這其中會有很多坑。再提一點,每次具體的測試我們最后進行多次,去掉那些毛刺數據,然后取平均值,這樣得到的結果更準確一些。
下面我將會以電量測試作為例子具體講解一下如何使用上面所謂的方法論。首先,我們先確認量化標準,電量測試的一種量化標準是測試電流,這種方式應該說是我們直接能想到的,但是這種方式的缺點較多,例如,測試工具不易獲得,測試的是全局的。所以,一般我們以下幾個數據作為衡量標準:
- CPU 時間片(單位:Jiffies,一般手機為每單位消耗10ms的CPU 輪詢時長);
- Alarm 喚醒次數和喚醒時長;
- WakeLock 鎖的使用;
那我們如何去獲得這些數據呢?
CPU時間片
CPU 時間分為用戶態、系統態和空閑態。所以,CPU時間片=用戶態時間片+系統態時間片
,除此之外,為了確保 CPU 時間片采集的準確性,測試前需要固定測試設備的 CPU 頻率。通過一下命令,我們可以查看具體進程的相關統計:
# %s為指定進程的pid
adb shell cat /proc/%s/stat
# 具體實例及結果輸出:
adb shell cat /proc/9972/stat
# 9972 (le.android.keep) S 201 201 0 0 -1 1077936448 12591 0 0 0 25 15 0 0 20 0 16
# 0 4895875 1524547584 10237 4294967295 1 1 0 0 0 0 4612 0 38136 4294967295 0 0 1
#7 0 0 0 0 0 0 0 0 0
結果說明:總的時間片 = 25+15 = 40,將兩次相減得到差值增量即可。參數解釋:
pid = 9972 應用的進程id
utime=25 第13位,該進程在用戶態運行的時間,單位:Jiffies
stime=15 第14位,該進程在內核態運行的時間,單位:Jiffies
Alarm 和 WakeLock
- 查看 Alarm,喚醒次數/時間:
dumpsys alarm
- 查看 WakeLock:
dumpsys power
或者cat /sys/power/wake_lock
接下來我們該確定測試場景了,對于電量測試來說,我們一般會重點放在后臺待機的場景下進行測試,為什么這么說呢?在前臺使用時,用戶是有感知的,此時電量消耗較高是正常的(相對而言)。而后臺待機情況下,用戶是無感知的,此時用戶認為電量消耗較低的。這這種情況下,我們就不需要自動化測試腳本了,只要確定測試環境就可以了。
本文講到這里,我們先告一段落吧,以后有空可以針對一種具體的專項測試進行詳細地分析。其實,要實施這些專項測試是需要一定功底的,作為 Android 測試人員,首先你得深入了解 Android 系統的一些特點,例如它的內存管理機制,Alarm 喚醒機制,進程線程模型;其次,Android 是基于 Linux 內核的,所以我們對 Linux 也要一定的了解,Android 也給我們提供了非常有用的命令行工具,很多的測試數據都可以通過命令行工具來獲得。
關于 Android 電量使用統計,推薦大家一篇 Android 官方的一篇文檔——Power Profiles for Android。
2015.4.10,append:
最近遇到一個問題,就是如何將 CPU 時間片消耗的Jiffies
值轉換為具體的電量消耗,也就是mAh
。為什么會有這個問題呢?好吧,其實就是因為一般人是不明白Jiffies
是什么意思的。下面是我個人的想法:
先普及一下物理上的一個公式吧,電能W(焦耳J)= P * t = U * I * t
,從公式中可以看出,在電壓恒定的情況下,只要知道電流和時間即可得到電量。
通過文檔——Power Profiles for Android,我們可以了解到Android設備中的各個硬件模塊在不同狀態下的平均電流值是不一樣的,例如我們講的 CPU,CPU 在不同狀態下(例如,運行頻率,active or idle)的平均電流是不一樣的。具體相應的電流值都記錄在文件power_profile.xml
中,而這個文件又在/system/framework/framework-res.apk
這個apk中,通過反編譯這個 apk 可以得到該文件。關于這個文件大家還可以參考一下這篇文章——電量統計之一:PowerProfile.java與power_profile.xml。
好了,講完電流,我們再講一下時間,也就是 CPU 的運行時間,這個時間其實就是Jiffies
,一般來講:1 Jiffies = 10ms
,然后我們可以計算電量了。目前來講,我的想法就是這樣,估計這個只能做個參考吧。
附加一個power_profile.xml
文件的內容給大家,記住,不同設備的值可能不一樣。
<?xml version="1.0" encoding="utf-8"?>
<device name="Android">
<!-- Most values are the incremental current used by a feature,
in mA (measured at nominal voltage).
The default values are deliberately incorrect dummy values.
OEM's must measure and provide actual values before
shipping a device.
Example real-world values are given in comments, but they
are totally dependent on the platform and can vary
significantly, so should be measured on the shipping platform
with a power meter. -->
<item name="none">0</item>
<item name="screen.on">0.1</item> <!-- ~200mA -->
<item name="screen.full">0.1</item> <!-- ~300mA -->
<item name="bluetooth.active">0.1</item> <!-- Bluetooth data transfer, ~10mA -->
<item name="bluetooth.on">0.1</item> <!-- Bluetooth on & connectable, but not connected, ~0.1mA -->
<item name="wifi.on">0.1</item> <!-- ~3mA -->
<item name="wifi.active">0.1</item> <!-- WIFI data transfer, ~200mA -->
<item name="wifi.scan">0.1</item> <!-- WIFI network scanning, ~100mA -->
<item name="dsp.audio">0.1</item> <!-- ~10mA -->
<item name="dsp.video">0.1</item> <!-- ~50mA -->
<item name="radio.active">0.1</item> <!-- ~200mA -->
<item name="radio.scanning">0.1</item> <!-- cellular radio scanning for signal, ~10mA -->
<item name="gps.on">0.1</item> <!-- ~50mA -->
<!-- Current consumed by the radio at different signal strengths, when paging -->
<array name="radio.on"> <!-- Strength 0 to BINS-1 -->
<value>0.2</value> <!-- ~2mA -->
<value>0.1</value> <!-- ~1mA -->
</array>
<!-- Different CPU speeds as reported in
/sys/devices/system/cpu/cpu0/cpufreq/stats/time_in_state -->
<array name="cpu.speeds">
<value>400000</value> <!-- 400 MHz CPU speed -->
</array>
<!-- Current when CPU is idle -->
<item name="cpu.idle">0.1</item>
<!-- Current at each CPU speed, as per 'cpu.speeds' -->
<array name="cpu.active">
<value>0.1</value> <!-- ~100mA -->
</array>
<!-- This is the battery capacity in mAh (measured at nominal voltage) -->
<item name="battery.capacity">1000</item>
<array name="wifi.batchedscan"> <!-- mA -->
<value>.0002</value> <!-- 1-8/hr -->
<value>.002</value> <!-- 9-64/hr -->
<value>.02</value> <!-- 65-512/hr -->
<value>.2</value> <!-- 513-4,096/hr -->
<value>2</value> <!-- 4097-/hr -->
</array>
</device>
append end
參考文章
- APT:APT是一個Android平臺高效性能測試組件,提供豐富實用的功能,適用于開發自測、定位性能瓶頸;測試人員完成性能基準測試、競品對比測試;
- Android 性能分析案例;
- Android Performance Case Study;
- 專欄:Android性能優化;
- Android Application Performance Improvement;
- Avoiding memory leaks;
- Android Layout Tricks #1;
- 如何分析Android應用內存使用情況。