[嵌入式系统-72]:RT-Thread-组件:单元测试框架utest

目录

utest 测试框架

​编辑

测试用例定义

测试单元定义

utest 应用框图

2. utest API

assert 宏

测试单元函数运行宏

测试用例导出宏

测试用例 LOG 输出接口

3. 配置使能

4. 应用范式

5. 测试用例运行要求

6. 运行测试用例

测试结果分析

7. 测试用例运行流程

8. 注意事项


utest 测试框架

utest(unit test)是 RT-Thread 开发的单元测试框架。设计 utest 的初衷是方便 RT-Thread 开发者使用统一的框架接口编写测试程序,实现单元测试、覆盖测试以及集成测试的目的。

测试用例定义

测试用例(testcase,简称 tc)是为实现特定测试目标而执行的单个测试,是包括测试输入、执行条件、测试过程和预期结果的规范,是一个有明确的结束条件明确的测试结果的有限循环。

utest(unit test)测试框架定义用户编写的测试程序为测试用例,一个测试用例仅包含一个 testcase 函数(类似 main 函数),可包含多个测试单元函数。

具体地通过 utest 测试框架提供的 API 完成的针对某一功能的测试代码就是一个测试用例。

测试单元定义

测试单元(test unit)是被测功能细分后的测试点,每个测试点可以任务是被测功能的最小可测单位。当然,不同的分类方式会细分出不同的测试单元。

utest 应用框图

utest 应用框图

如上图所示,测试用例基于测试框架 utest 测试框架提供的服务接口进行程序设计,支持将多个测试用例编译到一起进行测试

另外从图中可以看到,一个测试用例对应唯一的 testcase 函数,在 testcase 中包含多个测试单元(test unit)。

在RT Thread中使用utest进行单元测试的优点主要体现在以下几个方面:

  1. 提高代码质量:单元测试可以帮助开发人员确保每个模块或代码单元都按照预期工作,从而提高代码的整体质量。通过utest,开发人员可以在代码集成到整个系统之前,就发现并修复潜在的问题。
  2. 早期发现错误:utest允许在开发早期就进行错误检测,这意味着问题可以在其影响范围扩大之前就被发现。这有助于减少修复错误的成本,并提高开发效率。
  3. 简化调试过程:由于单元测试关注的是代码的最小可测单元,因此当测试失败时,开发人员可以更容易地定位问题所在。与集成测试或系统测试相比,单元测试的调试过程通常更为简单和直接。
  4. 促进模块化设计:通过编写单元测试,开发人员需要更仔细地考虑代码的结构和设计。这有助于促进模块化设计,使得代码更易于理解、维护和扩展。
  5. 增强代码可维护性:一旦为代码编写了单元测试,那么当未来对代码进行修改或重构时,就可以通过运行这些测试来验证代码是否仍然按预期工作。这有助于确保代码的可维护性,并减少因修改而引入新错误的风险。
  6. 持续集成和自动化测试:utest可以与持续集成(CI)工具(如Jenkins)结合使用,实现自动化测试。这意味着每次代码更改时,都可以自动运行测试,从而确保代码更改不会引入新的问题。这有助于保持代码库的健康和稳定。
  7. 跨平台兼容性测试:在RT Thread这样的嵌入式系统中,跨平台兼容性是一个重要的问题。通过utest,开发人员可以在不同的硬件和操作系统上运行测试,以确保代码的跨平台兼容性。

总之,使用utest进行单元测试是RT Thread开发中的一个重要实践,它可以帮助开发人员提高代码质量、早期发现错误、简化调试过程、促进模块化设计、增强代码可维护性、实现持续集成和自动化测试以及进行跨平台兼容性测试。

在RT Thread中进行单元测试,使用utest的好处主要体现在以下几个方面:

  1. 结构化和组织化:utest提供了一个统一的框架和接口,使得测试代码更加结构化和组织化。这有助于开发人员更好地管理、维护和扩展测试代码。
  2. 简化测试过程:utest测试框架提供了丰富的API和工具,使得编写和运行测试用例变得更加简单和高效。开发人员可以更加专注于测试逻辑本身,而无需过多关注测试环境的搭建和测试数据的准备。
  3. 提高测试效率:通过utest,开发人员可以编写可复用的测试代码,避免重复编写相似的测试逻辑。此外,utest还支持并发测试,可以同时运行多个测试用例,进一步提高测试效率
  4. 测试结果的可视化:utest通常与测试结果报告工具集成,可以将测试结果以图表、报告等形式展示,使得测试结果更加直观和易于理解。这有助于开发人员快速定位和解决问题。
  5. 便于持续集成和自动化测试:utest可以与持续集成(CI)工具(如Jenkins)结合使用,实现自动化测试。这意味着每次代码更改时,都可以自动运行测试,从而确保代码更改不会引入新的问题。这有助于保持代码库的健康和稳定。

至于为什么不直接写测试代码,原因有以下几点:

  1. 可维护性和可扩展性:直接编写测试代码可能会导致测试代码与业务代码紧密耦合,难以维护和扩展。而使用utest这样的测试框架,可以将测试代码与业务代码分离,使得测试代码更加独立和可维护。
  2. 测试质量:utest测试框架提供了丰富的测试功能和工具,可以确保测试代码的准确性和完整性。直接编写测试代码可能会遗漏一些重要的测试场景或条件,导致测试结果不准确。
  3. 测试效率:使用utest可以提高测试效率。通过编写可复用的测试代码和并发测试,可以缩短测试时间并提高测试覆盖率。而直接编写测试代码可能会浪费大量的时间和精力在重复编写相似的测试逻辑上。

因此,使用utest进行单元测试可以带来诸多好处,包括提高测试效率、确保测试质量、简化测试过程等。这些好处使得utest成为RT Thread中进行单元测试的重要工具之一。

2. utest API

为了能够实现格式统一的测试用例代码,测试框架 utest 为测试用例编写提供了一套通用的 API 接口。

assert 宏

注意:
这里的 assert 仅记录通过和失败的数量,不会产生断言并终止程序运行。其功能不等同于 RT_ASSERT。复制错误复制成功
assert 宏说明
uassert_true(value)value 为 true 则测试通过,否则测试失败
uassert_false(value)value 为 false 则测试通过,否则测试失败
uassert_null(value)value 为 null 则测试通过,否则测试失败
uassert_not_null(value)value 为非 null 值则测试通过,否则测试失败
uassert_int_equal(a, b)a 和 b 值相等则测试通过,否则测试失败
uassert_int_not_equal(a, b)a 和 b 值不相等则测试通过,否则测试失败
uassert_str_equal(a, b)字符串 a 和字符串 b 相同则测试通过,否则测试失败
uassert_str_not_equal(a, b)字符串 a 和字符串 b 不相同则测试通过,否则测试失败
uassert_in_range(value, min, max)value 在 min 和 max 的范围内则测试通过,否则测试失败
uassert_not_in_range(value, min, max)value 不在 min 和 max 的范围内则测试通过,否则测试失败

测试单元函数运行宏

UTEST_UNIT_RUN(test_unit_func)复制错误复制成功

测试用例中,使用 UTEST_UNIT_RUN 宏执行指定的测试单元函数 test_unit_func

测试单元(test unit)必须使用 UTEST_UNIT_RUN 宏执行。

测试用例导出宏

