I like TDD in theory and I spent so many years trying to get it perfect. I remember going to a conference where someone was teaching TDD while writing tic tac toe. Unsurprisingly, he didn’t finish in time.

The thing that I hate is people conflating TDD with testing or unit testing. They’re vastly different things. Also, I hate mocks. I spent so long learning all the test doubles to pass interviews: what’s the difference between a spy, fake, stub, mock, etc. Also doing it with dependency injection and all that. I much prefer having an in-memory database than mock what a database does. Last company I worked at, I saw people write tests for what would happen if the API returned a 404 and they wrote code that would handle it and all that. In practice, our HTTP library would throw an exception not return with a statusCode of 404. Kinda funny.

You obviously can’t always get replacements for things and you’ll need to mock and I get that. I just prefer to not use them if I can.

Also, TDD advocates love saying, you’re just not doing it well or you just don’t know enough.

I get it, you love TDD and it works for you and more power to you.

I definitely believe in testing and having resilient tests that will minimize changes upon refactoring, but TDD doesn’t work for me for most of the work I do. It works for some and I love it when it does, but yeah … sorry random long ramble.

I much prefer having an in-memory database than mock what a database does.

Which sounds great in theory but then you get to find where your prod DB and testing DB differ and you have to keep chasing that. Unless you are using something like SQLite which has both (disk and in-memory) as an option.

I worked at a place that used a different in-memory DB (H2, IIRC) in place of our MySQL DB for testing. It ended up being hell to maintain and had to have hacks for how H2 and MySQL differ (tests would work in H2 but fail if run against MySQL or vice versa).

anar
link
fedilink
6
edit-2
1Y

This reminds me when a senior engineer asked me to write exception handling on a one-off python script, not a production code - just a script devs can use internally. The “handling” was that the program should exit when a file is not found. He wanted me to try the file open, except the file error, print “file not found” message and exit(1).

Guess what, genius. Python already does that for you. No need to write an extra wrapper needlessly.

I had a coworker who was big into TDD. He was using it on a disaster project that was way over budget and long overdue. I was sitting in on a meeting between him and the client when he tried to defend the project’s status by saying “you don’t understand - we’ve written six times as much test code as actual code!” The client almost punched him.

IMO it doesn’t matter what methodology you use if a) you don’t have the ability to understand what the client actually needs, and 2) you can’t code your way out of a paper bag (or to put it more technically, if you over-architect your solution and then can’t solve all the self-inflicted problems you run into).

a) you don’t have the ability to understand what the client actually needs

the client doesn’t understand either. This I have had to learn to accept and not blame the client for, it’s OK and we’ll figure it out together

b) if you over-architect your solution

we can’t figure out what we actually need by overarchitecting something to death. If and when you find you’ve coded yourself into a corner because you didn’t architect well enough 6 months ago, then congratulations it seems like what you’re doing is good because you’ve made enough progress to actually need a better architecture

obviously I’m oversimplifying and people more experienced than me understand better how to walk the tightrope between unmaintainable spaghetti and an overengineered mess, but me, I try to keep shit as simple as possible because you never know

Fedora
link
fedilink
11Y

Time spent on tests is time saved in debugging, firefighting, troubleshooting, etc. If the project breaks down with a simple change, then tests also save the sanity of developers, and allows them to refactor the architecture.

Also, I hate mocks. I spent so long learning all the test doubles to pass interviews: what’s the difference between a spy, fake, stub, mock, etc.

Oh good grief. I haven’t even heard of half of those, and I’ve been writing code longer than most interviewers.

Also doing it with dependency injection and all that.

After struggling with several DI frameworks, I’ve come to the conclusion that DI is far too opaque and unpredictable to be useful.

OOP is also intentionally opaque, mind you, but debuggers can see through it if necessary, so that’s fine. DI, on the other hand, is opaque even to debuggers!

I much prefer having an in-memory database than mock what a database does.

I much prefer using the same DBMS for tests as the one used in production. That way, I can use its special features (like arrays as query parameters), and avoid bugs resulting from differences between DBMSes (which would only appear in production).

You obviously can’t always get replacements for things and you’ll need to mock and I get that. I just prefer to not use them if I can.

Indeed, and you usually can. Even if your system involves a bunch of services that normally run on different machines, who says you can’t spin up instances of them as part of the test? Tests are arbitrary code and can do anything that any other program can do, including starting subprocesses. Just be sure to terminate them once the test is finished, even if it fails.

After many failed attempts at TDD, I realized/settled on test driven design, which is as simple as making sure what you’re writing can be tested. I don’t see writing the test first as a must, only good to have, but testable code is definitely a must.

This approach is so much easier and useful in real situations, which is anything more complicated than foo/bar. Most of the time, just asking an engineer how they plan to test it will make all the difference. I don’t have to enforce my preference on anyone. I’m not restricting the team. I’m not creating a knowledge vacuum where only the seniors know how yo code and the juniors feel like they know nothing.

Just think how you plan to test it, anyone can do that.

I like to mock up dependencies with Docker Compose, then run all the tests against that. Keep the compose file in the repo, of course. I don’t tend to build a lot of real unit tests unless I’m doing something very novel and self contained. When you’re just assembling a service out of REST libraries and databases, integration testing is mostly what you want.

Create a post

Post funny things about programming here! (Or just rant about your favourite programming language.)

Rules:

  • Posts must be relevant to programming, programmers, or computer science.
  • No NSFW content.
  • Jokes must be in good taste. No hate speech, bigotry, etc.
  • 1 user online
  • 77 users / day
  • 211 users / week
  • 413 users / month
  • 2.92K users / 6 months
  • 1 subscriber
  • 1.53K Posts
  • 33.8K Comments
  • Modlog