React从基础入门到高级实战:React 高级主题 - 测试进阶:从单元测试到端到端测试的全面指南
React 测试进阶:从单元测试到端到端测试的全面指南
引言
在2025年的React开发环境中,测试不仅是代码质量的保障,更是提升开发效率和用户体验的关键支柱。随着React应用的复杂性不断增加,高级测试技术——如端到端(E2E)测试、快照测试和视觉回归测试——已成为不可或缺的工具。对于有经验的开发者来说,掌握这些技术不仅能显著提高测试覆盖率,还能为项目带来更高的稳定性、可维护性和性能优化空间。
React凭借其灵活性和强大的生态系统,为开发者提供了多样化的测试工具和方法。本文将深入探讨React测试的高级主题,包括使用Cypress和Playwright进行E2E测试,测试涉及Context和Redux的复杂组件,以及快照测试和视觉回归测试的最佳实践。我们还将通过一个多页面应用的完整测试流程案例和一个为现有项目添加E2E测试的练习,帮助您将理论转化为实践。此外,本文特别推荐Cypress的调试体验,展示其如何助力高效测试开发。希望这篇内容丰富、技术深入的指南能为您提供实用且前瞻性的洞察!
一、端到端测试:Cypress 与 Playwright
端到端(E2E)测试通过模拟真实用户行为,验证应用的整体功能和流程,是确保系统健壮性的重要手段。Cypress和Playwright作为两款领先的E2E测试工具,各具特色,适合不同的场景。
1.1 Cypress:调试体验的标杆
Cypress以其卓越的调试体验和易用性深受React开发者喜爱。它运行在浏览器内部,提供实时反馈和强大的交互性。
安装与配置
在项目中安装Cypress:
npm install cypress --save-dev
在package.json
中添加启动脚本:
"scripts": {"cypress:open": "cypress open","cypress:run": "cypress run"
}
运行npm run cypress:open
即可启动Cypress测试运行器。
基本用法
以下是一个测试登录流程的示例:
describe('登录流程', () => {it('成功登录并跳转到仪表板', () => {cy.visit('/login');cy.get('input[name="username"]').type('admin');cy.get('input[name="password"]').type('password123');cy.get('button[type="submit"]').click();cy.url().should('include', '/dashboard');cy.get('h1').should('contain', '欢迎,admin');});
});
cy.visit
:导航到指定页面。cy.get
:选择DOM元素。cy.type
:模拟用户输入。cy.click
:触发点击事件。cy.url().should
:断言URL变化。cy.get().should
:验证页面内容。
高级功能
Cypress支持自定义命令以提高代码复用性。例如,定义一个登录命令:
Cypress.Commands.add('login', (username, password) => {cy.visit('/login');cy.get('input[name="username"]').type(username);cy.get('input[name="password"]').type(password);cy.get('button[type="submit"]').click();
});
使用自定义命令简化测试:
it('使用自定义命令登录', () => {cy.login('admin', 'password123');cy.url().should('include', '/dashboard');
});
调试体验
Cypress提供以下调试利器:
- 实时重载:修改测试代码后自动重新运行。
- 时间旅行:回溯测试的每一步,查看DOM快照和状态。
- 网络拦截:使用
cy.intercept
模拟API响应。
示例:拦截API请求:
it('拦截登录请求', () => {cy.intercept('POST', '/api/login', { statusCode: 200, body: { success: true } }).as('loginRequest');cy.visit('/login');cy.get('button[type="submit"]').click();cy.wait('@loginRequest');cy.url().should('include', '/dashboard');
});
1.2 Playwright:跨浏览器测试的利器
Playwright支持多浏览器(Chromium、Firefox、WebKit)测试,适合需要跨平台验证的场景。
安装与配置
安装Playwright:
npm install playwright --save-dev
基本用法
测试登录流程:
const { chromium } = require('playwright');describe('登录流程', () => {it('成功登录', async () => {const browser = await chromium.launch({ headless: false });const page = await browser.newPage();await page.goto('http://localhost:3000/login');await page.fill('input[name="username"]', 'admin');await page.fill('input[name="password"]', 'password123');await page.click('button[type="submit"]');await page.waitForURL('**/dashboard');expect(await page.textContent('h1')).toContain('欢迎,admin');await browser.close();});
});
page.goto
:导航到URL。page.fill
:填充表单字段。page.click
:模拟点击。page.waitForURL
:等待URL跳转。textContent
:验证文本内容。
高级功能
Playwright支持并行测试和截图功能:
it('截图验证', async () => {const browser = await chromium.launch();const page = await browser.newPage();await page.goto('http://localhost:3000/dashboard');await page.screenshot({ path: 'dashboard.png' });await browser.close();
});
场景分析
- Cypress:调试体验优越,适合快速迭代和单浏览器测试。
- Playwright:跨浏览器支持强大,适合复杂、多平台项目。
二、测试复杂组件:Context 与 Redux
测试涉及状态管理的复杂组件需要模拟其依赖的环境,例如Context和Redux。
2.1 测试Context组件
React的Context API常用于局部状态共享。使用@testing-library/react
的render
函数和wrapper
选项可以轻松测试。
示例
假设有一个使用Context的组件:
import { useContext } from 'react';
import { ThemeContext } from './ThemeContext';export default function ThemeDisplay() {const { theme } = useContext(ThemeContext);return <p>当前主题: {theme}</p>;
}
测试代码:
import { render, screen } from '@testing-library/react';
import ThemeDisplay from './ThemeDisplay';
import { ThemeContext } from './ThemeContext';test('渲染Context提供的主题', () => {const contextValue = { theme: 'dark' };render(<ThemeContext.Provider value={contextValue}><ThemeDisplay /></ThemeContext.Provider>);expect(screen.getByText('当前主题: dark')).toBeInTheDocument();
});
使用wrapper
简化:
test('使用wrapper渲染Context', () => {const wrapper = ({ children }) => (<ThemeContext.Provider value={{ theme: 'light' }}>{children}</ThemeContext.Provider>);render(<ThemeDisplay />, { wrapper });expect(screen.getByText('当前主题: light')).toBeInTheDocument();
});
注意事项
- 确保Context值与组件期望的结构一致。
- 测试边缘情况,如Context未提供时的默认值。
2.2 测试Redux组件
Redux用于全局状态管理,测试时需模拟Store。
示例
假设有一个计数器组件:
import { useSelector, useDispatch } from 'react-redux';export default function Counter() {const count = useSelector((state) => state.count);const dispatch = useDispatch();return (<div><p>计数: {count}</p><button onClick={() => dispatch({ type: 'INCREMENT' })}>增加</button></div>);
}
Reducer:
const initialState = { count: 0 };
export default function reducer(state = initialState, action) {switch (action.type) {case 'INCREMENT':return { ...state, count: state.count + 1 };default:return state;}
}
测试代码:
import { render, screen, fireEvent } from '@testing-library/react';
import { Provider } from 'react-redux';
import { configureStore } from '@reduxjs/toolkit';
import Counter from './Counter';
import reducer from './reducer';test('渲染Redux状态并触发动作', () => {const store = configureStore({reducer,preloadedState: { count: 5 },});render(<Provider store={store}><Counter /></Provider>);expect(screen.getByText('计数: 5')).toBeInTheDocument();fireEvent.click(screen.getByText('增加'));expect(screen.getByText('计数: 6')).toBeInTheDocument();
});
preloadedState
:设置初始状态。fireEvent
:模拟用户交互。
场景分析
- Context:适合小型、局部状态管理,测试简单。
- Redux:适合大型应用,测试需关注状态变化和动作分发。
三、快照测试与视觉回归测试
快照测试和视觉回归测试专注于UI一致性,是React测试的重要补充。
3.1 快照测试
Jest的快照测试捕获组件的渲染输出,用于检测意外变化。
示例
import { render } from '@testing-library/react';
import Button from './Button';test('按钮快照匹配', () => {const { container } = render(<Button>点击我</Button>);expect(container).toMatchSnapshot();
});
生成的快照文件(__snapshots__/Button.test.js.snap
):
exports[`按钮快照匹配 1`] = `
<div><button>点击我</button>
</div>
`;
更新快照
当UI有意变更时,运行jest -u
更新快照。
最佳实践
- 小范围使用:避免对大型组件树生成快照,易导致难以维护。
- 结合功能测试:快照测试不能替代行为验证。
3.2 视觉回归测试
视觉回归测试通过比较UI截图检测变化,常与Storybook和Chromatic结合使用。
配置Storybook
编写故事:
import Button from './Button';export default {title: 'Components/Button',component: Button,
};export const Primary = () => <Button>点击我</Button>;
配置Chromatic
安装Chromatic:
npm install --save-dev chromatic
运行测试:
npx chromatic --project-token=<your-token>
Chromatic会生成截图并比较差异。
示例工作流
- 提交初始UI到Chromatic。
- 修改
<Button>
样式后重新运行。 - 查看Chromatic报告中的视觉差异。
场景分析
- 快照测试:快速、轻量,适合单元级别。
- 视觉回归测试:直观、全面,适合整体UI验证。
四、测试最佳实践:TDD 与测试优先
测试驱动开发(TDD)和测试优先是提升代码质量和可测试性的核心方法。
4.1 TDD 流程
TDD遵循“红-绿-重构”循环:
- 红:编写失败的测试。
- 绿:实现最小代码使测试通过。
- 重构:优化代码而不改变行为。
示例
实现一个加法函数:
- 编写测试:
test('加法函数应返回两数之和', () => {expect(add(2, 3)).toBe(5);
});
- 实现代码:
function add(a, b) {return a + b;
}
- 重构(若需要):
function add(a, b) {return Number(a) + Number(b); // 确保输入为数字
}
4.2 测试优先
在编写组件前先写测试,确保实现符合预期。
示例
测试一个按钮组件:
- 编写测试:
import { render, screen } from '@testing-library/react';
import Button from './Button';test('渲染按钮并显示文本', () => {render(<Button>提交</Button>);expect(screen.getByText('提交')).toBeInTheDocument();
});
- 实现组件:
export default function Button({ children }) {return <button>{children}</button>;
}
场景分析
- TDD:适合逻辑复杂的业务代码。
- 测试优先:适合UI组件,确保功能直观实现。
五、案例:测试一个多页面应用的完整流程
通过一个多页面应用的测试案例,展示E2E测试的实际应用。
5.1 应用需求
- 页面:登录、仪表板、用户管理。
- 功能:登录后跳转仪表板,管理用户列表。
5.2 测试实现
登录测试
describe('登录流程', () => {it('成功登录并跳转到仪表板', () => {cy.visit('/login');cy.get('input[name="username"]').type('admin');cy.get('input[name="password"]').type('password123');cy.get('button[type="submit"]').click();cy.url().should('include', '/dashboard');cy.get('h1').should('contain', '欢迎,admin');});it('登录失败显示错误', () => {cy.visit('/login');cy.get('input[name="username"]').type('admin');cy.get('input[name="password"]').type('wrong');cy.get('button[type="submit"]').click();cy.get('.error').should('contain', '登录失败');});
});
用户管理测试
describe('用户管理', () => {beforeEach(() => {cy.login('admin', 'password123'); // 使用自定义命令cy.visit('/users');});it('添加新用户', () => {cy.get('button#add-user').click();cy.get('input[name="name"]').type('新用户');cy.get('input[name="email"]').type('newuser@example.com');cy.get('button[type="submit"]').click();cy.get('table').should('contain', '新用户');});it('删除用户', () => {cy.get('table tr:first-child .delete-btn').click();cy.get('table').should('not.contain', '新用户');});
});
自定义命令
在cypress/support/commands.js
中:
Cypress.Commands.add('login', (username, password) => {cy.visit('/login');cy.get('input[name="username"]').type(username);cy.get('input[name="password"]').type(password);cy.get('button[type="submit"]').click();
});
5.3 分析
- 流程覆盖:测试从登录到核心功能的完整用户旅程。
- 可维护性:
beforeEach
和自定义命令减少代码重复。 - 健壮性:涵盖成功和失败场景。
六、练习:为项目添加 E2E 测试
通过一个实践练习,掌握为现有项目添加E2E测试的技能。
6.1 项目需求
- 应用:包含注册和登录页面。
- 目标:测试注册和登录流程。
6.2 实现
注册测试
describe('注册流程', () => {it('成功注册新用户', () => {cy.visit('/register');cy.get('input[name="username"]').type('testuser');cy.get('input[name="password"]').type('testpass123');cy.get('input[name="confirm-password"]').type('testpass123');cy.get('button[type="submit"]').click();cy.url().should('include', '/login');cy.get('.success-message').should('contain', '注册成功');});it('密码不匹配时失败', () => {cy.visit('/register');cy.get('input[name="username"]').type('testuser');cy.get('input[name="password"]').type('testpass123');cy.get('input[name="confirm-password"]').type('wrongpass');cy.get('button[type="submit"]').click();cy.get('.error-message').should('contain', '密码不匹配');});
});
登录测试
describe('登录流程', () => {before(() => {// 前置注册用户cy.visit('/register');cy.get('input[name="username"]').type('testuser');cy.get('input[name="password"]').type('testpass123');cy.get('input[name="confirm-password"]').type('testpass123');cy.get('button[type="submit"]').click();});it('使用注册用户登录', () => {cy.visit('/login');cy.get('input[name="username"]').type('testuser');cy.get('input[name="password"]').type('testpass123');cy.get('button[type="submit"]').click();cy.url().should('include', '/dashboard');cy.get('h1').should('contain', '欢迎,testuser');});
});
6.3 分析
- 用户旅程:覆盖注册到登录的完整流程。
- 前置条件:使用
before
确保测试数据一致。 - 可扩展性:可添加更多边缘情况测试。
七、Cypress 的调试体验:效率提升的关键
Cypress的调试功能是其核心优势之一,为开发者提供了无与伦比的测试开发体验。
7.1 实时重载
- 自动运行:保存测试文件后,Cypress立即重新执行。
- 即时反馈:快速发现问题,提高迭代效率。
7.2 时间旅行调试
- 步骤回溯:点击测试中的任意步骤,查看当时的DOM状态和日志。
- 网络监控:检查请求和响应的详细信息。
示例:
it('检查网络请求', () => {cy.intercept('GET', '/api/users', { fixture: 'users.json' }).as('getUsers');cy.visit('/users');cy.wait('@getUsers').its('response.statusCode').should('eq', 200);
});
运行时,Cypress界面显示每一步的快照。
7.3 视频录制与失败复现
- 自动录制:测试失败时生成视频,便于问题复现。
- 配置:在
cypress.config.js
中启用:
module.exports = {video: true,videoCompression: 32,
};
场景分析
- 快速定位:时间旅行帮助快速找到失败原因。
- 团队协作:视频和日志便于共享问题。
八、未来趋势:2025年的测试展望
随着技术演进,React测试领域将迎来新趋势:
- AI辅助测试:AI生成测试用例并优化覆盖率。
- 无头浏览器:提升测试速度,降低资源消耗。
- 云测试平台:支持跨设备、跨浏览器测试。
- 开发集成:测试工具与IDE深度融合。
结语
React测试进阶技术为开发者提供了从单元测试到端到端测试的全面解决方案。Cypress和Playwright助力高效E2E测试,Context和Redux测试确保复杂组件的可靠性,快照与视觉回归测试保障UI一致性,而TDD与测试优先提升代码质量。通过案例和练习,您可以将这些技术应用于实际项目,打造更健壮的React应用。Cypress的调试体验更是锦上添花,让测试开发变得高效而愉悦。
相关文章:
React从基础入门到高级实战:React 高级主题 - 测试进阶:从单元测试到端到端测试的全面指南
React 测试进阶:从单元测试到端到端测试的全面指南 引言 在2025年的React开发环境中,测试不仅是代码质量的保障,更是提升开发效率和用户体验的关键支柱。随着React应用的复杂性不断增加,高级测试技术——如端到端(E2…...
Ansible 剧本精粹 - 编写你的第一个 Playbook
Ansible 剧本精粹 - 编写你的第一个 Playbook 如果说 Ansible Ad-Hoc 命令像是你对厨房里的助手发出的零散口头指令(“切个洋葱”、“烧开水”),那么 Playbook 就是一份完整、详细、写在纸上的菜谱。它列明了所有需要的“食材”(变量),详细的“烹饪步骤”(任务),甚至还…...

【Elasticsearch】Elasticsearch 核心技术(二):映射
Elasticsearch 核心技术(二):映射 1.什么是映射(Mapping)1.1 元字段(Meta-Fields)1.2 数据类型 vs 映射类型1.2.1 数据类型1.2.2 映射类型 2.实际运用案例案例 1:电商产品索引映射案…...

【计算机网络】网络层协议
1. ICMP协议的介绍及应用 IP协议的助手 —— ICMP 协议 ping 是基于 ICMP 协议工作的,所以要明白 ping 的工作,首先我们先来熟悉 ICMP 协议。 ICMP 全称是 Internet Control Message Protocol,也就是互联网控制报文协议。 里面有个关键词 …...
.NET Core接口IServiceProvider
.NET Core 接口 IServiceProvider 深度剖析 在 .NET Core 和 .NET 5 的世界里,依赖注入(Dependency Injection,简称 DI)是构建可维护、可测试应用程序的关键技术。而 IServiceProvider 接口,正是依赖注入机制中的核心…...

结构型设计模式之Proxy(代理)
结构型设计模式之Proxy(代理) 前言: 代理模式,aop环绕通知,动态代理,静态代理 都是代理的一种,这次主要是记录设计模式的代理demo案例,详情请看其他笔记。 1)意图 为其…...

案例分享--汽车制动卡钳DIC测量
制动系统是汽车的主要组成部分,是汽车的主要安全部件之一。随着车辆性能的不断提高,车速不断提升,对车辆的制动系统也随之提出了更高要求,因此了解车辆制动系统中每个部件的动态行为成为了制动系统优化的主要途径,同时…...

Redis Set集合命令、内部编码及应用场景(详细)
文章目录 前言普通命令SADDSMEMBERSSISMEMBERSCARDSPOPSMOVESREM 集合间操作SINTERSINTERSTORESUNIONSUNIONSTORESDIFFSDIFFSTORE 命令小结内部编码使用场景 前言 集合类型也是保存多个字符串类型的元素的,但和列表类型不同的是,集合中 1)元…...

C++算法动态规划1
DP定义: 动态规划是分治思想的延申,通俗一点来说就是大事化小,小事化无的艺术。 在将大问题化解为小问题的分治过程中,保存对这些小问题已经处理好的结果,并供后面处理更大规模的问题时直接使用这些结果。 动态规划具…...
【快速预览经典深度学习模型:CNN、RNN、LSTM、Transformer、ViT全解析!】
🚀快速预览经典深度学习模型:CNN、RNN、LSTM、Transformer、ViT全解析! 📌你是否还在被深度学习模型名词搞混?本文带你用最短时间掌握五大经典模型的核心概念和应用场景,助你打通NLP与CV的任督二脉…...

KaiwuDB在边缘计算领域的应用与优势
KaiwuDB 在边缘计算场景中主要应用于 工业物联网(IIoT)、智能电网、车联网 等领域,通过其分布式多模架构和轻量化设计,在边缘侧承担 数据实时处理、本地存储与协同分析 的核心作用。以下是具体案例和功能解析: 1. 典型…...
如何避免二极管过载?
如何避免二极管过载? 二极管作为电路中的基础元件,其过载可能导致性能下降甚至烧毁。以下从选型、安装、保护设计及散热四方面提供实用解决二极管过载方案: 精准选型匹配需求 根据电路特性选择二极管类型:高频电路优先选用肖特基…...
Vue.js组件开发系统性指南
结合核心概念、最佳实践及性能优化策略,帮助您构建高效可维护的组件体系: 一、组件基础与核心结构 1.单文件组件(SFC)组织 模板:使用<template>定义HTML结构,遵循单根元素原则。 逻辑:在<script>中通过export default导出组件选项(数据、方法、生命周期钩…...
React---day9
11、css 11.1 styled的基本使用 CSS-in-JS的模式就是一种将样式(CSS)也写入到JavaScript中的方式,并且可以方便的使用JavaScript的状态; npm add styled-componentsconst Title styled.h1font-size: 1.5em;text-align: center…...
设计模式 - 模板方法模式
该模式将定义一个操作中的算法骨架,并将算法的一些步骤延迟到子类中实现,使得子类可以在不改变算法结构的情况下重定义算法的某些特定步骤。 例如,炒菜的步骤是固定的,具体可分为倒油、热油、倒蔬菜、倒调料品、翻炒等。通过模板…...

鸿蒙开发List滑动每项标题切换悬停
鸿蒙开发List滑动每项标题切换悬停 鸿蒙List滑动每项标题切换悬停,功能也很常见 一、效果图: 二、思路: ListItemGroup({ header: this.itemHead(secondClassify, index) }) 三、关键代码: build() {Column() {List() {ListIt…...

ubuntu开机自动挂载windows下的硬盘
我是ubuntu和windows的双系统开发,在ubuntu下如果想要访问windows的硬盘,需要手动点击硬盘进行挂载,这个硬盘我每次编译完都会使用,所以用下面的步骤简化操作,让系统每次开机后自动挂载。 第一步. 确定硬盘的设备标识…...
C# 实现软件开机自启动(不需要管理员权限)
本文参考C#/WPF/WinForm/程序实现软件开机自动启动的两种常用方法,将里面中的第一种方法做了封装成AutoStart类,使用时直接两三行代码就可以搞定。 自启动的原理是将软件的快捷方式创建到计算机的自动启动目录下(不需要管理员权限࿰…...

使用 Golang `testing/quick` 包进行高效随机测试的实战指南
使用 Golang testing/quick 包进行高效随机测试的实战指南 Golang testing/quick 包概述testing/quick 包的功能和用途为什么选择 testing/quick 进行测试快速入门:基本用法导入 testing/quick 包基本使用示例:快速生成测试数据quick.Check 和 quick.Val…...

32 C 语言字符处理函数详解:isalnum、isalpha、iscntrl、isprint、isgraph、ispunct、isspace
1 isalnum() 函数 1.1 函数原型 #include <ctype.h>int isalnum(int c); 1.2 功能说明 isalnum() 函数用于检查传入的整数参数是否为 ASCII 编码的字母或数字字符(A - Z、a - z、0 - 9,对应 ASCII 值 65 - 90、97 - 122、48 - 57)。…...

Qt实现一个悬浮工具箱源码分享
一、效果展示 二、源码分享 hoverToolboxWidget.h #ifndef HOVERTOOLBOXWIDGET_H #define HOVERTOOLBOXWIDGET_H#include <QWidget> #include <QMouseEvent> #include <QPropertyAnimation> #include <QStyleOption> #include <QPainter>namespa…...

线夹金具测温在线监测装置:电力设备安全运行的“隐形卫士”
在电网系统中,线夹金具是连接导线与输电塔架的关键部件,其运行状态直接影响电力传输的稳定性。传统人工巡检方式存在效率低、盲区多、数据滞后等问题,而线夹金具测温在线监测装置的普及,正为电力设备运维带来革新。 一、工作原理&…...

《TCP/IP 详解 卷1:协议》第4章:地址解析协议
ARP 协议 地址解析协议(ARP, Address Resolution Protocol)是IPv4协议栈中一个关键的组成部分,用于在网络层的IP地址与数据链路层的硬件地址(如MAC地址)之间建立映射关系。它的主要任务是: 将32位的IPv4地…...
Dify 离线升级操作手册(适用于无外网企业内网环境)
一、准备工作 准备一台能访问互联网的外网机器 用于拉取最新的 Dify 镜像和代码建议使用 Linux 或 Windows Docker 环境 准备传输介质 U盘、移动硬盘,或企业内部网络共享路径 确认当前内网 Dify 版本和配置 确认版本号,备份配置文件和数据库 二、外…...

Windows下运行Redis并设置为开机自启的服务
下载Redis-Windows 点击redis-windows-7.4.0下载链接下载Redis 解压之后得到如下文件 右键install_redis.cmd文件,选择在记事本中编辑。 将这里改为redis.windows.conf后保存,退出记事本,右键后选择以管理员身份运行。 在任务管理器中能够…...

网络编程之网络基础
基础理论:IP、子网掩码、端口号、字节序、网络基础模型、传输协议 socket:TCP、UDP、广播、组播、抓包工具的使用、协议头、并发服务器 Modbus协议 、HTTP协议、HTML、 分析服务器 源码、数据库 一、认识网络 网络:实现多设备通信 二、IP地址…...

Spring AI(11)——SSE传输的MCP服务端
WebMVC的服务器传输 支持SSE(Server-Sent Events) 基于 Spring MVC 的服务器传输和可选的STDIO运输 导入jar <dependency><groupId>org.springframework.ai</groupId><artifactId>spring-ai-starter-mcp-server-webmvc</a…...

计算机网络备忘录
计算机网络 - 网络互联与互联网 计算机网络重点学习本章,属于核心知识 包含网络层和传输层 的 相关协议 计算机网络层次重点掌握网络层与传输层。其中网络层主要是IP协议,解决主机-主机通信,传输层主要是TCP/UDP 协议,解决应用-…...

Spring Boot论文翻译防丢失 From船长cap
本文内容 微服务 微服务风格的特性组件化(Componentization )与服务(Services)围绕业务功能的组织产品不是项目强化终端及弱化通道分散治理分散数据管理基础设施自动化容错性设计设计改进 微服务是未来吗其它 微服务系统多大微…...
[蓝桥杯]最优包含
最优包含 题目描述 我们称一个字符串 SS 包含字符串 TT 是指 TT 是 SS 的一个子序列,即可以从字符串 SS 中抽出若干个字符,它们按原来的顺序组合成一个新的字符串与 TT 完全一样。 给定两个字符串 SS 和 TT,请问最少修改 SS 中的多少个字符…...