首页 > 代码库 > android金阳光自动化测试——学习历程:自动化预备知识上&&下

android金阳光自动化测试——学习历程:自动化预备知识上&&下

章节:自动化基础篇——自动化预备知识上&&下

网易云课堂:

上:http://study.163.com/course/courseLearn.htm?courseId=712011#/learn/video?lessonId=877113&courseId=712011

下:http://study.163.com/course/courseLearn.htm?courseId=712011#/learn/video?lessonId=877114&courseId=712011

 

主要讲解内容及笔记:

一、需要具备的能力:

测试一年,编程一年,熟悉并掌握业界自动化测试工具(monkey--压力测试、monkeyrunner--基于坐标点的可用作功能测试和回归测试、robotium、UIAutomator-google2013年推出的基于控件的框架),Python脚本写过自动化

二、希望具备能力:

1、linux命令(上学学过,但是忘记了,需要回顾和使用)

2、会android简单开发(只是停留在超级基础阶段,还需要看教程)

3、会eclipse插件开发(需要查看资料,自我学习)

三、业界自动化框架(需要自学)

1、基于坐标点触屏:monkeyrunner、北京播思自研工具

2、基于随机流的单元测试:CTS(针对android的framework的测试,防止把android架构改的面目全非)、Monkey(命令:adb monkey -p -v)

