单元测试 —— JUnit 5 参数化测试

JUnit 5参数化测试
目录
- 设置
- 我们的第一个参数化测试
- 参数来源
- @ValueSource
- @NullSource & @EmptySource
- @MethodSource
- @CsvSource
- @CsvFileSource
- @EnumSource
- @ArgumentsSource
- 参数转换
- 参数聚合
- 奖励
- 总结
如果您正在阅读这篇文章,说明您已经熟悉了JUnit。让我为您概括一下JUnit——在软件开发中,我们开发人员编写的代码可能是设计一个人的个人资料这样简单,也可能是在银行系统中进行付款这样复杂。在开发这些功能时,我们倾向于编写单元测试。顾名思义,单元测试的主要目的是确保代码的小、单独部分按预期功能工作。

如果单元测试执行失败,这意味着该功能无法按预期工作。编写单元测试的一种工具是JUnit。这些单元测试程序很小,但是非常强大,并且可以快速执行。现在我们已经了解了JUnit,接下来让我们聚焦于JUnit 5中的参数化测试。
参数化测试可以解决在为任何新/旧功能开发测试框架时遇到的最常见问题。
- 编写针对每个可能输入的测试用例变得更加容易。
- 单个测试用例可以接受多个输入来测试源代码,有助于减少代码重复。
- 通过使用多个输入运行单个测试用例,我们可以确信已涵盖所有可能的场景,并维护更好的代码覆盖率。
开发团队通过利用方法和类来创建可重用且松散耦合的源代码。传递给代码的参数会影响其功能。例如,计算器类中的sum方法可以处理整数和浮点数值。JUnit 5引入了执行参数化测试的能力,可以使用单个测试用例测试源代码,该测试用例可以接受不同的输入。这样可以更有效地进行测试,因为在旧版本的JUnit中,必须为每种输入类型创建单独的测试用例,从而导致大量的代码重复。
示例代码
本文附带有在 GitHub上(
code-examples/core-java/junit5-parameterized-tests at master · thombergs/code-examples · GitHub) 的一个可工作的示例代码。
设置
就像疯狂泰坦灭霸喜欢访问力量一样,您可以使用以下Maven依赖项来访问JUnit5中参数化测试的力量:
<dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-params</artifactId><version>5.9.2</version><scope>test</scope>
</dependency>
让我们来写些代码,好吗?
我们的第一个参数化测试
现在,我想向您介绍一个新的注解 @ParameterizedTest。顾名思义,它告诉JUnit引擎使用不同的输入值运行此测试。
import static org.junit.jupiter.api.Assertions.assertEquals;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;public class ValueSourceTest {@ParameterizedTest@ValueSource(ints = { 2, 4 })void checkEvenNumber(int number) {assertEquals(0, number % 2,"Supplied number is not an even number");}
}
在上面的示例中,注解@ValueSource为 checkEvenNumber() 方法提供了多个输入。假设我们使用JUnit4编写相同的代码,即使它们的结果(断言)完全相同,我们也必须编写2个测试用例来覆盖输入2和4。
当我们执行 ValueSourceTest 时,我们会看到什么:
ValueSourceTest
|_ checkEvenNumber
|_ [1] 2
|_ [2] 4
这意味着 checkEvenNumber() 方法将使用2个输入值执行。
在下一节中,让我们学习一下JUnit5框架提供的各种参数来源。
现在我也找了很多测试的朋友,做了一个分享技术的交流群,共享了很多我们收集的技术文档和视频教程。
如果你不想再体验自学时找不到资源,没人解答问题,坚持几天便放弃的感受
可以加入我们一起交流。而且还有很多在自动化,性能,安全,测试开发等等方面有一定建树的技术大牛
分享他们的经验,还会分享很多直播讲座和技术沙龙
可以免费学习!划重点!开源的!!!
qq群号:110685036

