自动化测试概念(以及部分框架,selenium,unittest)

1.自动化测试概念

  能够代替手工测试的方法和工具都可以称为自动化测试

  

  例如

  针对不同的测试对象

  web自动化   app自动化  接口自动化

  

  针对不同的测试类型

  功能测试自动化   链接测试自动化   性能测试自动化

  安全测试自动化

  

  实施自动化测试的目的在于

  1.人无法去完成对应的工作或者付出成本非常高

  2.可以快速的进行回归测试

  

2.自动化测试的分类

  1.基于代码的自动化   -- 单元测试自动化

  2.基于协议的自动化   -- 集成或者接口自动化

  3.基于UI的自动化     -- 系统测试的自动化

  

  注:一般情况下

  从代码难度讲   自动化代码难度会越来越低

  从实施难度讲   实施的难度越来越高,同时变更的影响也会越来也大

   

3.自动化测试用例的过程

  1.制定自动化测试计划

    自动化测试的目的

    全面自动化

针对部分业务流程和功能的部分自动化

    注:全面自动化实施难度会更高

  2.整理需要实施自动化的需求

  3.将对应的手工测试用例转换为自动化测试用例

  4.搭建自动化测试环境

      自动化测试环境一般会和手工测试环境分开

  注:手工测试环境往往更新会比较快

      环境当中也会存在很多脏数据(异常数据)

  可能会影响自动化测试脚本执行

  5.编写自动化测试脚本

      将自动化测试用例通过代码设计自动化测试脚本

  自动化测试脚本编写完成会经过调试和运行

  将其放入自动化测试用例库

  注:一般来说,自动化测试脚本要多次运行

      保证能够稳定之后才能放入用例库

注:自动化测试脚本转换为自动化测试用例的比例

需要经过长时间的调试运行(多个迭代版本的调试运行)

相应的转换率才会越来越高

  6.执行自动化测试脚本

    在执行结束之后,需要对脚本的执行结果进行检查

 1.脚本执行错误,分析脚本错误原因

     是否是环境或者数据引起,更新到正确的环境下重新运行

 如果不是这些情况,从用例库中移除,继续进行调试

 2.脚本执行后检查到错误

     确认是否是发现bug,一般由测试人员手工执行检查是否是有bug

 再次执行自动化脚本进行确认,确认后可以提交bug

 如果手工执行没有发现到错误,检查是脚本问题还是环境问题

 如果是环境问题,那么更新到正确环境下,重新运行

 如果不是,从用例库中移除,继续调试

 如果自动化测试脚本的执行通过率不高

 那么自动化测试脚本的维护成本就非常高

 一般来说,多次执行之后,自动化测试脚本的执行通过率会越来越高

 理论上 执行率可以达到100%  

        通过率会根据软件系统bug情况来确定

注:当然发现越多,说明测试脚本的有效性会越来越好

    注:自动化脚本的编写和执行是一个迭代过程

   用例的转化率会越来越高,执行率也会越来越高

   7.如果发现了bug,进行记录

     一般情况下会使用手工和自动化两种方式对缺陷进行回归验证。

4.实施UI自动化需要掌握的技能

  1.掌握一门编程语言

    java  python  

  2.掌握前端一些知识

    html + css + js

  3.熟悉网络知识

    http协议

  4.熟悉自动化测试框架

    web框架   selenium  robotframework

    app框架   appium

5.selenium的版本

  现在是selenium3的版本

  使用selenium需要安装对应浏览器的驱动程序

  使用selenium通过浏览器的驱动,对页面的元素进行操作

  通过驱动可以获取服务器返回的响应,通过对响应结果的检查,来确定操作是否正确

  

  注:不同的浏览器的有不同的驱动,同时也要针对浏览器的不同版本

  

自动化测试脚本selenium

