ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

100 Exercises to Learn Rust 第三章收官实战:用集成测试驱动一个带校验的 `Order` 类型

100 Exercises to Learn Rust 第三章收官实战:用集成测试驱动一个带校验的 `Order` 类型 示例工程教程【免费下载链接】100-exercises-to-learn-rustA self-paced course to learn Rust, one exercise at a time.项目地址https://gitcode.com/GitHub_Trending/10/100-exercises-to-learn-rust点击查看免费下载本章是《100 Exercises to Learn Rust》第三章ticket_v1的收尾练习。在经历了struct、校验、模块与可见性、封装、所有权、setter 等一连串基础概念后你需要以最少的引导完成最后一个类型建模任务实现一个带字段校验、访问器getter与修改器setter的Order订单类型并让位于tests目录的集成测试全部通过。读完本文你将掌握 Rust 中集成测试的目录约定与编译语义、pub可见性在跨模块/跨 crate 场景下的作用以及如何用构造函数 私有字段 公共方法构建一个不变量稳固的自定义类型。本章定位把训练转向自助式回顾 第三章开篇本章主线是用一个类 JIRA 的 Ticket 建模来学习 Rust 独有的ownership所有权体系以及struct、模块与可见性、内存管理、字符串等基础概念。前面的练习01_struct到11_destructor都有较为详细的指引而到了 12_outro 这一节原书刻意做了降级处理Youll have minimal guidance this time—just the exercise description and the tests to guide you.也就是说这是第三章的一次独立考试没有逐步提示只有练习描述和测试用例作为指引。你需要凭前面累积的知识独立完成一个全新的类型设计。练习要求你需要交付什么根据 练习源码中的任务注释你要在lib.rs中定义一个全新的Order类型并满足以下全部要求要求具体约束字段跟踪三份信息product_name、quantity、unit_price商品名校验不能为空且不能超过300 字节数量校验必须严格大于 0单价校验单位为分cents必须严格大于 0方法提供名为total的方法返回订单总价访问器与修改器为每个字段提供 getter 与 setter这些约束与前几节练习中Ticket的校验思路完全同源——你可以回看 02_validation.md 中用户可能构造出空标题、超长描述或无意义状态的动机以及 05_encapsulation.md 中用私有字段 公共方法维护不变量的封装原则。Order正是把同一套方法论迁移到一个全新领域对象上的实践。集成测试tests目录的特殊语义本次练习与之前最大的不同在于测试位置。注释明确指出Tests are located in a different place this time—in thetestsfolder. Thetestsfolder is a special location forcargo. Its where it looks forintegration tests.在 集成测试文件 的顶部源码又强调了两点use outro_02::Order; // Files inside the tests directory are only compiled when you run tests. // As a consequence, we dont need the #[cfg(test)] attribute for conditional compilation—its // implied.这里有三个必须理解的关键点目录约定cargo会把tests目录下的每个文件都编译成独立的测试 crate这是它的内置查找规则不需要任何额外配置。条件编译是隐式的tests目录下的文件只在运行测试时才被编译因此不需要像单元测试那样写#[cfg(test)]上一章大量出现的#[cfg(test)] mod tests { ... }正是单元测试形态详见 03_modules.md。测试的是公共 API集成测试编译为独立 crate从外部链接你的库 crate本例中 crate 名为outro_02见 Cargo.toml因此只能访问pub暴露的项。私有字段、pub(crate)项在这里都不可见——正如注释所说Integration here has a very specific meaning: they testthe public APIof your project. Youll need to pay attention to the visibility of your types and methods; integration tests cant access private orpub(crate)items.这直接呼应了 04_visibility.md 中关于可见性修饰符的讲解pub对外部 crate 可见而pub(crate)仅在当前 crate 内部可见。集成测试恰好是检验你可见性设计是否正确的天然裁判。测试用例即规格逐条推演Order的 API集成测试 中的每个#[test]都对应Order必须满足的一条规格我们逐条拆解1. 构造与访问test_orderlet mut order Order::new(Rusty Book.to_string(), 3, 2999); assert_eq!(order.product_name(), Rusty Book); assert_eq!(order.quantity(), 3); assert_eq!(order.unit_price(), 2999); assert_eq!(order.total(), 8997);Order::new是一个关联函数构造函数按顺序接收商品名、数量、单价三个参数。回顾 01_struct.md不接收self的方法称为静态方法只能用StructName::method(...)的函数调用语法调用。product_name()返回的是str断言直接与字符串字面量比较而quantity()与unit_price()的断言形如3、2999——说明 getter 返回的是引用u32。这正是 07_setters.md 中演示的访问器写法pub fn title(self) - String。total()返回订单总价3 × 2999 8997单位是分注意这里的乘法不能溢出而单元价格以分为单位意味着涉及金额时要用整数运算而非浮点。2. 修改setterorder.set_product_name(Rust Book.to_string()); order.set_quantity(2); order.set_unit_price(3999); assert_eq!(order.product_name(), Rust Book); assert_eq!(order.quantity(), 2); assert_eq!(order.unit_price(), 3999); assert_eq!(order.total(), 7998);order被声明为mut三个 setter 都以mut self接收者调用调用后变量继续可用、无需重新赋值——这正是 07_setters.md 中第二种 setter 形态mut self、无返回值的用法。setter 修改后total()重新计算为2 × 3999 7998说明total是基于当前字段值动态计算的。3. 校验#[should_panic]系列#[test] #[should_panic] fn test_empty_product_name() { Order::new(.to_string(), 3, 2999); } #[test] #[should_panic] fn test_long_product_name() { Order::new(a.repeat(301), 3, 2999); } #[test] #[should_panic] fn test_zero_quantity() { Order::new(Rust Book.to_string(), 0, 2999); } #[test] #[should_panic] fn test_zero_unit_price() { Order::new(Rust Book.to_string(), 3, 0); }#[should_panic]要求被测代码在非法输入下panic即调用panic!测试才算通过。这与 02_basic_calculator/04_panics.md 中恐慌概念的用法一致也与前面章节Ticket::new对空标题等非法状态的处理方式保持一致。四个非法场景正好一一对应四个校验规则空商品名、超过 300 字节的商品名a.repeat(301)构造出 301 字节、数量为 0、单价为 0。注意商品名上限的度量单位是字节而非字符。String是 UTF-8 编码的len()方法返回字节数——多字节字符如中文会占用多个字节。这是校验实现时必须小心的细节前章 02_validation.md 也提示过需要查阅String的方法来完成任务。推荐的实现路径结合前序章节的封装方法论一个稳妥的实现步骤是定义结构体字段全部保持私有Rust 默认私有从而强制所有实例必须经由构造函数创建杜绝绕过校验的可能05_encapsulation.md。实现构造函数new在创建实例前逐项检查四个不变量不合法时直接panic!注意空字符串可用is_empty()判断长度用len()判断字节数。实现访问器product_name(self) - str、quantity(self) - u32、unit_price(self) - u32返回引用以避免不必要的克隆07_setters.md。实现修改器set_product_name(mut self, ...)、set_quantity(mut self, ...)、set_unit_price(mut self, ...)每个 setter 在赋值前同样执行对应校验防止修改阶段破坏不变量。实现total返回quantity * unit_price注意乘法可能溢出可参考 02_basic_calculator/08_overflow.md 与 09_saturating.md 的讨论本测试用例中的数值量级不涉及溢出。特别要强调一点setter 也必须校验。如果不校验用户就能通过set_product_name()绕过构造函数的约束让封装形同虚设。这正是 05_encapsulation.md 中公共方法负责维护不变量的完整含义。如何运行与验证在练习目录下直接执行cargo testcargo会自动编译src/lib.rs以及tests目录下的集成测试。全部通过时你会看到形如5 passed的摘要若有失败项输出会指出是哪个#[test]失败以及断言期望值例如total()计算错误时assert_eq!会打印左右两侧的实际值便于定位。一个常见的隐蔽坑是可见性不足如果Order、Order::new或 getter/setter 忘记加pub集成测试编译时会直接报error[E0603]: struct is private之类的错误——因为在独立测试 crate 眼中非pub项根本不存在。这也是本章用集成测试反推公共 API 设计的训练价值所在。本章小结从 Ticket 到 Order 的能力迁移Order练习表面上只是换了一个领域对象实际上是对第三章全部核心概念的闭环验收struct与方法01_struct.md自定义类型 impl块 关联函数与实例方法校验02_validation.md用构造函数在源头拦截非法状态模块与可见性03_modules.md、04_visibility.md理解 crate 根、use语句与pub层级知道集成测试只能接触pub面封装05_encapsulation.md私有字段 公共方法维护不变量所有权与引用07_setters.mdgetter 用self返回引用setter 用mut self原地修改。当你让tests/integration.rs中 5 个测试1 个功能用例 4 个恐慌用例全部通过时你就已经具备用 Rust 独立建模一个带约束业务类型的能力了。下一章将进入 Ticket 的第二次迭代ticket_v2用enum、match与错误处理让类型系统更加强大——03_ticket_v1 的 outro 就是这次跃迁的完美起跳点。赞分享示例工程教程【免费下载链接】100-exercises-to-learn-rustA self-paced course to learn Rust, one exercise at a time.项目地址https://gitcode.com/GitHub_Trending/10/100-exercises-to-learn-rust点击查看免费下载相关推荐GitHub Desktop 开发工具链与调试指南编辑器配置、构建流程与 DevTools 实战GitHub Desktop 开发工具链与调试指南编辑器配置、构建流程与 DevTools 实战 本篇指南面向 GitHub Desktop 开源仓库的贡献者示例工程教程k-skill-setup 技能k-skill 安装、凭证解析与运行时环境验证的完整操作指南k skill setup 技能k skill 安装、凭证解析与运行时环境验证的完整操作指南 k skill 是一个面向韩国用户、以“让 AI Agent 更示例工程教程100-exercises-to-learn-rust用 TryFrom / TryInto 实现可失败的 Rust 类型转换100 exercises to learn rust用 TryFrom / TryInto 实现可失败的 Rust 类型转换 TryFrom 与 TryIn示例工程教程上一篇PaddleOCR 数据合成工具全景指南从 Style-Text 到 SynthTIGER 的选型与实战下一篇SerenityOS unveil(2) 深入解析用路径白名单为进程构建文件系统沙箱创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表