So this is more of a theoretical question rather than a programming question.
In my basic understanding of the Angular 4 framework a component can have inputs, outputs and services which also interact with the store to store data.
Now all of this, in the case of a web-app is displayed on a template. I have recently been looking at testing of such an app.
I plan to use Jasmine as the framework and Karma as the test runner on Chrome (for now).
With that said, what should I be testing for?
According to my understanding the basic tests should include some mock object handed to the component and checking if that is rendered properly on the template, mocking a service and checking what is rendered when we receive the correct response.
So what do I do after this? After I have tested this?
How is this behavior driven development? What can I do more?
What is a "good angular test"?
Since you have mensioned jasmine with karma, My perspective of answering this question will be mostly on Unit Testing. Let us go one question after another
What is a "good angular test"?
1) Unit testing should be written by the developer not by anyone else (tester).
2) It must have both positive and negative scenarios handled.
3) All network calls should be mocked or stubbed.
4) It should pass irrespective of environment.
5) It should have be easily readable, reliable and should not test the integration.
How is this behavior driven development? What can I do more?
In a nut shell BDD:
1) Write unit test cases prior to your development
2) Let all of your unit test cases fail
3) Start with your development unit by unit. Pass the assertion.
4) BDD is a advancement of TDD. In BDD we should not test the implementation but behavior should be tested.
5) BDD increases the code quality as well since we create test case based on behavior.
So what do I do after this? After I have tested this?
Current trend as explained above, after writing the test cases start with the development. Write the assertion, even the non technical person can understand the behavior.
You should also check if your bread-crumbs are in position, bread-crumbs are used for internal routing between pages. Also use the right path of your routing component in your app-module.
Related
Simply test case: Want to see if a given element is focused.
To check if an element is focused on a react web app with RTL and jest, you have two easy options available to you:
You can check if the element is the same as document.activeElement (may have to discard some wrappers)
You can extend your jest matchers with https://github.com/testing-library/jest-dom#tohavefocus and use expect(<element>).toHaveFocus()
I'm not sure what the equivalent check would be with react native (the RN equivalent to the jest-dom extension is https://github.com/testing-library/jest-native and is conspicuously missing the toHaveFocus matcher).
Sunk several hours in to this today. From what I can see, React Native Testing Library doesn't have this matcher and neither does the Jest Native matcher extender.
It looks like Detox supports it though.
There are lots of suggestions to use refs (which might let us call ref.current.isFocused()), or capture onFocus\onBlur events. But these aren't viable from the test environment perspective.
There were 2 things I observed with the refs.
The refs all get mocked out in jest (I don't know enough about jest to know why).
When the element is not focused, the ref is completely gone
Regarding, tracking onFocus\onBlur, it's unnecessary overhead and only further complicates the production code for the sake of testing. Then the component has to accept these as props and a mock has to be created for each one... no thanks!
I decided to open a feature request in the Jest Native project. Cross your fingers.
React.js users have it so easy!
I've been learning how to write automated tests for a React app, and it's brought up questions on how best to test a series of interactions with the app.
Let's say that I have a React app that allows the user to assign students to seats in a classroom: Here's an image of what such an app would look like.
I'd like to test creating a new student, adding that student to a seat in the classroom, and then moving that student back to the area of unseated students in the middle column (I'll call it the roster).
What would be the best way to write out the test(s) for this? Would it make sense to have a single large test case, which would include assertions for each of the interactions I'm testing (creating a new student, moving it between the classroom and roster)?
Or should I create multiple cases, where one depends on the other? In other words...
Test 1) Check that a new student is created successfully when submitting the form
Test 2) Using the student created in test 1, move the student to a seat in the classroom
Test 3) With the student now in a seat (due to test 2), move it back to the roster area
Another question I have is whether React Test Library would be sufficient for this purpose. Or would this be considered an end-to-end test that should be written using Cypress?
Your feedback is much appreciated!
The process you described can surely be tested with react-testing-library as an integrated test. From the docs/faq, it encourages testing a component high enough up the component tree, without mocking child components, in order to simulate and test what an actual user interaction would be like.
Also check out this Kent C. Dodds blog post .
You want your tests to be as granular as possible, as you have already split them in 3 different cases. This will make it easier for everyone to read your code.
As for the testing library, I would go with Cypress which advertises itself as a JavaScript End to End Testing Framework.
You are testing end-to-end functionality here by manipulating what seem to be multiple components. React testing library, on the other hand, seems to focus on testing individual components on a more low-level approach - there's a chance it will falter on the long run, but it probably gets the job done aswell.
I would like to reach 100% coverage on my javascript project using Jest. Some methods, in my opinion, are not suited for unit testing and should be skipped when analyzing the code coverage. I would like to be able to do something like this:
function toto() {
// Some function performing stuff we don't want to test e.g.
// promise called inside a complex authorization process
// involving an integration test really hard to mock.
}
expect(toto()).toBeUntestable();
The Jest API doesn't appear to have such possibility. It could be really useful since we could use this to aggregate bad code/hard-to-test code using this technique.
I'm really interested in your input regarding this situation since when it comes to tests, I find it really hard to have the right angle of approach.
I'm using jasmine and karma for unit tests of my app, with approx. 1000 tests at the moment, it takes around 10 seconds until they're finished.
It's not a problem right now, but in a couple of months the number of tests might become much bigger and I'd like to know if there's anything I can do to make them run faster, at least locally.
I found out that using:
jasmine.any(Object)
is much faster than comparing big objects.
Changing:
expect(some.method).toHaveBeenCalledWith("xyz");
into:
expect(some.method.calls.argsFor(0)[0]).toBe("xyz");
also seems to be a little bit faster.
Karma is lovely but it doesn't seem to have anything that improves performance yet, it's really useful for debugging though (reportSlowerThan).
Any other ideas how can I improve the performance of the tests?
What kind of performance improvements are you seeing in switching from toHaveBeenCalledWith?
I appreciate what you're trying to achieve – you have a test suite that runs 10 seconds and you're right to try and improve that situation – but if the savings are in < 500ms range I would be careful as the readability and clarity of your tests are put at risk.
toHaveBeenCalledWith communicates your intentions to others much better than the argsFor approach does, as does the message that would displayed if that test were to fail;
Expected function to have been called with "xyz"
vs
Expected undefined to be "xyz"
With that said, some ideas...
1
Look for areas where you can safely replace beforeEach calls;
The beforeEach function is called once before each spec in the describe in which it is called
With beforeAll calls;
The beforeAll function is called only once before all the specs in describe are run.
But be careful not to introduce shared state between tests which could skew your results (using Jasmine's option to run the tests in a random order might help here but I'm not sure how beforeAll is handled by this, it could be that those specs are still run together).
2
Continue using reportSlowerThan as you have been and pick off any that are really slow. If changes like the one you suggested are unavoidable, put them behind helper functions with well-chosen names so that what you're trying to achieve is still clear to other developers. Or better still, create Custom Matchers for them because that will also result in clear messages if the tests fail (add-matchers can help make this easier).
3
Consider switching from Jasmine to Jest, tests are written in pretty much the same way, but the test runner is much faster.
I have function in controller of my directive:
$scope.getPossibleWin = function() {
return betslipService.getPossibleWin()
}
betslipService injected into controller
Now I'm thinking how to test $scope.getPossibleWin:
Test that $scope.getPossibleWin calls betslipService.getPossibleWin
Test that $scope.getPossibleWin return correct value (but this already tested in betslipService!)
Test that $scope.getPossibleWin simply exist
What is best practices in wrappers testing?
Option 2 is the best, option 1 I am not very convinced about. I don't have experience with Javascript so I'm not sure why you should have to verify that a function exists (option 3).
You can find more information on it here but the reason that you should indeed add a test for this method is to prevent yourself from breaking anything in the future. If you only rely on that one method 5 layers deep in your application, it could be that one day you add code in a higher layer which changes the result but it is not being tested. Or at some level some code has a side-effect which disturbs the result that came from the bowels of your codebase.
Therefore I would suggest you to make a test for each (relevant) level. The question what should I test exactly is probably a little bit preference-oriented but I would argue that the very least you should do is testing whether it returns the correct value, as layed out above.
Should you test that it calls that specific inner method? You could, but that isn't exactly something you do in unit-testing because then you would be testing against the unit's internal workings. You don't care how it works inside, you just care that the function gives you the response that you expected. By coupling these two in your unit-test, you'll end up with a broken test for non-broken code when you decide to refactor the internal workings.