简体   繁体   English

Javascript 单元测试 - DOM 操作

[英]Javascript Unit Testing - DOM Manipulation

I'm quite new to Javacript Unit testing.我对 Javacript 单元测试很陌生。 One thing keep bothering me.一件事一直困扰着我。 When testing javascript, we often need to do the DOM manipulation.在测试javascript时,我们经常需要做DOM操作。 It looks like I am unit testing a method/function in a Controller/Component, but I still need to depend on the HTML elements in my templates.看起来我正在对控制器/组件中的方法/函数进行单元测试,但我仍然需要依赖模板中的 HTML 元素。 Once the id(or attributes used to be selectors in my test cases) is changed, my test cases also need to be CHANGED!一旦更改了 id(或在我的测试用例中曾经是选择器的属性),我的测试用例也需要更改! Wouldn't this violate the purpose of unit testing?这不会违反单元测试的目的吗?

One of the toughest parts of javascript unit testing is not the testing, it's learning how to architect your code so that it is testable. javascript 单元测试最困难的部分之一不是测试,而是学习如何构建代码以使其可测试。

You need to structure your code with a clear separation of testable logic and DOM manipulation.您需要通过明确分离可测试逻辑和 DOM 操作来构建代码。

My rule of thumb is this:我的经验法则是这样的:

If you are testing anything that is dependent on the DOM structure, then you are doing it wrong.如果您正在测试任何依赖于 DOM 结构的东西,那么您就做错了。

In summary:Try to test data manipulations and logical operations only.总结:尝试仅测试数据操作和逻辑操作。

I respectfully disagree with @BentOnCoding.我恭敬地不同意@BentOnCoding。 Most often a component is more than just its class.大多数情况下,组件不仅仅是它的类。 Component combines an HTML template and a JavaScript/TypeScript class.组件结合了一个 HTML 模板和一个 JavaScript/TypeScript 类。 That's why you should test that the template and the class work together as intended.这就是为什么您应该测试模板和类是否按预期协同工作。 The class-only tests can tell you about class behavior.仅类测试可以告诉您有关类的行为。 But they cannot tell you if the component is going to render properly and respond to user input.但是他们无法告诉您组件是否会正确呈现并响应用户输入。

Some people say you should test it in integration tests.有人说你应该在集成测试中测试它。 But integration tests are slower to write/run and more expensive (in terms of time and resources) to run/maintain.但是集成测试的编写/运行速度较慢,运行/维护成本更高(在时间和资源方面)。 So, testing most of your component functionality in integration tests might slow you down.因此,在集成测试中测试大部分组件功能可能会减慢您的速度。

It doesn't mean you should skip integration tests.这并不意味着您应该跳过集成测试。 While integration and E2E tests may be slower and expensive than unit tests, they bring you more confidence that your app is working as intended.虽然集成和 E2E 测试可能比单元测试更慢且成本更高,但它们让您更有信心相信您的应用程序正在按预期工作。 Integration test is where individual units/components are combined and tested as a group.集成测试是将单个单元/组件组合起来并作为一个组进行测试的地方。 It shouldn't be considered as an only place to test your component's template.它不应被视为测试组件模板的唯一场所。

I think I'd second @BentOnCoding's recommendation that what you want to unit test is your code , not anything else.我想我第二个@BentOnCoding 的建议是,您要进行单元测试的是您的代码,而不是其他任何内容。 When it comes to DOM manipulation, that's browser code, such as appendChild, replaceChild etc. If you're using jQuery or some other library, the same still applies--you're calling some other code to do the manipulation, and you don't need to test that.当涉及到 DOM 操作时,那就是浏览器代码,例如 appendChild、replaceChild 等。如果您使用 jQuery 或其他一些库,同样的情况仍然适用——您正在调用其他一些代码来进行操作,而您不需要不需要测试。 So how do you assert that calling some function on your viewmodel/controller resulted in the DOM structure that you wanted?那么你如何断言在你的视图模型/控制器上调用一些函数会产生你想要的 DOM 结构? You don't.你没有。 Just as you wouldn't unit test that calling a stored procedure on a DB resulted in a specific row in a specific table.就像您不会对在 DB 上调用存储过程会导致特定表中的特定行进行单元测试一样。 You need to instead think about how to abstract out the parts of your controller that deal with inputs/outputs from the parts that manipulate the DOM.相反,您需要考虑如何从操作 DOM 的部分中抽象出处理输入/输出的控制器部分。 For instance, if you had a method that called alert() based on some conditions, you'd want to separate the method into two:例如,如果您有一个根据某些条件调用 alert() 的方法,您希望将该方法分为两个:

  • One that takes and processes the inputs一个接受和处理输入的
  • One that calls window.alert()一个调用 window.alert()

During the test, you'd substitute window.alert (or your proxy method to it) with a fake (see SinonJS), and call your input processor with the conditions to cause (or not cause) the alert.在测试期间,您将 window.alert(或您的代理方法)替换为一个假的(请参阅 SinonJS),并使用条件调用您的输入处理器以引起(或不引起)警报。 You can then assert different values on whether the fake was called, how many times, with what values, etc. You don't actually test window.alert() because it's external to your code.然后,您可以断言是否调用了 fake 、调用了多少次、使用了什么值等不同的值。您实际上并没有测试 window.alert() 因为它是您的代码的外部。 It's assumed that those external dependencies work correctly.假设这些外部依赖项正常工作。 If they don't, then that's a bug for that library, but it's not your unit test's job to uncover those bugs.如果他们不这样做,那么这是该库的错误,但是发现这些错误不是您的单元测试的工作。 You're only interested in verifying your own code .您只对验证您自己的代码感兴趣。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM