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

Table tests (initial code) #46

Merged
merged 1 commit into from
Sep 24, 2016
Merged

Table tests (initial code) #46

merged 1 commit into from
Sep 24, 2016

Conversation

smyrman
Copy link
Collaborator

@smyrman smyrman commented Sep 16, 2016

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...

@smyrman
Copy link
Collaborator Author

smyrman commented Sep 16, 2016

Tested Go 1.6 code-path and pushed an amended commit to the branch:

$ docker run -v $GOPATH:/go golang:1.6 go test -v github.com/rs/rest-layer/schema/encoding/jsonschema
...
ok      github.com/rs/rest-layer/schema/encoding/jsonschema 0.019s

Copy link
Collaborator Author

@smyrman smyrman left a 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)
Copy link
Collaborator Author

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)
Copy link
Collaborator Author

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
}
Copy link
Collaborator Author

@smyrman smyrman Sep 16, 2016

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

Copy link
Contributor

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?

Copy link
Collaborator Author

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

Copy link
Contributor

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?

Copy link
Collaborator Author

@smyrman smyrman Sep 22, 2016

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....

Copy link
Collaborator Author

@smyrman smyrman Sep 22, 2016

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?

@rs
Copy link
Owner

rs commented Sep 16, 2016

Can you please rebase on master?

@smyrman
Copy link
Collaborator Author

smyrman commented Sep 16, 2016

rebased

// "description". Should it be encoded as "description" here as well?
expect: `{
"type": "object",
"title": "A list of students",
Copy link
Collaborator Author

@smyrman smyrman Sep 16, 2016

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

Copy link
Collaborator Author

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.

Copy link
Contributor

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.

Copy link
Collaborator Author

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 :-)

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

done

@smyrman
Copy link
Collaborator Author

smyrman commented Sep 17, 2016

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) {
Copy link
Collaborator Author

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.

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

done

@yanfali
Copy link
Contributor

yanfali commented Sep 17, 2016

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.

@smyrman
Copy link
Collaborator Author

smyrman commented Sep 19, 2016

Amended to include tests for Default.

@smyrman
Copy link
Collaborator Author

smyrman commented Sep 19, 2016

Sorry I've been tied up at work.

No worries:-)

Copy link
Contributor

@yanfali yanfali left a 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
Copy link
Contributor

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 ./... ?

Copy link
Collaborator Author

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.

Copy link
Contributor

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.

Copy link
Collaborator Author

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) {
Copy link
Contributor

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{}{
Copy link
Contributor

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?

Copy link
Collaborator Author

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).

Copy link
Collaborator Author

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.

Copy link
Collaborator Author

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
}
Copy link
Contributor

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?

@smyrman
Copy link
Collaborator Author

smyrman commented Sep 20, 2016

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.

@smyrman
Copy link
Collaborator Author

smyrman commented Sep 20, 2016

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.

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;-)

@smyrman
Copy link
Collaborator Author

smyrman commented Sep 22, 2016

Latest change include some encoding changes:

  • Renamed "title" -> "description" for consistency on object.
  • Set "additionalProperties".

Test changes:

  • Moved string tests from old test file to string_test.go
  • Reworked float/integer tests to compare only a sub-set of the JSON (The same way string_test.go now does it...).

@rs
Copy link
Owner

rs commented Sep 23, 2016

@smyrman: Are you ready for merging?

@smyrman
Copy link
Collaborator Author

smyrman commented Sep 23, 2016

@rs, yes, I think this PR can be merged.

@rs
Copy link
Owner

rs commented Sep 24, 2016

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.
@smyrman
Copy link
Collaborator Author

smyrman commented Sep 24, 2016

@rs, it's now rebased again.

@rs rs merged commit 5f71d11 into rs:master Sep 24, 2016
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.

None yet

3 participants