首页 > 编程语言 >学习python自动化——pytest单元测试框架

学习python自动化——pytest单元测试框架

时间:2024-02-26 22:45:13浏览次数:19  
标签:python 单元测试 fixture 用例 pytest print class def

一、什么是pytest

单元测试框架,unittest(python自带的),pytest(第三方库)。

用于编写测试用例、收集用例、执行用例、生成测试结果文件(html、xml)

1.1、安装pytest

pip install pytest

1.2、导入

import pytest

二、步骤

  2.1、TestCase(测试用例)

    2.1.1、创建测试类
      1)类名要以Test开头

class TestData:

    2.1.2、测试用例函数
      1)可以直接用函数、类的形式
      2)函数名必须是test_开头
      3)执行顺序,按照从上到下的代码顺序执行

def test_data():        #测试函数
print("test_data")

class TestData:
def test_hello(self):    #测试函数
print("test_hello")

    2.1.3、前置后置(fixture)

      前置:环境准备、数据准备
      后置:清理工作、数据清理

    pytest的fixture有2种实现方式:

      2.1.3.1、xunit-style,跟unittest框架的机制非常相似,即setup/teardown系列

        1、测试函数/方法级别:每一个测试函数都会执行的前置和后置。

          1)测试类内部的测试方法:

            前置函数名称:setup_method

            后置函数名称:teardown_method

          2)模块下的测试函数:

            前置函数名称:setup_function

            后置函数名称:teardown_function

        2、测试类级别:一个测试类只执行一次前置和后置。

          前置函数名称:setup_class

          后置函数名称:teardown_class

          注意:用@classmethod装饰

        3、测试模块级别:一个测试模块只执行一次前置和后置。

          前置函数名称:setup_module

          后置函数名称:teardown_module

from selenium import webdriver
from time import sleep
from random import randint

def setup_module():
print("==== 模块级的 setup 操作 ====")

def teardown_module():
print("==== 模块级的 teardown 操作 ====")

def test_random():
assert randint(1, 5) == 3

class TestWeb:

@classmethod
def setup_class(cls):
print("==== 测试类级的 setup 操作 ====")

@classmethod
def teardown_class(cls):
print("==== 测试类级的 teardown 操作 ====")

def setup_method(self):
print("==== 测试用例级的 setup 操作 ====")
self.driver = webdriver.Chrome()

def teardown_method(self):
print("==== 测试用例级的 teardown 操作 ====")
self.driver.quit()

def test_search(self):
self.driver.get("https://www.baidu.com/")
self.driver.find_element_by_id("kw").send_keys("柠檬班")
self.driver.find_element_by_id("su").click()
sleep(1)

      2.1.3.2、fixture机制,通过@pytest.fixture装饰器来定义fixture

         1、fixture定义

          1)fixture通过函数实现

          2)使用@pytest.fixture进行装饰

          3)前置和后置都放在同一个函数当中,通过yeild关键字区分前置和后置,yeild前面的为前置,yeild后面的为后置

import pytest

@pytest.fixture
def init():
print("用例执行之前,执行的代码") # 前置代码
yield
print("用例执行之后,执行的代码") # 后置代码

@pytest.fixture
def init2():
print("用例执行之前,执行的代码") # 只有用例执行之前的前置准备代码

@pytest.fixture
def init3():
yield
print("用例执行之后,执行的代码") # 只有用例执行之后的后置清理代码

          4)fixture有4个作用域:测试会话(session)、测试模块(module)、测试类(class)、测试用例(function)

           设置fixture的作用域,通过@pytest.fixture(scope=作用域)来设置。默认情况下,scope=function

import pytest

# 没有设置scope,默认为测试函数级别。即调用此fixture的测试类/模块/函数下,每个测试函数都会执行一次这个fixture
@pytest.fixture
def init():
print("用例执行之前,执行的代码") # 前置代码
yield
print("用例执行之后,执行的代码") # 后置代码

# 设置scope为class。调用此fixture的测试类下,只执行一次这个fixture.
@pytest.fixture(scope="class")
def init2():
print("用例执行之前,执行的代码") # 只有用例执行之前的前置准备代码

# 设置scope为session。autouse表示自动使用。
# 那么在pytest收集用例后,开始执行用例之前会自动化执行这个fixture当中的前置代码,
# 当所有用例执行完成之后,自动化执行这个fixture的后置代码。
@pytest.fixture(scope="session",autouse=True)
def init3():
yield
print("用例执行之后,执行的代码") # 只有用例执行之后的后置清理代

          5)fixture的返回值设置:yeild 返回值

            如果前置准备工作当中,有变量要传递给测试用例去使用的话,那么就需要返回这个变量,可以有多个返回值,返回值是个元组。

            yeild 返回值,返回值2,返回值3    

yield mysql_obj,True,123

        2、fixture调用

           2.1、自动调用:定义fixture有个参数:autouse,默认autouse=False

              自动调用时,所有的测试函数都会调用一次,所以只有session作用域时才适用。

import pytest

@pytest.fixture(autouse=True) #自动调用
def init():
print("===我是前置准备工作===")
yield
print("***我是后置清理工作***")

@pytest.fixture(scope="class")
def init_class():
print("===我是测试类 前置准备工作===")
yield
print("***我是测试类 后置清理工作***")

def test_hello():
print("hello pytest!!")

class Test_demo:
def test_bey(self):
print("bey pytest!!")

           2.2、主动调用:测试函数/测试类上加上:@pytest.mark.usefixtures("fixture的函数名称"),可以调用多个。

             当调用两个同级别的fixture函数时,按就近原则调用

            1)无需接收fixture返回值

import pytest
from random import randint

#测试类级别
@pytest.fixture(scope="class")
def init_class():
print("===我是 测试类 前置准备工作===")
mysql_obj = "fixture要返回出去的数据库对象"
yield mysql_obj,True,123 # 返回一个变量/对象
print("***我是 测试类 后置清理工作***")

# 测试函数级别
@pytest.fixture()
def init():
print("===我是前置准备工作===")
yield
print("***我是后置清理工作***")

# 测试函数级别
@pytest.fixture()
def init2():
print("===我是前置准备工作2===")
yield
print("***我是后置清理工作2***")

@pytest.mark.usefixtures("init") #去执行名为init的fixture函数
@pytest.mark.usefixtures("init2") #当调用两个同级别的fixture函数时,就近原则,先调用init2,再调用init
def test_hello():
print("hello pytest!!")

def test_demo(): #无前置后置
print("hello world")

@pytest.mark.usefixtures("init_class") #执行名为init_class测试类级别的前置后置
@pytest.mark.usefixtures("init") #当调用两个不同级别的fixture函数时,先调用init_class,再每个函数调用init
class TestDemo:

def test_random(self):
assert randint(3, 3) == 3

def test_abc(self):
assert True

@pytest.mark.usefixtures("init2") #当类内部函数有调用时,就近原则,先调用init2,再调用init
def test_bey(self):
print("bey pytest!!")

             2)要接收fixture返回值:fixture的函数名作为用例的参数,相当于fixture函数名 = fixture调用的返回值

              当fixture函数名作为测试用例参数时,在执行用例时,会自动寻找该函数的fixture,并执行。

              ps:pytest当中的测试用例,如果有参数,分为2种:

                1、fixture的名字

def test_random(self,init_class)
  pass

                2、参数化要传的参数

@pytest.mark.parametrize("case",datas)
def test_read_datas(case):
pass


import pytest
from random import randint

# 测试类级别
@pytest.fixture(scope="class")
def init_class():
print("===我是 测试类 前置准备工作===")
mysql_obj = "fixture要返回出去的数据库对象"
yield mysql_obj,True,123 # 返回一个变量/对象
print("***我是 测试类 后置清理工作***")

#@pytest.mark.usefixtures("init_class") # 当fixture函数名作为测试用例参数时,在执行用例时,会自动寻找该函数名并执行,所以这个可以不写
class TestDemo2:

def test_random(self,init_class): # fixture的名字作为用例的参数,相当于fixture名字 = fixture调用的返回值
mysql_obj, bool_obj, int_obj = init_class
print("从fixture当中接收的变量为:{}".format(init_class))
assert randint(1, 5) == 3