参数来源
JUnit5提供了许多参数来源注释。下面的章节将简要概述其中一些注释并提供示例。
@ValueSource
@ValueSource是一个简单的参数源,可以接受单个字面值数组。@ValueSource支持的字面值类型有short、byte、int、long、float、double、char、boolean、String和Class。
@ParameterizedTest
@ValueSource(strings = { "a1", "b2" })
void checkAlphanumeric(String word) {assertTrue(StringUtils.isAlphanumeric(word),"Supplied word is not alpha-numeric");
}
@NullSource & @EmptySource
假设我们需要验证用户是否已经提供了所有必填字段(例如在登录函数中需要提供用户名和密码)。我们使用注解来检查提供的字段是否为 null,空字符串或空格。
- 在单元测试中使用 @NullSource 和 @EmptySource 可以帮助我们提供带有 null、空字符串和空格的数据源,并验证源代码的行为。
@ParameterizedTest
@NullSource
void checkNull(String value) {assertEquals(null, value);
}@ParameterizedTest
@EmptySource
void checkEmpty(String value) {assertEquals("", value);
}
- 我们还可以使用 @NullAndEmptySource 注解来组合传递 null 和空输入。
@ParameterizedTest
@NullAndEmptySource
void checkNullAndEmpty(String value) {assertTrue(value == null || value.isEmpty());
}
- 另一个传递 null、空字符串和空格输入值的技巧是结合使用 @NullAndEmptySource 注解,以覆盖所有可能的负面情况。该注解允许我们从一个或多个测试类的工厂方法中加载输入,并生成一个参数流。
@ParameterizedTest
@NullAndEmptySource
@ValueSource(strings = { " ", " " })
void checkNullEmptyAndBlank(String value) {assertTrue(value == null || value.isBlank());
}
@MethodSource
该注解允许我们从一个或多个测试类的工厂方法中加载输入,并生成一个参数流。
- 显式方法源 - 测试将尝试加载提供的方法。
// Note: The test will try to load the supplied method
@ParameterizedTest
@MethodSource("checkExplicitMethodSourceArgs")
void checkExplicitMethodSource(String word) {
assertTrue(StringUtils.isAlphanumeric(word),
"Supplied word is not alpha-numeric");
}static Stream<String> checkExplicitMethodSourceArgs() {
return Stream.of("a1",
"b2");
}
- 隐式方法源 - 测试将搜索与测试类匹配的源方法。
// Note: The test will search for the source method
// that matches the test-case method name
@ParameterizedTest
@MethodSource
void checkImplicitMethodSource(String word) {assertTrue(StringUtils.isAlphanumeric(word),
"Supplied word is not alpha-numeric");
}static Stream<String> checkImplicitMethodSource() {
return Stream.of("a1",
"b2");
}
- 多参数方法源 - 我们必须将输入作为参数流传递。测试将按照索引顺序加载参数。
// Note: The test will automatically map arguments based on the index
@ParameterizedTest
@MethodSource
void checkMultiArgumentsMethodSource(int number, String expected) {assertEquals(StringUtils.equals(expected, "even") ? 0 : 1, number % 2);
}static Stream<Arguments> checkMultiArgumentsMethodSource() {return Stream.of(Arguments.of(2, "even"),Arguments.of(3, "odd"));
}
- 外部方法源 - 测试将尝试加载外部方法。
// Note: The test will try to load the external method
@ParameterizedTest
@MethodSource(
"source.method.ExternalMethodSource#checkExternalMethodSourceArgs")
void checkExternalMethodSource(String word) {assertTrue(StringUtils.isAlphanumeric(word),
"Supplied word is not alpha-numeric");
}
// Note: The test will try to load the external method@ParameterizedTest@MethodSource("source.method.ExternalMethodSource#checkExternalMethodSourceArgs")void checkExternalMethodSource(String word) { assertTrue(StringUtils.isAlphanumeric(word),"Supplied word is not alpha-numeric");}package source.method;
import java.util.stream.Stream;public class ExternalMethodSource {static Stream<String> checkExternalMethodSourceArgs() {return Stream.of("a1","b2");}
}
@CsvSource
该注解允许我们将参数列表作为逗号分隔的值(即 CSV 字符串字面量)传递,每个 CSV 记录都会导致执行一次参数化测试。它还支持使用 useHeadersInDisplayName属性跳过 CSV 标头。
@ParameterizedTest
@CsvSource({ "2, even",
"3, odd"})
void checkCsvSource(int number, String expected) {assertEquals(StringUtils.equals(expected, "even")? 0 : 1, number % 2);
}
@CsvFileSource
该注解允许我们使用类路径或本地文件系统中的逗号分隔值(CSV)文件。与 @CsvSource 类似,每个 CSV 记录都会导致执行一次参数化测试。它还支持各种其他属性 -numLinesToSkip、useHeadersInDisplayName、lineSeparator、delimiterString等。
示例 1: 基本实现
@ParameterizedTest
@CsvFileSource(
files = "src/test/resources/csv-file-source.csv",
numLinesToSkip = 1)
void checkCsvFileSource(int number, String expected) {assertEquals(StringUtils.equals(expected, "even")? 0 : 1, number % 2);
}
src/test/resources/csv-file-source.csv
NUMBER, ODD_EVEN
2, even
3, odd
示例2:使用属性
@ParameterizedTest
@CsvFileSource(files = "src/test/resources/csv-file-source_attributes.csv",delimiterString = "|",lineSeparator = "||",numLinesToSkip = 1)
void checkCsvFileSourceAttributes(int number, String expected) {assertEquals(StringUtils.equals(expected, "even")
? 0 : 1, number % 2);
}
src/test/resources/csv-file-source_attributes.csv
|| NUMBER | ODD_EVEN ||
|| 2 | even ||
|| 3 | odd ||
@EnumSource
该注解提供了一种方便的方法来使用枚举常量作为测试用例参数。支持的属性包括:
- value - 枚举类类型,例如 ChronoUnit.class
package java.time.temporal;public enum ChronoUnit implements TemporalUnit {SECONDS("Seconds", Duration.ofSeconds(1)),MINUTES("Minutes", Duration.ofSeconds(60)),
HOURS("Hours", Duration.ofSeconds(3600)),DAYS("Days", Duration.ofSeconds(86400)),//12 other units
}
ChronoUnit 是一个包含标准日期周期单位的枚举类型。
@ParameterizedTest
@EnumSource(ChronoUnit.class)
void checkEnumSourceValue(ChronoUnit unit) {
assertNotNull(unit);
}
在此示例中,@EnumSource 将传递所有16个 ChronoUnit 枚举值作为参数。
- names - 枚举常量的名称或选择名称的正则表达式,例如 DAYS 或 ^.*DAYS$
@ParameterizedTest
@EnumSource(names = { "DAYS", "HOURS" })
void checkEnumSourceNames(ChronoUnit unit) {assertNotNull(unit);
}
@ArgumentsSource
该注解提供了一个自定义的可重用ArgumentsProvider。ArgumentsProvider的实现必须是外部类或静态嵌套类。
- 外部参数提供程序
public class ArgumentsSourceTest {@ParameterizedTest@ArgumentsSource(ExternalArgumentsProvider.class)void checkExternalArgumentsSource(int number, String expected) {assertEquals(StringUtils.equals(expected, "even")? 0 : 1, number % 2,"Supplied number " + number +" is not an " + expected + " number");}
}public class ExternalArgumentsProvider implements ArgumentsProvider {@Overridepublic Stream<? extends Arguments> provideArguments(ExtensionContext context) throws Exception {return Stream.of(Arguments.of(2, "even"),Arguments.of(3, "odd"));}
}
- 静态嵌套参数提供程序
public class ArgumentsSourceTest {@ParameterizedTest@ArgumentsSource(NestedArgumentsProvider.class)void checkNestedArgumentsSource(int number, String expected) {assertEquals(StringUtils.equals(expected, "even")
? 0 : 1, number % 2,"Supplied number " + number +" is not an " + expected + " number");}static class NestedArgumentsProvider implements ArgumentsProvider {@Overridepublic Stream<? extends Arguments> provideArguments(ExtensionContext context) throws Exception {return Stream.of(Arguments.of(2, "even"),Arguments.of(3, "odd"));}}
}
参数转换
首先,想象一下如果没有参数转换,我们将不得不自己处理参数数据类型的问题。
源方法: Calculator 类
public int sum(int a, int b) {return a + b;
}
测试用例:
@ParameterizedTest
@CsvSource({ "10, 5, 15" })
void calculateSum(String num1, String num2, String expected) {int actual = calculator.sum(Integer.parseInt(num1),Integer.parseInt(num2));assertEquals(Integer.parseInt(expected), actual);
}
如果我们有String参数,而我们正在测试的源方法接受Integers,则在调用源方法之前,我们需要负责进行此转换。
JUnit5 提供了不同的参数转换方式
- 扩展原始类型转换
@ParameterizedTest
@ValueSource(ints = { 2, 4 })
void checkWideningArgumentConversion(long number) {assertEquals(0, number % 2);
}
使用 @ValueSource(ints = { 1, 2, 3 }) 进行参数化测试时,可以声明接受 int、long、float 或 double 类型的参数。
- 隐式转换
@ParameterizedTest
@ValueSource(strings = "DAYS")
void checkImplicitArgumentConversion(ChronoUnit argument) {assertNotNull(argument.name());
}
JUnit5提供了几个内置的隐式类型转换器。转换取决于声明的方法参数类型。例如,用@ValueSource(strings = "DAYS")注释的参数化测试会隐式转换为类型ChronoUnit的参数。
- 回退字符串到对象的转换
@ParameterizedTest
@ValueSource(strings = { "Name1", "Name2" })
void checkImplicitFallbackArgumentConversion(Person person) {assertNotNull(person.getName());
}public class Person {private String name;public Person(String name) {this.name = name;}//Getters & Setters
}
JUnit5提供了一个回退机制,用于自动将字符串转换为给定目标类型,如果目标类型声明了一个适用的工厂方法或工厂构造函数。例如,用@ValueSource(strings = { "Name1", "Name2" })注释的参数化测试可以声明接受一个类型为Person的参数,其中包含一个名为name且类型为string的单个字段。
- 显式转换
@ParameterizedTest
@ValueSource(ints = { 100 })
void checkExplicitArgumentConversion(@ConvertWith(StringSimpleArgumentConverter.class) String argument) {assertEquals("100", argument);
}public class StringSimpleArgumentConverter extends SimpleArgumentConverter {@Overrideprotected Object convert(Object source, Class<?> targetType)throws ArgumentConversionException {return String.valueOf(source);}
}
如果由于某种原因,您不想使用隐式参数转换,则可以使用@ConvertWith注释来定义自己的参数转换器。例如,用@ValueSource(ints = { 100 })注释的参数化测试可以声明接受一个类型为String的参数,使用
StringSimpleArgumentConverter.class将整数转换为字符串类型。
参数聚合
@ArgumentsAccessor
默认情况下,提供给@ParameterizedTest方法的每个参数对应于一个方法参数。因此,当提供大量参数的参数源可以导致大型方法签名时,我们可以使用ArgumentsAccessor而不是声明多个参数。类型转换支持如上面的隐式转换所述。
@ParameterizedTest
@CsvSource({ "John, 20","Harry, 30" })
void checkArgumentsAccessor(ArgumentsAccessor arguments) {Person person = new Person(arguments.getString(0),arguments.getInteger(1));assertTrue(person.getAge() > 19, person.getName() + " is a teenager");
}
自定义聚合器
我们看到ArgumentsAccessor可以直接访问@ParameterizedTest方法的参数。如果我们想在多个测试中声明相同的ArgumentsAccessor怎么办?JUnit5通过提供自定义可重用的聚合器来解决此问题。
- @AggregateWith
@ParameterizedTest
@CsvSource({ "John, 20","Harry, 30" })
void checkArgumentsAggregator(@AggregateWith(PersonArgumentsAggregator.class) Person person) {assertTrue(person.getAge() > 19, person.getName() + " is a teenager");
}public class PersonArgumentsAggregator implements ArgumentsAggregator {@Overridepublic Object aggregateArguments(ArgumentsAccessor arguments,ParameterContext context) throws ArgumentsAggregationException {return new Person(arguments.getString(0),
arguments.getInteger(1));}
}
实现ArgumentsAggregator接口并通过@AggregateWith注释在@ParameterizedTest方法中注册它。当我们执行测试时,它会将聚合结果作为对应测试的参数提供。ArgumentsAggregator的实现可以是外部类或静态嵌套类。
额外福利
由于您已经阅读完文章,我想给您一个额外的福利 - 如果您正在使用像Fluent assertions for java(AssertJ - fluent assertions java library)这样的断言框架,则可以将
java.util.function.Consumer作为参数传递,其中包含断言本身。
@ParameterizedTest
@MethodSource("checkNumberArgs")
void checkNumber(int number, Consumer<Integer> consumer) {consumer.accept(number);
}static Stream<Arguments> checkNumberArgs() { Consumer<Integer> evenConsumer =i -> Assertions.assertThat(i % 2).isZero();Consumer<Integer> oddConsumer =i -> Assertions.assertThat(i % 2).isEqualTo(1);return Stream.of(Arguments.of(2, evenConsumer),Arguments.of(3, oddConsumer));
}
总结
JUnit5的参数化测试功能通过消除重复测试用例的需要,提供多次使用不同输入运行相同测试的能力,实现了高效的测试。这不仅为开发团队节省了时间和精力,而且还增加了测试过程的覆盖范围和有效性。此外,该功能允许对源代码进行更全面的测试,因为可以使用更广泛的输入进行测试,从而增加了识别任何潜在的错误或问题的机会。总体而言,JUnit5的参数化测试是提高代码质量和可靠性的有价值的工具。
最后感谢每一个认真阅读我文章的人,看着粉丝一路的上涨和关注,礼尚往来总是要有的,虽然不是什么很值钱的东西,如果你用得到的话可以直接拿走!

软件测试面试文档
我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。


相关文章:
单元测试 —— JUnit 5 参数化测试
JUnit 5参数化测试 目录 设置我们的第一个参数化测试参数来源 ValueSourceNullSource & EmptySourceMethodSourceCsvSourceCsvFileSourceEnumSourceArgumentsSource参数转换参数聚合奖励总结 如果您正在阅读这篇文章,说明您已经熟悉了JUnit。让我为您概括一下…...
uview组件库的安装
更多的请查看官方文档uView 2.0 - 全面兼容 nvue 的 uni-app 生态框架 - uni-app UI 框架 (uviewui.com) // 如果您的根目录没有package.json文件的话,请先执行如下命令: // npm init -y 安装 npm install uview-ui2.0.36 // 更新 // npm update uvie…...
skywalking入门
参考: https://www.jianshu.com/p/ffa7ddcda4ab 参考: https://developer.aliyun.com/article/1201085 skywalking(APM) 调用链路分析以及应用监控分析工具 Skywalking主要由三大部分组成:agent、collector、webapp-…...
【Java 基础篇】Java多线程实现文件上传详解
文件上传是Web应用程序中常见的功能之一,用户可以通过网页将文件从本地计算机上传到服务器。在处理大文件或多用户并发上传的情况下,为了提高性能和用户体验,常常使用多线程来实现文件上传功能。本文将详细介绍如何使用Java多线程实现文件上传…...
【计算机基础】VS断点调试,边学边思考
📢:如果你也对机器人、人工智能感兴趣,看来我们志同道合✨ 📢:不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 📢:文章若有幸对你有帮助,可点赞 👍…...
BD就业复习第五天
1. 核心组件的优化:hive、spark、flink 针对Hive、Spark和Flink这三个核心组件,以下是它们的优化和一些常见面试题以及详细的回答: 1. Hive 优化 面试问题1:什么是Hive?为什么需要对Hive进行优化? 回答…...
ImportError: urllib3 v2.0 only supports OpenSSL 1.1.1+, currently the ‘ssl‘
报错: ImportError: urllib3 v2.0 only supports OpenSSL 1.1.1, currently the ‘ssl’ module is compiled with OpenSSL 1.1.0h 27 Mar 2018.解决办法:将urllib3的版本降低 pip install urllib31.26.15参考 python包报错ImportError: urllib3 v2.…...
Qt5开发及实例V2.0-第十二章-Qt多线程
Qt5开发及实例V2.0-第十二章-Qt多线程 第12章 Qt 5多线程12.1 多线程及简单实例12.2 多线程控制12.2.1 互斥量12.2.2 信号量12.2.3 线程等待与唤醒 12.3 多线程应用12.3.1 【实例】:服务器编程12.3.2 【实例】:客户端编程 本章相关例程源码下载1.Qt5开发…...
Windows 修改系统默认字体
Windows Registry Editor Version 5.00; 重装机后电脑屏幕及字体调整.reg.lnk ;; 显示器分辨率: 3840*2160 ;; 自定义缩放: 266 ;; 辅助功能 - 文本大小 - 110% ;; 最后 ClearType 文本调谐器; https://www.cnblogs.com/bolang100/p/8548040.html#WINDOWS 10 显示中的仅更改文…...
图像处理软件Photoshop 2024 mac新增功能
Photoshop 2024 mac是一款图像处理软件的最新版本。ps2024提供了丰富的功能和工具,使用户能够对照片、插图、图形等进行精确的编辑和设计。 Photoshop 2024 mac软件特点 快速性能:Photoshop 2024 提供了更快的渲染速度和更高效的处理能力,让用…...
JavaScript之观察者模式
本文作者为 360 奇舞团前端开发工程师 概述 在日常开发中,开发人员经常使用设计模式来解决软件设计中的问题。其中,观察者模式是一种常用的模式,它可以帮助开发人员更好地处理对象之间的通信。在 JavaScript 中,观察者模式的应用非…...
深入了解ln命令:创建硬链接和符号链接的实用指南
文章目录 1. 引言1.1 关于ln命令1.2 ln命令的作用和用途 2. 基本用法2.1 创建硬链接2.2 创建符号链接2.3 区别硬链接和符号链接 3. 操作示例3.1 创建硬链接的示例3.2 创建符号链接的示例3.3 查看链接信息 4. 注意事项和常见问题4.1 文件路径4.2 软链接的相对路径4.3 软链接的更…...
虚拟IP技术
1.说明 虚拟IP(Virtual IP Address,简称VIP)是一个未分配给真实弹性云服务器网卡的IP地址。 弹性云服务器除了拥有私有IP地址外,还可以拥有虚拟IP地址,用户可以通过其中任意一个IP(私有IP/虚拟IP…...
蓝桥杯 题库 简单 每日十题 day5
01 字符计数 字符计数 题目描述 给定一个单词,请计算这个单词中有多少个元音字母,多少个辅音字母。 元音字母包括a,e,i,o,u,共五个,其他均为辅音字母。 输入描述 输入格式: 输入一行࿰…...
【计算机网络】图解路由器(一)
图解路由器(一) 1、什么是路由器?2、什么是路由选择?3、什么是转发?4、路由器设备有哪些类型?5、根据性能分类,路由器有哪些类型?5.1 高端路由器5.2 中端路由器5.3 低端路由器 6、什…...
C语言文件的相关操作
C语言中文件的相关操作 文件的打开 使用文件的打开函数需要引入这个头文件:#include <fcntl.h> open函数 int open(char const *pathname, int flags, mode_t mode) 功能:打开已有的文件或者创建新文件参数 pathname:文件路径名&…...
Java入门级简单定时任务TimerTask
如果要执行一些简单的定时器任务,无须做复杂的控制,也无须保存状态,那么可以考虑使用JDK 入门级的定期器Timer来执行重复任务。 一、原理 JDK中,定时器任务的执行需要两个基本的类: java.util.Timer; java…...
Linux命令行教程:使用head和tail命令快速查看文件的开头和结尾
文章目录 简介A. 什么是head和tail命令B. head和tail命令的作用和用途 head命令A. 命令格式和语法B. 常见选项和参数1. -n:指定显示的行数2. -c:指定显示的字节数3. -v:显示文件名 C. 示例和应用实例1. 显示文件的前几行2. 显示多个文件的前几…...
[CISCN 2019 初赛]Love Math 通过进制转换执行命令
目录 hex2bin bin2hex base_convert 动态函数 第一种解法 通过get获取参数 绕过 第二种解法 读取请求头 getallheaders echo a,b 第三种解法 异或获得更多字符 这道题也是很有意思! 通过规定白名单和黑名单 指定了 函数为数学函数 并且参数也只能是规…...
【Linux】系统编程生产者消费者模型(C++)
目录 【1】生产消费模型 【1.1】为何要使用生产者消费者模型 【1.2】生产者消费者模型优点 【2】基于阻塞队列的生产消费者模型 【2.1】生产消费模型打印模型 【2.2】生产消费模型计算公式模型 【2.3】生产消费模型计算公式加保存任务模型 【2.3】生产消费模型多生产多…...
centos 7 部署awstats 网站访问检测
一、基础环境准备(两种安装方式都要做) bash # 安装必要依赖 yum install -y httpd perl mod_perl perl-Time-HiRes perl-DateTime systemctl enable httpd # 设置 Apache 开机自启 systemctl start httpd # 启动 Apache二、安装 AWStats࿰…...
第25节 Node.js 断言测试
Node.js的assert模块主要用于编写程序的单元测试时使用,通过断言可以提早发现和排查出错误。 稳定性: 5 - 锁定 这个模块可用于应用的单元测试,通过 require(assert) 可以使用这个模块。 assert.fail(actual, expected, message, operator) 使用参数…...
【git】把本地更改提交远程新分支feature_g
创建并切换新分支 git checkout -b feature_g 添加并提交更改 git add . git commit -m “实现图片上传功能” 推送到远程 git push -u origin feature_g...
三体问题详解
从物理学角度,三体问题之所以不稳定,是因为三个天体在万有引力作用下相互作用,形成一个非线性耦合系统。我们可以从牛顿经典力学出发,列出具体的运动方程,并说明为何这个系统本质上是混沌的,无法得到一般解…...
人工智能--安全大模型训练计划:基于Fine-tuning + LLM Agent
安全大模型训练计划:基于Fine-tuning LLM Agent 1. 构建高质量安全数据集 目标:为安全大模型创建高质量、去偏、符合伦理的训练数据集,涵盖安全相关任务(如有害内容检测、隐私保护、道德推理等)。 1.1 数据收集 描…...
Unity中的transform.up
2025年6月8日,周日下午 在Unity中,transform.up是Transform组件的一个属性,表示游戏对象在世界空间中的“上”方向(Y轴正方向),且会随对象旋转动态变化。以下是关键点解析: 基本定义 transfor…...
《Offer来了:Java面试核心知识点精讲》大纲
文章目录 一、《Offer来了:Java面试核心知识点精讲》的典型大纲框架Java基础并发编程JVM原理数据库与缓存分布式架构系统设计二、《Offer来了:Java面试核心知识点精讲(原理篇)》技术文章大纲核心主题:Java基础原理与面试高频考点Java虚拟机(JVM)原理Java并发编程原理Jav…...
qt+vs Generated File下的moc_和ui_文件丢失导致 error LNK2001
qt 5.9.7 vs2013 qt add-in 2.3.2 起因是添加一个新的控件类,直接把源文件拖进VS的项目里,然后VS卡住十秒,然后编译就报一堆 error LNK2001 一看项目的Generated Files下的moc_和ui_文件丢失了一部分,导致编译的时候找不到了。因…...
java 局域网 rtsp 取流 WebSocket 推送到前端显示 低延迟
众所周知 摄像头取流推流显示前端延迟大 传统方法是服务器取摄像头的rtsp流 然后客户端连服务器 中转多了,延迟一定不小。 假设相机没有专网 公网 1相机自带推流 直接推送到云服务器 然后客户端拉去 2相机只有rtsp ,边缘服务器拉流推送到云服务器 …...
Windows开机自动启动中间件
WinSW(Windows Service Wrapper 是一个开源的 Windows 服务包装器,它可以帮助你将应用程序打包成系统服务,并实现开机自启动的功能。 一、下载 WinSW 下载 WinSW-x64.exe v2.12.0 (⬇️ 更多版本下载) 和 sample-minimal.xml 二、配置 WinS…...
