javascript 如何对 (Angularjs) Web 应用程序进行集成测试
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/19078962/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to do Integration Testing for (Angularjs) Web Apps
提问by
I'm developing an Webapp. It consists of 2 parts. A node rest server and an angularjs client.
我正在开发一个 Web 应用程序。它由 2 个部分组成。一个节点休息服务器和一个 angularjs 客户端。
The app is structured this way: Rest Server <--> Api Module <--> Angular App
该应用程序的结构如下:Rest Server <--> Api Module <--> Angular App
The server is currently well tested. I have Unit Tests and Integration Tests. The Integration Tests are accessing a real database and calling the rest api over http. I think this is as high level as it can get for the server testing. The integration tests run fast, too. I'm pretty confident that the way I tested the server is sufficient for my use case and I'm happy with the results.
该服务器目前经过良好测试。我有单元测试和集成测试。集成测试正在访问一个真实的数据库并通过 http 调用其余的 api。我认为这是服务器测试所能达到的最高水平。集成测试也运行得很快。我非常有信心我测试服务器的方式足以满足我的用例,我对结果很满意。
However I'm struggling how to test the angularjs app. I have unit tests for the relevant directives and modules. Writing these wasn't an issue.
但是,我正在努力测试 angularjs 应用程序。我有相关指令和模块的单元测试。写这些不是问题。
I would like to write integration tests that cover user scenarios. Something like a signup scenario: The user visits the website, goes to the signup form, and submits the form with the data.
我想编写涵盖用户场景的集成测试。类似于注册场景:用户访问网站,转到注册表单,然后提交包含数据的表单。
The angularjs team is moving from ng-scenariosto protractor. Protractor is using Selenium to run the tests. Therefore there are two scopes: The app scope and the test scope.
angularjs 团队正在从ng-scenarios转向protractor。Protractor 使用 Selenium 来运行测试。因此有两个范围:应用范围和测试范围。
Now I can think of three different abstractions I could use. And I'm not sure which one suites me best.
现在我可以想到我可以使用的三种不同的抽象。而且我不确定哪一种最适合我。
- Mock the Api Module
- Mock the Rest Server
- Use the full server
- 模拟 Api 模块
- 模拟 Rest 服务器
- 使用完整服务器
Mock the Api Module
模拟 Api 模块
In this case I would need not to setup a server. All Interactions are running in the browser
在这种情况下,我不需要设置服务器。所有交互都在浏览器中运行
Advantage:
优势:
- No server is needed
- 不需要服务器
Disadvantage:
坏处:
- The api is in the browser scope and I have to tamper with this.
- api 在浏览器范围内,我必须篡改它。
I really like this solution, but I find it difficult to mock the Api.
The Api needs to be modified in the browsers scope.
Therefore I need to send the modification from the test to the browser.
This can be done, however I don't see how I could run assertions like mockedApi.method.wasCalledOnce()
in the tests scope
我真的很喜欢这个解决方案,但我发现很难模拟 Api。需要在浏览器范围内修改 Api。因此我需要将修改从测试发送到浏览器。这可以完成,但是我不知道如何mockedApi.method.wasCalledOnce()
在测试范围内运行断言
Mock the Rest Server
模拟 Rest 服务器
Advantage:
优势:
- Client would be unchanged
- Only one scope to deal with
- 客户端将保持不变
- 只处理一个范围
Disadvantage:
坏处:
- One has to setup the Rest Routes
- 必须设置休息路线
I could create a complete Mock Rest Server in nodejs.
Protractor Tests are written in nodejs, thus the control of the server can be done in the test.
Before I run the test I can tell the server how to respond.
Something like this: server.onRequest({method: 'GET', url: '/'}).respondWith('hello world')
我可以在 nodejs 中创建一个完整的 Mock Rest 服务器。Protractor 测试是用 nodejs 编写的,因此可以在测试中完成对服务器的控制。在我运行测试之前,我可以告诉服务器如何响应。像这样的东西:server.onRequest({method: 'GET', url: '/'}).respondWith('hello world')
Then I could do assertions like wasCalledOnce
然后我可以做这样的断言 wasCalledOnce
Use the full Server with Database
使用带有数据库的完整服务器
Each test is running with a complete server and can add elements to the database. After each test one can look at the expected elements in the database
每个测试都在一个完整的服务器上运行,并且可以向数据库添加元素。每次测试后,可以查看数据库中的预期元素
Advantage:
优势:
- Can be pretty sure, that if these tests are running the app is functional in the tested use case
- 可以肯定的是,如果这些测试正在运行,则应用程序在测试用例中可以正常运行
Disadvantage:
坏处:
- I already made a fairly intense integration test with the rest server. This feels like doing the same again.
- Setup depends on the full server
- 我已经与其余服务器进行了相当密集的集成测试。这感觉就像再次做同样的事情。
- 设置取决于完整的服务器
Current Conclusion
当前结论
- Mocking the Api would separate the server and the client completely.
- Using a Mock Api would be a higher level test, but would require a fake server
- Doing a full integration test would give the best reliability, but this is also highly dependant on the server code
- 模拟 Api 将完全分离服务器和客户端。
- 使用 Mock Api 将是一个更高级别的测试,但需要一个假服务器
- 进行完整的集成测试将提供最佳的可靠性,但这也高度依赖于服务器代码
What should I pick? What would you do?
我应该选择什么?你会怎么做?
回答by Kenneth Baltrinic
I think I answered this same question in the Protractor google group. I am much of the same mind as you about wanting no server but wanting all of my test code in one place (in Protractor) and not split between Protractor and the browser. To enable this, I took matters into my own hand and developed a proxy for the $httpBackend service which runs within Protractor. It allows one to configure the $httpBackend service as if it were running in Protractor. I have been working on it for a while now and its reasonably full featured at this point. It would be great if you could take a look and let me know if I am missing anything important.
我想我在 Protractor google group 中回答了同样的问题。我和你的想法很相似,不想要服务器,但想要我所有的测试代码在一个地方(在量角器中),而不是在量角器和浏览器之间分开。为了实现这一点,我自己动手并为在 Protractor 中运行的 $httpBackend 服务开发了一个代理。它允许配置 $httpBackend 服务,就像它在 Protractor 中运行一样。我已经研究它一段时间了,在这一点上它的功能相当齐全。如果您能看一看并让我知道我是否遗漏了任何重要信息,那就太好了。
回答by bdavidxyz
It is an excellent question, which has nothing to do with a particular tool. I had to face the same problem on a big "greenfield" (ie started from scratch) project.
这是一个很好的问题,与特定工具无关。我不得不在一个大的“绿地”(即从头开始)项目中面临同样的问题。
There is a problem of vocabulary here : the word "mock" is used everywhere, and what you called "integration test" are more "full end-to-end automated functional testing". No offence here, it's just that a clear wording will help to solve the problem.
这里有一个词汇问题:“mock”这个词随处可见,而你所说的“集成测试”更多的是“完整的端到端自动化功能测试”。这里没有冒犯,只是明确的措辞将有助于解决问题。
You actually suggested the correct answer yourself : #2 stub the rest server. #1 is feseable but will be soon too hard to develop and maintain, #3 is an excellent idea but has nothing to do with UI testing and UI validation.
您实际上自己建议了正确答案:#2 存根其余服务器。#1 是可行的,但很快就会难以开发和维护,#3 是一个好主意,但与 UI 测试和 UI 验证无关。
To achieve a high reliability of your front-end, independently of your backend, just stub the rest server, i.e. develop a stupid simple REST server that will idempotent, i. e. will ALWAYS answer the same thing to one http request. Keeping the idempotence principle will make development and test, very, very easier than any other option.
为了实现前端的高可靠性,独立于后端,只需存根其余服务器,即开发一个愚蠢的简单 REST 服务器,它将是幂等的,即始终对一个 http 请求回答相同的事情。保持幂等原则将使开发和测试比任何其他选择都容易得多。
Then for one test, you only check what is displayed on the screen (test the top) and what is send to the server (test the bottom), so that the full UI stack is tested only once.
然后对于一个测试,你只检查屏幕上显示的内容(测试顶部)和发送到服务器的内容(测试底部),这样整个 UI 堆栈只测试一次。
The full answer to the question should deserve an entire blog article, but I hope you can feel what to do from what I suggest.
这个问题的完整答案应该写一整篇博客文章,但我希望你能从我的建议中感受到该怎么做。
Best regards
最好的祝福
回答by TGH
Here is an approach for writing integration tests for your Angular code. The key concept is to structure your code in a way that lets you invoke the various functions in a way very similar to how it's consumed by the UI. Properly decoupling your code is important to be successful at this though:
这是为 Angular 代码编写集成测试的方法。关键概念是以某种方式构建您的代码,使您能够以与 UI 使用它的方式非常相似的方式调用各种函数。正确解耦您的代码对于在此方面取得成功很重要:
More here: http://www.syntaxsuccess.com/viewarticle/angular-integration-tests
更多信息:http: //www.syntaxsuccess.com/viewarticle/angular-integration-tests
回答by Bruno Santos
Mocking the REST server is the best, cleaner option in my opinion. Try Mountebank (http://www.mbtest.org). An amazing Virtualization Service tool.
在我看来,模拟 REST 服务器是最好的、更干净的选择。试试 Mountebank ( http://www.mbtest.org)。一个了不起的虚拟化服务工具。
回答by SHernandez
This is a great question. This is how I would do it:
这是一个很好的问题。这就是我将如何做到的:
As you already have the angular unit tests for the relevant directives and modules this is perfect.
由于您已经对相关指令和模块进行了角度单元测试,因此这是完美的。
The other thing that is perfect is that your server Integration Tests are accessing a real database and are also making sure the rest api over http works.
另一件完美的事情是您的服务器集成测试正在访问一个真实的数据库,并且还确保 http 上的其余 api 正常工作。
So why not just add some high level integration tests that include angular and your server at the same time.
那么为什么不添加一些同时包含 angular 和服务器的高级集成测试呢?
If you can avoid mocking, why not save the work to maintain the extra code, if possible.
如果可以避免模拟,为什么不保存工作以维护额外的代码,如果可能的话。
Also a good read: http://blog.ericbmerritt.com/2014/03/25/mocking-is-evil.html
也很好读:http: //blog.ericbmerritt.com/2014/03/25/mocking-is-evil.html