当前位置: 首页 > news >正文

第17章:Python TDD回顾与总结货币类开发

写在前面


这本书是我们老板推荐过的,我在《价值心法》的推荐书单里也看到了它。用了一段时间 Cursor 软件后,我突然思考,对于测试开发工程师来说,什么才更有价值呢?如何让 AI 工具更好地辅助自己写代码,或许优质的单元测试是一个切入点。 就我个人而言,这本书确实很有帮助。第一次读的时候,很多细节我都不太懂,但将书中内容应用到工作中后,我受益匪浅。比如面对一些让人抓狂的代码设计时,书里的方法能让我逐步深入理解代码的逻辑与设计。 作为一名测试开发工程师,我想把学习这本书的经验分享给大家,希望能给大家带来帮助。因为现在工作中大多使用 Python 代码,所以我把书中JAVA案例都用 Python 代码进行了改写 。

问题背景说明

在完成货币类的一系列开发与优化后,对整个开发过程进行回顾和总结具有重要意义。通过回顾,可以总结经验教训,发现开发过程中的优点和不足之处,为未来的项目开发提供参考,同时也有助于加深对测试驱动开发流程和方法的理解和掌握,提高开发者的技术水平和开发效率。

完成货币类的一系列开发与优化后,对整个过程进行回顾总结,有助于加深对Python TDD的理解,为后续开发积累经验。

17.1 思路说明

回顾从简单的乘法功能测试到复杂的多币种货币运算实现的过程,分析测试驱动开发的流程、遇到的问题及解决方法,总结代码优化和设计的思路。

17.2 测试代码(综合回顾测试)

import unittestclass Bank:def __init__(self):# 存储货币兑换汇率的字典,键是 (from_currency, to_currency) 元组,值是汇率self.rates = {}def addRate(self, from_currency, to_currency, rate):# 添加一种货币到另一种货币的汇率self.rates[(from_currency, to_currency)] = ratedef rate(self, from_currency, to_currency):# 获取从 from_currency 到 to_currency 的汇率# 如果是相同货币,汇率为 1if from_currency == to_currency:return 1# 尝试从 rates 字典中获取汇率,如果没有则默认为 1return self.rates.get((from_currency, to_currency), 1)def reduce(self, source, to):# 将表达式(如 Sum 或 Money)转换为指定货币的 Money 对象if isinstance(source, Sum):# 如果是 Sum 类型,将加数和被加数都转换为目标货币,然后求和amount = source.augend.reduce(self, to).amount + source.addend.reduce(self, to).amountreturn Money(amount, to)elif isinstance(source, Money):# 如果是 Money 类型,根据汇率进行转换rate = self.rate(source.currency, to)return Money(source.amount / rate, to)class Expression:def reduce(self, bank, to):# 抽象方法,用于将表达式转换为指定货币的 Money 对象passclass Money(Expression):def __init__(self, amount, currency):# 金额self.amount = amount# 货币类型self.currency = currencydef plus(self, addend):# 实现加法操作,返回一个 Sum 对象return Sum(self, addend)def times(self, multiplier):# 实现乘法操作,返回一个新的 Money 对象,金额乘以乘数return Money(self.amount * multiplier, self.currency)def reduce(self, bank, to):# 将自身转换为指定货币的 Money 对象# 调用 bank 的 rate 方法获取汇率rate = bank.rate(self.currency, to)return Money(self.amount / rate, to)class Sum(Expression):def __init__(self, augend, addend):# 加数self.augend = augend# 被加数self.addend = addenddef reduce(self, bank, to):# 将 Sum 中的加数和被加数转换为指定货币,然后求和amount = self.augend.reduce(bank, to).amount + self.addend.reduce(bank, to).amountreturn Money(amount, to)class Dollar(Money):def __init__(self, amount):# 调用父类 Money 的构造函数,将货币类型设置为 USDsuper().__init__(amount, "USD")class Franc(Money):def __init__(self, amount):# 调用父类 Money 的构造函数,将货币类型设置为 CHFsuper().__init__(amount, "CHF")class TestAllCurrencyOperations(unittest.TestCase):def test_mixed_addition(self):bank = Bank()# 添加瑞士法郎到美元的汇率为 2bank.addRate("CHF", "USD", 2)# 创建 5 美元的对象five_dollars = Dollar(5)# 创建 10 瑞士法郎的对象ten_francs = Franc(10)# 将 5 美元和 10 瑞士法郎相加并转换为美元result = five_dollars.plus(ten_francs).reduce(bank, "USD")# 验证结果是否等于 10 美元self.assertEqual(result.amount, 10)# 验证结果的货币类型是否为美元self.assertEqual(result.currency, "USD")def test_dollar_multiplication(self):# 创建 5 美元的对象five_dollars = Dollar(5)# 将 5 美元乘以 3result = five_dollars.times(3)# 验证结果是否等于 15 美元self.assertEqual(result.amount, 15)# 验证结果的货币类型是否为美元self.assertEqual(result.currency, "USD")if __name__ == '__main__':unittest.main()

17.3 源码说明

这段综合测试代码涵盖了多币种加法运算和货币乘法运算的测试用例。通过回顾整个开发过程,我们从最初的简单功能逐步实现了复杂的货币运算系统。在这个过程中,不断地编写测试用例、实现功能代码、优化代码结构,遵循TDD的流程解决了各种问题,提高了代码的质量和可维护性。总结这些经验,能帮助我们在未来的Python开发中更好地应用TDD方法。

TDD过程中的关键要点回顾

在讲授和实践TDD的过程中,有几个关键要点反复出现,这些要点对于理解和应用TDD至关重要。

  1. 让测试工作的方式

1.1 伪实现:在TDD流程中,当编写完测试用例后,为了快速验证测试框架是否正常工作,以及测试用例是否能够按照预期运行,我们会采用伪实现的方式。这是一种临时性的代码实现,它并不追求功能的完整性和正确性,只是简单地让测试能够通过。例如,在开发货币类的乘法功能时,最初的times方法可能只是返回一个固定值,像这样:

class Dollar:def __init__(self, amount):self.amount = amountdef times(self, multiplier):return 0  # 伪实现,仅为使测试通过

通过这种方式,我们可以快速检查测试环境和测试用例的基本逻辑是否正确。如果此时测试能够顺利通过,说明测试框架和测试用例的基本设置没有问题;如果测试失败,我们可以先排查测试相关的问题,而不是纠结于功能代码的实现细节。一旦确认测试环节无误,我们再逐步完善功能代码,将伪实现替换为真正的功能实现。

1.2 三角测量:三角测量是一种通过多个类似的测试用例来逐步明确需求和实现通用解决方案的方法。当我们只有一个测试用例时,可能会编写一个仅适用于该特定情况的代码实现,这可能导致代码缺乏通用性。而三角测量通过增加更多相似但又有细微差异的测试用例,帮助我们发现代码中的共性和变化点,从而设计出更通用的解决方案。例如,在测试Dollar对象的乘法方法times时,我们最初可能只有一个测试用例:

def test_dollar_multiplication():five = Dollar(5)result = five.times(2)assert result == 10

此时,times方法的实现可能只是针对5 * 2这个特定情况编写的。为了确保times方法在各种输入下都能正确工作,我们可以增加更多测试用例:

def test_dollar_multiplication():five = Dollar(5)result = five.times(2)assert result == 10result = five.times(3)assert result == 15ten = Dollar(10)result = ten.times(4)assert result == 40

通过这些不同输入的测试用例,我们可以发现乘法运算的通用规律,进而实现一个能够适用于各种输入的times方法,避免返回常量值,使代码更具通用性和健壮性。

1.3 显式实现:显式实现是TDD过程的最终阶段,在这个阶段,我们根据之前编写的测试用例和通过三角测量明确的需求,实现完整、正确且符合业务逻辑的功能代码。此时的代码不仅要满足所有测试用例的要求,还要考虑代码的性能、可读性、可维护性等方面。例如,在货币类开发中,经过伪实现和三角测量阶段后,我们最终实现的times方法可能是这样的:

class Dollar:def __init__(self, amount):self.amount = amountdef times(self, multiplier):return self.amount * multiplier

这个实现是基于前面的测试和分析,明确了乘法运算的具体需求后完成的,它能够正确处理各种输入情况,并且符合货币金额乘法运算的实际逻辑。

  1. 消除重复:去掉测试代码和程序代码间的重复部分,是推进设计和开发的重要手段。在TDD开发过程中,随着功能的增加和代码量的增长,很容易出现重复代码。这些重复代码可能存在于测试用例中,也可能在功能代码中,或者在两者之间。重复代码不仅增加了代码量,还会使维护变得困难,因为一处修改可能需要在多个地方同步进行。通过重构,我们可以提取重复的代码片段,将其封装成独立的函数、方法或类,使代码更加简洁、易维护。例如,在测试不同货币类的乘法和加法运算时,如果多个测试用例中都有创建货币对象和进行基本断言的重复代码,我们可以将这些重复部分提取出来,封装成一个辅助函数或测试基类中的方法,减少代码冗余。

  2. 测试的控制力:当开发过程中遇到不确定因素时,要加强测试的控制力,如同在路面湿滑时增大摩擦力;而当情况明朗时,则可以加速前进,提高开发效率。在TDD中,测试的控制力体现在对测试用例的编写和执行上。当开发过程中遇到新的功能需求、复杂的业务逻辑或不确定的技术方案时,我们需要编写更多详细的测试用例,覆盖各种可能的情况,确保代码在各种条件下都能正确运行。这就好比在路面湿滑时,我们需要小心翼翼地控制车辆,增加摩擦力以确保安全行驶。例如,在实现多币种货币运算时,由于涉及汇率转换、不同货币对象的组合等复杂情况,我们需要编写大量测试用例来验证各种情况下的运算结果是否正确。而当我们对某个功能已经非常熟悉,代码实现也相对稳定时,我们可以适当减少测试用例的数量,或者采用更高效的测试策略,提高开发效率,就像在路况良好时可以适当加速行驶一样。但需要注意的是,即使在情况明朗时,也不能完全忽视测试,仍然要保证代码的质量和正确性。

相关文章:

第17章:Python TDD回顾与总结货币类开发

写在前面 这本书是我们老板推荐过的,我在《价值心法》的推荐书单里也看到了它。用了一段时间 Cursor 软件后,我突然思考,对于测试开发工程师来说,什么才更有价值呢?如何让 AI 工具更好地辅助自己写代码,或许…...

opencv_KDTree_搜索介绍及示例

cv::flann::KDTreeIndexParams 说明,使用? cv::flann::KDTreeIndexParams 是 OpenCV 中用于配置 KD 树(K-Dimensional Tree)索引参数的类。KD 树是一种用于多维空间中的点搜索的数据结构,常用于最近邻搜索等问题。在…...

Windows 上安装 MongoDB 的 zip 包

博主介绍: 大家好,我是想成为Super的Yuperman,互联网宇宙厂经验,17年医疗健康行业的码拉松奔跑者,曾担任技术专家、架构师、研发总监负责和主导多个应用架构。 近期专注: RPA应用研究,主流厂商产…...

先进制造aps专题二十七 西门子opcenter aps架构分析

欧美的商业aps,主要就是sap apo,西门子opcenter aps,达索quintiq 从技术的层面,西门子aps是不如sap apo的,但是西门子aps是西门子数字化工厂产品的核心,有很多特色,所以分析 西门子aps主要分计划器和排产器两个部分 计…...

【数据分享】1929-2024年全球站点的逐年平均气温数据(Shp\Excel\无需转发)

气象数据是在各项研究中都经常使用的数据,气象指标包括气温、风速、降水、湿度等指标,其中又以气温指标最为常用!说到气温数据,最详细的气温数据是具体到气象监测站点的气温数据!本次我们为大家带来的就是具体到气象监…...

机器学习——什么是代价函数?

1.代价函数的定义 首先,提到代价函数是估计值和实际值的差,这应该是指预测值和真实值之间的差异,用来衡量模型的好坏。 在一元线性模型中,模型是直线,有两个参数,可能是斜率和截距。 通过调整这两个参数,让代价函数最小,这应该是说我们要找到最佳的斜率和截距,使得预测…...

docker 部署 MantisBT

1. docker 安装MantisBT docker pull vimagick/mantisbt:latest 2.先运行实例,复制配置文件 docker run -p 8084:80 --name mantisbt -d vimagick/mantisbt:latest 3. 复制所需要配置文件到本地路径 docker cp mantisbt:/var/www/html/config/config_inc.php.…...

02内存结构篇(D1_自动内存管理)

目录 一、内存管理 1. C/C程序员 2. Java程序员 二、运行时数据区 1. 程序计数器 2. Java虚拟机栈 3. 本地方法栈 4. Java堆 5. 方法区 运行时常量池 三、Hotspot运行时数据区 四、分配JVM内存空间 分配堆的大小 分配方法区的大小 分配线程空间的大小 一、内存管…...

Centos 8 交换空间管理

新增swap 要增加 Linux 系统的交换空间,可以按照以下步骤操作: 1. 创建一个交换文件 首先,选择文件路径和大小(例如,增加 1 GB 交换空间)。 sudo fallocate -l 1G /swapfile如果 fallocate 不可用&…...

“深入浅出”系列之数通篇:(5)TCP的三次握手和四次挥手

TCP(传输控制协议)的三次握手和四次挥手是TCP连接建立和释放的过程。 一、TCP三次握手 TCP三次握手是为了建立可靠的连接,确保客户端和服务器之间的通信能力。具体过程如下: 第一次握手:客户端向服务器发送一个带有…...

接口测试及接口测试常用的工具

🍅 点击文末小卡片,免费获取软件测试全套资料,资料在手,涨薪更快 首先,什么是接口呢? 接口一般来说有两种,一种是程序内部的接口,一种是系统对外的接口。 系统对外的接口&#xff…...

使用rpc绕过咸鱼sign校验

案例网站是咸鱼 找到加密函数i(),发现参数是由token时间戳appkeydata构成的 js客户端服务 考虑到网站可能有判断时间戳长短而让请求包失效的可能,我们请求包就直接用它的方法生成 下面我们先把token和h置为键值对tjh123 再把方法i()设为全局变量my_…...

NPC与AI深度融合结合雷鸟X3Pro AR智能眼镜:引领游戏行业沉浸式与增强现实新纪元的畅想

if… NPC(非玩家角色)与AI(人工智能)的深度融合,正引领游戏行业迈向一个全新的沉浸式与增强现实(AR)相结合的新时代。这一创新不仅预示着游戏体验的质变,更可能全面革新游戏设计与叙…...

【物联网】ARM核介绍

文章目录 一、芯片产业链1. CPU核(1)ARM(2)MIPS(3)PowerPc(4)Intel(5)RISC-V 2. SOC芯片(1)主流厂家(2)产品解决方案 3. 产品 二、ARM核发展1. 不同架构的特点分析(1)VFP(2)Jazelle(3)Thumb(4)TrustZone(5)SIMD(6)NEON 三、ARM核(ARMv7)工作模式1. 权限级别(privilege level)2.…...

Android系统定制APP开发_如何对应用进行系统签名

前言 当项目开发需要使用系统级别权限或frame层某些api时,普通应用是无法使用的,需要在AndroidManifest中配置sharedUserId: AndroidManifest.xml中的android:sharedUserId“android.uid.system”,代表的意思是和系统相同的uid&a…...

Tesla Free-Fall Attack:特斯拉汽车网络安全事件纪要

Tesla Free-Fall Attack:特斯拉汽车网络安全事件纪要 1. 引言 Tesla Free-Fall Attack 是由腾讯科恩实验室(Tencent Keen Security Lab)于2016年9月对特斯拉Model S汽车实施的一次远程攻击事件,揭示了汽车网络安全的严重漏洞&am…...

网络安全工程师学习路线

https://www.processon.com/view/link/6584f06465b7eb6189e99508 1、HTML基本语言 常用标签、表单、上传页面、登录页面、超链接2、javascript基本语法 变量、函数、流程控制语法、post请求、ajax请求、输入数据到页面、文件上传3、mysql基本用法 增删改查 infromation_sch…...

分区和分表有什么区别?

数据库中数据量过多,表太大的时候,不仅可以做分库分表,还可以做表分区,分区和分表类似,都是按照一定的规则将一张大表进行分解。 听上去好像也差不多,不就是将表拆分吗?那具体有什么差别呢&…...

C#,入门教程(01)—— Visual Studio 2022 免费安装的详细图文与动画教程

通过本课程的学习,你可以掌握C#编程的重点,享受编程的乐趣。 在本课程之前,你无需具备任何C#的基础知识,只要能操作电脑即可。 不过,希望你的数学不是体育老师教的。好的程序是数理化的实现与模拟。没有较好的数学基础…...

简述mysql 主从复制原理及其工作过程,配置一主两从并验证。

MySQL 主从同步是一种数据库复制技术,它通过将主服务器上的数据更改复制到一个或多个从服务器,实现数据的自动同步。 主从同步的核心原理是将主服务器上的二进制日志复制到从服务器,并在从服务器上执行这些日志中的操作。 MySQL主从同步是基…...

【JavaEE】-- HTTP

1. HTTP是什么? HTTP(全称为"超文本传输协议")是一种应用非常广泛的应用层协议,HTTP是基于TCP协议的一种应用层协议。 应用层协议:是计算机网络协议栈中最高层的协议,它定义了运行在不同主机上…...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中,Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染(即CPU被阻塞),这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案: 对惹,这里有一个游戏开发交流小组&…...

Vue3 + Element Plus + TypeScript中el-transfer穿梭框组件使用详解及示例

使用详解 Element Plus 的 el-transfer 组件是一个强大的穿梭框组件,常用于在两个集合之间进行数据转移,如权限分配、数据选择等场景。下面我将详细介绍其用法并提供一个完整示例。 核心特性与用法 基本属性 v-model:绑定右侧列表的值&…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台(Launchpad)多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显,都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

MODBUS TCP转CANopen 技术赋能高效协同作业

在现代工业自动化领域,MODBUS TCP和CANopen两种通讯协议因其稳定性和高效性被广泛应用于各种设备和系统中。而随着科技的不断进步,这两种通讯协议也正在被逐步融合,形成了一种新型的通讯方式——开疆智能MODBUS TCP转CANopen网关KJ-TCPC-CANP…...

12.找到字符串中所有字母异位词

🧠 题目解析 题目描述: 给定两个字符串 s 和 p,找出 s 中所有 p 的字母异位词的起始索引。 返回的答案以数组形式表示。 字母异位词定义: 若两个字符串包含的字符种类和出现次数完全相同,顺序无所谓,则互为…...

DeepSeek 技术赋能无人农场协同作业:用 AI 重构农田管理 “神经网”

目录 一、引言二、DeepSeek 技术大揭秘2.1 核心架构解析2.2 关键技术剖析 三、智能农业无人农场协同作业现状3.1 发展现状概述3.2 协同作业模式介绍 四、DeepSeek 的 “农场奇妙游”4.1 数据处理与分析4.2 作物生长监测与预测4.3 病虫害防治4.4 农机协同作业调度 五、实际案例大…...

算法:模拟

1.替换所有的问号 1576. 替换所有的问号 - 力扣(LeetCode) ​遍历字符串​:通过外层循环逐一检查每个字符。​遇到 ? 时处理​: 内层循环遍历小写字母(a 到 z)。对每个字母检查是否满足: ​与…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

海云安高敏捷信创白盒SCAP入选《中国网络安全细分领域产品名录》

近日,嘶吼安全产业研究院发布《中国网络安全细分领域产品名录》,海云安高敏捷信创白盒(SCAP)成功入选软件供应链安全领域产品名录。 在数字化转型加速的今天,网络安全已成为企业生存与发展的核心基石,为了解…...