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

Testenv test refactor #221

Merged
merged 11 commits into from
Nov 11, 2021
Merged

Conversation

darkowlzz
Copy link
Contributor

Introduces testenv based tests.
Refactors all the existing tests to use testenv.

⚠️ target branch of the PR is reconcilers-dev.

Expect(err).NotTo(HaveOccurred())
Expect(head.String()).NotTo(Equal(headHash))
})
// TODO: Implement adding request annotation.
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Regarding this, it looks like this test was changed in 4fde199#diff-1168fadffa18bd096582ae7f8b6db744fd896bd5600ee1d1ac6ac4474af251b9L292-L334 which removed the actual steps of this test case.
I couldn't figure out why this was removed from the commit and the associated PR.
Thought of adding it separately and leaving a TODO for now.

Copy link
Member

Choose a reason for hiding this comment

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

Yep that's pretty random. The tests got rearranged in that commit so they could be run with both git implementations; all I can think of it is that I killed those lines, expecting to yank them elsewhere, and neglected to do the second part.

@squaremo
Copy link
Member

squaremo commented Oct 18, 2021

TODO for me to check:

controllers/update_test.go

These use testWithRepoAndImagePolicy:

  • ImageUpdateAutomation
  • initialises Git OK (tested implicitly in the factored out testWithRepoAndImagePolicy)
  • commit spec
    • formats the commit message as in the template (TestImageUpdateAutomation_commit_message)
    • has the commit author as given (TestImageUpdateAutomation_commit_message)
  • update path
    • updates only the deployment in the specified path (TestImageUpdateAutomation_update_path)
  • commit signing ()
    • signs the commit with the generated GPG key (TestImageUpdateAutomation_signed_commit)

The following are run by looping over (git repo URL) protos and (git client library) impls. The original has a test "template" that is called with those two arguments, which has a few conditional blocks within to account for e.g., which git server bits to start and shutdown. The rewritten test has similar conditionals but differs in how it deals with shutting the git server down.

  • Using go-git with {HTTP, SSH} x {libgit2, go-git}

    • with PushSpec
      • creates and pushes the push branch (in t.Run("update with PushSpec", ...))
      • pushes another commit to the push branch (in t.Run("push branch gets updated" ...))
      • still pushes to the push branch after it's merged (in t.Run("still pushes to push branch after it's merged", ...)`; NB this has a small difference because it's run in sequence with the others, so it has to make another change to the latest image -- the dependence on ordering is something to watch for)
    • with Setters
      • updates to the most recent image (in t.Run("with update strategy setters", ...))
      • stops updating when suspended (in t.Run("no reconciliation when object is suspended", ...))
  • defaulting

    • defaults .spec.update to {strategy: Setters} (TestImageUpdateAutomation_defaulting)

controllers/git_test.go

(already in normal form)

controllers/git_error_test.go

(already in normal form)

pkg/test/files_test.go

pkg/update/filereader_test.go

  • load YAMLs with ScreeningLocalReader
    • loads only the YAMLS containing the token

pkg/update/result_test.go

  • image ref
    • gives each component of an image ref
    • deals with hostnames and digests
  • update results
    • deduplicates images
    • collects images by object

pkg/update/update_test.go

  • Update image via kyaml/setters2
    • updates the image marked with the image policy (setter) ref
    • gives the result of the update

@squaremo squaremo self-requested a review October 18, 2021 11:24
@squaremo squaremo self-assigned this Oct 18, 2021
pkg/test/files_test.go Outdated Show resolved Hide resolved
@squaremo
Copy link
Member

To be honest, I prefer the previous formulation (using ginkgo), which was more readable. To wit: I'm finding it difficult to check whether the same things are tested -- it's fairly obvious in the ginkgo version because the setting up and tearing down is separate to the assertions, and the assertions are separate to each other.

Sometimes the reliance of Ginkgo on closures makes it hard to see what's going on, it's true. But flattening it all out is two steps backward for one step forward, I reckon. If ginkgo absolutely must be removed, then I'd like at least to see some of the same structure preserved, where setup/teardown code is shared.

@darkowlzz
Copy link
Contributor Author

darkowlzz commented Oct 18, 2021

To be honest, I prefer the previous formulation (using ginkgo), which was more readable. To wit: I'm finding it difficult to check whether the same things are tested -- it's fairly obvious in the ginkgo version because the setting up and tearing down is separate to the assertions, and the assertions are separate to each other.

Sometimes the reliance of Ginkgo on closures makes it hard to see what's going on, it's true. But flattening it all out is two steps backward for one step forward, I reckon. If ginkgo absolutely must be removed, then I'd like at least to see some of the same structure preserved, where setup/teardown code is shared.

I had that feeling too initially while refactoring it and felt like it'd be better to restructure the tests in a completely different way. But being my first contribution to this code base, I tried to stick to the existing test layout as much as possible to keep the changes familiar and avoid dropping something entirely different. Was hoping to restructure more later once we move completely away from ginkgo and as I get more familiar with the code base. I believe it can be refactored in ways to make it better with helpers for common tasks. The checklist above would be very helpful in restructuring it and ensuring all the checks are retained. Now that we know what a direct conversion of the tests look like, I can give it another try with something different to help make it more readable and easy to maintain 🙂 .
Thanks for the review and very helpful feedback.

@hiddeco
Copy link
Member

hiddeco commented Oct 18, 2021

If ginkgo absolutely must be removed, [..]

It is not a strict requirement (nothing really is – I am just trying to advise and align). However, the kustomize-controller which has been ported awhile ago and seen multiple attributions since, has proven that once the tests are restructured it is much easier to add new tests, especially for new contributors.

@squaremo
Copy link
Member

I believe it can be refactored in ways to make it better with helpers for common tasks.

I think we can get something better than both ginkgo and "flat" tests, by factoring out some bits (which I found awkward with ginkgo) and using closures judiciously to share setup code.

The particular file I was looking at when I wrote the comment above was controllers/update_test.go, which mixes a lot of what were individual tests together into one long section in TestImageAutomation_commit_spec. I think the commit message, path and signing should really have their own tests, and just share a bit of setup.

TestImageAutomation_e2e after that uses a table appropriately, I think -- though it's still very long and could surely have some bits factored out (this was true of the ginkgo code too, it's not a new problem :-).

@darkowlzz
Copy link
Contributor Author

darkowlzz commented Oct 20, 2021

This is still not finished, but any feedback in the new structure would be very helpful.
I've added some helper functions for the common tasks and structured the tests in two parts. The first part sets up the git server, initializes a repo, creates GitRepository resource for the git repo and creates ImagePolicy. The second part is the actual tests in subtests where depending on the test case, ImageUpdateAutomation object is created and scenario specific operations are performed.
I can also try taking the common code of the first part and create a function out of it, but avoiding that for now, unless we are sure that such helper function will be very helpful and not hide too much to affect the readability.

Most of the checks in the checklist for update_test.go should be clear and easy to verify with this change.

I would recommend reading https://github.com/fluxcd/image-automation-controller/blob/435171316d0f331590e8047559aa7e1ec95ca5e2/controllers/update_test.go instead of the diff. To help myself, I've added a lot of comments. Will remove them once I'm finished.

@darkowlzz
Copy link
Contributor Author

This is ready for another review. I hope this is much easier than before to read. But I'm open for more restructuring and simplification.

The DCO check is failing with:

Commit sha: 3917048, Author: Michael Bridgen, Committer: Sunny; Expected "Michael Bridgen mikeb@squaremobius.net", but got "Michael Bridgen mikeb@weave.works".

Is it okay if I edit @squaremo 's commit signoff message myself?

@squaremo
Copy link
Member

Is it okay if I edit @squaremo 's commit signoff message myself?

That was me doing the PR in a directory where I hadn't explicitly set the commit author, sorry about that. Probably better if the author is corrected (to "Michael Bridgen michael@weave.works", rather than the sign-off.

@darkowlzz darkowlzz force-pushed the testenv-refactor branch 2 times, most recently from 8ad81bb to 6c9d377 Compare October 21, 2021 08:12
@darkowlzz
Copy link
Contributor Author

Probably better if the author is corrected (to "Michael Bridgen michael@weave.works", rather than the sign-off.

Changed it. Thanks.

@squaremo
Copy link
Member

squaremo commented Nov 1, 2021

The first part sets up the git server, initializes a repo, creates GitRepository resource for the git repo and creates ImagePolicy. The second part is the actual tests in subtests where depending on the test case, ImageUpdateAutomation object is created and scenario specific operations are performed.

It looks like this scheme is working well in controllers/update_test.go. The first few tests do exactly the same setup (I imagine this is why you mentioned more factoring-out!); perhaps you could use a callback:

func TestSignedCommit(t *testing.T) {
  testWithRepoAndImagePolicy(NewWithT(t), func(tmp, localRepo) {
    policyKey := types.NamespacedName{
      Name:      imagePolicyName,
      Namespace: namespace,
    }
    commitInRepo(g, repoURL, branch, "Install setter marker", func(tmp string) {
      g.Expect(replaceMarker(tmp, policyKey)).To(Succeed())
    })
    // ...
  })
}

(I've glossed over a lot of detail there of course, it's possible that the callback would need too many arguments)

@darkowlzz
Copy link
Contributor Author

Consolidated the common test setup code into testWithRepoAndImagePolicy() which also accepts a testFunc callback to run the test assertions after the setup.
It did result in passing a lot of arguments, but I guess it's okay the way it is now, manageable.

Ready for a review.

Copy link
Member

@squaremo squaremo 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 satisfied that the rewritten suite contains the same tests (thanks for making that pretty easy to check!). The new structure, with subtests sharing setup and common funcs factored out, is at least as good as the structure when using ginkgo I think, and has less magic and fewer lines 👍

I made a PR with a couple of suggestions, but I don't consider them prerequisites to merging this PR.

Thanks for persisting with this work, Sunny 🍍

pkg/update/result_test.go Outdated Show resolved Hide resolved
Add new testenv based TestMain in suite_test.go and move the ginkgo test
setup to legacy_suite_test.go. This helps to run both the ginkgo tests
and testenv based tests.

Signed-off-by: Sunny <darkowlzz@protonmail.com>
Signed-off-by: Sunny <darkowlzz@protonmail.com>
Signed-off-by: Sunny <darkowlzz@protonmail.com>
All the tests use testenv. Remove legacy envtest suite_test.

Signed-off-by: Sunny <darkowlzz@protonmail.com>
In controller-runtime v0.10.0, the client is updated to clean any stale
data in the target object when performing any operation. This results in
test failure for the code that constructs an object with both spec and
status, and creates the object and updates status it with the same
object. The fix is to set the status separately on the object before
updating it.

Refer: kubernetes-sigs/controller-runtime#1640

Signed-off-by: Sunny <darkowlzz@protonmail.com>
squaremo and others added 5 commits November 11, 2021 20:29
Two steps:

1. TestDiffDirectories did not check if the expected only return value
was correct; the intention was there to do so (judging by the
comment "change in order"), but my eye for detail failed me.

2. Reversing the directory comparison in the test revealed bugs in the
comparison code -- in general, it should skip any directory that is
not a directory in the comparator.

To make this easier, the code now keeps track of the expected files it
saw. That means the check for whether an actual file has an expected
counterpart only has two cases, yes or no (rather that trying to
account for whether it's a directory and so on). If a directory was
skipped while scanning the expected files, it won't be in the actual
files anyway.

Signed-off-by: Michael Bridgen <michael@weave.works>
Restructures the tests in update_test.go to separate the individual
checks into separate tests with helpers for common operations.

Signed-off-by: Sunny <darkowlzz@protonmail.com>
testWithRepoAndImagePolicy() contains common code to create a git
server, git repository and ImagePolicy for the test setup.
Also updates some test structure slightly.

Signed-off-by: Sunny <darkowlzz@protonmail.com>
This is just a cosmetic thing -- there's no need for the higher-order
func used to create mini test suites, given the protocol and git
implementation. This made the Gingko version clearer, arguably, but it
can be reduced away here for a bit less nesting.

Signed-off-by: Michael Bridgen <michael@weave.works>
This tidies the random string testWithRepoAndImagePolicy() arguments
into a struct, which reduces clutter (and the chance of getting them
in the wrong order) in invocations.

Signed-off-by: Michael Bridgen <michael@weave.works>
@darkowlzz
Copy link
Contributor Author

darkowlzz commented Nov 11, 2021

Rebased, merged the readability improvements by @squaremo and updated as per the last few suggestions to make the e2e tests more independent.

In TestImageUpdateAutomation_e2e, move the ImagePolicy to be created per
subtest and not shared in the common test environment. This makes the
tests more independent of each other.

Signed-off-by: Sunny <darkowlzz@protonmail.com>
@darkowlzz darkowlzz merged commit ad21e5f into fluxcd:reconcilers-dev Nov 11, 2021
@darkowlzz darkowlzz deleted the testenv-refactor branch November 11, 2021 15:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants