Selenium

1web-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 =执行操作+关闭操作

在这里插入图片描述

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. 判断是否正向用例:
                # 判断安全退出是否存在
                # 点击安全退出
                # 点击登录连接地址

日志

今日目标:
    1. 日志 【核心目标】
    2. 项目

一、日志
    1.1 什么是日志
       说明:记录系统运行程序一些步骤,对一个事件(点击事件)也称为日志(Log)
    1.2 特点
       1. 调试程序
       2. 定位跟踪bug
       3. 根据日志,查看系统运行是否出错;
       4. 分析用户行为,与数据统计
    1.3 级别
       1. debug # 调试级别
       2. info  # 信息级别
       3. warning # 警告
       4. error # 错误级别
       5. critical # 严重
       
       提示:
          1. 开发常用以上 debug、info、warning、error
          2. 测试常用级别:info、error
          
       注意:
       优先级别:debug>info>warning>error>critical
       当指定一个级别所展示的信息大于等于这个级别的信息:比如debug会展现所有的日志信息
       一般critical不建议使用
          
    1.4 Logging基本使用
       步骤:
          1. 导包  如:import logging
          2. 调用相应的级别方法,记录日志信息 logging.debug("debug...")
       设置级别:
          logging.basicConfig(level=logging.DEBUG)
       提示:
          1. 默认级别为:logging.WARNING
          2. 设置级别时调用的是logging文件夹下面的常量,而不是调用的小写方法
          3. 切记:设置级别以后,日志信息只会记录大于等于此级别的信息;
          4.大写常量,小写方法:loging.DEBUG
       
       设置格式
          fm = "%(asctime)s %(levelname)s [%(name)s] [%(filename)s (%(funcName)s:%(lineno)d] - %(message)s"
          logging.basicConfig(level=logging.DEBUG, format=fm)
       
       设置输入到文件
          logging.basicConfig(level=logging.DEBUG, format=fm, filename="../log/log01.log")
          
          
          

        
          
    1.5 logging 高级用法
       1). 为什么要使用高阶用法???
          1. 中文 乱码
          2. 无法同时输入到文件和控制台
       2). logging组成
          1. Logger 日志器
          2. handler 处理器
          3. formatter 格式器
          4. filter 过滤器
       3). 模块关系
          日志器:提供了,记录日志的入口,如:log.info("")
          处理器:真正将日志器内容发送到控制台还是文件或网络,都是处理器干的;每个日志器都可以添加多个不同的处理器
          格式器:处理器可以设置不同的格式,就需要使用格式器
          过滤器:处理器需要过滤日志信息,就需要设置过滤器;
          
       日志器: 
          操作:
             1. 导包 import logging
             2. 调用方法获取logger对象 # 如: logging.getlogger()
             3. 设置级别:logger.setlevel=logging.INFO
             4. 调用添加处理器方法 logger.addHandler(处理器)
             
       处理器: 
          类型: 
             1. 控制台处理器 StreamHandler()
             2. 文件处理器 fileHandler() # 文件无限增大
             3. 根据大小切割 RotatingFileHandler() 了解
             4. 根据时间切割 TimedRotatingFileHandler() 掌握
          
          获取:
             sf = logging.StreamHandler()
             
          TimedRotatingFileHandler()应用: 
             1. 导包: import logging.handlers
             2. 实例化:th = logging.handers.TimedRotatingFileHandler(filename="日志文件保存的目录及文件名",
                                                       when='M',
                                                       interval="1",
                                                       backupcount=30)
                1). when:时间单位
                2). interval:时间间隔
                3). backupcount:保留的备份数量
       格式器:
          获取: 
             fmt = "%(asctime)s %(levelname)s [%(name)s] [%(filename)s (%(funcName)s:%(lineno)d] - %(message)s"
             fm = logging.Formatter(fmt)
             
          将格式器添加到处理器中
             控制台处理器.setFormatter(fm)
             文件处理器.setFormatter(fm)
             
       应用:
          logger.info("日志信息")
          logger.error("日志信息")
          
       日志封装
          # 定义获取日之类
             # 定义类属性 logger = None
             
             @classemethod
             # 定义获取logger日志器的类方法
                if cls.logger is None: # 判断类属性logger是否还是为空,如果为空,就执行以下操作
                   # 获取 日志器对象
                   # 设置日志器级别
                   # 获取控制台处理器
                   # 获取文件处理器
                   # 获取格式器
                   # 将格式器添加到处理器中
                   # 将处理器添加到日志器中
                return 类属性logger
                
             注意:
                1. 以上条件无论是否成立,最后都会返回类属性logger;
                2. 当第一次调用时,条件一定成立,将类属性logger设置不为空;
                3. 当第二次以上调用时,永远返回第一次设置的类属性对象;
                
                
二、项目
传统的测试流程:
需求文档==用例分析--用例编写--用例评审--执行用例--提交bug--回归测试--上线验收--测试总结报告

自动化测试流程:
1.需求分析
2.挑选适合做自动化测试的功能
(功能测试里抽取)
3.设计测试用例
4.搭建自动化测试环境 [可选]
5.设计自动化测试项目的架构 [可选]
6.编写代码
7.执行测试用例
8.生成测试报告并且分析结果
 
注意:
自动化测试一般写正向用例,逆向比较少


项目介绍:
B2B 商家对企业
B2C 商家对客户

项目架构:
后台服务
数据库



    2.1 自动化测试流程
       1. 将功能用例转化自动化用例(在功能用例模板新增一列 是否自动化 )
       2. 搭建自动化测试环境(本机依赖的环境:python、pycharm、浏览器、浏览器驱动、selenium、 parameterized)
       3. 搭建自动化框架(po模式+数据驱动+log+报告)
       4. 编写代码
       5. 执行用例
       6. 生成报告\分析log
    
    2.2 自动化涉及的模块
       1. 登录  (登录成功)
       2. 购物车(添加商品到购物车)
       3. 订单  (下订单)
       4. 支付  (支付)
       
    2.3 自动化测试结构
       1. base(基类)
       2. page(页面对象)
       3. scripts(业务脚本)
       4. tool(工具类)
       5. data(存储测试数据文件)
       6. log(日志)
       7. image(失败截图)
       8. report(测试报告)
       
    2.4 base 公共方法封装实现
       # 查找元素方法
       # 点击元素方法
       # 输入元素方法
       # 获取元素文本方法
       # 截图方法
       # 判断元素是否存在方法封装
       
    2.5 登录分析
       0. 正确用户名+正确密码+正确验证码 预期:登录成功 并跳转到个人主页;
       1. 用户名为空 + 正确密码 + 正确验证码 预期:用户名不能空! 
       2. 正确用户名 + 空密码 + 正确验证码 预期:密码不能为空!
       3. 正确用户名 + 正确密码 + 空验证码  预期:验证码不能为空!
       4. 用户名不存在 + 正确密码 + 正确验证码 预期:账号不存在!
       5. 用户名格式不正确 + 正确密码 + 正确验证码 预期:账号格式不匹配!
       6. 正确用户名 + 错误密码 + 正确验证码 预期:密码错误!
       7. 正确用户名 + 正确密码 + 错误验证码 预期:验证码错误!
       
       

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

奶茶精Gaaa

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值