4 ms·
Over the years I have some notes about TDD: * Writing test first is simply unnatural. Way more developers need exploratory session to even discover what are th
by didip 6y ago
Over the years I have some notes about TDD:
* Writing test first is simply unnatural. Way more developers need exploratory session to even discover what are they supposed to do.
* That's because our spec is always vague and no amount of Agile process can help it.
* If you have a bunch of idempotent functions, they are the easiest to write tests on. So I would start there.
* Some languages are easier to do unit tests on, for example: Go. It gives everything you need: test runner, benchmarker, data race checker, unit test struct is part of std library, etc.
* This DSL: `describe(){ it "should work" { result.should eq true } }`, is nuts and counter productive. People are already not writing tests and you are adding another friction?
* To write or to not write mock? This is a controversial one, but in my opinion, it is simply practical to test directly on the database you are using. Your CI/CD should just prep the database you need instead of mocking. Once again, people are already not writing tests, don't add more frictions.
- mitjak 6y ago> Way more developers need exploratory session to even discover what are they supposed to do. to flip this: write tests to help discover what the thing is supposed to do
- ColeyG 6y agoThis idea doesn't make sense to me. Mind elaborating?
- mitjak 6y agosure! write a few tests pretending your thing is already implemented, to capture what you want it to do. at this point it's a step beyond writing no test and just typing `YourThing.Do()` in a text editor. does it make sense? is it awkward? should it even be `YourThing` or `SomeOtherThing`? what the "unit" is of what you're testing might change, or its API might. you're basically just trying to get a sketch of what it's like for the user. now, at the end of this, you'll have a clearer idea of the external API boundary, probably a clearer vision of how it should work, _and_ code you can test against. you've potentially just saved yourself the labour of writing the thing, realizing it needs to be redesigned, and rewriting it.
- cuddlybacon 6y agoI guess the hesitation I have is a do all that, and find out the real implementation should have just been something like adding a new field to an enum and adding/adjusting some if statements. It seems like a giant waste to build an api, when the there is one I could just extend. But to confirm I can just extend that api, I'd need to first implement the change to see it works.
- mitjak 6y agoright, i'm talking about implementing something new. if you're trying to refactor or alter an existing codebase, it can be even easier: you add another test to an already existing suite. i don't think i've ever sat down, written tests for a completely new implementation, only to find that i need to add a field somewhere. before i sit down to write tests, i do some preliminary thinking. i'm not saying, write tests without ever trying to think first. but do use tests to flesh out your change from outside of the black box.
- Strilanc 6y agoCommon advice when designing an API is to experiment with using the planned API before you implement it. TDD is one way of doing this exploration, where the exploration is codified into actual code using the API and including assertions about the behavior you intend to implement.
- arduinomancer 6y ago> * This DSL: `describe(){ it "should work" { result.should eq true } }`, is nuts and counter productive. People are already not writing tests and you are adding another friction? Completely agree. I have no idea why test libraries are so intent on making the test names readable as english sentences, it feels very awkward compared to just naming test methods.
- YorickPeterse 6y agoWhile I'm not a fan of DSLs as seen in Ruby's RSpec, I do enjoy being able to write regular sentences as test names; provided you don't have to stick with the pattern "it is expected to ...".
- jniedrauer 6y ago> Your CI/CD should just prep the database you need instead of mocking. This is a hard one. A lot of tests require setup steps even if you're using a real database, so it's not even that different than a mock. And if you can't give each test its own database to work with, then you have to run your tests serially. I'm working on a codebase that spins up 4 separate database engines in docker, and each test has quite a few setup steps. The result is brittle tests that take hours to run, so they're not very useful as a release gate. I've been bitten by mocks before too though, so I don't have good answers.
- sedatk 6y agoWe did that with transactions. Every test gets their own view of the database, and rolls its changes back after they're done. They take much longer than unit tests but it's worth it in the end as writing unit tests are easy, there is no need to create mocks, and you also test if your DB queries work too this way.
- neillyons 6y ago> * Writing test first is simply unnatural. Way more developers need exploratory session to even discover what are they supposed to do. Fully agree with this. It has been my experience. To quote Mat Ryer from Go Programming Blueprints > The first time we write a piece of code, all we are really doing is learning about the problem and how it might be tackled as well as getting some of our thinking out of our heads and onto paper (or into a text editor). The second time we write it, we are applying our new knowledge to actually solve the problem. https://neillyons.io/the-art-of-writing-is-rewriting/ https://neillyons.io/the-art-of-writing-is-rewriting/