Docs: Allow skipping response assertions (#34240)

We generate tests from our documentation, including assertions about the
responses returned by a particular API. But sometimes we *can't* assert
that the response is correct because of some defficiency in our tooling.
Previously we marked the response `// NOTCONSOLE` to skip it, but this
is kind of odd because `// NOTCONSOLE` is really to mark snippets that
are json but aren't requests or responses. This introduces a new
construct to skip response assertions:
```
// TESTRESPONSE[skip:reason we skipped this]
```
This commit is contained in:
Nik Everett 2018-10-04 08:03:38 -04:00 committed by GitHub
parent 3ccb7af56a
commit dc2cf28fde
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 32 additions and 16 deletions

View File

@ -226,10 +226,10 @@ public class RestTestsFromSnippetsTask extends SnippetsTask {
} else { } else {
current.println('---') current.println('---')
current.println("\"line_$test.start\":") current.println("\"line_$test.start\":")
/* The Elasticsearch test runner doesn't support the warnings /* The Elasticsearch test runner doesn't support quite a few
* construct unless you output this skip. Since we don't know * constructs unless we output this skip. We don't know if
* if this snippet will use the warnings construct we emit this * we're going to use these constructs, but we might so we
* warning every time. */ * output the skip just in case. */
current.println(" - skip:") current.println(" - skip:")
current.println(" features: ") current.println(" features: ")
current.println(" - default_shards") current.println(" - default_shards")
@ -250,13 +250,13 @@ public class RestTestsFromSnippetsTask extends SnippetsTask {
} }
} }
} }
if (test.skipTest) { if (test.skip) {
if (test.continued) { if (test.continued) {
throw new InvalidUserDataException("Continued snippets " throw new InvalidUserDataException("Continued snippets "
+ "can't be skipped") + "can't be skipped")
} }
current.println(" - always_skip") current.println(" - always_skip")
current.println(" reason: $test.skipTest") current.println(" reason: $test.skip")
} }
if (test.setup != null) { if (test.setup != null) {
// Insert a setup defined outside of the docs // Insert a setup defined outside of the docs
@ -274,10 +274,12 @@ public class RestTestsFromSnippetsTask extends SnippetsTask {
} }
private void response(Snippet response) { private void response(Snippet response) {
if (null == response.skip) {
current.println(" - match: ") current.println(" - match: ")
current.println(" \$body: ") current.println(" \$body: ")
response.contents.eachLine { current.println(" $it") } response.contents.eachLine { current.println(" $it") }
} }
}
void emitDo(String method, String pathAndQuery, String body, void emitDo(String method, String pathAndQuery, String body,
String catchPart, List warnings, boolean inSetup) { String catchPart, List warnings, boolean inSetup) {

View File

@ -122,7 +122,9 @@ public class SnippetsTask extends DefaultTask {
+ "contain `curl`.") + "contain `curl`.")
} }
} }
if (snippet.testResponse && snippet.language == 'js') { if (snippet.testResponse
&& 'js' == snippet.language
&& null == snippet.skip) {
String quoted = snippet.contents String quoted = snippet.contents
// quote values starting with $ // quote values starting with $
.replaceAll(/([:,])\s*(\$[^ ,\n}]+)/, '$1 "$2"') .replaceAll(/([:,])\s*(\$[^ ,\n}]+)/, '$1 "$2"')
@ -216,7 +218,7 @@ public class SnippetsTask extends DefaultTask {
return return
} }
if (it.group(4) != null) { if (it.group(4) != null) {
snippet.skipTest = it.group(4) snippet.skip = it.group(4)
return return
} }
if (it.group(5) != null) { if (it.group(5) != null) {
@ -249,7 +251,7 @@ public class SnippetsTask extends DefaultTask {
substitutions = [] substitutions = []
} }
String loc = "$file:$lineNumber" String loc = "$file:$lineNumber"
parse(loc, matcher.group(2), /(?:$SUBSTITUTION|$CAT) ?/) { parse(loc, matcher.group(2), /(?:$SUBSTITUTION|$CAT|$SKIP) ?/) {
if (it.group(1) != null) { if (it.group(1) != null) {
// TESTRESPONSE[s/adsf/jkl/] // TESTRESPONSE[s/adsf/jkl/]
substitutions.add([it.group(1), it.group(2)]) substitutions.add([it.group(1), it.group(2)])
@ -259,6 +261,9 @@ public class SnippetsTask extends DefaultTask {
substitutions.add(['\n$', '\\\\s*/']) substitutions.add(['\n$', '\\\\s*/'])
substitutions.add(['( +)', '$1\\\\s+']) substitutions.add(['( +)', '$1\\\\s+'])
substitutions.add(['\n', '\\\\s*\n ']) substitutions.add(['\n', '\\\\s*\n '])
} else if (it.group(4) != null) {
// TESTRESPONSE[skip:reason]
snippet.skip = it.group(4)
} }
} }
} }
@ -312,7 +317,7 @@ public class SnippetsTask extends DefaultTask {
boolean test = false boolean test = false
boolean testResponse = false boolean testResponse = false
boolean testSetup = false boolean testSetup = false
String skipTest = null String skip = null
boolean continued = false boolean continued = false
String language = null String language = null
String catchPart = null String catchPart = null
@ -337,8 +342,8 @@ public class SnippetsTask extends DefaultTask {
if (catchPart) { if (catchPart) {
result += "[catch: $catchPart]" result += "[catch: $catchPart]"
} }
if (skipTest) { if (skip) {
result += "[skip=$skipTest]" result += "[skip=$skip]"
} }
if (continued) { if (continued) {
result += '[continued]' result += '[continued]'
@ -352,6 +357,9 @@ public class SnippetsTask extends DefaultTask {
} }
if (testResponse) { if (testResponse) {
result += '// TESTRESPONSE' result += '// TESTRESPONSE'
if (skip) {
result += "[skip=$skip]"
}
} }
if (testSetup) { if (testSetup) {
result += '// TESTSETUP' result += '// TESTSETUP'

View File

@ -63,6 +63,8 @@ for its modifiers:
* `// TESTRESPONSE[_cat]`: Add substitutions for testing `_cat` responses. Use * `// TESTRESPONSE[_cat]`: Add substitutions for testing `_cat` responses. Use
this after all other substitutions so it doesn't make other substitutions this after all other substitutions so it doesn't make other substitutions
difficult. difficult.
* `// TESTRESPONSE[skip:reason]`: Skip the assertions specified by this
response.
* `// TESTSETUP`: Marks this snippet as the "setup" for all other snippets in * `// TESTSETUP`: Marks this snippet as the "setup" for all other snippets in
this file. This is a somewhat natural way of structuring documentation. You this file. This is a somewhat natural way of structuring documentation. You
say "this is the data we use to explain this feature" then you add the say "this is the data we use to explain this feature" then you add the
@ -73,6 +75,10 @@ for its modifiers:
right in the documentation file. In general, we should prefer `// TESTSETUP` right in the documentation file. In general, we should prefer `// TESTSETUP`
over `// TEST[setup:name]` because it makes it more clear what steps have to over `// TEST[setup:name]` because it makes it more clear what steps have to
be taken before the examples will work. be taken before the examples will work.
* `// NOTCONSOLE`: Marks this snippet as neither `// CONSOLE` nor
`// TESTRESPONSE`, excluding it from the list of unconverted snippets. We
should only use this for snippets that *are* JSON but are *not* responses or
requests.
In addition to the standard CONSOLE syntax these snippets can contain blocks In addition to the standard CONSOLE syntax these snippets can contain blocks
of yaml surrounded by markers like this: of yaml surrounded by markers like this:

View File

@ -89,7 +89,7 @@ Response:
} }
} }
-------------------------------------------------- --------------------------------------------------
// NOTCONSOLE // TESTRESPONSE[skip:historically skipped]
The results show that "h5n1" is one of several terms strongly associated with bird flu. The results show that "h5n1" is one of several terms strongly associated with bird flu.
It only occurs 5 times in our index as a whole (see the `bg_count`) and yet 4 of these It only occurs 5 times in our index as a whole (see the `bg_count`) and yet 4 of these