YAML 文件介绍

YAML 文件介绍,第1张

YAML 是一种可读性非常高,与程序语言数据结构非常接近。同让拍时具备丰富的表达能力和可扩展性,并且易于使用的数据标记语言。

YAML是 "YAML Ain't a Markup Language"(YAML不是一种标记语言)的递归缩写。

这么命名的方式,表示 YAML 强调的不是标记,而是数据本身。

YAML 参考了其他多种语言,包括:XML、C语言、Python、Perl 以及电子邮件格式 RFC2822。

YAML 发布与 2001 年,之前并不出名,现在逐渐开始流行。测试圈中坦散羡,主要应用于自动化测试过程,用来进行数据驱动的数据存储载体。

基本语法规则(很接近 Python 的语法规则):

支持的数据格式:

以下是 YAML 数据格式的示例:

对象

转换为Python字典格式为

YAML也支持另一种对象的写法,将所有的键值对写成一个行内对象

转换为Python字典格式为

数组

一组连词线开头的行,构成一个数组

转换为Python

也可以通过缩进空格来表示多维数组

转换为Python的列表

当然,也可以采用行内掘颤表示法

转换为Python

纯量

纯量是最基本的、不可再分的值。 以下数据类型都是常见的纯量。

纯量一般表示如下

转换为Python

yaml 文件通过 pyyaml 库转换后就是 Python 中对应的数据类型。直接进行 *** 作即可,相较从 excel 中读取数据全部是字符串的方式来说,处理更方便。相对于 json 格式,可读性更高。

知道ddt的基本使用方法之后,练习把之前用excel文件来维护的接口测试用例改用unittest+ddt来实现。

这里我选用yaml文件来管理接口参数,开始本来想用json,但是json无法添加注释,可读性不好。

下面截图是接口文档中的各个接口,每个接口都有一个固定的序号,所以在设计每个接口的测试数据时,以序号来区分不同接口

yaml文件内容如下,需要注意的是yaml的语法:

(1)键值对用冒号分割,但是冒号后需要加一个空格

(2)禁止使用tab缩进,只能使用空格键;缩进长度没有限制,只要元素对齐就表示这些元素属于一个层级

(3)字符串可以不用引号标注,也可以加引号,如果想把数字变为字符串弊消卖,加引号即可

(4)使用#表示注释

详情可以参考博客: https://blog.csdn.net/vincent_hbl/article/details/75411243

2. 简单 demo : python 读取 yaml 文件,取出接口参数

import yaml

fp = open('../dataconfig/信息互动模块接口.yaml', encoding='utf-8')   #有中文字符的话,加编码格式

                testdata = yaml.load(fp)

t = testdata['5.2.1.4']

print(t)

(1)封装读取yaml文件方法

handle_yaml.py

# coding: utf-8

# author: hmk

importyaml

importos

classHandleYaml:

    def __init__(self,file_path=None):

        if file_path:

           self.file_path = file_path

        else:

            root_dir =os.path.dirname(os.path.abspath('.'))

            # os.path.abspath('.')表示获取当前文件所在目录;os.path.dirname表示获取文件所在父目录;所以整个就是项目的所在路径self.file_path = root_dir +'/dataconfig/信息互动模块接口.yaml'  #获取文件所在的相对路径(相对整个项目)

        #elf.data = self.get_data()

    def get_data(self):

        fp =open(self.file_path, encoding='utf-8')

        data =yaml.load(fp)

        return data

if __name__ == '__main__':

    test = HandleYaml()

    p = test.get_data()

    print(p['5.2.1.1'])

[if !vml][endif]

(2)封装requests请求方法

[if !vml][endif]

# coding: utf-8

# author: Archer

importrequests

importjson

classRunMethod:

    defpost_main(self, url, data, header=None):if header is notNone:

          桥铅   res =requests.post(url=url, data=data, headers=header)

        else:

            res =requests.post(url=url, data=data)

        # print(res.status_code)

        # return res.json()

        return res    #为了租逗方便后面断言,这里不再对服务器响应进行json格式编码

def get_main(self, url, data=None, header=None):if header is notNone:

            res =requests.get(url=url, params=data, headers=header)

        else:

            res =requests.get(url=url, params=data)

            print(res.status_code)

        # return

res.json()

        return res

    def run_main(self, method, url, data=None, header=None):

    if method== 'POST':

            res =self.post_main(url, data, header)

        else:

            res =self.get_main(url, data, header)

        returnres

        # returnjson.dumps(res, indent=2, sort_keys=False, ensure_ascii=False)  #使用json模块格式化显示结果

[if !vml][endif]

(3)一个接口测试用例

[if !vml][endif]

# coding: utf-8

# author: Archer

importunittest

importddt

from base.run_method importRunMethod

from utils.handle_yaml importHandleYaml

get_data = HandleYaml()  # 从yaml文件中取出该接口的参数

params = get_data.get_data()['5.2.1.4']

@ddt.ddt

classTest(unittest.TestCase):

    """加载咨询详情接口"""

    defsetUp(self):

        self.url ='http://localhost:8088/ApprExclusiveInterface/api/enterprise/info/consult/loadDetail.v'

        self.run =RunMethod()

    @ddt.data(*params)

    deftest(self, value):

        r =self.run.run_main("GET", self.url, value)

        print(r)

       self.assertTrue(value['assert'] inr.text)

if __name__ == '__main__':

    unittest.main()

(4)利用HTMLTestRunner生成测试报告

run_report.py

# coding: utf-8

# author: hmk

from HTMLTestRunner importHTMLTestRunner

importunittest

importtime, os

root_dir = os.path.dirname(os.path.abspath('.'))  # 获取当前文件所在目录的父目录的绝对路径,也就是项目所在路径E:\DDT_Interface

case_dir = root_dir + '/test_case/'  # 根据项目所在路径,找到用例所在的相对项目的路径

print(root_dir)

print(case_dir)

"""定义discover方法"""

discover = unittest.defaultTestLoader.discover(case_dir,

pattern='test*.py', top_level_dir=None)

"""

1.case_dir即测试用例所在目录

2.pattern='test_*.py' :表示用例文件名的匹配原则,“*”表示任意多个字符

3.top_level_dir=None:测试模块的顶层目录。如果没顶层目录(也就是说测试用例不是放在多级目录中),默认为None

"""

if __name__ == "__main__":

    """直接加载discover"""

    now = time.strftime("%Y-%m-%d%H_%M_%S")

    filename = root_dir +'/report/' + now + '_result.html'  #定义报告存放路径

    print(filename)

    fp = open(filename,'wb')

    runner =HTMLTestRunner(stream=fp, title='个人网企业网接口测试报告', description='测试结果如下: ')

    runner.run(discover)

    fp.close()

ok ,unittest+ddt进行接口测试就完成了,还有很多不足,yaml配置文件还可以继续设计优化,例如可以把请求url也加进去。

其实感觉如何设计测试用例,组织测试数据也是一件很有意思的事情,很多事情都必须先有一个良好的设计思路才会进行的更顺畅。总之勤于思考,多参考他人的思路。不是有句话吗,学而不思则罔,思而不学则殆。

在我们的kubernetes中,你只需要两种结构类型就行了:

1、Lists

2、Maps

也就是说,你可能会遇到Lists的Maps和Maps的Lists,等等。不过不用担心,你只需要掌握了这两种结果也就可以了,其他更加复杂的我们暂且不讨论。

首先扒升明我们来看看Maps,我们都知道Map是字典,就是一个key:value的键值对,Maps可以让我们更加方便的去书写配置信息,例如:

第一行的---是分隔符,是可选的,在单一文件中,可连用三个连字号---区分多个文件。这里我们可以看到,我们有两个键:kind和apiVersion,它们对应的值分别是:v1和Pod。上面的YAML文件转化为json格式:

我们在创建一个相对复杂一点的YAML文件,创建一个KEY对应的值不是字符串而是一个Maps:

上面的YAML文件,metadata这个KEY对应的值就是一个Maps了,而且嵌套的labels这个KEY的值又是一个Map,可以多层嵌套。

YAML处理器是根据行缩进来知道内容之间的关联性的。比如我们上面的YAML文件,我们用了两个空格作为缩进,空格数量并不重要,但是你得保持一致,并且至少要求一个空格。

我们可以看到name和labels是相同级别的缩进,所以YAML处理器就知道了他们属于同一个Map,而app是labels的值是因为app的值缩进更大。

同样的我们转化为json格式:

Lists就是列表,说白就是数组,在Yaml文件中我们可以这样定义:

你可以有任何数量的项在列表中,每个笑答项的定义以破折号(-)开头的,与父元素直接可以缩进一个空格。转化为json格式:

当然,lists的子项可以是map,maps的子项也可以是lists:

比如这个YAML文件,我们定义了一个叫containers的Lists对象,每个子项都由name,image,ports组成,每个ports都有一个key为containerPort的Map组成,转换为json格式:

使用YAML文件来创建一个Deployment吧。

API 说明: https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.10/

这是普通的POD文件:

* apiVersion,这里的值是v1,这个版本号需要根据我们安装的kubernetes版本和资源类型进行变化的,记住不是写死的

* kind,这里我们创建的是一个pod,当然根据你的实际情况,这里资源类型可以是Deployment,Job,Ingress,Service等。

* medatada:包括了我们定义的Pod的一些meta信息,比如名称,namespace,标签等等信息。

* spec:包括一些containers,storage,volumes,或者其他Kubernetes需要知道参数,以及春告诸如是否在容器失败时重新启动容器的属性。你可以在待定kubernetes API找到完整的Kubernetes pod属性。

典型的容器的定义:

这是一个最小的定义: 一个名字(front),基于nginx镜像,以及容器将会监听一个端口80。在这些中,只有名字是非常重要的,你也可以指定一个更加复杂的属性,例如容器启动时运行的命令,应使用的参数,工作目录,或每次实例化时是否拉取镜像的新副本。以下是容器可设置的属性:

我们将上面创建的POD的YAML文件保存成一个pod.yaml。然后使用kubectl创建POD:

我们就可以使用我们前面比较熟悉的kubectl命令来查看POD状态了:

创建遇到问题,可以使用kubectl describe 进行排查。我们先删除上面创建的POD:

现在我们可以来创建一个真正的Deployment。在上面的例子中,我们只是单纯的创建一个POD实例,但是如果这个POD出现了故障的话,我们的服务也就挂掉了,所以kubernetes提供了一个Deployment的概念,可以让kubenetes去管理一组POD的副本,也就是副本集,这样可以保证一定数量的副本一直可用的,不会因为一个POD挂掉导致整个服务挂掉。我们这样定义一个Deployment:

注意这里的apiVersion对应的值是apps/v1,当然kind要指定为Deployment,因为这就是我们需要的,然后我们可以知道一些meta信息,比如名字,或者标签之类的。最后,最重要的是spec配置选项,这里我们定义需要两个副本,当然还有很多可以设置的属性,比如一个Pod在没有任何错误变成准备的情况下必须达到的最小秒数。

我们可以在 Kubernetes v1beta1 API 参考中找到一个完整的 Depolyment 可指定的参数列表。

现在我们来定义一个完整的 Deployment 的 YAML 文件:

和pod.yaml文件很类似。注意其中的template,其实就是对POD对象的定义。将deployment.yaml创建:

查看状态:

可以使用 http://www.yamllint.com/ 去检验 YAML 文件的合法性。


欢迎分享,转载请注明来源:内存溢出

原文地址: https://outofmemory.cn/tougao/12217290.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-21
下一篇 2023-05-21

发表评论

登录后才能评论

评论列表(0条)

保存