4 ms·
Things can go wrong at every step, which means each collection of fallible steps carries with it a combinatorial explosion of successes and failures. Do 5 falli
by closeparen 5y ago
Things can go wrong at every step, which means each collection of fallible steps carries with it a combinatorial explosion of successes and failures. Do 5 fallible statements in sequence and it's 5+4+3+2+1 = 15 mock expectations you need to write. This tedious enumeration exercise is the majority of the time that goes into writing Go programs, for me at least.
- boloust 5y agoMost of the time, you'll return early after an error. To get into a situation where you'd need to handle n! cases, you'd need to keep running the statements after a failure, and then collate and return all the errors at the end. Not sure why you'd want to do that. You'd definitely need to go out of your way to do something like this, and probably start asking yourself why you're doing this pretty early on. Plus it would flat out refuse to compile in some cases where there are dependencies between the statements.
- closeparen 5y agoIt’s + not * in that example.
- boloust 5y agoAh, okay. In that case it becomes {n + 1 \choose n - 1} What code are you writing that results in this set of possibilities?
- jerf 5y agoI have some code where I use multierrors and collect everything into one big error (I highly recommend this for "validation"-type code, you should generally return all errors not merely the first), but what code are you writing where you're running 5 statements unconditionally but need to handle nearly-arbitrary combinations of them failing, and multierrors aren't what you need?
- closeparen 5y agoIf you have 5 statements like "if err := doThing(); err != nil { return err }" then you need to simulate the success of all 5, success of the first 4 and failure of the last, success of the first 3 and failure of the 4th, success of the first 2 and failure of the 3rd, etc.
- morelisp 5y agoFor a total of six cases to deal with. Not 15.
- closeparen 5y agoI said 15 mock expectations, not cases.
- morelisp 5y agoIf all five of those things also need to be independently mocked, you're mocking too much and your mocks suck.
- closeparen 5y agoIf they're not mocked it's an integration test. Integration tests are welcome as a supplement to unit tests, but unit tests are table stakes.
- morelisp 5y agoAn automated test suite is table stables. If you can achieve correct, maintainable code better with functional or integration tests than unit tests, you should. There is no hard technical line between "unit test" and "integration tests", it's a semantic question of how you define your units. Even if do you take a tiny, restrictive definition of your units, you could still use a fake or stub instead of a mock. https://martinfowler.com/articles/mocksArentStubs.html https://martinfowler.com/articles/mocksArentStubs.html To get very specific for Go, we use testify suites, tend to set up fully functional stubs in `SetUp`, and then test cases either use them to verify happy paths, or `s.BreakStep1()` in one test, `s.BreakStep2()` in the next, etc. So in this case we would write a total of five extra lines for the five possible ways to break.