流量测试是app测试中比较重要的一项,因为现在的流量实在太贵了,而且各种助手都会统计你的使用流量情况,一旦你使用的过多,就可能会被卸载。
流量测试,我们可以在低、中、高三种负荷情况下进行测试:
-
低负荷:应用切到后台或锁屏状态;
-
中负荷:应用正常操作;
-
高负荷:应用极限操作,如下载;
那么针对三种负荷,我们可以选择如下场景进行测试:
-
app首次启动后流量
-
app后台或锁屏连续运行一段时间的流量
-
app常规操作的流量均值(可以参照umeng点击事件来设计用例)
-
app高负荷运行的流量均值和峰值(下载)
流量测试的方法一般有3类:
-
读取手机的文件来获取流量,需要自己写脚本
-
使用tcpdump +wireshark相结合的方法
-
使用第三方工具(各种工具原理不明,下文会做比较分析)
方法一:
通过tcp_rcv (接收的数据信息)和 tcp_snd(发送的数据信息)来获取流量;
1 首先获得app的uid:
每当设备上安装一个软件,就会在手机的proc/uid_stat文件夹下生成个uid的目录,放置流量文件。如图,我在安装了app并启动产生流量后,就会生成该文件夹。
当然,可以通过一下命令能获取app的uid
adb shell dumpsys package | grep packageSetting | grep {$packageName}
我们还可以通过一下命令来获取uid:
adb shell cat /proc/{$pid}}/status
2 然后进入{$uid}文件夹就能看到tcp_rcv和tcp_snd文件了
( adb shell cat proc/uid_stat/{$uid}/tcp_rcv
adb shell cat proc/uid_stat/{$uid}/tcp_snd )
注:只针对tcp协议网络的消耗统计,且在某些机型上不存在该路径。
方法二(推荐):
通过 /proc/net/xt_qtaguid/stats 来获取上行和下行的流量
1 先取得app的uid
2 然后通过以下命令来取得数据。有时候会取得几行数据,是因为一个uid可能对应多个进程,所以有几行,就求和几行。流量是累加的。
adb shell cat /proc/net/xt_qtaguid/stats | grep {$uid}
其中第6和8列为 rx_bytes(接收数据)和tx_bytes(传输数据)包含tcp,udp等所有网络流量传输的统计。
每列的含义:
idx iface acct_tag_hex uid_tag_int cnt_set rx_bytes rx_packets tx_bytes tx_packets rx_tcp_bytes rx_tcp_packets rx_udp_bytes rx_udp_packets rx_other_bytes rx_other_packets tx_tcp_bytes tx_tcp_packets tx_udp_bytes tx_udp_packets tx_other_bytes tx_other_packets
[具体参考url:http://stackoverflow.com/questions/12904809/tracking-an-applications-network-statistics-netstats-using-adb]
方法三:(网上也有此方法的介绍,但经测试,非常不准)
通过 /proc/{$pid}/net/dev
1 先取得app的pid
2 然后通过以下命令来获取数据
adb shell cat /proc/{$pid}/net/dev
然后取第一列和第九列的数据。
那么,这三种方法哪个更准确些呢?
我们执行相同的用例,分别对比3个方法和市面上的第三方工具采集的数据,看下准确性。
在测试中,我们发现方法一(通过tcp_rcv 和 tcp_rcv来计算流量并不适合所有的机型,因为有的手机没有这两个文件)
1 在tcp_rcv 和 tcp_rcv存在的情况下,执行完用例,各项数据分别为:
方法一: 5551KB
方法二: 6482.31KB
方法三: 6528.29KB
安测试: 5550.00KB
2 在tcp_rcv 和 tcp_snd不存在的情况下,执行完用例,各项数据分别为:
方法二: 4336.93KB
方法三: 4457.34KB
安测试: 4336.00KB
由此可以看出安测试优先以tcp_rcv 和 tcp_snd的值来计算流量,如果这两个文件不存在,那么取 /proc/net/xt_qtaguid/stats 中的值。
那么其他第三方工具是怎么做的呢?我们先看一下网易的emmagee,因为是开源的,所以直接看源码就可以了(https://github.com/NetEase/Emmagee)。
我下载了V2.2版本的emmagee,在 TrafficInfo.java中发现了emmagee使用的方法,他是用的方法一,所以有些机器上无法使用emmagee来测试流量。
但网易似乎发现了这个问题(https://github.com/NetEase/Emmagee/issues/40)上说,准备在后续的版本使用方法二来实现:
代码片段如下:
public long getTrafficInfo() {
RandomAccessFile rafTaffic = null;
long traffic = 0;
try {
rafTaffic = new RandomAccessFile("/proc/net/xt_qtaguid/stats", "r");
Log.i(LOG_TAG, "get traffic information");
String line = "";
while ((line = rafTaffic.readLine()) != null) {
Log.d(LOG_TAG, "line===" + line);
String[] linesplits = line.split(" ");
Log.d(LOG_TAG, "uid===" + uid);
Log.d(LOG_TAG, linesplits[3]);
if (linesplits[3].endsWith(uid)) {
traffic = traffic + Long.parseLong(linesplits[5])
+ Long.parseLong(linesplits[7]);
}
}
} catch (FileNotFoundException e) {
traffic = -1;
} catch (NumberFormatException e) {
Log.e(LOG_TAG, "NumberFormatException: " + e.getMessage());
e.printStackTrace();
} catch (IOException e) {
Log.e(LOG_TAG, "IOException: " + e.getMessage());
e.printStackTrace();
} finally {
try {
if (rafTaffic != null)
rafTaffic.close();
} catch (IOException e) {
Log.i(LOG_TAG,
"close randomAccessFile exception: " + e.getMessage());
}
}
Log.d(LOG_TAG, "Traffic===" + traffic);
return traffic;
}
在android的源码中,发现在 4.3.1 及之后的版本,android不在统计传输层的流量,而统计网络层测流量,流量的统计都放到了/proc/net/xt_qtaguid/stats这个文件下,流量需要通过读取这个文件获取(https://github.com/android/platform_frameworks_base/commit/92be93a94edafb5906e8bc48e6fee9dd07f5049e)
因此,方法二的兼容性更高,而且准确性更高(包含tcp,udp等所有网络流量传输的统计)。
注:
关于uid:
有些app通常不止一个进程在后台,而且进程号也不一样,那么这些进程的uid一样吗?
uid只跟app相关,同一个app有不同的进程,那么这些进程对应的uid是一致的