8.python+pytest

pytest + allure框架

**************************************************************************************
第一部分    requests

1. 安装requests,使用命令 pip install requests

    若在线安装失败,则使用以下镜像命令安装:
    pip install requests -i http://pypi.douban.com/simple --trusted-host pypi.douban.com


2. Python接口入门练习

    课件\09_接口测试\python+requests库的接口自动化测试.docx

        http://www.pingan.com/cms-tmplt/pinganlife/synShopList.do
        参数dateUpdated:2017-12-02
        平安接口是2017-12-02有数据,2020-06-09能跑,2010-06-09不能跑   


***************************************************************************************

第二部分   pytest+allure框架

1. 环境准备

    1-1. pycharm设置(默认Unittests):

        Tools → Python Integrated Tools → 第2行的 Default test runner选择py.test

        如果pycharm控制台报 Empty test suite 空测试套件,需要修改默认执行程序


    1-2. 安装pytest框架: pip install -U pytest

        验证是否成功:pytest --version 


    1-3. 安装allure

        1)首先安装jdk8及以上版本,即1.8+(注意环境变量的配置)

            JAVA_HOME: C:\Program Files\Java\jdk1.8.0_60\
            CLASSPATH: .;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar
            Path: %JAVA_HOME%\bin;%JAVA_HOME%\jre\bin

        2)allure下载地址:https://github.com/allure-framework/allure2/releases

            解压zip包后(路径不要中文),配置Path环境变量: C:\allure-2.17.2\bin
            DOS窗口验证: allure --version


    1-4. 安装allure-pytest 插件,用来生成 Allure 测试报告所需要的数据

           pip install allure-pytest

2. pytest框架的文件命名规则

        pytest的文件名,要以test_*.py 或*_test.py命名
        pytest的类,要以Test开头
        pytest的方法,要以test开头


3. pytest常用断言方式

  assert a in b:判断b包含a
  assert a == b:判断a等于b
  assert a != b:判断a不等于b


4. pytest框架示例代码如下:

    import pytest

    class TestCase():   # 创建测试类,以Test开头
        def setup_class(self):
        # def setup(self):
            print("环境准备")
        def testCase_01(self):  # 测试用例,以test开头
            print("测试用例1步骤")
            assert "a" == "a"
        def testCase_02(self):
            print("测试用例2步骤")
            assert "a" in "ab"
        def teardown_class(self):
        # def teardown(self):
            print("环境恢复")

    if __name__ == "__main__":
        pytest.main()
        # 指定文件运行
        # pytest.main(["-s","testCase.py"])

    注意:setup、teardown适用于执行单条用例,setup_class、teardown_class适用于批量执行

5. pytest中装饰器@pytest.mark.parametrize("参数名",data)可以实现测试用例参数化,
    放在类或类函数前面,作用类似DDT的数据驱动, parametrize读音 /pə'ræmətraɪz/,
    测试数据data常用列表形式(也支持元组),如:简单列表、列表套字典、列表套列表套多个字典

    如:@pytest.mark.parametrize("inputData, expectRes",
                                  [ ( '{"page":1}', '{"code":0,"msg":"成功"}' ),
                                    ( '{"page":2}', '{"code":0,"msg":"成功"}' ) ] )

    1).测试数据封装成列表的具体示例:

        data = [   [   {"username":"juzi01","password":"123456","password_confirmation":"123456"},
                            {"expect":"juzi01"}     ],
                        [   {"username":"","password":"123456","password_confirmation":"123456"},
                            {"expect":"\"code\":2001,\"msg\":\"missing username or password or password_confirmation\""}    ],
                        [   {"username":"juzi02","password":"123456","password_confirmation":"123456000"},
                            {"expect":"\"code\":2002,\"msg\":\"password/password_confirmation not identical\""}  ]    ]

        # 引入测试数据,并分解
        @pytest.mark.parametrize("testData,expected",data)
    
        # 测试用例,以test开头
        def testCase(self,testData,expected):
            print("这是用例具体步骤")


    2).测试数据放到yaml文件示例(需将测试数据转成yaml格式,可百度json转yaml):

            安装yaml:pip install pyyaml

        #  将测试数据放到yaml文件: 获取yaml文件完整路径→读取yaml文件,并转成列表格式
        import os,yaml
        yaml_path = os.path.join(os.path.dirname(__file__),"test_01_register.yaml")
        with open(yaml_path,"r",encoding="utf-8") as f:
            data = yaml.load(f.read(),Loader=yaml.FullLoader)

        # 引入测试数据
        @pytest.mark.parametrize("testData,expected",data)
        
        # 测试用例,以test开头
        def testCase(self,testData,expected):
            print("这是用例具体步骤")


    3).测试数据放到yaml文件示例(将读取yaml文件封装成函数,可以直接调用) → 不要求掌握

            # 定义函数法
            def getYaml(yamlName):
                yaml_path = os.path.join(os.path.dirname(os.path.dirname(os.path.abspath(__file__))),"testCases",yamlName)
                with open(yaml_path,"r",encoding="utf-8") as f:
                    res = f.read()
                    data = yaml.load(res,Loader=yaml.FullLoader)
                    return data

            # 调用函数getYaml
            data = getYaml("test_01_register.yaml")

