web自动化测试

一、自动化测试所属分类(站在代码可见度角度分类)

    1. 黑盒测试(功能测试)
    2. 灰盒测试(接口测试)
    3. 白盒测试(单元测试)
    提示:Web自动化测试属于黑盒测试(功能测试)

    优点

        1. 较少的时间内运行更多的测试用例;
        2. 自动化脚本可重复运行;
        3. 减少人为的错误;
        4. 测试数据存储,测试数据统一放在文本中,自动化程序自动去读取
        5. 解决回归测试,兼容性测试,压力测试,提高效率,保证产品质量

    缺点

        1. 不能取代手工测试;
        2. 手工测试比自动化测试发现的缺陷更多;
        3. 测试人员技能要求;

    误区:   

        1). 自动化测试完全替代手工测试
        2). 自动化测试一定比手工测试厉害
        3). 自动化可以发掘更多的BUG

分类:web(UI)自动化测试,app移动自动化测试,接口自动化测试,单元测试自动化测试

需求变动不频繁,项目周期长,项目需要回归测试——适合做web自动化测试

web自动化测试工具:QTP(web,桌面自动化),Selenium(主要做功能测试),Jmeter(基于Java,web,接口,性能测试),Loadrunner(web,性能),Robot framework(基于Python,关键字驱动)

web自动化测试:selenium,robot framework
App端自动化测试:Appium,Monkeyrunner,UIautomation
PC客户端(win32)自动化测试:QTP
接口自动化测试:Jmeter,Postman,httpUnit,RESTClient
云测平台:Testin,Testbird
性能测试:Jmeter,LoadRunner

二、web自动化测试工具 ——Selenium:

特点:开源软件,跨平台(linux,mac,windows),核心功能(能多个浏览器上进行自动化测试),多语言(java,python,ruby,JavaScript,c#),成熟稳定,功能强大(能实现商业工具大部分功能,因为开源,可以实现定制化功能)

Selenium家族要了解:SeleniumIDE + Selenium2.0(Selenium1.0+Webdriver)

三、Selenium IDE?【重点】

为什么学习IDE:
Selenium IDE是一个Firefox的插件,用于记录和播放用户浏览器的交互(录制web操作脚本)
    1. 使用Selenium IDE录制脚本,体验自动化脚本魅力
    2. 使用Selenium IDE录制的脚本转换为代码语言
(后期如果自己设计脚本,如果不知道什么方式定位元素,可使用此方法参考)

Selenium IDE 安装: 火狐浏览器 V35.0 选择 selenium IDE 2.9.1.1
1. 官网安装
    Version: 2.9.1.1
    通过官网安装插件:https://addons.mozilla.org/en-GB/firefox/addon/selenium-ide/versions/
2. 附加组件管理器
    1). 火狐浏览器 V24-V35
    2). 附加组件管理器-->搜索selenium IDE
    提示:
    1. IDE前面有个空格
    2. 附加组件管理器启动方式-   1) 工具菜单->附加组件 2) Ctrl+Shift+A
3. 离线安装
    下载:https://github.com/SeleniumHQ/selenium-ide/releases
    安装:下载好selenium_ide-2.9.1-fx.xpi直接拖入浏览器安装

界面介绍:

Selenium IDE界面

1. 文件:创建、打开和保存测试案例和测试案例集。编辑:复制、粘贴、删除、撤销和选择测试案例中的所有命令。Options : 用于设置seleniunm IDE。
2. 用来填写被测网站的地址。
3. 速度控制:控制案例的运行速度。
4. 运行所有:运行一个测试案例集中的所有案例。
5. 运行:运行当前选定的测试案例。
6. 暂停/恢复:暂停和恢复测试案例执行。
7. 单步:可以运行一个案例中的一行命令。
8. 录制:点击之后,开始记录你对浏览器的操作。
9. 案例集列表。
10. 测试脚本;table标签:用表格形式展现命令及参数。source标签:用原始方式展现,默认是HTML语言格式,也可以用其他语言展示。
11. 查看脚本运行通过/失败的个数。
12. 当选中前命令对应参数。
13. 日志/参考/UI元素/Rollup   

示例:
在base url输入https://www.baidu.com,点击录制按钮,开始录制
进入www.baidu.com,在搜索框中输入“淘宝官网”,点击百度一下,出来结果后,点击淘宝官网,进入淘宝官网,打开IDE结束录制,至此一个案例录制完毕
    注意:
    1. 录制:录制时红色录制按钮一定要打开->按下状态
    2. 回放:由于网络延迟原因-建议选择最低
    3. 浏览器:回放时浏览器要保持打开状态(否则点击回放,脚本无响应) 
    保存脚本,文件——save test case成html文件,导出成python语言,文件菜单->Export Test Cast As..->python2/unittest/WebDriver
    重点解释:
    1. id=kw:为百度搜索文本框id属性和值
    2. id=su: 为百度一下按钮id属性和值   

如何快速查找一个元素标签的属性和值?—— Firebug

定位调试插件 Firebug:FireBug插件是火狐浏览器一款插件,能够调试所有网站语言,同时也可以快速定位HTML页面中的元素;作用:定位元素(获取元素定位和查看元素属性); 在线安装: 1). 火狐浏览器 V35 2). 附加组件管理器-->搜索FireBug

Selenium IDE脚本编辑与操作 【了解】录制脚本时候是录制鼠标和键盘的所有在浏览器操作,那么脚本会出现多余的步骤,有时候我们需要手动填写脚本或修改脚本,所有我们有必要对Selenium IDE脚本编辑与操作有所了解;目的:手动修改或编写脚本(采用录制方式很容易记录出多余的操作)

    编辑一行命令:在Table标签下选中某一行命令,命令由command、Target、value三部分组成。可以对这三部分内容那进行编辑。

    插入命令:在某一条命令上右击,选择“insert new command”命令,就可以插入一个空白,然后对空白行进程编辑

    插入注释:鼠标右击选择“insert new comment”命令插入注解空白行,本行内容不被执行,可以帮助我们更好的理解脚本,插入的内容以紫色字体显示。

    移动命令:有时我们需要移动某行命令的顺序,我们只需要左击鼠标拖动到相应的位置即可。

    删除命令:选择单个或多个命令,然后点击鼠标右键选择“Delete”

    命令执行:选定要执行的命令点击单个执行按钮即可,注意:有一些命令必须依赖于前面命令的运行结果才能成功执行,否则会导致执行失败。

Selenium IDE常用command命令【了解】
    open(url)命令
    作用:打开指定的URL,URL可以为相对或是绝对URL;
    Target:要打开的URL;value值为空
        1). 当Target为空,将打开Base URL中填写的页面;
        2). 当Target不为空且值为相对路径,将打开Base URL + Target页面。如,假设Base URL为http://www.zhi97.com,而Target为/about.aspx,则执行open命令时,将打开http://www.zhi97.com/about.aspx
        3). 当Target以http://开头时,将忽略Base URL,直接打开Target的网址;对于url,http开头就是绝对路径           

    pause(waitTime)
    作用:暂停脚本运行
    waitTime:等待时间,单位为ms;//Target=1000

    goBack()
    作用:模拟单击浏览器的后退按钮;
    提示:由于没有参数,所以Target和Value可不填;

    refresh()
    作用:刷新当前页;
    提示:由于没有参数,所以Target和Value可不填;

    click(locator)
    作用:单击一个链接、按钮、复选框或单选按钮;
    提示:如果该单击事件导致新的页面加载,命令将会加上后缀“AndWait”,即“clickAnd Wait”, 或“waitForPageToLoad”命令;

    type(locator,value)
    作用:向指定输入域中输入指定值;也可为下拉框、复选框和单选框按钮赋值.
    Target:元素的定位表达式;
    Value:要输入的值;

    close()
    作用:模拟用户单击窗口上的关闭按钮;
    提示:由于没有参数,所以Target和Value可不填;

四. WebDriver了解与安装

- Webdriver (Selenium2)是一种用于Web应用程序的自动测试工具;
- 它提供了一套友好的API;说明:API:应用编程接口说明(WebDriver类库内封装非常多的方法,要使用这些方法,就需要友好的调用命名规则,API就是对库里的所有方法,参数,返回值的一些说明,有了这个,我们根据我们调用的方法名称,就知道这个方法有什么用,库有库的API,接口有接口的API,要使用一个库,就去看他的API,就可以用这个库来做项目开发)
- Webdriver完全就是一套类库,不依赖于任何测试框架,除了必要的浏览器驱动;必须要浏览器驱动,才能调用Webdriver

WebDriverAPI 支持的浏览器
    1. Firefox (FirefoxDriver)【推荐-本阶段学习使用】
    2. IE(InternetExplorerDriver)
    3. Opera(OperaDriver)
    4. Chrome (ChromeDriver)
    5. safari(SafariDriver)
    6. HtmlUnit (HtmlUnit Driver)
    提示:
        Firefox、Chrome:对元素定位和操作有良好的支持,同时对JavaScript支持也非常好。
        IE:只能在windows平台运行,所有浏览器中运行速度最慢
        HtmlUnit:无GUI(界面)运行,运行速度最快;
    推荐原因:1. Selenium IDE, 2. FireBug,3. 对WebDriver API支持良好

WebDriverAPI 支持的开发语言:Java,Python,PHP,JavaScript,Perl,Ruby,C#,可以用这些语言来调用webdriverAPI,用这个库里面的方法
官网文档:https://docs.seleniumhq.org/docs/03_webdriver.jsp

为什么要学习WebDriver? 自动化测试概念,WebDriver-定位元素,WebDriver-操作元素

环境搭建:要使用一种编程语言,也要搭建环境,把语言中别人写好的包安装好,还有就是要有编译器(对于java来说)或者解释器(对于python来说)来把我们写的代码编译或解释成计算机能懂的指令
    基于Python环境搭建:Windows系统(在这里我们以Windows7为案例),Python 3.5(以上版本),安装selenium包,浏览器,安装PyCharm   

    浏览器驱动:各个驱动下载地址:http://www.seleniumhq.org/download/
        火狐浏览器【推荐】
        FireFox 48以上版本:Selenium 3.X +FireFox驱动——geckodriver
        Firefox 48 以下版本:Selenium2.X 内置驱动

        IE浏览器(了解)
        IE 9以上版本:Selenium3.X +IE驱动
        IE 9以下版本:Selenium 2.X +IE驱动

        谷歌浏览器:selenium2.x/3.x +Chrome驱动

        注意:
    1. 浏览器的版本和驱动版本要一致!(如果是32bit浏览器而Driver是64bit则会导致脚本运行失败!)
    2. 浏览器驱动下载好后需要添加Path环境变量中(只要一个文件,例如.exe文件,它存在的目录路径是添加到环境变量中的,那么在系统的其他任何地方都可以执行这个这个文件,在添加环境变量的时候,一般是选择添加系统变量,而不是针对某个用户变量的path,添加时以;相隔,把路径粘贴进去即可),或者直接放到Python安装目录,因为Python以添加到Path中
     3. 推荐使用火狐浏览器(24、35)版

selenium 安装、卸载、查看命令
在安装selenium时,前提是Python3.5以上版本安装完毕且能正常运行
    安装:pip install selenium==2.48.0
    1). pip:通用的 Python 包管理工具。提供了对 Python 包的查找、下载、安装、卸载的功能
    2). install: 安装命令
    3). selenium==2.48.0: 指定安装selenium2.48.0版本(如果不指定版本默认为最新版本)
    卸载:pip uninstall selenium
    查看:pip show selenium

五、Webdriver的元素定位

为什么要学习元素定位方式?1. 让程序操作指定元素,就必须先找到此元素;2. 程序不像人类用眼睛直接定位到元素;3. WebDriver提供了八种定位元素方式

定位方式分类-汇总:
    1). id、name、class_name(指的是class这个属性对应的值):为元素属性定位
    2). tag_name(就是标签的名称):为元素标签名称
    3). link_text、partial_link_text:为超链接定位(a标签),只对链接有效,定位的是链接文本
    4). Xpath:为元素路径定位
    5). Css:为CSS选择器定位

Selenium Day1

元素定位【重点】
id,一般唯一,但重复也不报错

说明:通过元素的id属性来定位,HTML规定id属性在整个HTML文档中必须是唯一的,id定位就是通过元素的id属性来定位元素
前提:元素必须有id属性
方法:driver.find_element_by_id(id值)

实现案例-1需求:    1). 打开注册A.html页面,使用id定位,自动填写(账号A:admin、密码A:123456)    2). 填写完毕后,3秒钟关闭浏览器窗口  

案例实施步骤思路分析
1.导包 ——> from selenium import webdriver,from time import sleep
2.指定浏览器(实例化浏览器对象) ——> driver=webdriver.Firefox()
3.打开项目 ——> 打开注册A.html :driver.get(url)
4.找到元素(定位元素) ——> driver.find_element_by_id("")
5.操作元素 ——> 使用send_keys()方法发送数据: .send_keys("admin")
6.暂停 ——> sleep(3) 暂停3秒
7.关闭浏览器——> quit()

案例1代码实现:
from selenium import webdriver
from time import sleep

# 实例化浏览器
driver=webdriver.Firefox()
#  第二种写法:url=r'E:\...\注册A.html'  
# r的作用:被r修饰的字符串,字符串中的转义符不做转义使用
# 第三种写法:"file:///E:/.../注册A.html"
# /:斜杠,除法,5/3;\:反斜杠,目录结构

url='E:\\...\\注册A.html'  # url中\\转义
driver.get(url)
user=driver.find_element_by_id("userA")
user.send_keys("admin")
pwd=driver.find_element_by_id("passwordA") #这里的element没有s
pwd.send_keys("123456")
# 打完sleep后,ctrl+alt+空格,回车,快速导from time import sleep包
sleep(3)
driver.quit()

name,可重复
说明:通过元素的name属性来定位,name的属性值在当前文档中可以不是唯一的
前提:元素必须有name属性
方法:driver.find_element_by_name(name值)

