定向班第二期_Shell 进阶实战_20190907

性能分析分析

查看当前开放的端口和进程

netstat -tlnp

压测时统计当前机器的连接数

netstat -tnp| sed 1,2d | awk '{print $5}' | awk -F: '{print $1}' | sort | uniq -c | sort -nr

统计一个进程的信息

for i in {1..20};do sleep 1;ps -o %cpu,%mem -p 20444;done

通过ps统计cpu的数据是不准的,cputime/realtime会导致这个数据在进程运行很久后总体值很小。

利用top统计cpu mem

top -b -p 20444 -d 1

作业1

统计20次进程的cpu和mem的数据,并输出平均值,把命令和输出贴到回复里。大概用到的技术 ,top awk sed

cpu mem
0.1  20
0.2 30
------
0.15 25
top -b -p 20444 -n 20 -d 1 | grep --line-buffered 20444 | awk 'BEGIN{OFS="\\t";print "cpu","mem","avgc","avgm"}{c+=$9;m+=$10;print $9,$10,c/NR,m/NR}'

TODO

load的具体计算公式

Android自动化工具

通过adb shell 查看正在打开的app进程

adb logcat | grep Displayed
am force-stop com.xueqiu.android
ps
top
dumpsys activity top

如何获取界面

  • adb shell dumpsys activity top
  • uiautomator
  • uiautomatorviewer 路径 Android/sdk//tools/bin/uiautomatorviewer

界面元素解析

  • 控件类型 class android.widget.ImageView
  • 资源定位符:resource-id com.xueqiu.android:id/user_profile_icon
  • 内容描述:content-desc 增加可访问性的
  • 展示文本:text 如果是TextView控件,会有一个不为空的text属性,其他的控件也有,但是多数为空。
  • 父控件的第几个子元素:index 下标从0开始
  • 是否接受点击事件:clickable true
  • 位置:bounds [32,82][119,169]

uiautomator dump

dump命令

dump: creates an XML dump of current UI hierarchy
    dump [--verbose][file]
      [--compressed]: dumps compressed layout information.
      [file]: the location where the dumped XML should be stored, default is
      /sdcard/window_dump.xml

相关命令

  519  adb shell uiautomator
  520  adb shell uiautomator dump
  521  adb shell cat /sdcard/window_dump.xml
  522  adb shell uiautomator dump --compressed /sdcard/window_dump2.xml
  523  adb shell cat /sdcard/window_dump2.xml
  524  adb shell ls  /sdcard/window_dump2.xml
  525  adb shell "ls -l  /sdcard/*.xml"

dump结果

<?xml version='1.0' encoding='UTF-8' standalone='yes' ?><hierarchy rotation="0"><node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1080,1794]"><node NAF="true" index="0" text="" resource-id="com.xueqiu.android:id/sky_container" class="android.widget.RelativeLayout" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,100][1080,625]"><node NAF="true" index="0" text="" resource-id="com.xueqiu.android:id/iv_action_back" class="android.widget.ImageView" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,100][127,190]" /></node><node index="1" text="" resource-id="" class="android.widget.RelativeLayout" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[32,625][1048,741]"><node index="0" text="" resource-id="com.xueqiu.android:id/register_number_start" class="android.widget.LinearLayout" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[32,625][190,741]"><node index="0" text="+86" resource-id="com.xueqiu.android:id/register_number_start_text" class="android.widget.TextView" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[32,625][98,741]" /></node><node index="1" text="请输入手机号" resource-id="com.xueqiu.android:id/register_phone_number" class="android.widget.EditText" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="true" scrollable="false" long-clickable="true" password="false" selected="false" bounds="[190,625][1048,741]" /><node index="2" text="发送验证码" resource-id="com.xueqiu.android:id/register_code_text" class="android.widget.TextView" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[794,652][1048,714]" /></node><node index="2" text="验证码" resource-id="" class="android.widget.TextView" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[32,771][190,828]" /><node index="3" text="请输入四位验证码" resource-id="com.xueqiu.android:id/register_code" class="android.widget.EditText" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="true" password="false" selected="false" bounds="[190,742][1016,858]" /><node index="4" text="登录" resource-id="com.xueqiu.android:id/button_next" class="android.widget.TextView" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[32,964][1048,1064]" /><node index="5" text="邮箱手机号密码登录" resource-id="com.xueqiu.android:id/tv_login_with_account" class="android.widget.TextView" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[32,1114][1048,1168]" /><node index="6" text="第三方登录" resource-id="" class="android.widget.TextView" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[460,1541][620,1584]" /><node NAF="true" index="7" text="" resource-id="com.xueqiu.android:id/weixin_login" class="android.widget.ImageView" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[126,1623][231,1728]" /><node NAF="true" index="8" text="" resource-id="com.xueqiu.android:id/sina_login" class="android.widget.ImageView" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[487,1623][592,1728]" /><node NAF="true" index="9" text="" resource-id="com.xueqiu.android:id/tencent_login" class="android.widget.ImageView" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[849,1623][954,1728]" /></node></hierarchy>

格式化

<?xml version="1.0" encoding="UTF-8"?>
<hierarchy rotation="0">
   <node index="0" text="" resource-id="" class="android.widget.FrameLayout" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,0][1080,1794]">
      <node NAF="true" index="0" text="" resource-id="com.xueqiu.android:id/sky_container" class="android.widget.RelativeLayout" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,100][1080,625]">
         <node NAF="true" index="0" text="" resource-id="com.xueqiu.android:id/iv_action_back" class="android.widget.ImageView" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[0,100][127,190]" />
      </node>
      <node index="1" text="" resource-id="" class="android.widget.RelativeLayout" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[32,625][1048,741]">
         <node index="0" text="" resource-id="com.xueqiu.android:id/register_number_start" class="android.widget.LinearLayout" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[32,625][190,741]">
            <node index="0" text="+86" resource-id="com.xueqiu.android:id/register_number_start_text" class="android.widget.TextView" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[32,625][98,741]" />
         </node>
         <node index="1" text="请输入手机号" resource-id="com.xueqiu.android:id/register_phone_number" class="android.widget.EditText" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="true" scrollable="false" long-clickable="true" password="false" selected="false" bounds="[190,625][1048,741]" />
         <node index="2" text="发送验证码" resource-id="com.xueqiu.android:id/register_code_text" class="android.widget.TextView" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[794,652][1048,714]" />
      </node>
      <node index="2" text="验证码" resource-id="" class="android.widget.TextView" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[32,771][190,828]" />
      <node index="3" text="请输入四位验证码" resource-id="com.xueqiu.android:id/register_code" class="android.widget.EditText" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="true" password="false" selected="false" bounds="[190,742][1016,858]" />
      <node index="4" text="登录" resource-id="com.xueqiu.android:id/button_next" class="android.widget.TextView" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[32,964][1048,1064]" />
      <node index="5" text="邮箱手机号密码登录" resource-id="com.xueqiu.android:id/tv_login_with_account" class="android.widget.TextView" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[32,1114][1048,1168]" />
      <node index="6" text="第三方登录" resource-id="" class="android.widget.TextView" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="false" enabled="true" focusable="false" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[460,1541][620,1584]" />
      <node NAF="true" index="7" text="" resource-id="com.xueqiu.android:id/weixin_login" class="android.widget.ImageView" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[126,1623][231,1728]" />
      <node NAF="true" index="8" text="" resource-id="com.xueqiu.android:id/sina_login" class="android.widget.ImageView" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[487,1623][592,1728]" />
      <node NAF="true" index="9" text="" resource-id="com.xueqiu.android:id/tencent_login" class="android.widget.ImageView" package="com.xueqiu.android" content-desc="" checkable="false" checked="false" clickable="true" enabled="true" focusable="true" focused="false" scrollable="false" long-clickable="false" password="false" selected="false" bounds="[849,1623][954,1728]" />
   </node>
</hierarchy>

自动化命令

adb shell "uiautomator dump --compressed && cat /sdcard/window_dump.xml"
adb shell input tap x y
adb shell input text 1234

手工测试

less /tmp/dump.xml | grep -oE "<node.*?bounds=[^ ]*"
less /tmp/dump.xml | sed 's#<node#^<node#g' | tr ^ '\\n'
less /tmp/dump.xml | sed -e $'s#<node#\\\\\\n<node#g'
```

## \b休息 16:00回来
- uiautomator dump练习
- input 练习
- 练习dump文件的分行 查找 取出定位

## 作业2
打造一个android自动化工具

预期测试用例规范
```
click user_profile
click login_phone 
click 密码登录
send_keys 请输入手机号 15600534700
send_keys 登录密码 123456
click 'text="登录"' 
msg=$(get_attribute text md_content)
echo $msg
#assert
```

实现其中的click send_keys get_attribute三个函数,并把函数定义贴到回复里
- click 第一个参数是定位信息
- send_keys 第一个参数是定位信息 第二个是参数是输入内容
- get_attribute 第一个参数是属性,比如text resource-id等,第二个参数为定位信息


答案
```
page_source(){
  adb shell "uiautomator dump --compressed && cat /sdcard/window_dump.xml"
}
get_node(){
  page_source | sed -e $'s#<node#\\\\\\n<node#g' | grep "$1"
}
get_location(){
  get_attribute bounds "$1" | awk -F '\\\\[|,|\\\\]' '{print $2,$3}'
}
click(){
  adb shell input tap $( get_location "$1" )
}
send_keys(){
  click "$1"
  adb shell input text "$2"
}
get_attribute(){
  get_node "$2" | grep -o "$1"'="[^"]*"' | awk -F\\" '{print $2}'
}
```

## 课后作业
```
inspect(){
#todo: 打印所有的有resource-id或者text不为空的所有控件 坐标,第一列是id 第二列是text的前10个字符 第三列坐标。
#todo:层级

--- resource-id="ssss" text="xxxx"
------ resource-id="ssss" text="xxxx"
------ resource-id="ssss" text="xxxx"
------ resource-id="ssss" text="xxxx"
--- resource-id="ssss" text="xxxx"
}
```
关闭