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

Json matching function #1690

Closed

Conversation

akaswenwilk
Copy link

Summary

This enables flexible json matching based on matcher functions in addition to json equality checks.

Changes

  • added new JSONMatchedBy func
  • added a jsonmatch package to compare json objects
  • added comparison via functions for values of json objects

Motivation

My colleagues and I from every go based team I've worked with have always had difficulty with json. Oftentimes we want to check aspects of certain parts of JSON objects without having to do a full equality check. For instance, determining that a value is a uuid format, or that a datetime is in the past etc etc. While this can be done in other ways such as unmarshalling an object and checking individual values, giving an overview in the form of a json object can be much more clear.

an exmple from one of the tests:

func TestJSONMatchesBy_DeeplyNestedMatchers(t *testing.T) {
	mockT := new(testing.T)
	True(t, JSONMatchesBy(
		mockT,
		`["$THREE", {"foo": {"bar": {"baz": "$NOT_EMPTY"}}}, {"nested": { "array": ["$NOT_EMPTY", "foo"]}}]`,
		`[3, {"foo": {"bar": {"baz": "qux"}}}, {"nested": { "array": ["quux", "foo"]}}]`,
		ValueMatchers{
			"$THREE":     func(v interface{}) bool { return v == 3.0 },
			"$NOT_EMPTY": func(v interface{}) bool { return v != "" },
		}))
}

The only issue I'd like to still solve in another PR is adjusting the display of the diff to factor in matchers. I think it would be better to solve that problem separately.

Related issues

@@ -3,6 +3,7 @@
package assert

import (
jsonmatch "github.com/stretchr/testify/assert/jsonmatch"
Copy link
Contributor

Choose a reason for hiding this comment

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

Fix the import order please

Copy link
Author

Choose a reason for hiding this comment

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

I think this is what is meant? bdff014

@@ -3,6 +3,7 @@
package assert

import (
jsonmatch "github.com/stretchr/testify/assert/jsonmatch"
Copy link
Contributor

Choose a reason for hiding this comment

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

Fix the imports order please

Copy link
Author

Choose a reason for hiding this comment

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

what do you mean by the order actually? like alphabetically by package name?

Copy link
Author

Choose a reason for hiding this comment

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

also here: bdff014

@@ -1703,7 +1689,6 @@ func NotRegexp(t TestingT, rx interface{}, str interface{}, msgAndArgs ...interf
}

return !match

Copy link
Contributor

Choose a reason for hiding this comment

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

These files might need formating for sure, but I would encourage you to revert all these spaces changes. It mess up the history of the files.

If you want to format them, why not, but then please open a PR about it or use a separate commit in your current PR

Copy link
Author

Choose a reason for hiding this comment

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

makes sense, undid the auto formatting: bdff014

@@ -842,11 +829,9 @@ func TestNil(t *testing.T) {
if Nil(mockT, new(AssertionTesterConformingObject)) {
t.Error("Nil should return false: object is not nil")
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Here also your formatter committed so many changes

Copy link
Author

Choose a reason for hiding this comment

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

oops, i'll adjust this

Copy link
Author

Choose a reason for hiding this comment

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

removed: bdff014

Comment on lines 2690 to 2796
var cases = []struct {
cases := []struct {
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 pretty sure you are using gofumpt as I do 😁

Copy link
Author

Choose a reason for hiding this comment

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

hehe, indeed

Copy link
Author

Choose a reason for hiding this comment

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

also here: bdff014

Comment on lines +64 to +66
case float64:
n.kind = Number
n.value = v
Copy link
Contributor

Choose a reason for hiding this comment

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

What about json.Number?

Copy link
Author

Choose a reason for hiding this comment

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

instead of float64 for instance?

Copy link
Author

Choose a reason for hiding this comment

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

I'm not opposed to it, but what benefit would it provide?

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 sorry if I didn't explain it well.

Of course, the float64 case is needed.

My point was about the fact, and maybe I'm wrong, this function could receive data that was, or will be, decoded with UseNumber

https://pkg.go.dev/encoding/json#Decoder.UseNumber

But maybe I'm wrong and it cannot happen

Copy link
Author

Choose a reason for hiding this comment

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

Comment on lines 6 to 10
assert "github.com/stretchr/testify/assert"
jsonmatch "github.com/stretchr/testify/assert/jsonmatch"
http "net/http"
url "net/url"
time "time"
Copy link
Contributor

Choose a reason for hiding this comment

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

Please fix these imports please

Yes existing ones are already messed up

Copy link
Author

Choose a reason for hiding this comment

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

adjusted: bdff014

Comment on lines 6 to 10
assert "github.com/stretchr/testify/assert"
jsonmatch "github.com/stretchr/testify/assert/jsonmatch"
http "net/http"
url "net/url"
time "time"
Copy link
Contributor

Choose a reason for hiding this comment

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

Same here

Copy link
Author

Choose a reason for hiding this comment

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

@akaswenwilk akaswenwilk force-pushed the json-matching-function branch from f199b16 to 80861e6 Compare December 30, 2024 13:58
Comment on lines 5 to 10
import (
http "net/http"
jsonmatch "github.com/stretchr/testify/assert/jsonmatch"
url "net/url"
time "time"
)
Copy link
Contributor

Choose a reason for hiding this comment

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

The canonical way is this

Suggested change
import (
http "net/http"
jsonmatch "github.com/stretchr/testify/assert/jsonmatch"
url "net/url"
time "time"
)
import (
http "net/http"
url "net/url"
time "time"
jsonmatch "github.com/stretchr/testify/assert/jsonmatch"
)

Copy link
Author

Choose a reason for hiding this comment

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

ah, i see. fixed then!

Copy link
Author

Choose a reason for hiding this comment

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

looks like go generate doesn't let me fix the import order: https://github.com/stretchr/testify/actions/runs/12549993792/job/34992001258?pr=1690

Copy link
Contributor

Choose a reason for hiding this comment

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

Oh indeed then

The files are generated. I assume there is something to improve in the script that generate them. But then it's out of the scope of this PR.

Thank you for trying, and I'm sorry if you had to undo

Copy link
Author

Choose a reason for hiding this comment

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

no prob, thanks for the review!

@akaswenwilk
Copy link
Author

thanks @ccoVeille for your review and suggested changes! If you have a chance to look over it as well, I'd be grateful to be able to merge it to the main package @boyan-soubachov @dolmen @MovieStoreGuy @arjunmahishi or @brackendawson and also for an idea when/how we might be able to release it. thanks for the help!

@dolmen dolmen added enhancement pkg-mock Any issues related to Mock mock.ArgumentMatcher About matching arguments in mock labels Jan 7, 2025
@dolmen
Copy link
Collaborator

dolmen commented Jan 7, 2025

This seems to be an interesting feature, but at this time we do not want to increase the API surface of this framework which is already too huge for the limited maintainers resources.

@dolmen dolmen closed this Jan 7, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement mock.ArgumentMatcher About matching arguments in mock pkg-mock Any issues related to Mock
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants