-
-
Notifications
You must be signed in to change notification settings - Fork 206
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
Revamped output testing #657
Comments
I put some thought into this and this was the best I could come up with. [
{
"description": "readOnly generates its value as an annotation",
"schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://json-schema.org/tests/content/draft2020-12/readOnly/0",
"readOnly": true
},
"tests": [
{
"description": "readOnly is true",
"data": 1,
"assertions": [
{
"outputUnit": {
"keywordLocation": "/readOnly",
"absoluteKeywordLocation": "https://json-schema.org/tests/content/draft2020-12/readOnly/0#/readOnly",
"instanceLocation": "",
"annotation": true
},
"contains": true,
"expectedLocations": {
"flag": null,
"basic": "/annotations",
"detailed": "/annotations",
"verbose": "/annotations"
}
}
]
}
]
}
] Disregarding nesting, the output unit for is the same regardless of which output format is used. So, we should be able to say which output unit is expected and pair that with where it's expected to be depending on which format is used. The test would pass if the given "outputUnit" is present anywhere in the array pointed at by the "expectedLocation". An output unit would be considered present if all of the keywords in the given output unit are both required and the same value as output unit being compared. A major challenge I see with these tests is that there isn't a way to say an outputUnit must not appear somewhere. We might need to do that for testing a conditional. To address that, I included an "contains" property. If The biggest thing I notice that this can't express is if there are extra output units that are unexpected. |
I wonder if the best thing to do is just to include the full expected output result for the evaluation. Test harnesses would have to write code to compare it with their output in a way that ignore missing properties if they're optional, ignore extra properties, and compare arrays without regard to order. That's some non-trivial code to have to write for a test, which isn't great. But, ultimately, that would probably be the best way to test that output is interoperable enough between implementations to be useful for third-party processing. |
One of the problems that @karenetheridge and I recognized early on was that error messages can't be tested. You need to test that message is present, but you can't test the content because that's not specified. Having a schema was how I addressed this. That issue would exist with what you have unless we can somehow say that {
"keywordLocation": "/readOnly",
"absoluteKeywordLocation": "https://json-schema.org/tests/content/draft2020-12/readOnly/0#/readOnly",
"instanceLocation": "",
"error": "some error message"
} is just as acceptable as {
"keywordLocation": "/readOnly",
"absoluteKeywordLocation": "https://json-schema.org/tests/content/draft2020-12/readOnly/0#/readOnly",
"instanceLocation": "",
"error": "a different error message"
} I do like your general approach, though. |
I didn't think about that one. That's another thing is couldn't express.
I don't thing there's a simple solution here. No matter what we do, it's going to be complex. |
Iterating on @jdesrosiers' idea: [
{
"description": "readOnly generates its value as an annotation",
"schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://json-schema.org/tests/content/draft2020-12/readOnly/0",
"type": "integer",
"readOnly": true
},
"tests": [
{
"description": "readOnly is true",
"data": 1,
"assertions": [
{
"valid": true,
"keywordLocation": "/readOnly",
"absoluteKeywordLocation": "https://json-schema.org/tests/content/draft2020-12/readOnly/0#/readOnly",
"instanceLocation": "",
"annotation": true,
"operation": "contains",
"expectedLocations": {
"flag": null,
"basic": "/annotations",
"detailed": "/annotations",
"verbose": "/annotations"
}
}
]
},
{
"description": "annotation not collected",
"data": "string",
"assertions": [
{
"valid": false,
"keywordLocation": "/type",
"absoluteKeywordLocation": "https://json-schema.org/tests/content/draft2020-12/readOnly/0#/type",
"instanceLocation": ""
"hasError": true,
"operation": "contains",
"expectedLocations": {
"flag": null,
"basic": "/errors",
"detailed": "/errors",
"verbose": "/errors"
}
},
{
"keywordLocation": "/readOnly",
"absoluteKeywordLocation": "https://json-schema.org/tests/content/draft2020-12/readOnly/0#/readOnly",
"instanceLocation": "",
"annotation": true,
"operation": "not-contains",
"expectedLocations": {
"flag": null,
"basic": "/annotations",
"detailed": "/annotations",
"verbose": "/annotations"
}
}
]
}
]
}
] The Instead of We can still put the required values in a nested object, but I advise against calling it Lastly, 2019-09 and 2020-12 don't require that |
An alternate iteration is to just consider So if I also still think that |
I've created a branch (see commit ☝️) in my implementation that does the "alternate iteration" just above. The equality code wasn't hard to write, but I did need to do something custom for it. |
Just toying with this again, and expanding on the "minimal match" (I think I like "subset equality" better), I came up with this: [
{
"description": "readOnly generates its value as an annotation",
"schema": {
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://json-schema.org/tests/content/draft2020-12/readOnly/0",
"readOnly": true
},
"tests": [
{
"description": "readOnly is true",
"data": 1,
"output": {
"basic": {
"/annotations/#": {
"keywordLocation": "/readOnly",
"absoluteKeywordLocation": "https://json-schema.org/tests/content/draft2020-12/readOnly/0#/readOnly",
"instanceLocation": "",
"annotation": true
}
}
}
}
]
}
] In this case, we have a sort of pointer template where So some item in the Honestly, I think what we need is JSON Path, but I understand the issues of introducing another technology, especially one that doesn't have as wide support as JSON Schema. With JSON Path, we could easily write |
Following up on #247 and in light of @jdesrosiers' #652, I think we can do better for output tests.
The current test structure presents a JSON Schema that constrains several locations to specific values.
Example:
JSON-Schema-Test-Suite/output-tests/draft2020-12/content/readOnly.json
Lines 13 to 33 in 19947ea
However, maybe a simpler approach (both to implement and write) would be just to have a series of JSON Pointers and the values that are expected to be in the output at those locations. For example, the above test file could be re-written as:
As long as all of those locations in the output contain those values, it is considered valid.
There is one caveat that the current version of the test also enforces that the the
errors
property is disallowed whenannotations
is present, which is something that the spec requires, but the proposal can't cover that case. I'm open to options here if that's important to us.Edit: I've since realized that the pointers need indices because
annotations
is an array. I'm not sure if we can specify that the first one needs to be a particular value. Items in the array could be in any order. Maybe the tests could be engineered so that it's the only expected item?The text was updated successfully, but these errors were encountered: