一:selenium 实现ui自动化测试
什么是selenium自动化?使用ui自动化实现代码模拟人的操作。(点击,输入,滑动,下拉选择,浏览)
二:selenium实现环境搭建
pip install selenium==3.14
安装驱动和对应浏览器对应起来。
selenium的定位方法:
三 selenium提供了八种元素定位的方法
id:元素id属性值,如果id 属性唯一,那么就可以定位到,如果id是一串字母或者数值,则不能进行使用。有可能会是动态的id
name 定位:根据name的属性值来定位,但是如果name的属性值在页面不唯一,就无法进行定位。
classname:class 属性对应的值:
tagname:标签名查找,一般使用不了。
link text:模糊定位 ,一般使用不了
xpath: / 代表直接的子节点 , // 后代节点
css selector#根据标签以及标签的属性进行定位
partial link text:一般不要使用
from selenium import webdriver
driver=webdriver.Chrome("C:/Users/baocomputer/tools/chromedriver_win32/chromedriver.exe")
driver.maximize_window()
#打开具体的网页
driver.get("https://www.baidu.com/?tn=65081411_oem_dg")
#元素定位,定为搜索框
#driver.find_element_by_css_selector('input[name="wd"]').send_keys("昕诺飞公司")
driver.find_element_by_xpath('//*[@id="kw"]').send_keys("昕诺飞公司")
driver.find_element_by_xpath("//input[@name='wd']").send_keys("昕诺飞公司")
#driver.find_element_by_css_selector('input[value]').click()
"""
#id定位:
driver.find_element_by_id("id 属性的值")
#name定位
driver.find_element_by_name("name 属性值")
#class name 定位
driver.find_element_by_class_name("class 属性值")
# tagname 定位
driver.find_element_by_tag_name("tag 属性值")
#link_text定位
driver.find_element_by_link_text("文本查询")
#xpath 定位
driver.find_element_by_xpath("基于xpath方法是实现")
#css selector 定位
driver.find_element_by_css_selector("css属性")
#partial link text
driver.find_element_by_partial_link_text("模糊查询")
"""
四:webdriver的常见的方法:
1 元素的点击,元素的清除 ,元素的再次输入
元素清除:clear()
元素的输入:send_keys()
元素点击:click()
from selenium import webdriver
import time
driver= webdriver.Chrome("C:/Users/baocomputer/tools/chromedriver_win32/chromedriver.exe")
driver.maximize_window()
#设置隐式等待
driver.implicitly_wait(10)
#打开浏览器
driver.get("http://www.baidu.com")
#id定位属性
search_element = driver.find_element_by_id('kw')
search_element.send_keys("九阳真经")
time.sleep(2)
#先将之前搜索的清除
search_element.clear()
time.sleep(1)
#再次输入新的内容
search_element.send_keys('前孔达克洛伊')
#点击操作
driver.find_element_by_id('su').click()
2 submit提交方法
submit()方法用于提交表单数据,搜索框输入关键字之后的回车操作,就可以用该方法来模拟。
import time
from selenium import webdriver
driver = webdriver.Chrome()
#driver.maximize_window()
driver.implicitly_wait(10)
url = "https://www.baidu.com"
driver.get(url=url)
search_element = driver.find_element_by_id('kw')
#输入内容
#search_element.send_keys("九阳真经")
#对于表单的提交方法:使用sunmit提交
#search_element.submit()
#返回搜索框的大小
#print(search_element.size)
2获取文本信息
#获取百度一下文本按钮的文本信息
# time.sleep(2)
# button_element = driver.find_element_by_id("su").text
# print(button_element)
无法进行获取
# #获取hao123文本
# ele = driver.find_element_by_css_selector("a[href='https://www.hao123.com?src=from_pc']").text
# print(ele)
注意:我们获取文本信息的内容,获取标签中间的内容,如果是标签属性的值,使用text无法获取。
3获取标签内部的属性值
获取标签内部的属性值:get_attribute(name):获取属性值
button_selement = driver.find_element_by_id('su').get_attribute("value")
print(button_selement)
4查看页元素是否可见存在
#is_display():设置元素是否可见,在页面上是否显示该元素,如果能看到,返回true,反之false
button_selement = driver.find_element_by_id('su')
print(button_selement.is_displayed())
五 鼠标事件
在webDriver中,关于鼠标操作的方法封装在ActionChains类提供。Actionchains类提供了鼠标操作的常用方法
perform():执行了ActionChains中存储的行为
context_click():右击
double_click():双击
drag_and_drop():拖动
move_to_element():鼠标悬停
"""
鼠标事件
"""
from selenium import webdriver
import time
#导入ActionChains
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(10)
url = "https://www.baidu.com"
driver.get(url=url)
time.sleep(2)
#定位到设置
button_ele = driver.find_element_by_id("s-usersetting-top")
#鼠标悬停
#ActionChains(打开的浏览器对象).move_to_element(鼠标到定位的位置).perform()
#perform 执行前面的操作
ActionChains(driver).move_to_element(button_ele).perform()
六 键盘事件
1 模拟键盘事件 删除输入文本的某一个字
需要导入Keys这个类
from selenium import webdriver
import time
#导入ActionChains
#使用keys 这个类去调用键盘
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(10)
url = "https://www.baidu.com"
driver.get(url=url)
#定位到搜索框
search_ele = driver.find_element_by_id("kw")
#输入内容
search_ele.send_keys("seleniumm")
time.sleep(1)
#删除多余的m,调用删除键
search_ele.send_keys(Keys.BACK_SPACE)
search_ele.clear()
time.sleep(2)
search_ele.send_keys('python')
search_ele.send_keys(Keys.ENTER)
常用的键盘操作:
BackSpace 删除键
Space 空格键
Tab 制表键
ESC: 回退键
Enter :回车键
全选:ctrl+A
复制:Ctrl + C
粘贴:ctrl+V
设置元素等待
"""
设置元素等待
强制等待:time.sleep()
显示等待:显示等待的加载出来,需要是给每一个元素单独设置。偶尔有一个元素由于业务原因事件比较长,单独设置显示等待。
隐式等待:driver.implicitly_wait() 判断某个元素有没有加载出来,最大时间是10S,如果在第4s就就加载出来,那就往后面继续执行。没有加载
出来就会报错
"""
#显示等待:使得WebDriver等到某个元素条件成立时,继续执行,否则在达到最长时间时候抛出异常
from selenium import webdriver
#在显示等待的时候,元素定位方式需要使用by加载
from selenium.webdriver.common.by import By
#设置显示等待
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome()
driver.maximize_window()
#隐式等待
driver.implicitly_wait(10)
#显示等待:
driver.get("https://www.baidu.com")
#定位搜素框
search_box = driver.find_element_by_id('kw')
"""
WebDriver(浏览器,最大超时时间,轮询时间)
presence_of_element_located()#接受的元素定位方式和具体的表达式,使用元组的形式传入
By.ID :值得就是find_element_by_id
"""
#定位搜索框
search_obj = WebDriverWait(driver, 5, 0.5).until(EC.presence_of_element_located((By.ID, 'kw')))
search_obj.send_keys('shell编程')
#使用commit 方法进行提交
#search_obj.submit()
#键盘操作调用keys
search_obj.send_keys(Keys.ENTER)
窗口切换
关于窗口切换,模拟就是窗户切换,模拟浏览器进行操作。
浏览器打开会有一个叫句柄的概念,是唯一的:
方式一:我们进行页面窗口切换的时候,我们需要保存当前的页面的句柄信息,当打开第二个页面的句柄信息时候
通过driver.window_handles 方法获取当前所有句柄信息,该信息是以列表的形式存储。我们通过循环迭代这个列表,获取我们即将打开的句柄信息,然后模拟浏览器进行新页面的操作。
设置元素等待
强制等待:time.sleep()
显示等待:显示等待的加载出来,需要是给每一个元素单独设置。偶尔有一个元素由于业务原因事件比较长,单独设置显示等待。
隐式等待:driver.implicitly_wait() 判断某个元素有没有加载出来,最大时间是10S,如果在第4s就就加载出来,那就往后面继续执行。没有加载
出来就会报错
#显示等待:使得WebDriver等到某个元素条件成立时,继续执行,否则在达到最长时间时候抛出异常
import time
from selenium import webdriver
#在显示等待的时候,元素定位方式需要使用by加载
from selenium.webdriver.common.by import By
#设置显示等待
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome()
driver.maximize_window()
#隐式等待
driver.implicitly_wait(10)
#打开网页
driver.get("https://www.baidu.com")
#定位搜素框
search_box = driver.find_element_by_id('kw')
search_box.send_keys('shell')
search_box.send_keys(Keys.ENTER)
windowhandle = driver.current_window_handle
print(windowhandle)
#定位一下百度百科
driver.find_element_by_xpath('//div[@id=3]//h3/a').click()
time.sleep(3)
#获取当前浏览器所有的句柄
all_handle = driver.window_handles
#根据句柄进行切换
for head in all_handle:
if head != windowhandle:
driver.switch_to.window(head)
#在切换后的句柄页面点击新的操作进行保存:
driver.find_element_by_xpath('/html/body/div[3]/div[1]/div[2]/div/div[1]/dl/dd/span[2]/a[4]').click()
方式二:
我们利用下标来做窗口切换。
import time
from selenium import webdriver
#在显示等待的时候,元素定位方式需要使用by加载
from selenium.webdriver.common.keys import Keys
driver = webdriver.Chrome()
driver.maximize_window()
#隐式等待
driver.implicitly_wait(10)
#打开网页
driver.get("https://www.baidu.com")
#定位搜素框
search_box = driver.find_element_by_id('kw')
search_box.send_keys('shell')
search_box.send_keys(Keys.ENTER)
#定位一下百度百科
driver.find_element_by_xpath('//div[@id=3]//h3/a').click()
time.sleep(3)
handles = driver.window_handles
print(handles)
driver.switch_to.window(handles[-1])
#在切换后的句柄页面点击新的操作进行保存:
driver.find_element_by_xpath('/html/body/div[3]/div[1]/div[2]/div/div[1]/dl/dd/span[2]/a[4]/em').click()
handles_new = driver.window_handles
print(handles_new)
driver.switch_to.window(handles_new[-1])
driver.find_element_by_xpath("/html/body/div[2]/div[2]/div[2]/div[3]/ul/li[5]/div[1]/a").click()
表单切换
关于iframe表单的切换
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
import time
#创建对象:
driver = webdriver.Chrome()
#windows最大化
driver.maximize_window()
url = 'https://www.baidu.com'
url1 = 'https://mail.163.com/'
driver.get(url=url1)
#表单切换
"""
iframe 标单切换
driver.switch_to.frame() 默认可以写标签iframe 的id和name属性的值,前提是id和name 要唯一,不能是动态变换。
还可以通过其他的定位方式定位到iframe标签,然后定位到iframe 标签对象传入到switch_to.frame()对象中
"""
#先通过xpath方法进行定位
iframe = driver.find_element_by_xpath("//div[@id='loginDiv']/iframe")
driver.switch_to.frame(iframe)
time.sleep(3)
#当id是一串无序的字符串或者数字的时候,我们使用id属性定位无法进行定位。
#定位iframe 标签定位:需要解决动态标签问题,同时需要解决iframe 标签定位。
element_email = driver.find_element_by_css_selector('input[name="email"]')
element_email.send_keys('baoqiwei0130')
element_password = driver.find_element_by_css_selector('input[name="password"]')
element_password.send_keys('BQWWNJ11220311')
#点击登录按钮:
element_login = driver.find_element_by_id('dologin')
element_login.click()
#由于上面登录时候邮箱密码在内层子页面,,通过iframe 已经切换进去了,需要切换到最外层方法
driver.switch_to.default_content()
# 点击vip
driver.find_element_by_css_selector("a[href='https://v.mail.163.com/?utm_source=163loginnav']").click()
警告窗问题处理:
警告框处理,就是一些弹窗提醒:
普通的alert 弹窗处理:
from selenium import webdriver
import os
import time
driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(10)
#对于静态网页:我们基于os模块获取地址,做一个地址的拼接
file_path = "file:///" + os.path.abspath("弹窗页面.html")
driver.get(file_path)
#操作普通alert弹窗
#进行元素定位
driver.find_element_by_css_selector('input[onclick="alterbutton()"]').click()
#切换到alert弹窗
alert_obj = driver.switch_to.alert
#获取弹窗的文本信息
print(alert_obj.text)
time.sleep(3)
#点击弹窗的确认按钮
alert_obj.accept()
confirmButtton 弹窗处理
from selenium import webdriver
import os
import time
driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(10)
file_path = "file:///" + os.path.abspath("弹窗页面.html")
driver.get(file_path)
driver.find_element_by_css_selector('input[onclick="confirmButtton()"]').click()
#进入alert弹窗
confirm_obj = driver.switch_to.alert
print(confirm_obj.text)
time.sleep(3)
# #点击确定按钮
# confirm_obj.accept()
#点击取消
confirm_obj.dismiss()
promptButton 弹窗操作文本信息处理的弹窗
from selenium import webdriver
import os
import time
driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(10)
file_path = "file:///" + os.path.abspath("弹窗页面.html")
driver.get(file_path)
driver.find_element_by_css_selector('input[onclick="promptButton()"]').click()
#进入alert弹窗(需要切到弹窗)
prompt_obj = driver.switch_to.alert
time.sleep(2)
#弹窗输入内容
prompt_obj.send_keys('python')
time.sleep(1)
#点击确定按钮
prompt_obj.accept()
下拉选择框的处理:
自己创建一个下拉选择框
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>下拉选择框</title>
</head>
<body>
<select name="myselect">
<!--value属性的值,下拉选择选项一般是唯一的-->
<option value="o1">谷歌搜素</option>
<option value="o2">百度搜素</option>
<option value="o3">搜狗搜素</option>
<option value="o4">搜狐搜素</option>
<option value="o5">bing搜素</option>
<option value="o6">360搜素</option>
</select>
</body>
</html>
定位搜素框,我们需要导入一个包:
下拉选项的定位方式:
索引定位
value属性定位
文本定位
from selenium.webdriver.support.ui import Select
from selenium import webdriver
import os
from selenium.webdriver.support.ui import Select
import time
driver = webdriver.Chrome()
driver.maximize_window()
driver.implicitly_wait(10)
file_path = "file:///" + os.path.abspath("下拉选择框.html")
driver.get(file_path)
#实例化一个对象,将定位的对象传入到实例对象里面
s1 = Select(driver.find_element_by_name('myselect'))
#选择具体的选项 选取方式:
# #方式1 :索引选择,索引从0 开始
# s1.select_by_index(3)
# #方式2 :通过value属性的值:
# s1.select_by_value('o4')
#方式3 文本定位属性
s1.select_by_visible_text('bing搜索')
文件上传
关于文件上传操作:
邮箱添加附件这个就是邮件上传最重要的进行元素定位
selenium执行js代码
浏览器的滚动条就是执行js代码实现
from selenium import webdriver
import time
driver = webdriver.Chrome()
driver.get("https://www.baidu.com")
driver.implicitly_wait(10)
driver.maximize_window()
time.sleep(3)
js = "window.scrollTo(100,400);"
driver.execute_script(js)
unittest单元测试框架
一:unittest是单元测试框架是收到了junit 的启发,和其他测试框架有有着相似的风格,支持自动化测试,配置共享和关机的代码执行,unittest是Python内置的单元测试框架,主要用于单元测试,具备编写用例、组织用例、执行用例、输出报告等作用。
单元测试经常用到的五个概念
test case:自动化测试用例,一个TestCase的实例就是一个测试用例;
test suite:测试套件,是多个测试用例的集合;
testLoader:加载器,用于加载TestCase到TestSuite中。其中有几个loadTestsFrom__()方法,就是从各个地方寻找TestCase,创建它们的实例,然后add到TestSuite中,再返回一个TestSuite实例;
test runner:执行测试,执行测试用例,并将测试结果保存到TextTestResult实例中,包括运行了多少测试用例,成功了多少,失败了多少等信息;
test fixture:测试夹具,一个测试用例的初始化准备及环境还原,主要包含setUp() 和 setDown()方法;
二:使用步骤:
1 引入unitest 这个模块,创建testcount类继承了testcase类
2 断言的方法assert.Equal方法
3main()函数方法执行上面的所有的测试用例
三:unitest模块重要组成:
1 :testcase: 用来写测试用例,相当于实例方法
2:Testsuit 就是将所有的测试用例集合到一起来执行
3 TestRunnner 测试用例的执行,testrunner方法提run()方法来执行testcase/testsuit
4 testfixture 对于一个测试环境的初始化操作,通过覆盖testcase的setuop方法来实现。
四:对测试环境的初始化和清除
setUpModule/tearDownModule:整个模块开始和结束时候执行
setupClasss/ tearDownClass:在测试类开始和结束的时候执行
setUp/tearDown:在测试用例开始或者结束的时候被执行
四关于TestSuit用法:测试环境清除初始化
import unittest
from cacl import Count
"""
测试用例类需继承unittest.Testcase
测试用例的其实就是一个实例方法
该测试用例方法就是一个必要使用test开头
"""
#模块的初始化
def setUpModule():
print("_______setUpModule___________")
#模块的清除
def tearDownModule():
print("______tearDownModule___________")
class CountTest(unittest.TestCase):
@classmethod
def setUp(self) -> None:
print("_______setUpClass___________")
@classmethod
def tearDownClass(cls) -> None:
print("_______tearDownClass___________")
#测试加法
def test_add(self):
print("*****************test_add**************")
#调用项目代码的加法
#类的实例化
c1 = Count(5,6)
res = c1.add()
#进行断言
self.assertEqual(res,11)
def test_sub(self):
print("****************testsub******************")
c2 = Count(10,2)
res = c2.subtractrion()
self.assertEqual(res,8)
if __name__ == '__main__':
#执行测试用例
CountTest.main()
TestSuit创建测试套件
测试套件类似于测试单,测试用例属于测试套件的,一个测试套件可以有多个测试。
import unittest
from CountTest import CountTest
#创建测试套件对象
suite = unittest.TestSuite()
#使用addTest方法加载testcase到testsuit中,用于少量的测试用例
suite.addTest(CountTest('test_add'))
suite.addTest(CountTest('test_sub'))
#执行测试套件,创建执行器
runner = unittest.TextTestRunner()
#使用执行器执行测试套件
runner.run(suite)
Ran 2 tests in 0.002s
_______setUpModule___________
******用例级别****
*****************test_add**************
*****用例接级别******
******用例级别****
****************testsub******************
*****用例接级别******
_______tearDownClass___________
______tearDownModule___________
添加多个测试用例到测试套件之中
我们可以使用一个列表来接受
将测试用例的集合放在一个列表里面。我们将列表传递给给addTests方法中实现多测试用例集合的传递。
import unittest
from CountTest import CountTest
#创建测试套件对象
suite = unittest.TestSuite()
#使用addTest方法加载testcase到testsuit中,用于少量的测试用例
case = [
CountTest('test_add'),
CountTest('test_sub')
]
# suite.addTest(CountTest('test_add'))
# suite.addTest(CountTest('test_sub'))
suite.addTests(case)
#执行测试套件,创建执行器
runner = unittest.TextTestRunner()
#使用执行器执行测试套件
runner.run(suite)
模糊匹配:
进行模糊匹配
"""
指定模糊匹配
指定模糊匹配规则,自动生成测试过用例
"""
import unittest
casepath = "../day03"
#进行模糊匹配
suitcase = unittest.defaultTestLoader.discover(start_dir=casepath,pattern='Cou*.py')
#创建执行器
runner = unittest.TextTestRunner()
#执行测试用例
runner.run(suitcase)
注意:测试执行的顺序,是按照测试名称ascii顺序执行的。
跳过测试和预期失败
unittest提供了实现某些需求的装饰器
我们需要在测试用例每一个装饰前面加上@符号
unittest提供了以下的一些方法:
@unittest.skip(reason)#无条件跳过测试用例
@unittest.skipif(条件,reason)#跳过装饰的测试,如果条件为真
@unittest.skipUnless(条件,reason) #跳过装饰的测试,除非条件为真
@unittest.exceptedFailure()#测试标记失败,不管直接结果是否失败,一律标记为失败,但不会抛出异常信息
@unittest.exceptedFailure#如果断言失败,不计入case数目中
import unittest
from cacl import Count
"""
测试用例类需继承unittest.Testcase
测试用例的其实就是一个实例方法
该测试用例方法就是一个必要使用test开头
"""
#模块的初始化
def setUpModule():
print("_______setUpModule___________")
#模块的清除
def tearDownModule():
print("______tearDownModule___________")
class CountTest(unittest.TestCase):
#测试类的初始化
@classmethod
def setUp(self) -> None:
print("_______setUpClass___________")
@classmethod
def tearDownClass(cls) -> None:
print("_______tearDownClass___________")
#用例级别的初始化
def setUp(self) -> None:
print("******用例级别****")
def tearDown(self) -> None:
print("*****用例接级别******")
#测试加法
def test_add(self):
print("*****************test_add**************")
#调用项目代码的加法
#类的实例化
c1 = Count(5,6)
res = c1.add()
#进行断言
self.assertEqual(res,11)
@unittest.skip("该用例的开发未完成")
def test_sub(self):
print("****************testsub******************")
c2 = Count(10,2)
res = c2.subtractrion()
self.assertEqual(res,8)
try:
def test_func(self):
print("***************执行test_func函数****************")
c3 = Count(8,9)
res = c3.add()
self.assertEqual(res,10)
print("***************执行失败********************")
except Exception as e:
print()
if __name__ == '__main__':
#执行测试用例
CountTest.main()
生成测试报告
借助HTMLRunner ,这是unittcase的一个库,是单元测试框架的一个扩展。它生成易于使用的HTML测试报告。
但是在HTMLRunner是基于python2 进行开发的,对于python3环境而言,对其中的部分内容进行修改。
import unittest
import time
import os
from common.HTMLRunner import HTMLTestRunner
from BeautifulReport import BeautifulReport
#测试报告的存放地址
report_path = "./report"
report_title = "冒烟测试"
#测试的描述
report_desc = "冒烟测试"
if not os.path .exists(report_path):
os.mkdir(report_path)
#构建获取时间日期作为报告的名字
get_time = time.strftime("%Y%m%d%H%M%S")#获取当前的时间
#构建测试报告存放路径和名字,这个加上当前的时间做一个拼接,作为报告的名称。
file_path = report_path + f"{get_time}.html"
#执行测试,生成测试报告
#指定加载测试用例的路径。指定加载
case_path = "./test_case"
#模糊匹配对应的测试用例
suite = unittest.defaultTestLoader.discover(start_dir=case_path, pattern='C*.py')
# with open(file_path,'wb') as f1:
# #第一个参数指的是生成的测试报告给那个文件写入
# runner = HTMLTestRunner(f1,title=report_title,description=report_desc)
# #执行套件
# runner.run(suite)
#将测试套件存放到BeautifulReport()里面。
BeautifulReport(suite).report(filename=file_path,description=report_desc,report_dir=report_path)
#BeautifulReport(suite).report(filename='测试报告文件名称',
# description='测试报告标题',
# report_dir='.')
# report_dir='.'把report放到当前目录下
版权归原作者 土豆爱牛肉 所有, 如有侵权,请联系我们删除。