当前位置: 首页 > news >正文

单元测试实战(五)普通类的测试

为鼓励单元测试,特分门别类示例各种组件的测试代码并进行解说,供开发人员参考。

本文中的测试均基于JUnit5。

单元测试实战(一)Controller 的测试

单元测试实战(二)Service 的测试    

单元测试实战(三)JPA 的测试    

单元测试实战(四)MyBatis-Plus 的测试

​​​​​​​单元测试实战(五)普通类的测试

单元测试实战(六)其它

概述

普通类或曰POJO的测试,是最简单的一种情况,大多数情况下只使用JUnit即可。万一有不易实例化的外部依赖,也可以用Mockito的@Mock来模拟。这类测试一般应脱离Spring上下文来进行。

需要的话,在每个测试之前应清理/重置测试数据,一般为方法参数或待测类实例;断言应主要检查待测类的行为是否符合预期。

依赖

大多数普通类测试只依赖JUnit,但作为一般实践,我们通常也带上Spring Boot自己的测试工具集。

<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope>
</dependency>
<dependency><groupId>org.junit.jupiter</groupId><artifactId>junit-jupiter-api</artifactId><scope>test</scope>
</dependency>

示例

以下是一个BigDecimal的包装类,实现了一些BigDecimal的最佳实践;该类是我们的待测试类:

package com.aaa.sdk.utils;import java.math.BigDecimal;
import java.math.RoundingMode;
import java.text.DecimalFormat;
import java.util.Objects;/*** BigDecimal的包装类,封装了以下实践:* <li>不允许null值(使用工厂方法创建实例时会直接报错)。</li>* <li>避免double构造传参造成精度丢失。</li>* <li>封装equals,强制使用compareTo来比较。</li>* <li>封装格式化输出(补零对齐,默认两位)。</li>* <li>封装加减乘除,尤其除法,强制使用BigDecimal的三参方法避免无限小数报错。</li>* <li>直观的判断正数、负数、零的方法。</li>* <br/>** 本类设计为不可变对象,非读方法(加减乘除、取反、四舍五入等)都会产生新对象。** @author ioriogami**/
public class DecimalWrapper implements Comparable<DecimalWrapper> {/*** 默认精度,保留两位。*/public static final int DEFAULT_SCALE = 2;private final BigDecimal decimal;private DecimalWrapper(BigDecimal decimal) {Objects.requireNonNull(decimal);this.decimal = decimal;}// 以下工厂方法/*** 通过一个BigDecimal对象构造DecimalWrapper实例。* @param decimal 本wrapper代表的BigDecimal对象*/public static DecimalWrapper of(BigDecimal decimal) {return new DecimalWrapper(decimal);}/*** 通过一个String实例构造DecimalWrapper实例。* @param s 字符串数值*/public static DecimalWrapper of(String s) {return of(new BigDecimal(s));}/*** 通过一个double实例构造DecimalWrapper实例。* @param d double数值*/public static DecimalWrapper of(double d) {return of(new BigDecimal(String.valueOf(d)));}/*** 通过一个float实例构造。* @param f float数值*/public static DecimalWrapper of(float f) {return of(new BigDecimal(String.valueOf(f)));}// 以下一般接口/*** 获取底层的BigDecimal对象*/public BigDecimal toBigDecimal() {return decimal;}/*** 获取double值。*/public Double toDouble() {return decimal.doubleValue();}@Overridepublic String toString() {return decimal.toPlainString();}@Overridepublic int hashCode() {return decimal.hashCode();}@Overridepublic boolean equals(Object obj) {if (obj instanceof DecimalWrapper) {DecimalWrapper other = (DecimalWrapper) obj;return decimal.compareTo(other.decimal) == 0;}return false;}@Overridepublic int compareTo(DecimalWrapper that) {if (that == null) return 1;return this.decimal.compareTo(that.decimal);}// 以下格式化输出/*** 四舍五入保留两位。* @return 一个新的DecimalWrapper对象*/public DecimalWrapper round() {return round(DEFAULT_SCALE, RoundingMode.HALF_UP);}/*** 四舍五入保留i位。* @param scale 精度,即i,保留几位。* @return 一个新的DecimalWrapper对象*/public DecimalWrapper round(int scale) {return round(scale, RoundingMode.HALF_UP);}/*** m舍n入保留i位。** @param scale 精度,即i,保留几位。* @param mode 舍入策略(m和n)。* @return 一个新的DecimalWrapper对象*/public DecimalWrapper round(int scale, RoundingMode mode) {return of(decimal.setScale(scale, mode));}/*** 获得四舍五入保留两位(强制补0)后的字符串。*/public String format() {return new DecimalFormat("0.00").format(decimal.setScale(DEFAULT_SCALE, RoundingMode.HALF_UP));}/*** 获得四舍五入保留i位(强制补0)后的字符串。* @param scale 精度,即i,保留几位。*/public String format(int scale) {return format(scale, RoundingMode.HALF_UP);}/*** 获得m舍n入保留scale位(强制补0)后的字符串。不会影响本身的值。* @param scale 精度,即i,保留几位。* @param mode 舍入策略(m和n),若为null则默认四舍五入。* @return 格式化后的字符串。*/public String format(int scale, RoundingMode mode) {if (scale <= 0) throw new IllegalArgumentException("精度必须大于0");if (mode == null) mode = RoundingMode.HALF_UP;StringBuilder buff = new StringBuilder("0.");for (int i = 0; i < scale; i++) {buff.append("0");}return new DecimalFormat(buff.toString()).format(decimal.setScale(scale, mode));}// 以下加减乘除、取反/*** 加法。*/public DecimalWrapper add(DecimalWrapper other) {if (other == null) throw new IllegalArgumentException("操作数为null,无法进行加法运算。");return of(decimal.add(other.decimal));}/*** 减法。*/public DecimalWrapper subtract(DecimalWrapper other) {if (other == null) throw new IllegalArgumentException("操作数为null,无法进行减法运算。");return of(decimal.subtract(other.decimal));}/*** 乘法。*/public DecimalWrapper multiply(DecimalWrapper other) {if (other == null) throw new IllegalArgumentException("操作数为null,无法进行乘法运算。");return of(decimal.multiply(other.decimal));}/*** 除法。*/public DecimalWrapper divide(DecimalWrapper other) { // 使用三参除法,避免结果为无限小数时报错。return divide(other, DEFAULT_SCALE, RoundingMode.HALF_UP);}/*** 除法,指定精度和舍入策略。*/public DecimalWrapper divide(DecimalWrapper other, int scale, RoundingMode mode) {if (other == null) throw new IllegalArgumentException("操作数为null,无法进行除法运算。");if (scale <= 0) throw new IllegalArgumentException("精度必须大于0");if (mode == null) mode = RoundingMode.HALF_UP;return of(decimal.divide(other.decimal, scale, mode));}/*** 取反。*/public DecimalWrapper negate() {return of(decimal.negate());}/*** 判断是否零值,不管到底是0.0、0.00还是0.0000..*/public boolean isZero() {return decimal.signum() == 0;}/*** 判断是否正数。*/public boolean isPositive() {return decimal.signum() == 1;}/*** 判断是否正数。*/public boolean isNegative() {return decimal.signum() == -1;}
}

