作为一名即将进入第一个专业项目节奏的新手开发人员,我正在努力尽快养成良好的习惯。然而,我发现我经常忘记测试、推迟测试,或者在构建结束时进行一大堆测试,而不是一次进行一个测试。

我的问题是,在从事大型项目时,您喜欢采用什么节奏,以及测试适合其中的哪些位置。

有帮助吗?

解决方案

好吧,如果你想关注 TDD 的人, 在开始编码之前 ;)

我和你的处境非常相似。我想要更多地进行测试,但我目前所处的位置是我们正在努力“获取代码”,而不是“获取正确的代码”,这让我感到害怕。因此,我正在慢慢尝试将测试流程集成到我的开发周期中。

现在, 我一边编码一边测试,尝试在编写代码时破坏代码. 。我确实发现很难进入 TDD 思维模式。这需要时间,但这就是我想要的方式 上班..

编辑:

我想我应该对此进行扩展,这是我的基本“工作流程”......

  1. 从代码,可能的对象设计中计划我想要的内容,等等。
  2. 创建我的头等舱,在顶部添加巨大的评论,概述我的“愿景”是什​​么。
  3. 概述基本测试场景..这些基本上将成为单位测试。
  4. 创建我的第一个方法..还写了一个简短的评论,解释了它是如何的 预期的 上班。
  5. 编写一个自动化测试,看看它是否符合我的预期。
  6. 对每种方法重复步骤 4-6(请注意,自动化测试位于在 F5 上运行的巨大列表中)。
  7. 然后,我创建一些强大的测试来模拟工作环境中的类,显然可以解决任何问题。
  8. 如果在此之后发现任何新的错误,我就会返回并编写新的测试,确保它失败(这也可以作为该错误的概念验证),然后修复它。

我希望这有帮助..对如何改进这一点的评论持开放态度,正如我所说,这是我关心的问题。

其他提示

在签入代码之前。

首先而且经常。如果我要为系统创建一些新功能,我将首先定义接口,然后为这些接口编写单元测试。要确定要编写哪些测试来考虑接口的 API 及其提供的功能,请拿出笔和纸,思考一下潜在的错误条件或证明它正在执行正确工作的方法。如果这太困难,那么您的 API 可能不够好。关于测试,看看是否可以避免编写测试多个特定对象的“集成”测试,并将它们保留为“单元”测试。

然后创建接口的默认实现(不执行任何操作,返回垃圾值,但不引发异常),将其插入测试以确保测试失败(这测试您的测试是否有效!:) )。然后写入功能并重新运行测试。这种机制并不完美,但会覆盖许多简单的编码错误,并为您提供运行新功能的机会,而无需将其插入整个应用程序。

接下来,您需要结合现有功能在主应用程序中对其进行测试。这是测试更加困难的地方,如果可能的话,应该将部分外包给优秀的 QA 测试人员,因为他们有破坏事物的诀窍。如果您也具备这些技能,这会很有帮助。说实话,正确进行测试是您必须掌握的技巧。我自己的经验来自于我自己的幼稚部署以及用户在愤怒使用它时报告的后续错误。

起初,当这种情况发生在我身上时,我发现用户故意试图破坏我的软件而感到恼火,我想将所有“错误”标记为“培训问题”。然而,经过反思,我意识到我们(作为开发人员)的角色是使应用程序尽可能简单可靠,即使是白痴也可以使用。我们的职责是赋予白痴权力,这就是我们获得美元报酬的原因。白痴处理。

为了有效地进行这样的测试,您必须进入尝试打破一切的心态。假设用户的职责是猛击按钮并通常试图以奇怪而奇妙的方式破坏您的应用程序。假设如果你没有发现缺陷那么它们将在生产中被发现给你的公司带来严重的颜面损失。对所有这些问题承担全部责任,并在生产中发现您负责(甚至部分负责)的错误时诅咒自己。

如果您完成了上述大部分操作,那么您应该开始编写更健壮的代码,但是它有点像一种艺术形式,需要大量的经验才能擅长。

需要记住的一个好关键是

“尽早测试,经常测试,当你认为已经完成时再次测试”

什么时候测试?当代码正确运行很重要时!

当我自己组装一些东西时,我会在最后进行测试。不好的做法,但这些通常都是小东西,我会使用几次,仅此而已。

在一个较大的项目中,我在编写类之前编写测试,并在每次对该类进行更改后运行测试。

我不断地测试。在完成函数内部的循环后,我运行程序并在循环顶部命中断点,然后运行它。这只是为了确保该过程完全按照我的意愿进行。

然后,一旦一个功能完成,就可以对其进行整体测试。您可能想在调用函数之前设置一个断点,并检查调试器以确保它正常工作。

我想我会说:“经常测试。”

我最近才将单元测试添加到我的常规工作流程中,但我编写了单元测试:

  • 表达每个新代码模块的需求(在我编写接口之后但在编写实现之前)
  • 每当我想“最好...当我完成时”
  • 当出现问题时,量化错误并证明我已经修复了它
  • 当我编写显式分配或释放内存的代码时——我讨厌寻找内存泄漏......

我在大多数构建上运行测试,并且总是在运行代码之前运行。

从单元测试开始。具体来说,请查看 TDD(测试驱动开发)。TDD 背后的概念是先编写单元测试,然后编写代码。如果测试失败,您将返回并重新编写代码。如果通过了,您将继续进行下一个。

我对 TDD 采用混合方法。我不喜欢针对任何东西编写测试,所以我通常先编写一些代码,然后放入单元测试。这是一个迭代的过程,一个你永远不会真正完成的过程。您更改代码,运行测试。如果有任何失败,请修复并重复。

另一种测试是集成测试,它在流程的后期进行,通常由 QA 测试团队完成。无论如何,集成测试解决了将各个部分作为一个整体进行测试的需要。这是您关心测试的工作产品。这个问题更难处理,因为它通常涉及自动化测试工具(例如机器人)。

另外,请查看像 CruiseControl.NET 这样的产品来进行持续构建。CC.NET 很好,因为它会在每次构建时运行您的单元测试,并立即通知您任何失败。

我们在这里不进行 TDD(尽管有些人提倡这样做),但我们的规则是您应该检查您的单元测试以及您的更改。它并不总是发生,但是很容易返回并查看特定的变更集并查看是否编写了测试。

我发现,如果我等到编写一些新功能结束时才进行测试,我会忘记许多我认为可能会破坏该功能的边缘情况。如果您正在做一些自学的事情,那么这是可以的,但在专业环境中,我发现我的流程是以下经典形式:红色、绿色、重构。

红色的: :编写你的测试,使其失败。这样您就知道测试正在针对正确的变量进行断言。

绿色的: :以最简单的方式让您的新测试通过。如果这意味着对其进行硬编码,那也没关系。这对于那些只想立即发挥作用的人来说非常有用。

重构: :现在您的测试已通过,您可以放心地返回并更改代码。你的新改变打破了你的测试?太好了,您的更改有一个您没有意识到的含义,现在您的测试正在告诉您。

这种节奏使我随着时间的推移加快了开发速度,因为我基本上有一个历史编译器,用于处理我认为需要检查才能使功能正常工作的所有内容!反过来,这会带来许多其他好处,我不会在这里讲到......

这里有很多很棒的答案!

我尝试在有意义的最低级别进行测试:

  • 如果单个计算或条件很困难或复杂,请在编写时添加测试代码并确保每部分都能正常工作。完成后注释掉测试代码,但将其留在那里以记录您如何测试算法。

  • 测试每个功能。

    • 每个分支至少锻炼一次。
    • 锻炼 边界条件 -- 代码改变其行为的输入值 -- 捕获“差一”错误。
    • 测试有效和无效输入的各种组合。
    • 寻找可能破坏代码的情况并进行测试。
  • 使用与上述相同的策略测试每个模块。

  • 将代码主体作为一个整体进行测试,以确保组件正确交互。如果您一直在努力进行较低级别的测试,那么这本质上是一个“置信度测试”,以确保组装过程中没有任何损坏。

由于我的大部分代码都是针对嵌入式设备的,因此我特别关注鲁棒性、各种线程、任务和组件之间的交互以及资源的意外使用:内存、CPU、文件系统空间、 ETC.

一般来说,越早遇到错误,就越容易隔离、识别和修复它,并且您可以花更多的时间来创造而不是追寻自己的尾巴。*

**我知道,-1 表示无偿的缓冲区指针引用!*

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top