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

bun 单元测试

bun test

Bun 附带了一个快速、内置、兼容 Jest 的测试运行程序。测试使用 Bun 运行时执行,并支持以下功能。

  • TypeScript 和 JSX
  • 生命周期 hooks
  • 快照测试
  • UI 和 DOM 测试
  • 使用 --watch 的监视模式
  • 使用 --preload 预加载脚本

Bun 旨在与 Jest 兼容,但并非所有内容都已实现。若要跟踪兼容性,请参阅此跟踪问题。

运行测试

bun test

测试是用 JavaScript 或 TypeScript 编写的,带有类似 Jest 的 API。有关完整文档,请参阅编写测试。

// main.test.tsimport { expect, test } from "bun:test";test("2 + 2", () => {expect(2 + 2).toBe(4);
});

运行器以递归方式在工作目录中搜索与以下模式匹配的文件:

  • *.test.{js|jsx|ts|tsx}
  • *_test.{js|jsx|ts|tsx}
  • *.spec.{js|jsx|ts|tsx}
  • *_spec.{js|jsx|ts|tsx}

您可以通过将其他位置参数传递给 bun test 来过滤要运行的测试文件集。路径与其中一个筛选器匹配的任何测试文件都将运行。通常,这些过滤器将是文件或目录名称;尚不支持 glob 模式。

bun test <filter> <filter> ...

要按测试名称进行筛选,请使用 -t/--test-name-pattern 标志。

# run all tests or test suites with "addition" in the name
bun test --test-name-pattern addition

若要在测试运行程序中运行特定文件,请确保路径以 .// 或 / 开头,以将其与筛选器名称区分开来。

bun test ./test/specific-file.test.ts

测试运行程序在单个进程中运行所有测试。它加载所有 --preload 脚本(有关详细信息,请参阅生命周期),然后运行所有测试。如果测试失败,测试运行程序将退出,并显示非零退出代码。

使用 --timeout 标志指定每个测试的超时(以毫秒为单位)。如果测试超时,它将被标记为失败。默认值为 5000

# default value is 5000
bun test --timeout 20

使用 --rerun-each 标志可多次运行每个测试。这对于检测片状或非确定性测试失败非常有用。

bun test --rerun-each 100

使用 --bail 标志在预定的测试失败次数后提前中止测试运行。默认情况下,Bun 将运行所有测试并报告所有故障,但有时在 CI 环境中,最好提前终止以减少 CPU 使用率。

# bail after 1 failure
bun test --bail# bail after 10 failure
bun test --bail 10

与 bun run 类似,您可以将 --watch 标志传递给 bun test,以监视更改并重新运行测试。

bun test --watch

生命周期 hooks

Bun 支持以下生命周期钩子:

Hook描述
beforeAll在所有测试之前运行一次。
beforeEach在每次测试之前运行。
afterEach在每次测试后运行。
afterAll在所有测试后运行一次。

这些钩子可以在测试文件中定义,也可以在预加载了 --preload 标志的单独文件中定义。

 bun test --preload ./setup.ts

有关完整文档,请参阅测试>生命周期。

Mocks

使用 bun.mock 创建 mock 函数。模拟在测试之间自动重置。

import { test, expect, mock } from "bun:test";
const random = mock(() => Math.random());test("random", () => {const val = random();expect(val).toBeGreaterThan(0);expect(random).toHaveBeenCalled();expect(random).toHaveBeenCalledTimes(1);
});

或者,您可以使用 jest.fn(),它的行为是完全相同的。

import { test, expect, jest } from "bun:test";const random = jest.fn(() => Math.random());

有关完整文档,请参阅测试>模拟。

快照测试

bun test 支持快照测试。

// example usage of toMatchSnapshot
import { test, expect } from "bun:test";test("snapshot", () => {expect({ a: 1 }).toMatchSnapshot();
});

要更新快照,请使用 --update-snapshots 标志。

bun test --update-snapshots

有关完整文档,请参阅测试>快照。

UI 和 DOM 测试

Bun 与流行的 UI 测试库兼容:

  • HappyDOM快乐DOM
  • DOM Testing LibraryDOM 测试库
  • React Testing LibraryReact 测试库

有关完整文档,请参阅测试> DOM 测试。

性能

Bun 的测试运行速度很快。

编写测试

从内置的 bun:test 模块中导入类似 Jest 的 API 来定义测试。从长远来看,Bun 旨在实现与 Jest 的完全兼容;目前,仅支持一组有限的 expect 匹配器。

基本用法

定义一个简单的测试:

// math.test.tsimport { expect, test } from "bun:test";test("2 + 2", () => {expect(2 + 2).toBe(4);
});

就像在 Jest 中一样,你可以在不导入它们的情况下使用 describe、test、expect 和其他函数。但与 Jest 不同,它们没有被注入到全局作用域中。相反,Bun 转译器会自动在内部注入一个来自 bun:test 的导入。

typeof globalThis.describe; // "undefined"
typeof describe; // "function"

这种转译器的集成仅在bun测试期间发生,并且只针对测试文件和预加载脚本。实际上,对于最终用户来说,这没有什么明显区别。

可以使用 describe 将测试分组为套件。

// main.test.tsimport { expect, test, describe } from "bun:test";describe("arithmetic", () => {test("2 + 2", () => {expect(2 + 2).toBe(4);});test("2 * 2", () => {expect(2 * 2).toBe(4);});
});

测试也可以是异步的。

import { expect, test } from "bun:test";test("2 * 2", async () => {const result = await Promise.resolve(2 * 2);expect(result).toEqual(4);
});

或者,使用 done 回调来标记完成。如果你在测试定义中将 done 回调作为一个参数包含进来,你必须调用它,否则测试将挂起。

import { expect, test } from "bun:test";test("2 * 2", done => {Promise.resolve(2 * 2).then(result => {expect(result).toEqual(4);done();});
});

可以通过给可选的第三个参数传递一个数字来指定每个测试的超时时间(以毫秒为单位)。

import { test } from "bun:test";test("wat", async () => {const data = await slowOperation();expect(data).toBe(42);
}, 500); // test must run in <500ms

test.skip

用 test.skip 跳过个别测试。这些测试将不会被运行。

import { expect, test } from "bun:test";test.skip("wat", () => {// TODO: fix thisexpect(0.1 + 0.2).toEqual(0.3);
});

test.todo

使用 test.todo 将测试标记为待办事项。这些测试将会运行,并且测试运行器会期望它们失败。如果它们通过了,那么将会提示你将它们标记为常规测试。

import { expect, test } from "bun:test";test.todo("fix this", () => {myTestFunction();
});

要仅运行标记为 todo 的测试,请使用 bun test --todo。

bun test --todo

test.only

要运行特定的测试或测试套件,请使用 test.only() 或 describe.only()。一旦声明,运行 bun test --only 将只执行被标记为 .only() 的测试/测试套件。如果在声明了 test.only() 的情况下运行 bun test 但没有使用 --only 选项,那么将执行给定套件中所有测试,直到遇到带有 .only() 的测试。在两种执行场景中,describe.only() 的功能都相同。

import { test, describe } from "bun:test";test("test #1", () => {// does not run
});test.only("test #2", () => {// runs
});describe.only("only", () => {test("test #3", () => {// runs});
});

以下命令只会执行测试 #2 和 #3。

bun test --only

以下命令会执行测试#1、#2和#3。

bun test

test.if

要条件性地运行测试,请使用 test.if()。如果条件为真值,则会运行测试。这对于仅在特定架构或操作系统上运行的测试特别有用。

test.if(Math.random() > 0.5)("runs half the time", () => {// ...
});const macOS = process.arch === "darwin";
test.if(macOS)("runs on macOS", () => {// runs if macOS
});

为了基于某些条件跳过测试,可以使用 test.skipIf() 或 describe.skipIf()。

const macOS = process.arch === "darwin";test.skipIf(macOS)("runs on non-macOS", () => {// runs if *not* macOS
});

test.each

要在测试表中为多个 case 返回一个函数,请使用test.each。

const cases = [[1, 2, 3], [3, 4, 5]];test.each(cases)("%p + %p should be %p", (a, b, expected) => {// runs once for each test case provided
})

根据标签的类型,可以对其格式进行多种设置。

%ppretty-format
%sString
%dNumber
%iInteger
%fFloating point
%jJSON
%oObject
%#Index of the test case
%%Single percent sign (%)

 匹配器

Bun 实现了以下匹配器。全面兼容 Jest 的路线图正在制定中;在这里跟踪进度。

.not
.toBe()
.toEqual()
.toBeNull()
.toBeUndefined()
.toBeNaN()
.toBeDefined()
.toBeFalsy()
.toBeTruthy()
.toContain()
.toStrictEqual()
.toThrow()
.toHaveLength()
.toHaveProperty()
.extend
.anything()
.any()
.arrayContaining()
.assertions()
.closeTo()
.hasAssertions()
.objectContaining()
.stringContaining()
.stringMatching()
.addSnapshotSerializer()
.resolves()
.rejects()
.toHaveBeenCalled()
.toHaveBeenCalledTimes()
.toHaveBeenCalledWith()
.toHaveBeenLastCalledWith()
.toHaveBeenNthCalledWith()
.toHaveReturned()
.toHaveReturnedTimes()
.toHaveReturnedWith()
.toHaveLastReturnedWith()
.toHaveNthReturnedWith()
.toBeCloseTo()
.toBeGreaterThan()
.toBeGreaterThanOrEqual()
.toBeLessThan()
.toBeLessThanOrEqual()
.toBeInstanceOf()
.toContainEqual()
.toMatch()
.toMatchObject()
.toMatchSnapshot()
.toMatchInlineSnapshot()
.toThrowErrorMatchingSnapshot()
.toThrowErrorMatchingInlineSnapshot()

生命周期钩子

测试运行器支持以下生命周期钩子。这对于加载测试装置、模拟数据和配置测试环境非常有用。

使用 beforeEach 和 afterEach 来执行每个测试的设置和拆卸逻辑。

import { beforeEach, afterEach } from "bun:test";beforeEach(() => {console.log("running test.");
});afterEach(() => {console.log("done with test.");
});

 使用 beforeAll 和 afterAll 执行每个范围的设置和拆卸逻辑。范围由定义钩子的位置决定。

将钩子范围限定为特定的 describe 块:

import { describe, beforeAll } from "bun:test";describe("test group", () => {beforeAll(() => {// setup});// tests...
});

将钩子范围限定在测试文件:

import { describe, beforeAll } from "bun:test";beforeAll(() => {// setup
});describe("test group", () => {// tests...
});

为了将整个多文件测试运行范围限定在挂钩内,请在单独的文件中定义这些挂钩。

// setup.tsimport { beforeAll, afterAll } from "bun:test";beforeAll(() => {// global setup
});afterAll(() => {// global teardown
});

然后使用 --preload 在任何测试文件之前运行设置脚本。

$ bun test --preload ./setup.ts

为了避免每次运行测试时都需要输入 “--preload”,您可以将其添加到 bunfig.toml 文件中:

[test]
preload = ["./setup.ts"]

Mocks

使用模拟函数创建模拟数据。

import { test, expect, mock } from "bun:test";
const random = mock(() => Math.random());test("random", async () => {const val = random();expect(val).toBeGreaterThan(0);expect(random).toHaveBeenCalled();expect(random).toHaveBeenCalledTimes(1);
});

另外,你也可以像Jest中那样使用 jest.fn() 函数,它的行为方式是完全一样的。

import { test, expect, jest } from "bun:test";
const random = jest.fn(() => Math.random());test("random", async () => {const val = random();expect(val).toBeGreaterThan(0);expect(random).toHaveBeenCalled();expect(random).toHaveBeenCalledTimes(1);
});

mock() 的结果是一个被添加了一些额外属性的新函数。 

import { mock } from "bun:test";
const random = mock((multiplier: number) => multiplier * Math.random());random(2);
random(10);random.mock.calls;
// [[ 2 ], [ 10 ]]random.mock.results;
//  [
//    { type: "return", value: 0.6533907460954099 },
//    { type: "return", value: 0.6452713933037312 }
//  ]

以下属性和方法在模拟函数上实现。

mockFn.getMockName()

mockFn.mock.calls

mockFn.mock.results

mockFn.mock.instances

mockFn.mock.contexts

mockFn.mock.lastCall

mockFn.mockClear()

mockFn.mockReset()

mockFn.mockRestore()

mockFn.mockImplementation(fn)

mockFn.mockImplementationOnce(fn)

mockFn.mockName(name)

mockFn.mockReturnThis()

mockFn.mockReturnValue(value)

mockFn.mockReturnValueOnce(value)

mockFn.mockResolvedValue(value)

mockFn.mockResolvedValueOnce(value)

mockFn.mockRejectedValue(value)

mockFn.mockRejectedValueOnce(value)

mockFn.withImplementation(fn, callback)

.spyOn()

可以使用SpyOn()创建一个Spy来跟踪对函数的调用,而无需将其替换为模拟函数。这些Spy可以传递给.toHaveBeenCalled()和.toHaveBeenCalledTimes()。

import { test, expect, spyOn } from "bun:test";const ringo = {name: "Ringo",sayHi() {console.log(`Hello I'm ${this.name}`);},
};const spy = spyOn(ringo, "sayHi");test("spyon", () => {expect(spy).toHaveBeenCalledTimes(0);ringo.sayHi();expect(spy).toHaveBeenCalledTimes(1);
});

 mock.module

模块模拟允许你覆盖一个模块的行为。使用 mock.module(path: string, callback: () => Object) 来模拟一个模块。

import { test, expect, mock } from "bun:test";mock.module("./module", () => {return {foo: "bar",};
});test("mock.module", async () => {const esm = await import("./module");expect(esm.foo).toBe("bar");const cjs = require("./module");expect(cjs.foo).toBe("bar");
});

像 Bun 的其余部分一样,模块 mocks 同时支持import和require。

覆盖已导入的模块

如果你需要覆盖一个已经被导入的模块,你不需要做什么特别的事情。只需要调用 mock.module(),模块就会被覆盖。

import { test, expect, mock } from "bun:test";// The module we're going to mock is here:
import { foo } from "./module";test("mock.module", async () => {const cjs = require("./module");expect(foo).toBe("bar");expect(cjs.foo).toBe("bar");// We update it here:mock.module("./module", () => {return {foo: "baz",};});// And the live bindings are updated.expect(foo).toBe("baz");// The module is also updated for CJS.expect(cjs.foo).toBe("baz");
});
提升和预加载

如果你需要在导入模块之前确保对其进行模拟,你应该使用 --preload 在运行测试之前加载你的模拟。

// my-preload.ts
import { mock } from "bun:test";mock.module("./module", () => {return {foo: "bar",};
});
bun test --preload ./my-preload

你可以在 bunfig.toml 文件中添加 preload:

[test]
# Load these modules before running tests.
preload = ["./my-preload"]

如果我 mock 一个已经被导入的模块,会发生什么?

如果你 mock 一个已经被导入的模块,该模块将在模块缓存中被更新。这意味着任何导入该模块的模块都将获得被 mock 的版本,但原始模块仍然会被评估。这意味着原始模块的任何副作用仍然会发生。

如果你想防止原始模块被评估,你应该在测试运行前使用 --preload 来加载你的模拟模块。

__mocks__目录和自动模拟 

目前尚不支持自动模拟。如果这阻止了你切换到Bun,请提交一个issue。

实现细节

模块模拟对 ESM 和 CommonJS 模块有不同的实现。对于ES模块,我们在 JavaScriptCore 中添加了补丁,允许 Bun 在运行时覆盖导出值并递归更新实时绑定。

从 Bun v1.0.19 开始,Bun会自动解析 mock.module() 中的规范参数,就像你进行了导入一样。如果解析成功,那么解析后的规范字符串将用作模块缓存中的键。这意味着你可以使用相对路径、绝对路径甚至模块名称。如果规范未解析,则使用原始规范作为模块缓存中的键。

解析后,被模拟的模块将存储在ES模块注册表和 CommonJS require 缓存中。这意味着你可以对模拟模块交替使用import和require。

回调函数是惰性调用的,只有当模块被导入或要求时才会调用。这意味着你可以使用mock.module()来模拟尚不存在的模块,而且你还可以使用mock.module()来模拟其他模块导入的模块。

日期和时间

bun:test 允许你在测试中更改时间。

这可以与以下任一项一起使用:

  • Date.now
  • new Date()
  • new Intl.DateTimeFormat().format()

计时器目前暂不支持,但可能在 Bun 的未来版本中支持。

setSystemTime

要更改系统时间,请使用 setSystemTime:

import { setSystemTime, beforeAll, test, expect } from "bun:test";beforeAll(() => {setSystemTime(new Date("2020-01-01T00:00:00.000Z"));
});test("it is 2020", () => {expect(new Date().getFullYear()).toBe(2020);
});

为了支持使用 Jest 的 useFakeTimers 和 useRealTimers 的进行测试,可以使用 useFakeTimers 和 useRealTimers:

test("just like in jest", () => {jest.useFakeTimers();jest.setSystemTime(new Date("2020-01-01T00:00:00.000Z"));expect(new Date().getFullYear()).toBe(2020);jest.useRealTimers();expect(new Date().getFullYear()).toBeGreaterThan(2020);
});test("unlike in jest", () => {const OriginalDate = Date;jest.useFakeTimers();if (typeof Bun === "undefined") {// In Jest, the Date constructor changes// That can cause all sorts of bugs because suddenly Date !== Date before the test.expect(Date).not.toBe(OriginalDate);expect(Date.now).not.toBe(OriginalDate.now);} else {// In bun:test, Date constructor does not change when you useFakeTimersexpect(Date).toBe(OriginalDate);expect(Date.now).toBe(OriginalDate.now);}
});

计时器 - 请注意,我们尚未实现用于模拟计时器的内置支持,但这在规划之中。

重置系统时间

要重置系统时间,不向 setSystemTime 传递任何参数:

import { setSystemTime, expect, test } from "bun:test";test("it was 2020, for a moment.", () => {// Set it to something!setSystemTime(new Date("2020-01-01T00:00:00.000Z"));expect(new Date().getFullYear()).toBe(2020);// reset it!setSystemTime();expect(new Date().getFullYear()).toBeGreaterThan(2020);
});

设置时区

要更改时区,可以将 $TZ 环境变量传递给 bun test。

TZ=America/Los_Angeles bun test

或在运行时设置 process.env.TZ:

import { test, expect } from "bun:test";test("Welcome to California!", () => {process.env.TZ = "America/Los_Angeles";expect(new Date().getTimezoneOffset()).toBe(420);expect(new Intl.DateTimeFormat().resolvedOptions().timeZone).toBe("America/Los_Angeles",);
});test("Welcome to New York!", () => {// Unlike in Jest, you can set the timezone multiple times at runtime and it will work.process.env.TZ = "America/New_York";expect(new Date().getTimezoneOffset()).toBe(240);expect(new Intl.DateTimeFormat().resolvedOptions().timeZone).toBe("America/New_York",);
});

相关文章:

bun 单元测试

bun test Bun 附带了一个快速、内置、兼容 Jest 的测试运行程序。测试使用 Bun 运行时执行&#xff0c;并支持以下功能。 TypeScript 和 JSX生命周期 hooks快照测试UI 和 DOM 测试使用 --watch 的监视模式使用 --preload 预加载脚本 Bun 旨在与 Jest 兼容&#xff0c;但并非所…...

阿里云2核4G服务器支持多少人同时在线?

2核4G服务器支持多少人在线&#xff1f;阿里云服务器网账号下的2核4G服务器支持20人同时在线访问&#xff0c;然而应用不同、类型不同、程序效率不同实际并发数也不同&#xff0c;2核4G服务器的在线访问人数取决于多个变量因素&#xff1a; 2核4G&#xff1a;2核CPU和4G内存对…...

浏览器发出一个请求到收到响应步骤详解

前言 在网络通信中&#xff0c;浏览器向Web服务器发送HTTP请求消息的过程是一个复杂而精密的环节&#xff0c;涉及到URL解析、DNS解析、数据拆分、路由表规则和MAC头部添加等一系列步骤。本文将深入探讨这一过程的每个环节&#xff0c;帮助读者更全面地了解浏览器与Web服务器之…...

121. 买卖股票的最佳时机【leetcode】/动态规划

121. 买卖股票的最佳时机 给定一个数组 prices &#xff0c;它的第 i 个元素 prices[i] 表示一支给定股票第 i 天的价格。 你只能选择 某一天 买入这只股票&#xff0c;并选择在 未来的某一个不同的日子 卖出该股票。设计一个算法来计算你所能获取的最大利润。 返回你可以从…...

K8S Service相关概念

Service基本概念 K8S Service是K8S实现微服务架构最重要的组件之一&#xff0c;主要作用&#xff1a;1&#xff09;为Pod提供稳定的访问地址&#xff08;域名或IP&#xff09;&#xff0c;2&#xff09;实现负责均衡&#xff0c;3&#xff09;自动屏蔽后端Endpoints的变化。 …...

小米消金剖析“冒充老板”诈骗案例,呼吁群众提高反诈意识

近年来&#xff0c;诈骗手段日益翻新&#xff0c;冒充公司老板身份进行诈骗的案例屡见不鲜。不法分子利用人们的焦虑心理&#xff0c;以冒充老板的身份进行诈骗&#xff0c;给无数工作人员和企业带来了巨大的经济损失。重庆小米消费金融有限公司&#xff08;以下简称“小米消金…...

全量知识系统问题及SmartChat给出的答复 之14 解析器+DDD+文法型 之2

Q36. 知识系统中设计的三种文法解析器和设计模式之间的关系 进一步&#xff0c;我想将 知识系统中设计的三种语言&#xff08;形式语言、人工语言和自然&#xff09;的文法解析器和DDD中的三种程序类型&#xff08;领域模型、领域实体和领域服务&#xff09; 形式语言文法 我…...

蓝桥杯备赛 day2 | 4. 付账问题 5. 数字三角形

付账问题&#xff0c;关键是要了解整型的范围&#xff0c;确定获取输入数据的变量类型 需要注意的是int的十进制范围-32768 ~ 32767&#xff0c;那么我们可以知道&#xff0c;人数n是可以用int来装的&#xff0c;需付款数S应该是long long&#xff0c;获取的每个人初始钱数也应…...

2024关于idea激活码报This license xxxx has been suspended

HOSTS文件中增加 0.0.0.0 www.jetbrains.com 0.0.0.0 account.jetbrains.com 然后...

Android9-W517-使用NotificationListenerService监听通知

目录 一、前言 二、前提 三、方案 方案一 方案二 方案三 方案四 方案五 方案六 方案七 四、关于NotificationListenerService类头注释 五、结论 一、前言 NotificationListenerService可以让应用监听所有通知&#xff0c;但是无法获得监听通知的权限&#xff0c;如…...

git的“You can‘t push commits with committe“解决方法

如果使用错误的用户和邮箱执行了git提交&#xff0c;在执行 git push 时将遇到如下错误&#xff1a; ! [remote rejected] feature_116390305_story_0 -> feature_116390305_story_0 (You cant push commits with committer ‘yijian’ or email eyjianqq.com who is not ex…...

CAN总线的拓扑类型和CAN收发器(原理讲解)

1&#xff1a;CAN收发器&#xff08;原理讲解&#xff09; 从原理上来讲CAN_H拉升电压&#xff0c;或CAN_L拉低电压的原理。 以上是TJA1145AT的俯瞰图&#xff0c;此芯片是NXP比较先进的CAN收发器&#xff0c;带SPI总线系统。 回到正题&#xff0c;CAN_H和CAN_L收发器是通过内…...

如何实现WordPress后台显示文章、分类目录、标签等的ID?

我们平时在使用WordPress的过程中&#xff0c;偶尔需要用到文章的ID&#xff0c;或分类目录ID&#xff0c;或标签ID&#xff0c;或媒体库ID&#xff0c;或评论ID&#xff0c;或用户ID等&#xff0c;但是WordPress后台默认是不显示它们的ID的。 今天boke112百科就跟大家分享如何…...

【GB28181】SIP协议实践之Windows下VS2019编译eXosip、osip,测试(附工程源码,一键打开编译)

引言 SIP开源库或者GB28181,这里选择了osip和eXosip,但是这两个库的编译使用有些麻烦,源码下来之后编译会出现很多问题,网上也没有找到完整的编译介绍,只能一步一步的找办法解决,以下帮大家整理编译过程。 如果不想编译,可以跳转文章末尾链接直接下载相应工程直接编译即…...

GPT提示语格式——个人自用

总体格式 指令&#xff1a;将 输入 划分为/翻译为/提取出/... 输出 输出格式&#xff1a;... 输入示例&#xff1a;... 输出示例&#xff1a;... 输入&#xff1a;... 输出&#xff1a;基本概述 示例 指令&#xff1a; 提取以下文本中的介词。 输入&#xff1a;“虽然这些发展…...

MCU最小系统电路设计(以STM32F103C8T6为例)

目录 一、何为最小系统&#xff1f; 二、最小系统电路设计 1.电源 &#xff08;1&#xff09;各种名词解释 &#xff08;2&#xff09;为什么会有VDD_1 _2 _3区分&#xff1f; &#xff08;3&#xff09;Mirco USB &#xff08;4&#xff09;5v->3.3v滤波电路 &#…...

[JavaWeb学习日记]JSP+Cookie+Filter与登录+CRUD案例

目录 一.JSP 二.EL表达式与JSTL标签 三.Cookie 四.Session 五.Filter 六. 登录CRUD:品牌增删改查案例 Demo一览 1.导包 2.构建包结构 3.创建数据库表tb_brand与user 4.创建实体类 5.mybatis的配置文件和logback配置文件 6.写接口 7.工具类&#xff1a;生成图片与…...

Ruby网络爬虫教程:从入门到精通下载图片

概述 网络爬虫技术在信息时代扮演着重要的角色&#xff0c;它可以自动化地获取互联网上的信息&#xff0c;为用户提供便利的数据服务。本文将带领读者从零开始&#xff0c;通过学习Ruby编程语言&#xff0c;逐步掌握网络爬虫的设计与实现&#xff0c;重点介绍如何利用网络爬虫技…...

各中间件性能、优缺点对比

参考资料&#xff1a; Kafka、ActiveMQ、RabbitMQ、RocketMQ 有什么优缺点&#xff1f;...

修改表中某个字段等于另一个字段减去 2 小时的 SQL

需求&#xff1a;将表中到达时间按照客户要求改为比赛时间的提前 N 小时&#xff0c;具体如下&#xff1a; 表结构 update contestSchedule SET mainRefereeArrivalTimeDATE_FORMAT(CONCAT(2024-03-04 ,gameTime)- INTERVAL 2 HOUR, %H:%i), assistantRefereeArrivalTimeDAT…...

智慧工地云平台源码,基于微服务架构+Java+Spring Cloud +UniApp +MySql

智慧工地管理云平台系统&#xff0c;智慧工地全套源码&#xff0c;java版智慧工地源码&#xff0c;支持PC端、大屏端、移动端。 智慧工地聚焦建筑行业的市场需求&#xff0c;提供“平台网络终端”的整体解决方案&#xff0c;提供劳务管理、视频管理、智能监测、绿色施工、安全管…...

屋顶变身“发电站” ,中天合创屋面分布式光伏发电项目顺利并网!

5月28日&#xff0c;中天合创屋面分布式光伏发电项目顺利并网发电&#xff0c;该项目位于内蒙古自治区鄂尔多斯市乌审旗&#xff0c;项目利用中天合创聚乙烯、聚丙烯仓库屋面作为场地建设光伏电站&#xff0c;总装机容量为9.96MWp。 项目投运后&#xff0c;每年可节约标煤3670…...

关于 WASM:1. WASM 基础原理

一、WASM 简介 1.1 WebAssembly 是什么&#xff1f; WebAssembly&#xff08;WASM&#xff09; 是一种能在现代浏览器中高效运行的二进制指令格式&#xff0c;它不是传统的编程语言&#xff0c;而是一种 低级字节码格式&#xff0c;可由高级语言&#xff08;如 C、C、Rust&am…...

SpringCloudGateway 自定义局部过滤器

场景&#xff1a; 将所有请求转化为同一路径请求&#xff08;方便穿网配置&#xff09;在请求头内标识原来路径&#xff0c;然后在将请求分发给不同服务 AllToOneGatewayFilterFactory import lombok.Getter; import lombok.Setter; import lombok.extern.slf4j.Slf4j; impor…...

什么是Ansible Jinja2

理解 Ansible Jinja2 模板 Ansible 是一款功能强大的开源自动化工具&#xff0c;可让您无缝地管理和配置系统。Ansible 的一大亮点是它使用 Jinja2 模板&#xff0c;允许您根据变量数据动态生成文件、配置设置和脚本。本文将向您介绍 Ansible 中的 Jinja2 模板&#xff0c;并通…...

C++使用 new 来创建动态数组

问题&#xff1a; 不能使用变量定义数组大小 原因&#xff1a; 这是因为数组在内存中是连续存储的&#xff0c;编译器需要在编译阶段就确定数组的大小&#xff0c;以便正确地分配内存空间。如果允许使用变量来定义数组的大小&#xff0c;那么编译器就无法在编译时确定数组的大…...

Java数值运算常见陷阱与规避方法

整数除法中的舍入问题 问题现象 当开发者预期进行浮点除法却误用整数除法时,会出现小数部分被截断的情况。典型错误模式如下: void process(int value) {double half = value / 2; // 整数除法导致截断// 使用half变量 }此时...

如何更改默认 Crontab 编辑器 ?

在 Linux 领域中&#xff0c;crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用&#xff0c;用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益&#xff0c;允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...

客户案例 | 短视频点播企业海外视频加速与成本优化:MediaPackage+Cloudfront 技术重构实践

01技术背景与业务挑战 某短视频点播企业深耕国内用户市场&#xff0c;但其后台应用系统部署于东南亚印尼 IDC 机房。 随着业务规模扩大&#xff0c;传统架构已较难满足当前企业发展的需求&#xff0c;企业面临着三重挑战&#xff1a; ① 业务&#xff1a;国内用户访问海外服…...

深入浅出WebGL:在浏览器中解锁3D世界的魔法钥匙

WebGL&#xff1a;在浏览器中解锁3D世界的魔法钥匙 引言&#xff1a;网页的边界正在消失 在数字化浪潮的推动下&#xff0c;网页早已不再是静态信息的展示窗口。如今&#xff0c;我们可以在浏览器中体验逼真的3D游戏、交互式数据可视化、虚拟实验室&#xff0c;甚至沉浸式的V…...