51Testing软件测试论坛

 找回密码
 (注-册)加入51Testing

QQ登录

只需一步,快速开始

微信登录,快人一步

手机号码,快捷登录

查看: 723|回复: 1
打印 上一主题 下一主题

[原创] Selenium-常见控件操作之Web自动化(下)

[复制链接]
  • TA的每日心情
    无聊
    昨天 09:05
  • 签到天数: 1023 天

    连续签到: 2 天

    [LV.10]测试总司令

    跳转到指定楼层
    1#
    发表于 2022-12-22 13:41:59 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
     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库来处理。

    分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
    收藏收藏
    回复

    使用道具 举报

    本版积分规则

    关闭

    站长推荐上一条 /1 下一条

    小黑屋|手机版|Archiver|51Testing软件测试网 ( 沪ICP备05003035号 关于我们

    GMT+8, 2024-9-25 00:34 , Processed in 0.069372 second(s), 23 queries .

    Powered by Discuz! X3.2

    © 2001-2024 Comsenz Inc.

    快速回复 返回顶部 返回列表