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

Tech Debt: Simplify unit tests by using UnstructuredSet & ObjMetadataSet with AssertEqual deep comparison #428

Open
karlkfi opened this issue Oct 11, 2021 · 10 comments
Assignees
Labels
lifecycle/frozen Indicates that an issue or PR should not be auto-closed due to staleness.

Comments

@karlkfi
Copy link
Contributor

karlkfi commented Oct 11, 2021

Follow up after #419 and #426

/assign @karlkfi

@ash2k
Copy link
Member

ash2k commented Oct 18, 2021

I've just bumped the version of cli-utils I use and found the UnstructuredSet change. I'm wondering how exactly it's going to help with testing? I'm also using cmp to do diffing and I don't see how the new Equal method is helpful.

p.s. Also, I think ideally methods for testing should live in a separate package and not on a type that is used in production code.

@karlkfi
Copy link
Contributor Author

karlkfi commented Oct 18, 2021

The Equal ignores order and duplicates when comparing the set. Having an Equal on the list also allows comparison of structs that contain the list.

It also indicates to callers that input/output order isn’t important while still allowing cli-utils to sort it without a huge refactor.

@ash2k
Copy link
Member

ash2k commented Oct 18, 2021

The Equal ignores order and duplicates when comparing the set. Having an Equal on the list also allows comparison of structs that contain the list.

Ok, I see the description of Equal() here https://pkg.go.dev/github.com/google/go-cmp/cmp#pkg-overview. Can it show the diff in this case (i.e. why the sets are different)? I suspect it cannot, but I haven't tried.

When using cmp, this can be done via cmp.FilterPath()+cmp.Transformer(). I'm using this technique to transform a runtime.Object into an Unstructured to compare object regardless if they are typed or not. We can use this approach to convert UnstructuredSet into e.g. a []map[string]interface{} after deduplicating and sorting it (sort must be deterministic - perhaps GVK+namespace+name+hash of the object to resolve ordering conflicts).

The benefit of this approach is that cmp would be able to show a meaningful diff and that there is no method for tests on the type.

It also indicates to callers that input/output order isn’t important while still allowing cli-utils to sort it without a huge refactor.

I don't mind the alias per se, I think it makes sense to have it as a way to carry the semantics (and doc) on it.

@ash2k
Copy link
Member

ash2k commented Oct 18, 2021

So if we build a cmp.Option that would do that transformation, we and library users will be able to use it like this:

a := ... // a is a struct/slice/map, containing UnstructuredSet
b := ... // b is a struct/slice/map, containing UnstructuredSet
assert.Empty(t, cmp.Diff(a, b, cliUtilsTesting.TransformUnstructuredSet()))

I use assert.Empty(t, cmp.Diff()) because it prints the diff between objects, not just says they are not equal and fails, forcing me to run the test under a debugger.

@karlkfi
Copy link
Contributor Author

karlkfi commented Oct 18, 2021

I added a testutil.assertEqual/assertNotEqual already that prints a diff on failure. We’re using it for event comparison already in the e2e tests. It doesn’t currently sort the elements for the diff, but we could make it use the transformer pattern before diffing. There’s already a sorter in the ordering package.

I’m hoping to just get rid off the ExpEvent objects all together and compare actual events, but it requires some more enhancements to make things in the event structs more comparable first. There’s some annoyingly deep recursion happening in them that probably shouldn’t have been exposed in a public facing API.

Anyway, I’ll take a stab at using the new sets for the unit tests. It’s should make it clear what other enhancements are needed. But yes, getting a clear and actionable error on failure is definitely one of the goals.

@karlkfi karlkfi changed the title Simplify unit tests by using UnstructuredSet & ObjMetadataSet with AssertEqual deep comparison Tech Debt: Simplify unit tests by using UnstructuredSet & ObjMetadataSet with AssertEqual deep comparison Dec 2, 2021
@k8s-triage-robot
Copy link

The Kubernetes project currently lacks enough contributors to adequately respond to all issues and PRs.

This bot triages issues and PRs according to the following rules:

  • After 90d of inactivity, lifecycle/stale is applied
  • After 30d of inactivity since lifecycle/stale was applied, lifecycle/rotten is applied
  • After 30d of inactivity since lifecycle/rotten was applied, the issue is closed

You can:

  • Mark this issue or PR as fresh with /remove-lifecycle stale
  • Mark this issue or PR as rotten with /lifecycle rotten
  • Close this issue or PR with /close
  • Offer to help out with Issue Triage

Please send feedback to sig-contributor-experience at kubernetes/community.

/lifecycle stale

@k8s-ci-robot k8s-ci-robot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Mar 2, 2022
@karlkfi
Copy link
Contributor Author

karlkfi commented Mar 25, 2022

/remove-lifecycle stale

@k8s-ci-robot k8s-ci-robot removed the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Mar 25, 2022
@k8s-triage-robot
Copy link

The Kubernetes project currently lacks enough contributors to adequately respond to all issues and PRs.

This bot triages issues and PRs according to the following rules:

  • After 90d of inactivity, lifecycle/stale is applied
  • After 30d of inactivity since lifecycle/stale was applied, lifecycle/rotten is applied
  • After 30d of inactivity since lifecycle/rotten was applied, the issue is closed

You can:

  • Mark this issue or PR as fresh with /remove-lifecycle stale
  • Mark this issue or PR as rotten with /lifecycle rotten
  • Close this issue or PR with /close
  • Offer to help out with Issue Triage

Please send feedback to sig-contributor-experience at kubernetes/community.

/lifecycle stale

@k8s-ci-robot k8s-ci-robot added the lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. label Jun 23, 2022
@k8s-triage-robot
Copy link

The Kubernetes project currently lacks enough active contributors to adequately respond to all issues and PRs.

This bot triages issues and PRs according to the following rules:

  • After 90d of inactivity, lifecycle/stale is applied
  • After 30d of inactivity since lifecycle/stale was applied, lifecycle/rotten is applied
  • After 30d of inactivity since lifecycle/rotten was applied, the issue is closed

You can:

  • Mark this issue or PR as fresh with /remove-lifecycle rotten
  • Close this issue or PR with /close
  • Offer to help out with Issue Triage

Please send feedback to sig-contributor-experience at kubernetes/community.

/lifecycle rotten

@k8s-ci-robot k8s-ci-robot added lifecycle/rotten Denotes an issue or PR that has aged beyond stale and will be auto-closed. and removed lifecycle/stale Denotes an issue or PR has remained open with no activity and has become stale. labels Jul 24, 2022
@karlkfi
Copy link
Contributor Author

karlkfi commented Jul 24, 2022

/remove-lifecycle rotten
/lifecycle frozen

@k8s-ci-robot k8s-ci-robot added lifecycle/frozen Indicates that an issue or PR should not be auto-closed due to staleness. and removed lifecycle/rotten Denotes an issue or PR that has aged beyond stale and will be auto-closed. labels Jul 24, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
lifecycle/frozen Indicates that an issue or PR should not be auto-closed due to staleness.
Projects
None yet
Development

No branches or pull requests

4 participants