unittest自动化测试框架讲解以及实战

news2024/11/26 23:34:17

为什么要学习unittest

按照测试阶段来划分,可以将测试分为单元测试、集成测试、系统测试和验收测试。单元测试是指对软件中的最小可测试单元在与程序其他部分相隔离的情况下进行检查和验证的工作,通常指函数或者类,一般是开发完成的。

单元测试可以将测试工作前移,及早发现问题,降低解决问题的成本。同时单元测试还可以保证单个模块的功能没有问题,为后续的集成测试提供准备,可以减少合成后的出现的问题。

对于测试来说,单元测试就是执行用例。为了更好的管理用例,我们需要学习Python自带的单元测试框架unittest.

unittest框架及原理

unittest是python自带的一套测试框架,学习起来也相对容易,unittest框架最核心的概念有四个:

  • test case:测试用例。unittest中提供了一个基本类TestCase,可以用来创建新的测试用例,一个TestCase的示例就是一个测试用例;unittest中测试用例的方法都是以 test开头的,且执行顺序会按照方法名的ASCII值排序。
  • test fixure:测试夹具。用于测试用例换进的搭建和销毁,即用例测试前环境的大件(SetUp前置条件),测试后环境的恢复(TearDown后置条件)。比如测试前需要登陆获取token等就是测试用例需要的环境,运行完成后执行下一个用例前需要还原环境,以免影响下一条用例的测试结果。
  • test suit:测试套件。用来把需要一起执行的测试用例几种放到一块执行,相当于一个篮子。我们一般使用 TestLoader来加载测试用例到测试套件中。
  • test runner:测试运行。用来执行测试用例的,并返回测试用例的执行结果。可以结合图形或者文本接口,把返回的测试结果更形象的展示出来,如 HTMLTestRunner.

unittest断言

断言是测试用例的中很重要的一部分内容,可以用来检查操作是否正确。比如说登入处理,成功后的页面一定有类似于用户名称之类的元素,这个时候我们就可以使用断言判断预期结果与实际是否一致,如果吻合,就可以认为测试用例通过。

在Python基础中,有一个 assert断言方法,基本使用格式为 assert 表达式,基本信息。在unittest框架中,也提供了一个自带的断言方式,如果断言失败即不通过就会抛出一个 AssertionError断言错误;成功则标识通过。

以下的断言方法都有一个 msg=None参数(表中只列出了第一个,其实都有),默认返回 None。但是如果指定msg参数的值,则将该信息作为失败的错误信息返回。

方法检查
assertEqual(a, b ,msg=None)a == b
assertNotEqual(a, b)a != b
assertTrue(x)bool(x) is True
assertFalse(x)bool(x) is False
assertIs(x, b)a is b
assertIsNot(a, b)a is not b
assertIsNone(x)x is None
assertIsNotNone(x)x is not None
assertIn(a, b)a in b
assertNotIn(a, b)a not in b
assertIsInstance(a, b)isinstance(a, b)
assertNotIsInstance(a, b)not isinstance(a, b)

TestCase测试用例

编写测试用例前,我们需要创建一个类继承unittest里面的TestCase类,之后我们才能真正的使用unittest框架去编写测试用例.

步骤如下:

  • 导入unittest模块
  • 创建一个测试类,继承unittest.TestCase
  • 定义测试方法,方法名必须以test_开头
  • 调用unittest.main()方法来运行测试用例。unittest.main()方法会搜索该模块下所有以test开头的测试用例和方法,并自动执行。

代码示例

# 注册功能代码

# users列表存储成功注册的用户
users = [{'username': 'testing', 'password': '123456'}]  

def register(username, password1, password2):
  
  if not all([username, password1, password2]):
    return {'code': 0, 'msg': '所有参数不能为空.'}
  
  # 注册
  for user in users:
    if username == user['username']:
      return {'code': 0, 'msg': '用户名已存在!'}
  
  else:
    if password1 != password2:
      return {'code': 0, 'msg': '两次密码输入不一致!'}
    else:
      if 6 <= len(username) <= 18 and 6 <= len(password1) <= 18:
        # 追加到users列表
        users.append({'username': username, 'password': password2})
        return {'code': 0, 'msg': '注册成功.'}
      else:
        return {'code': 0, 'msg': '用户名和密码的长度必须在6~18位之间.'}
  
  