6. 生成allure测试报告的三种方法

    方法1. 在pycharm中,以非py.test方式运行(文件名以test_开头)

        if __name__ == "__main__":
            # 如果工作路径有误,需要将工作路径切换到当前目录下
            # cur_path = os.path.dirname(os.path.abspath(__file__))
            # os.chdir(cur_path)        

            # 第一步,指定在当前文件夹的temp下,生成测试报告需要的数据
            os.system("pytest --alluredir=./temp")

            # 第二步,清空原来reports的报告,并根据temp下的数据,生成测试报告放在reports下
            os.system("allure generate ./temp -o ./reports --clean")

        注:在pycharm中能正常运行,但没有生成allure报告,且控制台报一串红色方框问号,
             原因是环境变量没有生效,需要重启pycharm,或重启电脑。    


    方法2. 在DOS中,以pytest方式运行(py文件名可以任意)

        打开文件所在路径,命令行输入可以生成allure报告的2个命令

        命令1,运行程序,生成报告:pytest py文件 --alluredir 生成报告文件的临时文件夹
            如:pytest pytest框架.py --alluredir ./temp

        命令2,启动服务,查看临时报告:allure serve 生成报告文件的临时文件夹
            如:allure serve ./temp


    方法3. 在DOS中,以python方式运行(py文件名必须以test_开头)
        
            1). py文件的调试入口 if __name__ 里面,需要写入以下内容:

                if __name__ == "__main__":
                    # 第一步,指定在当前文件夹的temp下,生成测试报告需要的数据
                    os.system("pytest --alluredir=./temp")
                    # 第二步,清空原来reports的报告,并根据temp下的数据,生成测试报告放在reports下
                    os.system("allure generate ./temp -o ./reports --clean")

            2). 打开文件所在路径,命令行输入以下2个命令:

                python test_pytest框架.py

                allure open reports

7. 打开allure报告的方法

    在report下index.html文件是不能直接用浏览器打开的,出现页面都是loading的情况,
      需要用allure命令渲染之后打开才能展示效果。可用以下两种方法:

        1. 可以直接在pycharm中用浏览器打开

        2. 可以在DOS窗口用命令打开:  allure open 存放报告的文件夹

            如C盘: allure open C:\pytest框架\reports

            或D盘: D: → cd D:\pytest框架\reports → allure open ./


8. @allure 装饰器中的一些功能点:
       想对用例集分层,增加可读性,可以使用以下三个装饰器,写在类或方法前面:

        import allure    # 先导包

        @allure.epic("版本号")                # 敏捷里的概念,或者项目版本,如V1.0.5
        @allure.feature("测试模块")        # 定义被测试对象的功能点,如商品管理
        @allure.story("测试功能点")        # 定义被测功能的用户场景,即子功能点,如新增商品

9. br_api 项目练习

    9-1. 如在C盘根目录创建项目文件夹br_api,里面有如下内容:

            public      公共部分,存放公共数据、方法等,如封装token、服务器信息等
                public.py

            testCases   用例层,存放测试用例
                test_01_register.py
                test_02_login.py

            reports     存放测试报告

            runMain.py  主程序文件,调用所有接口用例执行,并生成测试报告


    9-2. 调用公共部分时,报错 ModuleNotFoundError: No module named 'xxx',可能路径问题,
        可以参考下方的 13.注意事项里面的第3条,或者定义项目路径为绝对路径,具体如下:

                import os,sys
                # 构造项目路径
                projectPath = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
                sys.path.append(projectPath)
                from public.public import host,getToken


    9-3. 如果pycharm里面没有生成报告,可以到DOS窗口执行如下命令:

            cd C:\课堂练习\python练习\br-api

            python runMain.py

            allure open reports


    9-4. 脚本调试好,使用Jenkins做持续集成测试

        Jenkins日程表设置:00 18 * * *
        (分时日月周,表示每晚18:00执行脚本)

        Jenkins命令: 
            项目文件在C盘:          cd C:\br_api → python runMain.py
            项目文件在D盘: D: → cd C:\br_api → python runMain.py

10. 注意事项: 
        1.同一模块中,变量名和函数名不能相同,
        2.变量名不能和从别的模块导入的变量名相同
        3.如果报错 No module named 'public',需要设置项目文件夹,具体为:
            选择项目文件夹如br_api,右键选择底部的Mark Directory as → Sources Root
        4.如果报 No such file or directory: 'D:\\Program Files\\JetBrains\
            \PyCharm 5.0.3\\jre\\jre\\bin\\test_03_task.yaml'
            可能是临时路径问题,可用os.path.dirname(os.path.abspath(__file__))代替os.getcwd()


