About a month ago, I started a well received discussion about unit-tests. What people think about them and how they help them to design systems or fix bugs.
Overall, the responses were in favour of unti-tests or at least automated testing in general. Some people were even advocating Test Driven Development (TDD) as a crucial part of their software design.
Only a minority didn't write unit-tests and all of them seemed like senior developers to me, people who don't have the feeling unit-tests would help them with their current problems.
I also had the impression, while many people write unit-tests, they use them in different ways. Sure, they check a small part of their code and they check it to ensure some kind of quality, but the approaches seem different.
To me it seemed like there are two main groups. People who start with a test and people who add them later.
Some use TDD to design their units, they think about how they want to use a part of their code, write a bunch of tests that reflect the desired behaviour and then they implement the tested part of code until the tests stop to fail.
Others also use TDD, but they find writing "good" tests to be the wrong way. They know what their code needs to do and how they want to use it later, so why bother writing tests for it? Instead they write tests for the edge-cases and look that their code fails when it gets wrong data.
And then thare are even people who say, TDD is just TDD. Like, if you write unit-tests somehow, then you are doing TDD.
All these approaches have the similarity that they form the structure of your code. If you want to do TDD, you need to write your code in a way that allows to access the units for testing from the outside.
With TDD your code may end up being more modular and with better encapsulation than without it.
Still one could argue that structuring code for tests instead of the real problems at had shouldn't be the goal, on the other hand if you write code with SOLID principles in mind, you end up with easily testable code too, so maybe the SOLID and TDD are simply two sides of the same coin?
I think this is why some of the senior developers don't see much value in TDD, they have the impression it doesn't add anything to the code they already write.
But there are plenty of senior developers out there who do TDD, because it's an easier way to enforce SOLID principles without thinking. You write your tests and then your code and can be pretty save that the resulting code is reasonably good while you have enough mental capacity left for other problems of the project.
Lets call the next kind of developers Bug Driven Testers (BDT). They code their software without any automated tests and later, when the manual testers or production users report some errors, they track down the bug and write a minimal test case to reproduce that bug. Later they fix it so the test passes.
Some say they only write such tests for nasty bugs or bugs that are hard to reproduce manually.
Some say they keep the tests forever and some say, if the bug hasn't shown up for a year, delete the test. Because if you write a test for every bug, you can end up with hundrets of them after some years, which slow the CI/CD process down quite a bit.
But the generall idea here is, design your code and add tests when it fails. Don't use the tests as a core design practice, but as a way to enhance what you already designed.
There are also some variations of the existing test practices. They could help people who don't have the experience to write good tests and don't want to clutter their code-base with bad ones.
Another apporach comes from FP. It's called property based testing and seems to allow a mix of the two TDD apporaches mentioned above.
The idea is, you statically type the code units you want to test. Then you write a test that puts some data in your code, but instead of writing it like a normal test, you write it with a property testing framework, that calculates all the possible inputs for your code based on the types you allowed.
Instad of writing tests for a few integers, you write the "integer test" and the framework generates all the integers for you. This allows you to write unit-tests for the good part of your code and adds the tests for (possible) the bad part on the fly.
The main idea of the tests in general, independent of TDD or BDT, is, you want to be save that if your code breaks your test should reflect that.
Mutation based testing breaks your code and looks if your tests still pass.
It mutates the units of code you want to test, removes some return statements, changes some variables, etc. pp.
If your tests don't fail, either the change wasn't critical or the tests would have also failed you with real problems later.
I'm still not happy with my testing practice.
In my last small project I tried the TDD approach and had the feeling it wouldn't add anything, but it seemed to me that some problems simply don't lead themself to unit-tests in general. Sadly these problems are the only ones left, that make my dev-life hard.
I tried to write an API client with the help of TDD, but since the client relied on the API, the tests didn't help much. I mocked the API and after all was done I felt pretty good, but when I used the client later it failed right away, because the API required some additional data that wasn't specified.
I know this isn't a problem of TDD and many people even write you shouldn't mock stuff just to get unit tests running, but well, integrating APIs is one main concern for me so I tried it anyway :D
Probably integration tests are the way to go here, but often you don't have different API stages, only the production API and you don't want to clutter it with your test calls, so mocking seemed like a nice way.
Maybe I even did everything right and the problem was the badly specified API, but as I said, often you can't choose here.
I also often have problems with React-Native UI components looking differently after library updates. Don't know if snapshop testing would help here or if this is simply a device problem? I have the feeling they only help if a library breaks a component, not if it just makes it ugly, haha.
I think: Probably yes?
I really want to like it, and many people, most who are smarter than me, love it, so I feel like an ignorant or dumb for not using it.