BTW I use @mfeathers explanation that "unit tests are tests that run fast" as a possible valid (foundation/element of a) definition of the term unit test.
Stop arguing which element of structure is meant by unit. Unit does not denote an element of structure. It denotes an element of behavior.
And that shouldn't be surprising: Tests are executable specifications of required BEHAVIOR (NOT: STRUCTURE) by example.
So the full definition of unit test is: "Unit tests are fast executable specifications of required behavior by example."
BTW this also means that a 1:1 association with framework and test style, like Cucumber - not unit test, JUnit - unit test, is wrong.
If you use JUnit but your tests are slow, they are not unit tests.
If you use Cucumber, and your tests are fast, they might be unit tests.
Side note: I like to use Cucumber not only for acceptance testing but also for unit testing, especially in those situations where the unit directly implements behavior that I want to describe for or discuss with other humans in pure business language instead of programming.
We can, of course, not write unit tests purely on behavior. Behavior is inaccessible without an element of structure that exposes behavior to make it accessible.
An element of structure that exposes behavior to make it accessible is called "interface".
But unit tests should not couple to more structure than necessary. Their means is not to verify structure. Their usage of structure serves only a few purposes:
• Access behavior for verification
• Unit interface documention
• Decoupling to make them fast
• Fault injection
Refactoring means a change to the structure of source code without changing the required behavior. The latter is specified by the tests.
Unit tests shall support us with refactoring by providing a safety net so we change structure without accidentally changing required behavior.
Unit tests that are too knowledgable about structure make refactoring expensive. The more that unit tests know about structure, the more the unit tests have to change as well when we change structure. This is a negative impact in at least two ways.
The first negative impact is that refactoring becomes more effort. Not only do we have to - intention - change the structure of the production code, but now we also have to change the structure of the test code.
The second negative impact is worse. When we change tests at the same time, and the change is non-trivial, we might, by accident, impact the means of verification of behavior of the test.
Summary: "Unit" in "Unit Test" means unit of behavior (not unit of structure). Structure may change due to refactoring. Keep risk out of refactoring by having unit tests. Keep effort and risk out of refactoring by not coupling your unit tests to structure more than necessary.
BTW: Yes, this also means that Chicago/Detroit (Stateism) wins over London (Mockism) when all other parameters are equivalent because mocks introduce potentially harmful coupling to structure, and that makes future change more difficult/expensive. Slide by @pragdave
• • •
Missing some Tweet in this thread? You can try to
force a refresh
Agile is much more about reducing lead time, defects, and all kinds of wastes by empiricism (feedback; transparency, inspection, adaptation) on all various scales of time (from seconds to months) than any particular method or framework.
Your practices, methods, and frameworks should be aligned with this: Check where you are, decide where you want to be, go a small step in that direction, look at how that worked, and repeat. Establish that cycle on various time scales.
On the cycle of seconds, we can use editor-based static code analysis, pair programming, and ensemble programming, to get instant feedback on code while code is written.
It seems it's that time again to clear up some misconceptions about DevOps. A thread.
DevOps means Development Operations. If your team isn't doing both, development and operations of the same product/project, it's not DevOps.
DevOps is not about tools but about mindset. Using Docker, Kubernetes, Helm Charts, Packer, Terraform, etc, does not make you DevOps. Having the same team performing development and operations does.
Scrum is all about empiricism. Empiricism is good. Empiricism is usually not the problem. In fact, Scrum can even increase the problem.
So you know you have a problem. You can't react to change fast enough. Empiricism isn't helpful: it will only tell you what you already know: that you can't react to change fast enough.
Are you ready for a little thread on a few aspects of software (re-)design, sparkled with inspirational quotes around the topic?
Let's go!
"Life is really simple, but we insist on making it complicated."
― Confucius
When we get the chance for a (rewrite or re-)design, there is a temptation that we should resist, from a technical perspective as well as from a business perspective. That temptation is to equate "better" with "more". And that's wrong.
The fundamental vim ideas:
• Commands come in sequences. Having a command mode allows commands with fewer keystrokes and fewer modifier keys to make you more efficient. Also, move away less from the touch typing homerow.
• Commands are mnemonic. For example, z for folding...
...z looks like a sheet of paper when folded.
Why hjkl? Touch typing homerow. Of that, h is left, l is right. The shape j goes down, k goes up. I don't remember specifically what hjkl do, I just remember that the whole editor is mnemonic. That way I remember more with less.
• Repetition. All normal commands can be combined with ranges and counts.