如何使用Jest测试你的React组件
在本文中,我们将了解如何使用Jest(Facebook 维护的一个测试框架)来测试我们的React组件。我们将首先了解如何在纯 JavaScript 函数上使用 Jest,然后再了解它提供的一些开箱即用的功能,这些功能专门用于使测试 React 应用程序变得更容易。
值得注意的是,Jest 并不是专门针对 React:您可以使用它来测试任何 JavaScript 应用程序。然而,它提供的一些功能对于测试用户界面来说非常方便,这就是为什么它非常适合 React。
应用测试示例
在我们测试任何东西之前,我们需要一个应用程序来测试!您可以在 GitHub 上找到它以及我们即将编写的所有测试。如果您想使用该应用程序来感受一下,您还可以在线找到现场演示。
该应用程序使用 ES2015 编写的,使用带有 Babel ES2015 和 React 预设的 webpack 进行编译。我不会详细介绍构建设置,但如果您想查看的话,一切都在 GitHub 存储库中。您可以在自述文件中找到有关如何在本地运行应用程序的完整说明。如果您想了解更多信息,该应用程序是使用webpack构建的,我推荐“ Webpack 初学者指南”进行学习。
应用程序的入口是app/index.js
:
-
render(
-
<Todos />,
-
document.getElementById('app')
-
);
该Todos
组件是应用程序的主要内容。它包含所有状态(该应用程序的硬编码数据,实际上可能来自 API 或类似数据),并有渲染两个子组件。
因为Todos
组件包含所有状态,所以每当有任何变化时,它需要Todo
和AddTodo
组件通知它。因此,它将函数向下传递到这些组件中,当某些数据发生变化时它们可以调用这些函数,并Todos
可以相应地更新状态。
最后,现在您会注意到所有业务逻辑都包含在app/state-functions.js
:
-
export function toggleDone(todos, id) {…}
-
export function addTodo(todos, todo) {…}
-
export function deleteTodo(todos, id) {…}
如果您熟悉 Redux,它们与 Redux 所谓的reducer
非常相似。事实上,如果这个应用程序变得更大,会考虑迁移到 Redux 以获得更明确、结构化的数据方法。
选择 TDD 而不是 TDD?
关于测试驱动开发的优缺点已经有很多文章写过了,开发人员需要先编写测试,然后再编写修复测试的代码。这背后的想法是,通过先编写测试,您必须思考您正在编写的API,并且它可能会导致更好的设计。我认为这在很大程度上取决于个人偏好和测试的类型。我发现,对于React组件,我喜欢先编写组件,然后为最重要的功能添加测试。然而,如果您发现先为组件编写测试符合您的工作流程,那么您应该这样做。在这里没有硬性规定,做适合您和您的团队感觉最好的事情。
什么是Jest
Jest首次发布于2014年,尽管它最初引起了很多关注,但该项目一度停滞不前,并没有得到很积极的开发。然而,Facebook投入了大量精力来改进Jest,并发布了一些令人印象深刻的变化,值得重新考虑。与最初的开源发布相比,Jest仅保留了名称和标志。其他一切都已经改变和重写。如果您想了解更多信息,可以阅读Christoph Pojer的评论,他在其中讨论了该项目的当前状态。
如果您对使用其他框架设置Babel、React和JSX测试感到沮丧,那么我强烈建议您尝试Jest。如果您发现现有的测试安装速度很慢,我也强烈推荐Jest。它可以自动并行运行测试,其watch模式能够运行与更改文件相关的测试,这在您拥有大量测试套件时是非常宝贵的。它已经配置了JSDom,这意味着您可以编写浏览器测试但通过Node运行它们。它可以处理异步测试,并且具有内置的高级功能,如mocking、spy和stub。
安装和配置 Jest
首先,我们需要安装 Jest。因为我们也在使用 Babel,所以我们将安装另外几个模块,使 Jest 和 Babel 可以正常使用:
npm install --save-dev jest babel-jest @babel/core @babel/preset-env @babel/preset-react
您还需要一个babel.config.js
包含 Babel 配置的文件,以使用您需要的任何预设和插件。如下所示:
-
module.exports = {
-
presets: [
-
'@babel/preset-env',
-
'@babel/preset-react',
-
],
-
};
本文不会深入探讨 Babel 的设置。如果您想具体了解有关 Babel 的更多信息,看我以前的文章。
我们还不会安装任何 React 测试工具,因为我们不会从测试组件开始,而是从测试状态函数开始。
Jest 期望在一个文件夹中找到我们的测试__tests__
,这已成为 JavaScript 社区中的一种流行惯例,我们将在这里坚持这一惯例。如果您不喜欢该__tests__
设置,开箱即用的 Jest 还支持查找任何.test.js
文件.spec.js
。
由于我们将测试我们的状态函数,因此请继续创建__tests__/state-functions.test.js
。 下面是一个测试用例,进行测试检查Jest配置是否正常。
-
describe('Addition', () => {
-
it('knows that 2 and 2 make 4', () => {
-
expect(2 + 2).toBe(4);
-
});
-
});
现在,进入您的package.json
, 添加npm test
命令:
-
"scripts": {
-
"test": "jest"
-
}
如果您现在执行npm test
命令,您应该会看到测试运行并通过!
-
PASS __tests__/state-functions.test.js
-
Addition
-
✓ knows that 2 and 2 make 4 (5ms)
-
Test Suites: 1 passed, 1 total
-
Tests: 1 passed, 1 total
-
Snapshots: 0 passed, 0 total
-
Time: 3.11s
如果您曾经使用过 Jasmine 或其他测试框架,Jest允许我们使用describe和it来嵌套测试。您使用多少嵌套取决于您。我喜欢嵌套我的测试,这样所有传递给describe和it的描述字符串几乎就像一个句子一样。
当涉及到实际断言时,您需要将要测试的内容包装在expect()调用中,然后在其上调用断言。在这种情况下,我们使用了toBe。您可以在Jest文档中找到所有可用断言的列表。toBe使用===来检查给定值是否与测试的值匹配。通过本教程,我们将遇到一些Jest的断言。
测试业务逻辑
我们将测试我们的第一个状态函数toggleDone
。 toggleDone
接收当前状态和我们想要切换的todo的ID。每个todo都有一个完成属性,而toggleDone应该将其从true切换为false,反之亦然。 注意:如果您正在跟随本文,确保已经克隆了代码库,并将app
文件夹复制到包含您的__tests__
文件夹的同一目录中。您还需要安装所有应用程序的依赖项(例如React)。在克隆存储库后运行npm install
即可确保全部安装完成。
我将从app/state-functions.js
导入函数并设置测试的结构开始。当Jest允许您使用describe
和it
进行嵌套时,您也可以使用test,这通常更易于阅读。test只是Jest it函数的别名,但有时可以使测试更易于阅读,减少嵌套。例如,以下是我如何使用嵌套的describe
和it
调用编写该测试的方法:
-
import { toggleDone } from '../app/state-functions';
-
describe('toggleDone', () => {
-
describe('when given an incomplete todo', () => {
-
it('marks the todo as completed', () => {
-
});
-
});
-
});
这是test
用法:
-
import { toggleDone } from '../app/state-functions';
-
test('toggleDone completes an incomplete todo', () => {
-
});
测试仍然很容易读懂,但现在缩进少了一些。这主要取决于个人喜好;选择您更喜欢的风格即可。
现在我们可以编写断言了。首先,我们将创建我们的起始状态,然后将其传递到toggleDone
中,以及我们要切换的todo的ID。toggleDone
将返回我们的最终状态,然后我们可以对其进行断言:
-
import { toggleDone } from "../app/state-functions";
-
test("tooggleDone completes an incomplete todo", () => {
-
const startState = [{ id: 1, done: false, text: "Buy Milk" }];
-
const finState = toggleDone(startState, 1);
-
expect(finState).toEqual([{ id: 1, done: true, text: "Buy Milk" }]);
-
});
现在我使用toEqual
进行断言。您应该使用toBe
来测试原始值(例如字符串和数字),使用toEqual
测试对象和数组。toEqual
是专门用于处理数组和对象的,并且会递归检查给定对象内的每个字段或项目以确保其匹配。
有了这个,我们现在可以运行npm test
并看到我们的状态函数测试通过:
-
PASS __tests__/state-functions.test.js
-
✓ tooggleDone completes an incomplete todo (9ms)
-
Test Suites: 1 passed, 1 total
-
Tests: 1 passed, 1 total
-
Snapshots: 0 passed, 0 total
-
Time: 3.166s
配置热更新
在更改测试文件后,手动再次运行npm test有点繁琐
。 Jest最好的功能之一是其监视模式,它会监视文件更改并相应地运行测试。它甚至可以根据更改的文件确定要运行的子集测试。它非常强大和可靠,您可以在监视模式下运行Jest,并在整天编写代码时保留它。
要在监视模式下运行它,您可以运行npm test -- watch
。在第一个--之后传递给npm test
的任何内容都将直接传递给基础命令。这意味着这两个命令是等效的:
npm test -- --watch
jest --watch
我建议您在另一个终端窗口中将Jest保留运行,以便在本教程的其余部分中使用。
在继续测试React组件之前,我们将在另一个状态函数上编写一个测试。在实际应用程序中,我会编写更多的测试,但是为了本教程的缘故,我将跳过其中一些。现在,让我们编写一个测试,以确保我们的deleteTodo函数正常工作。在查看下面我的编写方式之前,请尝试自己编写它并查看您的测试与我的测试有何不同。
请记住,您需要更新顶部的导入语句以导入deleteTodo
和toggleTodo
:
import { toggleDone, deleteTodo } from "../app/state-functions";
这是我编写测试用例:
-
test('deleteTodo deletes the todo it is given', () => {
-
const startState = [{ id: 1, done: false, text: 'Buy Milk' }];
-
const finState = deleteTodo(startState, 1);
-
expect(finState).toEqual([]);
-
});
这个测试与第一个测试并没有太大的区别:我们设置起始状态,运行我们的函数,然后对最终状态进行断言。如果您已在监视模式下运行Jest,请注意它如何检测到您的新测试并运行它,以及它运行速度的快速性!这是一种在写测试时立即得到反馈的好方法。
上面的测试还演示了测试的过程,其中包括:
- 设置
- 执行要测试的功能
- 对结果进行断言
通过以这种方式布局测试,您会发现更容易跟踪和处理它们。
现在我们已经满意测试我们的状态函数,让我们继续测试React组件。
测试 React 组件
值得注意的是,默认情况下,我实际上鼓励您不要在React组件上编写太多测试。您想要非常彻底测试的任何内容,例如业务逻辑,都应该从组件中提取出来并作为独立的函数存在,就像我们之前测试的状态函数一样。尽管如此,有时测试一些React交互(例如,确保用户单击按钮时调用特定函数并传递正确参数)是很有用的。我们将从测试我们的React组件是否呈现正确的数据开始,然后再看看如何测试交互。
为了编写测试,我们将安装Enzyme
,这是由Airbnb
编写的包装库,使测试React组件变得更加容易。
注意:自本文首次编写以来,React团队已经转向Enzyme
,并推荐使用[React Testing Library(RTL)](https://testing-library.com/docs/react-testing-library/intro)
。阅读该页面很值得一看。如果您正在维护已经使用Enzyme测试的代码库,则无需放弃所有内容并转移,但对于新项目,我建议考虑RTL
。
除了Enzyme
之外,我们还需要安装适用于我们使用的React版本的适配器。对于React v16,使用enzyme-adapter-react-16,但对于React v17,目前没有官方适配器可用,因此我们必须使用非官方版本。请注意,该软件包旨在作为临时措施,直到正式支持发布,并将在那时被弃用。
npm install --save-dev enzyme @wojtekmaj/enzyme-adapter-react-17
我们需要对 Enzyme
进行少量设置。在项目的根目录中,创建setup-tests.js
以下代码并将其放入其中:
-
import { configure } from 'enzyme';
-
import Adapter from '@wojtekmaj/enzyme-adapter-react-17';
-
configure({ adapter: new Adapter() });
然后,我们需要告诉Jest在执行任何测试之前为我们运行此文件。我们可以通过配置setupFilesAfterEnv
选项来实现这一点。您可以将Jest配置放在自己的文件中,但我喜欢使用package.json
并将东西放在jest对象中,Jest也会自动检测到它:
-
"jest": {
-
"setupFilesAfterEnv": [
-
"./setup-tests.js"
-
]
-
}
现在我们准备编写一些测试了!让我们测试该Todo
组件是否在段落内呈现其待办事项的文本。首先我们将创建__tests__/todo.test.js
并导入我们的组件:
-
import Todo from '../app/todo';
-
import React from 'react';
-
import { mount } from 'enzyme';
-
test('Todo component renders the text of the todo', () => {
-
});
从Enzyme
导入了mount
。mount
函数用于呈现我们的组件,然后允许我们检查输出并对其进行断言。即使我们在Node
中运行测试,我们仍然可以编写需要DOM的测试。这是因为Jest配置了jsdom
,一个在Node
中实现DOM的库。这很好,因为我们可以编写基于DOM的测试,而无需每次启动浏览器进行测试。
可以使用mount
来创建我们的Todo
-
const todo = { id: 1, done: false, name: 'Buy Milk' };
-
const wrapper = mount(
-
<Todo todo={todo} />
-
);
然后,我们可以调用wrapper.find
,给它一个CSS选择器,以查找我们希望包含Todo文本的段落。这个API可能会让您想起jQuery,这是有意设计的。这是一个在渲染的输出中搜索匹配元素的非常直观的API。
const p = wrapper.find('.toggle-todo');
最后,我们可以断言其中的文本是Buy Milk
:
expect(p.text()).toBe('Buy Milk');
完整的测试用例是这样的:
-
import Todo from '../app/todo';
-
import React from 'react';
-
import { mount } from 'enzyme';
-
test('TodoComponent renders the text inside it', () => {
-
const todo = { id: 1, done: false, name: 'Buy Milk' };
-
const wrapper = mount(
-
<Todo todo={todo} />
-
);
-
const p = wrapper.find('.toggle-todo');
-
expect(p.text()).toBe('Buy Milk');
-
});
现在我们有了一个测试,可以检查我们是否成功地渲染了todos。 接下来,让我们看一下如何使用Jest的spy功能来断言具有特定参数的函数被调用。在我们的情况下很有用,因为我们有一个Todo组件,它被赋予了两个函数作为属性,当用户单击按钮或执行交互时应该调用这些函数。
在这个测试中,我们将断言当Todo
被单击时,组件将调用它所赋予的doneChange
属性:
-
test('Todo calls doneChange when todo is clicked', () => {
-
});
我们希望有一个可以用来跟踪其调用及其调用参数的函数。然后,我们可以检查当用户单击Todo时,doneChange
函数是否被调用,并且被调用时使用了正确的参数。幸运的是,Jest在功能上提供了这个功能来使用spy(间谍)
。spy
是一种函数,其实现方式并不重要,您只需要关心它何时以及如何被调用。可以将其想象为您在侦察该函数。要创建一个spy
,我们调用jest.fn()
:
const doneChange = jest.fn();
这提供了一个函数,我们可以对其进行监视并确保其被正确调用。让我们从使用正确的props来呈现我们的Todo
开始:
-
const todo = { id: 1, done: false, name: 'Buy Milk' };
-
const doneChange = jest.fn();
-
const wrapper = mount(
-
<Todo todo={todo} doneChange={doneChange} />
-
);
接下来,我们可以再次查找我们的段落,就像在前面的测试中一样:
const p = wrapper.find(".toggle-todo");
然后我们可以调用simulate
它来模拟用户事件,并click
作为参数传递:
p.simulate('click');
现在我们只需要断言我们的spy函数是否被正确调用。在这种情况下,我们期望它被调用时使用了ID为1
的todo。我们可以使用expect(doneChange).toBeCalledWith(1)
来断言这一点,然后我们的测试就完成了!
-
test('TodoComponent calls doneChange when todo is clicked', () => {
-
const todo = { id: 1, done: false, name: 'Buy Milk' };
-
const doneChange = jest.fn();
-
const wrapper = mount(
-
<Todo todo={todo} doneChange={doneChange} />
-
);
-
const p = wrapper.find('.toggle-todo');
-
p.simulate('click');
-
expect(doneChange).toBeCalledWith(1);
-
});
结论
Facebook很久以前就发布了Jest,但最近已经被广泛采用和改进。它已经快速成为JavaScript开发人员的首选,而且它只会变得更好。如果你以前尝试过Jest并且不喜欢它,我无法足够地鼓励你再次尝试它,因为现在它基本上是一个完全不同的框架。它快速,重复运行规格非常出色,提供了出色的错误消息,并且有一个出色的表达式API,用于编写良好的测试。
感谢每一个认真阅读我文章的人!!!
作为一位过来人也是希望大家少走一些弯路,如果你不想再体验一次学习时找不到资料,没人解答问题,坚持几天便放弃的感受的话,在这里我给大家分享一些自动化测试的学习资源,希望能给你前进的路上带来帮助。
软件测试面试文档
我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。
视频文档获取方式:
这份文档和视频资料,对于想从事【软件测试】的朋友来说应该是最全面最完整的备战仓库,这个仓库也陪伴我走过了最艰难的路程,希望也能帮助到你!以上均可以分享,点下方小卡片即可自行
相关文章:

如何使用Jest测试你的React组件
在本文中,我们将了解如何使用Jest(Facebook 维护的一个测试框架)来测试我们的React组件。我们将首先了解如何在纯 JavaScript 函数上使用 Jest,然后再了解它提供的一些开箱即用的功能,这些功能专门用于使测试 React 应…...

微网能量管理研究
微网能量管理研究的重点 微网系统的建模 建立分布式能源单元模型以及微网系统的整体运行、协调控制和优化配置等方面的模型 分布式电源控制策略 微网内分布式电源及储能系统运行依赖于电力电子接口技术,需要相应的充放电控制策略 再生能源发电预测 准确预测太阳能…...

Java基础面试题02:简述什么是值传递和引用传递?
面试题:简述什么是值传递和引用传递? 什么是值传递? 值传递(pass by value)是指在调用函数时,把实际参数的值复制一份传递给函数。换句话说,函数内部对参数的任何修改,都不会影响到…...

【STL】10.set与map的模拟实现
一、源码及框架分析 SGI-STL30版本源代码,map和set的源代码在map/set/stl_map.h/stl_set.h/stl_tree.h等及个头文件中。 map和set的实现结构框架核心部分截取出来如下: // set #ifndef __SGI_STL_INTERNAL_TREE_H #include <stl_tree.h> #endif …...

Playwright(Java版) - 8: Playwright 元素交互的高级应用
在自动化测试中,处理复杂的页面交互是常见的需求。例如,应对动态加载的元素、处理弹窗与对话框、模拟拖放操作,甚至在绘图板上进行绘图操作。 1 动态元素与弹窗处理 1.1 动态元素的加载与等待 动态页面可能会导致元素在操作时尚未完全加载&…...

播放器开发之ffmpeg 硬件解码方案
硬件编解码的概念 硬件编解码是⾮CPU通过烧写运⾏视频加速功能对⾼清视频流进⾏编解码,其中⾮CPU可包括GPU、FPGA或者 ASIC等独⽴硬件模块,把CPU⾼使⽤率的视频解码⼯作从CPU⾥分离出来,降低CPU的使⽤负荷,使得平台能 ⾼效且流畅…...

n、nvm、nrm、pnpm、yarn各种指令大全
n mac的版本管理工具(可能与nvm冲突) 安装 # 使用 npm / yarn npm i -g n yarn global add n # 使用 brew brew install n环境变量 export PATH"/usr/local/n/versions/node:$PATH"命令详解 版本查看 # 查看 n 版本 n --version/-V # 查…...

数据库管理-根据日期字段进行数据筛选更新数据
项目场景 数据插入、更新、查询 数据库中一张审计表格用来记录数据的操作包括数据的id,数据名称sjmc,数据状态sjzt,数据创建时间createtime,数据更新时间updatetime。 具体需求如下: 根据数据名称更新sjzt和update…...

03. 运算符
一、运算符与表达式 运算符 就是对字面量或者变量进行操作的符号;表达式 是指用运算符把字面量或者变量连接起来,符合 Python 语法的式子。不同运算符连接的表达式体现的是不同类型的表达式;Python 中的运算符主要包括 算术运算符、赋值运算符…...

【最优清零方案——贪心+滑动窗口+线段树】
题目 代码 #include <bits/stdc.h> using namespace std; using ll long long; const int N 1e6 10; int a[N]; struct node {int l, r;int m, p, lazy; } tr[4 * N]; void pushup(node &u, node &l, node &r) {if (l.m r.m){u.m l.m;u.p max(l.p, r.…...

一个点绕任意点旋转后的点的坐标
在平面坐标上,任意点P(x1,y1),绕一个坐标点Q(x2,y2)逆时针旋转θ角度后,新的坐标设为(x, y)的计算公式: x (x1 - x2)*cos(θ) - (y1 - y2)*sin(θ) x2 ; y (x1 - x2)*sin(θ) (y1 - y2)*cos(θ) y2 ; 另一个场景应用,坐标轴绕…...

大数据面试题每日练习--HDFS是如何工作的?
HDFS(Hadoop Distributed File System)是一个分布式文件系统,设计用于存储非常大的文件。它的主要工作原理如下: NameNode:管理文件系统的命名空间,维护文件目录树和文件元数据信息。NameNode记录每个文件…...

Python的3D可视化库 - vedo (2)visual子模块 基本可视化行为
文章目录 1. visual模块的继承关系2. 基类CommonVisual的方法2.1 获取对象信息2.1.1 对象本身信息2.1.2 对象的查找表2.1.3 对象标量范围2.1.4 对象缩略图 2.2 呈现对象2.2.1 在窗口显示1.2.2 对象可见性 2.2.3 对象颜色2.2.4 对象透明度 2.3 添加标度条2.3.1 2D标度条2.3.2 3D…...

Java AIO(NIO.2)
Java AIO(Asynchronous I/O,异步I/O),也被称为NIO.2,是Java平台提供的一种处理异步输入/输出操作的机制。作为Java NIO(New I/O)的扩展,AIO引入了一些新的API和特性,旨在…...

Flink 常用问题及常用配置(有用)
一、Flink 常用问题及常用配置 参数 示例 说明 execution.checkpointing.interval 3min Checkpoint 触发间隔 state.backend rocksdb / filesystem 用于设置statebackend类型, 默认会以内存为statebackend(无法支持大状态) taskmanager.memory.jvm-overhead.max 204…...

RocketMQ: 消息过滤,通信组件,服务发现
消息过滤 1 ) 简单消息过滤 /*** 订阅指定topic下tags分别等于 TagA 或 TagC 或 TagD */consumer.subscribe("TopicTest1", "TagA || TagC || TagD");如以上代码所示,简单消息过滤通过指定多个 Tag 来过滤消息,过滤的动作在服务器进…...

