-
Notifications
You must be signed in to change notification settings - Fork 113
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
Table tests (initial code) #46
Conversation
837ce35
to
f9214a3
Compare
Tested Go 1.6 code-path and pushed an amended commit to the branch:
|
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.
Some changes done to non-tests.
assert.Equal(t, 3.1, s) | ||
s, err = Float{Boundaries: &Boundaries{Min: 2, Max: math.NaN()}}.Validate(3.1) | ||
assert.NoError(t, err) | ||
assert.Equal(t, 3.1, s) |
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.
Not sure if support for NaN and Inf values was intended to work, but since it does work, I added some tests for it.
assert.Equal(t, 3, s) | ||
s, err = Integer{Boundaries: &Boundaries{Min: 2, Max: math.NaN()}}.Validate(3) | ||
assert.NoError(t, err) | ||
assert.Equal(t, 3, s) |
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.
Same here. Not sure if support for NaN and Inf values was intended to work, but since it does work, I added some tests for it.
ew.writeFormat(`, "maximum": %s`, strconv.FormatFloat(b.Max, 'E', -1, 64)) | ||
} | ||
return ew.err | ||
} |
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 added this method to use the same code-path for encoding both integer and float boundaries. I also added support for NaN and Inf values so that:
- Max=NaN is treated as no limit.
- Max=+Inf is treated as no limit.
- Min=NaN is treated as no limit.
- Min=-Inf is treated as no limit.
Might be useful in some cases to only set one limit... I checked that this worked with the existing schema package logic by first inspecting the code, and then by adding some tests.
Hint: The following is always true for NaN, where f is any float64 value:
(f < NaN) == false
(f > NaN) == false
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.
hmm, isn't NaN an error?
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.
NaN means Not a Number
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.
Yes but why accept it? I mean, nan is triggered by strings, so is it a good idea to silently accept it?
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 mean, nan is triggered by strings
What do you mean it's triggered by strings? Where, and how? E.g strconv.ParseFloat()
would return an error and a zero value, not NaN: https://play.golang.org/p/Xx50p-LgL7
so is it a good idea to silently accept it?
I don't think there are too many ways people can set NaN by mistake. They may get an NaN
if they do math.Acos(1.1)
etc., but that doesn't really sound like a common pattern for setting float limits? I would assume the most reasonable way people could set a NaN value, would be if they did so deliberately via math.NaN()
...
Yes but why accept it?
Currently I made the JSON Schema accept it simply because the schema
package already accepts it (silently), and we should handle the value 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.
PS! This doesn't mean it can't be changed, if there is a compelling reason to change how NaN is handled by the schema
package, but I suggest that's handled in another PR, and only if needed?
Can you please rebase on master? |
f9214a3
to
5da5f04
Compare
rebased |
// "description". Should it be encoded as "description" here as well? | ||
expect: `{ | ||
"type": "object", | ||
"title": "A list of students", |
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 am wondering if we should switch this to "description". @yanfali, do you have an opinion? Is it any reason in particular that you chose to encode the schema description as "title" for "object", while it's encoded as "description" for other types?
JSON Schema defines both "title" and "description", where title is supposed to be shorter, and description is supposed to be longer. http://json-schema.org/latest/json-schema-validation.html#anchor98
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 think the best thing to do would be to switch to "description", and if we need "title" in the future, add a Title property to schema.Field.
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 don't feel strongly about this. In fact the first time I submitted this, I totally forgot I used title.
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.
In which case I suggest we change it to description for consistency :-)
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.
done
5da5f04
to
2b248bb
Compare
Added float tests, added one more "all" (package level) test, and removed redundant tests from old test file. |
assert.JSONEq(t, expect, b.String()) | ||
} | ||
|
||
func TestDefaultEncodingWithStringFieldAndIntegerDefault(t *testing.T) { |
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.
OK, haven't added any tests for default, so this was removed by mistake. Will add some tests to replace it.
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.
done
Sorry I've been tied up at work. I will review it this evening PST and let you know my thoughts. Thanks for doing this. |
2b248bb
to
46a9041
Compare
Amended to include tests for Default. |
No worries:-) |
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.
OK, initial review done. A few comments, that's a lot of work thanks. Only major concern is package name. I made a similar choice when I created the jsonschema package, so make sure it runs from the top most level too. Putting it in subpath test/ would probably work just as well.
@@ -0,0 +1,11 @@ | |||
// +build !go1.7 | |||
|
|||
package jsonschema_test |
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.
interesting, why does this have a separate package? I'm not familiar with this pattern. Doesn't this mean you can't inspect package variables? Is that the intention? what happens when you run this from the top most level via ./... ?
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.
@yanfali, This is the Go way to test the public interface of your package. It makes you having to import the package you are testing, and only give access to the public interface. Presumably you could have done the same for the tests you put in the encoding package.
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.
Excellent, thanks for explaining. The encoding test was testing imports rather than public interface so the intention was different. I was ignorant of this pattern.
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 was hoping to link to a blog post or some docs explaining the "_test" suffix, but I couldn't find it just now. However, it's a very common pattern, and you can also see it's commonly used in the Go standard library. E.g. https://golang.org/src/strings/reader_test.go
} | ||
|
||
// test performs the actual test and is used by both implementations of run. | ||
func (tc *encoderTestCase) test(t *testing.T) { |
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.
neat
schema: schema.Schema{ | ||
Fields: schema.Fields{ | ||
"name": schema.Field{ | ||
Default: map[string]interface{}{ |
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.
ok, this is an odd use case, is this the same as allowed?
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.
Yeah, just documenting the current behaviour. I adde a comment some way up (above the test where I use an int).
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 will change it to be less odd to avoid confusion, probably by setting the default one level out.
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.
done
ew.writeFormat(`, "maximum": %s`, strconv.FormatFloat(b.Max, 'E', -1, 64)) | ||
} | ||
return ew.err | ||
} |
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.
hmm, isn't NaN an error?
In many programs it probably is, but for Go it's a IEEE 754 “not-a-number” value. I found it "fitting" as a way of describing "no limit", although it's not strictly needed in our case as we could rely on +/-Inf as the only "supported" values. However, without any added special-casing, both NaN and Inf numbers would result in invalid JSON if specified by the user. |
As mentioned, adding a "_test" suffix to the package name for any test that do not require access to private types, functions or variables, is the Go way. Also, it's the Go way to keep all package tests in the same folder/package so that e.g. "go test -cover IMPORT_PATH" never lies;-) |
46a9041
to
032fae6
Compare
Latest change include some encoding changes:
Test changes:
|
@smyrman: Are you ready for merging? |
@rs, yes, I think this PR can be merged. |
Could you please rebase on master? |
Adds some initial table tests, and remove corresponding tests from the previous test implementation. Also updates the boundary handling encoding wise to handle NaN and Inf values gracefully. In the schema package, the integer and float FieldValidators should already handle this values with existing code. Added tests to make sure it continues to do so.
032fae6
to
3d57393
Compare
@rs, it's now rebased again. |
Pushing for an initial review to check that I am moving in the right direction. Note that this PR is based on #45, so we should probably either merge that first, or abandon it and review everything here. @rs, up to you.
I was aiming to move in a similar direction as the schema package by having one test file per Validator type. Even there is no file per validator for the encoding part yet (maybe there will be in the future to prevent validatorToJSONSchema from growing to large?), it made it easier to see what I have implemented tests for, and to splitt concerns...