【实战】一、Jest 前端自动化测试框架基础入门(一) —— 前端要学的测试课 从Jest入门到TDD BDD双实战(一)
文章目录
- 一、前端要学的测试课
- 1.前端要学的测试
- 2.前端工程化的一部分
- 3.前端自动化测试的例子
- 4.前端为什么需要自动化测试?
- 5.课程涵盖内容
- 6.前置技能
- 7.学习收获
- 二、Jest 前端自动化测试框架基础入门
- 1. 自动化测试背景及原理
- 前端自动化测试产生的背景及原理
- 2.前端自动化测试框架
- 3.使用 Jest 修改自动化测试样例
- 4.Jest 的简单配置
学习内容来源:Jest入门到TDD/BDD双实战_前端要学的测试课
相对原教程,我在学习开始时(2023.08)采用的是当前最新版本:
项 | 版本 |
---|---|
@babel/core | ^7.16.0 |
@pmmmwh/react-refresh-webpack-plugin | ^0.5.3 |
@svgr/webpack | ^5.5.0 |
@testing-library/jest-dom | ^5.17.0 |
@testing-library/react | ^13.4.0 |
@testing-library/user-event | ^13.5.0 |
babel-jest | ^27.4.2 |
babel-loader | ^8.2.3 |
babel-plugin-named-asset-import | ^0.3.8 |
babel-preset-react-app | ^10.0.1 |
bfj | ^7.0.2 |
browserslist | ^4.18.1 |
camelcase | ^6.2.1 |
case-sensitive-paths-webpack-plugin | ^2.4.0 |
css-loader | ^6.5.1 |
css-minimizer-webpack-plugin | ^3.2.0 |
dotenv | ^10.0.0 |
dotenv-expand | ^5.1.0 |
eslint | ^8.3.0 |
eslint-config-react-app | ^7.0.1 |
eslint-webpack-plugin | ^3.1.1 |
file-loader | ^6.2.0 |
fs-extra | ^10.0.0 |
html-webpack-plugin | ^5.5.0 |
identity-obj-proxy | ^3.0.0 |
jest | ^27.4.3 |
jest-enzyme | ^7.1.2 |
jest-resolve | ^27.4.2 |
jest-watch-typeahead | ^1.0.0 |
mini-css-extract-plugin | ^2.4.5 |
postcss | ^8.4.4 |
postcss-flexbugs-fixes | ^5.0.2 |
postcss-loader | ^6.2.1 |
postcss-normalize | ^10.0.1 |
postcss-preset-env | ^7.0.1 |
prompts | ^2.4.2 |
react | ^18.2.0 |
react-app-polyfill | ^3.0.0 |
react-dev-utils | ^12.0.1 |
react-dom | ^18.2.0 |
react-refresh | ^0.11.0 |
resolve | ^1.20.0 |
resolve-url-loader | ^4.0.0 |
sass-loader | ^12.3.0 |
semver | ^7.3.5 |
source-map-loader | ^3.0.0 |
style-loader | ^3.3.1 |
tailwindcss | ^3.0.2 |
terser-webpack-plugin | ^5.2.5 |
web-vitals | ^2.1.4 |
webpack | ^5.64.4 |
webpack-dev-server | ^4.6.0 |
webpack-manifest-plugin | ^4.0.2 |
workbox-webpack-plugin | ^6.4.1" |
具体配置、操作和内容会有差异,“坑”也会有所不同。。。
一、前端要学的测试课
1.前端要学的测试
- Jest入门
- TDD实战
- BDD实战
2.前端工程化的一部分
- 前端自动化测试
- 高质量代码设计
- 高质量代码实现
3.前端自动化测试的例子
Vue、Echarts、React、Ant-Design…这些都有使用到自动化测试
4.前端为什么需要自动化测试?
- 改需求时,代码重构:导致修复时间长,成本高
- 自动化测试,修复时间少,难度低
5.课程涵盖内容
学习安排:
- 第1章 课程介绍
- 第2章 Jest 基础
- 第3章 Jest 进阶
- 第4&6章 React 测试
- 第5&7章 Vue 测试
- 第8章 前端自动化测试的思考总结
6.前置技能
7.学习收获
- 彻底入门前端自动化测试
- 根据项目完成测试方案选型
- 主流前端测试工具使用
- 完成前端自动化测试项目落地
- 形成多维度前端架构思维
二、Jest 前端自动化测试框架基础入门
1. 自动化测试背景及原理
前端自动化测试产生的背景及原理
作为一名前端开发开发者,每天都会遇到各种各样的 bug,比如安全性的 bug,逻辑 bug,性能 bug,展示 bug 等,在日常开发过程中想要不出 bug 几乎是不可能的。
当遇到复杂的业务场景或对代码进行修补的时候出现 bug 其实是非常正常的事情,bug 本身并不可怕,可怕的是把 bug 真正的带到线上。
所以为了防止 bug 上线,可以做些 比如 codeview 的整合,通过测试同学的测试,帮助发现代码潜在的问题,或者通过灰度发布这样的机制帮助在代码上线之前进行局部的验证,这些方法都可以很好地帮助降低 bug 上线的概率。
但是对于前端来说还有没有更好的办法降低代码中 bug 出现的频率呢?是有的,一些简单错误可以通过以下几种工具来规避:
TypeScript
、 Flow
、 EsLint
、 StyleLint
…
它们都可以帮助提高前端代码质量,减少 bug 数量,当然这还不够,还可以使用前端自动化测试工具来进一步避免 bug 的产生。
说到自动化测试,在后端自动化测试已经很普遍被应用了,但是在前端领域目前被普及的情况并不是很好,因此学习前端测试刻不容缓
常见测试种类:
- 单元测试
- 集成测试
- end To end 端到端测试
- 回归测试
- 性能测试
- 压力测试
- …
.
拓展学习
- 前端自动化测试探索 - FEX
为了更好的理解,接下来进入代码环节
-
新建文件夹(
mkdir lesson1
) -
打开新建的文件夹(
cd lesson1
) -
创建文件(
touch math.js
)
function add(a,b) {return a + b;
}function minus(a,b) {return a - b;
}
- 创建文件(
touch index.html
),引入math.js
<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>math.js</title><script src="math.js"></script>
</head>
<body></body>
</html>
- 创建文件(
touch math.test.js
)
let result = add(3, 7);
let expected = 10;if(result !== expected) {throw Error(`3 + 7 应该等于 ${expected},但是结果却是${result}`);
}result = minus(3, 3);
expected = 0;if(result !== expected) {throw Error(`3 - 3 应该等于 ${expected},但是结果却是${result}`);
}
直接打开页面在浏览器的控制台,输入 math.test.js
中的测试代码并执行
index.html
已经引入了math.js
这个函数库,可以通过直接在控制台执行的方式调用- 测试过程中若是修改了原代码,需要刷新页面再执行测试代码
我们写的测试的例子基本上都是一个套路,就是 先预期一个结果,然后在执行计算出真正的结果,然后两个结果进行比较是否相同,如果相同就可以通过,如果不相同就抛出异常错误信息。
优化测试代码,单独封装一个 expect
函数,方便使用:
function expect(result) {return {toBe: function (actual) {if (result !== actual) {throw Error('预期值和实际值不相等');}}}
}expect(add(3,3)).toBe(6);
expect(minus(6,3)).toBe(3);
但是有个问题就是测试结果报错后从报错信息上看并不知道具体是函数库中的哪个方法错了。所以进一步优化:
function expect(result) {return {toBe: function (actual) {if (result !== actual) {throw Error(`预期值和实际值不相等 预期${actual} 结果却是${result}`);}}}
}function test (desc, fn) {try {fn();console.log(`${desc} 通过测试`)}catch (e) {console.log(`${desc} 没有通过测试 ${e}`)}
}test('测试加法 3 + 7', () => {expect(add(3,3)).toBe(6);
});test('测试减法 6 - 3', () => {expect(minus(6,3)).toBe(3);
});
2.前端自动化测试框架
在实际项目中只有 except
和 test
两个方法显然是不够的,同时还有很多自动化测试机制需要集成。
现在业界已经有很多前端自动化测试框架,这些框架里面集成了非常多的方法和机制供选用,在使用过程中的可以方便快捷的进行项目级别的前端自动化测试了。
目前业界主流的几个前端自动化测试框架包括 Jasmine、Mocha+Chai、Jest。
一个好的前端自动化测试框架应该在以下几个方面比较突出:
- 性能好
- 功能丰富
- 易用性高
Jest 优势:
- 速度快(在编辑过程中可以自动运行修改部分的测试代码)
- API 简单
- 易配置
- 隔离性好
- 监控模式
- IDE 整合
- 快照 Snapshot
- 多项目并行
- 覆盖率报告快速生成
- Mock 丰富
- 支持拓展性强,如:Babel、TypeScript、Node.js、React、Angular、Vue
3.使用 Jest 修改自动化测试样例
接下来开始使用 Jest,在这之前需要提前安装好 Node 环境,具体可参见
【笔记】Node.js概述和开发环境搭建
- 新建文件夹(
mkdir lesson2
) - 进入新建的目录(
cd lesson2
) - 初始化 npm 包管理环境(
npm init
) - 一路回车后可以看到目录下生成一个文件 ——
package.json
- 安装 Jest (
npm i jest@24.8.0 -D
)-D
表示只有在开发的时候才会运行测试用例
- 安装好后将上节代码复制过来并作如下修改:
math.js
作为 node 模块导出
function add(a,b) {return a + b;
}function minus(a,b) {return a - b;
}function multi(a,b) {return a * b;
}module.exports = {add,minus,multi
}
math.test.js
中 math.js
作为 node 模块导入并使用
const math = require('./math')
const {add,minus,multi
} = mathtest('测试加法 3 + 7', () => {expect(add(3,3)).toBe(6);
});test('测试减法 6 - 3', () => {expect(minus(6,3)).toBe(3);
});test('测试乘法 3 * 3', () => {expect(multi(3,3)).toBe(9);
});
修改配置 package.json
:
{..."scripts": {"test": "jest --watchAll"},...
}
--watchAll
表示监听所有测试用例,当有发生变化时,自动运行 jest 重跑所有测试用例
控制台运行 npm run test
,结果如下:
> lesson2@1.0.0 test
> jestPASS ./math.test.js√ 测试加法 3 + 7 (4ms)√ 测试减法 6 - 3√ 测试乘法 3 * 3 (1ms)Test Suites: 1 passed, 1 total
Tests: 3 passed, 3 total
Snapshots: 0 total
Time: 5.468s
Ran all test suites.
若是测试代码写错,结果如下:
> lesson2@1.0.0 test
> jestFAIL ./math.test.js√ 测试加法 3 + 7 (6ms)√ 测试减法 6 - 3 (1ms)× 测试乘法 3 * 3 (7ms)● 测试乘法 3 * 3expect(received).toBe(expected) // Object.is equalityExpected: 3Received: 915 |16 | test('测试乘法 3 * 3', () => {> 17 | expect(multi(3,3)).toBe(3);| ^18 | });at Object.<anonymous> (math.test.js:17:22)Test Suites: 1 failed, 1 total
Tests: 1 failed, 2 passed, 3 total
Snapshots: 0 total
Time: 4.258s
Ran all test suites.
为什么
math
中的方法必须导出来呢?
因为 Jest 在前端项目中帮助我们完成两类内容:
- 单元测试(模块测试)
- 集成测试(多个模块测试)
因此必须要以模块的方式来使用
不论是按照 CommonJS 还是 Es Module 改造,都需要符合 Jest 才能进行自动化测试
但是这样的话在 html 文件中使用会产生报错:
Uncaught ReferenceError: module is not defined
可以小改造一下(math.js
):
...
try {module.exports = {add,minus,multi}
} catch (e) {}
这种报错一般是不会出现在项目中的,现在的项目基本都是模块化编码
4.Jest 的简单配置
jest 有默认配置,下面来自定义配置,在这之前需要生成配置文件,运行 npx jest --init
(Jest\lesson2\jest.config.js
完整如下) :
// For a detailed explanation regarding each configuration property, visit:
// https://jestjs.io/docs/en/configuration.htmlmodule.exports = {// All imported modules in your tests should be mocked automatically// automock: false,// Stop running tests after `n` failures// bail: 0,// Respect "browser" field in package.json when resolving modules// browser: false,// The directory where Jest should store its cached dependency information// cacheDirectory: "C:\\Users\\AImooc-Oliver\\AppData\\Local\\Temp\\jest",// Automatically clear mock calls and instances between every testclearMocks: true,// Indicates whether the coverage information should be collected while executing the test// collectCoverage: false,// An array of glob patterns indicating a set of files for which coverage information should be collected// collectCoverageFrom: null,// The directory where Jest should output its coverage filescoverageDirectory: "coverage",// An array of regexp pattern strings used to skip coverage collection// coveragePathIgnorePatterns: [// "\\\\node_modules\\\\"// ],// A list of reporter names that Jest uses when writing coverage reports// coverageReporters: [// "json",// "text",// "lcov",// "clover"// ],// An object that configures minimum threshold enforcement for coverage results// coverageThreshold: null,// A path to a custom dependency extractor// dependencyExtractor: null,// Make calling deprecated APIs throw helpful error messages// errorOnDeprecated: false,// Force coverage collection from ignored files using an array of glob patterns// forceCoverageMatch: [],// A path to a module which exports an async function that is triggered once before all test suites// globalSetup: null,// A path to a module which exports an async function that is triggered once after all test suites// globalTeardown: null,// A set of global variables that need to be available in all test environments// globals: {},// The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.// maxWorkers: "50%",// An array of directory names to be searched recursively up from the requiring module's location// moduleDirectories: [// "node_modules"// ],// An array of file extensions your modules use// moduleFileExtensions: [// "js",// "json",// "jsx",// "ts",// "tsx",// "node"// ],// A map from regular expressions to module names that allow to stub out resources with a single module// moduleNameMapper: {},// An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader// modulePathIgnorePatterns: [],// Activates notifications for test results// notify: false,// An enum that specifies notification mode. Requires { notify: true }// notifyMode: "failure-change",// A preset that is used as a base for Jest's configuration// preset: null,// Run tests from one or more projects// projects: null,// Use this configuration option to add custom reporters to Jest// reporters: undefined,// Automatically reset mock state between every test// resetMocks: false,// Reset the module registry before running each individual test// resetModules: false,// A path to a custom resolver// resolver: null,// Automatically restore mock state between every test// restoreMocks: false,// The root directory that Jest should scan for tests and modules within// rootDir: null,// A list of paths to directories that Jest should use to search for files in// roots: [// "<rootDir>"// ],// Allows you to use a custom runner instead of Jest's default test runner// runner: "jest-runner",// The paths to modules that run some code to configure or set up the testing environment before each test// setupFiles: [],// A list of paths to modules that run some code to configure or set up the testing framework before each test// setupFilesAfterEnv: [],// A list of paths to snapshot serializer modules Jest should use for snapshot testing// snapshotSerializers: [],// The test environment that will be used for testing// testEnvironment: "jest-environment-jsdom",// Options that will be passed to the testEnvironment// testEnvironmentOptions: {},// Adds a location field to test results// testLocationInResults: false,// The glob patterns Jest uses to detect test files// testMatch: [// "**/__tests__/**/*.[jt]s?(x)",// "**/?(*.)+(spec|test).[tj]s?(x)"// ],// An array of regexp pattern strings that are matched against all test paths, matched tests are skipped// testPathIgnorePatterns: [// "\\\\node_modules\\\\"// ],// The regexp pattern or array of patterns that Jest uses to detect test files// testRegex: [],// This option allows the use of a custom results processor// testResultsProcessor: null,// This option allows use of a custom test runner// testRunner: "jasmine2",// This option sets the URL for the jsdom environment. It is reflected in properties such as location.href// testURL: "http://localhost",// Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout"// timers: "real",// A map from regular expressions to paths to transformers// transform: null,// An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation// transformIgnorePatterns: [// "\\\\node_modules\\\\"// ],// An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them// unmockedModulePathPatterns: undefined,// Indicates whether each individual test should be reported during the run// verbose: null,// An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode// watchPathIgnorePatterns: [],// Whether to use watchman for file crawling// watchman: true,
};
常见的配置里面都有,可以按需求选择注释或放开
- 运行
npx jest --coverage
可以查看覆盖率
PASS ./math.test.js√ 测试加法 3 + 7 (13ms)√ 测试减法 6 - 3 (1ms)√ 测试乘法 3 * 3 (1ms)----------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |math.js | 100 | 100 | 100 | 100 | |
----------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 3 passed, 3 total
Snapshots: 0 total
Time: 4.569s
Ran all test suites.
不仅在控制台有,在根目录也生成了相应文件:
.
|-- clover.xml
|-- coverage-final.json
|-- lcov-report
| |-- base.css
| |-- block-navigation.js
| |-- index.html
| |-- math.js.html
| |-- prettify.css
| |-- prettify.js
| |-- sort-arrow-sprite.png
| `-- sorter.js
`-- lcov.info1 directory, 11 files
Jest/lesson2/coverage/lcov-report/index.html
可以直接访问:
可以修改配置 package.json
:
{..."scripts": {"coverage": "jest --coverage"},...
}
之后运行 npm run coverage
,也是一样的效果
修改
Jest\lesson2\jest.config.js
中的coverageDirectory
可以指定生成目录名称
一般前端项目中都是使用 ESModule 的语法,按 ESModule 改一下:
math.js
function add(a,b) {return a + b;
}function minus(a,b) {return a - b;
}function multi(a,b) {return a * b;
}export {add,minus,multi
}
math.test.js
import {add,minus,multi
} from './math'test('测试加法 3 + 7', () => {expect(add(3,3)).toBe(6);
});test('测试减法 6 - 3', () => {expect(minus(6,3)).toBe(3);
});test('测试乘法 3 * 3', () => {expect(multi(3,3)).toBe(9);
});
改完代码之后,运行 jest 会有报错产生,这是因为 jest 是运行在 node 环境,并不能直接识别 ESModule 的语法,这就要用到 babel 了
安装 babel 相关依赖:
npm i @babel/core@7.4.5 @babel/preset-env@7.4.5 -D
在根目录新建 babel 配置文件 .babelrc
{"presets": [["@babel/preset-env", {"targets": {"node": "current"}}]]
}
再次运行 jest ,成功!
jest 运行底层机制:
- npm run jest
- jest (babel-jest)
- babel-core
- 取 .babelrc 配置
- 在运行测试之前,结合 babel,先把代码做一次转化
- 运行转化过的测试用例代码
- Jest中文文档 | Jest中文网 · 🃏 Jest - 令人愉快的 JavaScript 测试框架
本文仅作记录, 实战要点待后续专文总结,敬请期待。。。
相关文章:

【实战】一、Jest 前端自动化测试框架基础入门(一) —— 前端要学的测试课 从Jest入门到TDD BDD双实战(一)
文章目录 一、前端要学的测试课1.前端要学的测试2.前端工程化的一部分3.前端自动化测试的例子4.前端为什么需要自动化测试?5.课程涵盖内容6.前置技能7.学习收获 二、Jest 前端自动化测试框架基础入门1. 自动化测试背景及原理前端自动化测试产生的背景及原理 2.前端自…...

蓝桥杯Java组备赛(二)
题目1 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int n sc.nextInt();int max Integer.MIN_VALUE;int min Integer.MAX_VALUE;double sum 0;for(int i0;i<n;i) {int x sc.nextInt()…...

人力资源智能化管理项目(day10:首页开发以及上线部署)
学习源码可以看我的个人前端学习笔记 (github.com):qdxzw/humanResourceIntelligentManagementProject 首页-基本结构和数字滚动 安装插件 npm i vue-count-to <template><div class"dashboard"><div class"container"><!-- 左侧内…...

Conda管理Python不同版本教程
Conda管理Python不同版本教程 目录 0.前提 1.conda常用命令 2.conda设置国内源(以添加清华源为例,阿里云源同样) 3.conda管理python库 4.其它 不太推荐 pyenv管理Python不同版本教程(本人另一篇博客,姊妹篇&…...

free pascal:fpwebview 组件通过 JSBridge 调用本机TTS
从 https://github.com/PierceNg/fpwebview 下载 fpwebview-master.zip 简单易用。 先请看 \fpwebview-master\README.md cd \lazarus\projects\fpwebview-master\demo\js_bidir 学习 js_bidir.lpr ,编写 js_bind_speak.lpr 如下,通过 JSBridge 调用本…...

数据结构——单链表专题
目录 1. 链表的概念及结构2. 实现单链表初始化尾插头插尾删头删查找在指定位置之前插入数据在指定位置之后插入数据删除指定位之前的节点删除指定位置之后pos节点销毁链表 3. 完整代码test.cSList.h 4. 链表的分类 1. 链表的概念及结构 在顺序表中存在一定的问题: …...

Linux:开源世界的王者
在科技世界中,Linux犹如一位低调的王者,统治着开源世界的半壁江山。对于许多技术爱好者、系统管理员和开发者来说,Linux不仅仅是一个操作系统,更是一种信仰、一种哲学。 一、开源的魅力 Linux的最大魅力在于其开源性质。与封闭的…...

⭐北邮复试刷题103. 二叉树的锯齿形层序遍历 (力扣每日一题)
103. 二叉树的锯齿形层序遍历 给你二叉树的根节点 root ,返回其节点值的 锯齿形层序遍历 。(即先从左往右,再从右往左进行下一层遍历,以此类推,层与层之间交替进行)。 示例 1:输入:…...

文件上传漏洞--Upload-labs--Pass07--点绕过
一、什么是点绕过 在Windows系统中,Windows特性会将文件后缀名后多余的点自动删除,在网页源码中,通常使用 deldot()函数 对点进行去除,若发现网页源代码中没有 deldot() 函数,则可能存在 点绕过漏洞。通过点绕过漏洞&…...
MySQL高级特性篇(1)-JSON数据类型的应用
MySQL是一种常用的关系型数据库管理系统,它提供了多种数据类型,其中包括JSON数据类型。JSON(JavaScript Object Notation)是一种常用的数据交换格式,它以键值对的形式组织数据,并支持嵌套和数组结构。MySQL…...

如何用Qt实现一个无标题栏、半透明、置顶(悬浮)的窗口
在Qt框架中,要实现一个无标题栏、半透明、置顶(悬浮)的窗口,需要一些特定的设置和技巧。废话不多说,下面我将以DrawClient软件为例,介绍一下实现这种效果的四个要点。 要点一:移除标题栏&#…...

ViT: transformer在图像领域的应用
文章目录 1. 概要2. 方法3. 实验3.1 Compare with SOTA3.2 PRE-TRAINING DATA REQUIREMENTS3.3 SCALING STUDY3.4 自监督学习 4. 总结参考 论文: An Image is Worth 16x16 Words: Transformers for Image Recognition at Scale 代码:https://github.com…...

Sora 的工作原理(及其意义)
原文:How Sora Works (And What It Means) 作者: DAN SHIPPER OpenAI 的新型文本到视频模型为电影制作开启了新篇章 DALL-E 提供的插图。 让我们先明确一点,我们不会急急忙忙慌乱。我们不会预测乌托邦或预言灾难。我们要保持冷静并... 你…...
Java学习笔记2024/2/16
知识点 面向对象 题目1(完成) 定义手机类,手机有品牌(brand),价格(price)和颜色(color)三个属性,有打电话call()和sendMessage()两个功能。 请定义出手机类,类中要有空参、有参构造方法,set/get方法。 …...
XLNet做文本分类
import torch from transformers import XLNetTokenizer, XLNetForSequenceClassification from torch.utils.data import DataLoader, TensorDataset # 示例文本数据 texts ["This is a positive example.", "This is a negative example.", "Anot…...

Swift 5.9 新 @Observable 对象在 SwiftUI 使用中的陷阱与解决
概览 在 Swift 5.9 中,苹果为我们带来了全新的可观察框架 Observation,它是观察者开发模式在 Swift 中的一个全新实现。 除了自身本领过硬以外,Observation 框架和 SwiftUI 搭配起来也能相得益彰,事倍功半。不过 Observable 对象…...

分享一个学英语的网站
名字叫:公益大米网 Freerice 这个网站是以做题的形式来记忆单词,题干是一个单词,给出4个选项,需要选出其中最接近题干单词的选项。 答对可以获得10粒大米,网站的创办者负责捐赠。如图 触发某些条件&a…...

【动态规划】【C++算法】2742. 给墙壁刷油漆
作者推荐 【数位dp】【动态规划】【状态压缩】【推荐】1012. 至少有 1 位重复的数字 本文涉及知识点 动态规划汇总 LeetCode2742. 给墙壁刷油漆 给你两个长度为 n 下标从 0 开始的整数数组 cost 和 time ,分别表示给 n 堵不同的墙刷油漆需要的开销和时间。你有…...

【后端高频面试题--设计模式上篇】
🚀 作者 :“码上有前” 🚀 文章简介 :后端高频面试题 🚀 欢迎小伙伴们 点赞👍、收藏⭐、留言💬 往期精彩内容 【后端高频面试题–设计模式上篇】 【后端高频面试题–设计模式下篇】 【后端高频…...
P3141 [USACO16FEB] Fenced In P题解
题目 如果此题数据要小一点,那么我们可以用克鲁斯卡尔算法通过,但是这个数据太大了,空间会爆炸,时间也会爆炸。 我们发现,如果用 MST 做,那么很多边的边权都一样,我们可以整行整列地删除。 我…...

MFC内存泄露
1、泄露代码示例 void X::SetApplicationBtn() {CMFCRibbonApplicationButton* pBtn GetApplicationButton();// 获取 Ribbon Bar 指针// 创建自定义按钮CCustomRibbonAppButton* pCustomButton new CCustomRibbonAppButton();pCustomButton->SetImage(IDB_BITMAP_Jdp26)…...

《从零掌握MIPI CSI-2: 协议精解与FPGA摄像头开发实战》-- CSI-2 协议详细解析 (一)
CSI-2 协议详细解析 (一) 1. CSI-2层定义(CSI-2 Layer Definitions) 分层结构 :CSI-2协议分为6层: 物理层(PHY Layer) : 定义电气特性、时钟机制和传输介质(导线&#…...
汇编常见指令
汇编常见指令 一、数据传送指令 指令功能示例说明MOV数据传送MOV EAX, 10将立即数 10 送入 EAXMOV [EBX], EAX将 EAX 值存入 EBX 指向的内存LEA加载有效地址LEA EAX, [EBX4]将 EBX4 的地址存入 EAX(不访问内存)XCHG交换数据XCHG EAX, EBX交换 EAX 和 EB…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲
文章目录 前言第一部分:体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分:体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题
【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要: 近期,在使用较新版本的OpenSSH客户端连接老旧SSH服务器时,会遇到 "no matching key exchange method found", "n…...

Selenium常用函数介绍
目录 一,元素定位 1.1 cssSeector 1.2 xpath 二,操作测试对象 三,窗口 3.1 案例 3.2 窗口切换 3.3 窗口大小 3.4 屏幕截图 3.5 关闭窗口 四,弹窗 五,等待 六,导航 七,文件上传 …...
腾讯云V3签名
想要接入腾讯云的Api,必然先按其文档计算出所要求的签名。 之前也调用过腾讯云的接口,但总是卡在签名这一步,最后放弃选择SDK,这次终于自己代码实现。 可能腾讯云翻新了接口文档,现在阅读起来,清晰了很多&…...
CSS | transition 和 transform的用处和区别
省流总结: transform用于变换/变形,transition是动画控制器 transform 用来对元素进行变形,常见的操作如下,它是立即生效的样式变形属性。 旋转 rotate(角度deg)、平移 translateX(像素px)、缩放 scale(倍数)、倾斜 skewX(角度…...

C++ 设计模式 《小明的奶茶加料风波》
👨🎓 模式名称:装饰器模式(Decorator Pattern) 👦 小明最近上线了校园奶茶配送功能,业务火爆,大家都在加料: 有的同学要加波霸 🟤,有的要加椰果…...
LangChain 中的文档加载器(Loader)与文本切分器(Splitter)详解《二》
🧠 LangChain 中 TextSplitter 的使用详解:从基础到进阶(附代码) 一、前言 在处理大规模文本数据时,特别是在构建知识库或进行大模型训练与推理时,文本切分(Text Splitting) 是一个…...