------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------
**************************************************************************************


以下是代码示例
-------------------------------------------------------------------------------------------


yaml文件名:test_data.yaml
文件内容如下:

- - name: tom
    age: 20
  - expectRes: hello
- - name: 橘子
    age: 25
  - expectRes: 'hello,world'


pytest框架示例----------------------------------------------------------------------------

文件名:test_case.py,实际项目中可以写成test_01_register、test_02_login等


import pytest,os,yaml

class TestExample():
    # 1.测试用例:无参数
    '''
    def test_case01(self):
        # 测试步骤
        print("测试步骤,无参数")

        # 断言
        expectRes = "hello"
        actualRes = "hello,world"
        # 判断actualRes包含expectRes
        assert expectRes in actualRes
'''
    # 2.测试用例:只有一个参数
    '''
    data = "赚大钱"
    @pytest.mark.parametrize("args",[data])    # 列表格式传参
    def test_case02(self,args):
        # 测试步骤
        print("测试步骤,只有一个参数:%s"%args)

        # 断言
        expectRes = "hello"
        actualRes = "hello"
        assert expectRes == actualRes
'''
    # 3.测试用例:参数为列表中嵌套了字典
    '''
    data = [ {"name":"tom","age":20},
             {"name":"橘子","age":25}
             ]
    @pytest.mark.parametrize("args",data)
    def test_case02(self,args):
        # 测试步骤
        print("测试步骤,传入参数是:%s,%d"%(args["name"],args["age"]))

        # 断言
        expectRes = "hello"
        actualRes = "hello666"
        assert expectRes != actualRes
'''
    # 4.测试用例:参数为列表中嵌套列表和多个字典
    '''
    data = [ [{"name":"tom","age":20},{"expectRes":"hello"}],
             [{"name":"橘子","age":25},{"expectRes":"hello,world"}]
             ]
    @pytest.mark.parametrize("inputData,expect",data)
    def test_case02(self,inputData,expect):
        # 测试步骤
        print("测试步骤,传入参数是:%s,%d"%(inputData["name"],inputData["age"]))
        # 断言
        expectRes = expect["expectRes"]
        print("预期结果expectRes是:",expectRes)
        actualRes = "hello666"
        assert expectRes != actualRes
'''

    # 5.测试用例:将测试数据放入yaml文件,地址:https://oktools.net/json2yaml

    # 拼接yaml文件的完整路径
    yaml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),"test_data.yaml")
    # 读取yaml文件内容
    with open(yaml_path,"r",encoding="utf-8") as f:
        res = f.read()
        data = yaml.load(res,Loader=yaml.FullLoader)

    # data = [ [{"name":"tom","age":20},{"expectRes":"hello"}],
    #          [{"name":"橘子","age":25},{"expectRes":"hello,world"}]
    #          ]
    @pytest.mark.parametrize("inputData,expect",data)
    def test_case02(self,inputData,expect):
        # 测试步骤
        print("测试步骤,传入参数是:%s,%d"%(inputData["name"],inputData["age"]))
        # 断言
        expectRes = expect["expectRes"]
        print("预期结果expectRes是:",expectRes)
        actualRes = "hello666"
        assert expectRes != actualRes

if __name__ == "__main__":
    # 运行当前文件夹下所有以test_开头的py文件
    # pytest.main()
    # 运行指定py文件
    pytest.main(["-s","test_case.py"])


引入allure测试报告----------------------------------------------------------------------------


import pytest,os,yaml,allure

@allure.epic("V1R2C03")     # 版本号
@allure.feature("商品管理") # 测试模块
@allure.story("添加商品")   # 测试模块中的子功能点

class TestExample():

    # 拼接yaml文件的完整路径
    yaml_path = os.path.join(os.path.dirname(os.path.abspath(__file__)),"test_data.yaml")
    # 读取yaml文件内容
    with open(yaml_path,"r",encoding="utf-8") as f:
        res = f.read()
        data = yaml.load(res,Loader=yaml.FullLoader)

    # data = [ [{"name":"tom","age":20},{"expectRes":"hello"}],
    #          [{"name":"橘子","age":25},{"expectRes":"hello,world"}]
    #          ]
    @pytest.mark.parametrize("inputData,expect",data)
    def test_case02(self,inputData,expect):
        # 测试步骤
        # print("测试步骤,传入参数是:%s,%d"%(inputData["name"],inputData["age"]))
        # 断言
        expectRes = expect["expectRes"]
        # print("预期结果expectRes是:",expectRes)
        actualRes = "hello6660"
        assert expectRes != actualRes


if __name__ == "__main__":
    # 第一步,指定在当前文件夹的temp下,生成测试报告需要的数据
    os.system("pytest --alluredir=./temp")
    # 第二步,根据temp下的数据,生成测试报告放在reports下,并清空原来的报告
    os.system("allure generate ./temp -o ./reports --clean")
 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值