UTEST_TC_EXPORT(testcase, name, init, cleanup, timeout)复制错误复制成功
参数描述
testcase测试用例主承载函数(规定使用名为 static void testcase(void) 的函数
name测试用例名称(唯一性)。规定使用测试用例相对 testcases 目录的相对路径以 . 进行连接的命名格式
init测试用例启动前的初始化函数
cleanup测试用例结束后的清理函数
timeout测试用例预计需要的测试时间(单位是秒)

测试用例命名要求:

测试用例需要按照规定的格式命名。规定使用当前测试用例相对 testcases 目录的相对路径以 . 进行连接的命名格式,名字中包含当前测试用例文件的文件名(除去后缀名的文件名)。

测试用例命名示例:

假设在测试用例 testcases 目录下,有 testcases\components\filesystem\dfs\dfs_api_tc.c 测试用例文件,那么该 dfs_api_tc.c 中的测试用例的名称命名为 components.filesystem.dfs.dfs_api_tc

测试用例 LOG 输出接口

utest 测试框架依赖 ulog 日志模块进行日志输出,并且 utest 测试框架中已经日志输出级别。因此只要在测试用例里加入 #include "utest.h" 即可使用 ulog 日志模块的所有级别接口(LOG_D/LOG_I/LOG_E)。

另外,utest 测试框架增加了额外的日志控制接口,如下:

#define UTEST_LOG_ALL    (1u)
#define UTEST_LOG_ASSERT (2u)void utest_log_lv_set(rt_uint8_t lv);复制错误复制成功

用户可以在测试用例中使用 utest_log_lv_set 接口控制日志输出级别。UTEST_LOG_ALL 配置输出所有日志,UTEST_LOG_ASSERT 配置仅输出 uassert 失败后的日志。

3. 配置使能

使用 utest 测试框架需要在 ENV 工具中使用 menuconfig 进行如下配置:

RT-Thread Kernel  --->Kernel Device Object  --->(256) the buffer size for console log printf /* utest 日志需要的最小 buffer */
RT-Thread Components  --->Utilities  --->  -*- Enable utest (RT-Thread test framework) /* 使能 utest 测试框架 */(4096) The utest thread stack size          /* 设置 utest 线程堆栈(-thread 模式需要) */(20)   The utest thread priority            /* 设置 utest 线程优先级(-thread 模式需要) */复制错误复制成功

4. 应用范式

前面介绍了 utest 测试框架和相关 API,这里介绍基本的测试用例代码结构

测试用例文件必须的代码块如下所示:

/** Copyright (c) 2006-2019, RT-Thread Development Team** SPDX-License-Identifier: Apache-2.0** Change Logs:* Date           Author       Notes* 2019-01-16     MurphyZhao   the first version*/#include <rtthread.h>
#include "utest.h"static void test_xxx(void)
{uassert_true(1);
}static void test_xxx(void) 
{ 
    uassert_true(yyy());   //测试某个函数运行的结果是否正确
}static rt_err_t utest_tc_init(void) //运行测试用例前的初始化
{return RT_EOK;
}static rt_err_t utest_tc_cleanup(void) //运行测试例后的清除操作
{return RT_EOK;
}static void testcase(void)    //一个测试用例,可以包含多个测试单元
{UTEST_UNIT_RUN(test_xxx); //测试单元,可以有多个测试单元
}
UTEST_TC_EXPORT(testcase, "components.utilities.utest.sample.sample_tc", utest_tc_init, utest_tc_cleanup, 10);
复制错误复制成功

备注:

测试用例的名字,并不是测试用例的源代码的文件名称,而是通过UTEST_TC_EXPORT制定的名称!!!

一个基本的测试用例必须包含以下内容:

  • 文件注释头(Copyright)

    测试用例文件必须包含文件注释头,包含 Copyright、时间、作者、描述信息。

  • utest_tc_init(void)

    测试运行前的初始化函数,一般用来初始化测试需要的环境

  • utest_tc_cleanup(void)

    测试结束后的清理函数,用来清理测试过程中申请的资源(如内存,线程,信号量等)。

  • testcase(void)

    测试主体函数,一个测试用例实现仅能包含一个 testcase 函数(类似 main 函数)。通常该函数里只用来运行测试单元执行函数 UTEST_UNIT_RUN 。一个测试用例函数可以通过多个UTEST_UNIT_RUN 运行多个测试单元。

    一个 testcase 中可以包含多个测试单元,每个测试单元由 UTEST_UNIT_RUN 执行。

  • UTEST_UNIT_RUN

    测试单元执行函数。运行一次测试单元对应的函数。

  • test_xxx(void)

    每个功能单元的测试实现。用户根据需求确定函数名和函数实现。

  • uassert_true

    用于判断测试结果的断言宏(该断言宏并不会终止程序运行)。测试用例必须使用 uassert_xxx 宏来判断测试结果,否则测试框架不知道测试是否通过。

    所有的 uassert_xxx 宏都通过后,整个测试用例才算测试通过。

  • UTEST_TC_EXPORT

    将测试用例 testcase 函数导出到测试框架中,这样就可以通过测试用例框架执行该测试用来了!!!

UTEST_UNIT_RUN本身并不会直接启动一个线程来运行程序测试单元。UTEST_UNIT_RUN(或类似的宏/函数)是用于在UTest测试框架中定义一个测试单元(test unit)的。这个宏/函数的作用是将你的测试代码封装成一个可执行的测试单元,但具体的执行方式(例如是否作为线程运行)则取决于UTest测试框架的实现以及你的测试策略。

在UTest中,测试单元通常被定义为一个包含测试代码的函数。当你调用UTEST_UNIT_RUN(或类似的宏/函数)来运行测试时,UTest测试框架会按照你定义的测试单元来执行测试代码。这些测试代码可以是在主线程中顺序执行,也可以是在多个线程中并发执行,具体取决于你的测试策略和实现方式。

如果你在RT-Thread这样的实时操作系统环境中使用UTest,并且想要将测试单元作为线程来运行,那么你可能需要自己在代码中创建线程,并在线程函数中调用UTEST_UNIT_RUN来运行测试单元。这样做的好处是可以实现测试的并发执行,提高测试效率。但是,你也需要注意线程同步和通信的问题,以确保测试的正确性和稳定性。

5. 测试用例运行要求

测试框架 utest 将所有的测试用例导出到了 UtestTcTab 代码段,在 IAR 和 MDK 编译器中不需要在链接脚本中定义 UtestTcTab 段,但是在 GCC 编译时,需要在链接脚本中显式地设置 UtestTcTab 段。

因此,测试用例要在 GCC 下能够编译运行,必须要先在 GCC 的链接脚本中定义 UtestTcTab 代码段。

在 GCC 链接脚本的 .text 中,增加 UtestTcTab 段的定义,格式如下所示:

/* section information for utest */
. = ALIGN(4);
__rt_utest_tc_tab_start = .;
KEEP(*(UtestTcTab))
__rt_utest_tc_tab_end = .;复制错误复制成功

6. 运行测试用例

测试框架提供了以下命令,便于用户在 RT-Thread MSH 命令行中运行测试用例,命令如下:

utest_list 命令

列出当前系统支持的测试用例,包括测试用例的名称和测试需要的时间。该命令无参数。

utest_run 命令

测试用例执行命令,该命令格式如下:

utest_run [-thread or -help] [testcase name] [loop num]复制错误复制成功
utest_run 命令参数描述
-thread使用线程模式运行测试框架,否则,在msh线程中运行测试用例
-help打印帮助信息
testcase name指定测试用例名称。支持使用通配符*,支持指定测试用例名称前部分字节
loop num指定测试用例循环测试次数,可以多长执行某个测试用例

UTEST_UNIT_RUN本身并不会直接启动一个线程来运行程序测试单元。UTEST_UNIT_RUN(或类似的宏/函数)是用于在UTest测试框架中定义一个测试单元(test unit)的。这个宏/函数的作用是将你的测试代码封装成一个可执行的测试单元,但具体的执行方式(例如是否作为线程运行)则取决于UTest测试框架的实现以及你的测试策略。

在UTest中,测试单元通常被定义为一个包含测试代码的函数。当你调用UTEST_UNIT_RUN(或类似的宏/函数)来运行测试时,UTest测试框架会按照你定义的测试单元来执行测试代码。这些测试代码可以是在主线程中顺序执行,也可以是在多个线程中并发执行,具体取决于你的测试策略和实现方式。

如果你在RT-Thread这样的实时操作系统环境中使用UTest,并且想要将测试单元作为线程来运行,那么你可能需要自己在代码中创建线程,并在线程函数中调用UTEST_UNIT_RUN来运行测试单元。这样做的好处是可以实现测试的并发执行,提高测试效率。但是,你也需要注意线程同步和通信的问题,以确保测试的正确性和稳定性。

测试命令使用示例:

msh />utest_list
[14875] I/utest: Commands list :
[14879] I/utest: [testcase name]:components.filesystem.dfs.dfs_api_tc; [run timeout]:30
[14889] I/utest: [testcase name]:components.filesystem.posix.posix_api_tc; [run timeout]:30
[14899] I/utest: [testcase name]:packages.iot.netutils.iperf.iperf_tc; [run timeout]:30备注:当前,在utest测试框架中,注册了3个测试用例,可以借助utest框架,用utest_run直接运行着3个测试用例。msh />msh />utest_run components.filesystem.dfs.dfs_api_tc
[83706] I/utest: [==========] [ utest    ] started
[83712] I/utest: [----------] [ testcase ] (components.filesystem.dfs.dfs_api_tc) started
[83721] I/testcase: in testcase func...
[84615] D/utest: [    OK    ] [ unit     ] (test_mkfs:26) is passed
[84624] D/testcase: dfs mount rst: 0
[84628] D/utest: [    OK    ] [ unit     ] (test_dfs_mount:35) is passed
[84639] D/utest: [    OK    ] [ unit     ] (test_dfs_open:40) is passed
[84762] D/utest: [    OK    ] [ unit     ] (test_dfs_write:74) is passed
[84770] D/utest: [    OK    ] [ unit     ] (test_dfs_read:113) is passed
[85116] D/utest: [    OK    ] [ unit     ] (test_dfs_close:118) is passed
[85123] I/utest: [  PASSED  ] [ result   ] testcase (components.filesystem.dfs.dfs_api_tc)
[85133] I/utest: [----------] [ testcase ] (components.filesystem.dfs.dfs_api_tc) finished
[85143] I/utest: [==========] [ utest    ] finished备注:
测试框架会按照自己的格式和顺序,以及是否启动独立线程的设置,运行测试用例,并把测试结果按照特定的格式显示出来。msh />复制错误复制成功

测试结果分析

utest 日志展示

如上图所示,测试用例运行的日志从左到右被分成了四列,分别是 log 日志头信息、结果栏、属性栏、详细信息展示栏。

日志中使用 result 属性标识该测试用例测试结果(PASSED or FAILED)。

7. 测试用例运行流程

测试用例运行流程

从上面的流程图中可以得到以下内容:

  • utest 测试框架是顺序执行 testcase 测试用例函数中的所有测试单元(函数调用)
  • 上一个 UTEST_UNIT_RUN 宏执出现了 assert,后面的所有 UTEST_UNIT_RUN 会跳过执行

8. 注意事项

Note

注:- 使用 GCC 编译前,确定链接脚本是否增加了 UtestTcTab 段 - 编译前确保 RT-Thread Kernel -> Kernel Device Object -> (256) the buffer size for console log printf 至少为 256 字节 - 测试用例中创建的资源(线程、信号量、定时器、内存等)需要在测试结束前释放 - 一个测试用例实现仅能使用 UTEST_TC_EXPORT 导出一个测试主体函数(testcase 函数) - 为编写的测试用例程序编写 README.md 文档,指导用户配置测试环境

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

14.集合、常见的数据结构

集合 概念 Java中的集合就是一个容器&#xff0c;用来存放Java对象。 集合在存放对象的时候&#xff0c;不同的容器&#xff0c;存放的方法实现是不一样的&#xff0c; Java中将这些不同实现的容器&#xff0c;往上抽取就形成了Java的集合体系。 Java集合中的根接口&#x…

MySQL数据库---增删查改汇总

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文着重整理MySQL数据库增删查改功能 主要是整理语法 争取做到要用什么语法 可以快速找到复制粘贴 增添语法 INSERT into tab(列名,列名,列名) values(内容,内容,内容); 插入一行数据 INSERT into tab(列名,…

邦注科技 模具保护器 CCD电子眼 专业工业视觉检测设备

模具保护器是一种用于保护模具的设备&#xff0c;可以在塑料压铸和冲床等加工过程中起到保护模具的作用。以下是关于模具保护器在保护塑料压铸和冲床模具方面的应用&#xff1a; 塑料压铸模具保护器&#xff1a; 防止碰撞&#xff1a;在塑料压铸过程中&#xff0c;模具可能会…

Android Studio报错:Constant expression required

【出现的问题】&#xff1a; 使用JDK17以上版本&#xff0c;switch语句报错&#xff1a;Constant expression required 【解决方法】&#xff1a; 在gradle.properties配置文件下添加代码&#xff1a; android.nonFinalResIdsfalse 如图&#xff1a; 接着再点击右上角的Sync…

数仓开发:DIM层数据处理

一、了解DIM层 这个就是数仓开发的分层架构 我们现在是在DIM层&#xff0c;从ods表中数据进行加工处理&#xff0c;导入到dwd层&#xff0c;但是记住我们依然是在DIM层&#xff0c;而非是上面的ODS和DWD层。 二、处理维度表数据 ①先确认hive的配置 -- 开启动态分区方案 -- …

Python深度学习基于Tensorflow(6)神经网络基础

文章目录 使用Tensorflow解决XOR问题激活函数正向传播和反向传播解决过拟合权重正则化Dropout正则化批量正则化 BatchNormal权重初始化残差连接 选择优化算法传统梯度更新算法动量算法NAG算法AdaGrad算法RMSProp算法Adam算法如何选择优化算法 使用tf.keras构建神经网络使用Sequ…

活动图与状态图:UML中流程图的精细化表达——专业解析系统动态性与状态变迁

流程图是一种通用的图形表示法&#xff0c;用以展示步骤、决策和循环等流程控制结构。它通常用于描述算法、程序执行流程或业务过程&#xff0c;关注于任务的顺序执行。流程图强调顺序、分支和循环&#xff0c;适用于详细说明具体的处理步骤&#xff0c;图形符号相对基础和通用…

Logfire-Python可观测平台快速上手

我最近在优化之前的FastAPI接入可观测性平台&#xff0c;正好分享一下Pydantic团队推出的logfire&#xff0c;希望对大家的Python工程化有帮助。 Github: https://github.com/pydantic/logfire 官网链接: Pydantic Logfire Documentation Logfire是Pydantic团队推出的可观测…

数据结构复习指导之二叉树的遍历

文章目录 二叉树 考纲内容 复习提示 1.二叉树的遍历 1.1先序遍历&#xff08;PreOrder&#xff09; 1.2中序遍历&#xff08;InOrder&#xff09; 1.3后序遍历&#xff08;PostOrder&#xff09; 1.4递归算法和非递归算法的转换 1.5层次遍历 1.6由遍历序列构造二叉树…

3.yolov5训练前的图片处理详解(python)

其实&#xff0c;yolov5模型可以分为深度网络、数据处理&#xff08;图片处理&#xff09;、损失函数、优化器选择、训练和预测及部分构成&#xff0c;相信大家对训练和预测的代码比较熟悉。前面两章我们根据代码和结构图了解了yolov5的深度网络&#xff0c;接下来看数据处理的…

力扣刷题--数组--第三天

今天再做两道二分查找的题目&#xff0c;关于二分查找的知识可看我前两篇博客。话不多说&#xff0c;直接开干&#xff01; 题目1&#xff1a;69.x 的平方根 题目详情&#xff1a;   给你一个非负整数 x &#xff0c;计算并返回 x 的 算术平方根 。由于返回类型是整数&#…

首席数据官CCRC-CDO如何构筑企业数据合规的坚固防线

在当今信息化快速发展的时代&#xff0c;数据已经成为企业最宝贵的资产之一。然而&#xff0c;随着数据规模的迅速增长&#xff0c;数据合规问题也日益凸显。首席数据官&#xff08;CDO&#xff09;作为企业中负责数据战略和管理的核心人物&#xff0c;构筑企业数据合规的坚固防…

吴恩达2022机器学习专项课程C2(高级学习算法)W1(神经网络):2.5 更复杂的神经网络

目录 示例填写第三层的层数1.问题2.答案 公式&#xff1a;计算任意层的激活值激活函数 示例 层数有4层&#xff0c;不包括输入层。 填写第三层的层数 1.问题 你能把第二个神经元的上标和下标填写出来吗&#xff1f; 2.答案 根据公式g(wxb)&#xff0c;这里的x对应的是上…

Unity EventSystem入门

概述 相信在学习Unity中&#xff0c;一定有被UI事件困扰的时候把&#xff0c;当添加UICanvas的时候&#xff0c;Unity会为我们自动添加EventSystem&#xff0c;这个是为什么呢&#xff0c;Unity的UI事件是如何处理的呢&#xff0c;在使用各个UI组件的时候&#xff0c;一定有不…

Springboot+Vue项目-基于Java+MySQL的个人云盘管理系统(附源码+演示视频+LW)

大家好&#xff01;我是程序猿老A&#xff0c;感谢您阅读本文&#xff0c;欢迎一键三连哦。 &#x1f49e;当前专栏&#xff1a;Java毕业设计 精彩专栏推荐&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb;&#x1f447;&#x1f3fb; &#x1f380; Python毕业设计 &…

电脑文件x3daudio1 7.dll怎么修复?快速修复x3daudio1 7.dll的方法

你试过电脑文件x3daudio1 7.dll丢失么&#xff1f;如果你有遇到这种情况&#xff0c;那么可能你的某些程序就会启动不了&#xff0c;毕竟这个文件是用来处理音频功能的&#xff0c;那么我们要怎么去修复&#xff1f;下面我们一起来详细的了解电脑文件x3daudio1 7.dll这个文件吧…

顺序栈的操作

归纳编程学习的感悟&#xff0c; 记录奋斗路上的点滴&#xff0c; 希望能帮到一样刻苦的你&#xff01; 如有不足欢迎指正&#xff01; 共同学习交流&#xff01; &#x1f30e;欢迎各位→点赞 &#x1f44d; 收藏⭐ 留言​&#x1f4dd;既然选择了远方&#xff0c;当不负青春…

DNS、ICMP、NAT以及代理服务器

目录 1. DNS 1.1. DNS 背景 1.2. 域名简介 1.3. 域名解析过程 2. ICMP 2.1. ICMP 的功能 2.2. ICMP 的报文格式 2.3. ping 命令 2.4. traceroute 命令 3. NAT和代理服务器 3.1. NAT 技术 3.2. NAT IP转换过程 3.3. NAT 技术的缺陷 3.4. 代理服务器 3.4.1. 正向…

1.使用uniapp搭建微信小程序项目并引入前端组件资源

文章目录 1. 项目配置1.1. 新建vue3项目1.2. 关联云空间1.3. 运行到微信开发者工具 2. 前端组件2.1. uniCloud的内置组件和扩展组件2.2. uView3.02.3. 在uniapp项目引入uview3 1. 项目配置 1.1. 新建vue3项目 由于我们要使用vue3而不是vue2&#xff0c;所以要选好版本&#x…

SpringBoot实现统一返回值+全局异常处理

在这里首先感谢的就是程序员老罗&#xff0c;从他的项目里面学到了这些东西。 首先就是去创建一个SpringBoot项目&#xff0c;这里我就不多做赘述了 封装一个统一返回对象 package com.example.demo.vo;public class ResponseVO<T> {private String status;private In…