We've just started developing a web app with AngularJS and we're having some problems with testing it properly so we could use some advice.
Generally, there are the following components to test:
Web API
Angular Controllers
Angular routing
HTML rendering and Angular binding of Controllers to the HTML elements
How does one test all of this with minimal effort and no, if possible, overlap?
For any database-centric application, complete integration testing (i.e. with a live server, connected to a database loaded with data) would be particularly messy because there would have to be a process that generates sufficient data for all tests and resets the DB and tests would have to be careful not to modify each other's data. (if I'm missing something here please let me know)
Given the above point, I'm assuming it is best to sever the link between server and client and run the Angular tests using mock data only.
Also, I'm assuming that if E2E testing takes care of all possible scenarios, unit testing controllers is redundant as their values are bound to the model (and would thus be testing all of 2, 3 and 4 above). Unit testing would only be helpful in very complex controllers or to test services and directives.
However, we could not find any information on how to mock stuff with $httpBackend on a per-test basis like you would do in unit tests, using expect*(). Angular docs seem to suggest using when*() plus the occasional passthrough() when necessary.
But, this poses the aforementioned problem of creating test data for all scenarios and you'd probably need to reset the in-memory DB before each test to be sure the tests are not affected. Also, you're losing the safety of using $httpBackEnd.expect*() which checks that there are no missing or redundant calls to the server - This would suggest to me that it would also require unit testing controllers to check this.
Can someone provide a detailed testing strategy for AngularJS apps that addresses the testing of the 4 components above as well as the concerns written above?
Not sure - since your angular app is theoretically decoupled from your backend, there's no particular reason that angular tests and backend tests need to be commingled. I would test them separately, with each test suite assuming that the other component works fine. (So when testing angular, you assume that the server will work as expected.)
Unit tests - they provide more depth than E2E tests. It's easier to verify specific conditions the code will face. It's also easy to mock out all dependencies as necessary and test just the component the unit tests is interested in. Unit tests don't concern themselves with how the UI works, or that the right data is bound correctly, but rather than the business logic of the app is correct.
(and 4) E2E tests - less granularity, focusing on making sure the UI looks as expected from an end user perspective. You are right that it's messy to test against a live database (although some people enjoy the safety provided by a full end-to-end integration test), and so you should use $httpBackend to mock out the server.
Refer this https://www.sitepoint.com/unit-and-e2e-testing-in-angularjs/.
If your service/factory uses the http service to call a remote API you can return fake data from it for unit testing.If you are starting a new Angular project consider using Protractor for E2E tests.
Related
What is the correct way to write E2E tests using Cypress for my front-end React app and a 3rd-party API (server) that is not under my control?
Server not been under my control, means I can't seed the DB with test data to perform a specific test.
Although, I am aware of stubbing the responses I get back from the server, I feel that an E2E test should be as close as to real life (not stubbing or mocking things).
In my case, maybe stubbing is the only way to go. I don't know, as I'm new to testing.
Any help?
Beside stubbing there is another solution onboard of Cypress called 'Mocking'. In that case you feed the test the response you expect it to get. That is exactly
the solution which we are using in our frontend to really test the application. But beside those tests we have (what we call smoke-tests) which do a real E2E test. We choose to make the E2E more like a sanity test. For example:
Our mocked test does checks for complete forms including error handling. Our smoke-tests only tests 1 happy path and 1 sad path. If those two work, we dare to conclude that all mocked tests also work in real life.
I'm currently working on a Rails project that uses RSpec as the testing framework. We have different Rails fixture data that helps us test our UI when we're in different states.
However, I've been intrigued with using TestCafe to handle our functional UI testing. I've played around with various examples of the website and it seems great to use. But the one part holding me back from introducing it into my project is I'm not sure how to use TestCafe to set up something equivalent to Rails fixture data - i.e. I want to use TestCafe to set up different scenarios where my database is in a particular state so that I can then test the UI.
I've tried searching through TestCafe's documentation but haven't had much luck since TestCafe seems to use the word "fixtures" to represent a particular page you're testing and not the mock data.
Unfortunately there is no built-in support for handling test databases. But because tests are executed in Node.js environment, you can use e.g. db-migrate and js-yaml modules to load your fixtures to the test database.
I'm presently working on a very large modular web app. where the front-end is implemented using AngularJS 1.x. The project is about 2 years old and there was never any unit testing done as part of the development process. There is now a requirement to add unit testing for at least 85% of the Angular codebase. The general consensus seems to be: "Use Jasmine/Karma or Mocha/Chai/Sinon" for unit testing.
My concern after looking at the usual testing libraries is the amount of work that will need to be put in for data mocks and unit testing in general. It seems excessive and almost as bad as re-developing the application. Recently I've also read a couple of articles regarding the general overhead of unit testing with sophisticated testing libraries like Jasmine (see: https://medium.com/javascript-scene/why-i-use-tape-instead-of-mocha-so-should-you-6aa105d8eaf4#.1bzhv0q1f)
The part about using Tape JS to test got me wondering whether that is easily done in Angular 1.x. I've very new to unit testing and wanted to find out whether anyone has done unit testing using Tape with Angular 1.x? Is this possible?
Thoughts on pros/cons/experiences with Tape and generally unit testing in Angular, would be greatly appreciated.
Thank you.
Following up on my comment.
I think the reason everyone uses Jasmine is that they want to test their code through the AngularJS interface, and that requires a test harness.
For example - let's say you are writing a test for a component. You will have to bootstrap the component's angular.module. You'll also have to create an instance of the component's controller through $componentController. And if the controller requires any dependencies, you'll have to make sure those dependencies also have their angular.module bootstrapped.
Jasmine does all this great.
However, Jasmine can very quickly become unwieldy. It introduces all sorts of global variables. There is a ton of repetition involved with BeforeEach. And to run your tests, you'll probably have to use Karma, which requires a lot of dependencies and is pretty darn slow.
I think you could skip all this and just use TapeJS if you were okay with testing your code as plain old javascript. I think this approach is okay for unit tests -- but for e2e tests, you should dive into jasmine/protractor.
For example, my AngularJS applications are written in Typescript with class syntax. Every component controller and service is a typescript class that is also exported. So to test with TypeJS, all you have to do is import the typescript class, create an instance of it, and voila. You now have access to all the methods (assuming they are all public), and you can test that input/output works as expected.
This should work fine for AngularJS 1.5+, but if you have an app with a lot of directives, I'm not sure how that would work.
I do hope this helps. Spending days trying to get test runners to work is the worst.
Read more:
https://ponyfoo.com/articles/testing-javascript-modules-with-tape
Is there a way we can use QUnit to do E2E testing on Angular client?
I don't wish to mock the data from server but need to test real time response from service validating client services too.
Is there a work around, since what I've read that "angular-mock" has to be used for sending a request but it only mocks the server rather than sending an actual request to server.
I need to only code tests for service layer, therefore I'd like to make use of my QUnit tests (already written).
My last resort will be opting for Jasmine if this fails. :/
There is a wording confusion here. The question should be "how to write integration test with AngularJS".
What you are trying to do is to test two pieces of software together, which mean no unit test, but you are also not testing the whole angularJS app, so you are not doing e2e test either.
There is a karma-qunit-adapter that suggest your service layer could be test with QUnit, but as the name of the framework suggest it is to be used for unit testing purpose, so the solution you will achieve may be hacky. You will have to write your own generic adapters to test input/output requests.
I want to do a smoke test in order to test the connection between my web app and the server itself. Does Someone know how to do it? In addition I want to do an acceptance tests to test my whole application. Which tool do you recommend?
My technology stack is: backbone and require.js and jquery mobile and jasmine for BDD test.
Regards
When doing BDD you should always mock the collaborators. The tests should run quickly and not depend on any external resources such as servers, APIs, databases etc.
The way you would want to make in f.e. Jasmine is to declare a spy that pretends to be the server. You then move on to defining what would be the response of the spy in a particular scenario or example.
This is the best aproach if you want your application to be environment undependent. Which is very needed when running Jenkins jobs - building a whole infrastructure around the job would be hard to reproduce.
Make spy/mock objects that represent the server and in your specs define how the external sources behave - this way you can focus on what behavior your application delivers under specified circumstances.
This isn't a complete answer, but one tool we've been using for our very similar stack is mockJSON. It's a jQuery plugin that does a nice job both:
intercepting calls to a URL and instead sending back mock data and
making it easy to generate random mock data based on templates.
The best part is that it's entirely client side, so you don't need to set up anything external to get decent tests. It won't test the actual network connection to your server, but it can do a very good job validating that type of data your server would be kicking back. FWIW, we use Mocha as our test framework and haven't had any trouble getting this to integrate with our BDD work.
The original mockJSON repo is still pretty good, though it hasn't been updated in a little while. My colleagues and I have been trying to keep it going with patches and features in my own fork.
I found a blog post where the author explain how to use capybara, cucumber and selenium outside a rails application and therefore can be use to test a javascript app. Here are the link: http://testerstories.com/?p=48