I need to refactor all enzyme unit test to react native testing library.
In Enzyme, to get the props of the children elements I can use some thing like :
((rootElement.props() as Props).prop).toBe(value).
The prop() function returns the props hash for the current node of the wrapper. NOTE: can only be called on a wrapper of a single node.
How can I do the same in react native testing library ?
Should I only pass the full path to the prop? like this:
expect(nextUpNoThanksButton[0].props.children.props.isSelected).toEqual(true);
Or is there another way to do this ?
The very fundamental tenet of React Testing Library is to not test if a component received props or do any sort of assertions with props, state etc.
Hence, I don't think it's possible to do what you need in RTL in this case.
And this ideology goes a long way in writing better unit tests.
While enzyme gives these options, and in some cases, they are helpful, it can be argued that it makes for a way to make improper assertions and eventually beat the very purpose of unit tests.
Verify what happens after you pass some set of props. That is, what happens on the DOM. Because eventually, that is what matters, and you are asserting what happens in the real world from an end user's perspective. And this is the point which RTL promotes.
You can always do things like,
Assert if a function was called. Pass a function callback as prop and then you can verify if it's been called.
Assert that some other action happened which is an effect of passing a specific prop.
Assert things getting shown or not shown on the DOM as an effect of a prop.
We have gone through the same process where out entire unit tests suites were built using Enzyme. We eventually decided to move to RTL and roughly this is the approach we have followed,
Any new unit tests being written, should use RTL. No exceptions.
Any existing unit tests which used Enzyme, can remain. They would still run and do their job.
Every once in a while, as part of general code changes, we would try and pick up enzyme based unit tests and convert them. Based on complexity this exercise can take time. But you can start with low hanging fruits and work your way up to more complex ones and convert them methodically to use RTL.
Hope this helps.
Related
I'm currently getting to grips with Lucene indexing, and scratching my head about the "correct" approach if using TDD.
To do this you have to create an IndexWriter, produce an index based on a simple collection of texts (Strings), which are tokenized, stemmed, etc.
To look up a query in this index you have to create a DirectoryReader, make a Query, get the hits, etc.
So in the course of making my first test class (JUnit 4) I did each of these steps, one by one, making a new test method for each step in this process which ultimately produces a non-zero number of hits, if all goes well.
The problem I have is that the last test method does ALL these steps: clears the index directory, creates an IndexWriter, makes the index, etc. etc. and finally counts the hits. This last method can ultimately be tripped up by anything along the way going wrong. Furthermore, the previous methods all seem redundant...! And no "mocking" opportunities seem to present themselves...
Is this a candidate for a "test suite"? How does a TDD Pro develop "appropriate" testing for a situation like this?
It sounds to me that the last test method you refer to is more of an integration test than a unit test. Unit tests should only test a very specific unit of code (usually a method or part of a method) and should mock out any interactions with other classes, shouldn't touch a database, filesystem, or anything outside of the specific unit of code under test. It sounds like the first tests you created are unit tests and last test is an integration test. It's ok to have some redundency between the two types of tests since the unit test are testing very specific pieces of logic and integration testing test the interaction between those pieces.
I am working on some application in Java and writing JUnit tests. I have a design question about Unit Testing. I have one class that reads a file and Create object called Song by reading different lines and parsing based on some algorithm. I have written some unit test on that. Next step after parsing is to actually convert that song to a different format based on some properties of Song object. I have another class that works as a translator. There is a method translate that takes Song object as input. Now in unit test for translator. I need a Song object with all valid properties. I am confused here that should I create a new Song object by putting same functionality as in parser or should I call the parser service to do that for me. I feel it will not be isolated if I take the second option. But in first option it's like duplicate code. Can somebody guide me on this?
There's nothing wrong in using a Builder in order to create the input data for a SUT invocation when this data is complex, however I see 2 risks here.
If the builder fails your test will fail too, but it shouldn't. As you said unit tests should be isolated from external code.
If you use code coverage as a metric to evaluate how good your unit tests are (I don't mean this is right), by looking at the builder's coverage you'll be tempted to think it's tested though obviously isn't.
My opinion is there's not a best solution fitting all the scenarios. In case the input data is not very complex try to build it "manually", otherwise use the builder.
With a good design pattern like MVP, MVC, etc we aim to move all logic out of the GUI. That leaves us with a light weight GUI which ideally just need to "bind" its buttons and fields to properties in some business logic layer. This is a great approach as this layer will be free from GUI stuff, and we can easily write unit tests for it.
My question is: Is this enough? Or should we still unit test the GUI layer?
IMHO if you remove whole logic from GUI, you don't need to test it automatically. Of course you still need to run it to see if it looks like it should :)
This is about unit tests. For integration tests it is still good to test everything, e.g. by Selenium, if possible.
Sometime the GUI is not really that dumb. For instance there might be drag and drop support, custom components which display their content based on where they are placed and many more. In that case these things need to be specifically tested both in integration tests and individually in unit tests.
Most of the time the integration tests start from the UI layer and we end up testing a lot of UI layer in those scenarios as well. I once read a comment from someone about unit-testing that you don't need to write tests for code that can be easily broken for instance getters/setters can be easily broken (for example getter returns the value it is supposed to do and we can break it easily by not returning the value) so we don't end up writing unit tests for getter and setters unless there is some logic embedded in it (in which case these are not actually getter and setters).
So if the GUI is totally dumb and there is only bindings in it then unit tests are not required.
I'm new to unit testing so I'd like to get the opinion of some who are a little more clued-in.
I need to write some screen-scraping code shortly. The target system is a web ui where there'll be copious HTML parsing and similar volatile goodness involved. I'll never be notified of any changes by the target system (e.g. they put a redesign on their site or otherwise change functionality). So I anticipate my code breaking regularly.
So I think my real question is, how much, if any, of my unit testing should worry about or deal with the interface (the website I'm scraping) changing?
I think unit tests or not, I'm going to need to test heavily at runtime since I need to ensure the data I'm consuming is pristine. Even if I ran unit tests prior to every run, the web UI could still change between tests and runtime.
So do I focus on in-code testing and exception handling? Does that mean to draw a line in the sand and exclude this kind of testing from unit tests altogether?
Thanks
Unit testing should always be designed to have repeatable known results.
Therefore, to unit test a screen-scraper, you should be writing the test against a known set of HTML (you may use a mock object to represent this)
The sort of thing you are talking about doesn't really sound like a scenario for unit-testing to me - if you want to ensure your code runs as robustly as possible, then it is more, as you say, about in-code testing and exception handling.
I would also include some alerting code, so they system made you aware of any occasions when the HTML does not get parsed as expected.
You should try to separate your tests as much as possible. Test the data handling with low level tests that execute the actual code (i.e. not via a simulated browser).
In the simulated browser, just make sure that the right things happen when you click on buttons, when you submit forms, and when you follow links.
Never try to test whether the layout is correct.
I think the thing unit tests might be useful for here is if you have a build server they will give you an early warning the code no longer works. You can't write a unit test to prove that screenscraping will still work if the site changes its HTML (because you can't tell what they will change).
You might be able to write a unit test to check that something useful is returned from your efforts.
I have a simple project, mostly consisting of back-end service code. I have this fully unit-tested, including my DAL layer...
Now I have to write the front-end. I re-use what business objects I can in my front-end, and at one point I have a grid that renders some output. I have my DAL object with some function called DisplayRecords(id) which displays the records for a given ID...
All of this DAL objects are unit tested. But is it worth it to write a unit test for the DisplayRecords() function? This function is calling a stored proc, which is doing some joins. This means that my unit-test would have to set-up multiple tables, one with 15 columns, and its return value is a DataSet (this is the only function in my DAL that returns a datset - because it wasnt worth it to create an object just for this one grid)...
Is stuff like this even worth testing? What about front-end logic in general - do people tend to skip unit tests for the ASP.NET front-end, similar to how people 'skip' the logic for private functions? I know the latter is a bit different - testing behavior vs implementation and all... but, am just curious what the general rule-of-thumb is?
Thanks very much
There are a few things that weigh into whether you should write tests:
It's all about confidence. You build tests so that you have confidence to make changes. Can you confidently make changes without tests?
How important is this code to the consumers of the application? If this is critical and central to everything, test it.
How embarrassing is it if you have regressions? On my last project, my goal was no regressions-- I didn't want the client to have to report the same bug twice. So every important bug got a test to reproduce it before it was fixed.
How hard is it to write the test? There are many tools that can help ease the pain:
Selenium is well understood and straightforward to set up. Can be a little expensive to maintain a large test suite in selenium. You'll need the fixture data for this to work.
Use a mock to stub out your DAL call, assuming its tested elsewhere. That way you can save time creating all the fixture data. This is a common pattern in testing Java/Spring controllers.
Break the code down in other ways simply so that it can be tested. For example, extract out the code that formats a specific grid cell, and write unit tests around that, independent of the view code or real data.
I tend to make quick Selenium tests and just sit and watch the app do its thing - that's a fast validation method which avoids all the manual clicking.
Fully automated UI testing is tedious and should IMO only be done in more mature apps where the UI won't change much. Regarding the 'in-between' code, I would test it if it is reused and/or complicated/ introducing new logic, but if its just more or less a new sequence of DAL method calls and specific to a single view I would skip it.