一天一个关于测试知识点,5分钟内讲解你最关心的软件测试问题,今天就接着来谈谈关于软件测试中的“API:操作API(二)”。
上一章节回顾 | API:操作API(一)
(5)等待(显示/隐私/强制等待)。
Selenium3.X等待包括显式等待,隐式等待与强制等待。
l 显式等待
显式等待的语法如下。
WebDriverWait(driver,timout,pool_frequency=0.5,ignored_exception=None)
其中。
l driver:浏览器驱动器。
l timeout :最长超时时间。
l pool_frequency :检测的间隔(步长)时间,默认0.5秒。
l ignored_exception :超时后的异常信息,默认情况抛出NoSuchElementException。
案例4-54:显式等待页面元素的出现。
from selenium import webdriver
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
…
element = WebDriverWait(driver,5,0.5).until(
EC.presence_of_element_located((By.ID,"J_LinkBasket")) )
这段代码的意思是:每隔0.5秒检查一下页面中id为"J_LinkBasket"的元素是否加载上来,如果在5秒钟内加载上来继续后续的操作,否则抛出NoSuchElementException。显示等待仅作用于单独的元素。可以通过presence_of_element_located进行定位,也可以通过其他方式进行定位,见表4-48。
案例4-55:显式等待标题是否包含特定元素。
element = WebDriverWait(self.driver,5,0.5).until(title_contains(("软件测试")))
l 隐式等待
在本节开始的Selenium测试用例的初始化操作中已经介绍的隐式等待。
语法:
driver.implicitly_wait(int seconds)
与显式等待不同的是,显示等待仅作用于单独的元素,而隐式等待作用于页面所有的元素。当元素在指定的描述内没有加载出来,继续等待,超过则抛出NoSuchElementException。
案例4-56:隐式等待5秒钟。
driver.implicitly_wait(5)
l 强制等待
理论上Selenium是不允许使用强制等待的,由于Selenium是一个开源框架,在Selenium的显隐式等待上存在着一定的缺陷,甚至有些浏览器不支持Selenium的显隐式等待,所以在程序中不得不仍旧使用强制等待。特别需要指出的是强制等待不是Selenium特有的,使用的是Python语言自带的等待函数。经常使用time类中的sleep方法进行强制等待,格式如下。
import time
…
time.sleep(5)
(6)多表单切换。
如果页面中存在着iframe或frame,对表单内的元素进行操作,必须先通过如下命令进入才可以操作。
语法:
driver.switch_to.frame("val")
其中Selenium程序首先找id是否为val的iframe或frame,如果不存在,在找name是否为val的iframe或frame。对于iframe或frame中没有id也没有name的情形,可以通过以下方法来实现。
element=driver.find_element_by_class_name("j_minilogin_iframe")
driver.switch_to.frame(element)
案例4-57:检查是否通过frame中的菜单进入某个页面。
from mydriver import drivers
class Check3testing(unittest.TestCase):
def setUp(self):
d = drivers()
self.driver=d.driver
self.driver.implicitly_wait(5)
self.driver.get("http://www.3testing.com")
def test_check3testing(self):
checktext = "小李"
self.driver.switch_to.default_content()#默认定位到主框架
self.driver.switch_to.frame("head")#切换到id为"introduce"的iframe
self.driver.find_element_by_id("introduce").click()#点击id为"introduce"的菜单
self.driver.switch_to.default_content()#返回主框架
self.assertEqual(self.driver.title,"小李个人介绍",msg="标题错误")//#判断是否进入正确的页面
def tearDown(self):
self.driver.quit()
在http://www.3testing.com首页中存在两个iframe。
<body>
<iframe id="head" src="include/head.htm" width="100%" height="350" scrolling="no" frameborder="0"></iframe>
…
<iframe id="button" src="include/button.htm" width="100%" height="120" scrolling="no" frameborder="0"></iframe>
</body>
</html>
id="head"的frame为页面的头部菜单栏,id="button"的frame为页面的尾部菜单栏。现在要通过点击头部菜单栏的id为"introduce"的菜单进入“我的介绍”,进入后通过判断主页面的title标记来判断是否进入正确的页面。如果没有self.driver.switch_to.frame("head")语句,程序见找不到id为"introduce"的菜单,读者可以亲自试验一下。
(7)切换新窗口。
尽管切换新窗口代码相对比较长,但是其比较固定,建议将其封装在一个公共类中。
案例4-58:打开新窗口后关闭旧窗口。
class util:
def switch_windows_and_Close(self,driver,current_windows): #driver为当前驱动,current_windows为切换前的窗口句柄
all_handles = driver.window_handles#获取所有窗口的句柄
for handle in all_handles://遍历所有窗口句柄
if handle != current_windows:#如果遍历句柄不是当前窗口句柄,则为新窗口
driver.switch_to_window(handle) #尝试是否可以进入
break
for handle in all_handles:#遍历所有窗口句柄
if handle == current_windows:#如果遍历句柄是当前窗口句柄,则为老窗口
driver.switch_to_window(handle) #进入老窗口
driver.close()#关闭老窗口
break
for handle in all_handles:#遍历所有窗口句柄
if handle != current_windows:#如果遍历句柄不是当前窗口句柄,则为新窗口
driver.switch_to_window(handle)#返回新窗口
break
打开新窗口后关闭旧窗口,首先要进入新窗口,确保新窗口是否被打开,然后返回旧窗口,关闭旧窗口,在这里特别需要注意的是,关闭旧窗口后,必须再次返回新窗口,否则当前窗口句柄会指向一个空指针,从而造成测试程序失败。
当然有时候要求打开就窗口而不需要关闭旧窗口,方法很简单,在上面的程序中去掉第二、第三个循环,也放在公共方法中,代码如下。
案例4-59:打开新窗口后不关闭旧窗口。
def switch_windows (self,driver,current_windows): #driver为当前驱动,current_windows为切换前的窗口句柄
all_handles = driver.window_handles#获取所有窗口的句柄
for handle in all_handles://遍历所有窗口句柄
if handle != current_windows: #如果遍历句柄不是当前窗口句柄,则为新窗口
driver.switch_to_window(handle) #尝试是否可以进入
break
下面来看一下测试京东查询并进入第一个商品详情页面的测试代码。
案例4-60:京东查询并进入第一个商品详情页面。
from util import drivers,util
def setUp(self):
d = drivers()
self.driver=d.driver
self.driver.implicitly_wait(5)
self.driver.get("https://www.jd.com/")
def test_CheckJingdong(self):
Util=util()
self.driver.find_element_by_id("key").clear()#清空查询输入框
self.driver.find_element_by_id("key").send_keys('巧克力') #输入查询内容
self.driver.find_element_by_class_name("button").click()#点击查询按钮
current_windows = self.driver.current_window_handle#获取当前窗口句柄
self.driver.find_element_by_class_name('p-tag').click()#点击第一个查询出来的商品,弹出新窗口
Util.switch_windows(self.driver,current_windows)#切换并且关闭当前窗口
element = WebDriverWait(self.driver,5,0.5).until(EC.presence_of_element_located((By.ID,"key")))#显示等待
self.assertIn"巧克力",self.driver.title,msg="没有找到巧克力")#进行断言
def tearDown(self):
self.driver.quit()
(8)窗口滚动操作。
可以执行JavaScript来实现窗口滚动的功能,但是没有检查点,所以这里没有断言。
案例4-61:窗口滚动操作。
def CheckStroll (self):
inputstring='大数据'
self.driver.find_element_by_id("kw").clear()
self.driver.find_element_by_id("kw").send_keys(inputstring)
self.driver.find_element_by_id("su").click()
time.sleep(1)
try:
#移动到窗口最下方
self.driver.execute_script("window.scrollTo(100,document.body.scrollHeight);")
time.sleep(3)
#scrollIntoView(true):移动到屏幕中间;scrollIntoView(false):移动到屏幕底部
self.driver.execute_script("document.getElementById('1').scrollIntoView(true);")
time.sleep(3)
#下移400像素
self.driver.execute_script("window.scrollBy(0,400);")
time.sleep(3)
except:
print(traceback.print_exc))
(9)下拉条(Select)操作。
对下拉条进行操作,需要调用Select类:from selenium.webdriver.support.ui import Select。具体操作见表4-49。
案例4-62:下拉条(Select)操作。
对于下面的HTML。
<body>
<form name="form" action="">
<select name="phones" id="ph" multiple> <option value="华为">华为</option>
<option value="三星">三星</option>
<option value="中兴">中兴</option>
<option value="小米">小米</option>
</select><br>
<button onclick="javascript:selectinfo()">选择提示</button>
</form>
</body>
</html>
如下Selenium测试代码。
def test_CheckSelect(self):
self.driver.find_element_by_css_selector('#ph > option:nth-child(4)').click()#通过CSS定位到小米选项,注意这里从1开始,所以是4
#se= self.driver.find_element_by_name('phones') #定位到select
#Select(se).select_by_visible_text('小米'#通过text定位到小米选项
#Select(se).select_by_value('小米') #通过值定位到小米选项
#Select(se).select_by_index(3) #通过索引定位到小米选项,注意这里从0开始,所以是3
self.driver.find_element_by_id('button').click()#点击按钮
text=self.driver.switch_to_alert().text #获取弹窗框里面的文字
self.assertEqual(text,"我选择的是小米") #断言
(10)单选按钮(Radio)操作。
通过elenium.is_selected()来判断单选按钮是否被选择。
案例4-63:单选按钮(Radio)操作。
对于下面的HTML。
<h4>单选:性别</h4>
<form>
<label value="radio">男</label>
<input name="sex" value="male" id="boy" type="radio"><br>
<label value="radio1">女</label>
<input name="sex" value="female" id="girl" type="radio">
</form>
如下Selenium测试代码。
def test_CheckRadio (self):
sexRadio = self.driver.find_element_by_xpath("//input[@value='male']")
sexRadio.click()# 点击选择“男”选项
self.assertTrue(sexRadio.is_selected(),"男单选框未被选中!")# 断言“男”单选框选中