Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

lib: Use counterfeiter to mock interfaces in tests #7375

Merged
merged 11 commits into from
Mar 3, 2021

Conversation

imsodin
Copy link
Member

@imsodin imsodin commented Feb 18, 2021

I was looking for test tooling to time tests (found gotestsum) and in the process stumbled over counterfeiter: It generates functional test classes for any given interface. As I was annoyed by having to change the various lib/api/mocked_... types to make tests pass in the past, I very much appreciate the idea of having those generated automatically. There's more boilerplate to get rid of in the fake connection in model testing. And the mocked classes provide lots of functionality (controlling what functions do, providing info on which functions were called including arguments, ...) which we could make use of (I guess a lot of the request_test.go stuff could be simplified.

The mocks are created with go:generate, i.e. there's now more assets to generate. I refactored the lazy asset building to work on a list of assets, and rebuild those which are necessary. An asset specifies a list of source and destination paths, which are all walked to get the newest time (and missing root means rebuild too).

There's one ugly hack: The mocked classes always include a reference to the interface. That can lead to cyclic imports. And it seems unlikely that's going to change given the upstream history: maxbrunsfeld/counterfeiter#121. Thus I added a generation script to remove this reference from the generated code for one protocol interface that we do use in protocol tests.

@calmh
Copy link
Member

calmh commented Feb 27, 2021

This seems like a fair amount of complexity for something that isn't super hard to do manually, but allright. However I think we should treat it the same as protobuf stuff -- generate explicitly and check in, so that go test more or less works out of the box for most packages.

@imsodin
Copy link
Member Author

imsodin commented Feb 28, 2021

I see that. It's definitely not hard, just a bit annoying. And I liked this "mock-generator", so wanted to make use of it. Having done the change myself I am not a good judge for the trade-off between complexity/tediousness of the generation vs convenience/functionality of the mocks, as I am set to underestimate the former. I don't want to push this through, if you feel it's too much baggage or something.
I now check the mocks in and there's a simple testmocks subcommand like proto to (re-)generate them.

@calmh
Copy link
Member

calmh commented Mar 1, 2021

No I kinda like adding the mock behavior as required in the test rather than having it somewhere else in the mock, so this is fine to me. Just need to look at it again.

Copy link
Member

@calmh calmh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm cool with the meat of the change. In fact, it's better since relevant functionality is moved closer to the tests that requires it. 👍

})
}

func pruneInterfaceCheck(path string, size int64) error {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is kind of meta, but this seems like a fragile function for several reasons. One obvious alternative would be to pass it through a filter that removes lines starting with var _ =, though of course you gain some extra juggling of a temp file and whatnot.

@@ -66,6 +66,9 @@ func checkCopyright(path string, info os.FileInfo, err error) error {
if copyrightRe.MatchString(scanner.Text()) {
return nil
}
if scanner.Text() == "// Code generated by counterfeiter. DO NOT EDIT." {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

script/prune_mocks.go Outdated Show resolved Hide resolved
script/prune_mocks.go Outdated Show resolved Hide resolved
@imsodin imsodin merged commit 3d91f7c into syncthing:main Mar 3, 2021
@imsodin imsodin deleted the counterfeiter branch March 3, 2021 07:53
imsodin added a commit that referenced this pull request Mar 3, 2021
@calmh calmh added this to the v1.15.0 milestone Mar 3, 2021
@calmh calmh added the frozen-due-to-age Issues closed and untouched for a long time, together with being locked for discussion label Aug 11, 2022
@syncthing syncthing locked and limited conversation to collaborators Aug 11, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
frozen-due-to-age Issues closed and untouched for a long time, together with being locked for discussion
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants