Automation data-driven? The most complete interface automation test yaml data-driven actual combat, it is enough to read this article


foreword

When we do automated testing, we usually store configuration information and test data in specific files to separate data and scripts, thereby improving code readability and maintainability, and facilitating later optimization.

The form of configuration files is even more diverse, such as: ini, yaml, json, toml, py, xml, properties, etc.

Python interface automated testing: https://www.bilibili.com/video/BV16G411x76E/

YAML is a lightweight text format that can be used to store structured data, ideal for testing data.

When using YAML data-driven for automated testing, it is usually necessary to prepare one or more YAML files, which contain test case data and expected results. The test script will read these files, execute the corresponding test steps according to the data in the files, and then verify whether the actual results are consistent with the expected results.

Let's explore the YAML data-driven in interface automation testing in detail

1. What is YAML

YAML: YAML Ain't a Markup Language, the translation is that YAML is not a markup language.

It is a data-centric markup language that is more suitable for configuration files than XML and JSON.

The suffix of YAML configuration files is .yml or .yaml, such as: caituotuo.yml or caituotuo.yaml.

The syntax of YAML is similar to other high-level languages, and it can simply express data forms such as lists, hash tables, and scalars. It uses whitespace indentation and heavily relies on appearance features, and is especially suitable for expressing or editing data structures, various configuration files, dumping debug content, file outlines, etc.

2. YAML syntax

1) Basic grammar
Use indentation to indicate hierarchical relationship;
indentation does not allow tabs, only spaces are allowed (officially, tabs are not allowed, of course, if you use tabs, it is also possible in some places, such as on PyCharm software);
indentation The number of spaces entered is not important, as long as the elements of the same level are left-aligned;
case-sensitive;
add # in front to indicate comments;

req:
  username: xxxxxx # 这是姓名
  gender: Boy
  ip: ******
  blog: www.xxxxxx.com
res:
  status: 1
  code: 200

2) Data type
Object: a collection of key-value pairs, also known as mapping (mapping) / hash (hashes) / dictionary (dictionary)
array: a set of values ​​arranged in order, also known as sequence (sequence) / list ( list)
scalars: a single, indivisible value, also known as a literal

Scalar refers to a single, indivisible value, such as: numbers, strings, Boolean values, Null, dates, etc. The scalar can be written directly in the value of the key-value pair.

String:
By default, strings do not need to use single or double quotes

username: 张三

Of course, it is also possible to use double quotes or single quotes to wrap characters.

username: 'Hello world 张三'
username: "Hello world 张三"

Strings can be split into multiple lines, each line will be converted into a space

# 字符串可以拆成多行,每一行会被转化成一个空格 '测试 张三'
username3: 测试
  张三

Boolean value:

boolean:
  - TRUE  #true,True都可以
  - FALSE  #false,False都可以
  
# {'boolean': [True, False]}

number:

float:
  - 3.14
  - 6.8523015e+5  #可以使用科学计数法
int:
  - 123
  - 0b1010_0111_0100_1010_1110    #二进制表示
  
# {'float': [3.14, 685230.15], 'int': [123, 685230]}

Null:

null:
  nodeName: 'node'
  parent: ~  #使用~表示null
  parent2: None  #使用None表示null
  parent3: null  #使用null表示null
  
# {None: {'nodeName': 'node', 'parent': None, 'parent2': 'None', 'parent3': None}}

time and date:

date:
  - 2023-04-18    #日期必须使用ISO 8601格式,即yyyy-MM-dd
datetime:
  - 2023-04-18T15:09:30+08:00    #时间使用ISO 8601格式,时间和日期之间使用T连接,最后使用+代表时区
  
# {'date': [datetime.date(2023, 4, 18)], 'datetime': [datetime.datetime(2023, 4, 18, 15, 9, 30, tzinfo=datetime.timezone(datetime.timedelta(seconds=28800)))]}

Object
Use the form of key:[space]value to represent a pair of key-value pairs (spaces cannot be omitted), for example: blog: caituotuo.top.

Inline writing:

key: {
    
    key1: value1, key2: value2, ...}

Ordinary writing, using indentation to represent the hierarchical relationship between objects and properties:

key: 
    child-key: value
    child-key2: value2

Array Lines
starting with - represent an array.

Ordinary writing:

name:
    - 测试
    - 张三
    -

YAML supports multidimensional arrays, which can be represented using inline:

key: [value1, value2, ...]

A child member of a data structure is an array, you can indent one space below the item:

username:
      -
        - 测试张三
        - 张三
        --
        - A
        - B
        - C
        
# {'username': [['测试张三', '张三', '张'], ['A', 'B', 'C']]}

Relatively complex example:

The companies attribute is an array, and each array element is composed of three attributes: id, name, and price

companies:
    -
        id: 1
        name: zhangshan
        price: 300W
    -
        id: 2
        name: 测试张三
        price: 500W
       
# {'companies': [{'id': 1, 'name': 'zhangshan', 'price': '300W'}, {'id': 2, 'name': '测试张三', 'price': '500W'}]}

Arrays can also be expressed in flow:

companies2: [ {
    
     id: 1,name: zhangshan,price: 300W },{
    
     id: 2,name: 测试张三,price: 500W } ]

Composite structure
The above three data structures can be used in any combination to achieve different user requirements, for example:

platform:
  - A1
  - A2
  - A3
sites:
  A1: 测试张三
  A2: 测试李四
  A3: xxxxxx.com
  
# {'platform': ['A1', 'A2', 'A3'], 'sites': {'A1': '测试张三', 'A2': '测试李四', 'A3': 'xxxxxx.com'}

3. Quote

& anchor and * alias, can be used for reference.

For example:
& is used to establish anchor point defaults, << means to merge into the current data, * is used to refer to the anchor point

defaults: &defaults
  adapter: postgres
  host: localhost

development:
  database: myapp_development
  <<: *defaults

test:
  database: myapp_test
  <<: *defaults

Equivalent to:

defaults:
  adapter: postgres
  host: localhost

development:
  database: myapp_development
  adapter: postgres
  host: localhost

test:
  database: myapp_test
  adapter: postgres
  host: localhost

4. Organizational structure

A YAML file can consist of one or more documents. The — is used as a separator between the documents, and the entire document is independent of each other without interfering with each other. If the YAML file only contains one document, the — separator can be omitted.

---
website:
  name: 测试张三
  url: xxxxxx.com
---
website: {
    
     name: 测试张三,url: www.xxxxxx.com }
---
A1: 测试张三
---
A2: 测试张三
f7 = "./files/多文档.yml"
with open(f7, "r", encoding="UTF-8") as f:
    content = yaml.safe_load_all(f)
    for i in content:
        print(i)

5. Actual combat

Encapsulation ideas
Encapsulate YAML-related operations into CommonUtil public modules, and then directly import and call them.

Related functions:
read yaml file data;
convert yaml data into json format;
dynamically set parameters;

Here I want to talk about dynamically setting parameters.
In automated testing, you must not write all the parameters to death, so parameterization will be used, for example: extract the return value of the previous interface as the input parameter of the next interface, here through Python The Template module in is used to set dynamic parameters

In the yaml file, variables are set in the form of $variable name

username: $username

Attach a specific value to the variable

with open(yaml_path, "r", encoding="UTF-8") as f:
	text = f.read()
# Template(text).safe_substitute(key_value)
Template(text).safe_substitute({
    
    "username": "测试张三"}) # username为变量名

full code

import os
from string import Template
import yaml


class YamlUtil:
    @staticmethod
    def yaml_util(yaml_path, key_value=None):
        """
        读取yml文件 设置动态变量
        :param yaml_path: 文件路径
        :param key_value: 动态变量 如:{"username": "测试张三"} yaml中的变量:$username
        :return:
        """
        try:
            with open(yaml_path, "r", encoding="UTF-8") as f:
                text = f.read()
                if key_value is not None:
                    re = Template(text).safe_substitute(key_value)
                    json_data = yaml.safe_load(re)
                else:
                    json_data = yaml.safe_load(text)
            return json_data
        except FileNotFoundError:
            raise FileNotFoundError("文件不存在")
        except Exception:
            raise Exception("未知异常")

    @staticmethod
    def multiple(yaml_path):
        """
        多文档
        :param yaml_path: yaml文件路径
        :return: list
        """
        json_data = []
        try:
            with open(yaml_path, "r", encoding="UTF-8") as f:
                content = yaml.safe_load_all(f)
                for i in content:
                    json_data.append(i)
            return json_data
        except FileNotFoundError:
            raise FileNotFoundError("文件不存在")
        except Exception:
            raise Exception("未知异常")


if __name__ == '__main__':
    f1 = "./files/初体验.yml"
    print(YamlUtil().yaml_util(f1))

    f2 = "./files/纯量.yml"
    print(YamlUtil().yaml_util(f2))

    f3 = "./files/数组.yml"
    print(YamlUtil().yaml_util(f3))

    f4 = "./files/复合结构.yml"
    print(YamlUtil().yaml_util(f4))

    f5 = "./files/引用.yml"
    print(YamlUtil().yaml_util(f5))

    f6 = "./files/参数化.yml"
    print(YamlUtil().yaml_util(f6, {
    
    "username": "测试张三"}))

    f7 = "./files/多文档.yml"
    for i in YamlUtil().multiple(f7):
        print(i)
The following is the most complete software test engineer learning knowledge architecture system diagram in 2023 that I compiled

1. From entry to mastery of Python programming

Please add a picture description

2. Interface automation project actual combat

Please add a picture description

3. Actual Combat of Web Automation Project

Please add a picture description

4. Actual Combat of App Automation Project

Please add a picture description

5. Resume of first-tier manufacturers

Please add a picture description

6. Test and develop DevOps system

Please add a picture description

7. Commonly used automated testing tools

Please add a picture description

Eight, JMeter performance test

Please add a picture description

9. Summary (little surprise at the end)

Struggle is the only way in life, how can you see a rainbow without going through wind and rain. No matter how rough the road ahead is, as long as you have firm belief and work hard, success will not be far away.

There is no hopelessness in the world, only those who refuse to work hard. Everyone has the potential and opportunity to create their own future. As long as you have the courage to pursue your dreams and persevere, success is beckoning to you.

Success requires courage, determination and perseverance. When you set out to chase your dreams, you are bound to encounter setbacks and difficulties. But as long as you persevere and face it positively, you can overcome all difficulties and achieve what you want.

Guess you like

Origin blog.csdn.net/shuang_waiwai/article/details/130223479