selenium+unitTest+Yaml

第一章 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

  1. 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()
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小桃子的思念

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

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

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

打赏作者

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

抵扣说明:

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

余额充值