1.selenium自动化框架的版本

  2,3的版本主要是通过驱动程序去调用浏览器接口,来实现对页面操作

  1的版本通过中间代理的方式,截取浏览器发送的请求,由selenium再组装

  请求并接收服务器的响应,这种方式来实现对页面的操作

  

  2,3版本下写的脚本不需要做太多改动,基本上可以运行

  但是1版本下的脚本不能在2,3版本下运行

  

2.页面元素定位的方法

  一般通过页面的html代码(浏览器的F12工具)

  来查找页面元素对应的代码,获取到对应的定位信息

  1.通过id来定位

示例

#test.find_element_by_id('kw').send_keys("软件测试")

test.find_element("id","kw").send_keys("软件测试")

  2.通过name来定位

#test.find_element_by_name("wd").send_keys("软件测试")

test.find_element("name","wd").send_keys("软件测试")

  3.通过class来定位

#test.find_element_by_class_name("s_ipt").send_keys("软件测试")

test.find_element("class name","s_ipt").send_keys("软件测试")

注:class name之间是空格,不要使用下划线

  4.通过tag来定位

  这种方式一般不用来去定位页面标签,但是如果页面的元素非常少

  可以唯一定位到一个标签的时候,也可以使用

test.find_element_by_tag_name("a").click()

  5.使用链接的文本来定位 a 标签

#test.find_element_by_link_text("hao123").click()

test.find_element("link text","hao123").click()

  6.使用链接的部分文本来定位a标签

#test.find_element_by_partial_link_text("hao").click()

test.find_element("partial link text","hao").click()

3.使用xpath来定位

  1.使用绝对路径来定位

  绝对路径是从页面的第一个标签  /html开始

  如果在某个路径上,同级出现多个相同的标签,需要写上标签的索引值,索引值从1开始

  例如  div[1]  div[2]  

  test.find_element_by_xpath("/html/body/div/form/div[2]/div/input").

  send_keys("test")

  注:这种方法不推荐使用,除非页面非常简单,页面代码不会经常改动

  2.使用标签名+属性名的方式

示例

test.find_element_by_xpath("//input[@name='account']").send_keys("mayi")

标签名由于是绝对路径  标签名前面使用 //    例如这里是  //input

属性名需要加上  @   例如这里是@name

然后属性的值,因为在一个字符串中,要注意字符串里面的引号使用  例如外面是双引号,里面使用单引号

 3.先定位到上级标签,再使用上下层级的关系,通过路径来定位

示例

test.find_element_by_xpath("//form[@method='get']/div[2]/div/input").send_keys("mayi")

这里input标签如果没有属性,那么可以找到能够使用属性定位的上级标签

 4.如果标签有多个属性,可以通过and运算符将多个属性拼接起来进行定位

示例

test.find_element_by_xpath("//input[@name='account' and @class='layui-input']").send_keys("mayi")

注:属性一样要加@符号

   同样该方法也适用于先定位上级标签再去通过路径去定位

   

 5.使用工具获取xpath地址来进行定位

 这里是使用F12工具提供xpath路径地址

//*[@id="kw"]   注:这里的* 是代表任意标签,使用里面的属性进行定位

xpath同样可以使用定位方式+定位信息这种的方法来定位

示例

test.find_element('xpath','/html/body/div/form/div[2]/div/input').send_keys("test")

元素定位

1.对浏览器的控制

get -- 相对输入url地址,跳转到对应的页面

       如果一次性执行多个get方法,会在同一个页面进行多次的跳转

   

set_window_size(宽,高)   -- 会按照设置的宽和高来显示页面的内容窗口

maximize_window()  -- 将页面窗口直接最大化的展示

minimize_window() -- 将页面窗口最小化到任务栏

back  -- 后退到前一个页面  但是要注意能不能后退

forward  -- 前进到下一个页面  但是要注意有能够前进的访问历史

refresh -- 刷新当前页面

示例

test.get("http://192.168.150.131/zentao/user-login.html")

test.get("https://www.baidu.com/")

test.back()

test.forward()

