移动端测试——数据驱动 (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
  • 测试报告

更新中......


原文地址:https://www.cnblogs.com/ricsy/p/11581723.html