3、基于元素图形对比:SeeTest(网址:http://experitest.com)、I-Test

4、腾讯Bita(bita.qq.com)和GT(gt.tencent.com,关注性能测试)

5、百度云和ITestIn(http://testin.cn)、阿里巴巴(TMTS)

6、基于控件信息:Robotium+Junit4框架、东舟Smart-Robot、美国风河公司:wind test managerment

7、NativeDriver和Selenium(已经被UIAutomator替代)

四、ADB详解

1、ADB——官网文档(PORT:TCP 5037)

ADB(android debug bridge)即调试桥接,是一种命令行工具,可以与你的模拟器或者是andorid设备进行通讯,包括三部分组成:

(1)是一个客户端,可以运行在你的开发机上

(2)是一个服务器,以后台形式运行在你的开发机上,当一个server启动后,它就会绑定TCP的5037端口并且监听从adb客户端发出的请求——所有的adb客户端都使用这个端口5037来与server进行通信,如果安装了其他如腾讯手机助手啊之类的,把这个端口占用了,就会导致adb不可用,就需要通过kill servers将其杀掉

(3)是一个守护进程,使得每一个模拟器或者设备的实例都能够运行在后台

adb.exe的具体位置:安装程序/sdk/platform-tools,如D:\Program Files\adt-bundle-windows-x86-20130717\sdk\platform-tools

2、测试ADB

adb命令行:

(1)adb devices     #查看设备列表

问题:这里提示unauthorized?为什么?

没有授权,也就是说手机连接电脑后提示的USB调试的授权,点击确定后,就能够被识别,不行就多试几次

但是为什么用手机助手就能够装上呢?他怎么处理的未授权的问题呢?

(2)adb install 拖进来的apk文件    #安装apk文件

如:abd install wifinext.apk,之后会提示安装进度和success,即提示成功了

(3)adb uninstall 已经安装的apk文件    #卸载apk文件

adb uninstall wifinext.apk,之后会提示Failure

原因在于安装后的包名已将改变,变为AndroidMainifest.xml文件中<manifest>节点下,package元素所指定的名字

因此使用:adb uninstall com.qihoo.linker ,之后提示success

(4)adb push 拖进来的一个文件  /data/local/tmp     #将某文件push进一个目录下

作用:可以测试当空间被占满之类的情况下程序的运行情况,如可以拖进来一个很大的程序,关注内存等

(5)adb pull          #与push相对,将文件拉出

如:adb pull  /data/local/tmp/xxx.apk    C://

(6)adb kill-server

(7)adb shell之后出现的$:表示没有被root,是#:表示被root

3、AndroidDebugBridge源码详解

ADB的源码位置:D:\Program Files\adt-bundle-windows-x86-20130717\sdk\tools\lib\ddmlib.jar

就是要包含这个ddmlib.jar,具体如何理解:

http://stackoverflow.com/questions/17381324/how-to-tell-if-android-device-detected-by-adb

这个是在stackoverflow上的一个问答:关于如何才能知道android设备是否连接通过adb?

查看一下androiddebugbridge的源码,能够看到里面有一个createbrige的方法,源代码如下:

能够搜索到有两个createbridge方法,一种是createbridge()方法,该方法会判断是否存在一个adb连接,是则将其返回;

另一种是createbridge(String osLocation, boolean forceNewBridge)

该方法会生成一个新的adb连接,不论原来是否存在

   1 /*   2  * Copyright (C) 2007 The Android Open Source Project   3  *   4  * Licensed under the Apache License, Version 2.0 (the "License");   5  * you may not use this file except in compliance with the License.   6  * You may obtain a copy of the License at   7  *   8  *      http://www.apache.org/licenses/LICENSE-2.0   9  *  10  * Unless required by applicable law or agreed to in writing, software  11  * distributed under the License is distributed on an "AS IS" BASIS,  12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  13  * See the License for the specific language governing permissions and  14  * limitations under the License.  15  */  16   17 package org.athrun.ddmlib;  18   19   20 import java.io.BufferedReader;  21 import java.io.IOException;  22 import java.io.InputStreamReader;  23 import java.lang.Thread.State;  24 import java.net.InetAddress;  25 import java.net.InetSocketAddress;  26 import java.net.UnknownHostException;  27 import java.security.InvalidParameterException;  28 import java.util.ArrayList;  29 import java.util.Map;  30 import java.util.regex.Matcher;  31 import java.util.regex.Pattern;  32   33 import org.athrun.ddmlib.Log.LogLevel;  34   35 /**  36  * A connection to the host-side android debug bridge (adb)  37  * <p/>  38  * This is the central point to communicate with any devices, emulators, or the  39  * applications running on them.  40  * <p/>  41  * <b>{@link #init(boolean)} must be called before anything is done.</b>  42  */  43 public final class AndroidDebugBridge {  44   45     /*  46      * Minimum and maximum version of adb supported. This correspond to  47      * ADB_SERVER_VERSION found in //device/tools/adb/adb.h  48      */  49   50     private final static int ADB_VERSION_MICRO_MIN = 20;  51     private final static int ADB_VERSION_MICRO_MAX = -1;  52   53     private final static Pattern sAdbVersion = Pattern  54             .compile("^.*(\\d+)\\.(\\d+)\\.(\\d+)$"); //$NON-NLS-1$  55   56     private final static String ADB = "adb"; //$NON-NLS-1$  57     private final static String DDMS = "ddms"; //$NON-NLS-1$  58     private final static String SERVER_PORT_ENV_VAR = "ANDROID_ADB_SERVER_PORT"; //$NON-NLS-1$  59   60     // Where to find the ADB bridge.  61     final static String ADB_HOST = "127.0.0.1"; //$NON-NLS-1$  62     final static int ADB_PORT = 5037;  63   64     private static InetAddress sHostAddr;  65     private static InetSocketAddress sSocketAddr;  66   67     private static AndroidDebugBridge sThis;  68     private static boolean sInitialized = false;  69     private static boolean sClientSupport;  70   71     /** Full path to adb. */  72     private String mAdbOsLocation = null;  73   74     private boolean mVersionCheck;  75   76     private boolean mStarted = false;  77   78     private DeviceMonitor mDeviceMonitor;  79   80     private final static ArrayList<IDebugBridgeChangeListener> sBridgeListeners = new ArrayList<IDebugBridgeChangeListener>();  81     private final static ArrayList<IDeviceChangeListener> sDeviceListeners = new ArrayList<IDeviceChangeListener>();  82     private final static ArrayList<IClientChangeListener> sClientListeners = new ArrayList<IClientChangeListener>();  83   84     // lock object for synchronization  85     private static final Object sLock = sBridgeListeners;  86   87     /**  88      * Classes which implement this interface provide a method that deals with  89      * {@link AndroidDebugBridge} changes.  90      */  91     public interface IDebugBridgeChangeListener {  92         /**  93          * Sent when a new {@link AndroidDebugBridge} is connected.  94          * <p/>  95          * This is sent from a non UI thread.  96          *   97          * @param bridge  98          *            the new {@link AndroidDebugBridge} object.  99          */ 100         public void bridgeChanged(AndroidDebugBridge bridge); 101     } 102  103     /** 104      * Classes which implement this interface provide methods that deal with 105      * {@link IDevice} addition, deletion, and changes. 106      */ 107     public interface IDeviceChangeListener { 108         /** 109          * Sent when the a device is connected to the {@link AndroidDebugBridge} 110          * . 111          * <p/> 112          * This is sent from a non UI thread. 113          *  114          * @param device 115          *            the new device. 116          */ 117         public void deviceConnected(IDevice device); 118  119         /** 120          * Sent when the a device is connected to the {@link AndroidDebugBridge} 121          * . 122          * <p/> 123          * This is sent from a non UI thread. 124          *  125          * @param device 126          *            the new device. 127          */ 128         public void deviceDisconnected(IDevice device); 129  130         /** 131          * Sent when a device data changed, or when clients are 132          * started/terminated on the device. 133          * <p/> 134          * This is sent from a non UI thread. 135          *  136          * @param device 137          *            the device that was updated. 138          * @param changeMask 139          *            the mask describing what changed. It can contain any of 140          *            the following values: {@link IDevice#CHANGE_BUILD_INFO}, 141          *            {@link IDevice#CHANGE_STATE}, 142          *            {@link IDevice#CHANGE_CLIENT_LIST} 143          */ 144         public void deviceChanged(IDevice device, int changeMask); 145     } 146  147     /** 148      * Classes which implement this interface provide methods that deal with 149      * {@link Client} changes. 150      */ 151     public interface IClientChangeListener { 152         /** 153          * Sent when an existing client information changed. 154          * <p/> 155          * This is sent from a non UI thread. 156          *  157          * @param client 158          *            the updated client. 159          * @param changeMask 160          *            the bit mask describing the changed properties. It can 161          *            contain any of the following values: 162          *            {@link Client#CHANGE_INFO}, 163          *            {@link Client#CHANGE_DEBUGGER_STATUS}, 164          *            {@link Client#CHANGE_THREAD_MODE}, 165          *            {@link Client#CHANGE_THREAD_DATA}, 166          *            {@link Client#CHANGE_HEAP_MODE}, 167          *            {@link Client#CHANGE_HEAP_DATA}, 168          *            {@link Client#CHANGE_NATIVE_HEAP_DATA} 169          */ 170         public void clientChanged(Client client, int changeMask); 171     } 172  173     /** 174      * Initializes the <code>ddm</code> library. 175      * <p/> 176      * This must be called once <b>before</b> any call to 177      * {@link #createBridge(String, boolean)}. 178      * <p> 179      * The library can be initialized in 2 ways: 180      * <ul> 181      * <li>Mode 1: <var>clientSupport</var> == <code>true</code>.<br> 182      * The library monitors the devices and the applications running on them. It 183      * will connect to each application, as a debugger of sort, to be able to 184      * interact with them through JDWP packets.</li> 185      * <li>Mode 2: <var>clientSupport</var> == <code>false</code>.<br> 186      * The library only monitors devices. The applications are left untouched, 187      * letting other tools built on <code>ddmlib</code> to connect a debugger to 188      * them.</li> 189      * </ul> 190      * <p/> 191      * <b>Only one tool can run in mode 1 at the same time.</b> 192      * <p/> 193      * Note that mode 1 does not prevent debugging of applications running on 194      * devices. Mode 1 lets debuggers connect to <code>ddmlib</code> which acts 195      * as a proxy between the debuggers and the applications to debug. See 196      * {@link Client#getDebuggerListenPort()}. 197      * <p/> 198      * The preferences of <code>ddmlib</code> should also be initialized with 199      * whatever default values were changed from the default values. 200      * <p/> 201      * When the application quits, {@link #terminate()} should be called. 202      *  203      * @param clientSupport 204      *            Indicates whether the library should enable the monitoring and 205      *            interaction with applications running on the devices. 206      * @see AndroidDebugBridge#createBridge(String, boolean) 207      * @see DdmPreferences 208      */ 209     public static synchronized void init(boolean clientSupport) { 210         if (sInitialized) { 211             throw new IllegalStateException( 212                     "AndroidDebugBridge.init() has already been called."); 213         } 214         sInitialized = true; 215         sClientSupport = clientSupport; 216  217         // Determine port and instantiate socket address. 218         initAdbSocketAddr(); 219  220         MonitorThread monitorThread = MonitorThread.createInstance(); 221         monitorThread.start(); 222  223         HandleHello.register(monitorThread); 224         HandleAppName.register(monitorThread); 225         HandleTest.register(monitorThread); 226         HandleThread.register(monitorThread); 227         HandleHeap.register(monitorThread); 228         HandleWait.register(monitorThread); 229         HandleProfiling.register(monitorThread); 230         HandleNativeHeap.register(monitorThread); 231     } 232  233     /** 234      * Terminates the ddm library. This must be called upon application 235      * termination. 236      */ 237     public static synchronized void terminate() { 238         // kill the monitoring services 239         if (sThis != null && sThis.mDeviceMonitor != null) { 240             sThis.mDeviceMonitor.stop(); 241             sThis.mDeviceMonitor = null; 242         } 243  244         MonitorThread monitorThread = MonitorThread.getInstance(); 245         if (monitorThread != null) { 246             monitorThread.quit(); 247         } 248  249         sInitialized = false; 250     } 251  252     /** 253      * Returns whether the ddmlib is setup to support monitoring and interacting 254      * with {@link Client}s running on the {@link IDevice}s. 255      */ 256     static boolean getClientSupport() { 257         return sClientSupport; 258     } 259  260     /** 261      * Returns the socket address of the ADB server on the host. 262      */ 263     public static InetSocketAddress getSocketAddress() { 264         return sSocketAddr; 265     } 266  267     /** 268      * Creates a {@link AndroidDebugBridge} that is not linked to any particular 269      * executable. 270      * <p/> 271      * This bridge will expect adb to be running. It will not be able to 272      * start/stop/restart adb. 273      * <p/> 274      * If a bridge has already been started, it is directly returned with no 275      * changes (similar to calling {@link #getBridge()}). 276      *  277      * @return a connected bridge. 278      */ 279     public static AndroidDebugBridge createBridge() { 280         synchronized (sLock) { 281             if (sThis != null) { 282                 return sThis; 283             } 284  285             try { 286                 sThis = new AndroidDebugBridge(); 287                 sThis.start(); 288             } catch (InvalidParameterException e) { 289                 sThis = null; 290             } 291  292             // because the listeners could remove themselves from the list while 293             // processing 294             // their event callback, we make a copy of the list and iterate on 295             // it instead of 296             // the main list. 297             // This mostly happens when the application quits. 298             IDebugBridgeChangeListener[] listenersCopy = sBridgeListeners 299                     .toArray(new IDebugBridgeChangeListener[sBridgeListeners 300                             .size()]); 301  302             // notify the listeners of the change 303             for (IDebugBridgeChangeListener listener : listenersCopy) { 304                 // we attempt to catch any exception so that a bad listener 305                 // doesn‘t kill our 306                 // thread 307                 try { 308                     listener.bridgeChanged(sThis); 309                 } catch (Exception e) { 310                     Log.e(DDMS, e); 311                 } 312             } 313  314             return sThis; 315         } 316     } 317  318     /** 319      * Creates a new debug bridge from the location of the command line tool. 320      * <p/> 321      * Any existing server will be disconnected, unless the location is the same 322      * and <code>forceNewBridge</code> is set to false. 323      *  324      * @param osLocation 325      *            the location of the command line tool ‘adb‘ 326      * @param forceNewBridge 327      *            force creation of a new bridge even if one with the same 328      *            location already exists. 329      * @return a connected bridge. 330      */ 331     public static AndroidDebugBridge createBridge(String osLocation, 332             boolean forceNewBridge) { 333         synchronized (sLock) { 334             if (sThis != null) { 335                 if (sThis.mAdbOsLocation != null 336                         && sThis.mAdbOsLocation.equals(osLocation) 337                         && forceNewBridge == false) { 338                     return sThis; 339                 } else { 340                     // stop the current server 341                     sThis.stop(); 342                 } 343             } 344  345             try { 346                 sThis = new AndroidDebugBridge(osLocation); 347                 sThis.start(); 348             } catch (InvalidParameterException e) { 349                 sThis = null; 350             } 351  352             // because the listeners could remove themselves from the list while 353             // processing 354             // their event callback, we make a copy of the list and iterate on 355             // it instead of 356             // the main list. 357             // This mostly happens when the application quits. 358             IDebugBridgeChangeListener[] listenersCopy = sBridgeListeners 359                     .toArray(new IDebugBridgeChangeListener[sBridgeListeners 360                             .size()]); 361  362             // notify the listeners of the change 363             for (IDebugBridgeChangeListener listener : listenersCopy) { 364                 // we attempt to catch any exception so that a bad listener 365                 // doesn‘t kill our 366                 // thread 367                 try { 368                     listener.bridgeChanged(sThis); 369                 } catch (Exception e) { 370                     Log.e(DDMS, e); 371                 } 372             } 373  374             return sThis; 375         } 376     } 377  378     /** 379      * Returns the current debug bridge. Can be <code>null</code> if none were 380      * created. 381      */ 382     public static AndroidDebugBridge getBridge() { 383         return sThis; 384     } 385  386     /** 387      * Disconnects the current debug bridge, and destroy the object. 388      * <p/> 389      * This also stops the current adb host server. 390      * <p/> 391      * A new object will have to be created with 392      * {@link #createBridge(String, boolean)}. 393      */ 394     public static void disconnectBridge() { 395         synchronized (sLock) { 396             if (sThis != null) { 397                 sThis.stop(); 398                 sThis = null; 399  400                 // because the listeners could remove themselves from the list 401                 // while processing 402                 // their event callback, we make a copy of the list and iterate 403                 // on it instead of 404                 // the main list. 405                 // This mostly happens when the application quits. 406                 IDebugBridgeChangeListener[] listenersCopy = sBridgeListeners 407                         .toArray(new IDebugBridgeChangeListener[sBridgeListeners 408                                 .size()]); 409  410                 // notify the listeners. 411                 for (IDebugBridgeChangeListener listener : listenersCopy) { 412                     // we attempt to catch any exception so that a bad listener 413                     // doesn‘t kill our 414                     // thread 415                     try { 416                         listener.bridgeChanged(sThis); 417                     } catch (Exception e) { 418                         Log.e(DDMS, e); 419                     } 420                 } 421             } 422         } 423     } 424  425     /** 426      * Adds the listener to the collection of listeners who will be notified 427      * when a new {@link AndroidDebugBridge} is connected, by sending it one of 428      * the messages defined in the {@link IDebugBridgeChangeListener} interface. 429      *  430      * @param listener 431      *            The listener which should be notified. 432      */ 433     public static void addDebugBridgeChangeListener( 434             IDebugBridgeChangeListener listener) { 435         synchronized (sLock) { 436             if (sBridgeListeners.contains(listener) == false) { 437                 sBridgeListeners.add(listener); 438                 if (sThis != null) { 439                     // we attempt to catch any exception so that a bad listener 440                     // doesn‘t kill our 441                     // thread 442                     try { 443                         listener.bridgeChanged(sThis); 444                     } catch (Exception e) { 445                         Log.e(DDMS, e); 446                     } 447                 } 448             } 449         } 450     } 451  452     /** 453      * Removes the listener from the collection of listeners who will be 454      * notified when a new {@link AndroidDebugBridge} is started. 455      *  456      * @param listener 457      *            The listener which should no longer be notified. 458      */ 459     public static void removeDebugBridgeChangeListener( 460             IDebugBridgeChangeListener listener) { 461         synchronized (sLock) { 462             sBridgeListeners.remove(listener); 463         } 464     } 465  466     /** 467      * Adds the listener to the collection of listeners who will be notified 468      * when a {@link IDevice} is connected, disconnected, or when its properties 469      * or its {@link Client} list changed, by sending it one of the messages 470      * defined in the {@link IDeviceChangeListener} interface. 471      *  472      * @param listener 473      *            The listener which should be notified. 474      */ 475     public static void addDeviceChangeListener(IDeviceChangeListener listener) { 476         synchronized (sLock) { 477             if (sDeviceListeners.contains(listener) == false) { 478                 sDeviceListeners.add(listener); 479             } 480         } 481     } 482  483     /** 484      * Removes the listener from the collection of listeners who will be 485      * notified when a {@link IDevice} is connected, disconnected, or when its 486      * properties or its {@link Client} list changed. 487      *  488      * @param listener 489      *            The listener which should no longer be notified. 490      */ 491     public static void removeDeviceChangeListener(IDeviceChangeListener listener) { 492         synchronized (sLock) { 493             sDeviceListeners.remove(listener); 494         } 495     } 496  497     /** 498      * Adds the listener to the collection of listeners who will be notified 499      * when a {@link Client} property changed, by sending it one of the messages 500      * defined in the {@link IClientChangeListener} interface. 501      *  502      * @param listener 503      *            The listener which should be notified. 504      */ 505     public static void addClientChangeListener(IClientChangeListener listener) { 506         synchronized (sLock) { 507             if (sClientListeners.contains(listener) == false) { 508                 sClientListeners.add(listener); 509             } 510         } 511     } 512  513     /** 514      * Removes the listener from the collection of listeners who will be 515      * notified when a {@link Client} property changed. 516      *  517      * @param listener 518      *            The listener which should no longer be notified. 519      */ 520     public static void removeClientChangeListener(IClientChangeListener listener) { 521         synchronized (sLock) { 522             sClientListeners.remove(listener); 523         } 524     } 525  526     /** 527      * Returns the devices. 528      *  529      * @see #hasInitialDeviceList() 530      */ 531     public IDevice[] getDevices() { 532         synchronized (sLock) { 533             if (mDeviceMonitor != null) { 534                 return mDeviceMonitor.getDevices(); 535             } 536         } 537  538         return new IDevice[0]; 539     } 540  541     /** 542      * Returns whether the bridge has acquired the initial list from adb after 543      * being created. 544      * <p/> 545      * Calling {@link #getDevices()} right after 546      * {@link #createBridge(String, boolean)} will generally result in an empty 547      * list. This is due to the internal asynchronous communication mechanism 548      * with <code>adb</code> that does not guarantee that the {@link IDevice} 549      * list has been built before the call to {@link #getDevices()}. 550      * <p/> 551      * The recommended way to get the list of {@link IDevice} objects is to 552      * create a {@link IDeviceChangeListener} object. 553      */ 554     public boolean hasInitialDeviceList() { 555         if (mDeviceMonitor != null) { 556             return mDeviceMonitor.hasInitialDeviceList(); 557         } 558  559         return false; 560     } 561  562     /** 563      * Sets the client to accept debugger connection on the custom 564      * "Selected debug port". 565      *  566      * @param selectedClient 567      *            the client. Can be null. 568      */ 569     public void setSelectedClient(Client selectedClient) { 570         MonitorThread monitorThread = MonitorThread.getInstance(); 571         if (monitorThread != null) { 572             monitorThread.setSelectedClient(selectedClient); 573         } 574     } 575  576     /** 577      * Returns whether the {@link AndroidDebugBridge} object is still connected 578      * to the adb daemon. 579      */ 580     public boolean isConnected() { 581         MonitorThread monitorThread = MonitorThread.getInstance(); 582         if (mDeviceMonitor != null && monitorThread != null) { 583             return mDeviceMonitor.isMonitoring() 584                     && monitorThread.getState() != State.TERMINATED; 585         } 586         return false; 587     } 588  589     /** 590      * Returns the number of times the {@link AndroidDebugBridge} object 591      * attempted to connect to the adb daemon. 592      */ 593     public int getConnectionAttemptCount() { 594         if (mDeviceMonitor != null) { 595             return mDeviceMonitor.getConnectionAttemptCount(); 596         } 597         return -1; 598     } 599  600     /** 601      * Returns the number of times the {@link AndroidDebugBridge} object 602      * attempted to restart the adb daemon. 603      */ 604     public int getRestartAttemptCount() { 605         if (mDeviceMonitor != null) { 606             return mDeviceMonitor.getRestartAttemptCount(); 607         } 608         return -1; 609     } 610  611     /** 612      * Creates a new bridge. 613      *  614      * @param osLocation 615      *            the location of the command line tool 616      * @throws InvalidParameterException 617      */ 618     private AndroidDebugBridge(String osLocation) 619             throws InvalidParameterException { 620         if (osLocation == null || osLocation.length() == 0) { 621             throw new InvalidParameterException(); 622         } 623         mAdbOsLocation = osLocation; 624  625         checkAdbVersion(); 626     } 627  628     /** 629      * Creates a new bridge not linked to any particular adb executable. 630      */ 631     private AndroidDebugBridge() { 632     } 633  634     /** 635      * Queries adb for its version number and checks it against 636      * {@link #MIN_VERSION_NUMBER} and {@link #MAX_VERSION_NUMBER} 637      */ 638     private void checkAdbVersion() { 639         // default is bad check 640         mVersionCheck = false; 641  642         if (mAdbOsLocation == null) { 643             return; 644         } 645  646         try { 647             String[] command = new String[2]; 648             command[0] = mAdbOsLocation; 649             command[1] = "version"; //$NON-NLS-1$ 650             Log.d(DDMS, 651                     String.format("Checking ‘%1$s version‘", mAdbOsLocation)); //$NON-NLS-1$ 652             Process process = Runtime.getRuntime().exec(command); 653  654             ArrayList<String> errorOutput = new ArrayList<String>(); 655             ArrayList<String> stdOutput = new ArrayList<String>(); 656             int status = grabProcessOutput(process, errorOutput, stdOutput, 657                     true /* waitForReaders */); 658  659             if (status != 0) { 660                 StringBuilder builder = new StringBuilder( 661                         "‘adb version‘ failed!"); //$NON-NLS-1$ 662                 for (String error : errorOutput) { 663                     builder.append(‘\n‘); 664                     builder.append(error); 665                 } 666                 Log.logAndDisplay(LogLevel.ERROR, "adb", builder.toString()); 667             } 668  669             // check both stdout and stderr 670             boolean versionFound = false; 671             for (String line : stdOutput) { 672                 versionFound = scanVersionLine(line); 673                 if (versionFound) { 674                     break; 675                 } 676             } 677             if (!versionFound) { 678                 for (String line : errorOutput) { 679                     versionFound = scanVersionLine(line); 680                     if (versionFound) { 681                         break; 682                     } 683                 } 684             } 685  686             if (!versionFound) { 687                 // if we get here, we failed to parse the output. 688                 Log.logAndDisplay(LogLevel.ERROR, ADB, 689                         "Failed to parse the output of ‘adb version‘"); //$NON-NLS-1$ 690             } 691  692         } catch (IOException e) { 693             Log.logAndDisplay(LogLevel.ERROR, ADB, 694                     "Failed to get the adb version: " + e.getMessage()); //$NON-NLS-1$ 695         } catch (InterruptedException e) { 696         } finally { 697  698         } 699     } 700  701     /** 702      * Scans a line resulting from ‘adb version‘ for a potential version number. 703      * <p/> 704      * If a version number is found, it checks the version number against what 705      * is expected by this version of ddms. 706      * <p/> 707      * Returns true when a version number has been found so that we can stop 708      * scanning, whether the version number is in the acceptable range or not. 709      *  710      * @param line 711      *            The line to scan. 712      * @return True if a version number was found (whether it is acceptable or 713      *         not). 714      */ 715     @SuppressWarnings("all") 716     // With Eclipse 3.6, replace by @SuppressWarnings("unused") 717     private boolean scanVersionLine(String line) { 718         if (line != null) { 719             Matcher matcher = sAdbVersion.matcher(line); 720             if (matcher.matches()) { 721                 int majorVersion = Integer.parseInt(matcher.group(1)); 722                 int minorVersion = Integer.parseInt(matcher.group(2)); 723                 int microVersion = Integer.parseInt(matcher.group(3)); 724  725                 // check only the micro version for now. 726                 if (microVersion < ADB_VERSION_MICRO_MIN) { 727                     String message = String.format( 728                             "Required minimum version of adb: %1$d.%2$d.%3$d." //$NON-NLS-1$ 729                                     + "Current version is %1$d.%2$d.%4$d", //$NON-NLS-1$ 730                             majorVersion, minorVersion, ADB_VERSION_MICRO_MIN, 731                             microVersion); 732                     Log.logAndDisplay(LogLevel.ERROR, ADB, message); 733                 } else if (ADB_VERSION_MICRO_MAX != -1 734                         && microVersion > ADB_VERSION_MICRO_MAX) { 735                     String message = String.format( 736                             "Required maximum version of adb: %1$d.%2$d.%3$d." //$NON-NLS-1$ 737                                     + "Current version is %1$d.%2$d.%4$d", //$NON-NLS-1$ 738                             majorVersion, minorVersion, ADB_VERSION_MICRO_MAX, 739                             microVersion); 740                     Log.logAndDisplay(LogLevel.ERROR, ADB, message); 741                 } else { 742                     mVersionCheck = true; 743                 } 744  745                 return true; 746             } 747         } 748         return false; 749     } 750  751     /** 752      * Starts the debug bridge. 753      *  754      * @return true if success. 755      */ 756     boolean start() { 757         if (mAdbOsLocation != null 758                 && (mVersionCheck == false || startAdb() == false)) { 759             return false; 760         } 761  762         mStarted = true; 763  764         // now that the bridge is connected, we start the underlying services. 765         mDeviceMonitor = new DeviceMonitor(this); 766         mDeviceMonitor.start(); 767  768         return true; 769     } 770  771     /** 772      * Kills the debug bridge, and the adb host server. 773      *  774      * @return true if success 775      */ 776     boolean stop() { 777         // if we haven‘t started we return false; 778         if (mStarted == false) { 779             return false; 780         } 781  782         // kill the monitoring services 783         mDeviceMonitor.stop(); 784         mDeviceMonitor = null; 785  786         if (stopAdb() == false) { 787             return false; 788         } 789  790         mStarted = false; 791         return true; 792     } 793  794     /** 795      * Restarts adb, but not the services around it. 796      *  797      * @return true if success. 798      */ 799     public boolean restart() { 800         if (mAdbOsLocation == null) { 801             Log.e(ADB, 802                     "Cannot restart adb when AndroidDebugBridge is created without the location of adb."); //$NON-NLS-1$ 803             return false; 804         } 805  806         if (mVersionCheck == false) { 807             Log.logAndDisplay(LogLevel.ERROR, ADB, 808                     "Attempting to restart adb, but version check failed!"); //$NON-NLS-1$ 809             return false; 810         } 811         synchronized (this) { 812             stopAdb(); 813  814             boolean restart = startAdb(); 815  816             if (restart && mDeviceMonitor == null) { 817                 mDeviceMonitor = new DeviceMonitor(this); 818                 mDeviceMonitor.start(); 819             } 820  821             return restart; 822         } 823     } 824  825     /** 826      * Notify the listener of a new {@link IDevice}. 827      * <p/> 828      * The notification of the listeners is done in a synchronized block. It is 829      * important to expect the listeners to potentially access various methods 830      * of {@link IDevice} as well as {@link #getDevices()} which use internal 831      * locks. 832      * <p/> 833      * For this reason, any call to this method from a method of 834      * {@link DeviceMonitor}, {@link IDevice} which is also inside a 835      * synchronized block, should first synchronize on the 836      * {@link AndroidDebugBridge} lock. Access to this lock is done through 837      * {@link #getLock()}. 838      *  839      * @param device 840      *            the new <code>IDevice</code>. 841      * @see #getLock() 842      */ 843     void deviceConnected(IDevice device) { 844         // because the listeners could remove themselves from the list while 845         // processing 846         // their event callback, we make a copy of the list and iterate on it 847         // instead of 848         // the main list. 849         // This mostly happens when the application quits. 850         IDeviceChangeListener[] listenersCopy = null; 851         synchronized (sLock) { 852             listenersCopy = sDeviceListeners 853                     .toArray(new IDeviceChangeListener[sDeviceListeners.size()]); 854         } 855  856         // Notify the listeners 857         for (IDeviceChangeListener listener : listenersCopy) { 858             // we attempt to catch any exception so that a bad listener doesn‘t 859             // kill our 860             // thread 861             try { 862                 listener.deviceConnected(device); 863             } catch (Exception e) { 864                 Log.e(DDMS, e); 865             } 866         } 867     } 868  869     /** 870      * Notify the listener of a disconnected {@link IDevice}. 871      * <p/> 872      * The notification of the listeners is done in a synchronized block. It is 873      * important to expect the listeners to potentially access various methods 874      * of {@link IDevice} as well as {@link #getDevices()} which use internal 875      * locks. 876      * <p/> 877      * For this reason, any call to this method from a method of 878      * {@link DeviceMonitor}, {@link IDevice} which is also inside a 879      * synchronized block, should first synchronize on the 880      * {@link AndroidDebugBridge} lock. Access to this lock is done through 881      * {@link #getLock()}. 882      *  883      * @param device 884      *            the disconnected <code>IDevice</code>. 885      * @see #getLock() 886      */ 887     void deviceDisconnected(IDevice device) { 888         // because the listeners could remove themselves from the list while 889         // processing 890         // their event callback, we make a copy of the list and iterate on it 891         // instead of 892         // the main list. 893         // This mostly happens when the application quits. 894         IDeviceChangeListener[] listenersCopy = null; 895         synchronized (sLock) { 896             listenersCopy = sDeviceListeners 897                     .toArray(new IDeviceChangeListener[sDeviceListeners.size()]); 898         } 899  900         // Notify the listeners 901         for (IDeviceChangeListener listener : listenersCopy) { 902             // we attempt to catch any exception so that a bad listener doesn‘t 903             // kill our 904             // thread 905             try { 906                 listener.deviceDisconnected(device); 907             } catch (Exception e) { 908                 Log.e(DDMS, e); 909             } 910         } 911     } 912  913     /** 914      * Notify the listener of a modified {@link IDevice}. 915      * <p/> 916      * The notification of the listeners is done in a synchronized block. It is 917      * important to expect the listeners to potentially access various methods 918      * of {@link IDevice} as well as {@link #getDevices()} which use internal 919      * locks. 920      * <p/> 921      * For this reason, any call to this method from a method of 922      * {@link DeviceMonitor}, {@link IDevice} which is also inside a 923      * synchronized block, should first synchronize on the 924      * {@link AndroidDebugBridge} lock. Access to this lock is done through 925      * {@link #getLock()}. 926      *  927      * @param device 928      *            the modified <code>IDevice</code>. 929      * @see #getLock() 930      */ 931     void deviceChanged(IDevice device, int changeMask) { 932         // because the listeners could remove themselves from the list while 933         // processing 934         // their event callback, we make a copy of the list and iterate on it 935         // instead of 936         // the main list. 937         // This mostly happens when the application quits. 938         IDeviceChangeListener[] listenersCopy = null; 939         synchronized (sLock) { 940             listenersCopy = sDeviceListeners 941                     .toArray(new IDeviceChangeListener[sDeviceListeners.size()]); 942         } 943  944         // Notify the listeners 945         for (IDeviceChangeListener listener : listenersCopy) { 946             // we attempt to catch any exception so that a bad listener doesn‘t 947             // kill our 948             // thread 949             try { 950                 listener.deviceChanged(device, changeMask); 951             } catch (Exception e) { 952                 Log.e(DDMS, e); 953             } 954         } 955     } 956  957     /** 958      * Notify the listener of a modified {@link Client}. 959      * <p/> 960      * The notification of the listeners is done in a synchronized block. It is 961      * important to expect the listeners to potentially access various methods 962      * of {@link IDevice} as well as {@link #getDevices()} which use internal 963      * locks. 964      * <p/> 965      * For this reason, any call to this method from a method of 966      * {@link DeviceMonitor}, {@link IDevice} which is also inside a 967      * synchronized block, should first synchronize on the 968      * {@link AndroidDebugBridge} lock. Access to this lock is done through 969      * {@link #getLock()}. 970      *  971      * @param device 972      *            the modified <code>Client</code>. 973      * @param changeMask 974      *            the mask indicating what changed in the <code>Client</code> 975      * @see #getLock() 976      */ 977     void clientChanged(Client client, int changeMask) { 978         // because the listeners could remove themselves from the list while 979         // processing 980         // their event callback, we make a copy of the list and iterate on it 981         // instead of 982         // the main list. 983         // This mostly happens when the application quits. 984         IClientChangeListener[] listenersCopy = null; 985         synchronized (sLock) { 986             listenersCopy = sClientListeners 987                     .toArray(new IClientChangeListener[sClientListeners.size()]); 988  989         } 990  991         // Notify the listeners 992         for (IClientChangeListener listener : listenersCopy) { 993             // we attempt to catch any exception so that a bad listener doesn‘t 994             // kill our 995             // thread 996             try { 997                 listener.clientChanged(client, changeMask); 998             } catch (Exception e) { 999                 Log.e(DDMS, e);1000             }1001         }1002     }1003 1004     /**1005      * Returns the {@link DeviceMonitor} object.1006      */1007     DeviceMonitor getDeviceMonitor() {1008         return mDeviceMonitor;1009     }1010 1011     /**1012      * Starts the adb host side server.1013      * 1014      * @return true if success1015      */1016     synchronized boolean startAdb() {1017         if (mAdbOsLocation == null) {1018             Log.e(ADB,1019                     "Cannot start adb when AndroidDebugBridge is created without the location of adb."); //$NON-NLS-1$1020             return false;1021         }1022 1023         Process proc;1024         int status = -1;1025 1026         try {1027             String[] command = new String[2];1028             command[0] = mAdbOsLocation;1029             command[1] = "start-server"; //$NON-NLS-1$1030             Log.d(DDMS, String.format(1031                     "Launching ‘%1$s %2$s‘ to ensure ADB is running.", //$NON-NLS-1$1032                     mAdbOsLocation, command[1]));1033             ProcessBuilder processBuilder = new ProcessBuilder(command);1034             if (DdmPreferences.getUseAdbHost()) {1035                 String adbHostValue =http://www.mamicode.com/ DdmPreferences.getAdbHostValue();1036                 if (adbHostValue != null && adbHostValue.length() > 0) {1037                     // TODO : check that the String is a valid IP address1038                     Map<String, String> env = processBuilder.environment();1039                     env.put("ADBHOST", adbHostValue);1040                 }1041             }1042             proc = processBuilder.start();1043 1044             ArrayList<String> errorOutput = new ArrayList<String>();1045             ArrayList<String> stdOutput = new ArrayList<String>();1046             status = grabProcessOutput(proc, errorOutput, stdOutput, false /* waitForReaders */);1047 1048         } catch (IOException ioe) {1049             Log.d(DDMS, "Unable to run ‘adb‘: " + ioe.getMessage()); //$NON-NLS-1$1050             // we‘ll return false;1051         } catch (InterruptedException ie) {1052             Log.d(DDMS, "Unable to run ‘adb‘: " + ie.getMessage()); //$NON-NLS-1$1053             // we‘ll return false;1054         }1055 1056         if (status != 0) {1057             Log.w(DDMS,1058                     "‘adb start-server‘ failed -- run manually if necessary"); //$NON-NLS-1$1059             return false;1060         }1061 1062         Log.d(DDMS, "‘adb start-server‘ succeeded"); //$NON-NLS-1$1063 1064         return true;1065     }1066 1067     /**1068      * Stops the adb host side server.1069      * 1070      * @return true if success1071      */1072     private synchronized boolean stopAdb() {1073         if (mAdbOsLocation == null) {1074             Log.e(ADB,1075                     "Cannot stop adb when AndroidDebugBridge is created without the location of adb."); //$NON-NLS-1$1076             return false;1077         }1078 1079         Process proc;1080         int status = -1;1081 1082         try {1083             String[] command = new String[2];1084             command[0] = mAdbOsLocation;1085             command[1] = "kill-server"; //$NON-NLS-1$1086             proc = Runtime.getRuntime().exec(command);1087             status = proc.waitFor();1088         } catch (IOException ioe) {1089             // we‘ll return false;1090         } catch (InterruptedException ie) {1091             // we‘ll return false;1092         }1093 1094         if (status != 0) {1095             Log.w(DDMS, "‘adb kill-server‘ failed -- run manually if necessary"); //$NON-NLS-1$1096             return false;1097         }1098 1099         Log.d(DDMS, "‘adb kill-server‘ succeeded"); //$NON-NLS-1$1100         return true;1101     }1102 1103     /**1104      * Get the stderr/stdout outputs of a process and return when the process is1105      * done. Both <b>must</b> be read or the process will block on windows.1106      * 1107      * @param process1108      *            The process to get the ouput from1109      * @param errorOutput1110      *            The array to store the stderr output. cannot be null.1111      * @param stdOutput1112      *            The array to store the stdout output. cannot be null.1113      * @param displayStdOut1114      *            If true this will display stdout as well1115      * @param waitforReaders1116      *            if true, this will wait for the reader threads.1117      * @return the process return code.1118      * @throws InterruptedException1119      */1120     private int grabProcessOutput(final Process process,1121             final ArrayList<String> errorOutput,1122             final ArrayList<String> stdOutput, boolean waitforReaders)1123             throws InterruptedException {1124         assert errorOutput != null;1125         assert stdOutput != null;1126         // read the lines as they come. if null is returned, it‘s1127         // because the process finished1128         Thread t1 = new Thread("") { //$NON-NLS-1$1129             @Override1130             public void run() {1131                 // create a buffer to read the stderr output1132                 InputStreamReader is = new InputStreamReader(1133                         process.getErrorStream());1134                 BufferedReader errReader = new BufferedReader(is);1135 1136                 try {1137                     while (true) {1138                         String line = errReader.readLine();1139                         if (line != null) {1140                             Log.e(ADB, line);1141                             errorOutput.add(line);1142                         } else {1143                             break;1144                         }1145                     }1146                 } catch (IOException e) {1147                     // do nothing.1148                 }1149             }1150         };1151 1152         Thread t2 = new Thread("") { //$NON-NLS-1$1153             @Override1154             public void run() {1155                 InputStreamReader is = new InputStreamReader(1156                         process.getInputStream());1157                 BufferedReader outReader = new BufferedReader(is);1158 1159                 try {1160                     while (true) {1161                         String line = outReader.readLine();1162                         if (line != null) {1163                             Log.d(ADB, line);1164                             stdOutput.add(line);1165                         } else {1166                             break;1167                         }1168                     }1169                 } catch (IOException e) {1170                     // do nothing.1171                 }1172             }1173         };1174 1175         t1.start();1176         t2.start();1177 1178         // it looks like on windows process#waitFor() can return1179         // before the thread have filled the arrays, so we wait for both threads1180         // and the1181         // process itself.1182         if (waitforReaders) {1183             try {1184                 t1.join();1185             } catch (InterruptedException e) {1186             }1187             try {1188                 t2.join();1189             } catch (InterruptedException e) {1190             }1191         }1192 1193         // get the return code from the process1194         return process.waitFor();1195     }1196 1197     /**1198      * Returns the singleton lock used by this class to protect any access to1199      * the listener.1200      * <p/>1201      * This includes adding/removing listeners, but also notifying listeners of1202      * new bridges, devices, and clients.1203      */1204     static Object getLock() {1205         return sLock;1206     }1207 1208     /**1209      * Instantiates sSocketAddr with the address of the host‘s adb process.1210      */1211     private static void initAdbSocketAddr() {1212         try {1213             int adb_port = determineAndValidateAdbPort();1214             sHostAddr = InetAddress.getByName(ADB_HOST);1215             sSocketAddr = new InetSocketAddress(sHostAddr, adb_port);1216         } catch (UnknownHostException e) {1217             // localhost should always be known.1218         }1219     }1220 1221     /**1222      * Determines port where ADB is expected by looking at an env variable.1223      * <p/>1224      * The value for the environment variable ANDROID_ADB_SERVER_PORT is1225      * validated, IllegalArgumentException is thrown on illegal values.1226      * <p/>1227      * 1228      * @return The port number where the host‘s adb should be expected or1229      *         started.1230      * @throws IllegalArgumentException1231      *             if ANDROID_ADB_SERVER_PORT has a non-numeric value.1232      */1233     private static int determineAndValidateAdbPort() {1234         String adb_env_var;1235         int result = ADB_PORT;1236         try {1237             adb_env_var = System.getenv(SERVER_PORT_ENV_VAR);1238 1239             if (adb_env_var != null) {1240                 adb_env_var = adb_env_var.trim();1241             }1242 1243             if (adb_env_var != null && adb_env_var.length() > 0) {1244                 // C tools (adb, emulator) accept hex and octal port numbers, so1245                 // need to accept1246                 // them too.1247                 result = Integer.decode(adb_env_var);1248 1249                 if (result <= 0) {1250                     String errMsg = "env var " + SERVER_PORT_ENV_VAR //$NON-NLS-1$1251                             + ": must be >=0, got " //$NON-NLS-1$1252                             + System.getenv(SERVER_PORT_ENV_VAR);1253                     throw new IllegalArgumentException(errMsg);1254                 }1255             }1256         } catch (NumberFormatException nfEx) {1257             String errMsg = "env var " + SERVER_PORT_ENV_VAR //$NON-NLS-1$1258                     + ": illegal value ‘" //$NON-NLS-1$1259                     + System.getenv(SERVER_PORT_ENV_VAR) + "‘"; //$NON-NLS-1$1260             throw new IllegalArgumentException(errMsg);1261         } catch (SecurityException secEx) {1262             // A security manager has been installed that doesn‘t allow access1263             // to env vars.1264             // So an environment variable might have been set, but we can‘t1265             // tell.1266             // Let‘s log a warning and continue with ADB‘s default port.1267             // The issue is that adb would be started (by the forked process1268             // having access1269             // to the env vars) on the desired port, but within this process, we1270             // can‘t figure out1271             // what that port is. However, a security manager not granting1272             // access to env vars1273             // but allowing to fork is a rare and interesting configuration, so1274             // the right1275             // thing seems to be to continue using the default port, as forking1276             // is likely to1277             // fail later on in the scenario of the security manager.1278             Log.w(DDMS,1279                     "No access to env variables allowed by current security manager. " //$NON-NLS-1$1280                             + "If you‘ve set ANDROID_ADB_SERVER_PORT: it‘s being ignored."); //$NON-NLS-1$1281         }1282         return result;1283     }1284 1285 }

 

在以上源码中,还有一个connect方法和disconnect方法,可以通过复写这两个方法,将adb当前的连接情况打印出来脚本信息

4、ADB在自动化工具和框架中的作用

可以使用adb的方法,通过打印脚本信息来判断设备连接情况,这是最初级且最基础的技术

 

备注:

BAT测试笔试面试题目:

腾讯笔试题目

1、如何测试分布式ATM机?     这个针对一些大系统的题目,集群部署

2、使用一个数组实现三个堆栈,要求有效的使用数组的存储空间,可以使用其他数据结构

涉及到一个测试人员对整个系统的了解,包括前段的负载均衡到主备应用等

3、编写一个脚本,统计log文件中首个单词出现的次数:error:xxxx

 

阿里2面的部分面试题目

1、Robotium源码架构实现

2、Robotium的工具怎么根据id找到脚本id(脚本id和架构映射原理)

3、Monkeyrunner和UIAutomator的原理

4、你们怎么做电量测试(如何做到app进程级别,而不是整机?比如发一个intent请求之类的?)

5、影响手机电量的因素列举一下

6、稳定性和压力怎么做?

7、Robotium WebView怎么实现?

8、怎么让系统不休眠:1、通过PowerManager来精细控制,具体函数请指出    2、在View中设置FLAG_KEEP_SCREE_ON

 

百度1面题目

1、测试客户端 日文输入法,如果不认识日文,怎么用自动化解决?

2、不用变量交换两个数

3、脚本 怎么用并行和串行调bat批处理

4、怎么解决控件和点触屏自动化(要规划自动化方案)

5、用户安装了百度客户端,怎么实现自动化

6、自动化要验证功能准确性、性能还有UI界面,一个自动化验证多个?还是一个自动化脚本只验证一条用例?

7、怎么实现监控内存   在eclipse显示 DSS是什么意思

8、ANS出现怎么解决?

9、进程和线程 handle和runnable  以及广播和服务

10、Robotium和Monkeyrunner的区别

11、Radiobox和Checkbox自动化脚本怎么复用? (考的是正交法)

12、GC原理

13、android性能自动化怎么做

14、电量对比测试

15、android安全自动化怎么做

16、有个客户装了百度客户端,怎么规划灰度测试版本自动化

17、UI线程阻塞,怎么复现查log