0


自动化测试概念(以及部分框架,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()


本文转载自: https://blog.csdn.net/xiaoshuang221/article/details/136502105
版权归原作者 小双221 所有, 如有侵权,请联系我们删除。

“自动化测试概念(以及部分框架,selenium,unittest)”的评论:

还没有评论