• pytest测试框架+allure


    1、测试识别和运行

    文件识别:

    • 在给定的目录中,搜索所有test_.py或者_test.py文件

    用例识别:

    • Test*类包含的所有test_*的方法(测试类不能有__init__方法)
    • 不在类中的所有test_*方法
    • pytest也能执行unit test写的用例和方法

    运行方式
    1、pycharm页面修改默认的测试运行方式
    settings页面,输入pytest,修改Default test runner
    在这里插入图片描述
    2、右键执行python文件
    3、命令行界面执行,点击pycharm下方的terminal,打开命令行界面,执行pytest 命令
    在这里插入图片描述
    4、pycharm代码边界界面,左侧单条用例运行按钮
    在这里插入图片描述
    5、主函数运行方式
    在运行文件中编写主函数,主函数启动需要导入pytest包,不然找不到pytest方法

    import pytest
     
    class TestClass:
        def test_one(self):
            x = "this"
            assert "h" in x
     
        def test_two(self):
            x = "hello"
            assert hasattr(x, "check")
     
    if __name__ == '__main__':
    #    pytest.main()
        pytest.main("test_study.py")
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    pytest.main()会自动读取当前目录下的所有test开头的.py文件,运行test方法或者类

    可以传入不同的参数,让运行更加定制化

    pytest.main(['./'])               # 运行./目录下所有(test_*.py  和 *_test.py)
    pytest.main (['./subpath1'])    # 运行./subpath1 目录下用例
    pytest.main (['./subpath1/test_module1.py'])    # 运行指定模块
    pytest.main (['./subpath1/test_module1.py::test_m1_1'])  # 运行模块中的指定用例
    pytest.main (['./subpath2/test_module2.py::TestM2::test_m2_02'])  # 运行类中的指定用例
    pytest.main (['-k','pp'])         # 匹配包含pp的用例(匹配目录名、模块名、类名、用例名)
    pytest.main(['-k','spec','./subpath1/test_module1.py'])     # 匹配test_module1.py模块下包含spec的用例
    pytest.main(['-k','pp','./subpath2/test_module2.py::TestM2'])   # 匹配TestM2类中包含pp的用例
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    2、参数化

    @pytest.mark.parametrize(argnames,argvalues)

    • argnames:要参数化的变量,可以是string(用逗号分割),list,tuple
    • argvalues:参数化的值,list[tuple],以列表形式传入元组,每个元组都是一条测试数据
    • ids,:默认为none,用来重新定义测试用例的名称
    # 使用string分割参数化的变量
    @pytest.mark.parametrize('a,b',[(10,20),(30,40)])
    def test_param(a, b):
    	print(a,b)
    
    # 使用list分割参数化的变量
    @pytest.mark.parametrize(['a', 'b'],[(10,20),(30,40)])
    def test_param(a, b):
    	print(a,b)
    
    # 使用tuple分割参数化的变量
    @pytest.mark.parametrize(('a', 'b'),[(10,20),(30,40)])
    def test_param(a, b):
    	print(a,b)
    
    # 使用ids重新定义用例名称
    @pytest.mark.parametrize('a,b',[(10,20),(30,40)], ids=['case1', 'case2'])
    def test_param(a, b):
    	print(a,b)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20

    yaml参数化
    pip install PyYAML
    yaml实现list

    - 10
    - 20
    - 30
    
    • 1
    • 2
    • 3

    yaml实现字典

    by: id
    locator: name
    action: click
    
    • 1
    • 2
    • 3

    yaml二维数组

    companies:
      - id: 1
        name: company1
        price: 200w
      - id: 2
        name: company2
        price: 500w
    fruites:
      - name: 苹果
        price: 8.6
      - name: 香蕉
        price: 2.6
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    读取yaml文件
    yaml.safe_load(open(‘./data.yaml’))

    # -*- coding: utf-8 -*-
    import yaml
    
    with open("enviro.yaml", encoding="utf-8") as yaml_file:
        data = yaml.safe_load(yaml_file)
    
    print(data["fruites"])
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3、pytest-html报告

    pip install pytest-html
    pytest -s --html=./report.html
    
    • 1
    • 2

    4、测试报告美化-allure

    1、操作系统内部先安装allure
    2、安装allure-pytest插件

    pip install allure-pytest
    
    • 1

    3、运行测试用例
    查看pytest中allure相关的命令行参数

    C:\Users\Administrator>pytest --help | findstr allure  <== linux 使用grep过滤
      --allure-severities=SEVERITIES_SET     <==  根据用例级别过滤需要执行的用例
      --allure-epics=EPICS_SET               
      --allure-features=FEATURES_SET         <== 根据用例设置的feature名称过滤需要执行的用例
      --allure-stories=STORIES_SET           <== 根据用例设置的story名称过滤需要执行的用例
      --allure-ids=IDS_SET  Comma-separated list of IDs.
      --allure-link-pattern=LINK_TYPE:LINK_PATTERN
      --alluredir=DIR       <== 指定存放用例执行结果的目录
      --clean-alluredir     清除alluredir文件夹(如果存在)
      --allure-no-capture   Do not attach pytest captured logging/stdout/stderr to
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    4、执行测试命令

    # --alluredir: 用于指定存储测试结果的路径
    pytest [测试文件] -vs --alluredir=./result/ --clean-alluredir
    
    
    • 1
    • 2
    • 3

    5、查看测试报告

    • 在线查看报告,直接打开默认浏览器展示当前报告
    # 注意这里的serve书写,后面接用例执行结果(./result/:就是存放执行结果的目录路径)
    allure serve ./result/
    
    • 1
    • 2
    • 从结果生成报告
      1.生成报告,注意是将执行结果从/result目录,generate到/report目录
    # 注意:覆盖路径加--clean
    allure generate ./result/ -o ./report/ --clean
    
    • 1
    • 2

    2.打开报告

    allure open -h 127.0.0.1 -p 8883 ./report/
    
    
    • 1
    • 2

    在这里插入图片描述

    allure常用特性
    支持在报告中查看测试功能、子功能或场景、测试步骤和测试附加信息等,可以通过@feature、@story、@step和@attach等装饰器实现

    实现的步骤

    • import allure
    • 功能上加@allure.feature(“功能名称”)
    • 子功能上加@allure.story(“子功能名称”)
    • 用例标题@allure.title(“用例名称”)
    • 用例描述@allure.description(“用例描述”)
    • 步骤上加@allure.step(“步骤细节”)
    • @allure.attach(“具体文本信息”),需要附加的信息,可以是数据、文本、图片、视频和网页
    • 用例级别@allure.severity(级别)
    • 如果只测试登录功能运行的时候,可以加限制过滤
    # 注意这里--allure-features中间是-中线, 需要使用双引号
    #  不能过滤--allure-features下的--allure-stories
    pytest 文件名 --allure-features="登录模块"
    
    
    • 1
    • 2
    • 3
    • 4

    1、allure特性-feature/story
    @allure.feature与@allure.story的关系

    • feature相当于一个功能,一个大模块,将case分类到某个feature中,报告中Behaviors(功能中展示),相当于testsuite
    • story相当于这个功能或者模块下的不能场景,分支功能,属于feature之下的结构,报告中features中展示,详单与tescase
    • feature与story类似于父子关系
      2、allure特性-step
    • 测试过程中每个步骤,一般放在具体逻辑方法中
    • 可以放在关步骤中,在报告中显示
    • 在app、web自动化测试中,建议每切换到一个新页面就做一个step
      用法:
    • @allure.step():只能以装饰器的形式放在类或者方法上面
    • with allure.step():可以放在测试用例方法里面,但是测试步骤代码需要被该语句包含
      3、allure特性-testcase
      关联测试用例,可以直接给测试用例的地址链接,一般用于关联手工测试用例
      实力代码:
    import pytest
    import allure
    
    @allure.feature('用户登录')
    class TestLogin:
    
    	@allure.story('登录成功')
    	def test_login_success(self):
    		with allure.step('步骤1:打开应用'):
    			print('打开应用')
    		with allure.step('步骤2:进入登录页面'):
    			print('进入登录页面')
    		with allure.step('步骤3:输入用户名和密码'):
    			print('输入用户名和密码')
    		print('这是登录成功测试用例')
    
    	@allure.story('登录失败')
    	def test_login_fail(self):
    		print('这是登录失败测试用例')
    
    	@allure.story('登录失败')
    	@allure.title('用户名缺失')
    	def test_login_fail_a(self):
    		print('这是登录失败测试用例')
    
    	@allure.story('登录失败')
    	@allure.testcase('https://www.baidu.com/', '关联测试用例地址')
    	@allure.title('密码缺失')
    	@allure.description('这是一个用例描述信息')
    	def test_login_fail_b(self):
    		with allure.step('点击用户名'):
    			print('输入用户名')
    		with allure.step('点击密码'):
    			print('输入密码')
    		print('点击登录')
    		with allure.step('点击登录之后登录失败'):
    			assert '1' == 1
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    按重要性级别 进行一定范围测试
    通常测试用PO、冒烟测试、验证上线测试。按照重要性级别来分别执行
    缺陷严重级别

    1. Blocker级别——中断缺陷
        客户端程序无响应,无法执行下一步操作。
    2. Critical级别――临界缺陷,包括:
        功能点缺失,客户端爆页。
    3. Major级别——较严重缺陷,包括:
        功能点没有满足需求。
    4. Normal级别――普通缺陷,包括:
        1. 数值计算错误
        2. JavaScript错误。
    5. Minor级别———次要缺陷,包括:
        1. 界面错误与UI需求不符。
        2. 打印内容、格式错误
        3. 程序不健壮,操作未给出明确提示。
    6. Trivial级别——轻微缺陷,包括:
        1. 辅助说明描述不清楚
        2. 显示格式不规范,数字,日期等格式。 
        3. 长时间操作未给用户进度提示
        4. 提示窗口文字未采用行业术语
        5. 可输入区域和只读区域没有明显的区分标志
        6. 必输项无提示,或者提示不规范。
    7. Enhancement级别——测试建议、其他(非缺陷)
       1. 以客户角度的易用性测试建议。
       2. 通过测试挖掘出来的潜在需求。
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24

    解决方法:

    • 通过附加pytest.mark标记
    • 通过allure.feature,allure.story
    • 也可以通过allure.servity来附加标记
      步骤:
      在方法,函数和类上面加:@allure.severity(allure.severity_level.TRIVIAL)
      执行时过滤:pytest -vs [文件名] --allure-severities normal, critical

    前端自动化测试-截图
    前端自动化测试经常需要附加图片或html,在适当的地方,适当时机截图
    @allure.attach 实现不同类型附件,可以补充测试步骤或测试结果
    使用方式:

    • 在测试报告附加网页
    allure.attach(body(内容), name, attachment_type, extension)
    allure.attach('这是一段html', 'html测试', attachment_type=allure.attachment_type.HTML)
    
    
    • 1
    • 2
    • 3
    • 在测试报告附加图片
    allure.attach.file(source, name, attachment_type, extension)
    allure.attach.file('./123.jpg', name='这是一个图片', attachment_type=allure.attachment_type.JPG)
    
    
    • 1
    • 2
    • 3

    示例代码:

    import allure
    
    def test_attach_text():
    	allure.attach('这是一个纯文本', attachment_type=allure.attachment_type.TEXT)
    
    def test_attach_html():
    	allure.attach('这是一段html', 'html测试', attachment_type=allure.attachment_type.HTML)
    
    def test_attach_phote():
    	allure.attach.file('./123.jpg', name='这是一个图片', attachment_type=allure.attachment_type.JPG)
    
    def test_attach_video():
    	allure.attach.file('./123.mp4',name='这是一个视频',attachment_type=allure.attachment_type.MP4)
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    import allure
    from selenium import webdriver
    import time
    import pytest
    
    
    @allure.testcase('https://www.baidu.com/', '百度搜索功能')
    @pytest.mark.parametrize('data',
                             ['allure', 'pytest', 'unittest'],
                             ids=['search allure', 'search pytest', 'search unittest']
                             )
    def test_search(data):
    	with allure.step('步骤1:打开浏览器输入百度地址'):
    		driver = webdriver.Chrome()
    		driver.implicitly_wait(5)
    		driver.get('https://www.baidu.com/')
    
    	with allure.step(f'步骤2:在搜索框中输入{data}, 并点击百度一下'):
    		driver.find_element_by_id('kw').send_keys(data)
    		driver.find_element_by_id('su').click()
    		time.sleep(2)
    
    	with allure.step('步骤3: 截图保存到项目中'):
    		driver.save_screenshot(f'./result/{data}.jpg')
    		allure.attach.file(f'./result/{data}.jpg', name=f'搜索{data}的截图', attachment_type=allure.attachment_type.JPG)
    		allure.attach(driver.page_source, f'搜索{data}的网页内容', allure.attachment_type.HTML)
    
    	with allure.step('步骤4:关闭浏览器,退出'):
    		driver.quit()
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
  • 相关阅读:
    OA项目之我的审批(会议查询&会议签字)
    eunomia-bpf: 让 eBPF 程序的开发和部署尽可能简单
    微信小程序框架---视图层&逻辑层&API&事件
    sublime_text_4126_x64 激活及安装
    sqli-labs(less-11)
    Mac 执行 brew install 出现 Error: Command failed with exit 128: git
    MyBatisPlus
    python:OderedDict函数
    FPGA project :dds
    dataprp库本地参数
  • 原文地址:https://blog.csdn.net/HBT036017/article/details/128106987