class_name,同一元素可属于不同的class
说明:通过元素的class属性来定位
前提:元素必须有class属性
方法:find_element_by_class_name()

tag_name
说明:通过元素的标签名称,如:<input><a>... ,HTML本质就是由不同的tag(标签)组成,而每个tag都是指同一类,所以tag定位效率低, 一般不建议使用;tag_name定位就是通过标签名来定位;
前提:元素标签名在当前页面必须为唯一元素,或定位符合条件第一个元素;
返回:符合条件的第一个元素
方法: find_element_by_tag_name(标签名称) ——> 返回:符合条件的第一个标签

link_text
说明:只定位超链接<a>标签,它专门用来定位超链接文本(<a>标签</a>)
注意:必须为全部匹配本,需要传入a标签全部文本
方法:find_element_by_link_text(全部问本值)

找到元素后,单击以下click()
find_element_by_link_text(全部问本值).click()

partial_link_text
说明:它为link_text定位的补充说明,partial_like_text为模糊匹配;link_text全部匹配
注意:为模糊匹配,需要传入a标签局部文本-能表达唯一性
方法:find_element_by_partial_link_text(局部文本)

find_element[s]_by_XXX()
作用:查找定位所有符合条件的元素;返回的定位元素格式为数组(列表)格式;
说明:列表数据格式的读取需要指定下标(下标从0开始)

说明:使用tag_name获取第二个元素(密码框),即便页面只有唯一一个input标签元素,也一定要指定下标[0]
代码:driver.find_elements_by_tag_name("input")[1].send_keys("123456")

-----------------------------------------------------------------------------------------------------------------------------------
当在实际项目中标签没有id、name、class属性,或者id、name、class属性值为动态获取,随着刷新或加载而变化,要定位:Xpath,css定位

Xpath
说明:XPath即为XML Path 的简称,它是一种用来确定XML文档中某部分位置的语言。HTML可以看做是XML的一种实现,所以Selenium用户可以使用这种强大的语言在Web应用中定位元素。
XML:一种标记语言,用于数据的存储和传递。 后缀.xml结尾
提示:Xpath为强大的语言,那是因为它有非常灵活定位策略;

- Xpath定位策略(方式)
    路径-定位:绝对路径,相对路径
    利用元素属性-定位
    层级与属性结合-定位
    属性与逻辑结合-定位
    Xpath定位方法:driver.find_element_by_xpath()

    路径(绝对路径、相对路径):
        绝对路径:从最外层元素到指定元素之间所有经过元素层级路径 ;以单斜杠/开头,中间不能跳跃元素,如:/html/body/div/p[2]
        提示:绝对路径以/开始,使用Firebug可以快速生成,元素XPath绝对路径:使用在firebug中的html选项下,某一元素右键复制Xpath路径可得到绝对路径
        相对路径:从第一个符合条件元素开始(一般配合属性来区分);以双斜杠开头;后边必须跟标签名称或*(*表示所有标签)-Xpath路径内使用属性时,必须要使用@修饰,如://input[@id='userA']
        提示:相对路径以//开始,使用Friebug扩展插件FirePaht可快速生成,使用在firebug中的html选项下,某一元素右键复制最简Xpath路径可得到相对路径,但不一定找到,所以最好自己写
        提示:为了方便练习Xpath,可以在FireBug内安装扩展插件-FireFinder插件;火狐浏览器-->组件管理器-->搜索FireFinder

    利用元素属性
    说明:快速定位元素,利用元素唯一属性;
    示例:"//*[@id='userA']"  #Python中" "中再有字符串,要用单引号''   

    层级与属性结合
    说明:要找的元素没有属性,但是它的父级有;
    示例://*[@id='p1']/input

    属性与逻辑结合
    说明:解决元素之间个相同属性重名问题
    示例://*[@id='telA' and @class='telA']

    Xpath-延伸
    //*[text()="xxx"]                                         文本内容是xxx的元素,一定是全部匹配
    //*[starts-with(@attribute,'xxx')]                属性以xxx开头的元素
    //*[contains(@attribute,'xxx')]                 属性中含有xxx的元素

CSS
说明:CSS(Cascading Style Sheets)是一种语言,它用来描述HTML和XML的元素显示样式; (css语言书写两个格式:写在HTML语言中<style type="text/css">...   ;写在单独文件中 后缀.css)
而在CSS语言中有CSS选择器(不同的策略选择元素),在Selenium中也可以使用这种选择器;
提示:在selenium中极力推荐CSS定位,因为它比XPath定位速度要快;css选择器语法非常强大

CSS定位常用策略 (方式):find_element_by_css_selector()
-id选择器

注意:id选择器必须以#修饰,如:#userA <选择id属性值为userA的所有元素>
如:find_element_by_css_selector("#userA")

-class选择器
注意:以.修饰,如:.telA <选择class属性值为telA的所有元素>;元素必须有class属性

-元素选择器,就是标签名
格式:element  如:input <选择所有input元素>

-属性选择器
格式:[attribute=value] 或者 input[attribute=value]如:[placeholder="password"] <选择所有placeholder属性值为password的值> 

-层级选择器
说明:根据元素的父子关系来选择
格式:element>element,如:p>input <返回所有p元素下所有的input元素>
提示:> 可以用空格代替 如:p input 或者 p [type='password']

CSS延伸
input[type^='p'] 说明:type属性以p字母开头的元素
input[type$='d'] 说明:type属性以d字母结束的元素
input[type*='w'] 说明:type属性包含w字母的元素

-----------------------------------------------------------------------------------------------------------------------------------
定位(另一种写法)【了解】
说明:通过查看find_element_by_id底层实现方法,发现底层也是调用的By类方法进行的封装;
说明:第二种方法使用By类的封装的方法,所以需要导入By类包
导包:from selenium.webdriver.common.by import By
方法:find_element(By.ID,"userA")
    备注:需要两个参数,第一个参数为定位的类型由By提供,第二个参数为定位的具体方式

示例:
    driver.find_element(By.CSS_SELECTOR,'#emailA').send_keys("123@126.com")
    driver.find_element(By.XPATH,'//*[@id="emailA"]').send_keys('234@qq.com')
    driver.find_element(By.ID,"userA").send_keys("admin")
    driver.find_element(By.NAME,"passwordA").send_keys("123456")
    driver.find_element(By.CLASS_NAME,"telA").send_keys("18611111111")
    driver.find_element(By.TAG_NAME,'input').send_keys("123")
    driver.find_element(By.LINK_TEXT,'访问 新浪 网站').click()
    driver.find_element(By.PARTIAL_LINK_TEXT,'访问').click()

Day02总结

六、元素操作方法

1. clear()            清除文本
2. send_keys()        模拟输入
3. click()            单击元素

#修改电话号码要先清除原先内容,再传值
driver.find_element_by_css_selector("#tel").clear()
driver.find_element_by_css_selector("#tel").send_keys("13811111111")

七、WebDriver操作浏览器常用方法

1. maximize_window()     最大化 --> 模拟浏览器最大化按钮

