Load testing a mobile platform is especially hard to do, for the following reasons:
Here comes Rungutan!
JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way for securely transmitting information between parties as a JSON object. This information can be verified and trusted because it is digitally signed. JWTs can be signed using a secret (with the HMAC algorithm) or a public/private key pair using RSA or ECDSA.
Although JWTs can be encrypted to also provide secrecy between parties, we will focus on signed tokens. Signed tokens can verify the integrity of the claims contained within it, while encrypted tokens hide those claims from other parties. When tokens are signed using public/private key pairs, the signature also certifies that only the party holding the private key is the one that signed it.
{
"login": {
"path": "/obfuscated/path/that/does/login",
"method": "POST",
"data": "grant_type=OBFUSCATED&username=OBFUSCATED&password=OBFUSCATED",
"headers": {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Basic OBFUSCATED"
},
"get_token": {
"from": "response",
"key": "access_token",
"inject_as_header_key": "Authorization",
"inject_prefix_header_value": "Bearer "
}
}
}
The structure, as defined in the Documentation, is simple:
Well, the hard part was done!
After we sorted out the authentication logic, let's add some workflow paths.
{
"workflow": [
{
"path": "/obfuscated/first/url",
"method": "GET",
"data": "",
"headers": {
"Accept-Language": "ro_RO",
"Content-Type": "application/json",
"User-Agent": "Pago/1.9.12"
}
},
{
"path": "/obfuscated/second/url",
"method": "GET",
"data": "",
"headers": {
"Accept-Language": "ro_RO",
"Content-Type": "application/json",
"User-Agent": "Pago/1.9.12"
}
},
{
"path": "/obfuscated/third/url",
"method": "POST",
"data": "{\"buildVersion\": \"1.9.12\",\"model\": \"Google Android SDK built for x86 Os:29\",\"posBuild\": \"NATIVE\",\"posOS\": \"Android\"}",
"headers": {
"Accept-Language": "ro_RO",
"Content-Type": "application/json",
"User-Agent": "Pago/1.9.12"
}
}
]
}
Now that you have a workflow and a valid login method, all we have to do is define the rest of the test case:
{
"team_id": "mobileappdemo",
"test_name": "open app-> login -> get data -> post something",
"num_clients": 250,
"hatch_rate": 30,
"run_time": 600,
"threads_per_region": 3,
"domain_name": "the-mobile-app-api-hostname.com",
"protocol": "https",
"test_region": [
"eu-central-1"
],
"min_wait": 1000,
"max_wait": 1000,
"login": {
"path": "/obfuscated/path/that/does/login",
"method": "POST",
"data": "grant_type=OBFUSCATED&username=OBFUSCATED&password=OBFUSCATED",
"headers": {
"Content-Type": "application/x-www-form-urlencoded",
"Authorization": "Basic OBFUSCATED"
},
"get_token": {
"from": "response",
"key": "access_token",
"inject_as_header_key": "Authorization",
"inject_prefix_header_value": "Bearer "
}
},
"workflow": [
{
"path": "/obfuscated/first/url",
"method": "GET",
"data": "",
"headers": {
"Accept-Language": "ro_RO",
"Content-Type": "application/json"
}
},
{
"path": "/obfuscated/second/url",
"method": "GET",
"data": "",
"headers": {
"Accept-Language": "ro_RO",
"Content-Type": "application/json"
}
},
{
"path": "/obfuscated/third/url",
"method": "POST",
"data": "{\"buildVersion\": \"1.9.12\",\"model\": \"Google Android SDK built for x86 Os:29\",\"posBuild\": \"NATIVE\",\"posOS\": \"Android\"}",
"headers": {
"Accept-Language": "ro_RO",
"Content-Type": "application/json"
}
}
]
}
Now that you have a test, you can include it in your CI/CD process in order to ran it every time you deploy.
The CLI tool can help you integrate it easily with any system.
Here's a sample GitLab CI/CD integration for instance:
image: "python:3.7-alpine"
stages:
- load_test
variables:
RUNGUTAN_TEAM_ID: your_team
RUNGUTAN_API_KEY: your_api_key
before_script:
- pip install rungutan
load_test:
stage: load_test
script:
- rungutan tests add --test_file test_file.json --wait_to_finish --test_name ${CI_PROJECT_PATH_SLUG}-${CI_PIPELINE_ID}
Or, if you're not a fan of running PIP packages locally, you can use a Docker image. Here's a working example of Docker with Jenkins:
#!groovy
def RUNGUTAN_TEAM_ID=your_team
def RUNGUTAN_API_KEY=your_api_key
pipeline {
agent any
stages {
stage('LoadTest') {
agent {
docker {
image 'rungutancommunity/rungutan-cli:latest'
args '-u root -e ${RUNGUTAN_TEAM_ID} -e ${RUNGUTAN_API_KEY}'
reuseNode true
}
}
steps {
script {
rungutan tests add --test_file test_file.json --wait_to_finish --test_name ${BUILD_TAG}
}
}
}
}
}
And if you're using GitHub, you can just reuse the GitHub Marketplace Integration for Rungutan like this:
name: Load test with Rungutan
on:
release:
types:
- created
jobs:
load:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Load test your platform with Rungutan
uses: Rungutan/rungutan-actions@1.0.0
env:
RUNGUTAN_TEAM_ID: ${{ secrets.RUNGUTAN_TEAM_ID }}
RUNGUTAN_API_KEY: ${{ secrets.RUNGUTAN_API_KEY }}
RUNGUTAN_TEST_FILE: test_file.json
RUNGUTAN_TEST_NAME: ${{ github.repository }}-${{ github.ref }}