草庐IT

UI自动化测试之selenium工具(浏览器窗口的切换)

锦都不二 2023-07-17 原文

         目录

前言

方法

实例

①示例1

②示例2

附加知识

结语


前言

1、在浏览网页的时候,有时点击一个链接或者按钮,会弹出一个新的窗口。这类窗口也被称之为句柄(一个浏览器窗口的唯一标识符,通过句柄实现不同浏览器窗口之间的切换),在我们手动控制浏览器的时候,产生新的句柄时浏览器会自动的帮我们跳转到最新的句柄处(鼠标聚焦于最新打开的浏览器窗口)。

2、在UI自动化的过程中,代码并不会默认自动的跳转到最新的句柄处,需要代码去切换句柄也就是切换浏览器窗口。

3、使用Selenium工具进行 Web UI自动化测试,如果弹出新窗口时,没有对窗口进行切换,那么,WebDriver 对象 的焦点对应的,依然是旧窗口,后续的自动化操作,将继续在旧窗口中进行。所以我们需要使用代码来切换浏览器窗口。

方法

获取当前浏览器的所有窗口句柄

handles=driver.window_handles  # 返回值是一个列表

解释: WebDriver 对象 中有  window_handles 属性 ,返回一个列表,里面记录了当前浏览器所有的窗口句柄。【句柄:;浏览器对应窗口的 id】

②切换到最开始打开的窗口

driver.switch_to.window(handles[0])

解释:如果UI自动化操作的浏览器打开了多个窗口,那么获取到的列表的最后一个元素即为最新的浏览器窗口句柄。

③切换到最新打开的窗口

driver.switch_to.window(handles[-1])

④切换到倒数第二个打开的窗口

driver.switch_to.window(handles[-2])

⑤获取 WebDriver 对象 当前聚焦的浏览器窗口句柄

driver.current_window_handle() 

⑥验证 WebDriver 对象 的焦点是否聚焦在最新打开的浏览器窗口

# **先看下当前窗口url地址:**
 print(self.browser.current_url)
    
 # 打印所有的窗口 ['窗口ID1', '窗口ID2', '窗口ID3'] ==> 窗口句柄
 windows = self.browser.window_handles
 print(windows)
    
# 1 切换到最后的窗口
driver.switch_to.window(drivers[-1])
# 切换到最后的窗口后,打印下url,核对下是不是最后的窗口
print(driver.current_url)

 2 切换到第二个窗口
 # 先获取现在的窗口
 current_window = self.browser.current_window_handle
    
 # 获取第二个窗口的索引(由当前窗口索引+1)
 next_window_index = windows.index(current_window) + 1
    
 # 切换到第二个窗口
 self.browser.switch_to.window(windows[next_window_index])

⑦selenium工具浏览器窗口句柄切换API

实例

①示例1

1、手动操作浏览器打开打开赶集网:http://bj.ganji.com/,点击招聘求职按钮会发现右边多了一个窗口标签。

2、当我们用代码去执行点击的时候,发现界面上出现两个窗口,如下图这种情况就是浏览器的多窗口了。

【注意】:手动操作浏览器时呈现的效果是两个标签,而脚本执行时却出现了两个页面的原因:(默认脚本执行是不加载任何配置的)【手工点击是在浏览器中浏览器默认设置了新窗口打开方式为标签,而浏览器中的默认打开新窗口的方式为出现一个新页面】

3、获取当前浏览器的窗口句柄

①元素有属性,浏览器的窗口其实也有属性的,只是你看不到,浏览器窗口的属性用句柄(handle)来识别。

②人为操作的话,可以通过眼睛看,识别不同的窗口点击切换。但是脚本没长眼睛,它不知道你要操作哪个窗口,这时候只能句柄来判断了。

③获取当前页面的句柄方法: driver.current_window_handle 

4、获取所有的浏览器句柄

①定位赶集网招聘求职按钮,并点击

②点击后,获取当前所以的句柄: driver.window_handles 

5、切换句柄

方法一:

    1.循环判断是否与首页句柄相等。

    2.如果不等,说明是新页面的句柄。

    3.获取的新页面句柄后,可以切换到新打开的页面上。

    4.打印新页面的title或者url,看浏览器窗口是否切换成功。

方法二:

直接在获取到的浏览器句柄列表中取最后一个元素,然后代码中切换到这个句柄id。

6、关闭新窗口,切回主页 

    1.打开新页面后,其实只想验证新页面跳转对不对,这里可以做个简单的验证,获取当前页面的title验证

    2.验证完后切关闭新窗口

    3.切回句柄到首页

    4.打印当前页面的句柄,看是否切换到首页了

②示例2

#coding = utf-8


import unittest
from selenium import webdriver
from time import sleep
from selenium.webdriver.common.action_chains import ActionChains


class Truelogin(unittest.TestCase):
    @classmethod
    def setUpClass(cls):
        print("***开始进行登录***")

    def setUp(self):
        # 屏蔽自动化受控提示 && 开发者提示
        self.option = webdriver.ChromeOptions()
        self.option.add_experimental_option("excludeSwitches", ['enable-automation', 'load-extension'])
        # 屏蔽'保存密码'提示框
        self.prefs = {}
        self.prefs["credentials_enable_service"] = False
        self.prefs["profile.password_manager_enabled"] = False
        self.option.add_experimental_option("prefs", self.prefs)
        # 打开谷歌浏览器
        self.driver = webdriver.Chrome(options=self.option)
        # 窗口最大化
        self.driver.maximize_window()
        sleep(5)

        #打开登录界面
        self.driver.get("ur")
        sleep(5)
    def testcloudAIlogin(self):
        self.driver.switch_to.frame(0)
        self.driver.find_element_by_xpath("//input[@id='username']").send_keys("用户名")
        self.driver.find_element_by_xpath("//input[@id='password']").send_keys("密码*")
        self.driver.find_element_by_xpath("//div[@class='button']/a[@id='loginbtn']").click()
        sleep(5)
        # 获取当前窗口的句柄
        self.window1 = self.driver.current_window_handle
        #搜索框输入系统名称
        self.driver.find_element_by_css_selector("input#search-keyword").send_keys("名称")
        sleep(2)
        ActionChains(self.driver).move_to_element(self.driver.find_element_by_xpath("//a/span[text()='名称']")).perform()
        self.driver.find_element_by_xpath("//a/span[text()='名称']").click()
        sleep(10)

        # 获取所有窗口的句柄
        self.all_handles = self.driver.window_handles
        sleep(5)
        #切换到新窗口
        for self.handle in self.all_handles:
            if self.handle != self.window1:
                self.driver._switch_to.window(self.handle)
                print("***这是新窗口***")
        sleep(2)
        self.assertEqual("用户名",self.driver.find_element_by_xpath("//div[text()='用户名']").text)
        sleep(2)
        print("***登录完成***")

    def tearDown(self):
        self.driver.quit()
        print("***测试用例结束***")


    @classmethod
    def tearDownClass(cls):
         print("***一次测试结束***")

    if __name__ == '__main__':
        unittest.main()

附加知识

在web页面上经常有点击一个页面后,另外打开一个新窗口,是因为html中 a标签 的 target属性 是 _bank 。

在HTML中a标签target属性目标的四个参数的用法:

1、target="_self"表示:将链接的画面内容,显示在目前的视窗中。(内定值) 。 即:同窗口打开。

2、target="_parent"表示:将链接的画面内容,当成文件的上一个画面。即:当前窗口打开。

3、target="_top"表示:将框架中链接的画面内容,显示在没有框架的视窗中(即除去了框架)。即:顶端打开窗口。

4、target="_blank"表示:将链接的画面内容,在新的浏览视窗中打开。即:打开新窗口。

注意:当网页没有框架时,target="_self"和target="_parent"以及target="_top"三种方式的显示方式几乎相同。

结语

这篇贴子到这里就结束了,最后,希望看这篇帖子的朋友能够有所收获。

如果你觉得文章还不错,请大家 点赞、分享、留言 下,因为这将是我持续输出更多优质文章的最强动力!

