美文网首页自动化pytest
Pytest和Allure测试框架-超详细版+实战6

Pytest和Allure测试框架-超详细版+实战6

作者: C1R2 | 来源:发表于2021-02-24 22:34 被阅读0次

    六,日志管理及代码覆盖率

    1, pytest中logging的应用

    在这里插入图片描述

    2, 日志及级别的含义

    在这里插入图片描述

    自动化测试用例的调试信息非常有用,可以让我们知道现在的运行情况到,执行到哪步以及相应的出错信息等,可以在pytest里面,有时并不会输出所有信息,比如默认情况下pass的测试用例是没有print输出的。本文将介绍如何在pytest里面实时显示所有的log信息。

    1. 用print输出log信息
      slowTest_print.py1. 用print输出log信息
      slowTest_print.py
    import time
    
    
    def test_1():
        print('test_1')
        time.sleep(1)
        print('after 1 sec')
        time.sleep(1)
        print('after 2 sec')
        time.sleep(1)
        print('after 3 sec')
        assert 1, 'should pass'
    
    
    def test_2():
        print('in test_2')
        time.sleep(1)
        print('after 1 sec')
        time.sleep(1)
        print('after 2 sec')
        time.sleep(1)
        print('after 3 sec')
        assert 0, 'failing for demo purposes'
    

    运行上述程序,pytest会capture所有的输出,保存直到所有的测试用例都执行结束,并且只输出那些失败的测试用例的信息,对于成功的测试用例,没有print的信息显示。
    从下面的运行结果,如果需要查看test_1()的运行情况,没有log信息可看,print没有显示。

    C:\Users\yatyang\PycharmProjects\pytest_example>pytest -v slowTest_print.py

    以用‘-s’参数或者 ‘–capture=no’,这样就可以输出所有测试用的print信息。但是pytest还是会等着所有的测试用例都执行完毕才会显示运行结果。可以看到下面的test_1也显示出print的相关信息。

    C:\Users\yatyang\PycharmProjects\pytest_example>py.test --capture=no slowTest_print.py

    1. Python Logging用法
      一般情况下,一些程序的调试过程中我们会让它输出一些信息,特别是一些大型的程序,我们通过这些信息可以了解程序的运行情况,python提供了一个日志模块logging,它可以把我们想要的信息全部保存到一个日志文件中,方便查看。
    import logging
    
    logging.debug('This is debug message')
    logging.info('This is info message')
    logging.warning('This is warning message')
    

    屏幕上打印:
    WARNING:root:This is warning message
    默认情况下,logging将日志打印到屏幕,日志级别为WARNING;
    日志级别大小关系为:CRITICAL > ERROR > WARNING > INFO > DEBUG > NOTSET,当然也可以自己定义日志级别。

    1. 在pytest中用logging代替print
      我们现在来看看在pytest的测试用例里面用logging的输出代替print,有什么不同。
      slowTest_logging.py
    import time
    import logging
    
    logging.basicConfig(level=logging.DEBUG)
    
    def test_1():
        log = logging.getLogger('test_1')
        time.sleep(1)
        log.debug('after 1 sec')
        time.sleep(1)
        log.debug('after 2 sec')
        time.sleep(1)
        log.debug('after 3 sec')
        assert 1, 'should pass'
    
    
    def test_2():
        log = logging.getLogger('test_2')
        time.sleep(1)
        log.debug('after 1 sec')
        time.sleep(1)
        log.debug('after 2 sec')
        time.sleep(1)
        log.debug('after 3 sec')
        assert 0, 'failing for demo purposes'
    

    运行结果如下,log信息的显示是不是可读性更好了呢。可是pytest还是要等所有的结果都运行完毕才完全输出到屏幕上,没法看到实时的运行情况。比如现在要测试一个新的image,不知道quality如何,如果测试用例非常多,测试人员就得一直等,也许前面的一些测试用都失败就可以停止执行了。那怎么实现实时显示呢?请看方法4。

    C:\Users\yatyang\PycharmProjects\pytest_example>pytest slowTest_logging.py

    1. pytest用logging和–capture=no实现实时输出log信息
      请自己去运行下面的程序吧,可以看到该程序是实时输出当前测试用例执行的情况。
      C:\Users\yatyang\PycharmProjects\pytest_example>pytest -s slowTest_logging.py

    5.总结
    在写自动化测试用例时,添加有用的log信息是非常有必要的。比如在初期的调试过程,能够一旦运行有问题,就可以获取到精确的调试信息。后期在稳定的运行中,其他测试人员来运行也可以很容易上手,所以大家一定要重视测试用例的调试信息。
    通过本文,应该知道如何用pytest,logging和–capture=no实现运行测试用例的实时输出所有的log信息。

    3, 代码覆盖率-多用在单元测试中

    在这里插入图片描述

    一,上篇(---- pytest-cov)
    简介:
    pytest-cov 是pytest的一个插件,其本质也是引用 python coverage 库 用来统计代码覆盖率。以下这篇文章只供理解,真实项目的话,我们都是用api调用接口的,所以真实项目使用会更复杂一些,这个待下次说明。
    一般来说:
    路径覆盖率 > 判定覆盖 > 语句覆盖

    安装
    pip install pytest-cover

    安装完后有

    py.test -h 可以看到多了以下的用法,说明安装成功:
    coverage reporting with distributed testing support:
    

    另外说明:coverage 是在覆盖率是语句覆盖的一种,不能对你的逻辑做判读,真实意义的话,需要多结合项目本身,这个覆盖率数据没有很强大说服力,不要盲目追求。

    范例
    新建三个文件,cau.py 与test_conver.py 在同一个目录code下。run.py文件在上一级目录pp下。
    代码关系如下。


    在这里插入图片描述

    1.新建函数文件cau.py

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    def cau (type,n1, n2):
    
        if type==1:
            a=n1 + n2
        elif type==2:
            a = n1 - n2
        else:
            a=n1 * n2
        return a
    

    2.新建test_conver.py测试文件:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    from code.cau import cau
    class Test_cover:
        def test_add(self):
            a=cau(1,2,3)
            assert a==3
    

    3.新建执行脚本run.py

    #!/usr/bin/env ```python
    # -*- coding: utf-8 -*-
    import pytest
    
    if __name__=='__main__':
        pytest.main(["--cov=./code/" ,"--cov-report=html","--cov-config=./code/.coveragerc"] )  # 执行某个目录下case
    

    说明:–cov参数 后面接的是测试的目录 (经给测试,不能指定某个特定的文件。),程序代码跟测试脚本必须在同一个文件下。 --cov-report=html 生成报告 ,只需要python run.py 就可以运行

    coveragerc 意思是跳过某些脚本的覆盖率测试。此处跳过test_cover.py文件跟init文件。

    内容如下:

    [run]
    omit =
        tests/*
         */__init__.py
        */test_cover.py
    

    结果
    生成完后可以直接点击indexhtml


    在这里插入图片描述

    可以看到如下的执行情况,绿色代表运行,红色代表未被执行,自己检查下代码逻辑,可以得出该结果是正确的。


    在这里插入图片描述

    二:下篇(— coverage.py api)
    使用pytest-cov 无法统计用 api调用服务的测试脚本所覆盖率,但大部分的项目基本也是使用api调用。所以我们额外需要使用coverage.py api 来统计。
    当你安装pytest-cov时,已经默认安装了coverage 这个库。

    服务启动
    要想扫描到代码,必须在服务启动的时候要插入coverage相关配置。
    我这边是flask 启动的,所以在flask启动的代码上添加,如下:

    if __name__ == '__main__':
        cov = Coverage()
        cov.start()  # 开始检测代码
        print ("qidong")
        app.run(debug=True, host='0.0.0.0',port=9098)  #原本只有这一行
        cov.stop()  # 停止纪录
        print ("guanbi")
        cov.save()  # 保存在 .coverage 中
        print ("save")
        cov.html_report()  # 生成 HTML 报告
    
    

    原本我们是python xx.py 这样启动,但现在不可以。
    需要改成这样,source 表示目录,xx表示执行文件。

    coverage run --source='/xxx/' xx.py    
    
    

    启动运行图如下:


    在这里插入图片描述

    然后调用你的自动化脚本(自动化脚本是直接调的该服务提供的api 。)


    在这里插入图片描述

    自动化如果正常运行,能看到运行的请求

    以上说明你的脚本跟服务是没问题的

    ctr-c停掉该脚本后,最后显示save,如果显示”Coverage.py warning: No data was collected. (no-data-collected)“ 说明的服务运行方式有问题,coverage 服务没有运行到你代码

    报告生成
    输入以下命令

    coverage report
    
    
    在这里插入图片描述

    最后一步最后输入

    coverage html
    
    

    这样就可以省 html 文件了。

    导出在window上看,具体点击某个文件,点击run,你可以看到绿色的就是运行的。但有问题是,你会发现有些代码应该是要被执行,但却没有被执行。所以coverage的数据准不准很难说。

    4,allure测试报告框架

    pytest+allure现在都是结合jenkins来搞的,很简单相信大家都会,不会的老哥可以去看我的另一个博客持续集成里的有写

    5,定制报告

    在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述 在这里插入图片描述

    定制报告
    Feature: 标注主要功能模块
    Story: 标注Features功能模块下的分支功能
    Severity: 标注测试用例的重要级别
    Step: 标注测试用例的重要步骤
    Issue和TestCase: 标注Issue、Case,可加入URL

    1、Features定制详解

    # -*- coding: utf-8 -*-
    # @Time    : 2018/8/17 上午10:10
    # @Author  : WangJuan
    # @File    : test_case.py
    import allure
    import pytest
    
    @allure.feature('test_module_01')
    def test_case_01():
        """
        用例描述:Test case 01
        """
        assert 0
    
    @allure.feature('test_module_02')
    def test_case_02():
        """
        用例描述:Test case 02
        """
        assert 0 == 0
    
    if __name__ == '__main__':
        pytest.main(['-s', '-q', '--alluredir', './report/xml'])
    
    

    添加feature,Report展示见下图。


    在这里插入图片描述

    2、Story定制详解

    # -*- coding: utf-8 -*-
    # @Time    : 2018/8/17 上午10:10
    # @Author  : WangJuan
    # @File    : test_case.py
    import allure
    import pytest
    
    @allure.feature('test_module_01')
    @allure.story('test_story_01')
    def test_case_01():
        """
        用例描述:Test case 01
        """
        assert 0
    
    @allure.feature('test_module_01')
    @allure.story('test_story_02')
    def test_case_02():
        """
        用例描述:Test case 02
        """
        assert 0 == 0
    
    if __name__ == '__main__':
        pytest.main(['-s', '-q', '--alluredir', './report/xml'])
    
    

    添加story,Report展示见下图。


    在这里插入图片描述

    3、用例标题和用例描述定制详解

    # -*- coding: utf-8 -*-
    # @Time    : 2018/8/17 上午10:10
    # @Author  : WangJuan
    # @File    : test_case.py
    import allure
    import pytest
    
    @allure.feature('test_module_01')
    @allure.story('test_story_01')
    #test_case_01为用例title
    def test_case_01():
        """
        用例描述:这是用例描述,Test case 01,描述本人
        """
        #注释为用例描述
        assert 0
    
    if __name__ == '__main__':
        pytest.main(['-s', '-q', '--alluredir', './report/xml'])
    
    

    添加用例标题和用例描述,Report展示见下图。


    在这里插入图片描述

    4 、Severity定制详解
    Allure中对严重级别的定义:
    1、 Blocker级别:中断缺陷(客户端程序无响应,无法执行下一步操作)
    2、 Critical级别:临界缺陷( 功能点缺失)
    3、 Normal级别:普通缺陷(数值计算错误)
    4、 Minor级别:次要缺陷(界面错误与UI需求不符)
    5、 Trivial级别:轻微缺陷(必输项无提示,或者提示不规范)

    # -*- coding: utf-8 -*-
    # @Time    : 2018/8/17 上午10:10
    # @Author  : WangJuan
    # @File    : test_case.py
    import allure
    import pytest
    
    @allure.feature('test_module_01')
    @allure.story('test_story_01')
    @allure.severity('blocker')
    def test_case_01():
        """
        用例描述:Test case 01
        """
        assert 0
    
    @allure.feature('test_module_01')
    @allure.story('test_story_01')
    @allure.severity('critical')
    def test_case_02():
        """
        用例描述:Test case 02
        """
        assert 0 == 0
    
    @allure.feature('test_module_01')
    @allure.story('test_story_02')
    @allure.severity('normal')
    def test_case_03():
        """
        用例描述:Test case 03
        """
        assert 0
    
    @allure.feature('test_module_01')
    @allure.story('test_story_02')
    @allure.severity('minor')
    def test_case_04():
        """
        用例描述:Test case 04
        """
        assert 0 == 0
    
    if __name__ == '__main__':
        pytest.main(['-s', '-q', '--alluredir', './report/xml'])
    
    

    添加Severity,Report展示见下图。


    在这里插入图片描述

    5****Step定制详解

    # -*- coding: utf-8 -*-
    # @Time    : 2018/8/17 上午10:10
    # @Author  : WangJuan
    # @File    : test_case.py
    import allure
    import pytest
    
    @allure.step("字符串相加:{0},{1}")     
    # 测试步骤,可通过format机制自动获取函数参数
    def str_add(str1, str2):
        if not isinstance(str1, str):
            return "%s is not a string" % str1
        if not isinstance(str2, str):
            return "%s is not a string" % str2
        return str1 + str2
    
    @allure.feature('test_module_01')
    @allure.story('test_story_01')
    @allure.severity('blocker')
    def test_case():
        str1 = 'hello'
        str2 = 'world'
        assert str_add(str1, str2) == 'helloworld'
    
    if __name__ == '__main__':
        pytest.main(['-s', '-q', '--alluredir', './report/xml'])
    
    

    添加Step,Report展示见下图。


    在这里插入图片描述

    6、Issue和TestCase定制详解

    # -*- coding: utf-8 -*-
    # @Time    : 2018/8/17 上午10:10
    # @Author  : WangJuan
    # @File    : test_case.py
    import allure
    import pytest
    
    @allure.step("字符串相加:{0},{1}")     # 测试步骤,可通过format机制自动获取函数参数
    def str_add(str1, str2):
        print('hello')
        if not isinstance(str1, str):
            return "%s is not a string" % str1
        if not isinstance(str2, str):
            return "%s is not a string" % str2
        return str1 + str2
    
    @allure.feature('test_module_01')
    @allure.story('test_story_01')
    @allure.severity('blocker')
    @allure.issue("http://www.baidu.com")
    @allure.testcase("http://www.testlink.com")
    def test_case():
        str1 = 'hello'
        str2 = 'world'
        assert str_add(str1, str2) == 'helloworld'
    
    if __name__ == '__main__':
        pytest.main(['-s', '-q', '--alluredir', './report/xml'])
    
    

    添加Issue和TestCase,Report展示见下图。


    在这里插入图片描述

    **8、attach定制详解

     file = open('../test.png', 'rb').read()
     allure.attach('test_img', file, allure.attach_type.PNG)
    
    

    在报告中增加附件:allure.attach(’arg1’,’arg2’,’arg3’):
    arg1:是在报告中显示的附件名称
    arg2:表示添加附件的内容
    arg3:表示添加的类型(支持:HTML,JPG,PNG,JSON,OTHER,TEXTXML)

    添加attach参数,Report展示见下图。


    在这里插入图片描述

    6,pytest运行指定用例

    随着软件功能的增加,模块越来越多,也意味用例越来越多,为了节约执行时间,快速得到测试报告与结果,在工作中可以通过运行指定用例,达到快速执行用例

    例子目录


    在这里插入图片描述

    spec_sub1_modul_test.py

    #coding: UTF-8
    import pytest
    
    def test_004_spec():
        assert 1==1
    def test_005_spec():
        assert True==False
    
    class Test_Class():
        def test_006_spec(self):
            assert 'G' in "Goods"
    
    

    spec_sub2_modul_test.py

    #coding: UTF-8
    import pytest
    
    def test_007_spec():
        assert 1==1
    def test_008_spec():
        assert True==False
    
    class Test_Class():
        def test_009_spec(self):
            assert 'G' in "Goods"
    
    

    spec_001_modul_test

    #coding: UTF-8
    import pytest
    
    def test_001_spec():
        assert 1==1
    def test_002_spec():
        assert True==False
    
    class Test_Class():
        def test_003_spec(self):
            assert 'H' in "Hell,Jerry"
    
    

    运行指定模块

    if __name__ == '__main__':
        pytest.main("-v -s spec_001_modul_test.py")
    
    

    运行批量文件夹(运行当前文件夹包括子文件夹所有用例)

    #coding: UTF-8
    import pytest
    if __name__ == '__main__':
        pytest.main("-v -s ./")
    
    

    运行指定文件夹(subpath1目录下面所有用例)

    #coding: UTF-8
    import pytest
    if __name__ == '__main__':
        pytest.main("-v -s subpath1/")
    
    

    运行模块中指定用例 (运行模块中test_001_spec用例)

    if __name__ == '__main__':
        pytest.main("-v -s spec_001_modul_test.py::test_001_spec")
    
    

    运行class中指定的用例(运行模块中Test_Class类test_003_spec方法)

    if __name__ == '__main__':
       pytest.main("-v -s spec_001_modul_test.py::Test_Class::test_003_spec")
    
    

    模糊匹配运行用例(匹配当前目录下面包含)

    if __name__ == '__main__':
        #运行spec_001_modul_test模块中用例名称包含spec的用例
        pytest.main("-v -s -k spec spec_001_modul_test.py")
        #运行当前文件夹匹配Test_Class的用例,类文件下面的用例
        pytest.main('-s -v -k Test_Class')
    
    

    7,按重要性级别进行一定范围测试

    在这里插入图片描述

    此标记用来标识测试用例或者测试类的级别,分为blocker,critical,normal,minor,trivial5个级别,下面们把测试用例按级别标记,并查看一下测试报告


    在这里插入图片描述

    8, 为测试添加详说明@allure.description;@allure.title;

    1.title case标题
    可以自定义用例标题,标题默认为函数名.

    @allure.title

    # -*- coding: utf-8 -*-
    # @Time    : 2019/3/12 11:46
    # @Author  : zzt
    
    import allure
    import pytest
    
    @allure.title("用例标题0")
    def test_0():
        pass
    
    @allure.title("用例标题1")
    def test_1():
        pass
    
    def test_2():
        pass
    
    

    执行效果:


    在这里插入图片描述
    1. 说明
      可以添加测试的详细说明,以便根据需要为报告阅读器提供尽可能多的上下文。

    两种方式:
    @allure.description 提供描述字符串的装饰器
    @allure.description_html 提供一些HTML在测试用例的描述部分 (待研究)

    # -*- coding: utf-8 -*-
    # @Time    : 2019/3/12 11:46
    # @Author  : zzt
    
    import allure
    import pytest
    
    @allure.title("用例标题0")
    @allure.description("这里是对test_0用例的一些详细说明")
    def test_0():
        pass
    
    @allure.title("用例标题1")
    def test_1():
        pass
    
    @allure.title("用例标题2")
    def test_2():
        pass
    
    
    在这里插入图片描述

    9, 链接@allure.link @allure.issue @allure.testcase

    在这里插入图片描述

    @allure.link @allure.issue @allure.testcase

    # -*- coding: utf-8 -*-
    # @Time    : 2019/3/12 11:46
    # @Author  : zzt
    
    import allure
    import pytest
    
    @allure.feature('这里是一级标签')
    class TestAllure():
    
        @allure.title("用例标题0")
        @allure.story("这里是第一个二级标签")
        @pytest.mark.parametrize('param', ['青铜', '白银', '黄金'])
        def test_0(self, param):
            allure.attach('附件内容是: '+param, '我是附件名', allure.attachment_type.TEXT)
    
        @allure.title("用例标题1")
        @allure.story("这里是第二个二级标签")
        def test_1(self):
            allure.attach.file(r'E:\Myproject\pytest-allure\test\test_1.jpg', '我是附件截图的名字', attachment_type=allure.attachment_type.JPG)
    
        @allure.title("用例标题2")
        @allure.story("这里是第三个二级标签")
        @allure.issue('http://baidu.com', name='点击我跳转百度')
        @allure.testcase('http://bug.com/user-login-Lw==.html', name='点击我跳转禅道')
        def test_2(self):
            pass
    
    

    执行结果如下:


    在这里插入图片描述

    参考链接
    https://blog.csdn.net/qq_42610167/article/details/101204066

    相关文章

      网友评论

        本文标题:Pytest和Allure测试框架-超详细版+实战6

        本文链接:https://www.haomeiwen.com/subject/nxbptltx.html