Javascript单元测试-DOM操作

Javascript单元测试-DOM操作,javascript,unit-testing,Javascript,Unit Testing,我对Javascript单元测试非常陌生。有一件事一直困扰着我。在测试javascript时,我们通常需要进行DOM操作。看起来我正在对控制器/组件中的方法/函数进行单元测试,但我仍然需要依赖模板中的HTML元素。一旦id(或在我的测试用例中用作选择器的属性)更改,我的测试用例也需要更改!这难道不会违背单元测试的目的吗?javascript单元测试最困难的部分之一不是测试,而是学习如何构建代码以使其可测试 您需要将可测试逻辑和DOM操作明确分开来构建代码 我的经验是: 如果您正在测试任何依赖于D

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

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

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

我的经验是:

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


总而言之:试着只测试数据操作和逻辑操作。

我认为我支持@BentonCode的建议,即您想要进行单元测试的是您的代码,而不是其他任何东西。当涉及到DOM操作时,这是浏览器代码,如appendChild、replaceChild等。如果您使用jQuery或其他库,同样的情况仍然适用——您调用其他代码来进行操作,并且不需要测试。 那么,您如何断言在viewmodel/controller上调用某个函数会产生您想要的DOM结构呢?你没有。正如您不会进行单元测试一样,在DB上调用存储过程会导致特定表中的特定行。相反,您需要考虑如何从操纵DOM的部分中提取出控制器中处理输入/输出的部分。 例如,如果您有一个基于某些条件调用alert()的方法,则需要将该方法分为两部分:

  • 接收和处理输入的人
  • 调用window.alert()的程序

在测试过程中,您可以用一个假的(请参阅SinonJS)替换window.alert(或它的代理方法),并用导致(或不导致)该警报的条件调用您的输入处理器。然后,您可以根据是否调用了伪函数、调用了多少次、使用了什么值等来断言不同的值。实际上,您不会测试window.alert(),因为它位于代码外部。我们假设这些外部依赖关系正常工作。如果没有,那么这就是该库的一个bug,但是发现这些bug并不是单元测试的工作。您只对验证自己的代码感兴趣。

我不同意@BentonCode。通常,组件不仅仅是它的类。组件组合了一个HTML模板和一个JavaScript/TypeScript类。这就是为什么您应该测试模板和类是否按照预期协同工作。仅类测试可以告诉您类的行为。但他们无法告诉您组件是否将正确渲染并响应用户输入

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


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

谢谢您的回答!但是我们应该在哪里测试DOM操作的部件呢?端到端测试?你有关于这个话题的推荐书/教程吗?我不同意@BentOnCoding。DOM操作是web用户体验的关键部分。如果我们不能测试这一点,那么我们就不擅长我们所做的。DOM测试被忽略了,因为似乎没有一个好的方法来测试它。但是我发现越来越多的库失败了(比如Handlebarsjs),因为DOM不能被精确地测试以进行操作。@BentonCode假设一个web应用程序用一个复杂的日期选择器替换了所有的
。然后,如果我们不验证我们确实选择了正确的元素,那么替换元素的行为似乎是无关紧要的。我将从过去恢复这一点。对于提到的@Cuadue这样的场景,有没有答案?可以采取哪些措施来确保UI按其应有的方式运行,即隐藏/显示/更改元素?某种类似硒的自动化疯狂?@BentOnCoding并不总是这样。不是依赖于DOM结构,而是确保模板正确使用组件逻辑。我可以让一个应用程序有100%的覆盖率,1000个测试,但如果我没有正确的标记来调用组件的逻辑,它就完全没有用了。每种方法都有利弊。这是实际的经验法则。单元与E2E/集成测试:“无论在单元测试级别上测试什么,都应该在单元测试级别上进行测试”,这确实更好。尽管这取决于你的团队或应用程序大小。将大部分测试转移到集成/功能级别将减慢一切。多回购方法可以帮助实现这一点,或者在单回购上进行一些巧妙的设置。