test.find_element('id','kw').send_keys("软件测试")

test.refresh()

2.对页面元素标签的操作

clear  -- 清除输入框已经输入的内容

send_keys -- 向输入框输入内容

click  -- 模拟用户在页面点击的操作

submit -- 模拟表单的提交,不用于需要触发js脚本的情况

注:如果输入框有内容,直接使用send_keys 会在内容末尾追加一部分

   可以先使用clear将内容进行清除,再输入内容

   

3.获取页面元素的内容和属性

text  -- 读取页面元素显示在页面的内容

示例

print(test.find_element('xpath',"//*[@id='login-panel']/div[1]/h4").text)

注:也可以把内容赋值一个变量,然后去检查是否正确

size  -- 读取出页面元素的样式大小

示例

print(test.find_element('xpath',"//*[@id='login-panel']/div[1]/h4").size)

get_attribute  -- 获取到页面元素某一个属性的值

示例

print(test.find_element('id',"account").get_attribute('class'))

注: text和size在使用时没有括号

4.鼠标的操作模拟

需要先导入对应鼠标操作模块

from selenium.webdriver import ActionChains

记录需要操作的元素的地址信息

adress=test.find_element('xpath','//*[@id="login-form"]/form/table/tbody/tr[4]/td/a')

通过鼠标操作的模块 实现鼠标的模拟

ActionChains(test).click_and_hold(forget_pw).perform()

ActionChains  -- 对哪里浏览器实例进行操作

click_and_hold  -- 对某个页面元素进行操作

perform  -- 释放对应的操作

鼠标的模拟常见有以下几种情况

click_and_hold 左键点击并按住

Release 释放左键

--这两个操作往往是一起实施的

Context_click 右键

Double_click 双击

5.键盘输入的模拟

需要导入键盘模拟的模块

from selenium.webdriver.common.keys import Keys

定位需要模拟键盘操作的页面元素

addr=test.find_element('link text','关于百度')

在页面元素上使用send_keys方法来发起键盘操作

使用 Keys 方法,发送键盘的内容

Keys可以发送键盘上的功能按键

例如  Keys.DOWN  模拟键盘上的方向键

      Keys.F1  模拟键盘上的F1

  

也可以模拟一些组合按键

例如   addr.send_keys(Keys.CONTROL,'a')  模拟键盘上实施 ctrl + a 的全选操作

6.使用模块对下拉框进行操作

导入对应的模块

from selenium.webdriver.support.select import Select

注:也可以使用键盘的模拟来实现对下拉框的操作

   如果下拉框的数据每次是动态生成的,那么如果用键盘来模拟

   可能选择的数据就不准确

   

下拉框的选择一共3个方法

1 select_by_index # 通过索引定位    通过下拉框中值的索引  从0开始

2 select_by_value # 通过value值定位 通过下拉框的标签 value属性值来定位

  示例

  <option value="normal" selected="selected" data-keys="zhengchang zc">正常</option>

3 select_by_visible_text # 通过文本值定位,通过标签的文本值来定位

  示例

  上个示例标签的  正常  就是标签的文本

  

7.获取title和url

title和url对一个页面而言,不需要针对页面的标签进行操作

可以直接用浏览器对象来操作

示例

print(test.title)   -- 获取title

print(test.current_url)  --获取url

注:可以通过title或url来验证是否跳转到正确页面

8.implicitly_wait方法

这个方法会设置超时的时间值,在这个时间值内,如果服务器返回了响应

代码会立刻开始执行

如果服务器返回的时间超过设置的值,程序会报错

这个方法和sleep不同在于,sleep是将代码停止执行

等待时间结束后, 继续执行剩下的代码

注:一般情况下使用implicitly_wait方法

   但是在有些情况可能会需要使用sleep来等待页面数据处理和返回

   在编写脚本的过程中,可以灵活的使用这两个方法

   

9.切换到内嵌的子页面

使用switch_to.frame(定位信息)

