Live data from Hacker News

Write tests. Not too many. Mostly integration

blog.kentcdodds.com

261–270 of 338 posts

Re: Write tests. Not too many. Mostly integration

#261
post #6

I'd take a slightly different take: - Structure your code so it is mostly leaves. - Unit test the leaves. - Integration test the rest if needed. I like this approach in part because making lots of leaves also adds to the "literate"-ness of the code. With lots of opportunities to name your primitives, the code is much closer to being self documenting. Depending on the project and its requirements, I also think "lazy"…

> Integration test the rest if needed . Is there any situation where there is integration, but no need to test it? You seem to be suggesting that if the leaves are thoroughly tested, nothing can go wrong in their integration, but at the same time, I cannot imagine someone believing that.

Integration tests are always needed in some form, because you need to make sure the leaves are actually called, since unit tests are executed in a vacuum, the functions might work but might never be called at all, or might not work because of weird bugs that appear when only testing the whole tree.

Re: Write tests. Not too many. Mostly integration

#262
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…

> Why integration tests? Because they test that you are actually using some available network ports, have the correct database model in mind, didn't mistake the version of your libraries, got the deployment script right, and isn't just restarting everything in an infinite loop? Or maybe because E2E tests actually test stuff your company cares about, instead of some made-up rules that you've got from nowhere? Really,…

There’s a pyramid for a reason. It only takes a couple of tests to make sure that your plumbing connects all the way through. You inspect all the bits when they are going in but in the end you still check that things end up where they are supposed to.

I’ve been doing automated testing for a while. It’s hard to learn, there aren’t many people to emulate. Well, there are people to emulate but the winning strategies are conterintuitive, so your gut fights you the entire time. It took me 8 years to feel confident in tests and my own test code routinely makes me sad because I find antipatterns and I should know better. Also other people copy all of my mistakes :/

I’ve seen a number independent groups two or more years into their testing adventure and the failure modes are not that different. Everyone pretty much makes the same mistakes I do, and it’s frustrating watching everyone go through the pain before they accept that something has to change and it’s probably them.

The best strat I know of for testing is to use inductive reasoning and sampling to verify. If you don’t like the plumbing analogy then this is the Logic version of the same thing. If A -> B and B -> C then A -> C. Only a couple of your tests should verify A -> C and the bulk should check every kind of A [edit] and every kind of B.

If you want to do things like this without making your code not ‘say’ anything (a huge pet peeve of mine, so I can empathize with your concerns) then there are a couple of things to do there. One is an old trick from Bertrand Meyer: split code that makes decisions from code that acts upon them. Beth is split leaves the code more legible, not less.

Most of the boundary conditions are in the decisions. And this code is side effect free you can test the hell out of it with no mocks. Getting every permutation is straightforward and you can count your tests and your conditional branches to figure out if you are done.

Once your code looks like this, adding and removing new rules to the system later is a snap. Even much later.

Re: Write tests. Not too many. Mostly integration

#263
post #203

Clean architecture: https://smile.amazon.com/Clean-Architecture-Craftsmans-Softw... Anything that touches the real world should be as small as possible. I've been writing code using tests for about 4+ years and I now can't think of writing code any other way. I would be scared of refactoring. Also I'm testing the code anyway - why not write it down so it gets done every time? Run integration tests too for sanity - th…

The problem with always relying on testing is you lose your ability to create without the test crutch. Everything is red/green and your brain can get a lazy. Balance is the best.

What is science without tests? I say coding is similar.

Re: Write tests. Not too many. Mostly integration

#264
post #153

> You should very rarely have to change tests when you refactor code. I'm going to say this is poor, if not outright dangerous, advice. I'd argue the opposite: every time the code changes, it would be great if a test somewhere broke. Hell, if the tests originally were for a gigantic class with a ton of mocks but the code changed so there was lower coupling and the dependencies were injectable or separated in differen…

> every time the code changes, it would be great if a test somewhere broke

So, it doesn't matter if your code is correct or not?

> "the compiler catches some bugs right away!" as an advantage, which always makes me think "... and?"

And that leaves more time to design things right and test the stuff that actually matters.

Re: Write tests. Not too many. Mostly integration

#265
Reading all the comments reminds me why I really don't like working in large enterprise teams. People argue a lot about semantics ("what is a unit test?") and the only right way to do things but there is almost nothing practical to learn from.

I have found that in some projects unit tests are really easy to write and helpful but in others you spend more time on writing mocks and dependency injection than writing stable code.

I don't even know what I want to say exactly other than that we should focus more on practical solutions to real problems and less on debating semantics.

Re: Write tests. Not too many. Mostly integration

#266
post #46

Earlier quoted context omitted.

In some situations unit tests with lots of mocks will bring a negative value. Imagine a situation where you want to refactor a big piece of code with many dependencies but you don't want to change its public interface. If you mock everything, when you refactor, the test will break because the dependency structure will change, and the mocks are no longer relevant to the new implementation. You have to rewrite the test…

I agree with this. Although, if you offshore development here in the third-world where internet gets slower everyday. Running an integration test that queries to Amazon RDB can take forever. I hope this issue gets a spotlight and be noted that integration tests in third world countries is very very slow. And this high cost should be included in the estimates. To give you an idea, here it takes AT LEAST 5 seconds to l…

> Running an integration test that queries to Amazon RDB can take forever.

Why wouldn't you run your test on aws if it needs to integrate with rdb anyway?

Or are your code changes so massive that "git push" is slow?

Re: Write tests. Not too many. Mostly integration

#267

Earlier quoted context omitted.

> Why integration tests? Because they test that you are actually using some available network ports, have the correct database model in mind, didn't mistake the version of your libraries, got the deployment script right, and isn't just restarting everything in an infinite loop? Or maybe because E2E tests actually test stuff your company cares about, instead of some made-up rules that you've got from nowhere? Really,…

There’s a pyramid for a reason. It only takes a couple of tests to make sure that your plumbing connects all the way through. You inspect all the bits when they are going in but in the end you still check that things end up where they are supposed to. I’ve been doing automated testing for a while. It’s hard to learn, there aren’t many people to emulate. Well, there are people to emulate but the winning strategies are…

> There’s a pyramid for a reason.

Sorry, but I am still unconvinced people got that reason correctly.

Let's say you have that A -> B; B -> C pipeline. How many tests you should have on each step (and on the origin) depends completely on how much freedom that steps grants you. It is not something one can say generalities about.

For example, if you are writing an enterprise CRUD application, almost your entire freedom resides on the data mapping. That means that your tests should be equally divided between data validation and data storage/retrieval. And the second can only be done at the integration or E2E levels.

If you are writing a multi-client statefull server (like a threaded web server), the freedom concentrated on launching and reloading it is so large that you can't even reasonably test for it. You'd better design your software around proving this is correct and let testing for less problematic stuff.

My biggest issue with the unity test pushing isn't even that it forces a bad structure into the code (what it does), or that it's pushes for fragile and valueless code (what it also dies). It is that it's wrong at the larger level, oversimplifying stuff and letting people get out of the hook without thinking for themselves.

Re: Write tests. Not too many. Mostly integration

#268

Earlier quoted context omitted.

It seems the encouraged method is IoC these days, and that's just dreadful. IoC/Dependency resolution all over make it insanely hard to reason about code without running circles through the codebase. For me, IoC seems invented almost entirely to make up for how difficult testing can be in particular languages. Which, sure, making up for shortcomings as good, but the necessity to use IoC for it feels bad.

This is how I felt about IoC as a junior dev 15 years ago, before I'd actually used it myself. Nowadays the benefits are clear to me: more modular, testable code, and also lifecycle management. Give it a try, you may well change your views.

I've used it a fair deal. I've found I prefer languages that don't require IoC to make code testable.

I agree that it's one of the sanest options when it's required, I just think that language design should incorporate testing ergonomics from the start.

Re: Write tests. Not too many. Mostly integration

#269
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…

people ... don’t want to change how they write code. They just want tests for it Have you considered the possibility that those people are right? That's a reasonable conclusion to make if you are seeing lots of otherwise smart people that share an opinion that disagrees with yours. There are lots of valid reasons to change the style in which you write code. In my mind, fitting somebody's fad testing scheme is not one…

    Have you considered the possibility that those people are right?
Every time I’m looking at a code review with awful tests. I started out in statically typed languages and I can’t shake the feeling that we need to tool our way out of the testing conundrum.

Anything that is this hard to get right shouldn’t be the equal responsibility of every team member. For every other problem of this magnitude we have people who specialize and everyone else just has to be aware of the issues and consult when in doubt.

So it’s a struggle for me to try to get people do adhere to the strategy we’ve accepted without believing it’s the end all be all of software robustness. Because I’m not convinced. Nothing I’ve ever mastered in software has taken me half as long as testing, and that just ain’t right.

That said, I still like the structure about 80% of my tested code has. It usually does exactly what it says and nothing else. Local reasoning is a big deal to me.

Re: Write tests. Not too many. Mostly integration

#270

Earlier quoted context omitted.

I strongly agree with that, too. My current, experience-born belief is that if the only reason for introducing some architectural pattern is to accommodate testing better, the change is wrong and will likely hurt the code quality. Yes, you need to concede a little bit to allow for test points, but turning your code inside-out to have it go through three layers of indirection so that the middle one can be mocked easil…

yea, you should be changing code style to increase modularity in a way that is conceptually coherent in terms of what is easy to hold in your head. Increased testability should fall out of that because you can think through "What invariant should hold true about X under conditions/inputs Y1...Y4?"

Code you can hold in your head usually has a smaller surface area. Fewer moving parts equals easier testing.
Post reply on HN