0


selenium 自动化测试

一: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放到当前目录下

本文转载自: https://blog.csdn.net/qq_40315455/article/details/131071565
版权归原作者 土豆爱牛肉 所有, 如有侵权,请联系我们删除。

“selenium 自动化测试”的评论:

还没有评论