Live data from Hacker News

Write tests. Not too many. Mostly integration

blog.kentcdodds.com

111–120 of 338 posts

Re: Write tests. Not too many. Mostly integration

#111

This is my version: Don't stop writing tests. Not until 100% coverage. Mostly unit. Especially if you are developing a library. An untested code branch is a ticking time bomb, in my book. An application for the end users indeed does benefit from integration tests, a lot. The problem is running them efficiently. If they take an hour to run, nobody will care to analyse them.

Analyse? Shouldn't tests just pass?

Re: Write tests. Not too many. Mostly integration

#112

Earlier quoted context omitted.

>Why does everyone rethink a working strategy. Write lots of unit tests that are fast. * Because I want to avoid writing more code than necessary. * Because I want to avoid writing tightly coupled code. * Because I'd rather have a test that takes 2x longer and catches 5% more bugs. Premature optimization and all that.

I would recomnend not optimizing for less code. Optimize for reading less code. Unit tests actually tend to favor highly uncoupled code while integration seem to favor more coupling with e2e favoring the most coupling. I believe this is because the higher the level of testing the fewer public interfaces are thought about at lower levels. As for percentages about speed and coverage, that seems like a bad trade off of…

>I would recomnend not optimizing for less code.

That is a terrible recommendation. Unless writing less code comes at the expense of readability or coupling you should always aim to write less code instead of more.

>Unit tests actually tend to favor highly uncoupled code while integration seem to favor more coupling with e2e favoring the most coupling.

It's the exact opposite. End to end tests do not even necessarily couple to a language, let alone specific modules. They can be used to refactor virtually the entire code base without rewriting any test code.

That isn't to say that you should only use E2E tests. IMHO wherever there is a naturally loose coupling and a clean, relatively unchanging interface - that is a good place to cover with integration tests.

The worst thing to surround with tests is a module whose API you know you will be changing (which will break the test when you do).

>As for percentages about speed and coverage, that seems like a bad trade off of 5% gain for 100% slow down. Especially because test time compounds.

No, it's an excellent trade off. CPU time is dirt cheap and bugs are very expensive.

Moreover, you can run regression test suites while you eat, sleep and visit the water cooler so the absolute time does not really matter provided it catches bugs before release.

Re: Write tests. Not too many. Mostly integration

#113

Earlier quoted context omitted.

In this case, what's the difference if you write the test before or after though? You would still be covered. I don't lean in either directions in this argument, just curious to understand.

The difference is night and day - writing tests first means you write 'testable code' from the beginning. Following the red, green, refactor mantra means that for every change to your code, you already have a failed test waiting to pass. The result is your test cases make a lot more sense and are of a superior quality. To liken it to something you may be familiar with - when commenting your code, do you think it's be…

>do you think it's better to add comments in as you write the code? Or add in the comments at a later date after the code is all written?

Define "all written". If we are talking about a new function - obviously you write you comment for it after the function ready to be commented on. And obviously you won't be commenting every string you put there, right?

Now, if we are talking about the whole new feature, that can consist of many functions and whatever - yeah, you usually comment your code in the process of writting the feature, rather than doing it at a later time, which will never come.

Re: Write tests. Not too many. Mostly integration

#114
Just reading the comments, I agree with the common sentiment that you should have more unit tests than integration tests, but I have come around to the way of thinking that if I only have time to write a few tests then I would rather write E2E tests. This way, at the very least your entire stack is being exercised, and you have a way of ensuring that the happy path is passing consistently, which is the most important flow for an application (even if I'm personally more interested in keeping other flows sane). While I prefer unit tests due to their simplicity, speed and the speed at which they can aid debugging, these days I will only implement them after I have added a few E2E tests.

Re: Write tests. Not too many. Mostly integration

#115
post #74

Earlier quoted context omitted.

>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. I've seen what happens when a developer tries to abstract away a database in a database driven app so it can be "better unit tested". It's a goddamn mess. If your app reli…

> 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.

Re: Write tests. Not too many. Mostly integration

#116

Earlier quoted context omitted.

The difference is night and day - writing tests first means you write 'testable code' from the beginning. Following the red, green, refactor mantra means that for every change to your code, you already have a failed test waiting to pass. The result is your test cases make a lot more sense and are of a superior quality. To liken it to something you may be familiar with - when commenting your code, do you think it's be…

> To liken it to something you may be familiar with - when commenting your code, do you think it's better to add comments in as you write the code? Or add in the comments at a later date after the code is all written? I'm sure you immediately know which approach results in better quality commenting, and it's the same with TDD. Not to take the analogy too far, but usually when writing a chunk of code I can keep it's b…

People just don't write comments or tests after, that's the problem. If you do then that's fine, but after trying both routes I actually find TDD to feel like less work - not having to wait on large build times and manually navigating the UI actually makes for a more fun experience. Instant feedback being the fun part. Additionally writing tests 'after' always feels like work to me and I end up hating it, especially when I didn't write it in a testable way to begin with.

Re: Write tests. Not too many. Mostly integration

#117
post #97

Earlier quoted context omitted.

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

There is some cargo culting there but it's mostly correct. Helper is a code smell as it's a sign of "we don't know what the responsibility of this is or what to call it so we'll just chuck a load of shit in this file and call it a helper" . The methods in should belong to something and live on that class, not in an external class. RequestExtensions is more shit than the original solution. Extension methods are even w…

This is a matter of taste not fact. In functional languages the style is compositional with static functions everywhere. It works well. The keeping data and methods together thing is one approach. Sometimes it's great. Sometimes unnecessary.

For example would you argue against string formatting helpers? Or would they need to be written to an interface and added to myriad DI bucket lists?

Re: Write tests. Not too many. Mostly integration

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

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

>That said, if you go for functional style in OOP, i.e. shoving as much as you can into static helper functions and most of the rest into dumb private stateless functions, you suddenly gain both a clean architecture and lots of test points to use in unit tests. So you can have testable code, but you have to chill out with the OOP thing a bit.

Wow, this is exactely totally opposite of how one can achieve testability in OOP! For more details I recommend excellent Misko Hevery's article "Static Methods are Death to Testability" [1]. Also, I'd argue that "functional style in OOP" is an oxymoron - you're either OO or something else (functional, imperative...)

[1] http://misko.hevery.com/2008/12/15/static-methods-are-death-...

Re: Write tests. Not too many. Mostly integration

#119

Earlier quoted context omitted.

I don't see why TDD requires ruling out static methods and insisting on hiding everything behind an interface. Static methods are straightforward to test, certainly more than a class with multiple dependencies which need to be mocked. Usually the complaint is about coupling when calling static methods but these can be wrapped in a delegate if required.

Simply because you can't mock the static dependency, therefore that method is now dependent on the static class and you don't have any control over it. This is problematic - what if at some point later another developer adds a database call into the static method to do some logging? Now your testing will dirty whatever database you're using, as well as run 10x slower - and yet the test will still pass and everyone wi…

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.
Post reply on HN