51Testing软件测试论坛

标题: Selenium-常见控件操作之Web自动化(下) [打印本页]

作者: lsekfe    时间: 2022-12-22 13:41
标题: Selenium-常见控件操作之Web自动化(下)
 select下拉列表
  下拉列表的tag name是“select”,而下拉列表的选项的tag name是“option”。

  导包,可以用这两种方法任一个。
  from [url=]selenium[/url].webdriver.support.ui import Select
  from selenium.webdriver.support.select import Select


  ●实例化Select:Select(driver.find_element_by_id('s1Id'))。
  ●选择下拉选项:select类提供了3种选择某一选项的方法,分别是通过index选择下拉选项——select_by_index(index);通过value值选择下拉选项——select_by_value(value);通过可见text选择下拉选项——select_by_visible_text(text)。
  ●取消下拉选项:select类提供了4种方法取消原来的选择,分别是通过index取消下拉选项——deselect_by_index(index);通过value值取消下拉选项——deselect_by_value(value);通过可见text取消下拉选项——deselect_by_visible_text(text);全部取消选择——deselect_all()。
  ●返回选项:返回所有选项——options;返回第一个选中项——first_selected_option;返回所有选中项——all_selected_options。
  ●判断select选项是否可多选:is_multiple,返回一个布尔值。
  选择下拉值
  <!DOCTYPE html>
  <html lang="en">
  <head>
      <meta charset="UTF-8">
      <title>select下拉列表</title>
      </head>
  <body>
  <select id="s1Id">
  <option></option>
  <option value="o1" id="id1">o1</option>
  <option value="o2" id="id2">o2</option>
  <option value="o3" id="id3">o3</option>
  </select>
  </body>
  </html>
  from selenium import webdriver
  from time import sleep
  from selenium.webdriver.support.ui import Select
  driver = webdriver.Chrome()
  driver.get('C:\\Users\\Desktop\\my_html.html')
  ele = driver.find_element_by_id('s1Id')
  # Select(ele).select_by_index(1)#通过 index定位
  Select(ele).select_by_value('o2')#通过value属性定位
  # Select(ele).select_by_visible_text('o3')
  sleep(3)
  driver.quit()


  ●value是<option>标签的一个属性值,并不是显示在下拉列表中的值。
  ●visible_text是在<option>和</option>标签对中间的值,是显示在下拉列表中的值。
  取消选择
  <!DOCTYPE html>
  <html lang="en">
  <head>
      <meta charset="UTF-8">
      <title>可以多选的select下拉列表</title>
  </head>
  <body>
  <select id="s1Id" multiple="multiple">
  <option>请选择:</option>
  <option value="o1" id="id1">o1</option>
  <option value="o2" id="id2">o2</option>
  <option value="o3" id="id3">o3</option>
  </select>
  </body>
  </html>


   <select>标签多了一个multiple="multiple"的属性,这意味着该下拉列表的选项可以多选。
  from selenium import webdriver
  from time import sleep
  from selenium.webdriver.support.ui import Select
  driver = webdriver.Chrome()
  driver.get('C:\\Users\\Desktop\\my_html.html')
  ele = driver.find_element_by_id('s1Id')
  Select(ele).select_by_index(1)#通过 index定位
  sleep(2)
  Select(ele).deselect_by_index(1)#取消选择
  Select(ele).select_by_index(1)
  Select(ele).select_by_index(2)
  Select(ele).select_by_index(3)
  Select(ele).deselect_all()#取消所有选择
  sleep(3)
  driver.quit()


  获取选项
  获取所有option,并依次选中。
  ◆select提供了3个属性用于获取选项
  Options——返回包含所有选项的列表,其中选项是WebElement元素。
  all_selected_options——返回包含所有被选中的选项的列表。
  first_selected_option——提供第一个被选中的选项,也可以用于获取下拉列表的默认值。
  from selenium import webdriver
  from time import sleep
  from selenium.webdriver.support.ui import Select
  driver = webdriver.Chrome()
  driver.get('C:\\Users\\Desktop\\my_html.html')
  ele = driver.find_element_by_id('s1Id')
  all_options=Select(ele).options #返回所有option
  for i in range(len(all_options)):
      Select(ele).select_by_index(i)#循环option依次选中
  all=Select(ele).all_selected_options #获取所有被选择的选项
  for i in all:
      print(i.text)
  driver.quit()


  判断select下拉列表中的选项是否可多选
  ◆Select提供了一个属性,用来判断是否可多选is_multiple——返回一个布尔值,判断select选项是否可多选。
  from selenium import webdriver
  from time import sleep
  from selenium.webdriver.support.ui import Select
  driver = webdriver.Chrome()
  driver.get('C:\\Users\\Desktop\\my_html.html')
  ele = driver.find_element_by_id('s1Id')
  print(Select(ele).is_multiple)


  表格
  一个table标签对应一个表格;“table”里面包含若干“tr”,每个“tr”对应一行;每个“tr”下面包含若干“td”,每个“td”对应一个单元格。
  <!DOCTYPE html>
  <html lang="en">
  <head>
      <meta charset="UTF-8">
      <title>学习操作表格-1</title>
  </head>
  <body>
  <table border="1">
  <tr>
  <td>0-0</td>
  <td>0-1</td>
  <td id="CellWithId">Cell with id</td>
  <td>0-3</td>
  </tr>
  <tr>
  <td>1-0</td>
  <td>1-1</td>
  <td>1-2</td>
  <td>1-3</td>
  </tr>
  <tr>
  <td>2-0</td>
  <td>2-1</td>
  <td>2-2</td>
  <td>2-3</td>
  </tr>
  </table>
  <br>
  </body>
  </html>



  如果只是想获取某个单元格中的值,那么像定位普通元素一样定位单元格即可

  from selenium import webdriver
  from time import sleep

  driver = webdriver.Chrome()
  driver.get('C:\\Users\\yangyl13\\Desktop\\my_html.html')
  ele=driver.find_element_by_id('CellWithId')
  print(ele.text)


  场景二:假如想输出表格中所有单元格的值呢?
  思路:先定位页面中的表格对象元素;然后在该表格中,通过tag name = 'tr'找所有行;最后在每行中,通过tag name = 'td'找所有单元格。
  from selenium import webdriver
  from time import sleep

  driver = webdriver.Chrome()
  driver.get('C:\\Users\\Desktop\\my_html.html')
  table = driver.find_element_by_xpath('/html/body/table[1]')
  rows = table.find_elements_by_tag_name('tr')
  cols = rows[0].find_elements_by_tag_name('td')
  for i in range(len(rows)):
        for j in range(len(cols)):
              cell = rows.find_elements_by_tag_name('td')[j]
              print(cell.text)

  driver.quit()


  框架
  ●frame一般用来设置页面布局,将整个页面分成规则的几块,每一块里面包含一个新页面;iframe用来在页面的任何地方插入一个新的页面。
  from selenium import webdriver
  from time import sleep
  import os

  driver = webdriver.Chrome()
  html_file = 'File:///' + os.getcwd() + os.sep + 'myhtml6_8.html'
  driver.get(html_file)
  driver.switch_to.frame('iframe1')  # 通过id切换
  # driver.switch_to.frame('name1')  # 通过name切换
  # driver.switch_to.frame(0) # 通过index切换
  driver.find_element_by_id('kw').send_keys('storm') # 尝试定位搜索框,输入文字
  sleep(2)
  driver.quit()


  先定位iframe这个元素,然后切换到目标元素。
  from selenium import webdriver
  from time import sleep
  import os

  driver = webdriver.Chrome()
  html_file = 'File:///' + os.getcwd() + os.sep + 'myhtml6_8.html'
  driver.get(html_file)
  ele = driver.find_element_by_xpath('//*[@id="another"]/iframe') # 定位iframe元素
  driver.switch_to.frame(ele) # 直接传递元素
  driver.find_element_by_id('kw').send_keys('storm')
  sleep(2)
  driver.quit()


  4种从[url=]Web[/url]页面切换到iframe的方法。
  ●通过id切换(iframe有id属性):driver.switch_to.frame('iframe1')。
  ●通过name切换(iframe有name属性,且唯一):driver.switch_to.frame('name1')。
  ●通过index切换(index从0开始,即0代表页面中第一个iframe):driver.switch_to.frame(0)。
  ●通过定位元素切换:driver.switch_to.frame(iframe_element)。
  ●总原则:想操作iframe里面的元素,就要先切换到这个iframe上,然后进行操作;想操作iframe外面的元素,就必须跳出这个iframe。对于嵌套的iframe,进去的时候一层层进,出来的时候可以一层层出,也可以直接跳到最外层。
  ●切换到父级iframe的方法:switch_to. parent_frame。
  ●切换到主窗口的方法:switch_to.default_content。
  JavaScript弹窗
  JavaScript弹窗有3种:Alert、Confirm、Prompt。
  这3种JavaScript弹窗其实都是input标签,type为按钮(button),都调用了onclick事件,只不过该事件实现的功能有简单和复杂之分,因此其操作类似。
  ●Alert弹窗:文字信息+确定按钮。
  ●Confirm弹窗:文字信息+确定按钮+取消按钮。
  ●Prompt弹窗:文字信息+文本框+确定按钮+取消按钮。
  Alert弹窗
  下方代码用来准备一个包含Alert弹窗的页面。
  <!DOCTYPE html>
  <html lang="en">
  <head>
      <meta charset="UTF-8">
      <title>Alert学习</title>
  </head>
  <body>
  <h2>Alert Test</h2>

  <script type="text/javascript">
  function showAlert(){
      alert(document.f1.t1.value);
  }
  </script>
  <form name="f1">
      <input type="text" name="t1" value="Alert Message"><br><br>
      <input type="button" name="b1" value="Click For Alert"><br>
  </form>
  </body>
  </html>



  from selenium import webdriver
  from time import sleep

  driver = webdriver.Chrome()
  driver.get('C:\\Users\\yangyl13\\Desktop\\my_html.html')
  driver.find_element_by_name('b1').click()#点击按钮
  sleep(1)
  print(driver.switch_to.alert.text)#打印alert的text
  driver.switch_to.alert.accept()#点击alert弹窗的确定按钮
  sleep(2)
  driver.quit()


  confirm弹窗
  html示例:
  <!DOCTYPE html>
  <html lang="en">
  <head>
      <meta charset="UTF-8">
      <title>Confirm学习</title>
  </head>
  <body>
  <h4>Confirm Test</h4>

  <script type="text/javascript">
  function showConfirm(){
      var t1 = document.f1.t1;
      if (confirm("Some question?")){
           t1.value = "oked";
      }else{
           t1.value = "canceled";
      }
  }
  </script>
  <form name="f1">
      <input type="button" name="b1" value="Click For Confirm"><br><br>
      <input type="text" name="t1">
  </form>
  <br>
  </body>
  </html>

  from selenium import webdriver
  from time import sleep

  driver = webdriver.Chrome()
  driver.get('C:\\Users\\yangyl13\\Desktop\\my_html.html')
  driver.find_element_by_name('b1').click()#点击按钮
  sleep(1)
  print(driver.switch_to.alert.text)#打印confirm的text
  # driver.switch_to.alert.accept()#点击confirm弹窗的确定按钮
  driver.switch_to.alert.dismiss()#点击confirm的取消按钮
  sleep(2)
  driver.quit()


  prompt弹窗

  from selenium import webdriver
  from time import sleep

  driver = webdriver.Chrome()
  driver.get('C:\\Users\\yangyl13\\Desktop\\my_html.html')
  driver.find_element_by_name('b1').click() # 单击按钮打开Prompt弹窗
  sleep(1)
  print(driver.switch_to.alert.text) # 输出Prompt弹窗文字
  driver.switch_to.alert.send_keys('storm')
  sleep(3)
  driver.switch_to.alert.accept() # 单击Prompt弹窗中的"确定"按钮
  sleep(2)
  driver.find_element_by_name('b1').click() # 单击按钮打开Prompt弹窗
  sleep(1)
  driver.switch_to.alert.send_keys('shadow')
  sleep(1)
  driver.switch_to.alert.dismiss()
  sleep(2)
  driver.quit()


  这里有个问题,就是send_keys没有输入到prompt的文本框里。
  ●使用开发者工具无法查看到JavaScript弹窗中的元素,也就是说Alert弹窗是不属于网页DOM树的,在弹窗中单击是没有反应的。
  ●在使用switch_to.alert.×××之前,首先要确认弹窗确实是JavaScript弹窗。由于Alert 弹窗不美观(样式不好修改),在项目中经常会使用其他类型的弹窗。
  非JavaScript弹窗
  JavaScript弹窗虽然使用起来很方便,但支持的功能过于简单,某些情况下很难满足项目中的需求,因此还可能会使用其他类型的弹窗。
  (1)[url=]Windows[/url][url=]浏览器[/url]弹窗单击某个链接之后可能会打开一个新的浏览器弹窗,注意该弹窗跟之前的弹窗是平行关系,有自己的地址栏、最大化按钮、最小化按钮等,这个很容易分辨。而Alert弹窗更类似父子关系,或者叫从属关系,Alert必须依托于某一个弹窗。对于Windows浏览器弹窗,我们只需要通过窗口句柄切换到目标窗口,然后操作即可。
  (2)div弹窗div弹窗是通过网页元素构造成的弹窗。这种弹窗一般比较花哨且内容比较多,可以使用开发者工具查看元素内容。
  对于这类弹窗,将其视为普通元素去定位就好了。
  ◆注意事项在处理弹窗类元素的时候,需要做好元素是否已经加载的判断,避免由于网络等原因造成弹窗加载慢、元素定位不到等问题。
  日期时间控件
  <!DOCTYPE html>
  <html lang="en">
  <head>
      <meta charset="UTF-8">
      <title>日期时间控件</title>
  </head>
  <body>
  <input type="date" name="name1" id="id1">
  </body>
  </html>


  日期时间控件的外观虽然多种多样,但使用浏览器开发者工具查看,可以发现它就是一个input框。对于input框,我们是不是可以像普通文本框一样直接输入日期。
  from selenium import webdriver
  from time import sleep

  driver = webdriver.Chrome()
  driver.get('C:\\Users\\yangyl13\\Desktop\\my_html.html')
  sleep(2)
  driver.find_element_by_tag_name('input').send_keys('002020/06/06')
  sleep(5)
  driver.quit()


  ◆注意事项
  ●日期时间控件本身功能是否健全,需要人工去验证,自动化模拟单击实现成本太高(实际上,如果用的是标准化的日期时间控件,已经有大把的团队验证过其功能的健全性了)。
  ●自动化一般不验证日期时间控件的功能,只需要模拟输入,然后验证其他功能即可(自动化不是万能的,又或者说“物尽其用”即可)。
  ●有些日期时间控件有readonly属性,在使用send_keys方法之前,我们就需要做点“准备工作”了
  文件下载
  <!DOCTYPE html>
  <html lang="en">
  <head>
      <meta charset="UTF-8">
      <title>文件下载</title>
  </head>
  <body>
  <a href="storm.rar" download="storm.rar">下载</a>
  </body>
  </html>


  下载的本质就是一个<a>标签,有点类似链接,点击即可。
  如何下载到指定路径?
  from selenium import webdriver
  from time import sleep
  import os

  chromeOptions = webdriver.ChromeOptions() # 定义变量,存储Chrome浏览器的设置项
  prefs = {"download.default_directory": "D:\\A\\"}  # 指定默认下载路径
  chromeOptions.add_experimental_option("prefs", prefs) # 将prefs定义的下载路径应用于浏览器设置
  driver = webdriver.Chrome(chrome_options=chromeOptions) # 以自定义的设置项启动浏览器
  html_file = 'File:///' + os.getcwd() + os.sep + 'myhtml6_13.html'
  driver.get(html_file)
  sleep(2)
  driver.find_element_by_tag_name('a').click()
  sleep(5)
  driver.quit()


  如何验证确实下载了文件呢?
  from selenium import webdriver
  from time import sleep
  import os

  if os.path.exists("D:\\A\\storm.rar"):   # 先判断文件是否存在
        os.remove("D:\\A\\storm.rar")      # 如果存在则删除

  chromeOptions = webdriver.ChromeOptions() # 定义变量,存储Chrome浏览器的设置项
  prefs = {"download.default_directory": "D:\\A\\"}  # 指定默认下载路径
  chromeOptions.add_experimental_option("prefs", prefs) # 将prefs定义的下载路径应用于浏览器设置
  driver = webdriver.Chrome(chrome_options=chromeOptions) # 以自定义的设置项启动浏览器
  html_file = 'File:///' + os.getcwd() + os.sep + 'myhtml6_13.html'
  driver.get(html_file)
  sleep(2)
  driver.find_element_by_tag_name('a').click()
  sleep(5)  # 等待下载完成,然后再去判断文件是否存在
  if os.path.exists("D:\\A\\storm.rar"): # 判断文件是否存在
        print("文件下载成功")
  driver.quit()


  如何比对下载的文件?MD5值。
  文件上传
  在实际项目中,我们遇到的上传按钮大体上可以分为两种:一种是input控件,另外一种是通过js、flash等实现的且较复杂的非input控件。
  input控件
  <!DOCTYPE html>
  <html lang="en">
  <head>
      <meta charset="UTF-8">
      <title>文件上传学习</title>
  </head>
  <body>
  <form name="form1" action="fileUpload.php" method="post" enctype="multipart/form-data">
  <label for="file">File:</label>
  <input type="file" name="file" id="file" />
  </form>
  </body>
  </html>


  对于“input类型文件上传”功能,我们可以通过“send_keys”+“文件”的方式跳过对文件选择弹窗的操作。要知道这个文件选择弹窗是Windows弹窗,而WebDriver的操作范围是浏览器,我们是无法让其控制Windows弹窗的。
  from selenium import webdriver
  from time import sleep

  driver = webdriver.Chrome()
  driver.get('C:\\Users\\yangyl13\\Desktop\\my_html.html')
  sleep(2)
  driver.find_element_by_id('file').send_keys("C:\\Users\\yangyl13\\Desktop\\test.txt")
  sleep(2)
  driver.quit()


  selenium不支持上传多个文件。
  非input 型上传控件
  对于非input型上传控件,就不能使用send_keys取巧了。这类上传控件种类众多,有用a标签的、有用div的、有用button的、有用object的,我们没有办法直接在网页上处理这些上传操作。唯一的办法就是打开操作系统弹窗,再想办法去处理弹窗。而对于操作系统的弹窗,其涉及的层面已经不是Selenium能解决的了,怎么办?
  很简单,用操作系统层面的操作去处理,到这里我们基本找到了处理问题的思路。大致有以下几种方案。
  ●AutoIt,借助外力,我们去调用其生成的“.au3”或“.exe”文件。
  ●Python pywin32库,识别弹窗句柄,进而处理弹窗。
  ●SendKeys库。
  注意:当单击type=file的input类型的元素时会报错。
  遇到上传文件控件时,看看其是否是input型。如果是,那么恭喜你,可以用send_keys解决。如果碰到了div型的控件,用AutoIt处理也不难。如果还想验证能否同时上传多个文件,那么只能使用pywin32库来处理。


作者: oliver.tang    时间: 2023-2-28 14:05
ding




欢迎光临 51Testing软件测试论坛 (http://bbs.51testing.com/) Powered by Discuz! X3.2