http-test-runner
v8.5.0
Published
Runs hapi-lab tests that are defined using a simple test specification format.
Downloads
684
Readme
http-test-runner
This project contains code that makes it possible to run hapi-lab tests based on an array of test specifications. Each test specification contains information about what request should be made to the server and what the response should be.
Usage example (written in Typescript)
import TestRunner = require("http-test-runner");
import Lab = require("lab");
const lab = exports.lab = Lab.script();
const config: TestRunner.Configuration = {
lab: lab,
getServerUrl: () => "http://localhost:8080",
tests: [
{
id: "test1",
requests: [
{
path: "/user/user1"
}
]
},
{
id: "test2",
requests: [
{
path: "/user",
method: "post",
payload: {
username: "Test User 2",
email: "[email protected]"
}
}
]
}
],
expectedResponses: {
test1: [
{
payload: {
username: "Test User 1",
email: "[email protected]"
}
}
],
test2: [
{
statusCode: 401,
payload: {
message: "Unauthorized"
}
}
]
},
testReportFilePath: "./test-report.json",
responsesFilePath: "./responses.json"
};
lab.experiment("TestRunner example", () => {
lab.before((done) => {
// Start the service that should be tested on port 8080
});
// Runs the tests as specified by the configuration
TestRunner.performTests(config);
});
API
Configuration
These types define the configuration used when running tests:
export interface Headers {
[name: string]: string;
}
export interface Response {
payload?: any;
headers?: Headers;
/** Defaults to 200. */
statusCode?: number;
}
export interface Request {
path: string;
/** Defaults to GET. */
method?: string;
payload?: any;
/** Query parameters as an object */
query?: any;
headers?: Headers;
/** The response object paths specified here are ignored when validating the response, e.g. ["message", "data.timestamp"] */
ignoredResponsePaths?: string[];
/** Only the type ("string", "number", etc) is validated for the response object paths specified here. */
relaxedResponsePaths?: string[];
/** Only the type ("string", "number", etc) is validated for the response keys specified here. */
relaxedResponseKeys?: string[];
}
export type RequestModifier = (previousResponses: Response[], nextRequest: Request) => Request; // Returns a Modified version of the next request based on the response from current request.
export type ValidateResponseFunc = (responses: Response[], expectedResponses: Response[], test: Test) => void; // Should throw exception if validation fails;
export interface Test {
/** Unique id used to lookup expected response. */
id: string;
label?: string;
requests: Request[];
requestModifier?: RequestModifier;
/** If present, run before test */
before?: Function;
/** If presetn, run after test */
after?: Function;
/** If present the response is only checked using this function. */
validateResponseFunc?: ValidateResponseFunc;
/** If specified, numeric values are compared using delta comparison.
* The delta value is the maximum difference between actual and expected result that will be accepted. */
delta?: number;
/** Tests marked by serial will be run in serial before the rest of the tests are run */
serial?: boolean;
}
export interface Defaults {
request?: {
path?: string;
method?: string;
headers?: Headers;
ignoredResponsePaths?: string[];
relaxedResponsePaths?: string[];
relaxedResponseKeys?: string[];
};
response?: Response;
requestModifier?: RequestModifier;
validateResponseFunc?: ValidateResponseFunc;
delta?: number;
}
export type GetServerUrlFunc = () => string;
/**
* Maps Test.id to array of Response objects.
* Each item in the response array is the response for the corresponing request item for the test with that id.
* */
export type ExpectedResponses = { [id: string]: Response[]; };
export interface Encoding {
mimeType: string;
encode: Function;
decode: Function;
}
export interface TestReportItem {
id: string;
label?: string;
requests: Request[];
responses: Response[];
success: boolean;
expectedResponses?: Response[];
requestModifier?: string;
validateResponseFunc?: string;
}
export interface Configuration {
tests: Test[];
expectedResponses: ExpectedResponses;
/** hapi-lab instance. */
lab: any;
/** A function returning the url to the server that will be tested. */
getServerUrl: GetServerUrlFunc;
/** Default values for various configuration settings */
defaults?: Defaults;
/** If present a responses JSON file is generated containing a map of the actual responses keyed on the tests id. */
responsesFilePath?: string;
/** If present only the specified response headers are included in the responses, e.g. ["x-request-id, "content-language] */
activeResponseHeaders?: string[];
/** If present a test report JSON file is generated showing the request, response and expectedResponse if the test fails. The format is TestReportItem[] */
testReportFilePath?: string;
/** Prefix added to each request path. */
requestPathPrefix?: string;
/** Allows for different encodings to be used based on Accept and Content-Type headers. Default is JSON. */
encodings?: Encoding[];
/** Array of test id values. If present, only these tests will be performed. */
activeTests?: string[];
/** Array of test id values. If present, these tests will be skipped. */
skipTests?: string[];
/** Logs information useful for debugging. Defaults to off */
debugLogging?: boolean;
/** If set, the tests will be run in parallel with at most parlellCount tests running simultaneously */
parallelCount?: number;
};
Running the tests
import TestRunner = require("http-test-runner");
import Lab = require("lab");
const lab = exports.lab = Lab.script();
const config: Configutaion = {/*...*/}
lab.experiment("Running http-test-runner tests", () => {
// Runs the tests as specified by the configuration
TestRunner.performTests(config);
});