import unittest
from demo import register # 导入被测试代码

class RegisterTest(unittest.TestCase):
    '''注册接口测试类'''
  
    def test_register_success(self):
        '''注册成功'''
        data = ('palien', 'palien', 'palien') # 测试数据
        result = register(*data) # 测试结果
        expected = {'code': 0, 'msg': '注册成功.'} # 预期结果
        self.assertEqual(result, expected) # 断言测试结果与预期结果一致
        # pass
  
    def test_username_exist(self):
        '''注册失败-用户名已存在'''
        data = ('testing', '123456', '123456')
        result = register(*data)
        expected = {'code': 0, 'msg': '用户名已存在!'}
        self.assertEqual(result, expected)
  
    def test_username_isnull(self):
        '''注册失败-用户名为空'''
        data = ('', 'palien', 'palien')
        result = register(*data)
        expected = {'code': 0, 'msg': '所有参数不能为空.'}
        self.assertEqual(result, expected)
        # pass
  
    def test_username_lt18(self):
        '''注册失败-用户名长度大于18位'''
        data = ('palienpalienpalienpalien', 'palien', 'palien')
        result = register(*data)
        expected = {'code': 0, 'msg': '用户名和密码的长度必须在6~18位之间.'}
        self.assertEqual(result, expected)
        # pass
  
    def test_password1_not_password2(self):
        '''注册失败-两次输入密码不一致'''
        data = ('palien', 'palien1', 'palien2')
        result = register(*data)
        expected = {'code': 0, 'msg': '两次密码输入不一致!'}
        self.assertEqual(result, expected)
        # pass
  
# 如果要直接运行这个测试类,需要使用unittest中的main函数来执行测试用例
if __name__ == '__main__':
    unittest.main()

# Output
Windows PowerShell
版权所有 (C) Microsoft Corporation。保留所有权利。

尝试新的跨平台 PowerShell https://aka.ms/pscore6

PS D:\d_02_study\01_git> cd d:/d_02_study/01_git/papers/system/02automation
PS D:\d_02_study\01_git\papers\system\02automation> & C:/Users/TDH/AppData/Local/Programs/Python/Python310-32/python.exe d:/d_02_study/01_git/papers/system/02automation/demo.py
.....
----------------------------------------------------------------------
Ran 5 tests in 0.001s

OK
PS D:\d_02_study\01_git\papers\system\02automation> 

TestFixture测试夹具

unittest的测试夹具有两种使用方式,一种是以测试用例的方法为维度的:setUp()和 tearDown();另一种是以测试类为维度的:setUpClass()和 tearDownClass()

代码示例:

# users列表存储成功注册的用户
users = [{'username': 'testing', 'password': '123456'}]  

def register(username, password1, password2):
  
  if not all([username, password1, password2]):
    return {'code': 0, 'msg': '所有参数不能为空.'}
  
  # 注册
  for user in users:
    if username == user['username']:
      return {'code': 0, 'msg': '用户名已存在!'}
  
  else:
    if password1 != password2:
      return {'code': 0, 'msg': '两次密码输入不一致!'}
    else:
      if 6 <= len(username) <= 18 and 6 <= len(password1) <= 18:
        # 追加到users列表
        users.append({'username': username, 'password': password2})
        return {'code': 0, 'msg': '注册成功.'}
      else:
        return {'code': 0, 'msg': '用户名和密码的长度必须在6~18位之间.'}
  
  


import unittest
from demo import register # 导入被测试代码

class RegisterTest(unittest.TestCase):
    '''注册接口测试类'''
  
    @classmethod # 指明这是个类方法,以类为维度去执行的
    def setUpClass(cls) -> None:
          '''整个测试用例类中的用例执行之前,会先执行此方法'''
          print('-----setup---class-----')
  
    @classmethod
    def tearDownClass(cls) -> None:
          '''整个测试用例类中的用例执行完成后,会执行此方法'''
          print('-----teardown---class-----')
  
    def setUp(self):
        '''每条测试用例执行前都会执行'''
        print('用例{}开始执行...'.format(self))
  
    def tearDown(self):
        '''每条测试用例执行结束后都会执行'''
        print('用例{}执行结束...'.format(self))
  
    def test_register_success(self):
        '''注册成功'''
        data = ('palien', 'palien', 'palien') # 测试数据
        result = register(*data) # 测试结果
        expected = {'code': 0, 'msg': '注册成功.'} # 预期结果
        self.assertEqual(result, expected) # 断言测试结果与预期结果一致
        # pass
  
    def test_username_exist(self):
        '''注册失败-用户名已存在'''
        data = ('testing', '123456', '123456')
        result = register(*data)
        expected = {'code': 0, 'msg': '用户名已存在!'}
        self.assertEqual(result, expected)
  
    def test_username_isnull(self):
        '''注册失败-用户名为空'''
        data = ('', 'palien', 'palien')
        result = register(*data)
        expected = {'code': 0, 'msg': '所有参数不能为空.'}
        self.assertEqual(result, expected)
        # pass
  
    def test_username_lt18(self):
        '''注册失败-用户名长度大于18位'''
        data = ('palienpalienpalienpalien', 'palien', 'palien')
        result = register(*data)
        expected = {'code': 0, 'msg': '用户名和密码的长度必须在6~18位之间.'}
        self.assertEqual(result, expected)
        # pass
  
    def test_password1_not_password2(self):
        '''注册失败-两次输入密码不一致'''
        data = ('palien', 'palien1', 'palien2')
        result = register(*data)
        expected = {'code': 0, 'msg': '两次密码输入不一致!'}
        self.assertEqual(result, expected)
        # pass
  
# 如果要直接运行这个测试类,需要使用unittest中的main函数来执行测试用例
if __name__ == '__main__':
    unittest.main()


### Output
PS D:\d_02_study\01_git> cd d:/d_02_study/01_git/papers/system/02automation
PS D:\d_02_study\01_git\papers\system\02automation> & C:/Users/TDH/AppData/Local/Programs/Python/Python310-32/python.exe d:/d_02_study/01_git/papers/system/02automation/demo.py
-----setup---class-----
用例test_password1_not_password2 (__main__.RegisterTest)开始执行...   
用例test_password1_not_password2 (__main__.RegisterTest)执行结束...   
.用例test_register_success (__main__.RegisterTest)开始执行...
用例test_register_success (__main__.RegisterTest)执行结束...
.用例test_username_exist (__main__.RegisterTest)开始执行...
用例test_username_exist (__main__.RegisterTest)执行结束...
.用例test_username_isnull (__main__.RegisterTest)开始执行...
用例test_username_isnull (__main__.RegisterTest)执行结束...
.用例test_username_lt18 (__main__.RegisterTest)开始执行...
用例test_username_lt18 (__main__.RegisterTest)执行结束...
.-----teardown---class-----

----------------------------------------------------------------------
Ran 5 tests in 0.004s

OK
PS D:\d_02_study\01_git\papers\system\02automation> 

TestSuit测试套件

unittest.TestSuit()类用来表示一个测试用例集,把需要执行的用例类或模块集合在一起。

常用的方法:

  • unittest.TestSuit()
    • addTest():添加单个测试用例方法
    • addTest([...]):添加多个测试用例方法,方法名存在一个列表
  • unittest.TestLoader()
    • loadTestsFromTestCase(测试类名):添加一个测试类
    • loadTestsFromMdule(模块名):添加一个模块
    • discover(测试用例所在的目录):指定目录去加载,会自动寻找这个目录下所有符合命名规则的测试用例

代码示例:

'''
    以下三个文件必须在同一文件夹下:
    demo.py
    test_demo.py
    run_test.py
'''

import os
import unittest
import test_demo

# 第一步,创建一个测试套件
suit = unittest.TestSuite()

# 第二步,将测试用例加载到测试套件中

# # 方式一,添加单条测试用例
# case = test_demo.RegisterTest('test_register_success')
# '''
# 创建一个用例对象。
# 注意:通过用例类去创建测试用例对象的时候,需要传入用例的方法名(字符串类型)
# 这里不是像调用普通类中的方法那样通过类名.方法名调用,可以理解为unittest框架的特殊之处
# '''
# suit.addTest(case) # 添加用例到测试套件中

