【发布时间】:2009-12-11 23:06:42
【问题描述】:
所以 - 管理层正在寻求推动在所有未来的应用程序中进行单元测试 - 并最终进入完整的 TDD/持续集成/自动化构建模式(我希望如此)。然而,在这一点上,我们只关心让每个开发应用程序的人都使用单元测试向前发展。我想从基础开始。
我不会撒谎 - 我在单元测试方面无论如何都不是专家,但我确实有足够的理解来从基础开始这项计划,并让我们作为一个团队共同成长。我真的很想从你们所有的专家那里得到一些关于我对这件事的攻击计划的批评和批评。这是一个由大约 10 名开发人员组成的小商店团队,这为推进敏捷开发方法和最佳实践提供了绝佳机会。
首先 - 团队主要由中级开发人员组成,有几个初级开发人员和一个高级开发人员,他们几乎没有接触过单元测试。培训将是每半个月一次的会议,每次约 30-60 分钟(我猜可能会跑一个小时,而且可能更频繁)。我们将继续这些会议,直到有必要阻止他们让其他人赶上他们自己的“功课”和经验——但我们会一直在推动。
无论如何 - 这是我想出的课程计划。好吧,至少前两个。您的专家就课程的实际内容或结构等提供的任何建议都会很棒。非常感谢评论和批评。非常感谢。
如果这“太多”无法在此处发布或通读,我深表歉意。我认为对于希望首先进行单元测试的 SO 用户来说,这将是一个很好的线程。也许您可以直接跳到“课程计划”部分 - 再次感谢大家。
悬崖笔记 - 我意识到这篇文章非常长而且丑陋,所以这里是悬崖笔记 - 第 1 课将是“hello world 单元测试” - 第 2 课将为我最近的应用程序打开解决方案,并展示如何在现实生活中应用每个“hello world”示例......非常感谢大家迄今为止给我的反馈......只是想强调一个事实第 2 课 将包含现实生活中的生产单元测试,因为很多人建议我这样做,而这是我从一开始的计划 =)
单元测试课程计划
概述
为什么要进行单元测试?看起来像是一堆额外的工作 - 那为什么要这样做?
• 成为自己命运的主人。我们的大多数用户不做真正的 UAT,不幸的是,他们倾向于在生产中进行一次测试。通过单元测试,我们大大降低了与此相关的风险,特别是当我们创建足够的测试数据并尽可能多地考虑顶级输入时。虽然它不是防止所有错误的“灵丹妙药”——它是你的第一道防线——但它是一条巨大的前线,可与 SB 冠军巨人队相媲美。
• 单元测试强制执行良好的设计和架构实践。可以这么说,是“维护你的代码并知道你住在哪里的暴力精神病患者”。您根本无法编写经过良好单元测试的低质量代码
• 您有多少次因为太害怕破坏某些东西而没有重构臭代码?自动化测试消除了这种恐惧,使重构变得更加容易,进而使代码更具可读性和更易于维护。
• 底线 - 维护变得更容易和更便宜。现在花在编写单元测试上的时间可能很昂贵——但它为你节省的时间已经一次又一次地被证明是更有价值的。这是自动化测试代码的第一大理由。它给了我们信心,使我们能够对系统进行更雄心勃勃的更改,否则我们可能不得不减少对系统的要求,甚至可能根本不进行。
术语审查
• 单元测试 - 测试最低级别的单个工作单元。例如。 – 测试单个函数可以通过的所有可能的代码路径。
• 集成测试 - 测试您的单元如何协同工作。例如。 – 运行一个“工作”(或一系列函数调用),它使用已知输入完成大量工作 – 然后在最后查询数据库并断言这些值是您对这些已知输入的期望值(而不是必须关注- 在某处的网页上放置一个网格,例如进行功能测试)。
• 赝品——赝品是一种用于测试的对象。它允许您太容易不测试您不想测试的代码。不必调用您不想要的代码(例如数据库调用),您可以使用假对象来“伪造”该数据库调用,并可能从 XML/Excel 文件或模拟框架中读取数据。 o Mock – 一种您对其作出断言声明的假货。 o 存根 – 一种用作占位符代码的伪代码,因此您可以跳过数据库调用,但不要针对其进行断言
课程
第一课 - Hello Worlds
• Hello World 单元测试 - 我将创建一个经过单元测试的“hello world”控制台应用程序。将在会议期间即时创建此应用程序,展示 Visual Studio 2008 中的工具(测试项目、测试工具工具栏等),同时解释它们的作用。这将只有一个单元测试。 (好吧,也许我不会“即时”创建它=),必须多考虑一下)。还将解释 Assert 类及其用途以及单元测试的一般流程。
• Hello World,有点复杂。现在我们的函数有不同的路径/逻辑分支代码可以流过。我们将对此功能进行大约 3 个单元测试。这将是我在会议之前预先制定的解决方案。
• Hello World,依赖注入。 (不使用任何 DI 框架)。一种基于前一个解决方案的预写解决方案,这次使用依赖注入。将解释什么是 DI 并展示其工作原理的示例。
• Hello World,模拟对象。一个基于前一个解决方案的预写解决方案,这次使用我们新添加的 DI 代码将模拟对象注入到我们的类中,以展示模拟是如何工作的。将使用 NMock2.0,因为这是我接触过的唯一一个。非常简单的示例,仅显示模拟对象的使用。 (也许把这个放在单独的课程中?)。
• Hello World,(非自动)集成测试。在之前的解决方案的基础上,我们创建了一个集成测试,以展示如何一起测试 2 个函数,或一起测试整个类(也许将这个放在单独的课程中?)
第二课——现在我们知道了基础知识——如何在现实生活中应用它?
• 最佳实践概述 o 规则 #1 - 单一责任主体。单一责任主体。单一责任主体。开玩笑地说这是编写代码时要记住的最重要的事情。一个类应该只有一个目的;一个函数应该只做一件事。这里的关键词是“单元”测试——SRP 会将你的类和函数封装到单元中。 o 依赖注入是你第二好的朋友。 DI 允许您在运行时将行为“插入”到您拥有的类中。除此之外,这就是我们使用模拟框架使我们的更大类更容易测试的方式。
o 在编写代码时,请始终考虑“我将如何测试它”。如果它看起来“太难测试”,很可能是你的代码太复杂了。重新分解,直到它变成更多逻辑单元的类/函数 - 把一个做 5 件事的类变成 5 个类,一个调用另一个 4 个。现在你的代码将更容易测试 - 也更容易阅读和重构。
o 测试行为,而不是实施。简而言之,这意味着我们可以在大多数情况下只测试我们类上的公共函数。我们不关心测试私有的(实现),因为公共的(行为)是我们调用代码使用的。例如……我是一个百万富翁的软件开发人员,去阿斯顿马丁经销商处为自己买了一辆全新的 DB9。销售人员告诉我,它可以在 3 秒内完成 0-60。你将如何测试这个?你会举起发动机并进行诊断测试等吗?不...你会把它带到大路并以 160 英里/小时的速度行驶 =)。这是测试行为与实施。
• 审查一个真实的单元测试应用程序。在这里,我们将回顾上面的每个“hello world”示例——但以我最近的项目为例,但都是现实生活中的版本。我将打开一个简单的单元测试,一个更复杂的单元测试,一个使用 DI,一个使用 Mocks(可能与 DI 耦合)。这个项目相当小而且简单,所以它真的很适合。这还将包括测试 DAL 以及如何设置测试数据库来运行这些测试。
【问题讨论】:
-
在我的眼睛累了之前,我已经到了第二段。
-
哇.. 写所有这些的道具
-
好吧,我看不懂这么长的问题。最多两段你真正的问题是什么?
-
对不起,我确实提前道歉了 =)。我只是希望 cmets & 批评我教一个对单元测试一无所知的团队的方法。有什么好处吗?我应该改变什么?从 hello world 样本开始并让它们变得更复杂是一种好方法吗???
-
读起来有点多,但我设计了一个非常相似的培训。这是不容易的。让它粘起来更难。我的一些观察如下。
标签: unit-testing