自学内容网 自学内容网

Selenium

web-selenium

简介

可解决:回归测试,压力测试,兼容性测试

工具:QTP(收费,支持web,桌面软件自动化),Selenium(免费,开源,支持web),Robot framework(基于python的扩展关键字自动化工具)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

安装

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

注意:浏览器驱动版本必须和浏览器版本一致

案例


from time import sleep
from selenium import webdriver
driver = webdriver.Chrome()
driver.get('https://www.baidu.com')
sleep(3)
driver.quit()

元素定位

元素定位:通过元素的信息或元素的层级结构来定位元素

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

4.1 为什么要使用元素定位?
    要使用web自动化操作元素,必须首先找到此元素。
4.2 定位工具
    火狐:Firebug (F12获取直接点击 Friebug图标)
    谷歌:F12键(开发者工具)
4.3 定位元素时依赖于什么?
    1. 标签名
    2. 属性
    3. 层级
    4. 路径
    
4.4 定位方式
    1. id
    2. name
    3. class_name(使用元素的class属性定位)
    4. teg_name(标签名称 <标签名 .../>)
    5. link_text(定位超连接 a标签)
    6. partial_link_text(定位超链接 a标签 模糊)
    7. xpath(基于元素路径)
    8. css(元素选择器)
    
    汇总:
       1. 基于元素属性特有定位方式(id\name\class_name)
       2. 基于元素标签名称定位:tag_name
       3. 定位超链接文本(link_text、partial_link_text)
       4. 基于元素路径定位(xpath)
       5. 基于选择器(css)

id

说明:id定位就是通过id书写来定位元素,HTML规定id属性在整个HTML文档中必须是唯一的

前提:元素有id属性

id定位方法

element=driver.find_element_by_id(id)

注意:url中的链接/表示转义,//表示/,使用本地的链接前缀用file:///

id定位拓展

#查找元素用户名并且输入admin
driver.find_element_by_id("userA").send_keys("admin")

name,class_name

name定位就是根据元素name属性来定位。HTML文档中name的属性值是可以重复的。

前提:元素有name属性

name定位

element=driver.find_element_by_name(name)

name定位拓展

#查找元素用户名并且输入admin
driver.find_element_by_name("userA").send_keys("admin")

class_nam定位

说明:class_name 是根据class属性值来定位元素。HTML通过使用class来定义元素的样式

前提:元素有class属性

注意:如果class有多个属性值,只能使用其中的一个

代码:

element=driver.find_element_by_class_name(class_name)

tag_name

说明

tag_name,通过标签名定位,但一般存在多个相同的标签名,如果存在多个同样的标签,默认返回第一个,所以很少使用tag_name

代码

element=driver.find_element_by_tag_name(tag_name)

link_text,partial_link_text

link_text说明

专门定位超链接,并且是超链接()的文本内容

代码

element=driver.find_element_by_link_text(link_text)

其中link_text为超链接的文本内容

partial_link_text说明

对link_text的补充,partial_link_text除了可以使用全部文本匹配元素还可以使用局部来匹配元素,局部没有唯一代表词,默认操作符合条件的第一个元素

代码

element=driver.find_element_by_partial_link_text(partial_link_text)

partial_link_text可以传入a标签局部文本,模糊部分值,但必须能够表达唯一性

使用XPath,CSS原因

1.没有id,name,class属性使用XPath

2.link_text,partial_link_text 只适合超链接

3.tag_name只能找页面唯一的元素或者页面多个相同元素中第一个元素

XPath

XML Path的简称,是一门在XML文档中查找元素信息的语言

HTML可以看作是XML的一种实现,所以selenium用户可以使用这种强大的语言在web应用定位元素

XML:一种标记语言,用户数据的存储和传递,后缀.xml结尾

XPath定位:基于元素的路径

XPath定位策略(方式)

1.路径定位

2.利用元素属性定位

3.属性和逻辑结合定位

4.层级和属性结合定位

XPath定位方法

element=driver.find_element_by_xpath(xpath)

chromeXPath

F12 右键点击copy,右边会弹出来一列,可以看到XPath和fullpath

火狐XPath定位示例

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

2.4 Xpath常用的定位策略:
    1. 路径
       1). 绝对路径:
             语法:以单斜杠开头逐级开始编写,不能跳级。如:/html/body/div/p[1]/input
       2). 相对路径
             语法:以双斜杠开头,双斜杠后边跟元素名称,不知元素名称可以使用*代替。 
                如: //input 
                     //*
    2. 路径结合属性
          语法:在Xpath中,所有的属性必须使用@符号修饰 如://*[@id='id值']
    3. 路径结合逻辑(多个属性)
          语法://*[@id="id值" and @属性='属性值']
    4. 路径结合层级
          语法://*[@id='父级id属性值']/input
          
    提示:
       1. 一般见识使用指定标签名称,不使用*代替,效率比较慢。
       2. 无论是绝对路径和相对路径,/后面必须为元素的名称或者*
       3. 扩展:在工作中,如果能使用相对路径绝对不使用绝对路径。
       
2.5 Xpath扩展
    1. //*[text()='XXX'] # 定位文本值等于XXX的元素  
       提示:一般适合 p标签,a标签 
    2. //*[contains(@属性,'xxx')] # 定位属性包含xxx的元素 【重点】
       提示:contains为关键字,不可更改。 
    3. //*[starts-with(@属性,'xxx')] # 定位属性以xxx开头的元素
       提示:starts-with为关键字不可更改

CSS

css说明

说明: 
    1. CSS一种标记语言,焦点:数据的样式。控制元素的显示样式,就必须先找到元素,在css标记语言中找元素使用css选择器;
    2. css定位就是通过css选择器工具进行定位。
    3. 极力推荐使用,查找元素的效率比xpath高,语法比xpath更简单。

css定位语法

element = driver.find_element_by_css_selector(css_selector)
常用测试略:
    1. id 选择器
          前提:元素是必须有id属性
          语法:#id  如:#passwordA
    2. class 选择器
          前提:元素是必须有class属性
          语法:.class  如:.telA
    3. 元素选择器
          语法:element  如:input
    4. 属性选择器
          语法:[属性名=属性值]
    5. 层级选择器
          语法: 
             1. p>input 
             2. p input 
          提示:>与空格的区别,大于号必须为子元素,空格则不用。
          
扩展: 
    1. [属性^='开头的字母'] # 获取指定属性以指定字母开头的元素
    2. [属性$='结束的字母'] # 获取指定属性以指定字母结束的元素
    3. [属性*='包含的字母'] # 获取指定属性包含指定字母的元素
    
    复制xpath:/html/body/form/div/fieldset/p[1]/input
    复制最简://*[@id="userA"]
    复制CSS路径:html body form div#zc fieldset p#p1 input#userA
    
    提示: 
       1. 虽然借助工具可以快速生成xpath路径和css语法,但是前期不建议使用。
       2. 工具在智能,没有人智能。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

P37?拓展工具生成XPath,CSS

定位一组元素

方法:driver.find_elements_by_xxx()

返回结果:类型为列表,需要对列表进行访问和操作必须指定下标或进行遍历,[下标从0开始]

拓展8种元素定位的底层实现

方式:driver.find_element(By.xxx,‘value’)

参数说明:

By.xxx:为By类的类型 如:By.ID

value:元素的定位值 如:userA

By类:需要导包 位置:from selenium.webdriver.common by import By

元素的操作方法

操作元素的方法

1.让脚本模拟用户给指定元素输入值

2.让脚本模拟认为删除元素的内容

3.让脚本模拟点击操作

元素常用操作的方法

1.click() 单击元素

2.send_keys(value) 模拟输入

3.clear() 清除文本

提示:在输入方法前一段要清空操作

操作浏览器常用方法API

2.1 方法
    1). driver.maximize_window() # 最大化浏览器
    2). driver.set_window_size(w, h) # 设置浏览器大小 单位像素
    3). driver.set_window_position(x, y) # 设置浏览器位置
    4). driver.back() # 后退操作
    5). driver.forward() # 前进操作
    6). driver.refresh() # 刷新操作
    7). driver.close() # 关闭当前主窗口(主窗口:默认启动哪个界面,就是主窗口)
    8). driver.quit() # 关闭由driver对象启动的所有窗口
    9). driver.title # 获取当前页面title信息
    10). drive.current_url # 获取当前页面url信息
    
2.2 提示:
    1. driver.title 和 driver.current_url 没有括号,应用场景:一般为判断上步操作是否执行成功。
    2. driver.maximize_window() # 一般为我的前置代码,在获取driver后,直接编写最大化浏览器
    3. driver.refresh() 应用场景,在后面的cookie章节会使用到。
    4. driver.close()与driver.quit()区别:
       close():关闭当前主窗口
       quit():关闭由driver对象启动的所有窗口
       提示:如果当前只有1个窗口,close与quit没有任何区别。
