首页 > 其他分享 > unittest框架、Pytest框架

unittest框架、Pytest框架

时间:2023-04-07 17:23:01浏览次数:25  
标签:__ 框架 unittest pytest Pytest 测试 test 执行

unittest+pytest

unittest单元测试框架

unittest是python内置的单元测试框架,具备编写用例、组织用例、执行用例、输出报告等自动化框架的条件。

unittest工作原理

unittest结构图:

img

test case :一个完整的测试单元,执行该测试单元可以完成对某一个问题的验证,完整体现在:测试前环境准备(setUp),执行测试代码(run),及测试后环境还原(tearDown);
test suite :多个测试用例的集合,测试套件或测试计划;
testLoader :加载TestCase到TestSuite中的,其中loadTestsFrom__()方法用于寻找TestCase,并创建它们的实例,然后添加到TestSuite中,返回TestSuite实例;
test runner :执行测试用例,并将测试结果保存到TextTestResult实例中,包括运行了多少测试用例, 成功了多少,失败了多少等信息;
test fixture:一个测试用例的初始化准备及环境还原,主要是setUp() 和 setDown()方法;

例子:

#定义一个测试类(遵守驼峰命名法),继承unittest.TestCase
class TestCase(unittest.TestCase):
    #定义类,setUp、tearDown是unittest自带
    @classmethod
    def setUpClass(cls) -> None:
        print("测试开始1")
    def setUp(self) -> None:
        print("测试开始")

    #测试用例的命名规则为test_xxx,不以test_xxx命名的函数是方法,方法是不能被执行的
    def test_login(self):
        print("欢迎进入登录页面")

    def test_loginout(self):
        print("退出登录页面")

    def tearDown(self) -> None:
        print("测试结束")

    @classmethod
    def tearDownClass(cls) -> None:
        print("测试结束1")

if __name__ == '__main__':
    unittest.main
    
    
'''
测试开始1
测试开始
欢迎进入登录页面
测试结束
测试开始
退出登录页面
测试结束
测试结束1

'''
'''
setUpClass:整个测试开始后执行,只执行一次
tearDownClass:整个测试完成后执行,只执行一次
setUp:每运行一次用例前都会执行一次
tearDown:每运行一次用例后都会执行一次
测试用例的命名规则为test_xxx,不以test_xxx命名的函数是方法,方法是不能被执行的
'''

断言方法

测试中,我们会经常用到判断某个函数的返回结果是否等于某个值或者等于某个类型这种情况,非常适合使用断言来判断。在UnitTest中,TestCase 已经提供有封装好的断言方法进行断言校验。断言强调的是对于整个测试流程的结果进行判断,所以断言的内容是极为核心的。

assertEqual(a,b) a==b 值是否相等
aassertNotEqual(a,b) a!=b 值是否不相等
aasserIs(a,b) a is b 值是否相同
aassertIsNot(a,b) a is not b 值是否不同
assertIn(a,b) a in b a是否包含b
assertNotIn(a,b) a not in b a是否不包含b
ssertTrue(a) bool(a) is true 是否为真
assertFalse(a) bool(a)is false 是否为假
assertIsNone(a) a is None 是否为空
assertIsNotNone(a) a is None 是否不为空
assertIsInstance(a,b) Instance(a,b) a与b的数据类型一样
assertNotIsInstance(a) not Instance(a,b) a与b的数据类型不一样

@UnitTest.skip

有时候,测试用例很多,有些需要执行,有些不想执行,那就需要跳过一些测试用例,这时候就需要用到skip,skip用法:

无条件跳过,unittest.skip(“xxx”)
条件为True跳过,unittest.skipIf(1 < 2, ‘xxx’)
条件为False跳过,unittest.skipUnless(1 > 2, ‘xxx’)
执行失败不计入case总数中,unittest.expectedFailure

unittest.TestSuite

测试用例 是按照顺序执行,如果我们想自定义执行顺序怎么办,比如2可能依赖于1,在unittest中解决用例执行顺序的问题是使用TestSuite。

测试套件TestSuite的作用:

  • 用于给测试用例进行排序

  • 管理测试用例

unittest实战

步骤:

  1. 写一个类继承unittest.Testcase

  2. 导入unittest

  3. 编写测试用例(测试用例要以test开头)

    import time
    import unittest
    from selenium import webdriver
    
    #定义一个测试类(遵守驼峰命名法),继承unittest.TestCase
    class TestCase(unittest.TestCase):
        #定义类,setUp、tearDown是unittest自带
        @classmethod
        def setUpClass(cls) -> None:
            print("市政测试开始")
        def setUp(self) -> None:
            print("测试开始")
    
        #测试用例的命名规则为test_xxx,不以test_xxx命名的函数是方法,方法是不能被执行的
        def test_login(self):
            #将浏览器设置为全局变量,打开的浏览器不会关闭
            global driver
            print("欢迎进入登录页面")
            #打开谷歌浏览器
            driver = webdriver.Chrome();
            #加载管理员登录网页
            driver.get("https://municipal.test.shutoy.com/#/loginSecond?loginType=3")
            #浏览器加载最大
            driver.maximize_window()
            driver.find_element()
            time.sleep(5)
    
        def test_loginout(self):
            print("退出登录页面")
    
        def tearDown(self) -> None:
            print("测试结束")
    
        @classmethod
        def tearDownClass(cls) -> None:
            print("市政测试结束")
    
    if __name__ == '__main__':
        unittest.main
    

unittest运行很大的坑:

  1. 命令行方式

    python -m unittest 模块名.py
    
  2. main方式

需要配置环境(mian方法单独放在一个文件)

Pytest

pytest和unittest区别:

Pytest比起unittest来说比较自由,使用unittest首先,要继承TestCase的类,但是pytest是不需要的

在这里插入图片描述

一、用例设计规则

1.unittest

(1)测试类必须继承unittest.TestCase

(2)测试函数必须以”test_”开头

(3)测试类必须有unittest.main()方法

2.pytest

(1)测试文件的文件名必须以”test_”开头,或者以”_test”结尾

(2)测试类命名必须以”Test”开头

(3)测试函数名必须以”test”开头

(4)测试类里面不能使用”init”方法

总结:pytest是基于unittest衍生出来的新的测试框架,使用起来相对于unittest来说更简单、效率来说更高,pytest兼容unittest测试用例,但是反过来unittest不兼容pytest,所以说pytest的容错性更好一些!在使用交互逻辑上面pytest比unittest更全一些!

二、断言对比

1.unittest 断言

assertEqual(a, b) # 判断a和b是否相等

assertNotEqual(a, b) # 判断a不等于b

assertTrue(a) # 判断a是否为Ture

assertFalse(a) #判断a是否为False

assertIn(a, b) # a 包含在b里面

asserNotIn(a, b) # a 不包含在b里面

……

2.pytest 断言

pytest只需要用assert 来断言就行,assert 后面加需要断言的条件就可以了,例如:assert a = = b # 判断a是否等于b、

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

总结:从断言上面来看,pytest的断言比unittest要简单些,unittest断言需要记很多断言格式,pytest只有assert一个表达式,用起来比较方便

三、用例前置和后置

1.unittest前置和后置

(1)通过setup每个用例执行前执行,teardown每个用例执行后执行

(2)通过setupclass类里面所有用例执行前执行,teardownclass类里面所有用例执行后执行

2.pytest前置和后置

(1)模块级别:setup_module/teardown_module,整个.py全部用例开始前执行/全部用例执行完后执行

(2)函数级别:setup_function/teardown_function,只对函数级别生效,每个用例开始前和结束后执行一次

(3)类级别:setup_class/teardown_function,只对类级别生效,类里面所有用例开始前执行一次,所有用例执行完执行一次

(4)方法级别:setup_method/teardown_method,只是类里面方法级别生效,方法开始前执行一致,方法结束后执行一次

(5)方法级别:setup/teardown,这个与setup_method/teardown_method用法很类似,但是级别比method级别要低,也就是说在同一个方法中会先执行setup_method再执行setup,方法结束后先执行teardown再执行teardown_method

pytest自定义设置前置和后置:

通过firture可以自定义pytest的前置和后置,格式fixture(scope=”function”, params=None, autouse=False, ids=None, name=Noe)

scope:有四个级别,function(默认),class,module,session

params:参数列表

autouse:False为默认值,意思代表需要根据设置的条件(scope级别)来激活fixture,如果为Ture,则表示所有function级别的都被激活fixture

ids:每个字符串id的列表,感觉没啥实质性作用

name:fixture的名字

四、参数化

1.unittest参数化

可以通过nose_parameterized来实现,格式:@nose_parameterized.parameterized.expand(data), ‘data’为list格式的参数化的数据

2.pytest参数化

通过装饰器@pytest.mark.parametrize来实现

五、生成报告方式

1.unittest

通过HTMLTestRunner生成

2.pytest

(1)通过pytest-html生成html格式报告

(2)通过allure生成方案(很详细)

pytest是一个非常成熟的全功能的Python测试框架,主要有以下几个特点:

简单灵活,容易上手
支持参数化
能够支持简单的单元测试和复杂的功能测试,还可以用来做selenium/appnium等自动化测试、接口自动化测试(pytest+requests)
pytest具有很多第三方插件,并且可以自定义扩展,比较好用的如pytest-selenium(集成selenium)、pytest-html(完美html测试报告生成)、pytest-rerunfailures(失败case重复执行)、pytest-xdist(多CPU分发)等
测试用例的skip和xfail处理
可以很好的和jenkins集成
report框架----allure 也支持了pytest

在pytest框架中,有如下约束:
所有的单测文件名都需要满足test_.py格式或_ __test.py格式。
在单测文件中,测试类以Test开头,并且不能带有 init 方法(注意:定义class时,需要以T开头,不然pytest是不会去运行该class的)
在单测类中,可以包含一个或多个test_开头的函数。
此时,在执行pytest命令时,会自动从当前目录及子目录中寻找符合上述约束的测试函数来执行。

pytest

pytest运行方式:

第一种:命令行运行

pytest -s  name.py

第二种:主函数运行 -s:表示支持控制台打印,如果不加,print不会出现任何内容

if __name__ == '__main__':
    pytest.main(["-s","name.py"])

配置文件(pytest.ini):

应用场景:使用配置文件后可以快速的使用配置的项来选择执行哪些测试用例

注意:
1.在window下,pytest配置文件不允许写注释
2.一个工程内只需要一个pytest配置文件,并且保证文件名之前
3.一般情况下,只需要将pytest配置文件放到工程根目录下
4.配置有pytest配置文件的工程,只需要打开命令行,执行pytest命令,即可进行测试

使用方法:

  1. 项目下创建case模块

  2. 将测试脚本文件放到case中

  3. pytest的配置文件放在自动化项目目录下

  4. 名称为pytest.ini

  5. 命令行运行时会使用该配置文件中的配置

  6. 第一行内容为[pytest]

    示例

#告知系统该文件的类型
[pytest]
#指定测试用例存放位置
testpaths = ./case
#输出打印信息,添加pytest命令选项
addopts = -s
#执行的文件名
python_files = test*.py
#执行的测试类名
python_classes = Test*
#执行的方法名
python_functions = test*

image-20230314170946389

默认配置:

说明:测试用例文件名/测试类名/测试方法名都要以Test/test开头
[pytest]
testpaths = ./case
addopts = -s
python_files = test*.py
python_classes = Test*
python_functions = test*

自定义配置:

说明:测试用例文件名/测试类名/测试方法名,需要根据具体项目进行配置
修改默认配置的文件名/测试类名/测试方法名就可以
例如:
[pytest]
testpaths = ./case
addopts = -s
python_files = hm*.py
python_classes = Hm*
python_functions = hm*

单独指用一个文件执行:

[pytest]
testpaths = ./case
addopts = -s
python_files = 具体文件名称
python_classes = 具体类名
python_functions = 具体方法名

Pytest常用插件

1.能够生成pytest.html测试报告
2.能够控制pytest用例的执行顺序
3.能够掌握pytest失败重试

1.能够生成pytest.html测试报告

安装命令:

pip install pytest-html

使用:

1.在pytest配置文件中,增加命令选项, 在addopts = -s 后面增加 --html=用户路径/report.html
2.运行pytest命令,运行测试即可

--self-contained-html:代表直接生成html文件,无assert文件夹生成,将assert的css文件直接嵌入html中
[pytest]
testpaths = ./case
addopts = -s
          --html=./report/testReport.html  --self-contained-html
python_files = test*.py
python_classes = Test*
python_functions = test*

2.能够控制pytest用例的执行顺序

安装命令:

pip install pytest-ordering

使用:

1.标记于被测试的函数或者类。@pytest.mark.run(order=x)
2.根据order插入的指来指定运行顺序
3.order的值全部为正数或者负数时,值越小优先级越高
4.当正数负数同时存在,正数优先级高于负数

例子:

import pytest as pytest
class TestDemo:
    @pytest.mark.run(order=2)
    def test_001(self):
        print("djfijdiajfidjfifj")
        
    @pytest.mark.run(order=1)
    def test_002(self):
        print("请看下面一下啊")

3.能够掌握pytest失败重试

安装命令:

pip install pytest-rerunfailures

使用:

1.需要在pytest.ini增加命令选项,n代表次数
addopts = -s --reruns n
2.执行pytest测试即可

4.跳过测试函数

步骤:

1.在需要跳过的函数头上加上, @pytest.mark.skipif(条件,reason="跳过原因")
2.执行pytest即可
import pytest as pytest

a = 3
class TestDemo:
    @pytest.mark.run(order=2)
    def test_001(self):
        print("djfijdiajfidjfifj")

    @pytest.mark.skipif(a > 4 ,reason="A不对")
    @pytest.mark.run(order=1)
    def test_002(self):
        print("请看下面一下啊")

5.参数化功能

5.1 @pytest.mark.parametrize
1.在需要跳过的函数头上加上,@pytest.mark.parametrize(argnames,argvalues,indirect=False,ids=None,scope=None)
2.执行pytest即可
argnames:参数名
argvalues:参数对应的值,类型必须为可迭代类型,一般用list
一个参数使用方式:
1.argnames为字符串类型,根据需求决定何时的参数名
2.argvalues为列表类型,根据需求决定列表元素中的内容
3.在测试脚本中,参数,名字与argnames保持一致
4.在测试脚本中正常使用
import pytest as pytest

class TestDemo:
    # 单个参数
    # @pytest.mark.parametrize('参数变量',[数值1,数值2,数值3])
    @pytest.mark.parametrize("name", ["wang", "gui"])
    @pytest.mark.run(order=2)
    def test_001(self, name):
        print("姓名为", name)

    #多个参数
    #@pytest.mark.parametrize('参数1,参数2,..',[(数据1-1,数据1-2),(数据2-1,数据2-2),..])
    #注意
    #1.参数必须位于一个字符串内
    #2.数据格式为:[(),()]或者[[],[]]
    @pytest.mark.parametrize('name,age',[('小红','20'),('张三','18')])
    def test_002(self, name, age):
        print("姓名为:{},年龄为:{}".format(name,age))


if __name__ == '__main__':
    pytest.main('-s','test_case.py')
    
'''
test_case.py::TestDemo::test_001[wang] 姓名为 wang
PASSED
test_case.py::TestDemo::test_001[gui] 姓名为 gui
PASSED
test_case.py::TestDemo::test_002[\u5c0f\u7ea2-20] 姓名为:小红,年龄为:20
PASSED
test_case.py::TestDemo::test_002[\u5f20\u4e09-18] 姓名为:张三,年龄为:18
PASSED
'''
5.2 通过方法引用数据
import pytest as pytest


def list_a():
    return [('小红','20'),('张三','18')]

class TestDemo:

    #多个参数
    #@pytest.mark.parametrize('参数1,参数2,..',[(数据1-1,数据1-2),(数据2-1,数据2-2),..])
    #注意
    #1.参数必须位于一个字符串内
    #2.数据格式为:[(),()]或者[[],[]]
    @pytest.mark.parametrize('name,age',list_a())
    def test_002(self, name, age):
        print("姓名为:{},年龄为:{}".format(name,age))


if __name__ == '__main__':
    pytest.main('-s','test_case.py')

'''
test_case.py::TestDemo::test_002[\u5c0f\u7ea2-20] 姓名为:小红,年龄为:20
PASSED
test_case.py::TestDemo::test_002[\u5f20\u4e09-18] 姓名为:张三,年龄为:18
PASSED
'''
5.3 断言

assert xx:判断xx为真
assert not xx:判断xx不为真
assert a in b:判断b包含a
assert a not in b:判断b不包含a
assert a == b:判断a等于b
assert a != b:判断a不等于b

assert 表达式
assert 1==1

