-
Notifications
You must be signed in to change notification settings - Fork 107
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
tests: increase coverage of store.go #499
Conversation
I love to test code, but an admin needs to say |
|
@ondrejbudai Thanks a lot! That works perfectly :) |
Rather than use global variables, I would create a new dir/store for each test that you want to do. Otherwise, this looks like a good start to me. |
f166384
to
c0197c7
Compare
Ok I believe it's in a state worthy of review. This is just testing the functions that are working with Blueprints. I want to get that merged before moving on. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If I understand this correctly, these tests are dependant on each other and also on their order. I could not find a reliable source, but several SO posts[1][2] speak against depending on the test order.
I suggest encapsulating all the code in one big test and using the subTests, which does have a well-defined order. Also, using this method we can get rid of all the global variables,
[1] https://stackoverflow.com/questions/31201858/how-to-run-golang-tests-sequentially
[2] https://stackoverflow.com/questions/30171693/execute-test-cases-in-a-pre-defined-order
Indeed having inter dependencies between tests is generally considered bad practice. Each test must setup/teardown around itself. If this is undesirable (e.g. too expensive) then all of them should use a common environment but not be dependent on the state of the environment. If there are specific pre-conditions then each test must ensure they are met before doing any testing. FTR some test runners (e.g. rspec) can execute tests in randomized order which help discover and fix these inter dependencies. To my knowledge most other languages don't provide this ability. |
I tried to use the TestWrapper approach with a few tests now just to see how it looks and I find this to be pretty much the same like having one big test case. On the outside I just see
I liked it more when I could see all the test cases but as I understand it you can't do that when using a wrapper. But I guess making sure the tests run in the order I want is more important here. |
Ok I understand it's better to have each test case independent but here it's easier to just share that one state and assert the functions with that.
If the order in which the tests are being run ensures that and I ensure the order is always the same then it's ok? EDIT: |
So I tried another approach using testify/suite I think it looks pretty nice, setup and teardown looks easy, but the tests are executed in alphabetical order right now and I guess that could change in the future so I should not rely on that.. Some discussion was held here.
|
It seems to be that |
This is a unit test and such coupling between the test functions and order of execution is a very bad practice IMO. This generally makes the test suite/test functions more fragile. It could be acceptable for an integration style test which needs expensive setup operations but that doesn't seem to be the case here. The suite approach looks better to me, also that's what you can generally see in other tests written in go (e.g. blogs, examples, etc). I still don't understand what necessitates the inter-dependencies between test functions and their order of execution? In particular which test functions depend on what state or which other test functions? Answering this should help with untangling the functions from one another. Why not have the setup/teardown as functions and just call them before/after each test ? Will also solve the issue with os.Exit and defer. |
@atodorov You're right, I want to avoid bad practices and learn to do whatever is best. I like the Also the output looks like this now:
|
This adds coverage for the methods working with Blueprints
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like it, thanks!
This introduces a new library to the tests. I wonder if we should decide on a usage policy. I propose a simple "use it when you feel it's appropriate". Tagging @teg, @larskarlitski and @msehnout, so they know about this change.
internal/store/store_test.go
Outdated
@@ -1,15 +1,195 @@ | |||
package store | |||
|
|||
import ( | |||
"github.com/osbuild/osbuild-composer/internal/blueprint" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Imports are not grouped properly (no big issue)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh, do we have some rules for this or are there any common rules for this? I always just rely on go fmt
to do all this work.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We try sorting the imports like this:
- standard library
- 3rd party packages
- our packages
However, we don't enforce it (there's sadly no way to enforce it on the CI).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Now that I know this, I can enforce it on me myself :D ... Is it correct now?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can prepare-source
/ go fmt
take care of this somehow ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
However, we don't enforce it (there's sadly no way to enforce it on the CI).
@ondrejbudai there must be linters for that, right? At least in Python both pylint (and I think) isort follow the same policy as you described above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There's goimports
. I tried it and it had very strange results in some cases.
Then there's impi, but I wasn't brave enough to use it, it doesn't seem much popular. However, I think it does the grouping right. Feel free to investigate it if you see a value in it.
Sounds good to me. Thanks for letting me know. |
Sounds good to me too! |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for this!
I am creating this now just to get some specific advice, I know I need to do better naming, cover some more functions and probably some more changes.
I recently talked with @teg about how to tackle this after some recent changes and so what I intend to do here is create a temporary directory and in there create a new
state.json
(Line:17-18) and fill it with data using all the different methods instore.go
and use that to check the functionality of the other methods that retrieve the data and more... I want to delete the temp directory once all the tests are finished. I could do that by just deferring the deletion of the dir but that means I would have to do all the tests inside one function which I don't really like, I like it more when each function/method has it's own test function. So what I did now is created the temp dir as a global variable which seems to work fine but I have to remember to delete it at some point probably in the last function (Line:74), but I don't think this is correct because the dir would not get removed in case of some error and the function where it's being removed would not be ran.Any thoughts what's the best approach to solve this @teg @atodorov ?