HTTP REST API v2#
The HTTP REST API allows you to control your Stb-tester Nodes programmatically using HTTP requests and JSON.
This API is intended for integrating stb-tester with external systems, such as a Continuous Integration system.
Authentication#
To allow your scripts to access this API without providing your password, you need to generate an access token: Log into the portal using your browser, click on the user menu in the top right corner, and select “Generate new access token”. You can revoke access tokens from the same menu.
You must specify the token in the Authorization
HTTP header of every
request. If the token is missing or invalid you will get a “403 Forbidden”
response.
Example using curl:
curl -H "Authorization: token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9" \
https://company.stb-tester.com/api/...
Example using Python requests:
import requests
requests.post("https://company.stb-tester.com/api/...",
headers={"Authorization": "token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9"})
If you need to make multiple HTTP requests from a single script you can use
requests.Session
to set default values for every request:
import requests
session = requests.Session()
session.headers.update({"Authorization": "token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9"})
session.get("https://company.stb-tester.com/api/...")
session.post("https://company.stb-tester.com/api/...")
See also: User Access Control.
Rate limits#
Automated scripts that make many requests are subject to rate-limiting. If you are making requests in serial, you probably won’t even notice the rate-limiting, but if you send many requests at once in parallel, the requests may fail with the HTTP status code 429 Too Many Requests. If you receive a 429 response, your script should wait a few seconds before retrying.
The endpoints for downloading test-results artifacts have a generous “burst” rate, to allow batch scripts that download artifacts from a job with many test-runs.
Screenshots#
Grab screenshot#
- GET /api/v2/nodes/(node_id)/screenshot.png#
Grab a screenshot from the device under test.
Example using curl:
Save a screenshot to
screenshot.png
:curl -H "Authorization: token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9" \ https://company.stb-tester.com/api/v2/nodes/stb-tester-abcdef123456/screenshot.png \ > screenshot.png
- Response Headers:
Content-Type – image/png
- Status Codes:
200 OK – Success
403 Forbidden – Invalid access token
404 Not Found – Unknown node_id
429 Too Many Requests – Rate limits exceeded
503 Service Unavailable – Node is offline
Grab screenshot thumbnail#
- GET /api/v2/nodes/(node_id)/thumbnail.jpg#
Grab a small thumbnail of the screenshot from the device under test.
Example using curl:
Save a screenshot to
thumbnail.jpg
:curl -O -H "Authorization: token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9" \ https://company.stb-tester.com/api/v2/nodes/stb-tester-abcdef123456/thumbnail.jpg
- Response Headers:
Content-Type – image/jpeg
- Status Codes:
200 OK – success
403 Forbidden – Invalid access token
404 Not Found – Unknown node_id
429 Too Many Requests – Rate limits exceeded
503 Service Unavailable – Node is offline
Running tests#
List testcases#
- GET /api/v2/test_pack/<test_pack_revision>/test_case_names#
List testcases found at a particular revision (branch name or sha) of your test-pack. These names can be passed to /api/v2/run_tests.
Examples using Python requests:
List the testcases on the master branch:
import requests tests = requests.get( "https://company.stb-tester.com/api/v2/test_pack/master/test_case_names", headers={"Authorization": "token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9"} ).json() for test_name in tests: print test_name
List the testcases in your local git checkout:
import requests, subprocess my_sha = subprocess.check_output(['git', 'rev-parse', 'HEAD']).strip() tests = requests.get( "https://company.stb-tester.com/api/v2/test_pack/%s/test_case_names" % my_sha, headers={"Authorization": "token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9"} ).json() for test_name in tests: print test_name
Example output:
tests/menu.py::test_that_menu_appears_when_menu_key_is_pressed tests/menu.py::test_that_close_button_closes_menu tests/live_tv.py::test_that_pause_button_pauses_live_tv
- Response Headers:
Content-Type – application/json
- Status Codes:
200 OK – Success
403 Forbidden – Invalid access token
404 Not Found – Commit sha or branch not found in test-pack
429 Too Many Requests – Rate limits exceeded
Run tests#
- POST /api/v2/run_tests#
Run the specified testcases from the given git commit. The parameters are encoded in the request body as a JSON object. Returns a
job_uid
that can be used to poll for job completion and test results.Example using Python requests:
Start a test job with a single test:
response = requests.post( "https://company.stb-tester.com/api/v2/run_tests", headers={"Authorization": "token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9"}, data=json.dumps({ "node_id": "stb-tester-abcdef123456", "test_pack_revision": "master", "test_cases": ["tests/menu.py::test_that_menu_appears_when_menu_key_is_pressed"], "remote_control": "roku", })) print response.json()
{'job_uid': '/stb-tester-abcdef123456/0a23/972', 'job_url': 'https://company.stb-tester.com/api/v2/jobs/stb-tester-abcdef123456/0a23/972', 'status': 'running', 'start_time': '2015-05-28T14:46:35.354791Z', 'end_time': None, 'result_counts': {'pass': 0, 'fail': 0, 'error': 0, 'total': 1}, }
To make it easier for you to integrate Stb-tester with a Continuous Integration system such as Jenkins, we provide a helper script called
stbt_rig.py
. See Continuous Integration for details.- Request JSON Object:
node_id (string) – (mandatory) Which Stb-tester device to run the tests on. This is the name of the device as shown in the portal and on the physical case of the device, for example stb-tester-abcdef123456.
test_pack_revision (string) – (mandatory) Git commit SHA in test-pack repository identifying the version of the tests to run. Can also be the name of a git tag or branch.
test_cases (array) –
(mandatory) List of tests to run.
Testcase names have the form
(filename)::(function_name)
wherefilename
is given relative to the root of the test-pack repository andfunction_name
identifies a function within that file; for exampletests/my_test.py::test_that_blah_dee_blah
.The list of all possible testcase names for a given revision can be retrieved using /api/v2/test_pack/(test_pack_revision)/test_case_names.
remote_control (string) –
(usually mandatory) The remote control infrared configuration to use when running the tests.
This should match the name of a remote control configuration file in your test-pack git repository. For example if your test-pack has
config/remote-control/Sony_RM-ED022.lircd.conf
, then you should specify"Sony_RM-ED022"
.If not specified in the HTTP request, you must specify test_pack.default_remote_control in your test-pack’s configuration files.
category (string) –
(optional) Category to save the results in. Defaults to
"default"
.When you are viewing test results you can filter by this string so that you don’t see results that you aren’t interested in. For example you might set this to “soak test of release x”.
This must be a valid UTF-8 string and must not contain the characters
/
, newline (\n
), colon (:
), NUL (\0
),$
, or any control characters. It must not start with.
or-
and must not be empty. UTF-8 encoded Unicode characters are accepted.soak (string) –
(optional) Soak-testing mode. The allowed values are:
"run once"
– this is the default mode; it runs each of the specified testcases once."run forever"
– runs each of the testcases once, then repeats, forever. Use /api/v2/jobs/(job_uid)/stop to stop it.
shuffle (bool) –
(optional) Randomise the order in which the tests are run. The allowed values are:
true – Randomise the order in which the testcases are run, weighting towards running the faster testcases more often. See Run forever in random order for more information.
false – Run the testcases in the order in which they appear in
test_cases
. This is the default ifshuffle
is omitted.
tags (object) – (optional) Map of name:value pairs, for example
{"model": "T-1000"}
. Tags are passed to the test script as an automatic configuration key and are recorded in the test-results. Tags set here can be retrived in Python during the test-run withstbt.get_config("result.tags", "tagname")
. See also Tags.
- Response JSON Object:
job_uid (string) – Identifier that can be used later to refer to this test job (see the job status and stop endpoints below). This identifier is unique across all Stb-tester devices in your test farm.
job_url (string) – URL of the job status endpoint for this job. Included for convenience.
status – See /api/v2/jobs/(job_uid).
start_time – See /api/v2/jobs/(job_uid).
end_time – See /api/v2/jobs/(job_uid).
result_counts – See /api/v2/jobs/(job_uid).
- Request Headers:
Content-Type – application/json
- Response Headers:
Content-Type – application/json
- Status Codes:
200 OK – Test job started
400 Bad Request – Invalid json parameter
403 Forbidden – Invalid access token or node license expired
404 Not Found – Commit sha or branch not found in test-pack
404 Not Found – Unknown node_id
409 Conflict – A test job is already running
429 Too Many Requests – Rate limits exceeded
503 Service Unavailable – Node is offline
Inspect a test job#
- GET /api/v2/jobs/(job_uid)#
Find out the current status of the job started with /api/v2/run_tests.
- Parameters:
job_uid – The desired job’s universal identifier, as returned from /api/v2/run_tests.
- Response JSON Object:
job_uid (string) – Identifier that refers to this test job. This is unique across all Stb-tester devices in your test farm.
job_url (string) – The URL of this endpoint. This is included here for consistency with /api/v2/run_tests.
status (string) – Current status of the job. This can be either
"running"
or"exited"
.start_time (string) – The time at which the job started as an ISO8601 formatted datetime (for example
"2015-05-28T14:46:35.354791Z"
).end_time (string) – The time at which the job finished as an ISO8601 formatted datetime, or
null
if the job is still running.result_counts (object) –
A summary of the test results. This is a dictionary with the following keys:
pass – number of tests that completed and passed.
fail – number of tests that completed but failed.
error – number of tests that couldn’t complete due to an error (see Exceptions in the Python API reference).
total – can be greater than pass+fail+error if the job is still running or was stopped prematurely.
- Response Headers:
Content-Type – application/json
- Status Codes:
200 OK – Success
403 Forbidden – Invalid access token
404 Not Found – Unknown job_uid
429 Too Many Requests – Rate limits exceeded
Inspect a node’s current test job#
- GET /api/v2/nodes/(node_id)/job#
Similar to /api/v2/jobs/(job_uid) but instead of specifying a job_uid, it retrieves the current job on the specified Stb-tester device (or the last job that ran on that device if there is no job currently in progress).
Wait for a job to finish#
- GET /api/v2/jobs/(job_uid)/await_completion#
This is a “long poll” endpoint that will return when the job has finished running all its tests. It will return immediately if the job has already finished. To avoid timeouts from the HTTP client or any intermediate proxies, this will return “202 Accepted” after 55 seconds if the job still hasn’t finished. If you get a 202 response you should re-try the request.
- Response JSON Object:
job_uid (string) – Identifier of the current or latest test-job.
- Response Headers:
Content-Type – application/json
- Status Codes:
200 OK – Job finished
202 Accepted – Job still running; please re-try the request
404 Not Found – Unknown job_uid
Wait for a node’s current job to finish#
- GET /api/v2/nodes/(node_id)/job/await_completion#
Similar to /api/v2/jobs/(job_uid)/await_completion but instead of specifying a job_uid it waits for the current job on the specified Stb-tester device (or it will return immediately with “200 OK” if there is no job currently in progress).
Stop a job in progress#
- PUT /api/v2/jobs/(job_uid)/stop#
Stop a job started with /api/v2/run_tests.
By the time this endpoint returns a response, the job will be stopped. This makes it safe to use /api/v2/run_tests immediately after you receive the HTTP response from this endpoint.
This endpoint will respond with HTTP status 200 even if the job has already exited. This makes it safe to stop the same job any number of times (in other words, this endpoint is idempotent).
The HTTP methods PUT and POST are both valid for this endpoint and behave identically. PUT indicates that this endpoint is idempotent; POST is available for backward compatibility.
- Parameters:
job_uid – The desired job’s universal identifier, as returned from /api/v2/run_tests.
- Status Codes:
200 OK – The job is now stopped
202 Accepted – Timeout - the client should retry the request. If you receive this status code the job is stopping, but isn’t yet stopped. Typically this happens while waiting for the node to upload the artifacts from the job to the cloud. This status code can be avoided by putting the node on a sufficiently fast network.
403 Forbidden – Invalid access token
404 Not Found – Unknown job_uid
429 Too Many Requests – Rate limits exceeded
Stop a node’s current job#
- POST /api/v2/nodes/(node_id)/job/stop#
Similar to /api/v2/jobs/(job_uid)/stop but instead of specifying a job_uid, it stops the job that is currently running on the specified Stb-tester device.
Test results#
Get list of test results#
- GET /api/v2/results#
Retrieve test results for each test run, optionally filtered by a search expression.
Notes:
The response will not include a test-run that is currently in progress.
The response only includes the first 2,000 matching test-runs. Use the filter and sort parameters to retrieve older results (for example, sort by date, then make a second request using a filter to exclude results newer than the last result in the first response).
Example using Python requests:
response = requests.get( "https://company.stb-tester.com/api/v2/results", headers={"Authorization": "token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9"}, params={"filter": "job:/stb-tester-abcdef123456/0a23/972"}) print response.json()
[{'result_id': '/stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.34' 'job_uid': '/stb-tester-abcdef123456/0a23/972', 'result_url': 'https://company.stb-tester.com/api/v2/results/stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.34', 'triage_url': 'https://company.stb-tester.com/app/#/result//stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.34', 'start_time': '2015-05-28T14:46:35.354791Z', 'end_time': '2015-05-28T14:46:42.325432Z', 'test_pack_sha': 'c2c82cad08114f973e2c36f0bbfbfb0a78dad911', 'test_case': 'tests/epg.py::test_that_epg_is_populated', 'result': 'fail', 'failure_reason': 'EPG is empty' }, {'result_id': '/stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.44' 'job_uid': '/stb-tester-abcdef123456/0a23/972', 'result_url': 'https://company.stb-tester.com/api/v2/results/stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.44', 'triage_url': 'https://company.stb-tester.com/app/#/result//stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.44', 'start_time': '2015-05-28T14:46:45.431553Z', 'end_time': '2015-05-28T14:46:49.334224Z', 'test_pack_sha': 'c2c82cad08114f973e2c36f0bbfbfb0a78dad911', 'test_case': 'tests/epg.py::test_that_epg_is_populated', 'result': 'pass', 'failure_reason': None } ]
- Query Parameters:
filter – A search expression in the same format as the interactive search box in the test-results web interface, documented here. If not specified it will return all results (up to a limit of 2,000 results).
sort – “<fieldname>:asc” or “<fieldname>:desc”. Sort results by the specified field in ascending or descending order. <fieldname> can be “category”, “date”, “duration”, “job”, “testcase”, or “result”. Defaults to “date:desc”.
tz – A name like “America/Denver” from the Olson timezone database. This is the default timezone used for any dates specified in the filter parameter if the timezone isn’t explicit in those dates. Defaults to “UTC”.
The response consists of a JSON array of JSON objects. Each object corresponds to a test run. Each object contains a subset of the fields from /api/v2/results/(result_id):
- Response JSON Object:
result_id (string) – Identifier that refers to this test result. This is unique across all Stb-tester devices in your test farm.
result_url (string) – The REST API URL of this test result. You can use this URL to retrieve more information about the test run – see /api/v2/results/(result_id). You can also retrieve test artifacts such as logs and screenshots by appending /artifacts/(filename) to the url.
triage_url (string) – The URL of this test result in the portal, for viewing in a web browser.
job_uid (string) – Identifier that refers to this test job. See /api/v2/jobs/(job_uid).
start_time (string) – The time at which the test run started as an ISO8601 formatted datetime (for example
"2015-05-28T14:46:35.354791Z"
).end_time (string) – The time at which the test run finished as an ISO8601 formatted datetime.
test_case (string) – The name of the testcase as given to /api/v2/run_tests.
test_pack_sha (string) – The git sha of the test-pack revision as given to /api/v2/run_tests.
result (string) –
One of the following values:
pass – the testcase completed and passed.
fail – the testcase completed but failed.
error – the testcase couldn’t complete due to an error (see Exceptions in the Python API reference).
failure_reason (string) – The exception message when the test failed.
null
if the test passed.
- Response Headers:
Content-Type – application/json
- Status Codes:
200 OK – Success
400 Bad Request – Invalid filter, sort, or tz parameter.
403 Forbidden – Invalid access token
429 Too Many Requests – Rate limits exceeded
Get list of test results (CSV)#
- GET /api/v2/results.csv#
Takes the same parameters as /api/v2/results but returns CSV format (comma-separated values, suitable for opening with Excel) instead of JSON.
Get list of test results (XML)#
- GET /api/v2/results.xml#
Takes the same parameters as /api/v2/results but returns XML data (in jUnit format, which Jenkins knows how to interpret) instead of JSON. Also accepts the following additional parameter:
- Query Parameters:
include_tz – Include timezone information in the XML’s ISO8601 timestamps. This should be set to “true” unless the code interpreting the XML cannot cope with timezone information. Defaults to “false”, but this default may change in the future if no incompatible software is discovered — so you should always set this parameter.
Get detailed information about a test run#
- GET /api/v2/results/(result_id)/#
Retrieve detailed information about a test result.
Example using Python requests:
response = requests.get( 'https://company.stb-tester.com/api/v2/results/' + 'stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.44') print response.json()
{'result_id': '/stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.34' 'job_uid': '/stb-tester-abcdef123456/0a23/972', 'result_url': 'https://company.stb-tester.com/api/v2/results/stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.34', 'triage_url': 'https://company.stb-tester.com/app/#/result//stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.34', 'start_time': '2015-05-28T14:46:35.354791Z', 'end_time': '2015-05-28T14:46:42.325432Z', 'test_case': 'tests/epg.py::test_that_epg_is_populated', 'test_pack_branch': 'refs/heads/master', 'test_pack_sha': 'c2c82cad08114f973e2c36f0bbfbfb0a78dad911', 'username': 'johnsmith', 'result': 'fail', 'failure_reason': 'EPG is empty', 'job_category': 'example', 'traceback': '''Traceback (most recent call last): File "/usr/lib/stbt/stbt-run", line 88, in <module> function() File "tests/epg.py", line 24, in test_that_epg_is_populated assert epg_is_populated(), "EPG is empty" AssertionError: EPG is empty''', 'artifacts': { 'combined.log': {'size': 39381}, 'screenshot.png': {'size': 196119}, 'stderr.log': {'size': 39161}, 'stdout.log': {'size': 220}, 'thumbnail.jpg': {'size': 15220}, 'video.mp4': {'size': 262863}, 'my-custom-logfile.log': {'size': 52023}, 'a/file in a subdirectory/another.log': {'size': 2433} }, 'tags': {'model': 'T-1000'} }
- Parameters:
result_id – Identifier that refers to this test result, as returned from /api/v2/results. This is unique across all Stb-tester devices in your test farm.
The response consists of a JSON object, with the following elements:
- Response JSON Object:
result_id (string) – Identifier that refers to this test result. This is unique across all Stb-tester devices in your test farm.
result_url (string) – The REST API URL of this test result.
triage_url (string) – The URL of this test result in the portal, for viewing in a web browser.
job_uid (string) – Identifier that refers to this test job. See /api/v2/jobs/(job_uid).
start_time (string) – The time at which the test run started as an ISO8601 formatted datetime (for example
"2015-05-28T14:46:35.354791Z"
).end_time (string) – The time at which the test run finished as an ISO8601 formatted datetime.
test_case (string) – The name of the testcase as given to /api/v2/run_tests.
test_pack_sha (string) – The git sha of the test-pack revision given to /api/v2/run_tests.
test_pack_branch (string) – The git “ref” name of the test-pack branch. If you specified a git sha instead of a branch name when you submitted /api/v2/run_tests, then this will be
null
.username (string) – The user who started the test-job.
result (string) –
One of the following values:
pass – the testcase completed and passed.
fail – the testcase completed but failed.
error – the testcase couldn’t complete due to an error (see Exceptions in the Python API reference).
failure_reason (string) – The exception message when the test failed.
null
if the test passed.job_category (string) – The category as passed to /api/v2/run_tests when the tests were run.
traceback (string) – The traceback of the exception that caused the test to fail.
null
if the test passed.artifacts (object) – The files created during the test run. See /api/v2/results/(result_id)/artifacts/ for details.
tags (object) – A mapping of name:value tags as given to /api/v2/run_tests.
- Response Headers:
Content-Type – application/json
- Status Codes:
200 OK – Success
403 Forbidden – Invalid access token
404 Not Found – Unknown result_id
410 Gone – Result has been deleted
429 Too Many Requests – Rate limits exceeded
Get log output from test run#
- GET /api/v2/results/(result_id)/stbt.log#
Retrieve the output of the test run. This includes logging from stb-tester and any lines printed (written to stderr or stdout) by your Python code during the test run.
Each line consists of an ISO8601 datetime, followed by a space, followed by the message logged by your test script. For example:
2015-06-18T14:59:00.321421+00:00 A message printed by the test script
The file is served as utf-8, so you shouldn’t log invalid utf-8 byte sequences from your test script.
Example using Python requests:
Show the output of a test run:
result_url = 'https://company.stb-tester.com/api/v2/results/stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.44' response = requests.get('%s/stbt.log' % result_url', params={'tz': 'America/Denver'}) print response.text
2015-06-16T07:29:17.162452-06:00 stbt-run: Arguments: 2015-06-16T07:29:17.162615-06:00 control: lirc:172.17.0.133:8765:vstb 2015-06-16T07:29:17.162646-06:00 args: ['test_that_when_pressing_back_i_go_back_to_where_i_was_before_action_panel_epg'] 2015-06-16T07:29:17.162673-06:00 verbose: 1 2015-06-16T07:29:17.162701-06:00 source_pipeline: ximagesrc use-damage=false remote=true show-pointer=false display-name=:10 ! video/x-raw,framerate=24/1 2015-06-16T07:29:17.162728-06:00 script: /var/lib/stbt/test-pack/tests/brand_rollups.py 2015-06-16T07:29:17.162754-06:00 restart_source: False 2015-06-16T07:29:17.162781-06:00 sink_pipeline: fakesink sync=false 2015-06-16T07:29:17.162808-06:00 write_json: stbt-run.json 2015-06-16T07:29:17.162835-06:00 save_video: video.webm 2015-06-16T07:29:17.212650-06:00 stbt-run: Saving video to 'video.webm'
- Parameters:
result_id – The desired result’s identifier, as returned from /api/v2/results.
- Query Parameters:
tz – A name like “America/Denver” from the Olson timezone database. The timestamp at the beginning of each log line will be displayed in this timezone. Defaults to “UTC”.
- Response Headers:
Content-Type – text/plain; charset=utf-8
- Status Codes:
200 OK – Success
403 Forbidden – Invalid access token
404 Not Found – Unknown result_id
410 Gone – Result has been deleted
429 Too Many Requests – Rate limits exceeded
Get screenshot saved at end of test run#
- GET /api/v2/results/(result_id)/screenshot.png#
At the end of each test-run stb-tester saves a screenshot (in a lossless format) from the device under test. This can be useful for performing automated triage or as a source of new reference images.
This endpoint retrieves that screenshot.
Example usage:
Save the screenshot to disk as screenshot.png, using curl from the command line:
curl -O "https://company.stb-tester.com/api/v2/results/stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.44/screenshot.png"
Save the screenshot to disk from Python code, using the urllib module from the Python standard library:
import urllib result_url = 'https://company.stb-tester.com/api/v2/results/stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.44' urllib.urlretrieve('%s/screenshot.png' % result_url, 'screenshot.png')
View the screenshot in IPython notebook, using the Python requests library:
import IPython.display, requests result_url = 'https://company.stb-tester.com/api/v2/results/stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.44' response = requests.get('%s/screenshot.png' % result_url) IPython.display.Image(data=response.content)
Try a
stbt.match
against the saved screenshot:import cv2, numpy, requests, stbt result_url = 'https://company.stb-tester.com/api/v2/results/stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.44' response = requests.get('%s/screenshot.png' % result_url) image = cv2.imdecode(numpy.frombuffer(response.content, dtype='uint8'), 1) print stbt.match('my-reference.png', frame=image)
MatchResult(timestamp=None, match=False, region=Region(x=82, y=48, width=54, height=54), first_pass_result=0.942756436765, frame=1280x720x3, image='my-reference.png')
- Parameters:
result_id – The desired result’s identifier, as returned from /api/v2/results.
- Response Headers:
Content-Type – image/png
- Status Codes:
200 OK – Success
403 Forbidden – Invalid access token
404 Not Found – Unknown result_id
410 Gone – Result has been deleted
429 Too Many Requests – Rate limits exceeded
List artifacts produced during a test run#
- GET /api/v2/results/(result_id)/artifacts/#
List the files saved during a test run. This includes files written by stb-tester and any files written by your test scripts into the current working directory while the test is running.
Note: The files that stb-tester writes may change depending on the value of test_pack.stbt_version in .stbt.conf. It is therefore recommended to only rely on this endpoint to retrieve test artifacts that the test-scripts explicitly write and to use the values of /api/v2/results/(result_id) for data provided by stb-tester.
Example using Python requests:
List the files produced by a test run.
result_url = 'https://company.stb-tester.com/api/v2/results/stb-tester-abcdef123456/0a23/972/2015-05-28_14.46.44' response = requests.get('%s/artifacts/ % result_url') print response.json()
{ 'combined.log': {'size': 39381}, 'screenshot.png': {'size': 196119}, 'stderr.log': {'size': 39161}, 'stdout.log': {'size': 220}, 'thumbnail.jpg': {'size': 15220}, 'video.mp4': {'size': 262863}, 'my-custom-logfile.log': {'size': 52023}, 'a/file in a subdirectory/another.log': {'size': 2433} }
- Parameters:
result_id – The desired result’s identifier, as returned from /api/v2/results.
The response is a JSON object. The keys of the object are filenames and the values are dictionaries containing additional information about the files. Files in subdirectories are also listed, but the directories themselves won’t appear in the listing.
The information about each file is:
- Response JSON Object:
size (string) – The size of the file in bytes.
- Response Headers:
Content-Type – application/json
- Status Codes:
200 OK – Success
403 Forbidden – Invalid access token
404 Not Found – Unknown result_id
410 Gone – Result has been deleted
429 Too Many Requests – Rate limits exceeded
Get an artifact produced during a test run#
- GET /api/v2/results/(result_id)/artifacts/(filename)#
Retrieve files recorded during a test run.
For examples see the examples for the screenshot endpoint.
- Parameters:
result_id – The desired result’s identifier, as returned from /api/v2/results.
filename – The name of the file to retrive.
The response consists of the contents of a file given by
filename
recorded during a test run.- Response Headers:
Content-Type – Varies depending on the filename extension.
- Status Codes:
200 OK – Success
403 Forbidden – Invalid access token
404 Not Found – Unknown result_id
404 Not Found – Result doesn’t have this file
410 Gone – Result has been deleted
429 Too Many Requests – Rate limits exceeded
Test farm node information#
Get status of all nodes#
- GET /api/v2/nodes#
List all the Stb-tester devices in your test farm. The response is a JSON list of objects, one for each Stb-tester Node. See Get a node’s current status, below, for documentation about these objects.
Example using Python requests:
response = requests.get( 'https://company.stb-tester.com/api/v2/nodes', headers={"Authorization": "token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9"}) print(response.json())
[ { "node_id": "stb-tester-abcdef123456", "available": false, ... etc ... }, ... more nodes ... ]
- Response Headers:
Content-Type – application/json
- Status Codes:
200 OK – Success
403 Forbidden – Invalid access token
429 Too Many Requests – Rate limits exceeded
Get a node’s current status#
- GET /api/v2/nodes/(node_id)#
Get information about an Stb-tester device in your test farm. This includes information about the node’s configuration in git, the test job that it is running, and its active reservation, if any.
Example using Python requests:
node_id = "stb-tester-abcdef123456" response = requests.get( 'https://company.stb-tester.com/api/v2/nodes/' + node_id, headers={"Authorization": "token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9"}) print(response.json())
{ "available": false, "config": { "node": { "friendly_name": "Rack 3, Node 1" }, "device_under_test": { "device_type": "roku", "ip_address": "192.168.1.108" } }, "device_type": "roku", "external_ip_address": "1.2.3.4", "friendly_name": "Rack 3, Node 1", "geoip_city": "London", "geoip_country": "United Kingdom", "job": { "end_time": "2023-02-18T21:53:15.908299+00:00", "job_uid": "/stb-tester-abcdef123456/0000/319", "job_url": "https://company.stb-tester.com/api/v2/jobs/stb-tester-abcdef123456/0000/319", "log_url": "https://company.stb-tester.com/api/v2/jobs/stb-tester-abcdef123456/0000/319/log", "result_counts": { "error": 1, "fail": 0, "pass": 0, "total": 1 }, "start_time": "2023-02-18T21:52:26.139210+00:00", "status": "exited", "triage_url": "https://company.stb-tester.com/app/#/results?filter=job:/stb-tester-abcdef123456/0000/319" }, "last_used_by": "johnsmith", "last_used_time": "2023-02-22T14:25:02.156078+00:00", "licence_expiry": "2024-01-31", "local_ip_address": "192.168.1.101", "node_id": "stb-tester-abcdef123456", "node_url": "https://company.stb-tester.com/api/v2/nodes/stb-tester-abcdef123456", "not_available_reason": "Node stb-tester-abcdef123456 reserved by @johnsmith", "online": false, "reservation": { "expires": "2023-02-22T16:56:11+00:00", "message": "Overnight DVR soak", "message_html": "<p>Overnight DVR soak</p>", "node_id": "stb-tester-abcdef123456", "reservation_id": 6, "reserved_by_you": true, "start_time": "2023-02-22T15:56:11+00:00", "username": "johnsmith" } }
- Parameters:
node_id – The node ID (e.g. “stb-tester-abcdef123456”)
- Response JSON Object:
available (bool) –
true
if this node can be reserved. This will befalse
if the node is offline, reserved (even if it’s reserved by you), running a test, licence expired, has a pending software update, etc. Seenot_available_reason
below.Note: Reserving a node may still fail, if someone else has reserved it between the time you checked
available
and the time you tried to reserve it.config (object) – Configuration from the node-specific config file in git (on your main branch). This only includes node-specific configuration and doesn’t include the global configuration from
stbt.conf
.device_type (string or null) – The type of device under test, taken from the node-specific config file in git (on your main branch). This will be
null
if this configuration value is not set.external_ip_address (string or null) – The IP address that the node is currently using to connect to the portal from the perspective of the portal. This will be
null
if the portal has never seen this node. This will typically be a public IP address.friendly_name (string or null) – The friendly name of the node taken from the node-specific config file in git (on your main branch). This will be
null
if this configuration value is not set.geoip_city (string or null) – The physical location (city) of the node, as determined by geo-ip lookup using
external_ip_address
. See Location data. This will benull
if the portal has never seen this node, if the IP address is not in the geo-ip database, or if the city can’t be determined from the IP address. This information may be incorrect or change in a backward incompatible manner so shouldn’t be relied upon.geoip_country (string or null) – The physical location (country) of the node, as determined by geo-ip lookup using
external_ip_address
. See the caveats undergeoip_city
, above.job (object or null) – The job that is currently running on the node, or the last job that ran on the node. This will be
null
if the node has never run a job. For the description of each field see Inspect a test job.local_ip_address (string or null) – The IP address of the node’s network interface. This will be
null
if the portal has never seen this node. This will typically be a private IP address (e.g. 10.x.x.x or 192.168.x.x)last_used_by (string or null) – The username of the last user to use the node by running or stopping a job, using the manual remote control, making a reservation, grabbing a screenshot, etc. This will be
null
if the node has never been used.last_used_time (string or null) – The date and time that the node was last used, in ISO8601 format. This will be
null
if the node has never been used.licence_expiry (string) – The date that the node’s licence expires, in ISO8601 format.
node_id (string) – The node ID (e.g. “stb-tester-abcdef123456”).
node_url (string) – The URL of this node’s API endpoint.
not_available_reason (string or null) – Human-readable reason why
available
isfalse
. This will benull
ifavailable
istrue
.online (boolean) – Whether the node is currently online (powered on and can connect to the portal). See Troubleshooting: My Stb-tester node is offline.
reservation (object or null) – The reservation that is currently held on the node. This will be
null
if the node is not currently reserved. For documentation about this object see Reservations.
- Response Headers:
Content-Type – application/json
- Status Codes:
200 OK – Success
403 Forbidden – Invalid access token
404 Not Found – Unknown node_id
429 Too Many Requests – Rate limits exceeded
Reservations#
You can “reserve” an Stb-tester Node so that other users can’t start test jobs, stop test jobs, or use the manual remote control.
Your reservation is held until you end it using the End a reservation endpoint, or until it expires; you can Extend a reservation before it expires.
Other users can interrupt your reservation. In this way, reservations are advisory — any user can interrupt any other user’s reservation.
Reserve nodes for exclusive use#
- POST /api/v2/reservations#
Reserve one or more nodes.
This API is atomic: You will reserve all nodes, or none of them. If any of the nodes is in use (because it is already reserved or busy running a test-job), the request will fail with “409 Conflict”.
Example using Python requests:
Reserve two nodes for 12 hours:
response = requests.post( "https://company.stb-tester.com/api/v2/reservations", headers={"Authorization": "token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9"}, json={ "node_ids": ["stb-tester-000000000001", "stb-tester-000000000002"], "message": "Reserved for overnight DVR soak\n\nSee JIRA-12345 for details", "duration_secs": 12 * 60 * 60, }) print(response.json())
{ "reservations": [ { "expires": "2023-02-07T12:22:16+00:00", "message": "Reserved for overnight DVR soak\n\nSee JIRA-12345 for details", "message_html": "<p>Reserved for overnight DVR soak</p>\n<p>See JIRA-12345 for details</p>", "node_id": "stb-tester-000000000001", "reservation_id": 2, "reserved_by_you": true, "start_time": "2023-02-07T11:22:16+00:00", "username": "johnsmith" }, { "expires": "2023-02-07T12:22:16+00:00", "message": "Reserved for overnight DVR soak\n\nSee JIRA-12345 for details", "message_html": "<p>Reserved for overnight DVR soak</p>\n<p>See JIRA-12345 for details</p>", "node_id": "stb-tester-000000000002", "reservation_id": 3, "reserved_by_you": true, "start_time": "2023-02-07T11:22:16+00:00", "username": "johnsmith" } ] }
- Request JSON Object:
node_ids (array) – (mandatory) Which Stb-tester devices to reserve.
message (string) – (mandatory) Message that will be displayed to other users in the Stb-tester Portal while the reservation is active.
duration_secs (int) – (optional) Duration of the reservation in seconds. After this time, the reservation will end automatically.
null
(or unspecified) means that the reservation will never expire.
- Response JSON Object:
reservations (array) –
List of the reservations created by this request. This an array of objects with the same length as node_ids. Each object has the following fields:
reservation_id (int) – An identifier that uniquely identifies this reservation.
node_id (string) – The node that was reserved, for example
"stb-tester-abcdef123456"
.username (string) – The user who reserved the node.
start_time (string) – The time when the reservation started, in ISO8601 format.
expires (string) – The time when the reservation will expire, in ISO8601 format.
message (string) – The message that was given to the API.
message_html (string) – The message, converted from Markdown format to HTML.
reserved_by_you (bool) – Whether the reservation was made by the user who made this REST API request. This will always be
true
for the response to this request, but it will befalse
for other users querying the status of a reservation via other API endpoints.
- Request Headers:
Content-Type – application/json
- Response Headers:
Content-Type – application/json
- Status Codes:
200 OK – Reserved all the specified nodes
400 Bad Request – Invalid parameter
403 Forbidden – Invalid access token
404 Not Found – Unknown node_id
409 Conflict – One or more of the nodes are already reserved or busy
429 Too Many Requests – Rate limits exceeded
Extend a reservation#
- POST /api/v2/reservations/(reservation_id)/extend#
Extend your reservation. This affects the
expires
field of the reservation.Only the user who created the reservation can extend it.
Example using Python requests:
Extend a reservation by 10 minutes:
response = requests.post( "https://company.stb-tester.com/api/v2/reservations/%i/extend" % reservation_id, headers={"Authorization": "token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9"}, json={"duration_secs": 10 * 60})
- Parameters:
reservation_id – Reservation id as returned from the POST /api/v2/reservations endpoint.
- Request JSON Object:
duration_secs (int) – (mandatory) Extend the reservation’s current expiry by this amount of seconds.
- Request Headers:
Content-Type – application/json
- Status Codes:
204 No Content – Success: Reservation extended
400 Bad Request – Invalid parameter
400 Bad Request – Reservation already ended
403 Forbidden – Invalid access token
403 Forbidden – Reservation was not created by you
404 Not Found – Reservation doesn’t exist
429 Too Many Requests – Rate limits exceeded
End a reservation#
- DELETE /api/v2/reservations/(reservation_id)#
End a reservation. Call this when you have finished using the Stb-tester Node.
Only the user who created the reservation can use this endpoint. Other users must use the Interrupt a reservation endpoint.
Example using Python requests:
response = requests.delete( "https://company.stb-tester.com/api/v2/reservations/%i" % reservation_id, headers={"Authorization": "token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9"})
- Parameters:
reservation_id – Reservation id as returned from the POST /api/v2/reservations endpoint.
- Status Codes:
204 No Content – Reservations ended
204 No Content – Reservation already ended
400 Bad Request – Invalid parameter
403 Forbidden – Invalid access token
403 Forbidden – This reservation was not made by you
404 Not Found – Reservation doesn’t exist
429 Too Many Requests – Rate limits exceeded
Interrupt a reservation#
- POST /api/v2/reservations/(reservation_id)/interrupt#
Interrupt someone else’s reservation. Unlike End a reservation, this endpoint can be used by any user to end a reservation that was made by another user — but you must specify a message for the owner of the reservation.
Example using Python requests:
Interrupt a reservation that was created by the previous example:
response = requests.post( "https://company.stb-tester.com/api/v2/reservations/%i/interrupt" % reservation_id, headers={"Authorization": "token BP7BxqZvuZPGeQRBuG6fxh7S_B1iWmS9"}, json={"message": "Node needed for emergency regression testing\n\nSee JIRA-54321."})
- Parameters:
reservation_id – Reservation id as returned from the POST /api/v2/reservations endpoint.
- Request JSON Object:
message (string) – (mandatory) Message that will be displayed to the owner of the reservation.
- Request Headers:
Content-Type – application/json
- Status Codes:
204 No Content – Success - Reservation interrupted
204 No Content – Success - Reservation already ended
400 Bad Request – Invalid parameter
403 Forbidden – Invalid access token
404 Not Found – Reservation doesn’t exist
429 Too Many Requests – Rate limits exceeded