Lark/飞书 CLI Slides 域 E2E 测试覆盖指南:7 个叶命令的 100% 覆盖设计与验证策略
CLIAI 技能【免费下载链接】cliThe official Lark/飞书 CLI tool, maintained by the larksuite team — built for humans and AI Agents. Covers core business domains including Messenger, Docs, Base, Sheets, Calendar, Mail, Tasks, Meetings, and more, with 200 commands and 20 AI Agent Skills.项目地址https://gitcode.com/gh_mirrors/cli414/cli点击查看免费下载本篇技术指南围绕 tests/cli_e2e/slides/coverage.md 展开系统梳理 lark-cli 中 Slides幻灯片域的端到端E2E测试覆盖矩阵7 个叶命令全部覆盖、dry-run 层与 live 层双轨验证、错误信封与结构化输出的断言方式。读完本文你将理解为什么 slides 的命令测试必须跑在真实二进制这一层以及create、add-slide、update-slide、replace-slide、media-upload、media-download各自的覆盖要点与尚未覆盖的边界。覆盖矩阵总览根据 coverage.md 的 Metrics 小节Slides 域共有7 个叶命令leaf commands已覆盖 7 个覆盖率为 100%。这 7 个叶命令全部是 shortcut快捷命令而非直接暴露的原始 API 命令命令类型覆盖方式slides createshortcutdry-run 文件输入 live 创建回读slides add-slideshortcutdry-run 请求形状 live 增删往返slides delete-slideshortcutdry-run 请求形状含 wiki URL live 增删往返slides update-slideshortcutdry-run 请求形状 live 就地更新 可选历史回退slides replace-slideshortcutdry-run 规范化 live 别名替换/插入slides media-uploadshortcutdry-run parent_type 拆分 live 上传下载往返slides media-downloadshortcutdry-run 两步下载计划 live 上传下载往返每个命令的覆盖都遵循同一条铁律dry-run 层通过真实编译出的二进制验证请求构造live 层通过一次性演示文稿验证后端真实行为。这两层各自承担着单元测试package test无法证明的东西。测试分层的设计动机为什么单元测试不够coverage.md 中反复强调一个核心论点只有真实二进制这一层才能证明某个特性。以create的文件输入为例slides_create_slide_inputs_dryrun_test.go一个多行、引号密集的slideXML 页面要进入 JSON 数组在 shell 里必须做 JSON 转义。测试夹具page1刻意设计成这种形态slide xmlnshttps://www.larkoffice.com/sml/2.0\n data\n shape typetextcontentQ1 results amp; outlook/content/shape\n /data\n/slide因为从 shell 组装这个数组正是文件输入存在的全部理由——调用方此前靠 jq 做转义而没有 jq 的环境会把命令替换变成空参数。dry-run 测试断言data.api.1.body.slide.content与page1逐字节相等证明文件字节在没有调用方手里的 JSON 编码器的情况下原样到达请求体--slide的重复顺序即页面顺序--slide ./slide-01.xml在前、--slide ./slide-02.xml在后API 1 是 page1、API 2 是 page2且不存在 API 3。拒绝场景TestSlidesCreateRejectsBothSlideFormsDryRunE2E固定了exit code 2的错误信封error.type validation、error.subtype invalid_argument、error.param --slide、message 含 cannot be combined——这正是 Agent 解析后用于自我修复命令的机器可读结构。coverage.md 特别指出包级测试从不运行 dispatcher所以看不到这个信封。从源码看这一行为的底层实现在 shortcuts/slides/slides_create.go 的createSlideContents中--slides成品 JSON 数组与--slide可重复的单页 XML 或path互斥--slide不支持 stdin-因为一个进程只有一个 stdin-无法表达这一次出现--slides空值与 JSONnull字面量都会被拒绝前者是失败的命令替换形态后者会被误读为无页面导致空演示文稿被报告为成功只有显式[]合法。readSlideArgs还自行处理了前缀的文件读取与 UTF-8 BOM 剥离与框架对单值 Input flag 的处理保持一致。create从空壳到分页添加的编排TestSlides_CreateWorkflowAsUser 是create的 live 主路径以用户身份创建演示文稿断言返回的xml_presentation_id、title、slides_added、slide_ids随后通过原始 slides APIapi get /open-apis/slides_ai/v1/xml_presentations/id读回 XML 内容证明标题与页面正文确实持久化——而非仅信任写请求自身的响应。测试自清理在 cleanup 中用drive delete --file-token id --type slides --yes删除演示文稿。coverage.md 同时点明了 live 测试环境依赖TestSlides_CreateWorkflowAsUser需要真实用户 token源码中clie2e.SkipWithoutUserToken(t)会跳过无 token 的环境。dry-run 测试则通过setSlidesDryRunEnv(t)固定环境不依赖任何后端。从实现看slides_create.gocreate是一个典型的多步编排先POST /open-apis/slides_ai/v1/xml_presentations创建空壳buildPresentationXML生成 960×540 的presentation标题壳标题缺省为 Untitled再逐个POST .../slide添加页面每页进入时单独 lint坏页面会带着该页的 findings 被拒绝运行在失败点停止错误信息会说明已存在的演示文稿和已添加的页数appendSlidesProgressHint。createSlideQuery把revision_id钉死为-1latest而非暴露给调用方——因为演示文稿刚由同一命令创建不存在更早的版本可供锁定。create还声明了docs:document.media:uploadscope用于图片占位符上传并刻意不声明 drive scope创建从不触碰 driveURL 在本地BuildResourceURL构建。每次 create 最多 10 页maxSlidesPerCreate 10更多页面须先创建再逐个add-slide。add-slide/delete-slide追加、插入与无--yes的删除slides_slide_add_delete_dryrun_test.go 中的TestSlidesAddSlideDryRunE2E固定了两个请求形状追加到末尾不传before_slide_id--slide携带完整slideXML空字符串会被后端当作未知 slide 拒绝因此省略而非置空revision_id为-1images_to_upload为 0。插入到指定页之前--before-slide-id slide_target--revision-id 12乐观锁示例并通过--presentation-id别名传参覆盖了 presentation 参数别名解析。两个用例都断言POST /open-apis/slides_ai/v1/xml_presentations/presAddDryRun/slide这一 URL 形状。coverage.md 强调单测已覆盖同样的形状但只有真实二进制能证明完整slideXML 文档在 flag 解析后引号与尖括号原样保留——这恰恰是最容易产生 3350001 报错的一层。TestSlidesDeleteSlideDryRunE2E则验证删除的请求形状DELETE .../slideslide_idrevision_id-1并额外证明shortcut 无需--yes即可运行原始xml_presentation.slide.delete命令属于 high-risk-write会以 exit 10 confirmation_required 退出shortcut 特意把 Risk 定为 write见 slides_delete_slide.go。TestSlidesDeleteSlideWikiDryRunE2E还证明 wiki URL 会被声明为第一步解析dry-run 的第一段是GET /open-apis/wiki/v2/spaces/node_by_token?tokenwikcnE2ETOKEN第二段才是删除而非把 wiki 令牌直接发给 slides API。live 侧 TestSlides_SlideAddDeleteWorkflowAsUser 在一次性演示文稿上做真实增删往返且针对回读而非写响应本身断言——slide_id确实指向真实页面、--before-slide-id真的把页面定位在邻居之间而非仅仅被转发、删除后页面消失而两个邻居存活。update-slide单 part 的block_replace设计与历史回退coverage.md 对update-slide的 dry-run 覆盖做了精确描述一次请求携带一个block_replacepart其block_id是PAGE id——这是整个设计的核心若放元素 id 只会替换一个元素而留下页面其余部分。同时覆盖了slide服务别名、update命令别名、--xml拼写以及两个必须不产生请求的拒绝场景裸元素根、根 id 指向另一页。live 侧TestSlidesUpdateSlideLiveE2Eslides_update_slide_workflow_test.go是update-slide必需的后端断言用 lane 的 bot 凭证创建一次性演示文稿用返回的 page id 作为block_id替换其页面再通过xml-get读回验证新标记替换了旧标记且slide_id未变最后自清理。TestSlides_HistoryWorkflowslides_history_workflow_test.go是update-slide的可选 live 覆盖创建演示文稿、就地更新页面、断言返回的slide_id、持久化的标记、以及用原始 id 写回的元素保持该 id然后通过幻灯片历史回退并自清理。coverage.md 明确标注它仅在LARK_SLIDES_HISTORY_E2E1时运行因此尚未进入默认 live 通道——这是文档诚实记录的未覆盖边界之一。replace-slide规范化、严格边界与别名工作流slides_replace_slide_dryrun_test.go 的三个用例规范化用例TestSlidesReplaceSlideNormalizationDryRunE2E证明replace/insert、target_id、content、element这些兼容别名会被规范化为标准请求且结构化输出记录所有转换dry-run 的normalizations字段。空替换用例TestSlidesReplaceSlideEmptyReplacementDryRunE2E真正空的规范化载荷依然失败保持严格边界。常规用例TestSlidesReplaceSlideDryRunE2E合法的混合block_replaceblock_insert批处理保持不变。从实现看slides_replace_slide.goreplace-slide相对原始命令有五个价值点--presentation接受 token / slides URL / wiki URLwiki 需解析并声明条件 scopewiki:node:read对每个block_replacepart 自动向 replacement 的根元素注入idblock_id后端要求根携带该 id否则返回 3350001该要求未文档化且反复绊倒调用方对shape元素缺content/时自动注入SML 2.0 schema 要求每个 shape 必须携带 content 子节点3350001 错误时附带场景化 hint 供 AI Agent 自纠后端对 parts 产生的页面做 lint--no-lint可退出。str_replace刻意不暴露——产品方向是幻灯片编辑只走结构性block 级操作。parts 上限 200与 API catalog 声明的服务端上限一致客户端先校验可快速失败。live 侧TestSlides_ReplaceSlideAliasWorkflowAsUserslides_replace_slide_workflow_test.go读取服务端分配的 block ID通过replace/target_id/content替换一个目标、通过insert/element插入另一个读回整副演示文稿证明两次写入都持久化在请求位置且控制块存活清理时删除演示文稿。media-uploadnative/office 的parent_type拆分TestSlides_ImageUploadDryRunParentTypeslides_image_upload_dryrun_test.go覆盖的是 driveparent_type的拆分media-upload --file以及add-slide/update-slide背后path图片占位符管道都必须按演示文稿类型选择正确的parent_type——原生API 创建演示文稿上传为slide_file导入的 office 演示文稿上传为office_slide_file。coverage.md 强调负例部分最重要后端不校验parent_node与parent_type的对应关系错误的值也能上传成功只会在之后表现为渲染不出的图片。因此三个入口都以 wiki--presentation补充测试其真实 token 是预览dry-run绝不能解析的这些用例钉死slide_file是基于构造的正确而非猜测——resolvePresentationID拒绝任何obj_type非slides的 wiki 节点见 helpers.go而导入的 office 演示文稿是 drivefile节点永远过不了这道闸。它们存在的原因正是生产代码现在直接断言该值而不再靠把占位符跑过 office 检查来推导。create刻意缺席此通道它没有--presentationflag总是上传进刚通过 API 创建的演示文稿其 native-only 期望在单测通道中明确声明。实现佐证在 slides_media_upload.goslidesMediaParentType是唯一把 presentation token 映射为parent_type的地方common.IsLocalOfficeToken识别 office tokentoken 形态是 drive 级属性映射才是领域差异dry-run 的slidesDryRunParentType单独存在因为占位符 token 不该侥幸落入slideFileParentType分支那只是占位符拼写碰巧不匹配 office 形态。注释还记录了实测结论slide_image返回 1061001、slides_image/slides_file返回 1061002而slide_file返回可用作img src...的有效 file_token两个值都不被 multipartupload_prepare端点接受99992402因此图片上传统一封顶 20 MB。media-downloaddirect→preview 的两步回退计划slides_media_download_dryrun_test.go 的三个用例固定了 shortcut 规划的两个请求先GET /open-apis/drive/v1/medias/file_token/download直接 Drive media 下载失败后回退GET .../preview_download?preview_type16源文件预览制品以及file_token与解析后的output字段在--output、--output-dir、默认 output-dir 三种形态下的取值。校验用例通过真实命令注册固定了空 token 信封与 output/output-dir 互斥信封——这是包级测试在 HTTP 层打桩够不到的层。实现上slides_media_download.gomedia-download的 Risk 是 readscope 为docs:document.media:download回退分支才触发条件 scopedrive:file:download默认输出目录为.lark-slides/mediadefaultSlidesMediaDownloadDir--output指定单文件相对路径且扩展名可选.png/.jpg/.jpeg与--output-dir互斥Execute在直接下载返回权限错误isSlidesMediaDownloadPermissionError时才切换 preview 通道并将source标记为download或preview。live 媒体往返唯一能证明真实媒体 token 的层TestSlidesMediaUploadDownloadLiveE2Eslides_media_workflow_test.go是媒体链路必需的后端断言创建一次性演示文稿、生成确定性的 8×8 PNG 夹具、经media-upload上传验证返回的file_token、file_name、presentation_id、size与本地夹具一致再经media-download下载回来验证保存路径落在--output-dir下、content_type是 image/*、source为download或preview、磁盘字节数与报告的size一致最后清理演示文稿。coverage.md 的结论是这是唯一能证明真实 Slides 媒体 token 能穿越 direct-to-preview 过渡并返回可解码图片字节的层。阅读与验证建议覆盖矩阵本身见 tests/cli_e2e/slides/coverage.md 的 Command Table表格中每一行都标注了测试用例文件与未覆盖原因如 history workflow 需要LARK_SLIDES_HISTORY_E2E1。想复现 dry-run 断言可查看 slides_create_slide_inputs_dryrun_test.go 的--slide page.xml/--slides deck.json/--slides -三种输入与拒绝信封live 用例需要真实 tokenSkipWithoutUserToken历史用例需要额外环境变量。命令实现与测试的对应关系create见 slides_create.go、媒体上传见 slides_media_upload.go、媒体下载见 slides_media_download.go、结构化替换见 slides_replace_slide.go。这套覆盖设计的核心方法论值得借鉴dry-run 层证明命令会构造出什么live 层证明后端真正发生了什么而两层都跑在真实二进制上才能覆盖到 shell 转义、dispatcher 错误信封、flag 解析保真这类单元测试天然够不到的层。对于以 Agent 为目标的 CLI后者机器可解析的error.param信封、normalizations结构化输出与前者同样重要——它们正是 Agent 自我修复命令的接口契约。赞分享CLIAI 技能【免费下载链接】cliThe official Lark/飞书 CLI tool, maintained by the larksuite team — built for humans and AI Agents. Covers core business domains including Messenger, Docs, Base, Sheets, Calendar, Mail, Tasks, Meetings, and more, with 200 commands and 20 AI Agent Skills.项目地址https://gitcode.com/gh_mirrors/cli414/cli点击查看免费下载相关推荐iptvnator测试策略单元测试与E2E测试覆盖iptvnator测试策略单元测试与E2E测试覆盖 还在为IPTV播放器应用的稳定性担忧iptvnator采用全面的测试策略确保应用在各种场景下都能稳定运音视频视频桌面应用前端Headscale测试覆盖测试策略与覆盖率分析Headscale测试覆盖测试策略与覆盖率分析 概述 Headscale作为Tailscale控制服务器的开源自托管实现其测试策略和覆盖率直接关系到项目的稳后端网络认证鉴权OHIF Viewer 测试覆盖率指南Playwright E2E 测试体系与覆盖率统计实战OHIF Viewer 测试覆盖率指南Playwright E2E 测试体系与覆盖率统计实战 本文档围绕 OHIF Viewer 官方 3.11 版测试覆盖率医疗健康前端音视频创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