# 最大化浏览器
driver.maximize_window()
# 刷新
driver.refresh()
# 后退
driver.back()
# 前进
driver.forward()
# 设置浏览器大小
driver.set_window_size(300,300)
# 设置浏览器位置
driver.set_window_position(300,200)
# 关闭浏览器单个窗口
driver.close()
# 关闭浏览器所有窗口
driver.quit()
# 获取title
title = driver.title
# 获取当前页面url
url = driver.current_url

获取元素信息的常用方法

3.1 方法:
    1). text 获取元素文本  如:driver.text
    2). size 获取元素大小  如:driver.size
    3). get_attribute 获取元素属性值 如:driver.get_attribute("id")
    4). is_displayed 判断元素是否可见 如:element.is_displayed()
    5). is_enabled 判断元素是否可用 如: element.is_enabled()
    6). is_selected 判断元素是否被选中 如:element.is_selected()
    
3.2 提示: 
    1. text和size调用时 无括号
    2. get_attribute一般应用场景:判断一组元素是否为想要的元素或者判断元素属性值是否正确
    3. is_displayed、is_enabled、is_selected,在特殊应用场景中使用。

鼠标和键盘的操作

鼠标的操作


    4.1 为什么使用鼠标操作?
       为了满足丰富的html鼠标效果,必须使用对应的方法。
    4.2 鼠标事件对应的方法在哪个类中
       ActionChains类--->导包 
       from selenium.webdriver.common.action_chains import ActionChains
    4.3 鼠标事件常用的操作方法
       1. context_click() # 右击
          应用:context_click(element).perform()
       2. double_click() # 双击
          应用:double_click(element).perform()
       3. drag_and_drop() # 拖拽
          应用:drag_and_drop(source, target).perform
       4. move_to_element() #悬停
          应用: move_to_element(element).perform()
       5. perform() # 执行以上事件方法
    
    4.4 提示: 
       1. selenium框架中虽然提供了,右击鼠标方法,但是没有提供选择右击菜单方法,可以通过发送快捷键的方式解决(经测试,谷歌浏览器不支持)。
    

其他:鼠标实例化对象

action=ActionChains(driver)

键盘操作


    4.1 键盘对应的方法在Keys类中
       包:from selenium.webdriver.common.keys import Keys
    4.2 常用的快捷键:
       CONTROL:Ctrl键
       其他,请参考Keys底层定义的常亮
    4.3 应用
       组合键:element.send_keys(Keys.XXX, 'a')
       单键:element.send_keys(Keys.XXX)

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

q元素等待


    6.1 为什么要设置元素等待
       由于电脑配置或网络原因,在查找元素时,元素代码未在第一时间内被加载出来,而抛出未找到元素异常。
    6.2 什么是元素等待
       元素在第一次未找到时,元素等待设置的时长被激活,如果在设置的有效时长内找到元素,继续执行代码,如果超出设置的时长未找打元素,抛出未找到元素异常。
    6.3 元素等待分类
       1. 隐式等待
       2. 显示等待
    6.4 隐式等待
       方法:driver.implicitly_wait(30) # 一般情况下设置30秒
       特色:
          1. 针对所有元素生效。
          2. 一般情况下为前置必写代码(1.获取浏览器驱动对象;2. 最大化浏览器;3. 设置隐式等待)
          
    6.5 显示等待
       方法:WebDriverWait(driver,timeout=10, poll_frequency=0.5).until(lambda x:x.find_element_by_id("#user")).send_keys("admin")
       参数:
          timeout: 超时时间
          poll_frequency:访问频率,默认0.5秒找一次元素
          x: x为driver,它是WebDriverWait类将传入的driver赋值给类self._driver,until方法调用了self._driver;
          
       提示: 
          1. WebDriverWait(driver,timeout=10, poll_frequency=0.5).until(lambda x:x.find_element_by_id("#user"))返回的一个元素。
          
    6.6 显示等待与隐式等待区别:
       1. 显示等待:针对单个元素生效
       2. 隐式等待:针对全局元素生效

拓展send_keys 上传文件

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

下拉框

1.1 为什么单独使用下拉框?
    1. 如果option选项没有value值的化,css定位或其他定位就不太方便。
1.2 如何使用Select类
    操作:
       1. 导包:from  selenium.webdriver.support.select improt Select
       2. 实例化:s = Select(element)
       3. 调用方法:s.select_by_index()
1.3 提供哪些方法
       1. select_by_index() # 通过下标定位
       2. select_by_value() # 通过value值
       3. select_by_visible_text() #显示文本

1.4 注意事项
       1. 实例化select时,需要的参数为 select标签元素
       2. 调用Select类下面的方法,是通过索引、value属性值、显示文本去控制,而不需要click事件
    

警告框

2.1 为什么要处理警告框?
    如果页面由弹出框,不处理,接下来的将不生效。
2.2 对话框类型
    1. alert # 警告框
    2. confirm # 确认框
    3. prompt # 提示框

2.3 如何处理
    以上三种对话框,处理方法都一样。
    步骤:
       1. 切换到对话框
             方法:driver.switch_to.alert
       2. 处理对话框
             alert.text # 获取文本
             alert.accept() # 同意
             alert.dismiss() # 取消
             
    提示:无论以上哪个对话框,都可以使用取消、同意,因为调用的是后台的事件,根页面显示的按钮数量无关。
    
2.4 注意: 
    1. driver.switch_to.alert 方法适合以上三种类型对话框,调用时没有括号
    2. 获取文本的方法,调用时没有括号 如:alert.text
    3. 在项目中不是所有的小窗口都是以上三种对话框。

滚动条

 3.1 为什么要操作滚动条
在web自动化中有些特殊场景,如:滚动条拉倒最底层,指定按钮才可用。
3.2 如何操作 
第一步:设置操作滚动条操作语句
如:js = "window.scrollTo(0,10000)"
0: 左边距 --》水平滚动条
10000:上边距 -->垂直滚动条

第二步:调用执行js方法,将设置js语句传入方法中
方法:driver.execute_script(js)
3.3 说明
在selenium中没有直接提供定位滚动条组件方法,但是它提供了执行js语句方法,可以通过js语句来控制滚动条操作。

切换frame表单和多窗口切换

切换frame表单

提示:常用的frame表单有两种:frame、iframe

4.1 为什么要切换?
    当前主目录内没有iframe表单页面元素信息,不切换,找不到元素。
4.2 如何切换?
    方法:driver.switch_to.frame("id\name\element")
4.3 为什么要回到主目录
    iframe或frame只有在主目录才有相关元素信息,不回到主目录,切换语句会报错。
4.4 如何回到主目录
    方法:driver.switch_to.default_content()
4.5 提示:
    1.切换frame时,可以使用name、id、iframe元素

多窗口切换

5.1 为什么要切换多窗口?
    页面存在多个窗口式,seleniu默认焦点只会在主窗口上所有的元素,不切换切换窗口,无法操作除主窗口以外的窗口内元素
5.2 如何切换?
    思路:获取要切换的窗口句柄,调用切换方法进行切换。
    方法:
       1. driver.current_window_handle # 获取当前主窗口句柄
       2. driver.window_handles # 获取当前由driver启动所有窗口句柄
       3. driver.switch_to.window(handle) # 切换窗口
    步骤:
       1. 获取当前窗口句柄
       2. 点击链接 启动另一个窗口
       3. 获取当前所有窗口句柄
       4. 遍历所有窗口句柄
          5. 判断当前遍历的窗口句柄不等于当前窗口句柄
          6. 切换窗口操作
    

截屏

应用场景:失败截图,让错误看的更直观
方法: 
    driver.get_screenshot_as_file(imgepath)
参数:
    imagepath:为图片要保存的目录地址及文件名称
       如: 当前目录 ./test.png
           上一级目录 ../test.png
扩展:
    1. 多条用例执行失败,会产生多张图片,可以采用时间戳的形式,进去区分。
    操作: 
       driver.get_screenshot_as_file("../image/%s.png"%(time.strftime("%Y_%m_%d %H_%M_%S")))
       strftime:将时间转为字符串函数
注意:
    %Y_%m_%d %H_%M_%S:代表,年 月 日 时 分 秒

验证码

7.1 什么是验证码?
    一种随机生成信息(文字、数字、图片)
7.2 验证码作用
    防止恶意请求

7.3 验证码处理方式
    1. 去掉验证码(项目在测试环境、公司自己的项目)
    2. 设置万能验证码(测试环境或线上环境,公司自己项目)
    3. 使用验证码识别技术 (由于现在的验证码千奇百怪,导致识别率太低)
    4. 使用cookie解决(推荐)
    
7.4 cookie 介绍:
    生成:由服务器生成
    作用:标识一次对话的状态(登录的状态)
    使用:浏览器自动记录cookie,在下一条请求时将cookis信息自动附加请求
    
7.5 应用:
    方法: 
       1. driver.get_cookies() # 获取所有的cookie
       2. driver.add_cookies({字典}) # 设置cookie
    步骤: 
       1. 打开百度url driver.get("http://www.baidu.com")
       2. 设置cookie信息: driver.add_cookie({"name":"BDUSS","value":"根据实际情况编写"})
       3. 暂停2秒以上
       4. 刷新操作 
    注意: 
       1. 以上百度BDUSS所需格式为百度网站特有,别的网站请自行测试。
       2. 必须进行刷新操作。

unittest

一、UnitTest框架
    1.1 为什么使用UnitTest框架?
       1. 批量执行用例
       2. 提供丰富的断言知识
       3. 可以生成报告
       
    1.2 什么是UnitTest框架
       python自带一种单元测试框架
       
    1.3 核心要素
       1). TestCase(测试用例)
       2). TestSuite(测试套件)
       3). TextTestRunner(以文本的形式运行测试用例)
       4). TestLoader(批量执行测试用例-搜索指定文件夹内指定字母开头的模块) 【推荐】
       5). Fixture(固定装置(两个固定的函数,一个初始化时使用,一个结束时使用))
       
    TestCase:
       说明:测试用例
       步骤:
          1. 导包 import unittest
          2. 新建测试类并继承 unittest.TestCase
          3. 测试方法必须以test字母开头
       运行:
          1. 运行测试类所有的测试方法,光标定位到类当前行右键运行
          2. 运行单个测试方法:光标放到测试方法当前行。
    
    TestSuite:
       说明:测试套件 
       步骤: 
          1. 导包
          2. 获取测试套件对象 suite = unittest.TestSuite()
          3. 调用addTest()方法 添加测试用例
          
       添加测试用例方法: 
          1. suite.addTest(类名("方法名称")) # 添加指定类中指定的测试方法
          2. suite.addTest(unittest.makeSuite(类名)) # 添加指定类中所有已test开头的方法
    TextTestRunner:
       说明:执行测试套件方法
       步骤: 
          1. 导包
          2. 实例化后去执行套件对象 runner = unittest.TextTestRunner()
          3. 调用run方法去执行 runner.run(suite)
          
    TestLoader:
       说明:
          1. 将符合条件的测试方法添加到测试套件中
          2. 搜索指定目录文件下指定字母开头的模块文件下test开始的方法,并将这些方法添加到测试套件中,最后返回测试套件
       操作: 
          1. 导包
                import unittest
          2. 调用TestLoader()
                写法1. suite = unittest.TestLoader().discover("指定搜索的目录文件","指定字母开头模块文件")
                写法2. suite = unittest.defaultTestLoader.discover("指定搜索的目录文件","指定字母开头模块文件") 【推荐】
                注意:如果使用写法1,TestLoader()必须有括号。
          3. 执行测试套件
                unittest.TextTestRunner().run(suite)
                
    TestSuite与TestLoader区别:
       共同点:都是测试套件
       不同点:实现方式不同
          TestSuite: 要么添加指定的测试类中所有test开头的方法,要么添加指定测试类中指定某个test开头的方法
          TestLoader: 搜索指定目录下指定字母开头的模块文件中以test字母开头的方法并将这些方法添加到测试套件中,最后返回测试套件
          
二、fixture
    说明:装置函数(setUp、tearDown)
    级别:
       1). 函数级别 def setUp() / def tearDown()
             特性:几个测试函数,执行几次。每个测试函数执行之前都会执行 setUp,执行之后都会执行tearDwon
       2). 类级别 def setUpClass() / def tearDownClass()
             特性:测试类运行之前运行一次setUpClass 类运行之后运行一次tearDownClass
             注意:类方法必须使用 @classmethod修饰
       3). 模块级别:def setUpModule() / def tearDownModule()
             特殊:模块运行之前执行一次setUpModule ,运行之后运行一次tearDownModule
             
    提示:
       无论使用函数级别还是类级别,最后常用场景为:
          初始化:
             1. 获取浏览器实例化对象
             2. 最大化浏览器
             3. 隐式等待
          结束:
             关闭浏览器驱动对象
             
三、断言
    3.1 什么是断言?
       让程序代替人为判断执行结果是否与预期结果相等的过程
    3.2 为什么要断言?
       自动化脚本执行时都是无人值守,需要通过断言来判断自动化脚本的执行是否通过
       注:自动化脚本不写断言,相当于没有执行测试一个效果。
    3.3 常用断言
       1. self.assertEqual(ex1, ex2)  #判断ex1 是否相等ex2
       2. self.assertIn(ex1 ,ex2) # ex2是否包含ex1 注意:所谓的包含不能跳字符
       3. self.assertTrue(ex) # 判断ex是否为True
       
    3.4 断言练习
       目标:tpshop登录
       方法:
          def setUp():
             # 获取driver
             # 打开url
             # 最大化浏览器
             # 隐式等待
          def tearDown():
             # 关闭浏览器驱动
          
          def test_login_code_null():
             # 根据业务流程编写
             # ...
             # 失败截图
       
    3.5 扩展
       断言两种实现方式
          方式1:使用unittest框架中断言,详情请参考以上相关知识点。
          方式2:使用python自带断言
             1. assert str1 == str2 # 判断str1 是否与str2相等
             2. assert str1 in str2 # 判断str2 是否包含str1
             3. assert True/1 # 判断是否为True
             
四、参数化
    4.1 为什么要参数化
       解决冗余代码问题;
    4.2 什么是参数化
       说明:根据需求动态获取参数并引用的过程
    4.3 参数化应用场景
       场景:解决相同业务逻辑,不同测试数据问题。
       
    4.4 应用:
       1. 安装插件
          通过命令:
             安装:
                pip install parameterized
             验证:
                pip show parameterized
          通过pycharm:File-->setting-->Project 工程名称
          
       2. 应用插件
          1. 导包 from parameterized import parameterized
          2. 修饰测试函数 @parameterized.expand([数据])
             数据格式:
                1. 单个参数:类型为列表
                2. 多个参数:类型为列表嵌套元祖
                3. 在测试函数中的参数设置变量引用参数值,注意:变量的数量必须和数据值的个数相同

with opren 和 open的区别

1.共同点:打开文件

2.不同点,with open =执行操作+关闭操作

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

P104 PO模式

PO模式
    版本:
       v1:不采用任何模式(线性模型)
       v2:采用测试框 unittest
       v3:业务代码和页面对象进行
       v4:实际中的po模式编写
    
    案例:
       tpshop登录
          1. 账号不存在
          2. 密码错误
          
    问题:
       v1:无法批量运行
       v2: 业务脚本与页面对象没有分开
       v3: 代码冗余量太大
       
    PO介绍:
       PO: page(页面) object(对象)
       
       
    v4版本:
       结构:
          1. base(基类):page页面一些公共的方法;
             # Base类
                # 初始化方法
                # 查找元素方法
                # 点击元素方法
                # 输入方法
                # 获取文本方法
                # 截图方法
                注意:
                   1. 以上方法封装时候,解包只需1此,在查找元素解包;
                   2. driver为虚拟,谁调用base时,谁传入,无需关注从哪里来;
                   3. loc:真正使用loc的方法只有查找元素方法使用;
          2. page(页面对象):一个页面封装成一个对象;
             应用:继承base;
             
             实现:
                1. 模块名:page+实际操作模块名称  如:page_login.py 
                2. 页面对象名:以大驼峰方法将模块名抄进来,有下划线去掉下划线
                3. 方法:涉及元素,将每个元素操作单独封装一个操作方法;
                4. 组装:根据需求组装以上操作步骤;
          3. scripts(业务层):导包调用 page页面
             实现: 
                1. 模块:test+实际操作模块名称 如:test_login.py 
                2. 测试业务名称:以大驼峰方法将模块名抄进来,有下划线去掉下划线
                3. 方法: 
                   1. 初始化方法 setUp() 注:在unittest框架中不能使用def __init__()初始化方法;
                      # 实例化 页面对象 
                      # 前置操作 如:打开等等
                   2. 结束方法 teardown
                      # 关闭驱动
                   3. 测试方法
                      # 根据要操作的业务来实现
             
    扩展:
       loc变量:类型为元组 ;*loc为解包;

       
今天目标:
    1. 数据驱动 
    
    扩展:
       1. 线性驱动
       2. 模块驱动
       3. 数据驱动
一、数据驱动
    1.1 什么是数据驱动?
       说明:
          1. 通过测试数据控制用例的执行,直接影响测试结果;
          2. 数据驱动是最好结合PO+参数化技术使用;
    1.2 数据驱动优点
          将维护关注点放到测试数上,而不去关注测试脚本代码;
    1.3 数据驱动常用的格式
          1. JSON(重点)
          2. XML
          3. EXCEL
          4. CSV
          5. TXT
          
    1.4 JSON介绍
       1. 一种纯文本格式,后缀.json ;
       2. 一种轻量级数据交换格式;(接口数据传递基本使用json格式)
       3. 由键值对组成,和python的字典格式一模一样,不同之处在于(json是文本格式)
       4. json语法:花括号包含键值对,键与值之间使用冒号(:)分隔, 键值对之间使用逗号(,)分隔;
       
    1.5 json与字典转换
       1). 字典转为json字符串
          方法:dumps() 
          操作:
             1. 导包
             2. 调用dumps方法
             3. 打印类型
          注意:
             使用dumps方法,而不是dump方法;
       2) json字符串转字典
          方法: loads()
          操作: 
             1. 导包
             2. 调用loads方法
             3. 打印类型
          注意:
             1. 使用loads方法而不是load方法
             2. 字符串中的键名必须使用双引号;
    1.6 json的写与读
       1). 写入json
          方法:dump(写什么文件, 往那写)
          操作: 
             1. 导包
             2. 获取文件流f,并调用dump方法写入
          注意:
             1. 写入时模式 w
             2. 写入的方法 dump() 而不是 dumps()
             
       2). 读取json 【重点】
          方法:load()
          操作:
             1. 导包
             2. 获取文件流f,并调用load方法读取
          注意:
             1. 写入时模式 r
             2. 写入的方法 load() 而不是 loads()
             
二、练习计算器
链接:http://cal.apple886.com/
    结构:
       base
          # 初始化方法
          # 查找元素
          # 点击
          # 获取value属性方法封装
          # 截图
       page
          # 点击数字
             for n in num:
                loc = By.ID, ""simple{}".format(n)"
                # 调用baes内点击方法
          
          # 点击加号
          # 点击等号
          # 获取结果
          # 组装业务方法
       scripts
          # 初始化方法
             # 获取计算页面页面对象
             # 获取driver
             
          # 结束方法
             # 关闭driver
          # 测试加法方法
             # 调用加法运算业务方法
             # 断言
             
             
注意:断言在业务层
注意:结构化可以运用yeild生成器
生成器的本质就是一个迭代器
迭代器和生成器的区别: 迭代器是Python中内置的一种节省空间的工具,是python自带的;生成器是程序员自己写的。


    drvier封装
       类名
          # 定义类变量
          driver = None
          
          @classmethod
          # 获取driver方法
             如果 cls.driver is None:
                # 获取浏览器驱动对象
                # 最大化
                # 打开url 注:url建议写入配置文件中
             返回 cls.driver
          @classm3thod
          # 关闭driver方法
             如果 cls.driver:
                cls.driver.quit()
                # 注意此处一定要置空
                cls.driver = None
                
    读取json数据封装
       1. 读取工具封装
          # 导包
          # 打开json获取文件流 并 调用load方法
          
       2. 组装读取出来数据格式封装
          预期格式:[(),()]
          默认实际格式:{"":"","":""}
          思路:
             1. 新建空列表
             2. 使用字典.values()方法获取所有的字典值;
             3. 使用列表的.append((字典.get("键名")))
             4. 返回 arrs
       
       
    查找元素判断是否操作成功 思路封装
       def base_if_success():
          try:
             self.base_find_element(loc, timeout=2)
             return True
          except:
             return False
             
    如何区分正向逆向用例
       思路:在测试数据中添加一一个标识正向用例或逆向用例的标记: 如:True/False
       步骤:
          1. 调用登录方法(此登录方法中,只有输入用户名、输入密码、输入验证码、点击登录按钮) 切记:不要封装点击登录连接地址;
          2. 判断是否正向用例:
                # 判断安全退出是否存在
                # 点击安全退出
                # 点击登录连接地址

原文地址:https://blog.csdn.net/Mostan727/article/details/142342471

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!