linux ubuntu的脚本知
目录 一、变量的引用 二、判断指定的文件是否存在 三、判断目录是否存在 四、判断最近一次命令执行是否成功 五、一些比较符号 六、"文件"的读取和写入 七、echo打印输出 八、ubuntu切换到root用户 N、其它可以参考的网址 脚本功能强大,用起来也…...

HTTP有哪些风险?是怎么解决的?
一、风险 HTTP是通过明文传输的,存在窃听风险、篡改风险以及冒充风险。 二、如何解决 HTTPS在HTTP的下层加了一个SSL/TLS层,保证了安全,通过混合加密解决窃听风险、数字签名解决篡改风险、数字证书解决冒充风险。 (1࿰…...

3.12MayBeSomeLinearAlgebra
X是M*(D1),XT为(D1)*M Ω是一行D1列,X乘以欧米噶是M行D1列 行是说样本个数,列是特征数量 如果是小样本,那么可能会出现特征数量大于样本个数 如果MD*DM就是M*M,...

学习日志015--python单链表
创建 class Node:def __init__(self,data):# 数据域self.data data# 链接域self.next Noneclass LinkList:def __init__(self,):# 初始化头节点self.head None# 记录链表的长度self.size 0 增加 #头插def insert_head(self,value):# 创建新节点node Node(value)q self…...

如何在Windows右键新建菜单中添加自定义项
Windows Registry Editor Version 5.00[HKEY_CLASSES_ROOT\.py] "Python.File"[HKEY_CLASSES_ROOT\.py\ShellNew] "NullFile"""[HKEY_CLASSES_ROOT\Python.File] "FriendlyTypeName""文本.py"[HKEY_CLASSES_ROOT\Python.Fil…...

Spring Boot 3.0废弃了JavaEE,改用了Jakarta EE
Spring Boot 3.0废弃了JavaEE,改用了Jakarta EE 历史背景 javax变成Jakarta的主要原因是因为Java EE项目从Oracle转移到了Eclipse Foundation,并改名为Jakarta EE。 JavaEE是从Java 1.2版本开始推出的Java企业级开发平台,最初的名称是J2EE(J…...

pdf文档动态插入文字水印,45度角,旋转倾斜,位于文档中央,多行水印可插入中文
一行水印 /*** param inputFile 你的PDF文件地址* param outputFile 添加水印后生成PDF存放的地址* param waterMarkName 你的水印* return*/public static boolean waterMark(String inputFile,String outputFile, String waterMarkName){try {PdfReader reader new PdfRead…...

[ 渗透测试面试篇-2 ] 针对大规模资产的攻击思路
🍬 博主介绍 👨🎓 博主介绍:大家好,我是 _PowerShell ,很高兴认识大家~ ✨主攻领域:【渗透领域】【数据通信】 【通讯安全】 【web安全】【面试分析】 🎉点赞➕评论➕收藏 养成习…...

深入解析 Web 应用中的 CHIPS(Partitioned Cookie Attribute)
深入解析 Web 应用中的 CHIPS(Partitioned Cookie Attribute) 最新发现flask3.1.0 的版本引入了新的特性:对CHIPS的支持。不少同学对这个可能有点陌生,本文带大家了解一下。 为了在隐私保护和功能需求之间取得平衡,Goo…...

从搭建uni-app+vue3工程开始
技术栈 uni-app、vue3、typescript、vite、sass、uview-plus、pinia 一、项目搭建 1、创建以 typescript 开发的工程 npx degit dcloudio/uni-preset-vue#vite-ts my-vue3-project2、安装sass npm install -D sass// 安装sass-loader,注意需要版本10,…...

归并排序与逆序对问题(C语言版)
一、引言 归并排序是一种高效且稳定的排序方法,而逆序对问题是算法领域的一个经典问题,本文教大家如何实现归并排序,以及如何使用归并排序去结果逆序对问题 二、归并排序 归并排序思想 分解:将待排序的数组分成两半,…...

网络爬虫总结与未来方向
通过深入学习和实际操作,网络爬虫技术从基础到进阶得以系统掌握。本节将全面总结关键内容,并结合前沿技术趋势与最新资料,为开发者提供实用性强的深度思考和方案建议。 1. 网络爬虫技术发展趋势 1.1 趋势一:高性能分布式爬虫 随…...

C++ 核心数据结构:Stack 与 Queue 类深度解析
🌟快来参与讨论💬,点赞👍、收藏⭐、分享📤,共创活力社区。 🌟 目录 💯前言 💯Stack 类 (一)Stack 类的概念与特点 (二&#x…...

Python枚举类详解:用enum模块高效管理常量数据
《Python OpenCV从菜鸟到高手》带你进入图像处理与计算机视觉的大门! 在编程中,常量的管理是一个关键环节,合理的管理常量可以提高代码的可读性和可维护性。Python的enum模块提供了一种有效的方式来组织常量数据,通过枚举类(Enum)将相关的常量值集合在一起,使代码更具结…...