[TEST] Added ability to test apis that don't return json
The last response body gets now always stashed in the REST tests and can be retrieved via `$body`. This implies that not only expected values can be retrieved from the stashed values, but actual values as well. Added support for regular expressions to `match` assertion, using `Pattern.COMMENTS` flag for better readability through new custom hamcrest matcher (adopted in do section as well). Functionality added through new feature called `regex` that needs to be mentioned in the skip sections whenever needed till all the runners support it. Added also example tests for cat count api
This commit is contained in:
parent
5f8dbeaa8e
commit
88771fdf99
|
@ -164,6 +164,17 @@ testing indexing a document without a specified ID:
|
|||
- match: { _id: $id } # the returned `response._id` matches the stashed `id`
|
||||
....
|
||||
|
||||
The last response obtained gets always stashed automatically as a string, called `body`.
|
||||
This is useful when needing to test apis that return text rather than json (e.g. cat api),
|
||||
as it allows to treat the whole body as an ordinary string field.
|
||||
|
||||
Note that not only expected values can be retrieved from the stashed values (as in the
|
||||
example above), but the same goes for actual values:
|
||||
|
||||
....
|
||||
- match: { $body: /^.+$/ } # the returned `body` matches the provided regex
|
||||
....
|
||||
|
||||
The stash should be reset at the beginning of each test file.
|
||||
|
||||
=== `is_true`
|
||||
|
@ -193,6 +204,15 @@ should be identical, eg:
|
|||
- match: { _source: { foo: bar }}
|
||||
....
|
||||
|
||||
Supports also regular expressions with flag X for more readability (accepts whitespaces and comments):
|
||||
|
||||
....
|
||||
- match:
|
||||
$body: >
|
||||
/^ epoch \s+ timestamp \s+ count \s+ \n
|
||||
\d+ \s+ \d{2}:\d{2}:\d{2} \s+ \d+ \s+ \n $/
|
||||
....
|
||||
|
||||
=== `lt` and `gt`
|
||||
|
||||
Compares two numeric values, eg:
|
||||
|
|
|
@ -0,0 +1,77 @@
|
|||
---
|
||||
setup:
|
||||
- skip:
|
||||
features: regex
|
||||
|
||||
---
|
||||
"Test cat count help":
|
||||
- do:
|
||||
cat.count:
|
||||
help: true
|
||||
|
||||
- match:
|
||||
$body: >
|
||||
/^ epoch .+ \n
|
||||
timestamp .+ \n
|
||||
count .+ \n $/
|
||||
|
||||
---
|
||||
"Test cat count output":
|
||||
|
||||
- do:
|
||||
cat.count: {}
|
||||
|
||||
- match:
|
||||
$body: >
|
||||
/^ \d+ \s \d{2}:\d{2}:\d{2} \s 0 \s $/
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: index1
|
||||
type: type1
|
||||
id: 1
|
||||
body: { foo: bar }
|
||||
refresh: true
|
||||
|
||||
- do:
|
||||
cat.count: {}
|
||||
|
||||
- match:
|
||||
$body: >
|
||||
/^ \d+ \s \d{2}:\d{2}:\d{2} \s 1 \s $/
|
||||
|
||||
- do:
|
||||
index:
|
||||
index: index2
|
||||
type: type2
|
||||
id: 1
|
||||
body: { foo: bar }
|
||||
refresh: true
|
||||
|
||||
- do:
|
||||
cat.count:
|
||||
h: count
|
||||
|
||||
- match:
|
||||
$body: >
|
||||
/^ 2 \s $/
|
||||
|
||||
|
||||
- do:
|
||||
cat.count:
|
||||
index: index1
|
||||
|
||||
- match:
|
||||
$body: >
|
||||
/^ \d+ \s \d{2}:\d{2}:\d{2} \s 1 \s $/
|
||||
|
||||
- do:
|
||||
cat.count:
|
||||
index: index2
|
||||
v: true
|
||||
|
||||
- match:
|
||||
$body: >
|
||||
/^ epoch \s+ timestamp \s+ count \s+ \n
|
||||
\d+ \s+ \d{2}:\d{2}:\d{2} \s+ \d+ \s+ \n $/
|
||||
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* Licensed to Elasticsearch under one or more contributor
|
||||
* license agreements. See the NOTICE file distributed with
|
||||
* this work for additional information regarding copyright
|
||||
* ownership. Elasticsearch licenses this file to you under
|
||||
* the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
package org.elasticsearch.test.hamcrest;
|
||||
|
||||
import org.hamcrest.Description;
|
||||
import org.hamcrest.TypeSafeMatcher;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Matcher that supports regular expression and allows to provide optional flags
|
||||
*/
|
||||
public class RegexMatcher extends TypeSafeMatcher<String> {
|
||||
|
||||
private final String regex;
|
||||
private final Pattern pattern;
|
||||
|
||||
public RegexMatcher(String regex) {
|
||||
this.regex = regex;
|
||||
this.pattern = Pattern.compile(regex);
|
||||
}
|
||||
|
||||
public RegexMatcher(String regex, int flag) {
|
||||
this.regex = regex;
|
||||
this.pattern = Pattern.compile(regex, flag);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean matchesSafely(String item) {
|
||||
return pattern.matcher(item).find();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void describeTo(Description description) {
|
||||
description.appendText(regex);
|
||||
}
|
||||
|
||||
public static RegexMatcher matches(String regex) {
|
||||
return new RegexMatcher(regex);
|
||||
}
|
||||
|
||||
public static RegexMatcher matches(String regex, int flag) {
|
||||
return new RegexMatcher(regex, flag);
|
||||
}
|
||||
}
|
|
@ -70,7 +70,10 @@ public class RestTestExecutionContext implements Closeable {
|
|||
}
|
||||
}
|
||||
try {
|
||||
return response = callApiInternal(apiName, requestParams, body);
|
||||
response = callApiInternal(apiName, requestParams, body);
|
||||
//we always stash the last response body
|
||||
stash("body", response.getBody());
|
||||
return response;
|
||||
} catch(RestException e) {
|
||||
response = e.restResponse();
|
||||
throw e;
|
||||
|
|
|
@ -51,6 +51,9 @@ public abstract class Assertion implements ExecutableSection {
|
|||
}
|
||||
|
||||
protected final Object getActualValue(RestTestExecutionContext executionContext) throws IOException {
|
||||
if (executionContext.isStashed(field)) {
|
||||
return executionContext.unstash(field);
|
||||
}
|
||||
return executionContext.response(field);
|
||||
}
|
||||
|
||||
|
|
|
@ -29,10 +29,9 @@ import org.elasticsearch.test.rest.client.RestResponse;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.elasticsearch.common.collect.Tuple.tuple;
|
||||
import static org.elasticsearch.test.hamcrest.RegexMatcher.matches;
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.fail;
|
||||
|
@ -100,17 +99,15 @@ public class DoSection implements ExecutableSection {
|
|||
fail(formatStatusCodeMessage(e.restResponse(), "2xx"));
|
||||
} else if (catches.containsKey(catchParam)) {
|
||||
assertStatusCode(e.restResponse());
|
||||
} else if (catchParam.startsWith("/") && catchParam.endsWith("/")) {
|
||||
} else if (catchParam.length() > 2 && catchParam.startsWith("/") && catchParam.endsWith("/")) {
|
||||
//the text of the error message matches regular expression
|
||||
assertThat(formatStatusCodeMessage(e.restResponse(), "4xx|5xx"), e.statusCode(), greaterThanOrEqualTo(400));
|
||||
Object error = executionContext.response("error");
|
||||
assertThat("error was expected in the response", error, notNullValue());
|
||||
//remove delimiters from regex
|
||||
String regex = catchParam.substring(1, catchParam.length() - 1);
|
||||
String errorMessage = error.toString();
|
||||
Matcher matcher = Pattern.compile(regex).matcher(errorMessage);
|
||||
assertThat("error message [" + errorMessage + "] was expected to match [" + catchParam + "] but didn't",
|
||||
matcher.find(), equalTo(true));
|
||||
assertThat("the error message was expected to match the provided regex but didn't",
|
||||
error.toString(), matches(regex));
|
||||
} else {
|
||||
throw new UnsupportedOperationException("catch value [" + catchParam + "] not supported");
|
||||
}
|
||||
|
|
|
@ -21,6 +21,9 @@ package org.elasticsearch.test.rest.section;
|
|||
import org.elasticsearch.common.logging.ESLogger;
|
||||
import org.elasticsearch.common.logging.Loggers;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import static org.elasticsearch.test.hamcrest.RegexMatcher.matches;
|
||||
import static org.hamcrest.Matchers.equalTo;
|
||||
import static org.hamcrest.Matchers.notNullValue;
|
||||
import static org.junit.Assert.assertThat;
|
||||
|
@ -41,6 +44,19 @@ public class MatchAssertion extends Assertion {
|
|||
|
||||
@Override
|
||||
protected void doAssert(Object actualValue, Object expectedValue) {
|
||||
|
||||
//if the value is wrapped into / it is a regexp (e.g. /s+d+/)
|
||||
if (expectedValue instanceof String) {
|
||||
String expValue = ((String) expectedValue).trim();
|
||||
if (expValue.length() > 2 && expValue.startsWith("/") && expValue.endsWith("/")) {
|
||||
String regex = expValue.substring(1, expValue.length() - 1);
|
||||
logger.trace("assert that [{}] matches [{}]", actualValue, regex);
|
||||
assertThat("field [" + getField() + "] was expected to match the provided regex but didn't",
|
||||
actualValue.toString(), matches(regex, Pattern.COMMENTS));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
assertThat(errorMessage(), actualValue, notNullValue());
|
||||
logger.trace("assert that [{}] matches [{}]", actualValue, expectedValue);
|
||||
if (!actualValue.getClass().equals(expectedValue.getClass())) {
|
||||
|
@ -50,6 +66,7 @@ public class MatchAssertion extends Assertion {
|
|||
return;
|
||||
}
|
||||
}
|
||||
|
||||
assertThat(errorMessage(), actualValue, equalTo(expectedValue));
|
||||
}
|
||||
|
||||
|
|
|
@ -33,7 +33,7 @@ import java.util.List;
|
|||
*/
|
||||
public final class Features {
|
||||
|
||||
private static final List<String> SUPPORTED = Lists.newArrayList();
|
||||
private static final List<String> SUPPORTED = Lists.newArrayList("regex");
|
||||
|
||||
private Features() {
|
||||
|
||||
|
|
Loading…
Reference in New Issue