我正在尝试学习TDD。我已经看到了关于如何从最小可能的功能TDD咖啡自动售货机固件变得容易的例子和讨论。这些例子既是原始的,也是经过深思熟虑的,很难立刻说出来。但这是一个现实世界的问题。
链接。
最简单的链接器读取一个目标文件,执行魔术,并写入一个可执行文件。我认为我不能进一步简化它。我相信链接器设计可能会进化,但我完全不知道从哪里开始。关于如何处理这个的任何想法?
嗯,可能整个链接器对于第一次单元测试来说太大了。我可以事先设想一些粗糙的结构。链接器的作用是:
我的主要问题是子弹1. 2,3和4基本上采用常规数据结构,并根据某些配置将其转换为依赖于平台的混乱。我可以设计,设计看起来可行。但是,它应该选择一种依赖于平台的混乱,以几种支持的格式之一,并将其转换为常规结构。
该任务看起来很通用。它发生在您需要支持多种输入格式的任何地方,无论是图像处理,文档处理,您都可以命名。 TDD有可能吗?似乎要么测试太简单了,我很容易将其破解为绿色,或者它有点复杂,我需要实现整个对象/图像/文档格式阅读器,这是很多代码。而且没有中间立场。
答案 0 :(得分:1)
首先,看看Freeman& amp; amp; amp; amp; amp; amp;普赖斯。
现在,我试图用几句话回答一个棘手的问题。
TDD确实要求您思考(即设计)您将要做的事情。你必须:关于如何构建链接器的初步想法(设计)将指导您的初始测试。测试将强制执行模块化设计(因为每个测试仅测试单个行为,并且对您编写的其他代码的依赖性应该最小)。
当您继续时,您可能会发现您的想法发生了变化。您已经编写的测试将允许您自信地重构。
测试应该很简单。很容易将一个测试“破解”为绿色。但在每次“黑客”之后你都会重构。如果您在重构期间看到需要新的类或算法,那么编写测试以驱动其接口。确保测试只测试单个行为,方法是保持模块松散耦合(依赖注入,抽象基类,接口,函数指针等),并使用假货,存根和模拟将待测代码与其余部分隔离开来。系统
最后使用'客户'测试来确保您已交付功能。
这是思维方式的一个艰难变化,但很有趣,而且非常有益。诚实。
答案 1 :(得分:0)
答案 2 :(得分:0)
我想我所做的是提出图层和块,然后细分到我可能会考虑代码然后开始编写测试的地方。
我认为你的测试应该非常简单:不是单独的测试是TDD的强大功能,而是测试的总和。
我遵循的原则之一是方法应该适合屏幕 - 在这种情况下,测试通常很简单。
您的设计应该允许您模拟较低层,以便您只测试一层。
答案 3 :(得分:0)
TDD是关于规范,而不是测试。
从最简单的链接器规范来看,如果用目标文件提供可执行文件,TDD测试只需检查链接器魔术期间是否创建了可执行文件。
然后你编写一个让测试成功的链接器,例如:
然后你优化你的规格和你的TDD(这是你的四颗子弹)。
只要您可以编写规范,就可以编写TDD测试用例。
答案 4 :(得分:0)
你是对的,链接器对我来说似乎比一个“单位”大一点,并且TDD不会原谅你坐下来思考如何将你的问题分解成单位。 The Sudoku saga可以很好地说明如果您不首先考虑会出现什么问题!
专注于您的观点1,您已经通过列出可能出现在细分中的各种事物来描述了一系列(功能性的)单元,并暗示您需要支持多种格式。为什么不首先处理一个简单的情况,例如,一个只包含开发平台二进制格式的数据段的文件?您可以简单地将文件硬编码为测试中的二进制数组,然后检查它是否正确解释了该文件。然后选择另一个简单的案例,并测试它。继续。
现在神奇的是,你很快就会在你的代码和测试中看到重复的结构,并且因为你已经进行了测试,所以你可以非常积极地重构它。我怀疑这是你还没有经历过的一点,因为你说“看起来要么测试太简单了,我很容易将其破解为绿色,或者它有点复杂,我需要实现整体对象/图像/文档格式阅读器,这是很多代码。并且没有中间立场。“关键是你应该将它们全部砍成绿色,但是你就是这样做,你也在寻找你的黑客中的模式。
我以这种方式编写了一个(非常简单的)编译器,它的工作效果非常好。对于每个语法结构,我编写了一个我能想到的最小的程序,它以某种可观察的方式使用它,并让测试编译程序并检查它是否按预期工作。我使用了一个合适的解析器生成器,因为你无法合理地TDD进入其中一个(你需要稍微考虑一下!)经过大约三个周期后,很明显我重复了代码来遍历语法树,所以那被重构成像访客一样。
我也进行了大规模的验收测试,但最后我认为这些测试没有发现单元测试没有。