第一章 selenium封装
市场上主流框架设计模式
关键字驱动设计思路与实现
关键字驱动的设计思路与实现
目前市场上自动化框架的模式。两种
Pom设计模式:代码功底,纯代码进行测试,代码表现出来。特点:项目结构清晰。流程分成一个个的页面。
流程:登录–选择商品–添加购物车-下单–支付
登录一个页面对象
下单一个页面对象
支付一一个页面对象.
缺点:代码功底的要好
关键字驱动:简单的
会写代码的。写代码逻辑打开浏览器在输入框输入
yaml数据格式
功能测试自动化测试。
只要知道怎么去触发这个条件做自动化测试就行。
怎么刷,腾讯课堂实现了这个功能。
想刷花
找到刷花的操作实现
excel数据驱动实现
自动化框架优化扩展
关键字封装
访问方法
输入方法
点击方法
等待方法
关闭方法
ui_demo.py
from selenium import webdriver
import time
class Base:
driver = webdriver.Chrome()
# 访问
def open(self,url):
self.driver.get(url)
# 找元素 什么方式
def locator(self,by,value):
return self.driver.find_element(by,value)
# 输入内容
def on_input(self,by,value,txt):
self.locator(by,value).send_keys(txt)
# 点击按钮
def on_click(self,by,value):
self.locator(by,value).click()
# 等待 1、强制等待 2、隐式等待(全部加载完成) 3、显示等待(找到后就跳过)
def wait(self,n):
time.sleep(n)
# 关闭窗口
def close(self):
self.driver.quit()
test.py
from ui_demo import Base
driver = Base()
driver.open("http://www.baidu.com")
driver.on_input('id','kw',"自动化测试封装")
driver.on_click('id','su')
driver.wait(3)
driver.on_click('xpath','//*[@id="1"]/h3/a')
driver.wait(2)
driver.close()
第二章 unitTest
基于命令行来运行测试框架,实现自动化测试在实际运行时出现有包找不到的异常。
当需要通过命令行来运行工程,实现执行,就必须要将执行文件放在根路径下
问题:如果要多次不同数据对一个流程进行测试,那每一次都需要写一套完整的测试用例
测试用例的管理一般基于UnitTest/PyTest来进行管理,会更为的高效简洁
UnitTest:
是目前应用占据大半壁江山的一套测试框架,最初是用于单元测试,随着自动化测试发展,到现在成为自动化测试技术的主流应用,尤其是接口自动化。
因为UnitTest中封装有非常多的内容,且可以和其他模块进行完美cp组合,所以在用例管理上和代码管理上会有更加大的便利四大特色:
1.测试用例管理
2.测试套件和运行器,能够更有效地针对业务来进行用例管理,包括测试报告的集成
3.Setup和Teardown,前置与后置条件
4.断言机制,你只需要通过self.即可直接调用
环境部署:
1.UnitTest是一个测试用例框架
2.python安装时默认会有一个builtin模块,UnitTest框架是默认集成在python中的。意味着只要安装了python就有UnitTest
3.只需要通过import unittest即可实现调用
一)模板如下
"""
UnitTest测试框架应用:
1、类名继承unittest.TestCase
2、测试用例:所有测试用例,都是以函数形式存在,函数名称必须以test开头
3、用例加载顺序:UnitTest中有默认的用例加载顺序: 0-9 A-Z a-z
4、所有的前置后置都有等级存在:class级别,method级别
method级别:与用例相关联,每条用例执行前运行前置、执行后运行后置
class级别:
1、必须定义装饰器@classmethod
2、所有用例内容执行前只运行一次,所有用例内容执行后只运行一次
5、cls对象只在class级别前后位置中进行定义,而调用则还是通过self进行调用
"""
# 导入UnitTest模块
import unittest
#如何真正意义意义上应用UnitTest框架:必须在类名继承unittest.TestCase
class UnitDemo(unittest.TestCase):
# class级别的前置与后置
@classmethod
def setUpClass(cls) -> None:
print('@classmethod前置')
@classmethod
def tearDownClass(cls) -> None:
print("@classmethod后置")
# 前置条件:method级别
def setUp(self) -> None:
print('前置条件')
# 后置条件:method级别
def tearDown(self) -> None:
print('后置条件')
# 测试用例:所有测试用例,都是以函数形式存在,函数名称必须以test开头
def test_1login(self):
print('用例一')
def test_2delete(self):
print('用例二')
# 普通函数:封装逻辑代码,以便在测试用例下调用
def login(self):
print('我是普通函数的封装')
# 用例下调用普通函数
def test_3login(self):
self.login()
# 要运行测试用例
if __name__ == '__main__':
# UnitTest执行测试用例行为
unittest.main()
二)加入关键字驱动
base_demo.py
from selenium import webdriver
import time
class Base:
def __init__(self):
self.driver = webdriver.Chrome()
# 访问
def open(self,url):
self.driver.get(url)
# 找元素
def locator(self,by,value):
return self.driver.find_element(by,value)
# 输入内容
def on_input(self,by,value,txt):
self.locator(by,value).send_keys(txt)
# 点击
def on_click(self,by,value):
self.locator(by,value).click()
# 等待
def wait(self,n):
time.sleep(n)
# 关闭窗口
def closes(self):
self.driver.quit()
unit_demo.py
# 导入UnitTest模块
import unittest
from base_demo import Base
from selenium import webdriver
from time import sleep
# driver = Base()
#如何真正意义意义上应用UnitTest框架:必须在类名继承unittest.TestCase
class UnitDemo(unittest.TestCase):
# driver = Base()
# #class级别的前置与后置
# @classmethod
# def setUpClass(cls) -> None:
# cls.driver.open('https://www.baidu.com')
#
# @classmethod
# def tearDownClass(cls) -> None:
# cls.driver.closes()
# 前置条件:method级别
def setUp(self) -> None:
self.driver = Base()
self.driver.open("https://www.baidu.com")
# 后置条件:method级别
def tearDown(self) -> None:
self.driver.closes()
# 测试用例:所有测试用例,都是以函数形式存在,函数名称必须以test开头
def test_1login(self):
self.driver.on_input('id','kw','用例一')
self.driver.on_click('id','su')
self.driver.wait(3)
def test_2delete(self):
self.driver.on_input('id','kw','用例二')
self.driver.on_click('id','su')
self.driver.wait(3)
# 普通函数:封装逻辑代码,以便在测试用例下调用
def login(self):
print('我是普通函数的封装')
self.driver.on_input('id','kw','用例三')
self.driver.on_click('id','su')
self.driver.wait(3)
# 用例下调用普通函数
def test_3login(self):
self.login()
# 要运行测试用例
if __name__ == '__main__':
# UnitTest执行测试用例行为
unittest.main()
三)cls对象的赋值
"""
UnitTest测试框架应用:
1、类名继承unittest.TestCase
2、测试用例:所有测试用例,都是以函数形式存在,函数名称必须以test开头
3、用例加载顺序:UnitTest中有默认的用例加载顺序: 0-9 A-Z a-z
4、所有的前置后置都有等级存在:class级别,method级别
method级别:与用例相关联,每条用例执行前运行前置、执行后运行后置
class级别:
1、必须定义装饰器@classmethod
2、所有用例内容执行前只运行一次,所有用例内容执行后只运行一次
5、cls对象只在class级别前后位置中进行定义,而调用则还是通过self进行调用
6、修改cls对象的值,在全局生效,需要通过类名,对象进行赋值操作才可以生效,而通过self,对象进行赋值只能够在当下函数中生效
"""
# 导入UnitTest模块
import unittest
#如何真正意义意义上应用UnitTest框架:必须在类名继承unittest.TestCase
from time import sleep
from selenium import webdriver
class UnitDemo(unittest.TestCase):
# class级别的前置与后置
@classmethod
def setUpClass(cls) -> None:
cls.driver = webdriver.Chrome()
cls.driver.get("https://www.baidu.com")
cls.title = None #定义全局变量
Cls.tt = “c测试”
@classmethod
def tearDownClass(cls) -> None:
cls.driver.quit()
# # 前置条件:method级别
# def setUp(self) -> None:
# self.driver = webdriver.Chrome()
# self.driver.get("https://www.baidu.com")
# # 后置条件:method级别
# def tearDown(self) -> None:
# self.driver.quit()
# 测试用例:所有测试用例,都是以函数形式存在,函数名称必须以test开头
def test_1login(self):
input_ = self.driver.find_element_by_id('kw')
input_.clear()
input_.send_keys("self.tt")
button_ = self.driver.find_element_by_id("su")
button_.click()
sleep(2)
#打印出的是None
print(self.driver.title)
#打印出实际页面的标题
self.title = self.driver.title
print(self.title)
#修改cls.title = None的值的全局变量
UnitDemo.title = self.driver.title
def test_2delete(self):
input_ = self.driver.find_element_by_id('kw')
input_.clear()
input_.send_keys("appium")
button_ = self.driver.find_element_by_id("su")
sleep(3)
button_.click()
sleep(3)
# 普通函数:封装逻辑代码,以便在测试用例下调用
def login(self):
input_ = self.driver.find_element_by_id('kw')
input_.clear()
input_.send_keys("selenium")
button_ = self.driver.find_element_by_id("su")
button_.click()
sleep(3)
# 用例下调用普通函数
def test_3login(self):
self.login()
# 要运行测试用例
if __name__ == '__main__':
# UnitTest执行测试用例行为
unittest.main()
"""
UnitTest测试框架应用:
1、类名继承unittest.TestCase
2、测试用例:所有测试用例,都是以函数形式存在,函数名称必须以test开头
3、用例加载顺序:UnitTest中有默认的用例加载顺序: 0-9 A-Z a-z
4、所有的前置后置都有等级存在:class级别,method级别
method级别:与用例相关联,每条用例执行前运行前置、执行后运行后置
class级别:
1、必须定义装饰器@classmethod
2、所有用例内容执行前只运行一次,所有用例内容执行后只运行一次
5、cls对象只在class级别前后位置中进行定义,而调用则还是通过self进行调用
6、修改cls对象的值,在全局生效,需要通过类名,对象进行赋值操作才可以生效,而通过self,对象进行赋值只能够在当下函数中生效
"""
# 导入UnitTest模块
import unittest
#如何真正意义意义上应用UnitTest框架:必须在类名继承unittest.TestCase
from time import sleep
from selenium import webdriver
class UnitDemo(unittest.TestCase):
# class级别的前置与后置
@classmethod
def setUpClass(cls) -> None:
cls.driver = webdriver.Chrome()
cls.driver.get("https://www.baidu.com")
cls.title = None
@classmethod
def tearDownClass(cls) -> None:
cls.driver.quit()
# # 前置条件:method级别
# def setUp(self) -> None:
# self.driver = webdriver.Chrome()
# self.driver.get("https://www.baidu.com")
# # 后置条件:method级别
# def tearDown(self) -> None:
# self.driver.quit()
# 测试用例:所有测试用例,都是以函数形式存在,函数名称必须以test开头
def test_1login(self):
input_ = self.driver.find_element_by_id('kw')
input_.clear()
input_.send_keys("自动化测试")
button_ = self.driver.find_element_by_id("su")
button_.click()
sleep(2)
#打印出的是None
print(self.driver.title)
#打印出实际页面的标题
self.title = self.driver.title
print(self.title)
#修改cls.title = None的值的全局变量
UnitDemo.title = self.driver.title
#断言
self.assertEqual(self.title,"自动化测试_百度",'断言失败')
# 3.11111111111 3.1111111112 无限接近的判断语句
self.assertAlmostEqual(3.11111111,3.11111112,msg='失败')
# 当一个变量为空或者None或者False的时候,从布尔值的角度考虑都属于False
a = ''
self.assertTrue(a,msg='失败')
def test_2delete(self):
input_ = self.driver.find_element_by_id('kw')
input_.clear()
input_.send_keys("appium")
button_ = self.driver.find_element_by_id("su")
sleep(3)
button_.click()
sleep(3)
# 普通函数:封装逻辑代码,以便在测试用例下调用
def login(self):
input_ = self.driver.find_element_by_id('kw')
input_.clear()
input_.send_keys("selenium")
button_ = self.driver.find_element_by_id("su")
button_.click()
sleep(3)
# 用例下调用普通函数
def test_3login(self):
self.login()
# 要运行测试用例
if __name__ == '__main__':
# UnitTest执行测试用例行为
unittest.main()
第三章YAML
Yaml介绍与部署:
企业级自动化测试一定会遵循数据与代码分离的形态来实现。
所以有了数据驱动的概念。将在实际测试过程中所关联的数据内容,专门提取成一个独立存在的个体,通过读取文件来导入测试数据。类似于工具中的参数化。
主流的数据驱动:
excel :
针对小白而言,特别友好的一种数据驱动形态。维护起来会非常麻烦。
yaml、py、json:
维护非常的方便,极大地降低代码的编写。对于技术能力不好的人而言,很头疼。Yaml数据驱动:
yaml是一种文件格式,是各类编程语言下非常常用的一种文件格式。一般用于配置文件和数据驱动的内容管理。
python下的yaml实现:
1.安装: pip install PyYaml
2.内容定义:yaml有自己的规范化的语法,对于强迫症患者来说是非常非常非常友好的一
种语法。
传统的测试数据内容一般而言是各种数据类型的内容。如何要批量填入一整套数据内容,会通过一个列表或字典的格式将其保存会更加方便
通过横杠空格的方式定义list的内容,横杠后面一点要关联空格
通过冒号空格定义字典内容,冒号后面一点要加空格
获取yaml中的数据:
1、UniTtest下通过ddt的@file_data可以完美契合UnitTest实现数据驱动
2、通过yaml自身的函数形态获取数据内容
3、yaml的数据驱动下,一个用例对应一个yaml文件
4、yaml中的锚点和引用:
锚点通过&进行定义
引用通过*进行使用
<<表示追加引用
列表
1.test.yaml
# 第一版
# 定义list格式的数据内容
- 1
- 2
- 3
- 4
- 5
- yaml_read.py
#获取yaml文件
file = open('./data/test.yaml','r',encoding='utf-8')
# 直接遍历
for line in file.readlines():
print(line)
# 基于yaml库实现yaml文件的key2.2': 123}读取
value = yaml.load(stream=file,Loader=yaml.FullLoader)
print(value) #得到一个列表
字典格式:
1.test01.yaml
# 字典格式
key: value
ke1: value1
key2:
key2.1: value2.1
key2.2: '123'
嵌套
# 嵌套类型
-
key1: value
-
key2:
key2.1: value2.1
案例一
case.py
"""
基于yaml格式实现数据驱动
"""
import unittest
from time import sleep
from ddt import file_data, ddt
from selenium import webdriver
@ddt
class Case(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
cls.driver = webdriver.Chrome()
@classmethod
def tearDownClass(cls) -> None:
cls.driver.quit()
# 测试用例
@file_data('../data/search.yaml')
def test_search(self,txt):
# self.driver = webdriver.Chrome()
self.driver.get("https:www.baidu.com")
self.driver.find_element('id','kw').send_keys(txt)
self.driver.find_element('id','su').click()
sleep(3)
if __name__ == '__main__':
unittest.main()
search.yaml
-
txt: 'ces001'
-
txt: 'ces002'
案例二
keys.py
from selenium import webdriver
def open_browser(type_):
try:
driver = getattr(webdriver,type_)()
except Exception as e:
print(e)
driver = webdriver.Chrome()
return driver
class Keys:
# driver = webdriver.Chrome()
def __init__(self,type_):
self.driver = open_browser(type_)
self.driver.implicitly_wait(10)
def open(self,url):
self.driver.get(url)
def locate(self,name,value):
return self.driver.find_element(name,value)
def input(self,name,value,txt):
self.locate(name,value).send_keys(txt)
def click(self,name,value):
self.locate(name,value).click()
def quit(self):
self.driver.quit()
search01.yaml
# 需要管理整个测试用例中包含的数据以及对应的元素信息
-
url: https://www.baidu.com
input:
name: id
value: kw
txt: 关键字封装加数据驱动
click:
name: id
value: su
sleep: 3
case.py
import unittest
from time import sleep
from ddt import file_data, ddt
from selenium import webdriver
from web_key.keys import Keys
@ddt
class Case(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
cls.driver = Keys('Chrome')
@classmethod
def tearDownClass(cls) -> None:
cls.driver.quit()
# 测试用例
# @file_data('../data/search.yaml')
# def test_search(self,txt):
# # self.driver = webdriver.Chrome()
# self.driver.get("https:www.baidu.com")
# self.driver.find_element('id','kw').send_keys(txt)
# self.driver.find_element('id','su').click()
# sleep(3)
@file_data('../data/search01.yaml')
#关键字驱动的测试用例
def test_search01(self,**kwargs):
self.driver.open(kwargs['url'])
#self.driver.input(kwargs['input']['name'],kwargs['input']['value'],kwargs['input']['txt'])
self.driver.input(**kwargs['input'])
self.driver.click(**kwargs['click'])
sleep(kwargs['sleep'])
if __name__ == '__main__':
unittest.main()
案例三
case.py
import unittest
from time import sleep
from ddt import file_data, ddt
from selenium import webdriver
from web_key.keys import Keys
@ddt
class Case(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
cls.driver = Keys('Chrome')
cls.txt = None
@classmethod
def tearDownClass(cls) -> None:
cls.driver.quit()
#新增的用例,给第二条测试用例提供yaml数据
def test_search01(self):
Case.txt = '这是中途传递的测试参数'
#关键字驱动的测试用例
@file_data('../data/search02.yaml')
def test_search02(self,**kwargs):
#变化处
kwargs['input']['txt'] = self.txt
self.driver.open(kwargs['url'])
self.driver.input(**kwargs['input'])
self.driver.click(**kwargs['click'])
sleep(kwargs['sleep'])
if __name__ == '__main__':
unittest.main()
search02.yaml
# 需要管理整个测试用例中包含的数据以及对应的元素信息,txt元素作为上个用例下返回的
-
url: https://www.baidu.com
input:
name: id
value: kw
#下面这条数据由上一条测试用例提供
#txt: 关键字封装加数据驱动
click:
name: id
value: su
sleep: 3
案例四
# search03.yaml
-
common: &common
url: https://www.baidu.com
input:
name: id
value: kw
click:
name: id
value: su
sleep: 3
txt: 第一次
-
common:
<<: *common
txt: 第二次
-
common:
<<: *common
txt: 第三次
#case.py
import unittest
from time import sleep
from ddt import file_data, ddt
from selenium import webdriver
from web_key.keys import Keys
@ddt
class Case(unittest.TestCase):
@classmethod
def setUpClass(cls) -> None:
cls.driver = Keys('Chrome')
@classmethod
def tearDownClass(cls) -> None:
cls.driver.quit()
@file_data('../data/search03.yaml')
#关键字驱动的测试用例
def test_search01(self,common,txt):
self.driver.open(common['url'])
self.driver.input(**common['input'],txt=txt)
self.driver.click(**common['click'])
sleep(common['sleep'])
if __name__ == '__main__':
unittest.main()
# keys.py
from selenium import webdriver
def open_browser(type_):
try:
driver = getattr(webdriver,type_)()
except Exception as e:
print(e)
driver = webdriver.Chrome()
return driver
class Keys:
# driver = webdriver.Chrome()
def __init__(self,type_):
self.driver = open_browser(type_)
self.driver.implicitly_wait(10)
def open(self,url):
self.driver.get(url)
def locate(self,name,value):
return self.driver.find_element(name,value)
def input(self,name,value,txt):
self.locate(name,value).send_keys(txt)
def click(self,name,value):
self.locate(name,value).click()
def quit(self):
self.driver.quit()