3 ms·
This is true only if you adhere to the common definition of "unit test" where a unit test must test a single class or method on a class, often with use of lots
by SideburnsOfDoom 3y ago
This is true only if you adhere to the common definition of "unit test" where a unit test must test a single class or method on a class, often with use of lots of mocks.
Common but not necessarily best.
Let me pose a question: if refactoring is "changing code while tests stay green", then how do you refactor when any change to public methods always breaks tests? When "extract class" means a change to test class structure as well?
Testing at this close-coupled level far from mandatory. IMHO, the use of the word "unit" is deliberately vague: if it was always a "class test" or "method test" then it would be called "method test" and "class test" not "unit".
"unit" means "you choose". it means "a chunk of useful functionality", in problem domain or business terms. It means "can I test this in isolation from e.g. file system, http services and other concurrent tests", as per Michael Feathers's guidelines (1)
I'm not suggesting that you should never unit test at a close level of class and method; I am suggesting that you might benefit from a majority of unit tests being not at this close level.
1) https://www.artima.com/weblogs/viewpost.jsp?thread=126923 https://www.artima.com/weblogs/viewpost.jsp?thread=126923
- nottorp 3y agoWell, Agile also used to make sense before it was called Agile and turned into a set of rituals. Same for unit tests and any other practical matters that have turned into religion. Plus there's the little matter that you tend to think that your application is tested if it has automated tests. Then your colleague in sales who clicks like he's having an epileptic episode comes over and your app crashes 3 different times [1]. [1] True story. I used to ask him to click 2 min on whatever I was working on when he passed by my desk. [2] PalmOS had the gremlins tool. To my knowledge no other platform has it.
- SideburnsOfDoom 3y ago> Well, Agile also used to make sense before it was called Agile and turned into a set of rituals. If you want to make sense of "Agile" read "The Agile manifesto" (1), it's not long even with the 2nd page (2). but yes, the modern criticisms of modern "agile" are pretty much the same as the problems that caused that agile movement in the first place. And are starkly at odds with the Agile Manifesto, e.g. "Individuals and interactions over processes and tools" and "Responding to change over following a plan" vs "Our tool, Jira, enables micromanagement of human resources over a long-term plan" 1) https://agilemanifesto.org/ https://agilemanifesto.org/ 2) https://agilemanifesto.org/principles.html https://agilemanifesto.org/principles.html
- nottorp 3y ago> If you want to make sense of "Agile" read "The Agile manifesto" Yeah, too bad modern Agile doesn't have much to do with the original manifesto...
- pasc1878 3y agoYep one tester I know had as his first tests Hit multiple keys on the keyborard at once and do that for a few seconds. Then if it p[assed that he would get down to more structured testing. Testers have to assume the user is an idiot and also will always do the wrong thing.
- SideburnsOfDoom 3y agoTesters have value. But that value is not in yet again, before each release, taking a day to run through an excel spreadsheet of checks that should have been long ago automated into a 2-minute run.
- pasc1878 3y agoAgreed on more automation. But some tests will take time to run so a day turn round is a quick turnround. If you have databases involved it will not be a 2 minute run - the network latency will make the queries take time. Note these need to be run as integration tests so mocking is not sufficient.
- TheCoelacanth 3y ago2 minutes is an eternity in database time. You should be able to run dozens of test cases in that amount of time unless your app is just monstrously slow.
- pasc1878 3y agoThe time in the database is low. The time is the time transferring data over the network and the limiting factor is the number of individual transactions. A result processing one record does have similar speed to one looking at 1000 records.
- strogonoff 3y agoThe concept of refactor does not apply in context of publicly exposed interfaces—i.e., you logically never “refactor” a public API, you release a new version of it. As such, it would have different inputs and outputs and therefore its own separate tests. This becomes more difficult to reason about when what you build is not just a library but something more like a web service or a GUI/CLI app. For a library, a unit test may be able to cover public API and be an end-to-end test in effect, whereas for a more complex product intended to exist over time in production unit tests do in fact provide less of a guarantee, and versioning public API becomes difficult (unless you immediately drop support for any non-current API version).
- SideburnsOfDoom 3y agoIt is useful to be able to refactor the code behind that interface, or 1 or more levels down the call stack, while testing via that public interface. Contract changes is one reason for such a code change, but there are many others - including bug fixes, error handling, handling input cases that were not well supported before, performance or readability improvement, changing to use a new version of an internal library with a new contract, and pure refactoring to e.g. extract common code, with no other logical change. it is useful to do such incremental changes supported by tests on a "publicly exposed interface" that does not change frequently, instead of tests coupled to classes that are not not part of a "publicly exposed interface".
- deleted 3y ago[deleted]
- strogonoff 3y agoAbsolutely. If there is no logical change to a public interface, then your e2e tests (irrespective of whether they are unit tests, where units are strictly public members or classes or modules, or some other kind of tests) should not change either.