Live data from Hacker News

Write tests. Not too many. Mostly integration

blog.kentcdodds.com

51–60 of 338 posts

Re: Write tests. Not too many. Mostly integration

#51
I agree with the part that you should write tests, but I definitely disagree with the part that most of your tests should be integration tests.

As you pointed out the testing pyramid suggests that you should write more unit tests. Why? Because if you have ever tried TDD you know that unit tests make you write good (or at least acceptable) code. The reason for this is that testing bad code is hard. By writing mostly integration tests you lose one of the advantages of unit testing and you sidestep the bad code checking part.

The other reason is that unit tests are easy to write. If you have interfaces for your units of code then mocking is also easy. I recommend stubbing though, I think that if you have to use mocks it is a code smell.

Also the .gif with the man in pieces is a straw man. Just because you have to write at least 1 integration test to check whether the man has not fallen apart is not a valid reason to write mostly integration tests! You can't test your codebase reliably with them and they are also very costly to write, run and maintain!

The testing pyramid exists for a reason! It is a product of countless hours of research, testing and head scratching! You should introspect your own methods instead and you might arrive at the conclusion that the codebase you are working on is bad and it is hard to unit test, that's why you chosen writing mostly integration tests.

Re: Write tests. Not too many. Mostly integration

#52
post #48
post #47

Earlier quoted context omitted.

Private methods are the internals of your classes. It may change a lot for performance or to make it easy to maintain, one method may become 3 or 4. But people who use your class don't care. They input something in your public methods and expect something in return. The details of what happen inside should not matter. Adding tests there only help to slow you down and make the dev team resist needed changes. And when…

Ah, I think I see. If I break the functionality by changing the implementation of a private class, that should be reflected in the public API unit tests.

That's how I see it (in Java at least), unit tests are for guaranteeing that your classes API does what it says it does.

In Python I am more loosely goosey about my unit tests and unit tests there are more for helping me write/think about tricky code.

Re: Write tests. Not too many. Mostly integration

#53
post #42
post #27

Earlier quoted context omitted.

It depends on what you unit test and why. If it's for 100% test coverage: forget about it. If you test private methods: you're doing something wrong. What people usually see from the "unit test evangelists" are codebase for which you have tests for every method in the code. Then you do some refactoring and you have to rewrite tons of tests. And as those tests are just made to get 100% coverage you end-up with logic b…

> If you test private methods: you're doing something wrong. Maybe a silly question, but why? If I refactor a class to pull a common piece of functionality into a private method, why would I not want a test for that? One of the principle benefits of tests I see is allowing me to change the implementation without worrying about the behaviour, and I'm not sure why that wouldn't apply to private methods?

One reason why is because you should be testing the public behavior of a function/class not the details. The reason for this is because the public interface is what other parts of the codebase will come to rely on. Refactoring generally shouldn’t change the public interface as it will break other pieces of code within your codebase, or other codebases if it’s a library, and other systems if it’s a network api. So, if you test the public interface, generally refactors won’t break the tests.

Testing private functions also seems to be a smell that the overall setup of testing the class or function is too difficult. This can be because the class has too many branches in it, the argument list is too large, or too many other systems must be in place for it to function correctly. This, to me, indicates a public interface that is hard to use and will pass much of these issues on to the caller.

Lastly, if you are testing private functions to gain coverage then arguably the behavior in the private method isn’t actually useful to the public interface. The reason I say this is that testing the behavior of the class should end up touching all branch conditions inside the class or the public interface isn’t fully tested. By only testing the public interface it then also becomes easier to locate dead/unreachable code.

Hope that answers the why.

Re: Write tests. Not too many. Mostly integration

#54
post #4

Earlier quoted context omitted.

I work in a company where quite a few of the developers simply are incapable of writing anything but integration-tests. The reason? They don’t “believe” in unit-tests. They don’t think unit-testing “works in the real world”. They absolutely fail to accept that they need to write their code differently for automated testing to work well. How do you change such a mindset?

Assuming you are a developer, start writing some. Next bug you find that needs a unit/functional test (e.g. it is caused by a simple error in transformation in one function), write the test first as a table of inputs vs outputs, find it fails, fix the function, and leave the test in. Gradually, the code base will contain unit tests which are useful, people will see they are useful, and other people might start using…

I agree. Tests for bug fixes are extremely valuable. Of such tests, unit tests are often very feasible.

A test accompanying a bug fix holds value in many ways.

Firstly, it demonstrates to those reviewing the change that the fix is suitable.

Secondly, the presence of a test encourages reviewers to consider what a test does and doesn't cover, sometimes resulting in comments regarding improvements that had not otherwise been considered.

Thirdly, and of most importance in the long term, a test for a bug fix serves to document oddities previously discovered that were for a time not known about.

Re: Write tests. Not too many. Mostly integration

#55
post #3

Good lord. Why integration tests? I think the biggest thing you can do to write more integration tests is to just stop mocking so much stuff. Okay. The biggest problem I see with people trying to write unit tests is that they don’t want to change how they write code. They just want tests for it. It’s like watching an OO person try their hardest to write OO code in a functional language. So they try to write E2E tests…

This sort of discussion often gets confused because people have different ideas about what integration tests are and therefore talk past each other. I generally avoid the term altogether and recommend testing stable API's (which are often public) and avoiding testing internal API's that are more likely to change. This assumes you have a stable API, but that's true of most libraries.

Exactly - Integration tests !== E2E tests

Re: Write tests. Not too many. Mostly integration

#56
post #4

Earlier quoted context omitted.

I work in a company where quite a few of the developers simply are incapable of writing anything but integration-tests. The reason? They don’t “believe” in unit-tests. They don’t think unit-testing “works in the real world”. They absolutely fail to accept that they need to write their code differently for automated testing to work well. How do you change such a mindset?

I doubt that you can. There was a study a while back, and I apologize in advance because I do not have a link, that showed projects written with unittests took significantly longer to reach the market, but with significantly less bugs. However, overall time spend on the code was less. So conclusion was that unittests are a commitment to a long term goal of minimizing developer time, and the tradeoff is that it takes…

Man, I really want to read that study!

Re: Write tests. Not too many. Mostly integration

#57

Sounds good in theory. In practice there is one problem with having integrations tests only. The test are generally simple: they pass or they fail. A unit test tests just a small functionality, so when it fails, it's quite easy to find out the problem. When an integration test fails, then we can spend hours debugging the whole stack of layers trying to find out the real problem. I had this situation once. Every faili…

From my experience an integration test failure that requires significant efforts to investigate can only be covered with unit tests after one knows where the problem comes from. One cannot realistically write a bunch of unit tests and expect them to cover the problem unless one already knows about the problem.

Re: Write tests. Not too many. Mostly integration

#58
post #18
post #3

Good lord. Why integration tests? I think the biggest thing you can do to write more integration tests is to just stop mocking so much stuff. Okay. The biggest problem I see with people trying to write unit tests is that they don’t want to change how they write code. They just want tests for it. It’s like watching an OO person try their hardest to write OO code in a functional language. So they try to write E2E tests…

> Good lord. Why integration tests? Because they can find bugs and errors which unit tests cannot.

Funnily enough for the reasons carefully explained in the article. i.e. cost vs benefit, fragility etc.

Nobody disputes that if they came for free then full unit test coverage would be a good thing. The area open to reasonable debate is whether they give the best bang per buck in terms of testing (as opposed to the role of tests in TDD - which is a different kettle of fish: http://www.drdobbs.com/tdd-is-about-design-not-testing/22921... )

Re: Write tests. Not too many. Mostly integration

#59

Earlier quoted context omitted.

> The biggest problem I see with people trying to write unit tests is that they don’t want to change how they write code. They just want tests for it. It’s like watching an OO person try their hardest to write OO code in a functional language. The biggest problem I see with people advocating for tests and employing TDD is that they do change how they write code to accommodate tests. This leads to inclusion of lots of…

> as much as you can into static helper functions and most of the rest into dumb private stateless functions In our work we use C# and it is very hard, even next to impossible to make a static class pass a code review - given it's not for extension methods (which I hate... why not be explicit about the first parameter and stop acting as a part of the class ). They just tell us to use IoC and move to the next point. I…

C# is the new Java... facepalm

Re: Write tests. Not too many. Mostly integration

#60
I agree very much with this. I'd add one thing, adding tests and testing your code are not the same thing. You should write tests, mostly integration tests, testing public well defined boundaries of your class, your component, your service. Mock only IO if needed, but not other classes. But also tests the rest, but no need to add a test for them. Just run the code, try out the private functions, make sure they work.

And also go read Testivus: https://www.artima.com/weblogs/viewpost.jsp?thread=204677

Post reply on HN