Live data from Hacker News

Ask HN: How to approach testing in Golang?

news.ycombinator.com

31–37 of 37 posts

Re: Ask HN: How to approach testing in Golang?

#31

Earlier quoted context omitted.

I also use that same pattern. I'm very tempted to write a tool to be called by `go generate` to automatically create that kind of mock.

Please don't. I mean, do, whatever makes you happy. There's at least 3 of these flying around in various stages of abandonment. Here's one: https://github.com/vektra/mockery

Looks like there's an official tool: https://github.com/golang/mock

Re: Ask HN: How to approach testing in Golang?

#32

Earlier quoted context omitted.

I also use that same pattern. I'm very tempted to write a tool to be called by `go generate` to automatically create that kind of mock.

Please don't. I mean, do, whatever makes you happy. There's at least 3 of these flying around in various stages of abandonment. Here's one: https://github.com/vektra/mockery

Do any of those build this style of mock? I looked around a while back and didn't come across one.

edit: I looked again and found https://github.com/matryer/moq which seems similar

Re: Ask HN: How to approach testing in Golang?

#33

Earlier quoted context omitted.

A mock is a fake. Just so we are using the same terminology I'll define my terms: Fake: a test implementation of something that stands in for production code to solve certain testing problems. A fake can implement an API and provide simplified behaviour. A good example might be a piece of code that stands in for a hardware device driver that you use when you don't have access to the hardware. Another very common use…

>Outside-in and promiscuous mocking has several advantages -- especially when you are less experienced. It provides a framework for reasoning about how to do design. I find that any additional couplings to your code makes the couplings you do have more painful to work with. Some people think that by adding this kind of 'tight coupling' - low level mocks / unit tests - you feel that pain earlier on in the design proce…

Very similar to cigarettes, the really nasty effects don't usually materialise until quite far down the road -- when you don't have much opportunity to deal with them.

However, I don't think it has to be like this. I sometimes call mocking "wish based design". Sometimes you don't really know what shape is going to be good. You know ahead of time that TDDing a solution is likely to churn a lot of time writing stuff you are going to ultimately throw away. You can spike a solution to get some more information, but there is often a lot of pressure to ship whatever you spiked, no matter how successful you were (or how bad your tests ended up being).

With a mocking approach you think to yourself, "If this were already written and I was using it, ideally how would it work?" You mock your wish and you write the use side of the code in your tests. Quite frequently this reveals most of your naivety and allows you to design what it is you need. At that point, you replace the mocks with real implementation. It's at this point where I differ from the main proponents of the style (or at least last time I talked to them, which is admittedly several years ago). I will TDD my implementation, removing the mocks as I go.

So, on reflection, I guess I use it in places where I would otherwise spike a solution. Again, for fairly junior people, it can be a great technique to help them understand where to start. Often I find that junior people can't do TDD because they simply can't envision what they are building. They will spike a solution, jam a couple of tests in to show that it's basically working and call it a day. A mocked solution often ends up exposing state in the places where it needs to be. This is frequently better than the spiked solution which is usually an encapsulated ball of mud.

As I said before, though, I use it as a technique of last resort, not a technique of first resort.

Re: Ask HN: How to approach testing in Golang?

#34

Earlier quoted context omitted.

>Outside-in and promiscuous mocking has several advantages -- especially when you are less experienced. It provides a framework for reasoning about how to do design. I find that any additional couplings to your code makes the couplings you do have more painful to work with. Some people think that by adding this kind of 'tight coupling' - low level mocks / unit tests - you feel that pain earlier on in the design proce…

Very similar to cigarettes, the really nasty effects don't usually materialise until quite far down the road -- when you don't have much opportunity to deal with them. However, I don't think it has to be like this. I sometimes call mocking "wish based design". Sometimes you don't really know what shape is going to be good. You know ahead of time that TDDing a solution is likely to churn a lot of time writing stuff yo…

>However, I don't think it has to be like this. I sometimes call mocking "wish based design". Sometimes you don't really know what shape is going to be good.

That's why I write executable specs at a high level with my "wish based design", make that "test" pass and then refactor. Wish first -> code next -> only well designed code after that.

I don't feel the need to dive down another level and mock out real modules that are already covered by this high level test. That's just creating unnecessary work for myself and introducing a potential source of test bugs (where the mock doesn't match the reality).

Re: Ask HN: How to approach testing in Golang?

#35
1. Interfaces allow swapping out objects.

2. Mocking is a bad idea even in languages that support it well.

A better approach, when you do need to deal with fakes, is verified fakes: write two versions of an interface, and a test suite for that interface to ensure the fake acts the same as the real thing.

More here: https://codewithoutrules.com/2016/07/31/verified-fakes/

Re: Ask HN: How to approach testing in Golang?

#36
post #4

Check out https://github.com/stretchr/testify for more convenient assertions, as well as mocking support for implementing interfaces within your tests. You cannot do ad-hoc mocking of arbitrary functions in Go. If you want to write component-level tests that mock out other components, then you need an interface boundry between those components. Or better yet, you just write tests at the network level, spinning up moc…

I find vanilla Go testing (if res != exp { t.Fatal(...) }) much more versatile than testify. Testify did not cover some of my mocking use cases, and response on the repo was tepid, so I ditched it and was happier (this is a user POV, please don't come bashing me on not contributing to open source, etc.) For mocks, I use GoMocks ( https://github.com/golang/mock ), again a "standard" lib of go. It has Expect syntax whe…

I don't fully grok this logic. So if Google adds a test assertion framework to the stdlib, then you would recommend using because it is now "Go approved"? In that event nothing has changed other than where the code is coming from.

You can't reasonable say that both methods are equal. Would you still recommend the (if res != exp { t.Fatal(...)}) in this case? If "No", then doesn't that mean you actually prefer more complex assertion primitives?

Do you only use "if" test conditions in C, C++, Java, Python? Why or why not? If "No", why is it acceptable to use more code and logic just because you switched to Go?

Post reply on HN