有关UI自动化测试之selenium工具(浏览器窗口的切换)的更多相关文章

  1. ruby-on-rails - 使用 Ruby on Rails 进行自动化测试 - 最佳实践 - 2

    很好奇,就使用ruby​​onrails自动化单元测试而言,你们正在做什么?您是否创建了一个脚本来在cron中运行rake作业并将结果邮寄给您?git中的预提交Hook?只是手动调用?我完全理解测试,但想知道在错误发生之前捕获错误的最佳实践是什么。让我们理所当然地认为测试本身是完美无缺的,并且可以正常工作。下一步是什么以确保他们在正确的时间将可能有害的结果传达给您? 最佳答案 不确定您到底想听什么,但是有几个级别的自动代码库控制:在处理某项功能时,您可以使用类似autotest的内容获得关于哪些有效,哪些无效的即时反馈。要确保您的提

  2. ruby - i18n Assets 管理/翻译 UI - 2

    我正在使用i18n从头开始​​构建一个多语言网络应用程序,虽然我自己可以处理一大堆yml文件,但我说的语言(非常)有限,最终我想寻求外部帮助帮助。我想知道这里是否有人在使用UI插件/gem(与django上的django-rosetta不同)来处理多个翻译器,其中一些翻译器不愿意或无法处理存储库中的100多个文件,处理语言数据。谢谢&问候,安德拉斯(如果您已经在ruby​​onrails-talk上遇到了这个问题,我们深表歉意) 最佳答案 有一个rails3branchofthetolkgem在github上。您可以通过在Gemfi

  3. ruby - 使用 C 扩展开发 ruby​​gem 时,如何使用 Rspec 在本地进行测试? - 2

    我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当

  4. ruby-on-rails - Ruby on Rails with Haml - 如何从 erb 切换 - 2

    我正在从erb文件切换到HAML。我将hamlgem添加到我的系统中。我创建了app/views/layouts/application.html.haml文件。我应该只删除application.html.erb文件吗?此外,仍然有/public/index.html文件被呈现为默认页面。我想创建自己的默认index.html.haml页面。我应该把它放在哪里以及如何使系统呈现该文件而不是默认索引文件?谢谢! 最佳答案 是的,您可以删除任何已转换为HAML的View的ERB版本。至于你的另一个问题,删除public/index/h

  5. ruby - Ruby 的 Hash 在比较键时使用哪种相等性测试? - 2

    我有一个围绕一些对象的包装类,我想将这些对象用作散列中的键。包装对象和解包装对象应映射到相同的键。一个简单的例子是这样的:classAattr_reader:xdefinitialize(inner)@inner=innerenddefx;@inner.x;enddef==(other)@inner.x==other.xendenda=A.new(o)#oisjustanyobjectthatallowso.xb=A.new(o)h={a=>5}ph[a]#5ph[b]#nil,shouldbe5ph[o]#nil,shouldbe5我试过==、===、eq?并散列所有无济于事。

  6. ruby - RSpec - 使用测试替身作为 block 参数 - 2

    我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere

  7. ruby - Sinatra:运行 rspec 测试时记录噪音 - 2

    Sinatra新手;我正在运行一些rspec测试,但在日志中收到了一堆不需要的噪音。如何消除日志中过多的噪音?我仔细检查了环境是否设置为:test,这意味着记录器级别应设置为WARN而不是DEBUG。spec_helper:require"./app"require"sinatra"require"rspec"require"rack/test"require"database_cleaner"require"factory_girl"set:environment,:testFactoryGirl.definition_file_paths=%w{./factories./test/

  8. ruby-on-rails - 迷你测试错误 : "NameError: uninitialized constant" - 2

    我遵循MichaelHartl的“RubyonRails教程:学习Web开发”,并创建了检查用户名和电子邮件长度有效性的测试(名称最多50个字符,电子邮件最多255个字符)。test/helpers/application_helper_test.rb的内容是:require'test_helper'classApplicationHelperTest在运行bundleexecraketest时,所有测试都通过了,但我看到以下消息在最后被标记为错误:ERROR["test_full_title_helper",ApplicationHelperTest,1.820016791]test

  9. ruby - RuntimeError(自动加载常量 Apps 多线程时检测到循环依赖 - 2

    我收到这个错误:RuntimeError(自动加载常量Apps时检测到循环依赖当我使用多线程时。下面是我的代码。为什么会这样?我尝试多线程的原因是因为我正在编写一个HTML抓取应用程序。对Nokogiri::HTML(open())的调用是一个同步阻塞调用,需要1秒才能返回,我有100,000多个页面要访问,所以我试图运行多个线程来解决这个问题。有更好的方法吗?classToolsController0)app.website=array.join(',')putsapp.websiteelseapp.website="NONE"endapp.saveapps=Apps.order("

  10. ruby - 即使失败也继续进行多主机测试 - 2

    我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r

随机推荐