【问题标题】:Javascript Unit Testing - DOM ManipulationJavascript 单元测试 - DOM 操作
【发布时间】:2013-09-22 01:05:03
【问题描述】:

我对 Javacript 单元测试很陌生。一件事一直困扰着我。在测试 javascript 时,我们经常需要进行 DOM 操作。看起来我正在对控制器/组件中的方法/函数进行单元测试,但我仍然需要依赖模板中的 HTML 元素。一旦更改了 id(或在我的测试用例中用作选择器的属性),我的测试用例也需要更改!这不会违反单元测试的目的吗?

【问题讨论】:

    标签: javascript unit-testing


    【解决方案1】:

    javascript 单元测试最困难的部分不是测试,而是学习如何构建代码以使其可测试。

    您需要将可测试逻辑和 DOM 操作明确分离来构建代码。

    我的经验是这样的:

    如果您正在测试任何依赖于 DOM 结构的东西,那么您做错了。

    总结:尽量只测试数据操作和逻辑操作。

    【讨论】:

    • 感谢您的回答!但是我们应该在哪里使用 DOM Manipulation 来测试这些部分呢?端到端测试?你有没有推荐的关于这个话题的书籍/教程?
    • 我不同意@BentOnCoding。 DOM 操作是 Web 用户体验的关键部分。如果我们不能对此进行测试,那么我们就不擅长我们所做的事情。 DOM 测试被忽略了,因为似乎没有一个好的方法来测试它。但我发现越来越多的库(例如 Handlebarsjs)失败了,因为无法准确地测试 DOM 的操作。
    • @BentOnCoding 假设一个 Web 应用程序用一个复杂的日期选择器替换了所有 <input class='myFancyDateBox'>。然后,如果我们不验证我们确实选择了正确的元素,替换元素的行为似乎无关紧要。
    • 我正在从过去复活这个。像@Cuadue提到的场景有答案吗?可以做些什么来确保 UI 以应有的方式运行,即隐藏/显示/更改元素?某种类似 Selenium 的自动化疯狂?
    • @BentOnCoding 并非总是如此。不是您依赖于 DOM 结构,而是您确保模板正确使用您的组件逻辑。如果我没有正确的标记来调用组件的逻辑,我可以使应用程序具有 100% 的覆盖率、1000 次测试,但它完全无用。每种方法总是有利有弊。这是要考虑的实际经验法则。
    【解决方案2】:

    我非常不同意@BentOnCoding。大多数情况下,组件不仅仅是它的类。组件结合了 HTML 模板和 JavaScript/TypeScript 类。这就是为什么您应该测试模板和类是否按预期协同工作的原因。仅类测试可以告诉您类行为。但他们无法告诉您组件是否会正确呈现并响应用户输入。

    有人说你应该在集成测试中测试它。但是集成测试的编写/运行速度较慢,运行/维护成本更高(在时间和资源方面)。因此,在集成测试中测试大部分组件功能可能会减慢您的速度。

    这并不意味着您应该跳过集成测试。虽然集成和 E2E 测试可能比单元测试更慢且成本更高,但它们让您更加确信您的应用程序正在按预期工作。集成测试是将单个单元/组件组合在一起并作为一个组进行测试的地方。它不应被视为测试组件模板的唯一场所。

    【讨论】:

    • 单元与 e2e/集成测试:“无论什么可以在单元测试级别进行测试,都应该在单元测试级别进行测试”
    • 确实,这样更好。虽然这取决于您的团队或应用程序大小。将大部分测试转移到集成/功能级别会减慢一切。多仓库方法可以帮助解决这个问题,或者在单仓库上进行一些巧妙的设置。
    【解决方案3】:

    我想我会赞同@BentOnCoding 的建议,即您要进行单元测试的是您的代码,而不是其他任何东西。当涉及到 DOM 操作时,就是浏览器代码,例如 appendChild、replaceChild 等。如果您使用 jQuery 或其他库,同样适用——您正在调用其他代码来执行操作,而您不需要不需要测试。 那么你如何断言在你的视图模型/控制器上调用某些函数会产生你想要的 DOM 结构呢?你没有。就像您不会对在数据库上调用存储过程导致特定表中的特定行进行单元测试一样。相反,您需要考虑如何从操纵 DOM 的部分中抽象出控制器中处理输入/输出的部分。 例如,如果您有一个基于某些条件调用 alert() 的方法,您可能希望将该方法分成两个:

    • 接受和处理输入的人
    • 调用 window.alert() 的方法

    在测试期间,您将 window.alert(或您的代理方法)替换为假的(请参阅 SinonJS),并使用引发(或不引发)警报的条件调用您的输入处理器。然后,您可以断言是否调用了伪造品、多少次、使用什么值等不同的值。您实际上并不测试 window.alert() 因为它在您的代码之外。 假设这些外部依赖项正常工作。如果他们不这样做,那么这就是该库的错误,但发现这些错误不是您的单元测试的工作。您只对验证您自己的代码感兴趣。

    【讨论】:

      猜你喜欢
      • 2013-05-27
      • 2010-11-28
      • 2013-04-16
      • 1970-01-01
      • 1970-01-01
      • 2011-12-02
      • 2012-05-20
      • 1970-01-01
      相关资源
      最近更新 更多