以下是对DecimalWrapper进行测试的测试类:

package com.aaa.sdk.utils;import java.math.BigDecimal;
import java.math.RoundingMode;import org.junit.jupiter.api.Test;import static org.junit.jupiter.api.Assertions.*;class DecimalWrapperTest {@Testvoid testConstructBigDecimal() {DecimalWrapper d = DecimalWrapper.of(new BigDecimal("1.11"));assertEquals("1.11", d.format());}@Testvoid testConstructDouble() {DecimalWrapper d = DecimalWrapper.of(1.11);assertEquals("1.11", d.format());}@Testvoid testConstructString() {DecimalWrapper d = DecimalWrapper.of("1.11");assertEquals("1.11", d.format());}@Testvoid testConstructFloat() {DecimalWrapper d = DecimalWrapper.of(1.1f);assertEquals("1.10", d.format());}@Testvoid testConstructNullParam() {try {DecimalWrapper.of((String) null);fail("should not get here!");} catch (NullPointerException npe) {}try {DecimalWrapper.of((Double) null);fail("Should not get here!");} catch (NullPointerException npe) {}try {DecimalWrapper.of((Float) null);fail("Should not get here!");} catch (NullPointerException npe) {}try {DecimalWrapper.of((BigDecimal) null);fail("Should not get here!");} catch (NullPointerException npe) {}}@Testvoid testComparison() {DecimalWrapper d1 = DecimalWrapper.of(1.1);DecimalWrapper d2 = DecimalWrapper.of(1.2);DecimalWrapper d3 = DecimalWrapper.of(1.0);assertTrue(d1.compareTo(d2) < 0);assertTrue(d2.compareTo(d1) > 0);assertTrue(d3.compareTo(d1) < 0);assertTrue(d3.compareTo(d2) < 0);DecimalWrapper d4 = DecimalWrapper.of("1.00");assertTrue(d3.compareTo(d4) == 0);DecimalWrapper d5 = null;assertTrue(d3.compareTo(d5) > 0);}@Testvoid testToDecimal() {DecimalWrapper d1 = DecimalWrapper.of(1.11);assertEquals(d1.toBigDecimal(), new BigDecimal("1.11"));}@Testvoid testToDouble() {DecimalWrapper d1 = DecimalWrapper.of(1.11);assertEquals(d1.toDouble(), 1.11);}@Testvoid testEquals() {DecimalWrapper d1 = DecimalWrapper.of(1.12345);DecimalWrapper d2 = DecimalWrapper.of(1.12345f);DecimalWrapper d3 = DecimalWrapper.of("1.12345");DecimalWrapper d4 = DecimalWrapper.of(new BigDecimal("1.12345"));assertEquals(d1, d2);assertEquals(d2, d3);assertEquals(d3, d4);}@Testvoid testRoundDefault() {DecimalWrapper d1 = DecimalWrapper.of(1.12385);DecimalWrapper d2 = DecimalWrapper.of(1.12385f);DecimalWrapper d3 = DecimalWrapper.of("1.12385");DecimalWrapper d4 = DecimalWrapper.of(new BigDecimal("1.12385"));assertEquals(d1.round(), DecimalWrapper.of("1.12"));assertEquals(d2.round(), DecimalWrapper.of("1.12"));assertEquals(d3.round(), DecimalWrapper.of("1.12"));assertEquals(d4.round(), DecimalWrapper.of("1.12"));}@Testvoid testRound() {DecimalWrapper d1 = DecimalWrapper.of(1.12385);DecimalWrapper d2 = DecimalWrapper.of(1.12385f);DecimalWrapper d3 = DecimalWrapper.of("1.12385");DecimalWrapper d4 = DecimalWrapper.of(new BigDecimal("1.12385"));assertEquals(d1.round(3), DecimalWrapper.of("1.124"));assertEquals(d2.round(3), DecimalWrapper.of("1.124"));assertEquals(d3.round(3), DecimalWrapper.of("1.124"));assertEquals(d4.round(3), DecimalWrapper.of("1.124"));assertEquals(d4.round(3, RoundingMode.DOWN), DecimalWrapper.of("1.123"));}@Testvoid testFormat() {DecimalWrapper d1 = DecimalWrapper.of(1.12385);assertEquals(d1.format(), "1.12");assertEquals(d1.format(3), "1.124");assertEquals(d1.format(3, RoundingMode.DOWN), "1.123");}@Testvoid testAdd() {DecimalWrapper d1 = DecimalWrapper.of(1.12385);DecimalWrapper d2 = DecimalWrapper.of(1.12385);assertEquals(DecimalWrapper.of("2.24770"), d1.add(d2));DecimalWrapper d3 = DecimalWrapper.of(0);assertEquals(DecimalWrapper.of("1.12385"), d3.add(d2));assertTrue(d3.add(d3).isZero());}@Testvoid testSubtract() {DecimalWrapper d1 = DecimalWrapper.of(2.24770);DecimalWrapper d2 = DecimalWrapper.of(1.12385);assertEquals(DecimalWrapper.of("1.12385"), d1.subtract(d2));DecimalWrapper d3 = DecimalWrapper.of(0); // change to: 0.0assertEquals(DecimalWrapper.of("1.12385"), d2.subtract(d3));assertTrue(d2.subtract(d2).isZero());assertTrue(d3.subtract(d3).isZero());}@Testvoid testMultiply() {DecimalWrapper d1 = DecimalWrapper.of(1.12385);DecimalWrapper d2 = DecimalWrapper.of(1.12385);assertEquals(DecimalWrapper.of("1.2630388225"), d1.multiply(d2));DecimalWrapper d3 = DecimalWrapper.of(0.00);assertTrue(d2.multiply(d3).isZero());DecimalWrapper d4 = DecimalWrapper.of(-1);assertEquals(DecimalWrapper.of("-1.12385"), d1.multiply(d4));}@Testvoid testDivide() {DecimalWrapper d1 = DecimalWrapper.of(10.0);DecimalWrapper d2 = DecimalWrapper.of(3);assertEquals(DecimalWrapper.of(3.33), d1.divide(d2));DecimalWrapper d3 = DecimalWrapper.of(0);assertTrue(d3.multiply(d1).isZero());try {d1.divide(d3);fail("divide by zero, should not get here!");} catch (Exception e){}}@Testvoid testNegate() {DecimalWrapper d1 = DecimalWrapper.of(-1.12385);assertTrue(d1.isNegative());assertFalse(d1.isZero());assertFalse(d1.isPositive());DecimalWrapper d2 = d1.negate();assertTrue(d2.isPositive());assertFalse(d2.isZero());assertFalse(d2.isNegative());assertTrue(d1.add(d2).isZero());}}

测试类说明:

测试类的代码和被测类的代码都比较直观,不需做过多说明。

在该类中,我们为被测类的每个公共方法都创建了测试方法,且只用到了JUnit的@Test和Assertions;如果需要事前准备和事后清理工作,还可以加上@BeforeEach、@AfterEach、@BeforeAll、@AfterAll等方法。

第37行的testConstructNullParam是负面测试,测试当传入null值是不允许的,会抛出NullPointerException。

第101行的testRoundDefault、第113行的testRound,是对同一个方法的不同情况(精度)的测试。

私有方法的测试

私有方法不需要测试。对私有方法的测试,应通过调用它的公有方法的测试来进行。直接测试私有方法往往是一种代码“坏味道”。

虽然但是,有时候确实想给私有方法写一个测试,也不是做不到:

package com.aaa.api.auth.filter;import com.aaa.sdk.utils.Utils;
import org.junit.jupiter.api.Test;import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;import static org.junit.jupiter.api.Assertions.*;
class AuthNFilterTest {@Testvoid testExtractUsernameFromToken() throws InvocationTargetException, IllegalAccessException {String token = "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...";AuthNFilter filter = new AuthNFilter();Method m = Utils.doGetMethod(AuthNFilter.class, "extractUsernameFromToken", String.class);//long start = System.currentTimeMillis();String user = (String) m.invoke(filter, token);//System.out.println("User is " + user + ", used " + (System.currentTimeMillis() - start) + " ms");assertEquals("ioriogami", user);}
}

第15行,我们new了一个待测试对象。

第16行,我们用反射获取了AuthNFilter类的extractUsernameFromToken私有方法(该方法接受一个String类型的参数),然后在第18行对其进行调用。

 如需对构造方法、私有方法、静态方法、final类和方法进行mock,可以使用powermock提供的增强版Mockito:PowerMockito。

总结

普通类的测试以JUnit简单测试为主,一般不需要Spring上下文。

每一个public方法都有至少一个测试;对不同的情况/分支,建议有多个测试;最好也有负面测试。当然,一个完美的测试类应该测试每个方法的正面行为、负面行为、边缘情况;并应尽可能覆盖所有分支。但在有限的时间内,我们应识别最重要的方面进行测试。

单元测试针对单个类,原则上测试类与被测类一对一。当然也可以针对一组紧密相关的类/接口编写单元测试,比如pagewindow是一个实现无界分页的小模块,由几个接口和类组成,它的单元测试就是针对这一组类的。

Mock的原理是采用字节码生成的方式对要mock的类进行sub-class,然后生成这个子类的对象,以此达到对其行为进行订制的目的。显然,这种方式会受到Java继承机制的限制:静态类/方法、final类/方法、构造器、私有方法等都不能继承,因此就难以订制。

Mockito在2.1.0中加入了对final类/方法的支持。见 https://www.cnblogs.com/yuluoxingkong/p/14813558.html。

powermock提供的增强版Mockito:PowerMockito 则对这些方面提供了全面的支持。

相关文章:

单元测试实战(五)普通类的测试

为鼓励单元测试&#xff0c;特分门别类示例各种组件的测试代码并进行解说&#xff0c;供开发人员参考。 本文中的测试均基于JUnit5。 单元测试实战&#xff08;一&#xff09;Controller 的测试 单元测试实战&#xff08;二&#xff09;Service 的测试 单元测试实战&am…...

js 迭代器iterator 和 生成器Generator 10

✌ 文章目录 一、迭代器 iterator二、使用步骤1.引入库2.读入数据 总结 一、迭代器 iterator 迭代器是帮助我们对某个数据结构进行遍历的对象 迭代器&#xff1a;是一个对象&#xff0c;帮助我们对某个数据结构进行遍历 迭代器要符合迭代器协议&#xff0c;必须要有一个特定的n…...

100套Axure RP大数据可视化大屏模板及通用组件库

106套Axure RP大数据可视化大屏模板包括了多种实用美观的可视化组件库及行业模板库&#xff0c;行业模板涵盖&#xff1a;金融、教育、医疗、政府、交通、制造等多个行业提供设计参考。 随着大数据的发展&#xff0c;可视化大屏在各行各业得到越来越广泛的应用。可视化大屏不再…...

【OpenGauss源码学习 —— 执行算子(Append算子)】

执行算子&#xff08;Append算子&#xff09; Append 算子ExecInitAppend 函数exec_append_initialize_next 函数ExecAppend 函数ExecEndAppend 函数ExecReScanAppend 函数 声明&#xff1a;本文的部分内容参考了他人的文章。在编写过程中&#xff0c;我们尊重他人的知识产权和…...

Java(一)(引用类型的参数在传递,方法重载,面向对象编程基础)

基本类型和引用类型的参数在传递的时候有什么不同? 基本类型的值传递:参数传输存储的数据值 引用类型的值传递:参数传输存储的地址值 传递数组名字的时候,传递的是数组的地址,change方法可以通过地址直接访问我们在堆内存中开辟的数组,然后改变数组,数组中的元素发生变化 方…...

Vue第1天:特性概览

文章目录 Vue.js 简介 Vue的特性 如何使用Vue 安装Vue 通过CDN引入 使用npm 创建Vue实例 结语 Vue.js 简介 Vue.js&#xff08;通常简称为Vue&#xff09;是一款流行的JavaScript框架&#xff0c;专注于构建用户界面。它的设计灵感来自于现代的JavaScript框架&#xf…...

C++语法基础知识面经汇总

背景&#xff1a;汇总了网上C常考的基础知识&#xff0c;方便复习 1&#xff0c;static关键字 static可以用于成员变量&#xff0c;或者成员函数。存储空间在静态存储区&#xff08;编译器会将其初始化为0&#xff0c;对应的存储空间直到程序执行结束才会释放&#xff09;&…...

AM@幂级数性质@幂级数和函数求解

文章目录 幂级数性质四则运算性质分析性质求解和函数例例 幂级数性质 和多项式有相似的性质本文介绍用幂级数的性质求解幂级数和函数的两个例子 四则运算性质 若幂级数 ∑ n 0 ∞ a n x n \sum_{n0}^{\infin}a_{n}x^{n} ∑n0∞​an​xn(1)的收敛半径为 R 1 R_1 R1​,和函数为…...

PHP低版本安全问题

目录 1、PHP弱类型问题 1.1 MD5、 SHA1 弱比较问题 1.2 数组 0 1&#xff09;函数无法处理数组&#xff0c;返回0 2&#xff09;strcmp 2、特殊字符串导致的问题 2.1 "ffifdyop" 与 md5(string,raw) 2.2 ereg函数漏洞&#xff1a;00 截断 3、正则匹配问…...

结构体——C语言初阶

一.结构体的声明&#xff1a; &#xff08;1&#xff09;结构的基础知识&#xff1a; 结构体是一种构造数据类型把不同类型的数据组合成一个整体结构体是一些值的集合&#xff0c;这些值称为成员变量。结构的每个成员可以是不同类型的变量需要注意的是&#xff0c;结构体是一种…...

基于django电影推荐系统

基于django电影推荐系统 摘要 该Django电影推荐系统是一个简单而基础的框架&#xff0c;旨在展示系统的基本组件。系统包括两个主要模型&#xff0c;即Movie和Rating&#xff0c;用于存储电影信息和用户评分。视图层包括展示电影列表和电影详情的功能&#xff0c;使用模板进行页…...

【问题处理】WPS提示不能启动此对象的源应用程序如何处理?

哈喽&#xff0c;大家好&#xff0c;我是雷工&#xff01; 最近在用WPS打开word文件中&#xff0c;插入的Excel附件时&#xff0c;无法打开&#xff0c;提示&#xff1a;“不能启动此对象的源应用程序”。 经过上网查找处理办法&#xff0c;尝试解决&#xff0c;现将解决过程记…...

UE 程序化网格 计算横截面

首先在构造函数内加上程序化网格&#xff0c;然后复制网格体到程序化网格组件上&#xff0c;将Static Mesh&#xff08;类型StaticMeshActor&#xff09;的静态网格体组件给到程序化网格体上 然后把StaticMesh&#xff08;类型为StaticMeshActor&#xff09;Instance暴漏出去 …...

【Spring】IoC容器的一些总结与补充

文章目录 1. 创建容器的两种方式相对路径导入绝对路径导入 2. 获取Bean的三种方式getBean后强转类型getBean内写明类别根据类别获取bean 3. 容器层次结构4. BeanFactory5. bean的总结6. 注入的总结 1. 创建容器的两种方式 相对路径导入 ApplicationContext ctx new ClassPat…...

Java GUI实现五子棋游戏

五子棋是一种双人对弈的棋类游戏&#xff0c;通常在棋盘上进行。棋盘为 1515 的方格&#xff0c;黑白双方各执棋子&#xff0c;轮流在棋盘的格点上落子&#xff0c;先在横、竖、斜线上形成五个相连的同色棋子者获胜。五子棋规则简单&#xff0c;易学难精&#xff0c;兼具攻防和…...

Python 集成 Nacos 配置中心

Python 集成 Nacos 配置中心 下载 Nacos 官方 pyhton 库 pip install nacos-sdk-python # 指定国内阿里云镜像源 pip3 install nacos-sdk-python -i http://mirrors.aliyun.com/pypi/simple/ --trusted-host mirrors.aliyun.com配置 Nacos 相关信息 Global:nacos:port: 8848…...

Debian 11 更新 Node.js 版本

发布于 2023-07-14 在 https://chenhaotian.top/debian/d-upd-nodejs/ 步骤 从 NodeSource 服务下载需要的 Node.js 安装脚本。注意更换版本号。当前的 LTS 版本是 18.x curl -sL https://deb.nodesource.com/setup_18.x | sudo -E bash -现在可以直接从 apt 安装&#xff0…...

python 对图像进行聚类分析

import cv2 import numpy as np from sklearn.cluster import KMeans import time# 中文路径读取 def cv_imread(filePath, cv2_falgcv2.COLOR_BGR2RGB): cv_img cv2.imdecode(np.fromfile(filePath, dtypenp.uint8), cv2_falg) return cv_img# 自定义装饰器计算时间 def…...

程序员导航站

探路者 hello.alluniverse.vip 开发者导航 - Pro Developer网站导航 探路者是一款极简导航工具&#xff0c;致力于收录的每个站点都有其独特的作用。同时支持自定义导航&#xff0c;让用户快速实现个性化的导航站点。 特性概述 免费ChatGPT 装机必备 开发工具 Git精选项目 …...

BIO、NIO、AIO三者的区别及其应用场景(结合生活例子,简单易懂)

再解释三者之前我们需要先了解几个概念&#xff1a; 阻塞、非阻塞&#xff1a;是相较于线程来说的&#xff0c;如果是阻塞则线程无法往下执行&#xff0c;不阻塞&#xff0c;则线程可以继续往下 执行。同步、异步&#xff1a;是相较于IO来说的&#xff0c;同步需要等待IO操作完…...

深度学习YOLO图像视频足球和人体检测 - python opencv 计算机竞赛

文章目录 0 前言1 课题背景2 实现效果3 卷积神经网络4 Yolov5算法5 数据集6 最后 0 前言 &#x1f525; 优质竞赛项目系列&#xff0c;今天要分享的是 &#x1f6a9; 深度学习YOLO图像视频足球和人体检测 该项目较为新颖&#xff0c;适合作为竞赛课题方向&#xff0c;学长非…...

系列七、JVM的内存结构【堆(Heap)】

一、概述 一个JVM实例只存在一个堆内存&#xff0c;堆内存的大小是可以手动调节的。类加载器读取了类文件后&#xff0c;需要把类、方法、常变量放到堆内存中&#xff0c;保存所有引用类型的真实信息&#xff0c;以方便执行器执行&#xff0c;堆内存分为三个部分&#xff0c;即…...

什么是Selenium?如何使用Selenium进行自动化测试?

什么是 Selenium&#xff1f; Selenium 是一种开源工具&#xff0c;用于在 Web 浏览器上执行自动化测试&#xff08;使用任何 Web 浏览器进行 Web 应用程序测试&#xff09;。   等等&#xff0c;先别激动&#xff0c;让我再次重申一下&#xff0c;Selenium 仅可以测试Web应用…...

【蓝桥杯 第十五届模拟赛 Java B组】训练题(A - I)

目录 A、求全是字母的最小十六进制数 B、Excel表格组合 C、求满足条件的日期 D、 取数字 - 二分 &#xff08;1&#xff09;暴力 &#xff08;2&#xff09;二分 E、最大连通块 - bfs F、哪一天&#xff1f; G、信号覆盖 - bfs &#xff08;1&#xff09;bfs&#xf…...

【数据结构】手撕双向链表

目录 前言 1. 双向链表 带头双向循环链表的结构 2. 链表的实现 2.1 初始化 2.2 尾插 2.3 尾删 2.4 头插 2.5 头删 2.6 在pos位置之前插入 2.7 删除pos位置 3.双向链表完整源码 List.h List.c 前言 在上一期中我们介绍了单链表&#xff0c;也做了一些练习题&…...

性能测试 —— Jmeter接口处理不低于200次/秒-场景

需求&#xff1a;期望某个接口系统的处理能力不低于200次/秒&#xff0c;如何设计&#xff1f; ①这个场景是看服务器对某个接口的TPS值是否能大于等于200&#xff0c;就可以了&#xff1b; ②系统处理能力&#xff1a;说的就是我们性能测试中的TPS&#xff1b; ③只要设计一…...

Qt中使用QNetworkAccessManager类发送https请求时状态码返回0

前言 在项目开发中&#xff0c;碰到一个问题&#xff0c;使用QNetworkAccessManager类对象发送https请求时&#xff0c;状态码一直返回0&#xff0c;抓包分析看请求响应也是正常的。费了好大劲终于搞定了&#xff0c;主要是两个原因导致的。 原因一&#xff1a;未设置支持SSL…...

Linux - 物理内存管理 - memmap

说明 裁减内核预留内存占用&#xff0c;在启动log中&#xff0c;发现memmap占用了大块内存&#xff08;446个pages&#xff09;。 On node 0 totalpages: 32576 memblock_alloc_try_nid: 1835008 bytes align0x40 nid0 from0x0000000000000000 max_addr0x0000000000000000 al…...

Python爬虫动态ip代理防止被封的方法

目录 前言 一、什么是动态IP代理&#xff1f; 二、如何获取代理IP&#xff1f; 1. 付费代理IP 2. 免费代理IP 3. 自建代理IP池 三、如何使用代理IP爬取数据&#xff1f; 1. 使用requests库设置代理IP 2. 使用urllib库设置代理IP 3. 使用selenium库设置代理IP 四、常…...

01Urllib

1.什么是互联网爬虫&#xff1f; 如果我们把互联网比作一张大的蜘蛛网&#xff0c;那一台计算机上的数据便是蜘蛛网上的一个猎物&#xff0c;而爬虫程序就是一只小蜘蛛&#xff0c;沿着蜘蛛网抓取自己想要的数据 解释1&#xff1a;通过一个程序&#xff0c;根据Url(http://www.…...

python爬取酷我音乐 根据歌名进行爬取

# _*_ coding:utf-8 _*_ # 开发工具:PyCharm # 公众号:小宇教程import urllib.parse from urllib.request import urlopen import json import time import sys import osdef Time_1...

【深度学习】吴恩达课程笔记(五)——超参数调试、batch norm、Softmax 回归

笔记为自我总结整理的学习笔记&#xff0c;若有错误欢迎指出哟~ 【吴恩达课程笔记专栏】 【深度学习】吴恩达课程笔记(一)——深度学习概论、神经网络基础 【深度学习】吴恩达课程笔记(二)——浅层神经网络、深层神经网络 【深度学习】吴恩达课程笔记(三)——参数VS超参数、深度…...

腾讯云轻量级服务器和云服务器什么区别?轻量服务器是干什么用的

随着互联网的迅速发展&#xff0c;服务器成为了许多人必备的工具。然而&#xff0c;面对众多的服务器选择&#xff0c;我们常常会陷入纠结之中。在这篇文章中&#xff0c;我们将探讨轻量服务器和标准云服务器的区别&#xff0c;帮助您选择最适合自己需求的服务器。 腾讯云双十…...

解决:虚拟机远程连接失败

问题 使用FinalShell远程连接虚拟机的时候连接不上 发现 虚拟机用的VMware&#xff0c;Linux发行版是CentOs 7&#xff0c;发现在虚拟机中使用ping www.baidu.com是成功的&#xff0c;但是使用FinalShell远程连接不上虚拟机&#xff0c;本地网络也ping不通虚拟机&#xff0c…...

SpringBoot项目集成发邮件功能

1&#xff1a;引入依赖2&#xff1a;配置设置3&#xff1a;授权码获取&#xff1a;4&#xff1a;核心代码5&#xff1a;postman模拟验证6&#xff1a;安全注意 1&#xff1a;引入依赖 <dependency><groupId>org.apache.commons</groupId><artifactId>c…...

【Spring篇】使用注解进行开发

&#x1f38a;专栏【Spring】 &#x1f354;喜欢的诗句&#xff1a;更喜岷山千里雪 三军过后尽开颜。 &#x1f386;音乐分享【如愿】 &#x1f970;欢迎并且感谢大家指出小吉的问题 文章目录 &#x1f33a;原代码&#xff08;无注解&#xff09;&#x1f384;加上注解⭐两个注…...

Flink(六)【DataFrame 转换算子(下)】

前言 今天学习剩下的转换算子&#xff1a;分区、分流、合流。 每天出来自学是一件孤独又充实的事情&#xff0c;希望多年以后回望自己的大学生活&#xff0c;不会因为自己的懒惰与懈怠而悔恨。 回答之所以起到了作用&#xff0c;原因是他们自己很努力。 …...

【2023春李宏毅机器学习】生成式学习的两种策略

文章目录 1 各个击破2 一步到位3 两种策略的对比 生成式学习的两种策略&#xff1a;各个击破、一步到位 对于文本生成&#xff1a;把每一个生成的元素称为token&#xff0c;中文当中token指的是字&#xff0c;英文中的token指的是word piece。比如对于unbreakable&#xff0c;他…...

Android13 adb 无法连接?

Android13 adb 无法连接? 文章目录 Android13 adb 无法连接?一、前言二、替换adbGoogle 官网对adb的介绍&#xff1a;Google 提供的adb tools的下载&#xff1a; 三、总结1、adb connect 连接后显示offline2、输入adb devices 报错&#xff1a;版本不匹配导致3、adb常用命令4…...

Ubuntu 20.04 调整交换分区大小

Ubuntu 调整交换分区大小 一、系统情况二、去除旧的交换分区文件三、配置并启用交换分区四、查看swap文件大小 一、系统情况 Ubuntu &#xff1a;Ubuntu 20.04.6 LTS 交换分区位置&#xff1a; cat /proc/swaps二、去除旧的交换分区文件 去掉旧的交换分区有两个步骤&#x…...

将Agent技术的灵活性引入RPA,清华等发布自动化智能体ProAgent

近日&#xff0c;来自清华大学的研究人员联合面壁智能、中国人民大学、MIT、CMU 等机构共同发布了新一代流程自动化范式 “智能体流程自动化” Agentic Process Automation&#xff08;APA&#xff09;&#xff0c;结合大模型智能体帮助人类进行工作流构建&#xff0c;并让智能…...

高济健康:数字化科技创新与新零售碰撞 助推医疗产业优化升级

近日&#xff0c;第六届中国国际进口博览会在上海圆满落幕&#xff0c;首次亮相的高济健康作为一家专注大健康领域的疾病和健康管理公司&#xff0c;在本届进博会上向业内外展示了围绕“15分钟步行健康生活圈”构建进行的全域数字化升级成果。高济健康通过数字化科技创新与新零…...

SystemVerilog学习 (5)——接口

一、概述 验证一个设计需要经过几个步骤&#xff1a; 生成输入激励捕获输出响应决定对错和衡量进度 但是&#xff0c;我们首先需要一个合适的测试平台&#xff0c;并将它连接到设计上。 测试平台包裹着设计,发送激励并且捕获设计的输出。测试平台组成了设计周围的“真实世界”,…...

vue3插槽的使用

什么是插槽 Vue 3 插槽&#xff08;Slots&#xff09;是一个强大的工具&#xff0c;用于在组件之间传递内容和逻辑。通过使用插槽&#xff0c;我们可以将子组件中的内容插入到父组件中的特定位置。本篇文章将总结 Vue 3 插槽的基本用法、特点以及使用场景。 基本用法 插槽分为…...

IPTABLES问题:DNAT下如何解决内网访问内部服务器问题

这个问题&#xff0c;困扰了我几年了&#xff0c;今天终于得到解决。 问题是这样的&#xff0c;在局域网内部有一台服务器&#xff0c;通过IPTABLES的网关提供对外服务&#xff0c;做过IPTABLES网关的人都知道&#xff0c;这很容易做到&#xff0c;只要在网关机器上写一个DNAT…...

异步任务线程池——最优雅的方式创建异步任务

对于刚刚从校园出来的菜鸡选手很容易写出自以为没问题的屎山代码&#xff0c;可是当上线后就会立即暴露出问题&#xff0c;这说到底还是基础不够扎实&#xff01;只会背八股文&#xff0c;却不理解&#xff0c;面试头头是道&#xff0c;一旦落地就啥也不是。此处&#xff0c;抛…...

uniapp 跨页面传值及跨页面方法调用

uniapp 跨页面传值及跨页面方法调用 1、跨页面传值 使用全局方法监听uni.$emit、uni.$on、uni.$off 发布、监听、移除 methods: {addFun(){let data [1]uni.navigateBack({ // 返回上一页delta: 1})uni.$emit(successFun,{data}) // 传值} }监听页 onLoad() {uni.$on(succ…...

无线物理层安全大作业

这个标题很帅 Beamforming Optimization for Physical Layer Security in MISO Wireless NetworksProblem Stateme![在这里插入图片描述](https://img-blog.csdnimg.cn/58ebb0df787c4e23b0c7be4189ebc322.png) Beamforming Optimization for Physical Layer Security in MISO W…...

目标检测标注工具AutoDistill

引言 在快速发展的机器学习领域&#xff0c;有一个方面一直保持不变&#xff1a;繁琐和耗时的数据标注任务。无论是用于图像分类、目标检测还是语义分割&#xff0c;长期以来人工标记的数据集一直是监督学习的基础。 然而&#xff0c;由于一个创新性的工具 AutoDistill&#x…...

关于SPJ表的数据库作业

打字不易&#xff0c;且复制且珍惜 建表 use 库名;create table S( --供应商 SNO char(6) not null, SNAME char(10) not null, STATUS INT, CITY char(10), primary key(SNO));create table P( --零件 PNO char(6) not null, PNAME char(12)not null, COLOR char(4), WEIGHT…...