• yaml数据驱动以及封装xpath方法


    5数据驱动

    5.1 Yaml数据存储文件

    简介:YAML

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

    yamlyml是一个东西,所以这两个后缀名都可以。

    语法规则:

    • 大小写敏感
    • 使用缩进表示层级关系
    • 缩进时不允许使用tab,只能是空格(pycharmtab会自动被换为空格)
    • 缩进的空格数量无所谓,只要同一层级的关系缩进的空格是一样的即可

    支持的数据结构:

    键值对组合:映射、哈希、字典

    数组:列表、序列

    纯量:单个的,不可再分的值(不可再往下分的,比如列表中可以包含字典,字符串,但是字符串不能再分,纯量大概包含:(字符串、布尔值整数浮点数、null、时间日期

    5.2 字典和列表在yaml中的写法

    首先在pycharm中新建一个yaml文件,假如名字为data.yaml或者data.yml

    字典写法

    # 字典

    name: 'sy'

    age: 18

    字典是键值对的形式,yaml中,先写键,然后紧接着写冒号,再写一个空格,再写值,键不需要写引号yml会自动加上写完一个键值对,回车继续写,写完以后,如果正确的话,会变颜色,如图:

     

    新建一个py文件,内容为:

    import yaml
    
    def main():
    
    # 读取刚写的data.yml文件
    
        with open(r'./data.yml', 'r', encoding='UTF-8') as f:
            data = yaml.load(f)
            print(data)
     
    if __name__ == '__main__':
        main()

    如果yaml文件没有安装的话,先用pip安装一下:pip install pyyaml或者pip3 install pyyaml

    运行这个文件可以验证刚才写的yml文件是否正确。

    比如此时运行结果为:

    {'name': 'sy', 'age': 18}

    列表写法

    # 列表

    - '1'

    - '2'

    - 'abc'

    这里是一个中划线,一个空格,后面跟列表的值,注意这里不需要冒号。

    还是用上面的py文件验证,运行结果为:

    ['1', '2', 'abc']

    列表嵌套字典:

    或者

    运行结果:

    ['list', {'name': 'sy1', 'age': 18}, {'name': 'sy2', 'age': 20}]

    嵌套的话,主要是看值到底是什么,比如上面这个结果,整体一个列表,第一个值是’list’,那就直接在- 后面跟上’list’,第2个值是一个字典,- 后面就跟一个一个的键值对就行。每写完一个键值对,记得回车,然后tab或者空格。

    字典嵌套字典:

    运行结果:{'name': 'sy', 'age': {'rong': '18', 'yi': '20'}}

    字典嵌套列表:

    # 字典嵌套列表

    name: 'sy'

    age:

      - 'age1'

      - 'age2'

    这里一定要注意,’- age1’和’- age2’前面的空格数是一样的。

    运行结果:

    {'name': 'sy', 'age': ['age1', 'age2']}

    列表嵌套列表

     

    运行结果:['1', ['3', '4'], '5']

    综合运用,写出如下列表的yml文件

    ['1', '2', [5, 6, {'name': 'su', 'age': 18, 'key1': [18, 19], 'key2': {'k1': 10, 'k3': 20}}]]

     

    5.3 yaml纯量

    字符串:用双引号或者单引号引起来,事实上也可以不引,yml会自动识别。

    整数:没有双引号引起来的数字

    浮点数:带有小数点的,并且小数点后面最多能有15位,多余的会四舍五入。

    布尔型:TrueFalseTRUEFALSEtruefalse

    空值:NULLnullNullpythonNone表示的是空,所以用python输出的是None

    日期:2019-01-032019-01-03 23:20:59.111.111表示毫秒),python输出为:

    datetime.datetime(2019, 1, 3, 23, 20, 59, 111000)

    5.4 读写yaml

    yaml.load()方法

    上面已经用过yaml.load()方法,这个方法可以读取yml文件中的内容,具体用法:

    import yaml
    
    def main():
    # 读取刚写的data.yml文件
        with open(r'./data.yml', 'r', encoding='UTF-8') as f:
            # data = yaml.load(f)
            # 上面那种用法,后来被人认为不安全,运行的时候会报warning,可以改为:
            data = yaml.load(f, Loader=yaml.FullLoader)
            print(data)
    
    if __name__ == '__main__':
    
        main()

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

    这个方法可以用来写yml文件,常用的参数有:

    data:写入的数据,数据格式应为字典

    stream:写入的文件对象

    encoding=’utf-8’:设置写入编码格式

    allow_unicode=True :是否允许unicode编码

    代码示例:

    def main():
    
        with open(r'./test.yml', 'w') as ff:
    
            aproject = {'name': 'SY',
    
                        'race': 'Human',
    
                        'traits': ['中国', '你好']
                        }
    
            yaml.dump(aproject, ff, encoding='utf-8', allow_unicode=True)
    
            ff.close()

    这里一定要注意:encoding='utf-8', allow_unicode=True这两个参数可以保证写入的中文不会是Unicode编码格式,而是直接显示中文。

    另外待写入的数据aproject必须是字典

    5.5 锚点和引用

    锚点这个内容不常用,简单了解

    锚点:标注一个内容或者一段内容,类似定义变量

    引用:使用被锚点标注的内容,使用方法:<<: *锚点名

    例如:

    data: &info

      value: 123

      value1: 456

    name:

      name1: ss

      name2: yy

      <<: *info

    上面标红的地方是定义锚点,下面标黄色底色的是使用锚点,没有这两个的时候,这个yml内容是:

    {'data': {'value': 123, 'value1': 456}, 'name': {'name1': 'ss', 'name2': 'yy'}}

    加了锚点后:

    {'data': {'value': 123, 'value1': 456}, 'name': {'value': 123, 'value1': 456, 'name1': 'ss', 'name2': 'yy'}}

    上面的data的值放到了name中,而且只能全部放入,不能只放data的一部分。

    另外还有一个需要注意的点:data的值本身也是一个字典,如果这个字典的键和name中的键有一样的,则data中相同键不会被复制到name

    5.6 yaml数据驱动应用

    假如有个需求:进入设置页面,点击放大镜,输入内容,点击搜索。内容要求输入不同的值多次测试。

    这时候首先想到的就是使用pytest中的参数化功能:

        @pytest.mark.parametrize("content", ["hello", 123])
    
        def test_search(self, content):
    
            # 点击放大镜
            self.search_page.click_search()
    
            # 输入文字
            self.search_page.input_content(content)
    
            # 点击返回
            self.search_page.click_back()

    参数化功能如果不熟悉可以参考链接:

    https://www.cnblogs.com/sy_test/p/12546400.html

    然后现在我们想要yaml文件存储这些数据,然后将yml文件解析为列表,放到@pytest.mark.parametrize中。

    具体怎么做呢?

    首先看目录结构:

     

    跟之前的PO模式比,多了一个data文件夹,base文件夹中多了一个解析ymlpy文件。

    ps:PO模式在另外一个链接:https://www.cnblogs.com/sy_test/p/12565864.html

    search_data中放的内容:

     

    这个文件放的是test_searchtest_search1这两个用例的参数,如果有多个用例,可以继续往下加。

    base_yml.py的内容:

     

    file_name参数:待解析的yml文件,里面的内容应该知道了,就是返回yml的内容,上面讲过。注意这里返回去的是一个字典。

    search_page.py和之前PO模式讲过的一样,这里贴一下:

     

    然后就是test_search了:

     

    def param(test_name):

        return yaml_to_list("search_data")[test_name]

    yaml_to_list这个方法返回的是一个字典,通过[test_name]取得字典中test_name这个键对应的值,而这个值就是一个列表,这个函数,意义在于将这个列表返回去。

    5.7 xpath特殊处理

    5.7.1 xpath用法

    //*[contains(@xxx, ‘’)]这个上面讲过,比如:

    driver.find_element_by_xpath("//*[contains(@text, '更多')]").click()  # 点击更多

    这个意思是说text属性的内容包含更多两个字就可以。

    那么如果想要精确查找,怎么写?

    ("//*[contains(@text= '更多')]")

    text属性等于‘更多’才会被找到。

    如果 一个条件找不到,需要多个条件

    ("//*[contains(@text= '更多' and @name = '更多' )]")

    这个是说text属性等于更多,并且name属性也等于更多,才会被找到。

    当然也可以用contains方法和and共同使用。

    5.7.2 单条件拼接

    # //*[contains(@text, '更多')]

    # //*[@name='设置']

    # 我希望我使用这个方法的时候,不用很复杂,只要传一个参数"@text,更多"就能使用

    def make_xpath_unit_feature(loc):
    
        """
    
        拼接xpath中间的部分
    
        """
    
        args = loc.split(",")
    
        if len(args) == 2:
    
            feature_middle = "contains(" + args[0] + ",'" + args[1] + "')"
    
        elif len(args) == 3:
    
            if args[2] == "1":
    
                feature_middle = args[0] + "='" + args[1] + "'"
    
            elif args[2] == "0":
    
                feature_middle = "contains(" + args[0] + ",'" + args[1] + "')"
    
        return feature_middle
    
    
    def make_xpath_feature(loc):
    
        """
    
        loc的值为'@text,更多',表示要使用contains方法的xpath,
    
        '@text,更多,1':表示使用精确查找
    
        '@text,更多,0',表示要使用contains方法的xpath,
    
        """
    
        feature_start = "//*["
    
        feature_end = "]"
    
        feature = ""
    
        feature = make_xpath_unit_feature(loc)
    
        result = feature_start + feature + feature_end
    
        print(result)
    
    
    # 调用方法,查看结果
    
    make_xpath_feature("@text,更多")
    
    make_xpath_feature("@name,设置,1")

    5.7.3 多条件拼接

    # 假如有多个条件 例如://*[contains(@text, '更多') and @name='设置']

    # 那么中间的部分就是多次调用make_xpath_unit_feature这个方法,用and拼接起来

    def make_xpath_unit_feature(loc):
    
        """
    
        拼接xpath中间的部分
    
        """
    
        args = loc.split(",")
    
        # xpath查找的属性名
    
        key_index = 0
    
        # 属性值
    
        value_index = 1
    
        # 是按照什么方式查找,0表示使用contains方法,1表示使用精确查找
    
        option_index = 2
    
        if len(args) == 2:
    
            feature_middle = "contains(" + args[key_index] + ",'" + args[value_index] + "')" + " and "
    
        elif len(args) == 3:
    
            if args[option_index] == "1":
    
                feature_middle = args[key_index] + "='" + args[value_index] + "'" + " and "
    
            elif args[option_index] == "0":
    
                feature_middle = "contains(" + args[key_index] + ",'" + args[value_index] + "')" + " and "
    
        return feature_middle
    
    
    def make_xpath_feature(loc):
    
        """
    
        loc的值为'@text,更多',表示要使用contains方法的xpath,
    
        '@text,更多,1':表示使用精确查找
    
        '@text,更多,0',表示要使用contains方法的xpath,
    
        """
    
        feature_start = "//*["
    
        feature_end = "]"
    
        feature = ""
    
        if isinstance(loc, str):
    
            feature = make_xpath_unit_feature(loc)
    
        else:
    
            for i in loc:
    
                feature += make_xpath_unit_feature(i)
    
    
        feature = feature.rstrip(" and ")
    
        result = feature_start + feature + feature_end
    
        print(result)
    
    make_xpath_feature("@text,更多")
    
    make_xpath_feature("@name,设置,1")
    
    make_xpath_feature(["@name,设置,1", "@text,更多"])

    这个xpath相关方法就完成了,可以放到action里面作为一个工具类来使用了。

    完整的代码请参考:https://github.com/suyang2020/PoDemo

  • 相关阅读:
    DDD:管理“工作单元实例”的两种模式
    DDD:DDD+CQRS+高伸缩性的分布式架构
    ExtJS4.2:快捷键支持(没有你想象的那么简单)
    DDD:用 “四色原型” 进行 “职责分配”
    .NET:处理数据库事务中的并发
    Javascript:必须知道的Javascript知识点之“单线程事件驱动”
    技术交流:20130413线下交流总结,不再做苦逼的程序员
    Javascript:必须知道的Javascript知识点之“原型链”
    DDD:主键映射,你一直在使用的企业应用模式
    设计原则:重复的方式以及如何消除重复
  • 原文地址:https://www.cnblogs.com/sy_test/p/12575703.html
Copyright © 2020-2023  润新知