def test_abc(self):
assert True

      3、conftest.py共享机制

        3.1、共享实现

        1)在项目根目录下,创建一个conftest.py文件。

        2)文件名必须是conftest.py,大小写敏感,不可改名字。

        3)conftest.py当中,可以编写多个fixture

        4)在测试用例文件当中,不需要引入conftest.py文件。直接调用fixture的函数名,会自动去conftest.py当中查找的。

         3.2、conftest.py层级作用域

          conftest.py在项目根目录下,则项目下的所有测试用例,均可使用conftest.py中定义的fixture。即项目根目录下的conftest.py,作用域是整个项目。

          根目录下的conftest.py里的fixture,无论项目下的哪个用例,都可以使用。

          子目录day3-login下的conftest.py里的fixture,只有day3-login下的用例可以使用。

          子目录day3-register下的conftest.py里的fixture,只有day3-register下的用例可以使用。

           测试用例在执行时,调用fixture的顺序,按 就近原则 调用。

           测试用例文件中的fixture > 当前目录中的fixture > 上级目录中的fixture > 根目录中的fixture

       4、fixture嵌套

        嵌套使用即:一个fixture,可以做另外一个fixture的参数,自动调用参数的fixture。

@pytest.fixture
def init_class():
print(" %%%% 我是 day3-login包下test_random模块的测试类 前置准备工作 %%%% ")
yield
print(" %%%% 我是 day3-login包下test_random模块的测试类 后置清理工作 %%%% ")

@pytest.fixture
def init_case(init_class):      #init_class作为init_case的参数,当用例调用init_case时,init_case会自动调用init_class
print("测试用例级别 的前置")
print("=================================")
yield
print("测试用例级别 的后置")
print("===============用例 完结==================")

    2.1.4、断言:将预期结果与实际结果进行对比
      assert 表达式(True表示断言为真,False表示断言失败)

assert a==b

  2.2、用例收集:自动收集

    1)pytest自动收集用例规则:在当前文件所在的目录下,收集文件名为test_*.py或*_test.py的测试文件中,以test_开头的测试用例或Test开头的测试类。

    2)pytest.main():以当前文件所在的目录下,收集用例并执行。

pytest.main(["-s","-v"])
    3)用例分类执行
pytest.main(["day1/test_case1.py"])      #只执行day1目录下test_case1.py文件的测试用例

  2.3、TestRunner(用例执行)
    1)需要配置执行器:File>>>Settings>>>Tools>>>Python Integrated Tools>>>Default test runner:pytest
    2)执行顺序:测试文件顺序按ASCII码,文件内部测试用例按代码顺序执行

    3)若py文件执行过一次后,会保留上一次执行的方式,需要清除上一次执行记录。右上角——Edit Configurations——Remove掉该py文件。

   2.4、生成测试报告

    2.4.1、生成JunitXML 格式的测试报告:命令:--junitxml=path
    2.4.2、生成result log格式的测试报告:命令:--resultlog=report\log.txt
    2.4.3、生成Html格式的测试报告
      1)安装pytest-html插件

pip install pytest-html

      2)在pytest.main()的参数当中添加:--html=报告路径

pytest.main(["-s","-v","--html=report.html"])      #生成html格式的测试报告

    2.4.4、生成allure的测试文件
      2.4.4.1、allure是依据测试结果文件,呈现更好看的更多维度的测试报告。
      注意:它不执行用例也不生成测试结果文件。所以,要使用allure的时候,一定要先生成测试结果文件。allure需要依赖测试框架,执行测试用例后,根据测试结果再生成测试报告。

      2.4.4.2、allure的使用

        1、安装allure命令行工具
          1)下载allure安装包。下载地址:https://repo.maven.apache.org/maven2/io/qameta/allure/allure-commandline/

          2)下载完成之后,解压到任意目录
          3)配置环境变量:allure的bin目录。比如D:\allure-2.12.1\bin

          4)在cmd当中,执行allure命令,不报错即allure安装成功。

        2、pytest在执行用例之后,要生成allure可以识别的测试结果文件。
          1)安装插件

pip install allure-pytest

          2)在pytest.main()的参数当中添加:--alluredir=allure生成的文件目录(手动创建一个)

pytest.main(["-s","-v","--alluredir=allure_file"])

pytest.main(["--alluredir=allure_file","--clean-alluredir"])      #每次运行前清除allure_file中的文件,为防止数据重复

        3、使用allure去解析2中的测试结果文件,再呈现最终的测试报告
          1)在cmd当中首先跳转到rootdir下面

          2)在cmd当中执行命令:allure serve 2中的测试结果文件目录

   2.5、参数化(数据驱动)

    1、@pytest.mark.parametrize("参数名",列表数据)

datas={"api":"login","url":"http://api.lemoban.com/futureloan/login",
"api":"register","url":"http://api.lemoban.com/futureloan/register",
"api":"recharge","url":"http://api.lemoban.com/futureloan/recharge",
"api":"withdraw","url":"http://api.lemoban.com/futureloan/withdraw"}

@pytest.mark.parametrize("case",datas)
def test_read_datas(case):
pass

    2、组合参数化:多组参数,依次组合。
      使用多个@pytest.mark.parametrize

#示例:用例有4个:0,2/0,3/1,2/1,3 迪卡尔积
@pytest.mark.parametrize("x", [0, 1])
@pytest.mark.parametrize("y", [2, 3])
def test_foo(x, y):
pass

标签:python,单元测试,fixture,用例,pytest,print,class,def
From: https://www.cnblogs.com/mango-93/p/17959138

相关文章

  • Python的反射
    1、什么是反射反射是指在运行时检查、访问和修改对象的属性和方法。通过反射,可以动态地获取对象的信息并执行相应的操作,而不需要提前知道对象的具体结构。2、使用内置函数和来实现反射操作getattr(object,name[,default]):用于获取对象的属性值。参数 object 是要操作......
  • Python的魔术方法
    一、什么是魔术方法1、魔术方法是一组具有特殊命名和行为的特殊方法,它们允许您自定义类的行为。这些方法使用双下划线(__)作为前缀和后缀,因此也被称为双下划线方法或特殊方法。2、需要掌握每个方法什么时候触发或者执行二、常见的魔术方法1、__init__方法初始化方法,当一个类被......
  • python 发送grafana dashboard 面板内容截图到飞书群
    需求每天定时发送grafanadashboard截图至飞书群,每天获取前一天的算力服务器使用率趋势图环境docker环境#搭建docker环境、配置grafana#catdocker-compose.yamlversion:'3.5'services:grafana:image:grafana/grafana:latestrestart:alwaysports:-......
  • 可编辑模式下安装 python 包
    可编辑模式下安装python包一般情况下,我们使用的是pipinstallpkg来完成包的安装,默认的安装的目标目录在site-packages下,这种情况非常适合我们引用某些成熟包.如果我们想要给github某个项目贡献PR,或者仅仅要魔改一下某个项目,可以使用editable模式来安装.edit......
  • Python flask
    {{变量}}_init_.py这个文件的执行时间package,moduledebug模式、host、portdebug模式:热更新可以在浏览器上面显示错误信息host让别人可以访问自己的电脑url与试图映射urlRESTful风格传参@app.route('/user/<user_id>')#可以指定参数的类......
  • Python pip换源
    Pythonpip更换镜像源在使用Python的过程中,经常会使用到一些非标准内嵌的三方包,这些包给我们日常的开发提供了巨大的便利。但是在使用pip命令去下载这些三方包的时候,Python默认是从官网去下载的,由于它的官网是在国外,这就使得下载的速度灰常的慢;这个时候我们可以使用一些国内......
  • Python|statistics 数学统计函数模块
    方法描述statistics.harmonic_mean()计算给定数据集的调和平均值。是总体内各个变量值倒数1/x的算术平均数的倒数。statistics.mean()计算数据集的平均值statistics.median()计算数据集的中位数statistics.median_grouped()计算给定分组数据集的分组中位数......
  • Python使用shutil模块操作文件/文件夹
    Python的标准库中os模块已经可以操作文件了,但是具有很多局限性(比如不能复制文件),因此Python的另一个标准库shutil对文件/文件夹的移动,复制,删除文件夹,压缩,解压等操作做了增强,更加方便用户进行使用。 1、复制文件/文件夹(shutil.copy(src,dst))1.1复制文件复制文件常......
  • matlab和python语法方面的差异
    同为脚本语言,matlab和python在算法优化过程中都不可避免的会涉及到,甚至有些情况下会涉及到两种语言程序的互相转换,这几天我刚好也做了相关工作,需要将之前用matlab写的一个小算法模块转换成python,以方便和模型集成,过程不难,但因为需要同时涉及两种语言的书写风格,并且这两种语音在某......
  • Python + Apollo 实现配置中心
    --coding:utf-8--importjsonimportosimportthreadingimporttimefromdatetimeimportdatetime,timedeltafromtypingimportOptionalimportrequestsimportLogConfigasloggingclassApolloClient(object):definit(self,app_id,cluster='defaul......