移动端测试理论(下)

TouchAction 中 move to 使用相对坐标还是绝对路标的问题

和appium版本号有关,和wait的放置位置有关
在appium1.7中

TouchAction(driver).press.wait.move_to   # swipe 绝对坐标
TouchAction(driver).press.move_to.wait   # 相对坐标

在appium1.8中

TouchAction(driver).press.wait.move_to   #绝对坐标
TouchAction(driver).press.move_to.wait   # 绝对坐标

线程

多任务的简单介绍

  • 有很多事情在现实生活的场景中是同时进行的,比如开车的时候 手和脚共同来驾驶汽车,再比如唱歌跳舞也是同时进行的。
  • 多任务,就是能够在同一时间同时进行多个任务。
import time
import threading

def sing():
    for i in range(5):
        print("唱歌")
        time.sleep(1)

def dance():
    for i in range(5):
        print("跳舞")
        time.sleep(1)

# 主线程在从上往下跑

# 开一个子线程
t1 = threading.Thread(target=sing)
# 又开一个子线程
t2 = threading.Thread(target=dance)

t1.start()
t2.start()

多任务的原理

  • 什么叫“多任务”呢?简单地说,就是操作系统可以同时运行多个任务。打个比方,你一边在用浏览器上网,一边在听MP3,一边在用Word赶作业,这就是多任务,至少同时有3个任务正在运行。还有很多任务悄悄地在后台同时运行着,只是桌面上没有显示而已。

  • 单核cpu工作原理

    • 现在,多核CPU已经非常普及了,但是,即使过去的单核CPU,也可以执行多任务。由于CPU执行代码都是顺序执行的,那么,单核CPU是怎么执行多任务的呢?
    • 答案就是操作系统轮流让各个任务交替执行,任务1执行0.01秒,切换到任务2,任务2执行0.01秒,再切换到任务3,执行0.01秒……这样反复执行下去。表面上看,每个任务都是交替执行的,但是,由于CPU的执行速度实在是太快了,我们感觉就像所有任务都在同时执行一样。
    • 真正的并行执行多任务只能在多核CPU上实现,但是,由于任务数量远远多于CPU的核心数量,所以,操作系统也会自动把很多任务轮流调度到每个核心上执行。
  • 多核cpu工作原理

    • 和单核类似,相当于多了一个干活的人。
  • 并发:指的是任务数多于cpu核数,通过操作系统的各种任务调度算法,实现用多个任务“一起”执行(实际上总有一些任务不在执行,因为切换任务的速度相当快,看上去一起执行而已)

- 并行:指的是任务数小于等于cpu核数,即任务真的是一起执行的

  • 并行和并发都算是多任务,但并行实际上才是真正的多任务,并发是假的。

多任务的实现方法有多种,线程只是其中一种

线程的工作原理

  • 以唱歌跳舞的案例说明

  • 主线程

    • 我们常说的一个程序代码会从上往上执行,默认就是主线程来执行的。
  • 子线程

    • 人工开启的线程。主线程会等待子线程结束后再结束。
    • 子线程的任务完成,这个子线程就会消失了
  • 线程和线程之间会进行资源的抢夺,谁先执行谁后执行是不一定的

线程的两种创建方式

  • 直接使用threading模块的Thread类,指定要执行的方法,再调用start
  • 使用继承的方式,继承Thread类,重新run方法,创建这个对象后,再调用start

查看当前程序线程数量

  • threading.enumerate()
    • 获取所有线程,返回的是一个列表。
    • 如果需要个数,使用len(threading.enumerate())

为子线程传递参数

  • target方式
import time
import threading 

def sing(nums):
    for i in range(nums):
        print("唱歌")
        time.sleep(1)

def dance():
    for i in range(5):
        print("跳舞")
        time.sleep(1)

# args后面跟的是参数元组
# kargs后面跟的是参数字典,
# 但在这里,如果用的是字典,字典的keys的名字要和target中的函数的参数名字一致
t1 = threading.Thread(target=sing, args=(3,))
# 或者 t1 = threading.Thread(target=sing, kargs={"nums" : 3})
t2 = threading.Thread(target=dance)

t1.start()
t2.start()
  • 类继承方式
import threading

class Work1(threading.Thread):

    def __init__(self, nums):
        # 要重写父类的__init__方法,首先要在里面继承父类的__init__方法
        # 或者super().__init__()
        threading.Thread.__init__(self)
        self.nums = nums

    def run(self):
        for i in range(self.nums):
            print("haha")