标签:__,框架,unittest,pytest,Pytest,测试,test,执行
From: https://www.cnblogs.com/MaybeGut/p/17197781.html

相关文章

  • 公寓床描述,从框架到具体内容快讯
    公寓一体床为上层为钢架床,下层集木质衣柜、钢制鞋柜、木制电脑桌、木书架为一体的公寓床,规格一般为(2000×900×2150)mm【长*宽*高(床板下沿净高需在1800以上防止碰头)】。一、公寓一体床下层为衣柜、学习桌、书架联体,带键盘架和电脑的主机柜,衣柜大门板、大抽屉和主机门带明......
  • Day 23 23.1 Scrapy框架之简介&安装
    Scrapy框架简介(1)基本介绍Scrapy一个开源和协作的框架,其最初是为了页面抓取(更确切来说,网络抓取)所设计的,使用它可以以快速、简单、可扩展的方式从网站中提取所需的数据。但目前Scrapy的用途十分广泛,可用于如数据挖掘、监测和自动化测试等领域,也可以应用在获取API所返回......
  • Day 23 23.2 Scrapy框架之详解
    Scrapy框架详解【1】Spider类Spiders是定义如何抓取某个站点(或一组站点)的类,包括如何执行爬行(即跟随链接)以及如何从其页面中提取结构化数据(即抓取项目)。换句话说,Spiders是您为特定站点(或者在某些情况下,一组站点)爬网和解析页面定义自定义行为的地方。1、生成初始的Request......
  • 支付宝定时任务怎么做?三层分发任务处理框架介绍
    一、背景介绍技术同学对定时任务肯定不陌生。定时任务一般用来定时批量进行业务处理。支付宝卡包券到期提醒、删除过期失效券,五福大促批量给用户发放添福红包等场景,都是通过定时任务触发来完成的。作者有幸参与了2023兔年五福大促的开发,主导完成了福气乐园分会场平分5000万大奖需求......
  • scrapy爬虫框架(六)Item Pipeline的使用
      ItemPipeline即项目管道,它的调用发生在Spider产生Item之后。当Spider解析完Response,Item就会被Engine传递到ItemPipeline,被定义的ItemPipeline组件会顺次被调用,完成一连串的处理过程,比如数据清洗、存储等。  ItemPipeline的主要功能如下:清洗HTML数据。验证爬取数据,......
  • python+playwright 学习-50 pytest-playwright 多账号操作解决方案
    前言pytest-playwright插件可以让我们快速编写pytest格式的测试用例,它提供了一个内置的page对象,可以直接打开页面操作。但是有时候我们需要2个账号是操作业务流程,比如A账号创建了一个任务,需要用到B账号去操作审批动作等。如果需要2个账号同时登录,可以使用context上下文,它可......
  • ansible-galaxy命令快速创建角色框架
    在Ansible中创建角色,可以考虑使用ansible-galaxy命令快速创建角色框架。ansiblevsansible-galaxyAnsible是科幻小说银河系漫游指南中的一种超光速通讯工具,而Ansible社区的Galaxy就是类似类似dockerhub一样的存在,很多可以复用的角色(role),都在一个被称为AnsibleGalaxy的网站进......
  • GO框架 - gin简介
    Gin是一个用Go(Golang)编写的web框架。它是一个类似于martini但拥有更好性能的API框架,由于httprouter,速度提高了近40倍。如果你是性能和高效的追求者,你会爱上Gin.快速:基于Radix树的路由,小内存占用。没有反射。可预测的API性能。支持中间件:传入的HTTP请......
  • GO框架 - beego简介
    bee工具是一个为了协助快速开发beego项目而创建的项目,通过bee您可以很容易的进行beego项目的创建、热编译、开发、测试、和部署。简单化:RESTful支持、MVC模型,可以使用bee工具快速地开发应用,包括监控代码修改进行热编译、自动化测试代码以及自动化打包部署。智能化:支......
  • GO框架 - iris简介
    专注于高性能简单流畅的API高扩展性强大的路由和中间件生态系统使用iris独特的表达主义路径解释器构建RESTfulAPI动态路径参数化或通配符路由与静态路由不冲突使用重定向选项从URL中删除尾部斜杠使用虚拟主机和子域名变得容易分组API和静态或甚至动态子域名net/http......