相关新闻

电子工程师之家实战项目搭建:告别代码报错的5个关键步骤

电子工程师之家实战项目搭建:告别代码报错的5个关键步骤

电子工程师之家实战项目搭建:告别代码报错的5个关键步骤 刚把从网上抄来的电机控制代码复制到Keil里,按下编译键,屏幕上瞬间弹出一百多个错误?别慌,这几乎是每个进 电子工程师之家…

2026/9/23 3:15:38 阅读更多 →
Primavera-P6实战:从CPM计算到资源约束,把计划引擎用对

Primavera-P6实战:从CPM计算到资源约束,把计划引擎用对

简介:一套全面覆盖Primavera-P6软件操作与项目管理实践的全套培训幻灯片,面向项目计划工程师、PMO成员及需系统学习P6的项目管理人员,可有效解决计划编制、资源分配、进度跟踪和变更控制等核心问题。由PMP认证培训师周老师结合11年项目经验和…

2026/9/23 3:14:38 阅读更多 →
从个人博客到内容公司:17年内容创业经验分享

从个人博客到内容公司:17年内容创业经验分享

1. 从个人博客到内容公司的17年蜕变坐在开往南京的高铁上,窗外是三月江南特有的景致——成片的麦田泛着新绿,路边的树木抽出嫩芽。这种生机勃勃的景象,恰好映衬着我此刻的心情。2026年3月21日,我的个人博客"卢松松博客"…

2026/9/23 3:14:38 阅读更多 →

最新新闻

DeepSeek Windows原生部署实战:绕过WSL的高性能方案

DeepSeek Windows原生部署实战:绕过WSL的高性能方案

1. 为什么Windows上部署DeepSeek不是“装个软件”那么简单DeepSeek系列模型(尤其是DeepSeek-V2、DeepSeek-Coder、DeepSeek-MoE等)在开源社区热度持续走高,但很多人点开GitHub仓库看到docker-compose.yml或run.sh脚本时,第一反应是…

2026/9/23 3:54:28 阅读更多 →
Elasticsearch集群变慢?何时该独立部署协调节点及改造方法

Elasticsearch集群变慢?何时该独立部署协调节点及改造方法

说句得罪人的话:大部分人在 Elasticsearch 集群变慢时,第一反应是加数据节点、加副本、加磁盘,很少有人想到“协调节点”这几个字。我见过不少团队,3 个节点扛着每秒几千的查询,CPU 快被打满,业务方天天催&…

2026/9/23 3:54:28 阅读更多 →
GMM与DBSCAN聚类实战对比:突破KMeans瓶颈的概率与密度方法

GMM与DBSCAN聚类实战对比:突破KMeans瓶颈的概率与密度方法

聚类这个问题,平时写代码遇到最多的就是 KMeans,但真正业务里数据一复杂,KMeans 那种"按距离画圆"的思路往往就不够用了。要么簇的形状不规则,要么数据里有明显的离群点,要么样本本身存在重叠,这…

2026/9/23 3:54:28 阅读更多 →
DeepSeek Harness桌面端:智能体工具调用框架与接入实践

DeepSeek Harness桌面端:智能体工具调用框架与接入实践

DeepSeek官方仓库里突然出现了一个叫Harness的桌面端项目,消息在开发者社区传开后,问法五花八门:这跟DeepSeek网页版有什么区别?harness是个框架还是应用?能不能把Codex接进去?为什么还有人把deepseek herm…

2026/9/23 3:54:28 阅读更多 →
12款大模型Three.js代码生成实测:GPT-6 Astra鹈鹕骑车场景夺冠

12款大模型Three.js代码生成实测:GPT-6 Astra鹈鹕骑车场景夺冠

1. 从“鹈鹕骑车”说起:一个被玩坏的经典测试题第一次看到“鹈鹕骑车”这个测试题,大概是在某个深夜刷技术社区的时候。当时的第一反应是:这帮人真会玩。用 Three.js 渲染一只鹈鹕骑自行车的 3D 场景,然后让大模型来生成代码&…

2026/9/23 3:54:28 阅读更多 →
1天重启人生:用24小时重置状态,找回掌控感

1天重启人生:用24小时重置状态,找回掌控感

看到“我悟了!2亿人拜读的万字长文干货,如何在1天内重启你的人生?”这个标题时,我第一反应是:又是一个贩卖焦虑的标题党。毕竟“重启人生”这四个字已经被用滥了,好像只要早起、跑步、列个计划,…

2026/9/23 3:53:28 阅读更多 →

日新闻

3招搞定手机怎么下载微信面试难题实战项目解析

3招搞定手机怎么下载微信面试难题实战项目解析

3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A…

2026/9/23 0:00:23 阅读更多 →
2k显示屏性能优化踩坑:版本升级后API全变了,这份源码解析救了我

2k显示屏性能优化踩坑:版本升级后API全变了,这份源码解析救了我

2k显示屏性能优化踩坑:版本升级后API全变了,这份源码解析救了我 刚把开发环境的显示器从1080P换到2K,跑老项目直接报错,版本升级后 API…

2026/9/23 0:01:25 阅读更多 →
3步搞定美眉图实战项目,告别官方文档抓不住重点

3步搞定美眉图实战项目,告别官方文档抓不住重点

3步搞定美眉图实战项目,告别官方文档抓不住重点 官方文档翻了三遍还是云里雾里?别急,美眉图在实战项目中常被用来做数据可视化,但它的原理比你想的简单。今天咱们直接上手,用一个完整的小项目把美眉图跑通,不再死磕那些冗长的理论说明。…

2026/9/23 0:01:25 阅读更多 →

周新闻

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

Flutter for OpenHarmony游戏卡片渐变背景实战:从原理到性能优化

直接铺开项目本身吧。这几个月我一直在折腾一件事:用Flutter给OpenHarmony做一款游戏集合类的App,说白了就是把若干小游戏塞进一个壳里,用统一入口分发。这个方向本身不算新鲜,真正让我花了不少心思的,是首页那堆游戏卡…

2026/9/22 4:32:41 阅读更多 →
Word表格编号全攻略:从列表编号到题注交叉引用

Word表格编号全攻略:从列表编号到题注交叉引用

写Word文档,最让人头疼的往往是那些“看起来不起眼”的小问题。比如表格编号这事:今天在表后面多加了两个空白行,明天给客户交稿前发现整个章节的编号全部错位,光是挨个改序号就能耗掉大半个下午。我前阵子帮人整理一份上百页的技…

2026/9/22 4:38:57 阅读更多 →
从第一个站到第二个站:独立开发者的静态网站选型与落地实践

从第一个站到第二个站:独立开发者的静态网站选型与落地实践

1. 项目概述1.1 核心需求解析做独立开发者这几年,说实话,第一个网站上线的那天晚上我兴奋得没睡着。但等它跑了半年,流量惨淡、功能臃肿、代码自己都懒得看第二遍之后,我才慢慢琢磨明白一个道理:第一个网站是练手&…

2026/9/22 8:51:04 阅读更多 →

月新闻

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能

持续集成 流水线自动化与 声明式交付 实践:原型怎样变成可用功能分类:[AI/大模型]细分主题:AI 增强型 CI/CD 流水线自动化与 GitOps 实践:Agent 工作流、工具调用与任务拆解:从原型到生产的验收清单很多团队在尝试用大…

2026/9/21 15:36:51 阅读更多 →
容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场

容器编排 生产环境运维与排障实战:复盘记录怎样真正派上用场分类:[工程技术]细分主题:Kubernetes 生产环境运维与排障实战:可复制的项目复盘模板与决策记录大部分团队的事故复盘报告,最后都变成了躺在 Confluence 或钉…

2026/9/21 15:36:51 阅读更多 →
容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步

容器 容器化技术与镜像安全管理:核心链路应该先拆哪一步分类:[工程技术]细分主题:Docker 容器化技术与镜像安全管理:核心链路的逐步实现与关键代码取舍面对一个积累了五六年历史包袱的单体架构应用(包含 Web 接口、后台…

2026/9/22 2:43:42 阅读更多 →