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

feat: add new helpers to p/uassert #2547

Open
wants to merge 15 commits into
base: master
Choose a base branch
from

Conversation

kazai777
Copy link
Contributor

@kazai777 kazai777 commented Jul 8, 2024

Add functions based on go testify library to complete the p/uassert package

Contributors' checklist...
  • Added new tests, or not needed, or not feasible
  • Provided an example (e.g. screenshot) to aid review or the PR is self-explanatory
  • Updated the official documentation or not needed
  • No breaking changes were made, or a BREAKING CHANGE: xxx message was included in the description
  • Added references to related issues and PRs
  • Provided any useful hints for running manual tests
  • Added new benchmarks to generated graphs, if any. More info here.

@kazai777 kazai777 requested review from a team as code owners July 8, 2024 16:36
@kazai777 kazai777 requested review from deelawn and thehowl and removed request for a team July 8, 2024 16:36
@github-actions github-actions bot added the 🧾 package/realm Tag used for new Realms or Packages. label Jul 8, 2024
@kazai777 kazai777 changed the title feat: p/demo/uassert feat: p/uassert Jul 10, 2024
@moul moul changed the title feat: p/uassert feat: add new helpers to p/uassert Jul 14, 2024
Copy link
Member

@moul moul left a comment

Choose a reason for hiding this comment

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

you also need to update urequire accordingly.

@kazai777
Copy link
Contributor Author

you also need to update urequire accordingly.

the urequire file has been updated and I've fixed the conflict with the master branch. cc @moul

@kazai777 kazai777 requested a review from moul July 14, 2024 22:13
Copy link

codecov bot commented Jul 14, 2024

Codecov Report

All modified and coverable lines are covered by tests ✅

Project coverage is 55.01%. Comparing base (92e51c2) to head (3a58fa0).
Report is 115 commits behind head on master.

Additional details and impacted files
@@            Coverage Diff             @@
##           master    #2547      +/-   ##
==========================================
- Coverage   55.02%   55.01%   -0.01%     
==========================================
  Files         595      595              
  Lines       79665    79645      -20     
==========================================
- Hits        43837    43820      -17     
+ Misses      32512    32510       -2     
+ Partials     3316     3315       -1     
Flag Coverage Δ
gno.land 64.24% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

@kazai777 kazai777 requested a review from thehowl July 19, 2024 07:29
Copy link
Contributor

@deelawn deelawn left a comment

Choose a reason for hiding this comment

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

I have some concerns about whether we need all of the functionality introduced here. A lot of it is hard or impossible to get right and consistent with the existing testify packages without using reflection. I'm of the opinion that if we offer something like this with a subset of the same testify API, then the behavior that we do define should be identical. If there is behavior that is not identical we should omit the type and return a "unsupported type" error. But I've also been skeptical of using testify as a package -- the conversion of types to interfaces and then using reflection to get the original types always seemed odd to me when I know what the types are before I call the testify function, so why not just do the equality checks in my testing code.

But are are some things packages like this make easier, like handling panics and doing deep equality checks, though this package can't really do deep equality checking without reflection. Let's wait for someone else to offer a review as well.

t.Helper()
switch v1 := e1.(type) {
case int:
v2 := e2.(int)
Copy link
Contributor

Choose a reason for hiding this comment

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

Any of these type assertions can fail if the underlying types of e1 and e2 are not the same. This behavior is not consistent with the behavior of the testify package this is modeled after. Instead, it should fail will an error message that types are incompatible, or something of that equivalence.

return len(v) == 0
case func():
return v == nil
default:
Copy link
Contributor

Choose a reason for hiding this comment

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

The default should specify why it failed -- this is an unsupported type.

return v == nil
case *func():
return v == nil
case []int:
Copy link
Contributor

Choose a reason for hiding this comment

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

Slice values need to be compared to nil, not have their length checked. A nil slice will always have a length of zero, but non-nil slices of length zero can exist.

return len(v) == 0
case []bool:
return len(v) == 0
case map[string]int:
Copy link
Contributor

Choose a reason for hiding this comment

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

Same applies to maps as for slices; it needs to be compared to nil as both nil and non-nil maps can have a length of zero.

}

switch v := object.(type) {
case *int, *int8, *int16, *int32, *int64:
Copy link
Contributor

Choose a reason for hiding this comment

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

Type switch cases with multiple types won't work -- v will continue to be an interface type so it will evaluate to not nil because the underlying nil value is typed. Each of the types must be on its own separate line. Here is an example of this behavior: https://play.gno.land/p/wTCoLeDZiMb

return v == nil
case *map[string]int, *map[string]string, *map[string]bool:
return v == nil
case *func():
Copy link
Contributor

Choose a reason for hiding this comment

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

I'm not sure how useful this one is; an empty function is only of the the infinite types of function signatures. Maybe better to keep functions as unsupported types.

return len(v) == 0
case map[string]bool:
return len(v) == 0
case func():
Copy link
Contributor

Choose a reason for hiding this comment

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

Same comment as above in regards to whether this should support functions types.

}

// ElementsMatch asserts that two lists contain the same elements, regardless of order.
func ElementsMatch(t TestingT, listA, listB []interface{}, msgs ...string) bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

This signature differs from how it works in testify and how most users might expect it to work. I believe that the natural expectation is to pass two slice to this function and have it check if the elements match. The current implementation requires the slices to be transformed into slices of interfaces before this can be used; if that's the case, they might as well just check equality while iterating over the slices instead of building the interface slices.

So if we want a function like Elements match, it should accept interface{} types and then:

  1. Check to make sure that the slice types match
  2. Check to make sure they have the same length
  3. Check to make sure each of their elements are equal

Even then, the implementation is incomplete because it assumes primitive type slices; there would need to be deeper equality checks done to do this correctly.

}

// Subset asserts that all elements in the subset are present in the set.
func Subset(t TestingT, set, subset []interface{}, msgs ...string) bool {
Copy link
Contributor

Choose a reason for hiding this comment

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

Same concerns as ElementsMatch

// Same asserts that two pointers reference the same object.
func Same(t TestingT, expected, actual interface{}, msgs ...string) bool {
t.Helper()
if expected != actual {
Copy link
Contributor

Choose a reason for hiding this comment

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

This won't work as expected until this bug is fixed: #2624

@kazai777
Copy link
Contributor Author

I have some concerns about whether we need all of the functionality introduced here. A lot of it is hard or impossible to get right and consistent with the existing testify packages without using reflection. I'm of the opinion that if we offer something like this with a subset of the same testify API, then the behavior that we do define should be identical. If there is behavior that is not identical we should omit the type and return a "unsupported type" error. But I've also been skeptical of using testify as a package -- the conversion of types to interfaces and then using reflection to get the original types always seemed odd to me when I know what the types are before I call the testify function, so why not just do the equality checks in my testing code.

But are are some things packages like this make easier, like handling panics and doing deep equality checks, though this package can't really do deep equality checking without reflection. Let's wait for someone else to offer a review as well.

Do you think it would make more sense to develop the reflect package for gno first, so that it can be used here? This would guarantee better operation and be closer to the original testify package. @deelawn

@Kouteki Kouteki added review/triage-pending PRs opened by external contributors that are waiting for the 1st review and removed review/triage-pending PRs opened by external contributors that are waiting for the 1st review labels Oct 3, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
🧾 package/realm Tag used for new Realms or Packages.
Projects
Status: In Progress
Status: In Review
Development

Successfully merging this pull request may close these issues.

5 participants