去切换到内嵌的页面去

示例

frame_addr=test.find_element('id','loginIframe')

test.switch_to.frame(frame_addr)

切换回外层的页面

切换到上一级页面

switch_to.parent_frame()

切换到最外层的页面

switch_to.default_content()

10.网页的切换

chrome每打开一个网页,会开启对应新的进程

要切换网页,需要先获取当前打开的网页  current_window_handle  标识

然后开打新的页面之后,获取所有的页面标识  window_handles

注:所有的页面标识实际上一个列表

可以通过列表的读取,排除当前的页面的标识

使用 switch_to.window(标识) 切换到新打开页面的标识

注:网页的打开和关闭是由操作系统来管理的

   每次打开网页都需要记录对应的值,因为每次打开网页都会有一个不同的标识

   如果需要打开多个网页,可以每一个单独的去记录

   

11.页面的关闭和浏览器的关闭

close  -- 关闭当前打开的页面

quit -- 退出浏览器

12.警告框的处理

在网页中,做出一些操作之后,页面会弹出一个警告框

这种警告框一般情况下,弹出后不能继续操作页面

需要使用 switch_to_alert()  跳转到警告框

警告框一共分三种,都是用这个方法来跳转

alert : 只有一个确定按钮

confirm:  由确定和取消按钮

prompt:  有文字输入框

可以通过跳转的方法,使用

test.switch_to_alert().text  text 打印出警告框中的文本

test.switch_to_alert().accept()  相当于点击这个确定按钮

test.switch_to_alert().dismiss() 相当于关闭或者取消

test.switch_to_alert().send_keys("软件测试") 在警告框中的输入框中输入内容

注:该方法只对prompt这种类型警告框有效

   警告框是没有定位消息,使用 switch_to_alert()直接进行处理

12.操作浏览器的cookie信息

注意cookie信息的格式

在请求中可能存在多个cookie

可以使用

test.get_cookies() 获取当前页面的所有cookie信息

格式是以 列表和字典,cookie以列表中元素的形式存在

每个cookie有多个键值对以字典的形式存在

示例

[

{'domain': '.baidu.com', 'expiry': 1637739952, 'httpOnly': False, 'name': 'BA_HECTOR', 'path': '/', 'secure': False, 'value': 'at258h848h808heka31gprnt10r'},

{'domain': '.baidu.com', 'httpOnly': False, 'name': 'H_PS_PSSID', 'path': '/', 'secure': False, 'value': '35105_31254_35049_34584_34517_35233_34578_35167_34814_26350_35145'},

{'domain': '.baidu.com', 'expiry': 1669272352, 'httpOnly': False, 'name': 'BAIDUID', 'path': '/', 'secure': False, 'value': '0656D86D246547F6839C047B2C580A05:FG=1'},

{'domain': '.baidu.com', 'expiry': 3785219999, 'httpOnly': False, 'name': 'BIDUPSID', 'path': '/', 'secure': False, 'value': '0656D86D246547F6786AF018BBEFDE6C'},

{'domain': '.baidu.com', 'expiry': 3785219999, 'httpOnly': False, 'name': 'PSTM', 'path': '/', 'secure': False, 'value': '1637736351'},

{'domain': 'www.baidu.com', 'expiry': 1638600352, 'httpOnly': False, 'name': 'BD_UPN', 'path': '/', 'secure': False, 'value': '12314753'},

{'domain': 'www.baidu.com', 'httpOnly': False, 'name': 'BD_HOME', 'path': '/', 'secure': False, 'value': '1'}

]

可以用 add_cookie(cookie_dict) 方法来添加cookie信息

注意的是,cookie信息应该以字典形式存在,要保证键值对的完整

示例

test.add_cookie({'name':'BDUSS','value':'TE1bmFOOG1QcHhydzRvQ3BjbFh2REZkY2NIeEtDQXlsejdEUC1kdUNmb3hhOFZoSVFBQUFBJCQAAAAAAAAAAAEAAAAX0fMea28xOTgwMQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADHenWEx3p1hR'})

添加cookie之后,可以使用refresh这个方法,刷新页面让cookie生效

实际上向服务器发送请求,在请求中携带添加的cookie信息

可以使用 get_cookie(name): 读取某个cookie信息

需要写入cookie中name的值

示例

print(test.get_cookie('PSTM'))

delete_cookie(name,optionsString)

删除cookie信息,name是key的名称,optionsString是该cookie的选项,包括路径,域等信息

delete_all_cookies() 直接删除所有的cookie信息

unittest框架

1.构建自动化脚本测试工程

  1.需要使用方法去验证脚本执行成功

  2.同时记录脚本执行失败的情况

  3.实现对测试脚本的管理

  4.实现对测试数据的管理

  

2.使用unittest框架来记录脚本的执行情况

构建测试的类,继承于unittest中的TestCase这个类

class t_calc(unittest.TestCase):

    def setUp(self) -> None:

        print("用例执行开始")

    设计一个方法,对某个类的对象中一个方法结果进行验证

可以理解为这是一个测试用例

    def test_add(self):

    生成这个要测试的实例

        t1=calc(10,20)

使用unittest当中的断言,对实例的方法返回的结果进行验证

如果验证通过,这个用例会在结果当中记录为通过

如果验证不通过或者执行过程的当中发生错误,会记录不通过或者记录发生的错误情况

        self.assertEqual(t1.add(),30)

    def test_sub(self):

        t2=calc('a',20)

        self.assertEqual(t2.add(),200)

    def tearDown(self) -> None:

        print("用例执行结束")

执行结果有

.  -- 代表这个用例执行通过

F  -- 代表这个用例执行不通过,和预期结果不相同

E  -- 代表这个用例执行中发生了错误

self.assertEqual 这个方法称为断言,继承于unittest中的TestCase这个类

断言方法有很多种,根据实际情况来使用

assertEqual 两个值是否相等,如果相等,则通过,不相等记为不通过

setUp   -- 称为初始化方法,可以理解为每个用例执行之前需要执行一次

tearDown --做一些清理和结束的工作,每个用例执行之后需要执行一次

这两个方法的名字是固定的,不能修改

def test_add(self): 每个用例的方法名前面需要使用 test 做为开头

2.测试方法的执行

在代码的末尾使用

if __name__=="__main__":

    unittest.main()

会将所有的被测试的脚本全部执行

通过构建测试套件,选择对应的用例来执行

if __name__=="__main__":

    #生成一个测试套件

    suit=unittest.TestSuite()

#在测试套件中添加需要执行的用例

#使用addTest方法

#用例格式使用的是  类名('方法名')  方法名要做为字符串来导入

    suit.addTest(t_calc("test_add"))

#生成一个用例的执行实例

    runner=unittest.TextTestRunner()

#使用执行的实例去执行测试套件中的用例

    runner.run(suit)

3.使用HTMLTestRunner生成测试报告

实际上HTMLTestRunner是继承于unittest的,同样需要生成测试套件

并使用TextTestRunner去执行套件中的用例,但是它会将执行的结果收集起来

使用html模板来生成网页的报告

导入对应的模块

from HTMLTestRunner import HTMLTestRunner

在生成模块的实例

#htmltestrunner会写入一个文件,需要指定文件写入路径 文件名  和内容写入方式

fr = open('C:/Users/mycom/Desktop/testcalc01.html', 'wb')

#使用htmltestrunner生成用例的执行器,htmltestrunner会自动捕获用例的执行情况并进行一个记录

#stream -- 指定需要写入的文件对象

#title  -- html页面title

#description  -- 网页body中的提示信息

runner = HTMLTestRunner(stream=fr, title='报告', description='用例执行情况')

#使用runner去执行测试套件

runner.run(suit)

#文件写完了,关闭文件读写通道

fr.close()

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值