def main():
    w = Work1(2)
    w.start()

if __name__ == "__main__":
    main()

多线程的应用

在下载事件或者请求涉及到网络的时候,会是多线程的形式进行
点下载以后就会开一个线程让它去下载,主线程可以不用等下载完成了再去做别的操作

队列(queue)和栈(stack)的概念

队列:先进先出,在手机应用中有个运行循环,在监听事件操作,不是多线程的话,事件在队列中过来,只有前一个事件运行完了,下一个事件再进去循环,再进行下一个事件

:先进后出,----> 名词概念:进==>进栈,出==>出栈 或 弹栈,栈中最上面==>栈顶,栈中最下面==>栈底

appium多端口

  • 目标,让一个脚本去跑到多台手机。
    实现的思想:要开多个appium服务(对应多个端口号),然后不同的appium服务去连对应的多个手机(对应多个udid,只是一个唯一标识的字符串)

  • 打开多个appium服务:命令行打开appium,appium -p 4723appium -p 4725
    打开多个bootstrap服务(bootstrap引导的意思),与多个手机一一对应
    打开多个手机:在virtualbox里面,再导入多一个虚拟电脑,在genymotion里面就会多一个手机模拟器,点start就好了

移动端测试理论(下)_第1张图片
  • 注意点: appium sever端口要不同,开启多个。bootstrap端口要不同,开启多个。udid需要指定,udid表示设备的唯一表示符号,通过 adb devices 查看。 前半部分都是,比如模拟器的(192.168.57.101:5555)。

  • appium server 和 bootstrap 和 udid 应该是成对出现的。

  • 命令:

appium -p 4723 -bp 4724 -U 192.168.57.101:5555
  • p 表示 appium的端口

  • bp 表示 bootstrap的端口

  • U 表示设备的标识符

  • 修改init_driver让,init_driver接受port的参数。并且进行对应的连接。
    记得,创建的是不同的driver对象。

  • 因为如果使用threading.Thread的这种形式,需要指定执行的函数,所以,把需要执行的代码,封装成一个函数。然后使用以下代码:

在base_driver中

from appium import webdriver


def init_driver(port="4723"):
    # server 启动参数
    desired_caps = dict()
    # 设备信息
    desired_caps['platformName'] = 'Android'
    desired_caps['platformVersion'] = '5.1'
    desired_caps['deviceName'] = '192.168.164.101:5555'
    # app信息
    desired_caps['appPackage'] = 'com.android.settings'
    desired_caps['appActivity'] = '.Settings'
    # 中文
    desired_caps['unicodeKeyboard'] = True
    desired_caps['resetKeyboard'] = True
    # 不重置应用
    desired_caps['noReset'] = True
    # toast
    # desired_caps['automationName'] = 'Uiautomator2'
    # 声明对象
    driver = webdriver.Remote('http://localhost:' + port + '/wd/hub', desired_caps)
    return driver

在test_demo中:

import threading

from selenium.webdriver.common.by import By

from base_driver import init_driver
from base_action import BaseAction
from login_page import LoginPage


def do(port):
    driver = init_driver(port)
    login_page = LoginPage(driver)
    if "4723" == port:
        login_page.click((By.XPATH, "text,更多"))
    else:
        login_page.click((By.XPATH, "text,WLA"))


def main():
    ports = ["4723", "4725"]

    for i in ports:
        threading.Thread(target=do, args=(i,)).start()

    # for i in ports:
    #     driver = init_driver(i)
    #     login_page = LoginPage(driver)
    #     login_page.click((By.XPATH, "text,更多"))


if __name__ == '__main__':
    main()

来去执行创建多个driver并且进行脚本的操作。


Webview

使用inspect检查元素的好处是可以实时更新你在手机模拟器中的操作,但要翻墙


移动端测试理论(下)_第2张图片
移动端测试理论(下)_第3张图片
移动端测试理论(下)_第4张图片

iOS