driver.maximize_window()

2. set_window_size(100,100) 浏览器大小 --> 设置浏览器宽:距离左边屏幕的长度、高:距离上边屏幕的长度(单位为像素点)

driver.set_window_size(300,300)

3. set_window_position(300,200)    浏览器位置 --> 设置浏览器位置,(x,y)

driver.set_window_position(300,200)

4. back()                            后退 --> 模拟浏览器后退按钮,在本窗口打开第二个网站才能后退

driver.back()

5. forward()                        前进 --> 模拟浏览器前进按钮,要先后退才能前进

driver.forward()

6. refresh()                        刷新 --> 模拟浏览器F5刷新

driver.refresh()

7. close()                            关闭 --> 模拟浏览器关闭按钮(关闭单个窗口):关闭当前主窗口

driver.close()

8. quit()                            关闭 --> 关闭所有WebDriver启动的窗口

driver.quit()

八、WebDriver其他常用方法【掌握】

1. size                                返回元素大小
2. text                                 获取元素的文本
3. title                                 获取页面title
4. current_url                      获取当前页面URL
5. get_attribute("xxx")         获取属性值;xxx:要获取的属性
6. is_display()                     判断元素是否可见
7. is_enabled()                   判断元素是否可用

提示:
    1. size、text、title、current_url:为属性,调用时无括号;如:xxx.size
    2. title、current_url:使用浏览器实例化对象直接调用;    如: driver.title

# 获取用户名文本框大小
size=driver.find_element_by_id("userA").size
print('size:',size)

# 获取文本值,a标签内容
text=driver.find_element_by_id("fwA").text
print('a标签text:',text)

# 获取title
title=driver.title
print('title:',title)

# 获取当前页面url
url=driver.current_url
print('url:',url)

# 获取a标签href属性值
href=driver.find_element_by_id("fwA").get_attribute("href")
print('href属性值为:',href)

# 判断span是否显示
display=driver.find_element_by_css_selector('span').is_displayed()
print('span标签是否显示:',display)

# 判断取消按钮是否可用
enabled=driver.find_element_by_id('cancelA').is_enabled()
print('取消按钮是否可用:',enabled)

执行结果:
size: {'height': 30, 'width': 163}
a标签text: 访问 新浪 网站
title: 注册A
url: file:///E:/%E6%B5%8B%E8%AF%95/%E8%AF%BE%E4%BB%B6/Web%E8%87%AA%E5%8A%A8%E5%8C%96/Web%E8%87%AA%E5%8A%A8%E5%8C%96%E8%AF%BE%E4%BB%B6/02img/%E6%B3%A8%E5%86%8CA.html
href属性值为: http://www.sina.com.cn/
span标签是否显示: False
取消按钮是否可用: False

--------------------------------------------------------------------------------
九、鼠标操作方法

说明:在WebDriver中将操作鼠标的方法封装在ActionChains类中
1. context_click()            右击 --> 此方法模拟鼠标右键点击效果
说明:在ActionChains类中的鼠标右键方法是个已知的bug,因为它能点击右键出现菜单,但无法选择右键菜单选项,因此方法了解即可
2. double_click()            双击 --> 此方法模拟双标双击效果
3. move_to_element()        悬停 --> 此方法模拟鼠标悬停效果【掌握】
4. perform()                执行 --> 此方法用来执行以上所有鼠标方法

代码实现:
导包:from selenium.webdriver.common.action_chains import ActionChains
当我们不知道小括号内需要什么参数时,可以当光标在括号里的时候,按ctrl+p,就会有提示
实例化ActionChains对象:Action=ActionChains(driver)
username要先元素定位到:
username=driver.find_element_by_css_selector("#userA")
perform为执行所有鼠标操作:
调用右键方法:element=Action.context_click(username).perform()
或调用双击方法:element=Action.double_click(username).perform()   
或调用悬停方法:Action.move_to_element(element).perform()

5. drag_and_drop()            拖动 --> 此方法模拟双标拖动效果,选定拖动源元素释放到目标元素

源元素 socure=driver.find_element_by_id(xxx)
目标元素 target=driver.find_element_by_id(xxx)
调用方法 Action.drag_and_drop(source,target).perform()
#另一个拖拽方法,by offset,指定拖动的位置
调用方法 Action.drag_and_drop_by_offset(source,xoffset,yoffset).perform()

十、键盘操作

模拟键盘上一些按键或组合键的输入,如:ctrl+C,ctrl+V;WebDriver中对键盘的操作都封装在Keys类中

方法:send_keys(Keys.ss,"a")
导包:from selenium.webdriver.common.keys import Keys

常用键盘操作:
1. send_keys(Keys.BACK_SPACE)删除键(BackSpace)
2. send_keys(Keys.SPACE)空格键(Space)
3. send_keys(Keys.TAB)制表键(Tab)
4. send_keys(Keys.ESCAPE)回退键(Esc)
5. send_keys(Keys.ENTER)回车键(Enter)
6. send_keys(Keys.CONTROL,'a') 全选(Ctrl+A)
7. send_keys(Keys.CONTROL,'c')复制(Ctrl+C)

from selenium.webdriver.common.keys import Keys
# 定位用户名
element=driver.find_element_by_id("userA")

# 输入用户名
element.send_keys("admin1")

# 删除1,调用一次,删除一个,这里就是删除“1”
# 选中Keys,按ctrl+B,或者ctrl+鼠标左键,就可以查看Keys的源代码,知道Keys后面可以接什么关键字
element.send_keys(Keys.BACK_SPACE)

# 全选,一定要先全选才去复制
element.send_keys(Keys.CONTROL,'a')

# 复制
element.send_keys(Keys.CONTROL,'c')

# 粘贴
driver.find_element_by_id('passwordA').send_keys(Keys.CONTROL,'v')

十一、元素等待

概念:由于网络速度原因,电脑配置原因,服务器处理请求原因,WebDriver定位页面元素时如果未找到,会在指定时间内一直等待的过程;

-显式等待:
概念:使WebDriver等待指定元素条件成立时继续执行,否则在达到最大时长时抛出超时异常(TimeoutException)
提示:1). 在WebDriver中把显式等待的相关方法封装在WebDriverWait类中;2). 等待是判定条件成立时,那如何判断条件成立?相关判断的方法封装在expected_conditions类中

如果用户名文本框存在,就输入admin
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait

url = r'E:\测试\课件\Web自动化\Web自动化课件\02img\注册A.html'
driver = webdriver.Firefox()
driver.get(url)

"""
        WebDriverWait(driver, timeout, poll_frequency=0.5)
        1). driver:浏览器对象
        2). timeout:超时的时长,单位:秒
        3). poll_frequency:检测间隔时间,默认为0.5秒,即隔多长时间找一次元素
        调用方法 until(method):直到..时
        1). method:调用EC.presence_of_element_located(element)
             element:调用By类方法进行定位
"""
element = WebDriverWait(driver, 5).until(EC.presence_of_element_located((By.ID, 'userA')))
element.send_keys("admin")

- 隐式等待:
说明:实际工作中,一般都使用隐式等待;如果定位某一元素定位失败,那么就会触发隐式等待有效时长,等待元素加载指定的时长,如果在指定时长内加载完毕,则继续执行,否则抛出NoSuchElementException异常,如果元素在第一次就定位到则不会触发隐式等待时长
显式与隐式区别:
    - 作用域:显式等待为单个元素有效,隐式为全局元素,全局指当前主窗口中的所有元素
    - 方法:显式等待方法封装在WebDriverWait类中,而隐式等待则直接通过浏览器实例化对象调用

隐式等待调用方法
方法:implicitly_wait(timeout)
          (timeout:为等待最大时长,单位:秒)
调用:driver.implicitly_wait(10) 【重点-掌握】(driver:为浏览器实例化对象名称)
# 一般紧跟在driver实例化后还有driver.maximize_window() 后
提示:一般超时时长默认为30秒

Day03总结

十二、下拉选择框<Select类>

说明:下拉框就是HTML中<select>元素;Select类是WebDriver为解决select标签定位诞生的,此类定位的是select标签
select方法:
select_by_index()                --> 根据option索引来定位,从0开始
select_by_value()                --> 根据option属性 value值来定位
select_by_visible_text()            --> 根据option显示文本来定位
注意:
导包:1. Select(Ctrl+Alt+空格);2. from selenium.webdriver.support.select import Select

# 城市选项-暂停2秒后选择上海A,暂停2秒后选择重庆,暂停2秒后选择广州
# 导包
from time import sleepfrom selenium import webdriverfrom selenium.webdriver.support.select import Select
driver=webdriver.Firefox()
driver.get(r"e:\课堂\WebDriver\注册实例.html")
# 第一种方式 -使用tag_name
tags=driver.find_elements_by_tag_name("option")
for tag in tags:
     if tag.get_attribute("value")=="sh":
         sleep(2)
         tag.click()
for tag in tags:
     if tag.text=="重庆":
         tag.click()
for tag in tags:
     if tag.get_attribute("value")=="gz":
         sleep(2)
         tag.click()

# 第二种 使用css
driver.find_element_by_css_selector([value='sh']").click()
sleep(2)
driver.find_element_by_css_selector([value='cq']").click()
sleep(2)
driver.find_element_by_css_selector("[value='gz']").click()

# 第三种方法 通过使用Select类来定位; 注意:Select类只能定位select标签webelement=driver.find_element_by_css_selector("select")
# 实例化Select类
select=Select(webelement)
# 通过索引来定位
select.select_by_index(1)
sleep(2)
select.select_by_index(3)
sleep(2)
select.select_by_index(2)
# 通过value属性来选择
# 实例化Select
select=Select(webelement)
select.select_by_value("sh")
sleep(2)
select.select_by_value("cq")
sleep(2)
select.select_by_value("gz")
# 通过显示文本来定位
select=Select(webelement)
select.select_by_visible_text("上海")
sleep(2)
select.select_by_visible_text("重庆")
sleep(2)
select.select_by_visible_text("广州")
sleep(2)
driver.quit()

十三、警告框处理

说明:WebDriver中对处理警告框的操作,有专用的处理方法;
提示:HTML中常用的对话框有三种,处理的方法都一样:1). alert;2). confirm;3). prompt

警告框处理方法:
- text --> 返回alert/confirm/prompt中的文字信息
- accept()                --> 接受对话框选项
- dismiss()            --> 取消对话框选项

# 定位alerta按钮
driver.find_element_by_id("alerta").click()

# 获取警告框
alert=driver.switch_to.alert

# 打印警告框文本
print(alert.text)

# 接受警告框
alert.accept()

# 取消警告框,取消和接收不能同时使用
alert.dismiss()

十四、控制滚动条

说明:WebDriver类库中并没有直接提供对滚动条进行操作方法,但是它提供了可调用JavaScript脚本的方法,所以我们可以通过JavaScript脚本来达到操作滚动条的目的;
备注:滚动条:一种可控制程序显示范围的组件;JavaScript:一种流行脚本语言,可以操作HTML标签;JavaScript学习资料:http://www.w3school.com.cn/js/js_intro.asp

滚动条应用情况:
在HTML页面中,由于前端技术框架的原因,页面元素为动态显示,元素根据滚动条的下拉而被加款;页面注册同意条款,需要滚动条到最底层,才能点击同意

备注:js控制滚动条语句有很多种,如:js=document.documentElement.scrollTop=1000;但是推荐使用JS调用window句柄去控制;

# 需求:案例-1 注册页面A,打开页面2秒后,滚动条拉倒最底层
#. 设置JavaScritp脚本控制滚动条 js="window.scrollTo(0,1000)" (0:左边距,水平像素;1000:上边距,滚动条向下移动10000像素;单位像素)
#. WebDriver调用js脚本方法  driver.execute_script(js)
# 最底层,实际工作中,一般页面较大要设置(0,10000)到最底端
js1="window.scrollTo(0,1000)"

# 最顶层
js2="window.scrollTo(0,0)"

# 执行最底层
driver.execute_script(js1)

# 执行最顶层
driver.execute_script(js2)

十五、frame表单切换

frame:HTML页面中的一种框架,主要作用是在当前页面中指定区域显示另一页面元素;(HTML语言中,frame/iframe标签为表单框架)
说明:在WebDriver类库中封装了HTML页面中使用frame表单框架技术定位的方法

方法:
    - 切换方法 driver.switch_to.frame("表单name属性值或id属性值,一般是name")----切换表单方法
    - driver.switch_to.default_content()----恢复到默认页面(在frame表单中操作其他页面,必须先回到默认页面,才能进一步操作);原因:因为注册A页面内源码中没有iframe标签,要回到主页面才有iframe标签

需求:案例-2 注册实例.html, 此页面有三个注册界面,先填写最上边注册信息,其次填写注册A页面注册信息,最后填写注册B页面信息;定位方式不限
完成当前页面注册信息;
调用表单切换方法(switch_to.frame("myframe1"))切换到注册用户A表单中
调用恢复默认页面方法(switch_to.default_content())
调用表单切换方法(switch_to.frame("myframe2"))切换到注册用户B表单中

十六、多窗口切换

说明:在HTML页面中,经常有a标签也就是超链接,这些链接在被执行时,有的会在新的窗口打开链接;在WebDriver中封装了获取当前窗口句柄方法和获取所有窗口句柄的方法以及切换指定句柄窗口的方法;(句柄:英文handle,窗口的唯一识别码)

方法:
    1). driver.current_window_handle        --> 获取当前窗口句柄
    2). driver.window_handles                --> 获取所有窗口句柄
    3). driver.switch_to.window(handle)        --> 切换指定句柄窗口

需求:点击注册A页面链接,在打开的页面,填写A页面注册信息;
1. 获取注册实例.html当前窗口句柄
2. 点击注册实例.html页面中注册A页面
3. 获取所有窗口句柄
4. 遍历判断窗口句柄并切换到注册A页面
5. 操作注册A页面元素,注册信息

from time import sleep
from selenium.webdriver.common.keys import Keys
from selenium import webdriver
driver=webdriver.Firefox()
driver.get(r"e:\课堂\WebDriver\注册实例.html")
# 获取当前窗口句柄
current=driver.current_window_handle
print("启动后当前窗口句柄为:",current)
# 第一步定位注册A页面并点击
driver.find_element_by_partial_link_text("注册A网页").click()
# 获取所有窗口句柄
handles=driver.window_handlesprint("所有窗口句柄为:",handles)
# 遍历及切换
for handle in handles:
     if handle != current:
         # 执行切换窗口方法
         driver.switch_to.window(handle)
         # 第二步填写注册A信息         driver.find_element_by_css_selector("#userA").send_keys("admin")         driver.find_element_by_css_selector("#passwordA").send_keys("admin")         driver.find_element_by_css_selector("#telA").send_keys("1861111111")         driver.find_element_by_css_selector("#emailA").send_keys("admin@123.com")
sleep(2)
driver.quit()

十七、窗口截图

截图:把当前操作页面,截图保存到指定位置;自动化脚本是由程序去执行的,因此有时候打印的错误信息并不是十分明确。如果在执行出错的时候对当前窗口截图保存,那么通过图片就可以非常直观地看到出错的原因。在WebDriver类库中,提供了截图方法,我们只需要调用即可

方法:get_screenshot_as_file(imgpath) --> 截取当前窗口 (imgpath:图片保存路径)
例如:driver.get_screenshot_as_file("../Image/img02.png")

十八、验证码

验证码:一种随机生成的信息(图片、数字、字母、汉字、算术题)等为了防止恶意的请求行为,增加应用的安全性。在Web应用中,大部分系统在用户登陆的时候都要求输入验证码,而我们在设计自动化脚本时候,就需要面临这验证码的问题。WebDriver类库中没有对验证码处理的方法,但是在这里可以叙说下针对验证码的几种常用处理方式

1. 去掉验证码:(测试环境下-采用)开发做,注释掉
2. 设置万能掩码:(生产环境,线上环境,现网,已经有用户使用了-采用)开发做 用逻辑或or
3. 验证码识别技术:(通过Python-tesseract来识别图片类型验证码;识别率很难达到100%)
4. 记录cookie: (通过记录cookie进行登录-推荐)

- Cookie


cookie

②浏览器请求后,服务器验证了登陆的信息后,把信息加密,返回一个响应还有cookie的格式给浏览器,客户端把加密的信息储存
③ 客户端请求时,按cookie格式给服务器加密的登陆信息去解密
④服务器响应登陆成功的数据给服务端

Cookie是一小段的文本信息;格式:python中的字典(键值对组成)
Cookie产生:客户端请求服务器,如果服务器需要记录该用户状态,就向客户端浏览器颁发一个Cookie格式
Cookie使用:当浏览器再请求该网站时,浏览器把请求的网址连同该Cookie一同提交给服务器,服务器检查该Cookie,以此来辨认用户状态。
- 用户第一次登陆时,勾选下次直接登陆或者记住密码,就是采用记录cookie实现的
- cookie内记录用户名和密码(加密)信息,只要请求时服务器收到cookie,就识别成功,默认为已登陆。

第一次人工登陆拿到了cookie值,以后自动化脚本请求就直接从第3步开始,可以跳过验证码

WebDriver中对cookie操作提供相应的方法

方法:
    1. get_cookie(name)                    --> 获取指定cookie (name:为健名)
    2. get_cookies()                    --> 获取本网站所有本地cookies
    3. add_cookie(str)                    -->    添加cookie(str:为python中的字典格式)

# 需求:登陆百度,获取cookie; 使用获取的cookie,在WebDriver中,添加Cookie,达到登陆目的
# 登陆baidu,登陆的时候抓取 (BAIDUID,BDUSS)
# 使用add_cookie()方法,添加 (BAIDUID,BDUSS)键和值
# 调用刷新方法 driver.refresh()

from selenium import webdriver
import time
driver=webdriver.Firefox()
driver.get("https://www.baidu.com")
# cookie的填写不要有中文
driver.add_cookie({'name':'BAIDUID','value':'根据实际填写'})
driver.add_cookie({'name':'BDUSS','value':'根据实际填写'})
# 获取单个
cookieprint("get_cookie值为:",driver.get_cookie("name"))
# 获取所有的cookies
for cookie in driver.get_cookies():
     print("%s---->%s"%(cookie["name"],cookie["value"]))
time.sleep(3)
driver.refresh()
time.sleep(3)
driver.quit()

Day04总结

十九、UnitTest框架

框架:框架英文单词FrameWork;为解决一类事情的功能集合;UnitTest框架是专门用来进行执行代码测试的框架;UnitTest能够组织多个用例(自动化测试一个.py文件一个完整的过程是一个用例)去执行,提供丰富的断言方法(断言:让程序判断程序执行的结果是否与人预期的相符),提供丰富的日志与测试结果(测试结果就是我们的测试报告)

- UnitTest核心要素(UnitTest框架)

TestCase
TestSuite
TextTestRunner
Fixture

TestCase
说明:(翻译:测试用例)一个TestCase就是一条测试用例;
使用:
    1. 导包:import unittest            --> 导入unitest框架
     2. 继承:unittest.TestCase            --> 新建测试类继承unittest.TestCase
提示:
    1). 测试用例:在自动化测试中,一条用例就是一个完整的测试流程(有打开页面,也有关闭页面面);               
    2). 测试方法(以def开头的)名称命名必须以test开头;(原因:unittest.TestCase类批量运行的方法是搜索执行test开头的方法)

# 导包-->unittest框架
import unittest
# 想要运行所有方法,就把光标移到class Test01最后右键点运行
# 想要单独运行test01就把光标移到def test01后面右键点运行
# UnitTest不需要实例化Test01,也会自动运行里面的test开头的方法
# 必须要继承unittest.TestCase ,才算一条测试用例
class Test01(unittest.TestCase):
    def test01(self):
        print("test01被执行")
    def test02(self):
        print("test02被执行")

#注意:Python命名规范:不要以数字,汉字,开头;不要重复关键字;不能含特殊字符,空格
# unittest.main() 它会自动搜索这里所有test开头的方法执行
if __name__ == '__main__':
    unittest.main()

TestSuite
明:(翻译:测试套件)多条测试用例集合在一起,就是一个TestSuite;
使用:
    1. 实例化:    suite=unittest.TestSuite()  (suite:为TestSuite实例化的名称)
    2. 添加用例:suite.addTest(ClassName("MethodName"))   (ClassName:为类名;MethodName:为方法名)
    3. 添加扩展:suite.addTest(unittest.makeSuite(ClassName))    (搜索指定ClassName内test开头的方法并添加到测试套件中)

提示:
    1). 一条测试用例(.py)内,多个方法也可以使用测试套件
    2). TestSuite需要配合TextTestRunner才能被执行

TextTestRunner
说明:(翻译:测试执行)是用来执行测试用例套件
使用:
    1. 实例化: runner=unittest.TextTestRunner() (runner:TextTestRunner实例化名称)
    2. 执行:    runner.run(suite)    (suite:为测试套件名称)

# 导入unittest
import unittest

# 导入用例(.py)Test02 是类
from Day05.Case.test02import Test02
from Day05.Case.iwe_03import Test03

if __name__== '__main__':
    # 实例化suite
    suite=unittest.TestSuite()
    # 调用 添加用例方法
    suite.addTest(Test02("test001"))
    suite.addTest(Test02("test003"))
    suite.addTest(Test03("test001"))
    runner=unittest.TextTestRunner()
    runner.run(suite)

或者:
# 导入unittest
import unittest
# 导入用例(.py)
from Day05.Case.test02 import Test02
from Day05.Case.iwe_03 import Test03
if __name__ == '__main__':
     # 实例化
    suite suite=unittest.TestSuite()
     # 调用 添加用例方法 ,传入类名
     suite.addTest(unittest.makeSuite(Test02))
     # 实例化TexTestRunner()--->测试执行
     runner=unittest.TextTestRunner()
     # 调用run方法执行
     runner.run(suite)

Fixture,就是两个函数:setUp和tearDown
说明:是一个概述,对一个测试用例环境的搭建和销毁就是一个Fixture;
使用:
    1. 初始化(搭建):def setUp(self)        --> 无论在什么地方,首先执行    (setUp:此方法继承于unittest.TestCase)       
    2. 结束(销毁):    def tearDown(self)        --> 无论在什么地方,最后执行    (tearDown:此方法继承于unittest.TestCase)
提示:
    1. 必须继承unittest.TestCase类,setUp、tearDown才是一个Fixture;
    2. setUp:一般做初始化工作,比如:实例化浏览器、浏览器最大化、隐式等待设置
    3. tearDown:一般做结束工作,比如:退出登录、关闭浏览器
    4. 如果一个测试类有多个test开头方法,则每个方法执行之前都会运行setUp、结束时运行tearDown

需求:使用UnitTest框架对iweb_shop项目测试;登陆进行测试

操作步骤分析:
- 导包 import unittest
- 新建测试类并继承unittest.TestCast
- 新建一个Fixture(setUp、tearDown)
- 新建登录方法
- if __name__ == '__main__':
- unittest.main()执行

代码实现
import unittest
from time import sleep
from selenium import webdriver
class TestLoginOut(unittest.TestCase):
    def setUp(self):
        #self开头就变成了self的属性,driver就可以在下一个方法中使用
        self.driver=webdriver.Firefox()
        url = "http://localhost/iwebshop/"
        self.driver.get(url)
        self.driver.implicitly_wait(10)
        self.driver.maximize_window()
        print("setUp")
    
    def test_login(self):
        driver=self.driver
        driver.find_element_by_link_text("登录").click()
        driver.find_element_by_css_selector("input[alt*='邮箱']").send_keys("admin")
        driver.find_element_by_css_selector("input[alt*='密码']").send_keys("123456")
        driver.find_element_by_css_selector(".submit_login").click()
        sleep(3)
        driver.find_element_by_css_selector(".reg").click()

    def tearDown(self):
        sleep(2)
        self.driver.quit()
        print("tearDown")

# 有了这一句,以后就在这里执行,TestLoginOut 类的内容只在当前文件执行
# 当别的.py文件内,如要导入这个包的TestLoginOut类,
# 在别的.py文件执行时,就不会再执行一次TestLoginOut 的内容

if __name__ == '__main__':
    # 调用main方法执行unitetest内所有test开头方法
    unittest.main()

需求:将test01.py..test10.py共10条用例,将这10条用例批量执行;

问题
使用suite.addtest(unittest.makeSuite(className))导入10条测试类
addtest()需要添加10次,所以我们要使用defaultTestLoader

defaultTestLoader【重点】
说明:
    使用unittest.defaultTestLoader()类,通过该类下面的discover()方法自动搜索指定目录下指定开头的.py文件,并将查找到的测试用例组装到测试套件;
用法:
    test_dir = './'
    disconver = unittest.defaultTestLoader.discover(test_dir, pattern='iweb_*.py')
    (test_dir为要指定的目录 ./为当前目录;pattern:为查找的.py文件的格式 )

运行:
    runner=unittest.TextTestRunner()
    runner.run(disconver)

import unittest
if __name__== '__main__':
    # 搜索指定的目录指定的py文件,并返回所有搜索文内test开头的方法 ,返回的形式以测试套件的形式返回
    '''定义测试套件'''
    discover=unittest.defaultTestLoader.discover("../Lx",pattern="iweb_*.py")
    # 指定测试套件
    unittest.TextTestRunner().run(discover)

defaultTestLoader与TestSuite区别
1. TestSuite可以添加TestCase中所有test开头的方法和添加指定的test开头方法;
2. defaultTestLoader搜索指定目录下指定开头.py文件,并添加TestCase内所有test开头的方法,不能指定添加方法;
提示:defaultTestLoader属于TestSuite另一种实现方式;

- UnitTest断言

断言:让程序代替人为判断测试程序执行结果是否符合预期结果的过程

自动化脚本在执行的时候一般都是无人值守状态,我们不知道执行结果是否符合预期结果,所以我们需要让程序代替人,为检测程序执行的结果是否符合预期结果,这就需要使用断言;

UnitTest断言分类
    1. 基本布尔型断言
    2. 比较断言
    3. 复杂断言

基本布尔型断言(掌握常用即可):结果只有True和False

序号    断言方法                                               断言描述
1         assertEqual(arg1, arg2, msg=None)    验证arg1=arg2,不等则fail 【掌握】
2         assertNotEqual(arg1, arg2, msg=None)验证arg1 != arg2, 相等则fail
3         assertTrue(expr, msg=None)                  验证expr是true,如果为false,则fail
4         assertFalse(expr,msg=None)                 验证expr是false,如果为true,则fail
5         assertIsNone(expr, msg=None)              验证expr是None,不是则fail
6         assertIsNotNone(expr, msg=None)         验证expr不是None,是则fail
7         assertIn(arg1, arg2, msg=None)              验证arg1是arg2的子串,不是则fail【掌握】

需求:iweb项目登陆,输入正确用户名和密码,断言登录成功的用户名是否为admin,如果断言失败截图保存

扩展:图片名称为动态-时间;图片名称添加断言错误信息

实现步骤分析
成功登陆
获取登陆后的信息
添加断言

断言主要代码:注意:断言捕获异常,必须为:AssertionError
# 导包
import unittest
import time
import sys
from time import sleep
from selenium import webdriver
class Iweb_Login(unittest.TestCase):
     def setUp(self):
         # 实例化浏览器
         self.driver=webdriver.Firefox()
         # 打开项目网站
         self.driver.get("http://localhost/iwebshop/")
         # 浏览器最大化
         self.driver.maximize_window()
         # 设置隐式等待
         self.driver.implicitly_wait(30)
     
    # 正向登陆
     def test_iweb_login(self):
         # 获取driver
         driver=self.driver
         # 点击登录按钮跳转到登录页面
         driver.find_element_by_link_text("登录").click()
         # 定位用户名及操作
         driver.find_element_by_css_selector("[alt*='邮箱']").send_keys("111111")
         # 定位密码及操作         driver.find_element_by_css_selector('[name="password"]').send_keys("123456")
         # 点击登陆按钮
         driver.find_element_by_css_selector(".submit_login").click()
        # 断言代码-----------------------------------------------------------------------------------------------------
         # 获取登录后的提示信息
         text=driver.find_element_by_css_selector(".loginfo").text
         try:
             self.assertIn("admin",text)
         except AssertionError:
             # 设置时间字符串(获取运行时系统时间)
             nowtime=time.strftime("%Y_%m_%d %H_%M_%S") 
            # sys.exc_info()[1]必须要在except AssertionError:内捕获错误信息
             driver.get_screenshot_as_file("../Image/%s--%s.jpg"%(nowtime,sys.exc_info()[1]))
             # 抛出捕获的异常
             raise AssertionError
         # 断言代码----------------------------------------------------------------------------------------------------
         # 退出
         sleep(3)
         driver.find_element_by_link_text("安全退出").click()
     def tearDown(self):
         sleep(2)
         # 关闭浏览器
         self.driver.quit()
if __name__ == '__main__':
     unittest.main()

测试结果-HTML测试报告

HTML测试报告就是执行完测试用例后以HTML(网页)方式将执行结果生成报告
测试报告是本次测试目的最终体现形态,测试报告内包含了有关本次测试用例的详情,哪条通过哪条不通过都会有信息

HTML生成报告方式
    1. Export Test Results (UnitTest 自带)
    2. HTMLTestRunner(第三方模板)【重点】

Export Test Results (自带)提示:适合单条用例执行时使用,且要在继承了unittest.testcase里面,像之前的discover里面就不可以这样获取报告

Export Test Results 自带报告  


自带报告生成操作图

HTMLTestRunner【重点】

HTMLTestRunner

测试报告 生成步骤分析
先下载:HTMLTestRunner.zip,里面包含HTMLTestRunner.py文件
    1. 复制HTMLTestRunner.py文件到项目文件夹
    2. 导入HTMLTestRunner、UnitTest包   
    3. discover加载要执行的用例(discover=unittest.defaultTestLoader.discover(test_dir,pattern="test*.py"))
    4. 设置报告生成路径和文件名 (file_name=file_dir+nowtime+"Report.html")
    5. 打开报告 with open(file_name,'wb') as f: 二进制的读取,二进制写入的时候可以写图片
    6. 实例化HTMLTestRunner对象:runner=HTMLTestRunner(stream=f,[title],[description])
        参数说明:(stream:文件流,打开写入报告的名称及写入编码格式)
        ([],为可选;title为报告标题,如XXX自动化测试报告;description:为说明;比如操作系统、浏览器等版本)
    7. 执行:runner.run(discover)

实现代码
import time
# from 文件名称 import 类名
from CodeEdit.LX04.Tools.HTMLTestRunner import HTMLTestRunner
import unittest

# 加载当前目录
test_dir='.'
# 加载当前目录下iweb开头的.py文件
discover=unittest.defaultTestLoader.discover(test_dir,pattern="test*.py")

if __name__ == '__main__':
    # 定义报告目录
    file_dir="../Report/"
    # 定义报告名称格式
    nowtime=time.strftime("%Y-%m-%d %H_%M_%S")
    # 报告完整路径和名称
    file_name=file_dir+nowtime+"Report.html"
    with open(file_name,"wb") as f:
        # 实例化HTMLTestRunenr对象,传入报告文件流f
        runner=HTMLTestRunner(stream=f,title="iweb_shop项目Web自动化测试报告",description="测试用例共计2条")
        runner.run(discover)

-----------------------------------------------------------------------------------------------------------------------------------

补充断言资料:

基本布尔型断言
序号    断言方法                                                    断言描述
1        assertEqual(arg1, arg2, msg=None)        验证arg1=arg2,不等则fail 【常用】
2        assertNotEqual(arg1, arg2, msg=None)    验证arg1 != arg2, 相等则fail
3        assertTrue(expr, msg=None)                  验证expr是true,如果为false,则fail 【常用】
4        assertFalse(expr,msg=None)                 验证expr是false,如果为true,则fail 【常用】
5        assertIs(arg1, arg2, msg=None)                验证arg1、arg2是同一个对象,不是则fail
6        assertIsNot(arg1, arg2, msg=None)            验证arg1、arg2不是同一个对象,是则fail
7        assertIsNone(expr, msg=None)                   验证expr是None,不是则fail
8        assertIsNotNone(expr, msg=None)              验证expr不是None,是则fail
9        assertIn(arg1, arg2, msg=None)                   验证arg1是arg2的子串,不是则fail
10      assertNotIn(arg1, arg2, msg=None)            验证arg1不是arg2的子串,是则fail
11      assertIsInstance(obj, cls, msg=None)            验证obj是cls的实例,不是则fail
12      assertNotIsInstance(obj, cls, msg=None)      验证obj不是cls的实例,是则fail

比较断言
1、assertAlmostEqual (first, second, places = 7, msg = None, delta = None):
    验证first约等于second。 palces: 指定精确到小数点后多少位,默认为7
2、assertNotAlmostEqual (first, second, places, msg, delta):
    验证first不约等于second。 palces: 指定精确到小数点后多少位,默认为7 注: 在上述的两个函数中,如果delta指定了值,则first和second之间的差值必须≤delta
3、assertGreater (first, second, msg = None):
    验证first > second,否则fail
4、assertGreaterEqual (first, second, msg = None):
    验证first ≥ second,否则fail
5、assertLess (first, second, msg = None):
    验证first < second,否则fail
6、assertLessEqual (first, second, msg = None):
    验证first ≤ second,否则fail
7、assertRegexpMatches (text, regexp, msg = None):
    验证正则表达式regexp搜索匹配的文本text。 regexp:通常使用re.search()
8、assertNotRegexpMatches (text, regexp, msg = None):
    验证正则表达式regexp搜索不匹配的文本text。 regexp:通常使用re.search() 说明:两个参数进行比较(>、≥、<、≤、约等、不约等)

复杂断言
1、assertListEqual(list1, list2, msg = None):
    验证列表list1、list2相等,不等则fail,同时报错信息返回具体的不同的地方
2、assertTupleEqual (tuple1, tuple2, msg = None):
    验证元组tuple1、tuple2相等,不等则fail,同时报错信息返回具体的不同的地方
3、assertSetEqual (set1, set2, msg = None):
    验证集合set1、set2相等,不等则fail,同时报错信息返回具体的不同的地方
4、assertDictEqual (expected, actual, msg = None):
    验证字典expected、actual相等,不等则fail,同时报错信息返回具体的不同的地方


Day05总结
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,547评论 6 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,399评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,428评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,599评论 1 274
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,612评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,577评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,941评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,603评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,852评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,605评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,693评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,375评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,955评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,936评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,172评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,970评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,414评论 2 342