4 ms·
In my personal, subjective and very non-prescritive experience, unit tests aren't very useful for much. Behavioral Driven Development (i.e. Cucumber tests) at t
by WalterSear 4y ago
In my personal, subjective and very non-prescritive experience, unit tests aren't very useful for much. Behavioral Driven Development (i.e. Cucumber tests) at the module level are what I start with when attempting to corral musty code.
I totally agree that, even then, wrangling ungroomed interdependencies are definitely the biggest headache. But I have yet to adopt this approach and not think to myself, "why didn't I start this sooner?"
- bmitc 4y ago> In my personal, subjective and very non-prescritive experience, unit tests aren't very useful for much. Why is that? In more functional oriented languages, they are great because they allow you to verify behavior of functions. Then in the broader application, you're just composing pieces that have already been validated, and the compositions can also be tested. If you're able to incorporate property-based testing, then that's even better.
- WalterSear 4y ago* Because I care about function, not implementation * Writing tests has a cost, so I want to right as few as possible while ensuring functionality. * rewriting tests has a cost. When I start writing, I know what functionality I want, but I may iterate significantly on implementation. This makes unit tests both an impediment, and providing me no safety to perform the refactor/reimplementation. * the module, or it's equivalent structure in your language, is the optimal tradeoff between standalone functionality. Ideally, a module encompasses a small enough behaviour to fit in one's head. IMHO, an ideal single function should be small enough that it's behavior is readably obvious. * module inputs and dependencies are easier to instrument in tests. I/O and hardware API dependencies can be injected/overridden. On the other hand, private variables and internal instantiations can be complex and hard to mock appropriately when unit testing, unless you are able to structure absolutely everything as a pure function - IMHO a platonic ideal, particularly in the workplace. * Functional tests are easier for other coders (and even non-coders, in regards to feature files) to understand. "I wrote 100 unit tests" provides less information regarding actual functionality and productivity than "this feature's scenarios are all passing now." The originators of unit tests and extreme programming explicitly stated that unit tests are not to be checked into source control, and deleted instead. They felt that unit tests would overly constrain subsequent programmers, and that higher level suites were more useful at providing refactoring safety. The only time to submit a smaller sized test is as part of a bug fix, where one would write a failing test, fix the code and check it in. Fwiw, while I agree with them on this, I'm don't want to come across as appealing to authority. A lot of Agile/eXtreme/Scrum ideas reflect a simpler and very different time in coding, when code was, by necessity simpler and easier to reason about, and the culture of computers gave engineers much more power to push back on management demands and prioritize code quality. And some of the ideas are just hokey - like eXtreme programmings dislike for branches - encouraging all developers on a team to land their code on 'main' at the end of every day. Besides, the very first Agile project -that birthed the movement - went over time and over budget :)
- bmitc 4y agoWith this clarification, I'm not sure I'm understanding the distinction between a unit test and a functional test, so it's possible we're thinking the same thing. And I'm not sure there is a distinction with the languages I use, which are primarily functional languages. To me, units are functions and features that are exported by modules. With languages with immutable data and pure functions, tests are almost needed less at higher levels, because there you have easily understood compositions of things that already work. I agree that tests have costs, but they are part of the implementation. Just throwing them out means that the implementation is only partially there. It's just a fact of nature for code. One does have to be careful to avoid doing tests just for warm fuzzies though.
- throwbadubadu 4y agoI find this is always bean counting... in fact imo most unit testing should be about module boundaries, and not every single function (but fully admitted, that picture changes a bit with functional languages), because that is what is most reasonable. Whoever said that unit testing is about testing your most smallest bits only and you need to test your smallest program decompositions?? (And by that logic, why not test each individual line, or each individual expression???) Because composition also counts and you anyway need to test it, but instead hordes of programmers write unit test with bad mocks that only test unnecessary implementation detail and get fully in the way of any reasonable refactoring, but composition, functional behaviour is not tested. So imo it is all about definition of what is a unit: It can be your one complicated algorithm heavy function, it can be a whole module at its module interface, it can even be x modules together achieving together a functionality/behaviour. I can only roll eyes at people who try to tell other people what a unit test is and what not, and what is "wrong" unit testing.. I would hope we'd more distinguish bad vs good testing instead discussing about what is unit and what is integration testing... and most of the time bad tests stem from the crowd wanting to tell what is a unit test and what is not, tbh.
- WalterBright 4y agoI've had much success with it when I designed a program from the ground up to do unittests, i.e. the Warp C preprocessor program: https://github.com/DigitalMars/dmpp https://github.com/DigitalMars/dmpp Once it was all put together, nearly all the bugs were misunderstandings on my part, rather than detail bugs.