This page is meant to help a new user get familiarized with using the Rest.li Test Suite Specification. It explains how to run the example Java TestNG tests, and how to expand the Test Suite Specification.
For an overview of the test suite, refer to the test suite overview.
The Rest.li Test Suite Specification is language-independent, and it provides test data and guidelines to follow when
testing a Rest.li client.
To validate that the spec’s tests all pass using the Rest.li Java client binding, and to demonstrate how
to use the Test Suite Specification, this project contains a Java TestNG test suite,
located in the client-testsuite/src/test/java
folder.
The Java TestNG test suite follows the Rest.li Test Suite Specification, and it has two types of tests: data driven automated tests and manual assertion tests.
These tests are located in the TestRestClientAgainstStandardTestSuite
class, and the tests run are specified by manifest.json
.
For an example, consider the Java schema tests in the Java suite. Our testSchema() method verifies that Rest.li correctly
generates a data template from a schema, and manifest.json
specifies a list of schema-data pairs. These pairs are passed
to testSchema() using a TestNG data provider, so all the schema cases specified by manifest.json
are tested in the Java suite.
These tests are located in the TestRestClientWithManualAssertions
class.
Manual assertions are used to verify that Rest.li responses are decoded properly from http responses. Each test verifies
the content of the Rest.li response fields. These assertions are built by hand, but they should be similar across test suite languages.
To run all tests in the provided TestNG suite:
gradle test
This command should run successfully, since the Java implementation of the Rest.li client should pass all the tests.
Because the build is successful, it’s not immediately clear what is happening when gradle test
is run.
For better illustration, this guide will help you make tests that fail when run:
Try adding an untrue assertion to testSchema() in TestRestClientAgainstStandardTestSuite.java
.
Running gradle test
again will result in multiple tests failing, because testSchema() is used for all the schema
tests defined in manifest.json
.
Try adding an untrue manual assertion to TestRestClientWithManualAssertions.java
. For example, the following assertion
is untrue because the response should have 1 as its id:
@Test
public void testCollectionCreateAgain() throws Exception
{
Response<EmptyRecord> response = loadResponse("collection-create", "responses/collection-create.res");
Assert.assertEquals(response.getId(), "2");
}
Run gradle test
again, and this test should fail, while the other tests pass.
This section explains how to add a new language-independent test to the Rest.li Test Suite Specification. Please do not modify existing tests: multiple language implementations are using these test and changing existing tests may break their test suites.
Keep tests simple! They should test a single case and test it well.
To add a new JSON corner case, e.g. corner-case.json
:
client-testsuite/src/data/
, add corner-case.json
.manifest.json
, and add a list entry of the form {“data”: “data/[filename].json”}."jsonTestData": [
...
{ "data": "data/corner-case.json" }
...
],
To test a new schema, NewSchema.pdsc
:
client-testsuite/src/schemas/testsuite/
, add a new .pdsc file, NewSchema.pdsc
, with fields and
field types supported by Rest.li. Set “namespace” to “testsuite”. Rest.li client should generate a data template from
this .pdsc file.client-testsuite/src/data/
, add a corresponding .json file, new-schema.json
, with test data to fill your new data template’s fields.manifest.json
, find the schemaTestData list. Add an entry for your new schema, following the general format:
{“schema”: “testsuite.[SchemaName]”, “data”: “data/[json-name].json”}"schemaTestData": [
...
{"schema": "testsuite.NewSchema", "data": "data/new-schema.json"}
...
],
gradle build
before running the test, so Rest.li will generate the data binding.When adding a new wire protocol test, you also need to add its associated flat .req
and .res
files.
The Java suite contains a convenience tool to generate .restspec.json
, .req
, and .res
files for the
Rest.li Test Suite Specification. To use it:
*Resource.java
classes in the restli-testsuite-server
project under src/main/java/testsuite.
You can override a new method in an existing resource, or add a completely new resource class. For example, the following class is a simple collection resource that only overrides create() using the option to return the created entity.@RestLiCollection(name = "collectionReturnEntity", namespace = "testsuite")
public class CollectionReturnEntityResource extends CollectionResourceTemplate<Long, Message>
{
@ReturnEntity
@Override
public CreateKVResponse create(Message entity) {
if(entity.getMessage().equals("test message"))
{
return new CreateKVResponse<Long, Message>(1l, entity, HttpStatus.S_201_CREATED);
}
else if(entity.getMessage().equals("another message"))
{
return new CreateKVResponse<Long, Message>(3l, entity, HttpStatus.S_201_CREATED);
}
else
{
return new CreateKVResponse<Long, Message>(null, entity, HttpStatus.S_404_NOT_FOUND);
}
}
}
Re-generate the .restspec.json
and .snapshot.json
files:
gradle publishRestIdl
gradle publishRestSnapshot
Run the test server using:
gradle JettyRunWar
This will use the new restspecs to generate or update the appropriate request builders, which are used to make the requests in the following step.
Update RequestResponseTestCases.java
in the language-specific suites of client-testsuite
by adding a new
request and test name to the map of Rest.li requests to be tested.
For the java implementation, this is done by modifying the builtRequests map in the buildRequests() function,
in client-testsuite/src/test/java/com/linkedin/pegasus/testsuite/RequestResponseTestCases.java
.
builtRequests.put("collectionReturnEntity-create", new CollectionReturnEntityRequestBuilders(_options).create().input(testMessage).build());
Re-generate the request and response files. Files will be written to requests/
and responses/
, and to requests-v2/
and responses-v2/
:
gradle generateRequestAndResponseFiles
Note that Java’s requestBuilders are generating the request files with the desired output. These flat files can be used to test the other implementations for well-formed requests.
Update the “wireProtocolTestData” entry of manifest.json
to include test data references to all the files you’ve added.
If overriding a new method for an existing resource:
RequestResponseTestCases.java
in Step 4. The new operation test should look something like this, where test name is usually the resource and method, and “status” is the expected response status:{
"name": "collection-get",
"method": "get",
"request": "requests/collection-get.req",
"response": "responses/collection-get.res",
"status": 200
},
If adding a new resource: - Create a new entry for your resource in wireProtocolTestData list. This should follow the general format:
"wireProtocolTestData": [
{
"name": "collectionReturnEntity",
"restspec": "restspecs/testsuite.collectionReturnEntity.restspec.json",
"snapshot": "snapshots/testsuite.collectionReturnEntity.snapshot.json",
"operations": [
{
"name":"collectionReturnEntity-create",
"method": "create",
"request": "requests/collectionReturnEntity-create.req",
"response": "responses/collectionReturnEntity-create.res",
"status": 201
}
]
},
...
]
- For the list of operation tests, follow the instructions for overriding a new method for an existing resource.