【云真机平台】稳定性测试自动化脚本

前面文章中针对云真机平台稳定性设计了【云真机平台】平台稳定性测试方案,接下来实现具体的脚本进行稳定性测试

一、selenium IDE录制

许久没有写UI自动化,倍感陌生哈哈,那么使用selenium IDE进行录制看看是否能一把搞定

1.1 录制步骤

  • 打开页面
  • 点击立即使用
  • 点击断开连接

1.2 录制效果

在这里插入图片描述

1.3 脚本导出

从selenium IDE中导入录制的脚本(此处导出语言选择为Python pytest)

# Generated by Selenium IDE
import pytest
import time
import json
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.support import expected_conditions
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

class Testlluozh():
  def setup_method(self, method):
    self.driver = webdriver.Chrome()
    self.vars = {}
  
  def teardown_method(self, method):
    self.driver.quit()
  
  def test_untitled(self):
    # Test name: Untitled
    # Step # | name | target | value
    # 1 | open | / | 
    self.driver.get("http://uiat.gz.lluozh.cn/")
    # 2 | setWindowSize | 1545x708 | 
    self.driver.set_window_size(1545, 708)
    # 3 | click | xpath=(//button[@type='button'])[8] | 
    self.driver.find_element(By.XPATH, "(//button[@type=\'button\'])[8]").click()
    # 4 | click | xpath=//div[@id='mobile-container']/div[2]/div[6] | 
    self.driver.find_element(By.XPATH, "//div[@id=\'mobile-container\']/div[2]/div[6]").click()

二、多进程执行

前面测试方案中提及,需要同时执行1、2、5、10台设备,故需要多进程执行脚本文件

def device_connect(device_id):
	# TODO

if __name__ == '__main__':
 	device_list = ['lluozh001','lluozh002','lluozh003','lluozh004']
	for device_id in device_list:
	        p = Process(target=device_connect, args=(device_id,))
	        p.start()
	        p_list.append(p)
	    for p in p_list:
	        p.join()
	for p in p_list:
	        p.join()

三、连接特定设备

3.1 设备列表展示逻辑

录制脚本可执行成功,但多个进程执行时设备列表实时刷新连接状态,且将正在使用的设备排序在未使用设备后面,未使用设备根据借用时间排序

3.2 出现问题

出现两个进程同时点击连接某个设备,这样导致其中一个进程出现非预期的失败

3.3 解决方案

  1. 不同进程操作各自的设备,相互之间互不影响
  2. 根据设备名称查找对应的设备
  3. 定位到设备名称后通过子节点查找对应的父节并找到对应的btn

3.4 实现细节

  • 设备选择框的树状层级
    在这里插入图片描述

使用子节点查找对应的父节并找到对应的btn,对应的脚本

# 点击立即使用按钮
driver.find_element_by_xpath("//input[@value='{}']/../../../../../../../../../ul/li/span/button".format(device_id)).click()

四、连接状态

点击立即使用连接设备后需要判断连接是否成功

4.1 问题现象

虽然点击连接均会打开设备连接窗口,但连接异常时会有对应的提示,比如

  • 远程连接已断开
    在这里插入图片描述
  • 设备操作异常
    在这里插入图片描述

故仅通过窗口是否存在无法判断连接状态是否成功

4.2 判断提示字样是否存在

  • 提示字样的树状图
    在这里插入图片描述
  • 通过判断该字段是否存在
try:
	driver.find_element_by_class_name("connect-close")
expect:
	pass

发现不管是否连接成功该字段都存在

4.2 判断提示字样style属性

既然该字段均存在,即异常时该信息才显示,需要通过另外的属性判断
通过树状图可以看到style字段信息,存在时显示为display: block;

那不存在异常提示的时候呢?
在这里插入图片描述
从上图可以看出,显示的是display: none;

故判断连接是否成功可以通过字样的style属性

style = driver.find_element_by_class_name("connect-close").get_attribute("style")
if style == 'display: block;':
    return False
else:
    return True

五、页面刷新

5.1 设备断开时实现逻辑

  1. 前端操作断开设备连接

  2. 后台异步返回结果后前端立即页面状态刷新
    此时设备状态时占用中

  3. 后台处理断开连接逻辑
    此时设备实际状态为未使用,但前端页面若没刷新还是显示该设备在使用中

5.2 解决方案:

针对该问题在此次稳定性测试中的解决方案:

  1. 需要将逻辑改成同步,后台处理断开连接逻辑后再返回处理结果
  2. 每次连接状态前先刷新页面

接下来暂时使用每次连接前先大刷新页面的方式

# 页面大刷新(不进行大刷新出现页面中该设备使用状态未更新)
driver.refresh()

六、滑动翻页

除了需要不断的进行连接和断开操作外,还需要通过web端滑动页面操作测试其稳定性

当前使用的方案是selenium+python,如何实现在web页面对远程的手机页面进行滑动操作呢?

6.1 ActionChains

接下来主要是使用ActionChains尝试针对页面进行操作

ActionChains的方法列表:

  • click(on_element=None)
    单击鼠标左键
  • click_and_hold(on_element=None)
    点击鼠标左键,不松开
  • context_click(on_element=None)
    点击鼠标右键
  • double_click(on_element=None)
    双击鼠标左键
  • drag_and_drop(source, target)
    拖拽到某个元素然后松开
  • drag_and_drop_by_offset(source, xoffset, yoffset)
    拖拽到某个坐标然后松开
  • key_down(value, element=None)
    按下某个键盘上的键
  • key_up(value, element=None)
    松开某个键
  • move_by_offset(xoffset, yoffset)
    鼠标从当前位置移动到某个坐标
  • move_to_element(to_element)
    鼠标移动到某个元素
  • move_to_element_with_offset(to_element, xoffset, yoffset)
    移动到距某个元素(左上角坐标)多少距离的位置
  • perform()
    执行链中的所有动作
  • release(on_element=None)
    在某个元素位置松开鼠标左键
  • send_keys(*keys_to_send)
    发送某个键到当前焦点的元素
  • send_keys_to_element(element, *keys_to_send)
    发送某个键到指定元素

6.2 move_to_element

使用ActionChains中move_to_element的方式滑动操作

actions = ActionChains(driver)
element = driver.find_element_by_id("transparentCanvas")
actions.move_to_element(element).click_and_hold().perform()
time.sleep(1)
element = driver.find_element_by_id("transparentCanvas")
actions = ActionChains(driver)
ActionChains(driver).move_to_element(element).perform()
time.sleep(1)
element = driver.find_element_by_id("transparentCanvas")
actions = ActionChains(driver)
actions.move_to_element(element).release().perform()
ActionChains(driver).click(element).perform()

通过验证发现,以上脚本使用move_to_element的方式无法成功对手机屏幕进行翻页

6.3 move_by_offset

使用ActionChains中move_by_offset的方式滑动操作

 # 选择拖动滑块的节点
element = driver.find_element_by_id("transparentCanvas")
# ------------鼠标滑动操作------------
action = ActionChains(driver)
# 第一步:在滑块处按住鼠标左键
action.click_and_hold(element)
# 第二步:相对鼠标当前位置进行移动
action.move_by_offset(element.size.get('width'), 0)
# 第三步:释放鼠标
action.release()
# 执行动作
action.perform()

验证发现执行后依旧没有任何反应

6.3 drag_and_drop

使用ActionChains中之前使用过的drag_and_drop方式试试是否可以

element = driver.find_element_by_id("transparentCanvas")
ActionChains(driver).drag_and_drop_by_offset(element,element.size.get('width'), 0).perform()

执行后依旧没有反应,那究竟是哪里出现了问题呢?

6.4 offset数值

无法滑动成功,是否因为offset移动超过了范围导致未能成功

  • width-10

通过移动width-10的宽度

element = driver.find_element_by_id("transparentCanvas")
ActionChains(driver).drag_and_drop_by_offset(element,element.size.get('width')-10, 0).perform()

验证发现同样没有反应

  • width/2

通过移动width/2的宽度

element = driver.find_element_by_id("transparentCanvas")
ActionChains(driver).drag_and_drop_by_offset(element,element.size.get('width')/2, 0).perform()

验证发现同样没有反应

  • width/4

通过移动width/4的宽度

element = driver.find_element_by_id("transparentCanvas")
ActionChains(driver).drag_and_drop_by_offset(element,element.size.get('width')/4, 0).perform()

验证发现可成功滑动

在offset=width/4时,验证发现使用move_by_offset和drag_and_drop均可正常滑动

6.5 实现脚本

实现不断左右滑动的脚本

element = driver.find_element_by_id("transparentCanvas")
offset_x = element.size.get('width')/4
for j in range(0,100):
	# 左滑动
	ActionChains(driver).drag_and_drop_by_offset(element,offset_x, 0).perform()
	time.sleep(1)
	# 右滑动
	ActionChains(driver).drag_and_drop_by_offset(element, -offset_x, 0).perform()

七、截图

由于需要长时间自动化执行验证稳定性,那就不可能实时关注页面信息,故需要失败、异常或其他有需要时截取当时页面的图片,方便接下来定位问题

其实selenium封装了比较好的方式进行页面截图保存

# 文件目录
dir_name = '/Users/lluozh/docs/'
if not os.path.isdir(dir_name):
    os.makedirs(dir_name)
# 设备id
device_id = 'lluozh001'
# 执行次数
times = 1
# 执行时间
run_time = time.strftime('%Y%m%d%H%M%S', time.localtime(time.time()))
# 截图操作(截图目录中保存这些信息主要是方便出现问题时更好定位问题)
driver.get_screenshot_as_file(dir_name + "/{}_{}_{}_{}.png".format(device_id, times, run_time, connect[1]))

稳定性验证的自动化脚本完成

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sysu_lluozh

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值