测试一个iOS项目的方法

  • 开发ios的应用可以用Xcode软件,相当于开发安卓软件的Android studio,要测试ios应用也要用Xcode,因为Xcode中才有模拟器

  • 拿到这个项目文件,蓝色文件用Xcode打来,选择好模拟器,先运行一下(就会在模拟器中安装这个项目的app了),然后可以在模拟器中做相关操作(home键是键盘中的command+H),也可以在Xcode中我们可以找到一些项目的信息(例如设备信息,app信息,需要在测试脚本的前置代码中填写的)

  • 如果在Xcode中的Products文件夹下的app名字报红了(就是还没有安装这个app),就可以先运行一下(command+r),或者按着那个报红的文件编译一下(command+b)

  • 还是在pycharm中写测试脚本,在pycharm的terminal中pytest运行

    • 前置信息中,如果没有安装这个app,可以在Xcode中点Products下的已经编译过的app文件右键show in Finder(相当于windows中的资源管理器),然后复制一份里面的.app文件,去到你电脑测试项目文件夹下, 然后在前置代码中的desired_caps['app'] = os.path.abspath("./xxx.app")
    • 建议拿到项目后先在Xcode运行,模拟器中安装了这个app就不用上面这种形式了
  • 在iOS中,(View)Controller就相当于安卓中的activity,一个界面对应一个controller

在Xcode中运行iOS项目

移动端测试理论(下)_第5张图片

iOS前置代码

移动端测试理论(下)_第6张图片

对于已经安装了这个ios项目,如何在Xcode中获取它的bundleid信息(前置代码中app信息,其实就是bundleid,相当于安卓中的包名)


移动端测试理论(下)_第7张图片
移动端测试理论(下)_第8张图片

appium应用的另一个功能,可以查看页面元素

appium查看元素-android

移动端测试理论(下)_第9张图片
移动端测试理论(下)_第10张图片

appium左侧三个功能和右侧五个功能

移动端测试理论(下)_第11张图片

appium查看元素-iOS

移动端测试理论(下)_第12张图片

点击事件

移动端测试理论(下)_第13张图片
移动端测试理论(下)_第14张图片

滑动

Monkey

Monkey介绍

  • monkey 要用命令启动的话,首先要保证安卓模拟器是开着的


    移动端测试理论(下)_第15张图片

Monkey输出日志

  • -p后面是要测试的包名,100是要执行多少次动作


Monkey基本参数介绍

  • 课外知识:md5加密算法
  • 每次做monkey都建议加上-s seed值
  • 延时设置的是每个事件之间的时间间隔,并不是每个动作,这里例子中的参数100,就是动作,100个动作可能就几个事件
  • 可以通过-- pct-touch 等去控制想要发生的事件/动作的比例


    移动端测试理论(下)_第16张图片

Monkey日志分析

  • 如果出现了Exception,就拿之前设置的seed去复现,看点哪里出现问题,再拿真机去试操作,看是不是真的有问题


    移动端测试理论(下)_第17张图片

    移动端测试理论(下)_第18张图片

MonkeyRunner

  • MonkeyRunner是一套工具,一套API,可以用python代码去控制Monkey,告诉它去怎么生成这些随机的事件
  • 本质和Monkey做的事情是一样的,但Monkey是用命令行实现的,一个使用代码调用MonkeyRunner API实现的(MonkeyRunner底层也是用Monkey)

分辨率

像素

  • 像素是长度单位,一个像素就是一个小方格,一个小方格里面会有几个色块,当你在电脑屏幕上看到一个图片是红色的时候,里面的像素小方格里面的色块就只有红色有数值,其余的色块都是零,这就实现了显示红色了
  • 但为什么两台设备有一样的物理尺寸,不一样的分辨率,看到的图片位置大小都一样?
    • 这就涉及像素密(密度,pixels for inch)的问题,在同样尺寸,不同分辨率的两台设备中,项目会准备大小不同的图片(1x,2x,3x,安卓项目是在不同的文件夹下有相同的名称的图片,ios项目是在同一个文件夹下有不同名称的图片),让图片会去适配,例如在小分辨率中占30像素的图片,在分辨率大一倍的设备中就会占60像素
    • 在功能测试中,如果要测分辨率,就拿对应的图片大小去测主流分辨率的屏幕设备

补充:

  • token ---> 在大部分的开发项目中表示身份,就是表示身份信息

测试流程

  • 中断测试不常见,但是像游戏这种需求实时性的应用可能要做一下,但人工做就可以了
  • 密码MD5算法加密的是不可逆的,存在数据库中的密码也是加密过的,用户请求发送过来的密码(加密了)与数据库中的加密过的密码比对,一样就能登陆


    移动端测试理论(下)_第19张图片

    移动端测试理论(下)_第20张图片

    移动端测试理论(下)_第21张图片

你可能感兴趣的:(移动端测试理论(下))