# # 方式二:添加多条用例
# case1 = test_demo.RegisterTest('test_username_exist')
# case2 = test_demo.RegisterTest('test_username_isnull')
# suit.addTest([case1, case2]) # 添加用例到测试套件中。注意这里使用的是suit.addTest()方法而不是suit.addTests()方法

# # 方式三:添加一个测试用例集
# loader = unittest.TestLoader() # 创建一个加载对象
# suit.addTest(loader.loadFromTestCase(test_demo.RegisterTest)) # 通过加载对象从测试类中加载用例到测试套件中

# '''
#     通产我们使用方式4、5比较多,可以根据实际情况来运用。
#     其中方式5还可以自定义匹配规则,默认是会寻找目录下的test*.py文件,即所有以test开头命名的py文件。
# '''
# # 方式四:添加一个模块(其实就是一个后缀名为.py文件,这里就是test_demo.py文件)
# loader = unittest.TestLoader() # 创建一个加载对象
# suit.addTest(loader.loadTestsFromModule(test_demo))  # 通过加载对象从模块中加载测试用例到测试套件中

# 方式五:指定测试用例的所在目录路径,进行加载
loader = unittest.TestLoader() # 创建一个加载对象
case_path = os.path.dirname(os.path.abspath(__file__)) # 文件路径
# print('用例所在的目录路径为:', case_path)
# suit.addTest(loader.discover(case_path))  # 通过加载对象从用例所在目录加载测试用例到测试套件
suit.addTest(loader.discover(start_dir=case_path, pattern='test_demo*.py')) # 两个参数:路径和匹配规则

TestRunner执行用例

testRunner用来执行用例,并且可以生成相应的测试报告。测试报告有两种形式:一种是 text文本;一种是 html格式

html格式是 HTMLTestRunner插件辅助生成的,是Python标准库的unittest框架的一个拓展,可以生成一个清晰直观的html测试报告。使用的前提就是需要下载 HTMLTestRunner.py,下载完成后放在python安装目录下的scripts目录下即可。

text文本相对于html来说过于简陋,与输出控制台没有什么区别,也几乎不适用。

代码示例:

# demo.py,与test_demo.py和run_test.py在同一目录下

# 导入模块
import unittest
import os
import test_demo
from HTMLTestReportCN import HTMLTestRunner

# 用例文件所在目录
base_path = os.path.dirname(os.path.abspath(__file__))
# report_path = base_path + 'report.html'

# 打开报告文件


# 创建测试套件
suit = unittest.TestSuite()

# 通过模块加载测试用例
loader = unittest.TestLoader()
suit.addTest(loader.discover(start_dir=base_path, pattern='test_demo*.py'))

# 创建测试运行程序启动器
runner = HTMLTestRunner(
    stream=open('report.html', 'w', encoding='utf-8'),   # 打开一个报告文件,并将句柄传给stream
    tester='palien',                    # 报告中显示的测试人员  
    description='注册接口测试报告',      # 报告中显示的描述信息
    title='自动化测试报告'               # 测试报告标题
)

# 使用启动器去执行测试套件里面的测试用例
runner.run(suit)

相关参数说明:

  • stream:指定输出方式
  • tester:报告中要显示的测试人员的名字
  • description:报告中要显示的描述信息
  • title:测试报告的标题
  • verbosity:表示测试报告信息的详细程度,一共三个值,默认为2
    • 0(静默模式):只能获得总的测试用例书和总的结果,如:总共100个,失败90
    • 1(默认模式):类似静默模式,只是在在每个成功的用例面前有个. 每个失败的用例前面有个F
    • 2(详细模式):测试结果会显示每个测试用例的所有相关信息

运行完毕,在项目目录下面会生成一个report.html文件,在浏览器中打开,就可以看到测试报告了。

问题记录

在学习的过程中遇到了一些问题,记录一下。

  • HTMLTestRunner下载

经验证,以下两个文件就支持生成上面截图的报告。

  • 报错 TypeError: a bytes-like object is required, not 'str'解决

这是打开文件的方式不对造成的,附上问题解决博客:https://blog.csdn.net/Teresa_lqs/article/details/126250505?spm=1001.2101.3001.6661.1&utm_medium=distribute.pc_relevant_t0.none-task-blog-2~default~CTRLIST~Rate-1-126250505-blog-116235034.pc_relevant_default&depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2~default~CTRLIST~Rate-1-126250505-blog-116235034.pc_relevant_default&utm_relevant_index=1

  • 中文报告乱码问题

问题如图:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/513395.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

软件架构:软件架构设计的三个维度

架构设计是一个非常大的话题&#xff0c;不管写几篇文章&#xff0c;接触到的始终只是冰山一角&#xff0c;更多的是实践中去体会。这篇文章主要介绍面向对象OO、面向方面AOP和面向服务SOA这三个要素在架构设计中的位置与作用。   架构设计有三个维度&#xff0c;或者说是我们…

文案改写神器软件-文案改编神器

文案改写神器软件 文案改写神器软件通常致力于通过人工智能技术将一篇已有文案进行改写和改编&#xff0c;以达到复用或优化的目的。以下是文案改写神器软件通常可以做的事情&#xff1a; 改写原文&#xff1a;文案改写神器可以通过自定义规则、语法分析和文本相似性匹配等功能…

设计模式之【组合模式】,树形结构的完美解决方案

文章目录 一、什么是组合模式1、组合模式三大角色2、组合模式应用场景3、组合模式注意事项和细节 二、透明组合模式1、学院院系案例2、透明组合模式总结 三、安全组合模式1、linux目录系统案例2、安全组合模式总结 四、源码中使用的组合模式1、HashMap2、ArrayList3、MyBatis 一…

跨平台应用开发进阶(六十一):uni-app 跨平台技术开发框架可行性调研

文章目录 一、流程类二、研发类(uni-app框架)三、心得分享(研发踩坑&uni-app踩坑)四、拓展阅读 一、流程类 IOS和安卓企业开发者账户申请流程(申请渠道、需要提供的相关证明、审核时间等)。 答&#xff1a;uni-app使用HBuliderX作为开发IDE,支持邮箱、密码方式注册&#x…

95、Image Restoration with Mean-Reverting Stochastic Differential Equations

简介 主页&#xff1a;https://github.com/Algolzw/image-restoration-sde 扩散模型终于在去噪、超分辨率等应用了。 这是一种基于随机微分方程的通用图像恢复方法&#xff0c;关键结构包括均值还原SDE&#xff0c;该SDE将高质量图像转换为具有固定高斯噪声的平均状态的降级…

怎么压缩png图片的大小?4个简单高效工具分享

怎么压缩png图片的大小&#xff1f;大家都知道jpg和png是目前电脑上最主流的两大图片文件格式&#xff0c;jpg图片的体积比较小&#xff0c;因为它属于有损压缩的图片格式&#xff0c;而png图片的体积相对就要大很多了&#xff0c;因为png属于无损压缩的图片格式。大家也同样知…

Redission实现分布式锁之源码解析

Redission实现分布式锁之源码解析 1、Redission实现分布式锁之源码解析1.1 分布式锁-redission功能介绍1.2 分布式锁-Redission快速入门1.3 分布式锁-redission可重入锁原理1.4 分布式锁-redission锁重试和WatchDog机制1.5 分布式锁-redission锁的MutiLock原理 1、Redission实现…

5G+工业互联网观察——应用篇

5G与工业互联网的结合是5G应用的重要领域&#xff0c;前一篇《5G工业互联网观察——政策篇》我们对5G工业互联网的相关政策进行了整理和分析&#xff0c;本篇继续从应用的角度整理目前的典型场景和重点行业&#xff0c;并进行简单的分析。 文 | 无界 全文4500字&#xff0c;预计…

原创 | 一文读懂蒙特卡洛算法

作者&#xff1a;陈之炎本文约2000字&#xff0c;建议阅读10分钟 本文介绍了蒙特卡洛算法。 蒙特卡洛算法&#xff08;Monte Carlo algorithm&#xff09;是一种基于随机采样的计算方法&#xff0c;其基本思想是通过生成随机样本&#xff0c;利用统计学原理来估计数学问题的解。…

MySQL实战之主从数据同步机制

主从同步的重要性&#xff1a; 解决数据可靠性的问题需要用到主从同步&#xff1b;解决 MySQL 服务高可用要用到主从同步&#xff1b;应对高并发的时候&#xff0c;还是要用到主从同步。 一、MySQL 主从同步流程 当客户端提交一个事务到 MySQL 的集群&#xff0c;直到客户端收…

《JavaEE初阶》Servlet

《JavaEE初阶》Servlet 文章目录 《JavaEE初阶》Servlet编写一个Servlet的helloworld1. 认识Maven并创建maven项目:2. 引入依赖:3.创建目录:4. 编写代码:5. 打包6. 部署7.验证 优化打包部署操作.常见的错误: ServletAPI:利用ajax构造请求.使用第三方工具postman构造请求HttpSer…

KDXL-A工频输电线路参数测试仪

一、简介 由我公司开发、研制的专门用于输电线路工频参数测量的高精度仪器&#xff0c;对于输电线路的一系列工频参数可进行精密的测量。 KDXL-A输电线路参数测试仪具有体积小、重量轻、测量准确度高、稳定性好、操作简便易学等优点,可取代以往利用多表法测量线路参数的方法&am…

springboot-热部署

什么是热部署 事先我创建一个springboot项目&#xff0c;引入web依赖。 当我冷启动的时候&#xff0c;日志如下&#xff1a; D:\tools\jdk-17.0.3\bin\java.exe -XX:TieredStopAtLevel1 -noverify -Dspring.output.ansi.enabledalways -Dcom.sun.management.jmxremote -Dspr…

【神经网络】tensorflow -- 期中测试试题

题目一&#xff1a;&#xff08;20分&#xff09; 请使用Matplotlib中的折线图工具&#xff0c;绘制正弦和余弦函数图像&#xff0c;其中x的取值范围是&#xff0c;效果如图1所示。 要求&#xff1a; (1)正弦图像是蓝色曲线&#xff0c;余弦图像是红色曲线&#xff0c;线条宽度…

洛谷B2097 最长平台

最长平台 题目描述 对于一个数组&#xff0c;其连续的相同段叫做一个平台&#xff0c;例如&#xff0c;在 1 1 1&#xff0c; 2 2 2&#xff0c; 2 2 2&#xff0c; 3 3 3&#xff0c; 3 3 3&#xff0c; 3 3 3&#xff0c; 4 4 4&#xff0c; 5 5 5&#xff0c; 5 5 5&…

加密解密软件VMProtect入门使用教程(四):准备项目

VMProtect是新一代软件保护实用程序。VMProtect支持德尔菲、Borland C Builder、Visual C/C、Visual Basic&#xff08;本机&#xff09;、Virtual Pascal和XCode编译器。 同时&#xff0c;VMProtect有一个内置的反汇编程序&#xff0c;可以与Windows和Mac OS X可执行文件一起…

【2023 年第三届长三角高校数学建模竞赛】B 题 长三角新能源汽车发展与双碳关系研究 新能源汽车销售相关数据160M+下载

【2023 年第三届长三角高校数学建模竞赛】B 题 长三角新能源汽车发展与双碳关系研究 新能源汽车销售相关数据160M下载 1 题目 《节能与新能源汽车技术路线图 2.0》提出至 2035 年&#xff0c;新能源汽车市场占比超过 50%&#xff0c;燃料电池汽车保有量达到 100 万辆&#xff…

想做外贸却没有头绪?来看看这篇文章

海关总署公布最新数据&#xff1a;今年前4个月&#xff0c;我国外贸进出口总值13.32万亿元&#xff0c;同比增长5.8%&#xff0c;其中出口7.67万亿元&#xff0c;同比增长10.6%&#xff1b;进口5.65万亿元&#xff0c;同比增长0.02%。月度调查显示&#xff0c;出口订单增加的企…

图解LeetCode——238. 除自身以外数组的乘积

一、题目 给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请不要使用除法&#xff0c;且在 O(n…

SoringBoot——pom文件:starter

先来看一看&#xff1a; 这次我们来介绍SpringBoot的pom文件的另一个好玩的地方&#xff1a;starter。 starter的中文含义是启动器&#xff0c;所以有时候我们在Maven仓库找依赖的时候&#xff0c;如果开启了自动翻译就会经常会看见一个奇怪的词叫做某某弹簧启动器&#xff0…