News for hackers. Stuff that matters.
Re:Twelve Years of Go by vlunkr on Wednesday November 10, 2021 @03:51PM (#29180577)
> One of the things Go taught me is that I was not being as careful about my errors as I should be.

I identify with this so much. Especially when dealing with external things (file system, database, network) things can go wrong at nearly every step. And yeah, that means you have to check errors at every step, but it forces you to think about how you want to handle them, and what message you want to propagate when they happen. As a result, my Go code has very few unexpected errors in production.

Re:Twelve Years of Go by new_stranger on Wednesday November 10, 2021 @04:08PM (#29180836)
Hard to overemphasize this. Handling errors is similar to the benefits that writing tests provides - slower upfront, but a more stable product gets shipped.

Handling errors everywhere means problems are already solved before they happen. No 1 am pagerduty alerts because we didn't consider what would happen if a DNS server hung until we timed out and thought just wrapping in a try/catch and crashing was a good idea.

Re:Twelve Years of Go by closeparen on Wednesday November 10, 2021 @06:46PM (#29182533)
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.
Re:Twelve Years of Go by boloust on Wednesday November 10, 2021 @07:35PM (#29182972)
Most 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.

Re:Twelve Years of Go by closeparen on Wednesday November 10, 2021 @07:42PM (#29183020)
It’s + not * in that example.
Re:Twelve Years of Go by boloust on Wednesday November 10, 2021 @08:07PM (#29183222)
Ah, okay. In that case it becomes

  {n + 1 \choose n - 1}
What code are you writing that results in this set of possibilities?
Re:Twelve Years of Go by jerf on Wednesday November 10, 2021 @09:58PM (#29183965)
I 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?
Re:Twelve Years of Go by closeparen on Wednesday November 10, 2021 @10:09PM (#29184043)
If 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.
Re:Twelve Years of Go by morelisp on Thursday November 11, 2021 @07:46AM (#29187305)
For a total of six cases to deal with. Not 15.
Re:Twelve Years of Go by closeparen on Thursday November 11, 2021 @12:20PM (#29190456)
I said 15 mock expectations, not cases.
Re:Twelve Years of Go by morelisp on Thursday November 11, 2021 @01:47PM (#29191485)
If all five of those things also need to be independently mocked, you're mocking too much and your mocks suck.
Re:Twelve Years of Go by closeparen on Thursday November 11, 2021 @03:51PM (#29192995)
If 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.
Re:Twelve Years of Go by morelisp on Friday November 12, 2021 @03:08AM (#29197245)
An 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

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.

Re:Twelve Years of Go by closeparen on Friday November 12, 2021 @03:05PM (#29203946)
I think that is a fair opinion and my life at work would be better if others shared that opinion. Go however does officially stake out the opposite position: coverage only "counts" if the test is in the same package as the unit under test.