Writing a Megaload test
There are two basic concepts in Megaload that define a load profile: the test and phase. A test can be described as a container of phases, and it is the root element which includes all other elements of the load test specification.
Each test contains a sequence of phases that will be executed in that sequence order. A phase is a description of the load profile defined in terms of rate and number of concurrent scenarios (or users simulated by the test). A phase will have a duration and arrival rate, which determines how fast new scenarios are started. Once the maximum number of concurrent scenarios has been reached, it will keep stable while trying to reach the expected rate.
Each phase may contain several scenarios, which will be executed in parallel during the load test. A scenario contains a sequence of actions which represent requests to the SUT or additional behaviour.
The rest of this chapter explains how to write a very simple test specification using these concepts. The spec section describes in detail all the elements of a test specification.
The following example shows you how to write a test for a small online shop that uses HTTP and JSON. The test uses the calls to list customers and to get a customer's details.
The following call lists the customers:
GET http://<IP>:5050/customers
Response:
{"data" : [
{"id" : "goku",
"email" : "goku@dragon.ball",
"account_balance" : 500,
"currency" : "GBP"
},
{...},
{...}
],
"count" : 4
}
The following call gets the details for a specific customer:
GET http://<IP>:5050/customer/bulma
Response:
{"id" : "bulma",
"email" : "bulma@dragon.ball",
"account_balance" : 750000,
"currency" : "GBP"
}
You can write the test specification in any text editor, or using the embedded editor on the Megaload dashboard. To use the embedded editor, go to the dashboard, click Load Test and then Edit test cases.
Step 1: Define a plugin
The plugin is the target server or system under test (SUT). A plugin looks as follows:
{
"plugin" :
{
"id" : <ID>,
"plugin_info" : <SPECIFIC_PLUGIN_INFO>
}
}
id
specifies a name for the plugin.plugin_info
contains the plugin details.
For Example:
{
"plugin" :
{
"id" : "SUT-server",
"plugin_info" : {"http-plugin" :
{"servers" :
[
{ "host" : "127.0.0.1",
"port" : 80,
"ssl" : false }
],
"stats_per_url" : true
}
}
}
}
Step 2: Define a scenario
Our example has a simple scenario with a single request. A scenario looks as follows:
{
"scenario" :
{
"id" : <ID>,
"keepalive" : <REUSE_CONNECTION>,
"actions" : <ACTIONS>
}
}
id
is he name you give the scenario.keepalive
specifies whether to repeate the scenario and reuse open connections.actions
will contain the actions that should be executed - in this example an HTTP request.
An HTTP request looks as follows:
{
"http-request" :
{
"plugin_id" : <PLUGIN_ID>,
"method" : <HTTP_REQUEST_METHOD>,
"path" : <HTTP_REQUEST_URI>
}
}
For our example test:
{
"http-request" :
{
"plugin_id" : "SUT-server",
"method" : "GET",
"path" : "/customers"
}
}
The complete scenario:
{
"scenario" :
{
"id" : "get-customers",
"keepalive" : true,
"actions" : [{"http-request" :
{
"plugin_id": "SUT-server",
"method": "GET",
path": "/customers"
}
}],
}
}
Step 3: Define a phase
A phase includes a load profile that specifies a ramp-up time (so that the system is not immediately overloaded) and the maximum rate and number of processes. It also specifies which scenarios to execute.
{
"phase" :
{
"id" : <ID>,
"arrival_rate" : <RAMP_UP_ARRIVAL_RATE>,
"duration" : <TEST_DURATION>,
"concurrent_scenarios" : <MAX_CONCURRENT_SCENARIOS>,
"rate" : <RATE>,
"scenarios" : <SCENARIOS>
}
}
id
is the name you give the phase.arrival_rate
specifies an arrival rate in number of scenarios started per second.duration
specifies the duration of the phase in milliseconds.concurrent_scenarios
specifies the maximum number of concurrent scenarios.rate
specifies the maximum number of requests per second.scenarios
is used for specifying which scenarios to run and the frequency to choose them. In this example, we will run the scenario from the previous step.
The complete phase for this example:
{
"phase" :
{
"id" : "SUT-low",
"arrival_rate" : 10,
"duration" : 60000,
"concurrent_scenarios" : 100,
"rate" : 250,
"scenarios" : [{"get-customers" : 1}]
}
}
Step 4: Define a test
A test is a container of phases. It looks as follows:
{
"test" :
{
"id" : <ID>,
"phases" : <PHASES>,
"plugins" : <PLUGINS>
}
}
id
is the name you give the test.phases
will specify which phases to run. In this example, we will run the phase from the previous step.plugins
specifies the plugin to use.
Step 5: Put together a valid JSON document
Megaload input is a list of JSON objects:
[
{"test" : ... },
{"plugin" : ... },
{"phase" : ... },
{"scenario" : ... }
]
You can now save the test (for example, as SUT-test-example.json
), upload the text file using the Megaload dashboard and run the test. However it would be useful to include some checks in the test, using Megaload assertions.
Assertions
Megaload assertions can be included in both test
and phase
specifications. These assertions can check the value of any counter in the system and match it against the provided specification. Assertions are explained in more detail in the section assertions.
{
"test" :
{
"id" : "SUT-test",
"phases" : ["SUT-low"],
"plugins" : ["SUT-server"],
"assertions" : <ASSERTIONS>
}
}
The assertions can include counters and histograms, as shown below.
[
{"assert-counter" :
{"id" : "global_counter_failedRequests",
"metric" : "count",
"filter" : {"eq" : 0}}
},
{"assert-histogram" :
{"id" : "http_histogram_responseTime",
"statistic" : "mean",
"filter" : {"lt" : 150000}}
}
]
When you run the test, you can view the results of the assertions on the Load report page.
There is a different kind of assertion that can be used to validate the response code and content of HTTP responses. These assertions are used to determine whether a request is successful or not and increase the related counter. Thus, the test and phase assertions can be combined with these HTTP assertions to validate the result of a test.
Assertions are included in the HTTP request with the following format:
{
"http-request" :
{
"plugin_id" : <PLUGIN_ID>,
"method" : <HTTP_REQUEST_METHOD>,
"path" : <HTTP_REQUEST_URI>,
"assert_status" : <HTTP_RESPONSE_STATUS_CODE>,
"assert_body" : <ACTION_CHECK>
}
}
To validate the response code:
{
"http-request" :
{
"plugin_id" : "SUT-server",
"method" : "GET",
"path" : "/customers",
"assert_status" : "200"
}
}
To validate the content:
{
"http-request" :
{
"plugin_id" : "SUT-server",
"method" : "GET",
"path" : "/customers",
"assert_body" :
{"jsonpath-value" :
{"path" : "body.count",
"value" : 5}}
}
}
Megaload automatically updates counters for successful and failed requests:
global_counter_successfulRequests
global_counter_failedRequests
http_counter_successfulRequests_<SUT_IP>
http_counter_failedRequests_<SUT_IP>
The following checks whether a user is a customer of the shop:
{
"http-request" :
{
"plugin_id" : "SUT-server",
"method" : "GET",
"path" : "/customer/jack",
"assert_status" : "404"
}
}
When you run the test, go to Load report > Assertion details on the dashboard to view the results.