Selenium Web自动化窗口的控制、界面重新绘制

3.9 窗口控制

下面我们看一段 HTML

<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <title>定位网页元素</title>
</head>

<body style="width:1600px">

<div>
<span>输入框</span> <input type="text" style="margin-top:2200px">
</div>


</body>
</html>

可以看到这段 HTML 很简单,body 里面有个 divdiv 里面有个 span 里面有个 input 输入框,里面有个很奇特的属性 margin-top 它的意思是这个元素和他的上面元素的间隔有多高 2200px 像素,这个间隔是非常高的,
大家复制这段 html 看一下,比如做自动化的时候 web 页面很长,它的内容在很下面,我们需不要把这个页面滚动到下方让他出来再去操作这个元素呢?大家注意华为官网的看不到是因为元素所在的区域已经有了,只是你没有操作它,它属于不可见属性的看不到,但是我们现在讲的这种其实可见状态只是你滚动条没有拉下来,通长这种情况不需要你滚动下来的,它本身在视图上是有的,只是没呈现滚动区域里面。

from selenium import webdriver
executable_path = r"d:\tools\webdrivers\chromedriver.exe"

driver = webdriver.Chrome('E:\ChromDriver\chromedriver.exe')
driver.implicitly_wait(10)


driver.get(r'E:\case\Selenium\代码\samples_selenium\wd\lesson07\winsize.html')

searchbox = driver.find_element_by_tag_name('input')

searchbox.send_keys('你好啊\n')

input('...')
driver.quit()

如果确实需要改变窗口大小,有时确实让元素可见,才能点击(有时候确实是这样,不知道什么原因)或者觉得这样看起来更清楚一些。

  • 获取当前窗口的大小返回是字典格式
size = driver.get_window_size() #返回是字典格式
  • 调整窗口的大小,变宽、变高、变矮
driver.set_window_size(1100,size['height'])      #改变宽度

set_window_size(1100,size['height'])参数是多少个像素(我们这里是1100)。我们通常自动化的时候大家发现窗口可能并没有最大化 ,如果我们想把它调宽就 set_window_size(1100,size['height']) 第一个参数就是它的宽度。第二个参数就是它的高度,如果你觉得它不够高,可以改变它的高度。

driver.set_window_size(size['width'],500)      #改变高度
  • 最大化
driver.maximize_window()

下面是对网易云音乐写的代码,可拿去试一下。

from selenium import webdriver

driver = webdriver.Chrome(r"E:\ChromDriver\chromedriver.exe")
driver.implicitly_wait(10)

driver.get('http://music.163.com')

# 结果像这样 {'width': 855, 'height': 922}
size = driver.get_window_size()
print(size)
# 只改变宽度
driver.set_window_size(1300, size['height'])

#最大化
driver.maximize_window()

searchbox = driver.find_element_by_css_selector('#srch')

searchbox.send_keys('张学友\n')

driver.quit()

小知识点:
Windows 文本文件里面用 \r\n 表示回车加换行,但实际上 \nnewline可以表示下一行,通常在输入里面代表下一行 \n 就相当于敲了一个回车键,相当于换一行的意思。

上面我们讲了改变窗口大小的方法,但是有些时候我们把窗口的高度和宽度最大化元素还是看不到,因为要找的元素它在特别的右边或特别的下边窗口最大化都显现不出来,那就需要滚动元素的方案,selenium 没有直接的方法,可以使用最后一招, 直接让浏览器执行一段 javascript 脚本,因为浏览器它执行的前端代码用 JavaScript 写的,我们做 selenium 自动化,我们自动化程序把命令发送给浏览器驱动,浏览器驱动发送给浏览器,其实我们可以直接把它们要执行的代码发给它,就得到了最大的灵活性去控制浏览器。可以算是终极武器。 比如滚动屏幕,就可以使用 js 语言。

driver.execute_script('window.scrollBy(250,0)')

第一个参数250是横向滚动就是x坐标滚动,向右滚250个像素,如果有们想向左滚

driver.execute_script('window.scrollBy(-250,0)')就滚回去了

第二个参数是向下滚

driver.execute_script('window.scrollBy(0,300)')

上滚加个负号就好了。

下面是对网易云音乐写的代码,可以试一下效果:

from selenium import webdriver

driver = webdriver.Chrome('E:\ChromDriver\chromedriver.exe')
driver.implicitly_wait(10)

driver.get('http://music.163.com')

driver.execute_script('window.scrollBy(200,0)')

searchbox = driver.find_element_by_css_selector('#g_search input')

searchbox.send_keys('张学友\n')

driver.quit()

界面重新绘制

有这样一个教管系统,有课程管理、老师管理、培训班管理、培训班期管理、课时管理、学生管理,其中课程管理里面可以删除、添加、修改课程,假如我们要做这样一个自动化功能,做自动化之前比如有个用例自动化之前,需要当前系统中一门课程都没有。

image.png

就有一个初始化的操作,就是把当前系统中如果有课程全部删掉,全部删掉我们手工怎么做,手工删掉就是 点击“删除” 然后点击“确定”。我们自动化无非也是做这个操作,把所有的删除都点一遍。看似很简单我们按照这个思路去写代码,根据我们的思路要把所有的删除按钮找出来。

大家看一下根据什么属性去找呢,没有 id 根据 class,但是这个 class 有好多属性,btn-green 看名字就可以看出来按钮是绿色的按钮 btn-outlined 是外面有一个方框,根据这个 class 是不好去找的因为编辑也有同样的属性,这里根据 ng-click 这个属性去找比较好,他这个属性对应删除的动作,点了这个删除之后会执行一段 JavaScript 代码或函数,删除是跟这个紧密相关的,点击删除之后这里还有个确定。

image.png

这个元素在这里很好找,我们就不说了。
代码:

from selenium import  webdriver
import time


driver = webdriver.Chrome()
driver.implicitly_wait(5)

driver.get('http://localhost/mgr/login/login.html')
#登录
driver.find_element_by_id('username').send_keys('auto')
driver.find_element_by_id('password').send_keys('sdfsdfsdf')
driver.find_element_by_tag_name('button').click()

time.sleep(1)

#根据ng-click去找删除按钮,这里是个list
delButtons = driver.find_elements_by_css_selector(
'*[ng-click^=delOne]')


for button in delButtons:
    button.click()
    time.sleep(1)
    driver.find_element_by_css_selector(
        '.modal-footer  .btn-primary').click()

运行会发现删除第一个之后就不动了,报错了报错信息如下:

selenium.common.exceptions.StaleElementReferenceException: Message: stale element reference: element is not attached to the page document
  (Session info: chrome=74.0.3729.157)
  (Driver info: chromedriver=74.0.3729.6 (255758eccf3d244491b8a1317aa76e1ce10d57e9-refs/branch-heads/3729@{#29}),platform=Windows NT 10.0.17134 x86_64)

问题出在 button.click() 这一行,为什么点击会有异常呢,我们看一下描述stale element reference:stale 过期的意思,这个元素已经过期了,就是过期元素的引用,什么元素过期呢,我们大胆的猜一下就是这个 button 对应的这个元素。element is not attached to the page document 就是 button这个元素已经不在当前页面这个文档里了。大家以后做自动化的时候会经常遇到这种事情,因为现在 web 前端的开发很多开发人员使用的方法都会动态的更新的前端界面,之前最早的 web 界面的呈现,比如导致 web 界面出现了变化,都是发起 http 请求,后端返回一个完整的 http 页面给你,以前都是这样,随着前端开发衍进觉得这种效率太低,因为有的时候并不需要后端重新产生一个完整的界面,比如这个删除操作,删除一个课程只需要告诉后端我把这个课程删了,服务器处理一下在数据库把这个课程清除掉,没有必要让服务端再返回一个完整html的界面给前端,对于我们来说只需要在代码里动态的把课程清除掉就可以,所以这个时候前端的开发可以动态改变前端的内容,可以通过 JavaScript 代码更新界面,或者一些框架,这样就产生了一个问题就像之前这样看似点击删除按钮,点击确定好像界面只少了一个课程,但实际上有的框架就不是简单的把这一个元素删了,他有可能把整个表格获取一次重新产生了,重新产生意思是原来是4条记录现在重新产生了眼睛看起来就少了一条记录,实际上页面上所有的元素都重新创建了一遍,这就带来我们删除一门课程之后导致现在界面剩下来 3 个删除按钮已经不是刚才 4 个中的 3 个了,就是这个原因导致的。我们可以这样既然你之后界面刷新了那我们每次删除之后就重新获取当前界面的元素就可以了。

from selenium import  webdriver
import time


driver = webdriver.Chrome()
driver.implicitly_wait(5)

driver.get('http://localhost/mgr/login/login.html')

driver.find_element_by_id('username').send_keys('auto')
driver.find_element_by_id('password').send_keys('sdfsdfsdf')

driver.find_element_by_tag_name('button').click()


time.sleep(1)

driver.implicitly_wait(1)


while True:
#找删除按钮
    delButtons = driver.find_elements_by_css_selector(
    '*[ng-click^=delOne]')
#判断有没有删除按钮
    if delButtons == []:
        break
#如果有就找到第一个元素,点击他
    delButtons[0].click()
#点确定
    driver.find_element_by_css_selector('.modal-footer  .btn-primary').click()

    time.sleep(1)


driver.implicitly_wait(5)

这样就没有问题,因为我们每次删除按钮都会重新获取当前页面,大家会不会有个疑惑循环前有个 implicitly_wait(1) 循环后又把 implicitly_wait(1) 改成implicitly_wait(5) 呢,主要是因为循环删除总有一次删光了,删光了最后一次循环执行 delButtons = driver.find_elements_by_css_selector('[ng-click^=delOne]')* 的时候,因为删光了就没有元素,就会等待全局的等待时间比如5秒,就会等待5秒,临时的把时间改短了点这样比较好。这里的time.sleep(1)很重要,因为你点击确定删除的时候就会执行删除操作,服务端就会删除数据,界面刷新会花一段时间,如果没有sleep(1)就会立即获取页面,就会获取到没有更新的页面元素。

3.9.1 用半自动化的方法

有些自动化的输入需要人来输入的,比如我们常见的 验证码,我们可以打开12306 的登录看一下:

image.png

点击图中的所有的网球拍,你自动化怎么做,非常难做,人都很难看清楚何况用软件,即使做了失败率也是很高的,还有的时候检查很难,比如我们打开华为商城,比如说测试用例里面有一步检查当前界面的布局有没有错乱。那怎么检查,怎么用软件检查页面有没有错乱或者检查图片 log 是否正确,不好做。。。人工智能还没有到这一步,这些动作还是得人来做。这时候有人会说,假如我测试用例有这样的步骤,是不是就要跳掉了,不做自动化了。这个时候我们通常会采取半自动化的方式,因为只是其中某一个步骤需要人干预一下。半自动化在工作中也是非常常用的。我们可以在需要人干预的时候可以做出一些提示,比如说发出一些声音来。

import winsound
winsound.Beep(1500,3000)

这是我们随便举的一种方法,方法有很多。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,921评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,635评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,393评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,836评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,833评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,685评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,043评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,694评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,671评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,670评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,779评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,424评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,027评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,984评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,214评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,108评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,517评论 2 343

推荐阅读更多精彩内容