Live data from Hacker News

Write tests. Not too many. Mostly integration

blog.kentcdodds.com

301–310 of 338 posts

Re: Write tests. Not too many. Mostly integration

#301
I trust my own sense of when unit-tests and integration tests are appropriate.

If I'm working on a bit of code that has actual internal logic, then I'm happy to write unit tests so I can iterate on the test with scenarios while I code.

OTOH, if I'm writing a glorified CRUD pass through, api > model -> db-entity > do a thing > return result. There is nothing to unit test. Writing a few integration tests that call the API gives me much more confidence that everything is hooked up correctly than mocking a bunch of shit and asserting that a method was called that was obviously called.

Re: Write tests. Not too many. Mostly integration

#302
post #249

I go the complete opposite way. I've tried various testing strategies over 15~ different companies in all sorts of environments, and unit tests are the only thing that really work (IF you can convince the team to do it...and that's a big IF). The article starts with a point I agree with: the lower in the pyramid, the cheaper the tests but the lower the confidence level they bring. That's true. Where I disagree is how…

The second group I worked with that was earnestly interested in mature testing developed the 5/8ths rule.

To move a test one level down the pyramid, it takes about 5x as many tests. But the tests run 8 times as fast. So moving a test down takes more than 35% off the run time, and it fails the build minutes sooner. If you drop it down two levels it's 60% off the run time.

Interesting enough on its own, but maintaining those tests after one requirements change, plus the cost of rewriting them in the first place, is less work than the cost of maintaining the original tests. We didn't come up with a number for this but the difference was measured in man-days and missed deadlines about once a month, and we were convinced by the evidence.

I also agree with both your 'braindead' comment and your 80% estimate. The big payoffs come between 75% and 85% and above 85% you start getting artifacts. That 'data' distract more than it helps.

Re: Write tests. Not too many. Mostly integration

#303
post #102

Earlier quoted context omitted.

We should probably have two completely different versions of this discussion for typesafe and type-risky languages, since typechecking is effectively a form of testing at both unit and integration level.

I suspect I’ll be shifting from Node to Rust or one of its contemporaries at some point in the near future. I’ve given dynamic languages a very fair chance, kept an open mind and adopted its strategies instead of writing Pascal in any language, but it has failed to impress me. I want a statically typed language with reasonable affordances for FP, for the 20% of the code that is dead ugly when forced into object struc…

Is your decision mainly based on type-safety? We converted all of our nodejs to typescript primarily for easier refactoring, but it still hasn't fully satisfied our desire for change. We are thinking of switching to rust as well. We couldn't get past the Go generics argument, and would also prefer something staying towards the functional side. Any other languages you are considering?

Re: Write tests. Not too many. Mostly integration

#304
post #74

Earlier quoted context omitted.

> If your app relies heavily on using a database, your app naturally integrates with a database then it makes no sense to test without it. You are intentionally avoiding testing in a way that will pick up bugs. Also, with Docker it's now actually feasible to automatically test against a real database at a reasonable speed. A Postgres container spins up in a couple of seconds, a SQL Server one in a little over four.

That has nothing to do with docker, really. I run postgres standalone on my laptop and it starts in < 1 second.

[deleted]

Re: Write tests. Not too many. Mostly integration

#305
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"…

I’ve been practicing TDD for 6 years and this is exactly what I ended up doing. It’s a fantastic way to program.

My leaves are either pure functions (FP languages) or value objects that init themselves based on other value objects (OOP languages). These value objects have no methods, no computed properties, etc. Just inert data.

No mocks and no “header” interfaces needed.

On top of that I sprinkle a bunch of UI tests to verify it’s all properly wired up.

Works great!

Re: Write tests. Not too many. Mostly integration

#306
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"…

This is very interesting. I'm not 100% sure I understand. Any example of this or resources on this style?

Re: Write tests. Not too many. Mostly integration

#308
post #80

Earlier quoted context omitted.

The abstraction is consistent though, and familiarity is a good thing when navigating a codebase which has N amount of other devs pushing to it every day. I practise TDD for peace of mind - if I add new functionality to existing code I can be 99.9% sure I haven't made any regressions. When a client's system goes down on a friday, I can 99.9% guarantee it wasn't my code that is at fault. If I have to work at the weeke…

Exactly this. Confidence is everything. I can actually write entire features with appropriate test coverage from the ground up and they work first time and have close to zero defects in production. It's amazing when you spend 5-6 days writing code that does nothing and at the last moment, everything slots together with a few integration tests and wham, feature done. Not talking trivial stuff here either; big integrat…

> You see a lot of people arguing against this but I'm going to be honest, they churn out a lot of stuff that doesn't actually work.

My anecdata cancels out your anecdata. The TDD practitioners that I've met have, without exception, written code that worked fine for only the one case that they've tested. Example: They'd test a method for sending a message with the string "hello". Turns out the method didn't URL-encode the message before POST-ing it, and sending anything with a space was broken. They were confident and pushed the change.

Not saying you're wrong, just that TDD doesn't seem to work for everybody, and can even be a distraction.

Re: Write tests. Not too many. Mostly integration

#309

Earlier quoted context omitted.

How is static code different from other noninjected code, like stuff in a method. Taken to the logical conclusion we'll have thousands or classes full of max 2 operations per method.

How many static classes are your methods using? And what is the problem with injecting this stuff at the top of the class instead? If you plan to write tests, you have to control your dependencies, and DI is the simpliest way to do that.

Because these tests become too detached from reality if you inject everything. A silly example to make the point:

IAdder { double Add(double a, double b) }

Test:

car mockAdder = ... // Mock 1+1=2 etc.

Re: Write tests. Not too many. Mostly integration

#310

Earlier quoted context omitted.

I guess they meant so your tests can start with a blank or reproducible state. But you can of course achieve the same by running a script before your tests start. There are also some frameworks for doing this sort of thing too, such as Fixie for .NET

Drop-create scripts! One of my first epiphanies in the testing world.

Create only scripts can also be great in the right context.

Namely a context like travis-ci where you get a new clean environment each time.

Personally, I've develop few libraries/web UIs that relies on external software like a DNS server or an ldap directory.

And for those, I've a quick and dirty shell script that deploys bind/OpenLDAP.

It's far easier, faster and more accurate than mocking.

For example, what comes to my mind is the testing I do for all the SSL/TLS modes I support (SSL, StartTLS, certificate check disable or not, etc) in my ldap web application.

Travis also has available services in their build envs (stuff like redis, mongodb, mysql, cassandra...).

Post reply on HN