zoukankan      html  css  js  c++  java
  • 移动端测试——数据驱动 (9)

    数据驱动

    数据驱动可以理解是将脚本中的测试数据独立出来,方便对数据的统一管理

    • 存储方式
    存储方式 示例
    文件类存储 txt、excel、yaml、json等
    数据库存储 mysql、mongodb等
    • 自动化测试框架

    1.1 Yaml数据存储文件

    YAML 是一种所有编程语言可用的友好的数据序列化标准,语法和其他高阶语言类似,并且可以简单表达清单、散列表,标量等资料形态。文件扩展名是.yml.yaml

    1.1. 语法规则

    规则 说明
    1 大小写敏感
    2 使用缩进表示层级关系
    3 缩进时不允许使用Tab键,只允许使用空格
    4 缩进的空格数目不重要,只要相同层级的元素左侧对齐即可

    1.1.2 支持的数据结构

    数据结构 说明
    对象 键值对的集合

    又称为映射(mapping)、哈希(hashes) 、字典(dictionary)
    数组 一组按次序排列的值,又称为序列(sequence)、列表(list)
    纯量
    (scalars)
    单个的、不可再分的值

    1. 对象

    (1) 值为字符
    data.yaml
    animal: pets
    

    ==>转换为python代码
    字典

    {'animal': 'pets'}
    
    (2) 值为字典

    python字典

    data.yaml
    animal: {"ke1":"pets","key2":"app"} 
    

    ==>转换为python代码

    嵌套字典结构

    {animal: {"ke1":"pets","key2":"app"}}
    

    2. 数组

    方式一
    data.yaml
       animal: 
         - data1
         - data2
    

    转换为python代码

    {'animal': ['data1', 'data2']}
    
    方式二

    python列表

    data.yaml
    animal: ['data1', 'data2']
    

    ==>转换为python代码

    字典嵌套列表

    {'animal': ['data1', 'data2']}
    

    3. 纯量

    包含:字符串,布尔值,整数,浮点数,Null,日期

    (1) 字符串
    data.yaml
    value: "hello"
    

    ==>转换为python代码

    {"value":"hello"}
    
    (2) 布尔值
    data.yaml
    value1: true
    value2: false
    

    =>转换为python代码

    {'value1': True, 'value2': False}
    
    (3) 整数,浮点数
    data.yaml
    value1: 12
    value2: 12.102
    

    ==>转换为python代码

    {'value1': 12, 'value2': 12.102}
    
    (4) 空(Null)

    ~ 、Null、null表示为空

    data.yaml
    value1: ~
    

    ==>转换为python代码

    {'value1': None}
    
    (5) 日期
    data.yaml
    value1: 2017-10-11 15:12:12
    

    ==>转换为python代码

    {'languages': {'value1': datetime.datetime(2017, 10, 11, 15, 12, 12)}}
    
    (6) 锚点&和引用*

    锚点:标注一个内容,锚点名称自定义
    引用:使用被标注的内容<<: *锚点名

    data.yaml
    data: &imp
    value: 456
    name:
    value1: 123
    <<: *imp # "<<:" 合并到当前位置,"*imp" 引用锚点imp
    

    ==>转换为python代码

    {'data': {'value': 456}, 'name': {'value': 456, 'value1': 123}}
    

    1.2 Python解析yaml文件

    1.2.1 PyYAML库安装

    PyYAML为python解析yaml的库
    pip3 install -U PyYAML

    1.2.2 yaml文件内容

    Search_Data:
          search_test_001:
            value: 456
            expect: [4,5,6]
          search_test_002:
            value: "你好"
            expect: {"value":"你好"}
    

    1.2.3 读取yaml文件

    方法:
    yaml.load(stream, ,Loader=yaml.FullLoader)

    yaml.full_load(stream)
    参数:stream 待读取的读模式文件对象

    eg:

    import yaml
          with open("../Data/search_page.yaml",'r') as f:
              data = yaml.load(f,Loader=yaml.FullLoader)
              print(type(data)) # 打印data类型
              print(data) # 打印data返回值
    

    1.2.4 写入yaml文件内容

     {'Search_Data': {
                    'search_test_002': {'expect': {'value': '你好'}, 'value': '你好'}, 
                    'search_test_001': {'expect': [4, 5, 6], 'value': 456}}}
    

    1.2.5 写yaml文件

    方法: yaml.dump(data,stream,**kwds)

    常用参数 说明
    data 写入数据类型为字典
    stream 打开文件对象(写模式的文件对象)
    encoding='utf-8' 设置写入编码格式
    allow_unicode=True 是否允许unicode编码

    eg:

    不设置编码格式

     import yaml
          data = {'Search_Data': {
                          'search_test_002': {'expect': {'value': '你好'}, 'value': '你好'},
                          'search_test_001': {'expect': [4, 5, 6], 'value': 456}}}
          with open("./text.yaml","w") as f: # 在当前目录下生成text.yaml文件,若文件存在直接更新内容
              yaml.dump(data,f)
    

    设置编码格式

     import yaml
          data = {'Search_Data': {
                          'search_test_002': {'expect': {'value': '你好'}, 'value': '你好'},
                          'search_test_001': {'expect': [4, 5, 6], 'value': 456}}}
          with open("./text.yaml","w") as f: # 在当前目录下生成text.yaml文件,若文件存在直接更新内容
              yaml.dump(data,f,encoding='utf-8',allow_unicode=True)
    

    1.3 Yaml数据驱动应用

    目标集成Pytest完成测试任务

    1.3.1 测试项目

    业务场景:
    进入设置点击搜索按钮,输入搜索内容,点击返回

    1.3.2 目录结构:

    App_Project是项目文件夹

    项目文件夹 说明
    Basic 存储基础设施类

    __init__.py 空文件

    Init_Driver.py 手机驱动对象初始化

    Base.py 方法的二次封装

    read_data.py 数据解析读取方法
    Page 存储封装页面文件

    __init__.py 存储页面元素

    search_page.py 封装页面元素的操作方法
    Data 存储数据文件

    search_data.yaml

    (也可以是其他文件比如txt、excel、json、数据库等)
    Test 存储测试脚本目录

    test_search.py 测试搜索文件
    pytest.ini pytest运行配置文件

    1.3.3 前置条件

    • 手机驱动对象独立
    • 方法的二次封装
    • 完成页面的封装

    1.3.4 需编写的文件

    • 编写数据驱动文件search_data.yaml
    search_test_001: # 用例编号
        input_text: "你好" # 测试输入数据
    search_test_002:
        input_text: "1234"
    search_test_003:
        input_text: "*&^%"
    
    • 编写解析yaml文件类/方法
      read_data.py
    import yaml,os
    class Read_Data:
        def __init__(self,file_name):
            '''
                使用pytest运行在项目的根目录下运行,即App_Project目录
                期望路径为:项目所在目录/App_Project/Data/file_name
            '''
            self.file_path = os.getcwd() + os.sep + "Data" + os.sep + file_name 
        def return_data(self):
            with open(self.file_path,'r') as f:
                data = yaml.load(f) # 读取文件内容
                return data
    
        # data:{"search_test_001":{"input_text": "你好"},"search_test_002":{"input_text": "1234"},"search_test_003":{"input_text": "*&^%"}}
    
    • 编写测试脚本
      test_search.py
    import sys,os
    # 因为需要在项目的根目录下运行,所以需要添加python包搜索路径
    # pytest命令运行路径:App_Project目录下
    # os.getcwd(): App_Project所在目录/App_Project
    sys.path.append(os.getcwd())
    
    # 导入封装好的页面类
    from Page.search_page import Search_Page
    # 导入独立的手机驱动对象
    from Basic.Init_Driver import init_driver
    from Basic.read_data import Read_Data
    import pytest
    def package_param_data():
        list_data = [] # 存储参数值列表,格式[(用例编号1,输入内容2),(用例编号1,输入内容2)...]
        yaml_data = Read_Data("search_data.yaml").return_data() # 返回yaml文件读取数据
        for i in yaml_data.keys():
            list_data.append((i,yaml_data.get(i).get('input_text'))) # list_data中添加参数值
        return list_data
    
    class Test_Search:
        '''
            我们希望测试函数运行多次,不希望每运行一次做一次初始化和退出,
            所以使用setup_class,teardown_class,
            测试类内只运行一次初始化和结束动作.
        '''
        def setup_class(self):
            self.driver = init_driver()
    
        @pytest.mark.parametrize('test_id,input_text',package_param_data()) # 参数传递三组参数,会运行三次
        def test_search(self,test_id,input_text):
            # 示例化页面封装类
            sp = Search_Page(self.driver)
            # 调用操作类
            print("test_id:",test_id)
            sp.input_search_text(input_text)
            # 退出driver对象
    
        def teardown_class(self):
            self.driver.quit()
    
    • pytest的配置文件
      pytest.ini
    [pytest]
    addopts = -s  --html=./report.html
    # 测试路径
    testpaths = ./Test
    # 测试文件名
    python_files = test_*.py
    # 测试类名
    python_classes = Test_*
    # 测试的方法名
    python_functions = test_*
    

    1.3.5 项目运行

    • 启动appium 服务
      127.0.0.1:4723
    • 启动模拟机
    • 进入项目根目录
      cd App_Project
    • 命令行
      pytest
    • 测试报告

    更新中......


  • 相关阅读:
    超参数(Hyperparameter)
    验证和交叉验证(Validation & Cross Validation)
    训练集,验证集,测试集(以及为什么要使用验证集?)(Training Set, Validation Set, Test Set)
    特征的非线性变换(Feature Non-linear Transformation)
    机器学习---三种线性算法的比较(线性回归,感知机,逻辑回归)(Machine Learning Linear Regression Perceptron Logistic Regression Comparison)
    Numpy练习题
    过拟合产生的原因(Root of Overfitting)
    超哥笔记 ---集群、负载均衡、代理(7)
    搭建前端项目(2)
    超哥笔记 --nginx入门(6)
  • 原文地址:https://www.cnblogs.com/ricsy/p/11581723.html
Copyright © 2011-2022 走看看