- 开发工具
- 数据科学
【免费下载链接】archived-desktop-app
The old electron based nteract notebook
@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.
也就是说,它输出的产物分为两类:
- Notebook 数据:以字符串、普通 JSON 对象、immutable 结构三种形态存在的样例 notebook;
- 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配置,支持以下字段:
| 配置项 | 类型 | 默认行为 | 作用 |
|---|---|---|---|
codeCellCount | number | 1(单代码单元格) | 最终 notebook 中的代码单元格总数(内部从monocellNotebook起始并追加count - 1个空代码单元格) |
markdownCellCount | number | 0 | 追加指定数量的空 markdown 单元格(将emptyMarkdownCell的cell_type显式置为"markdown") |
hideAll | boolean | false | 为所有单元格的metadata.jupyter.source_hidden置为true,模拟全部源码隐藏的 notebook |
saved | boolean | false | 为true时savedNotebook与当前 notebook 一致(模拟"已保存"状态);否则savedNotebook为emptyNotebook |
noFilename | boolean | false | 为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; }三个值得注意的实现细节:
- 起始状态是
monocellNotebook:它是@nteract/commutable提供的"仅含一个空代码单元格的新 notebook"(见 structures.ts),因此codeCellCount: 2实际得到 1 个初始单元格 + 1 个追加单元格; - kernelspec 被固定为
python2:默认构造的 notebook 元数据中kernelspec.name为"python2",测试时可据此断言与 kernel 相关行为; hideAll的隐藏语义:hideCells通过acc.setIn([id, "metadata", "jupyter", "source_hidden"], true)逐单元格写入jupyter.source_hidden元数据,这与 nteract 实际的"隐藏源码"功能元数据保持一致。
mockAppState 构造的完整状态
除了 notebook 内容,mockAppState还一次性构造了完整的运行时骨架(src/index.ts):
- kernel 通道:创建一对 RxJS
Subject(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
相关推荐
nteract 架构演进:@nteract/stateful-components 整合进 @nteract/notebook-app-component 的 Breaking Change 解析
nteract 架构演进:@nteract/stateful components 整合进 @nteract/notebook app component 的
开发工具数据科学nteract Mythic 架构实战:用 Myth 组合 Redux Actions、Reducers 与 Epics
nteract Mythic 架构实战:用 Myth 组合 Redux Actions、Reducers 与 Epics 本文档是 nteract 仓库中 My
开发工具数据科学5分钟把微信公众号变成RSS源:wewe-rss私有部署与内容聚合实战
5分钟把微信公众号变成RSS源:wewe rss私有部署与内容聚合实战 上周帮朋友搭个人信息站,最卡的一环是:公众号文章根本没有 RSS 入口,内容被锁死在微信
开发工具数据科学
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考