4

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

我的问题是你在处理大型项目时喜欢进入什么节奏,以及测试适合它的地方。

4

12 回答 12

6

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

我和你的处境非常相似。我想更多地进行测试,但我目前正处于我们正在努力“把代码拿出来”而不是“把代码拿出来”的位置,这把我吓坏了。因此,我正在慢慢尝试将测试流程整合到我的开发周期中。

目前,我在编写代码时进行测试,试图在编写代码时破坏代码。我确实发现很难进入 TDD 思维模式。这需要时间,但这是我想要的工作方式。

编辑:

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

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

我希望这会有所帮助.. 对如何改进这一点开放评论,正如我所说,这是我的一个问题..

于 2008-08-22T17:57:37.160 回答
2

在签入代码之前。

于 2008-08-22T17:56:17.913 回答
1

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

然后创建你的接口的默认实现(什么都不做,返回垃圾值但不抛出异常),将其插入测试以确保测试失败(这测试你的测试工作!:))。然后写入功能并重新运行测试。这种机制并不完美,但会涵盖许多简单的编码错误,并为您提供运行新功能的机会,而无需将其插入整个应用程序。

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

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

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

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

于 2008-08-22T18:09:38.427 回答
1

要记住的一个好关键是

“尽早测试,经常测试,然后再测试,当你认为你已经完成了”

于 2008-08-22T18:46:55.387 回答
1

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

于 2008-09-20T05:22:17.457 回答
0

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

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

于 2008-08-22T17:56:38.940 回答
0

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

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

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

于 2008-08-22T18:03:18.223 回答
0

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

  • 表达对每个新代码模块的要求(在我编写接口之后但在编写实现之前)
  • 每次我想“最好……等我做完”
  • 当出现问题时,量化错误并证明我已经修复了它
  • 当我编写显式分配或取消分配内存的代码时---我不愿意寻找内存泄漏......

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

于 2008-08-22T18:03:22.950 回答
0

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

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

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

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

于 2008-08-22T18:05:21.773 回答
0

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

于 2008-08-22T19:00:10.020 回答
0

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

红色:编写测试以使其失败。这样你就知道测试是针对正确的变量断言的。

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

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

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

于 2008-09-10T15:42:43.037 回答
0

这里有很多很棒的答案!

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

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

  • 测试每个功能。

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

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

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

一般而言,您越早遇到错误,就越容易隔离、识别和修复它——而且您有更多的时间花在创造上,而不是追逐自己的尾巴。*

**我知道,-1 用于无偿缓冲指针参考!*

于 2008-10-29T01:14:42.887 回答