news 2026/10/10 9:06:25

nteract 测试脚手架实战:用 @nteract/fixtures 构建可复用的 Notebook Redux 状态与样例数据

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
nteract 测试脚手架实战:用 @nteract/fixtures 构建可复用的 Notebook Redux 状态与样例数据
  • 开发工具
  • 数据科学

【免费下载链接】archived-desktop-app

The old electron based nteract notebook

项目地址:https://gitcode.com/gh_mirrors/nt/archived-desktop-app
点击查看免费下载

@nteract/fixtures是 nteract 生态中专为测试场景设计的包,它同时提供结构化的内存型(immutable)Notebook 样例数据与可直接接入 Redux 的完整 mock 应用状态,让开发者无需手工构造复杂的DocumentRecord、kernel 通道与 entities 层级,即可快速搭建"开箱即用"的测试环境。读完本文,你将掌握fixtureStore/mockAppState的全部配置项语义、immutable 与字符串两种 fixture 的差异,以及如何在 epics、组件与 reducer 测试中直接复用这套脚手架。

包定位:为测试套件而生的一行式脚手架

在 nteract 的 monorepo 中,packages/fixtures 的官方定位非常明确:

This package contains fixtures for immutable and string notebooks for use in nteract test suites.

也就是说,它输出的产物分为两类:

  1. Notebook 数据:以字符串、普通 JSON 对象、immutable 结构三种形态存在的样例 notebook;
  2. Redux 状态:包含 notebook 内容、kernel 通道(RxJS Subject)、comms、contents、kernels 等完整 entity 的AppState,以及基于它创建的 ReduxStore。

从包结构看,核心实现集中在两个文件:

  • src/index.ts:mockAppState、fixtureStore及配置解析逻辑;
  • src/fixture-nb.ts:fixture、fixtureJSON、fixtureCommutable及更大的bigfixture系列。

包的依赖(见 package.json)为@nteract/commutable、@nteract/reducers与@nteract/types,这决定了它生成的 store 与生产环境使用同一套数据模型和 reducer,从而保证测试状态与真实运行时状态的结构一致性。

安装

$ yarn add @nteract/fixtures
$ npm install --save @nteract/fixtures

注意:该包面向测试环境,建议安装在devDependencies中;由于它内部依赖@nteract/commutable、@nteract/reducers、@nteract/types等包,安装时会一并解析这些依赖。

核心用法:一行代码创建带两个代码单元格的 Redux store

README 给出了最典型的使用场景——创建一个包含两个代码单元格的 Redux store:

import { fixtureStore } from "@nteract/fixtures"; export default () => { const testStore = fixtureStore({ codeCellCount: 2 }); return testStore; };

fixtureStore(config)的内部实现(见 src/index.ts)非常直接:先用mockAppState(config)生成初始AppState,再通过createStore(rootReducer, initialAppState)创建真实的 Redux store。其中根 reducer 由两部分组合而成(src/index.ts):

const rootReducer = combineReducers({ app: (state = makeAppRecord()) => state, core });
  • app:直接使用makeAppRecord()默认值(mockAppState会额外注入githubToken: "TOKEN");
  • core:完整复用@nteract/reducers的 core reducer。

这意味着测试中 dispatch 的 action 会走与生产完全一致的 reducer 管线,适合编写 epics 集成测试、组件交互测试等。

mockAppState 配置参数全解析

与 README 中仅出现的codeCellCount不同,源码注释与实现(src/index.ts)揭示了更完整的配置面。mockAppState(config)接受一个JSONObject配置,支持以下字段:

配置项类型默认行为作用
codeCellCountnumber1(单代码单元格)最终 notebook 中的代码单元格总数(内部从monocellNotebook起始并追加count - 1个空代码单元格)
markdownCellCountnumber0追加指定数量的空 markdown 单元格(将emptyMarkdownCell的cell_type显式置为"markdown")
hideAllbooleanfalse为所有单元格的metadata.jupyter.source_hidden置为true,模拟全部源码隐藏的 notebook
savedbooleanfalse为true时savedNotebook与当前 notebook 一致(模拟"已保存"状态);否则savedNotebook为emptyNotebook
noFilenamebooleanfalse为true时filepath为空字符串;否则为"dummy-store-nb.ipynb"

其中 notebook 的构造逻辑(src/index.ts)要点如下:

function buildFixtureNotebook(config: JSONObject) { let notebook = monocellNotebook.setIn( ["metadata", "kernelspec", "name"], "python2" ); if (config) { if (config.codeCellCount) { for (let i = 1; i < config.codeCellCount; i++) { notebook = appendCellToNotebook(notebook, emptyCodeCell); } } if (config.markdownCellCount) { for (let i = 0; i < config.markdownCellCount; i++) { notebook = appendCellToNotebook( notebook, emptyMarkdownCell.set("cell_type", "markdown") ); } } if (config.hideAll) { notebook = hideCells(notebook); } } return notebook; }

三个值得注意的实现细节:

  1. 起始状态是monocellNotebook:它是@nteract/commutable提供的"仅含一个空代码单元格的新 notebook"(见 structures.ts),因此codeCellCount: 2实际得到 1 个初始单元格 + 1 个追加单元格;
  2. kernelspec 被固定为python2:默认构造的 notebook 元数据中kernelspec.name为"python2",测试时可据此断言与 kernel 相关行为;
  3. hideAll的隐藏语义:hideCells通过acc.setIn([id, "metadata", "jupyter", "source_hidden"], true)逐单元格写入jupyter.source_hidden元数据,这与 nteract 实际的"隐藏源码"功能元数据保持一致。

mockAppState 构造的完整状态

除了 notebook 内容,mockAppState还一次性构造了完整的运行时骨架(src/index.ts):

  • kernel 通道:创建一对 RxJSSubject(frontendToShell/shellToFrontend),并通过Subject.create组装成 mock 的 kernel 消息通道,状态中的 kernel 为makeRemoteKernelRecord,status为KernelStatus.NotConnected;
  • 引用体系:通过createKernelRef()/createContentRef()生成合法的 kernel/content 引用 ID,并正确关联到DocumentRecord.kernelRef;
  • entities 层级:依次构造comms、contents.byRef、kernels.byRef三个 record,contents.byRef中挂载makeNotebookContentRecord,其model为makeDocumentRecord;
  • 单元格焦点:当codeCellCount > 1时,cellFocused会被设置为 cellOrder 中的第 2 个单元格(索引 1),便于测试"焦点在指定单元格"的交互场景。

数据型 fixture:字符串、JSON 与 immutable 三种形态

src/index.ts第 9 行将 fixture-nb.ts 中的三个导出透传出去:

export { fixtureCommutable, fixture, fixtureJSON } from "./fixture-nb";

fixture / fixtureJSON / fixtureCommutable

  • fixture:一个完整的 nbformat 4 notebookJSON 字符串,包含一个 markdown 单元格和一个带真实输出的代码单元格(含display_data类型的 HTML 输出与execute_result),语言信息为 Python 3(codemirror_modeipython/3);
  • fixtureJSON:对fixture执行JSON.parse得到的普通对象,适合需要直接操作 plain object 的断言场景,例如 epics 测试中用stringifyNotebook(fixtureJSON)校验序列化结果(见 contents.spec.ts);
  • fixtureCommutable:通过fromJS(fixtureJSON)转换为@nteract/commutable的 immutable Notebook,可直接与ImmutableNotebook类型交互。

三者共享同一份数据,只是形态不同,可按断言需要自由切换。

bigfixture 系列:更接近真实的"大"notebook

fixture-nb.ts 额外提供了bigfixtureJSON/bigfixtureCommutable/bigfixture三个导出,其内容包含 10 个单元格:markdown 说明、纯代码、带 HTML 输出的execute_result(一段由 Python 生成的柱状图 HTML)、空代码单元格与空 markdown 单元格等,元数据上还覆盖了trusted、collapsed、outputHidden、inputHidden等字段,适合验证复杂渲染与富输出处理的场景。这三个导出与fixture系列为同构的字符串/对象/immutable 三元组(bigfixture为JSON.stringify(bigfixtureJSON))。

在真实测试中的使用方式

从源码检索来看,@nteract/fixtures在整个 monorepo 的测试中承担了"标准状态工厂"的角色,覆盖 epics、状态化组件、连接组件与 reducer 测试:

1. 直接使用mockAppState构造状态快照

在 map-to-execute.spec.ts 中,用mockAppState({ codeCellCount: 2 })获取两个代码单元格的完整状态;cell.spec.tsx 则用codeCellCount: 3的状态渲染单元格组件并断言交互行为。

2. 使用fixtureStore驱动真实 Redux 流

cell-creator.spec.tsx 多次调用fixtureStore()(不带参数,即默认单代码单元格),随后向 store dispatch action 并配合组件测试工具验证 UI 响应——这正是 README 示例在生产测试中的典型落地方式。

3. 组合fixtureJSON做数据断言

contents.spec.ts 中,fixtureJSON被直接用于与后端序列化/反序列化结果做深度比较,验证内容保存与加载链路的正确性。

此外,mockAppState还被 selectors、reducers(notebook.spec.ts)等多处测试引用,说明它已成为 nteract 测试体系里构建AppState的事实标准入口。

使用建议与边界说明

  • 默认值语义:不传任何配置调用fixtureStore()时,得到的是含 1 个空代码单元格、kernelspec.name = "python2"、filepath = "dummy-store-nb.ipynb"、kernel 状态为NotConnected的 store,适合绝大多数"只需要一个合法 notebook 状态"的测试;
  • 关注点差异:需要"能 dispatch、能驱动 UI"的完整环境用fixtureStore;只需要"一个状态对象"做纯函数断言时用mockAppState;需要"特定 notebook 数据"参与序列化、渲染等断言时用fixture/fixtureJSON/fixtureCommutable;
  • 不做生产依赖:包内包含大量 mock 语义(如固定的"TOKEN"githubToken、NotConnected的 kernel 状态),仅适用于测试环境,不应在生产代码中 import。

小结

@nteract/fixtures以极小的 API 面(fixtureStore、mockAppState加一组数据型 fixture)封装了 nteract 测试中最繁琐的状态构建工作:完整的 entities 层级、RxJS kernel 通道、immutable notebook 与真实 reducer 管线。无论是编写 epics 集成测试、组件交互测试,还是对 notebook 数据进行序列化断言,它都提供了一套与生产代码同构、可一行调用的标准起点——这也是它被 packages/epics、packages/stateful-components、packages/notebook-app-component 等多个包测试广泛依赖的根本原因。

  • 开发工具
  • 数据科学

【免费下载链接】archived-desktop-app

The old electron based nteract notebook

项目地址:https://gitcode.com/gh_mirrors/nt/archived-desktop-app
点击查看免费下载
上一篇:brpc 服务端推送(Server Push)实现指南:远程事件与 Restful 回调两种模式
下一篇:Argo Workflows 静态代码分析与安全扫描实践:golangci-lint、ESLint 与 Snyk 的多层质量防线

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/10 9:05:11

手机投屏到电脑还能听声音?scrcpy 音频转发配置实战

手机投屏到电脑还能听声音&#xff1f;scrcpy 音频转发配置实战 【免费下载链接】scrcpy Display and control your Android device 项目地址: https://gitcode.com/GitHub_Trending/sc/scrcpy 开会时想把手机里的 App 演示给同事看&#xff0c;还希望对方能听到 App 内…

作者头像 李华
网站建设 2026/10/10 9:04:48

DeepSeek提升自动化测试效率:用例生成、失败分析与AI维护实战

搞自动化测试这些年&#xff0c;我最大的感受就是&#xff1a;用例维护比写用例累十倍&#xff0c;断言写不好等于白测&#xff0c;环境一崩全队emo。所以当 DeepSeek 这类 AI 工具开始把编程能力拉到接近普通工程师水平之后&#xff0c;我第一反应不是拿它写业务代码&#xff…

作者头像 李华
网站建设 2026/10/10 9:04:40

Rust 安全审计之 STRCMP 缺陷识别:string-comparison-finder 指南

AI 技能AI 插件应用安全网络安全AI 评测 【免费下载链接】skills Trail of Bits Claude Code skills for security research, vulnerability detection, and audit workflows 项目地址&#xff1a; https://gitcode.com/gh_mirrors/skills8/skills 点击查看 免费下载 导读 本…

作者头像 李华