Run tests: judge code against test cases
POST /api/run-tests/ runs one program against a list of tests, each in a fresh sandbox, and returns a verdict for each test, an overall verdict and a score from 0 to 100. Hidden tests come back with only their verdict, and each test counts as one run.
https://api.onlinecompiler.io/api/run-tests/Run one program against a list of tests and get a verdict for each, an overall verdict and a score, in one request. It authenticates like the sync endpoint and always waits for the result. Each test runs in its own fresh sandbox, and each test counts as one run against your monthly allowance and your per-minute and pending limits. Each test takes one of your account's pending slots when the request arrives and frees it when that test finishes, so on Free one 8-test request starts out using all of them, and your other runs (the widget's included) wait or get 429 until its tests start finishing.
| Field | Type | Required | Description |
|---|---|---|---|
| compiler | string | Yes | A compiler id, as on the other endpoints. |
| code | string | Yes | Source code (max 100KB). Compiled in every test, or once per request for C, C++ and Java when there are more tests than run at once. |
| tests | array | Yes | The tests to run, 1 up to your plan's limit (table below). |
| tests[].input | string | No | Standard input for this test (max 100KB). Empty if left out. |
| tests[].expected_output | string | Yes | What the program should print (max 64KB). Stderr is never compared. |
| tests[].hidden | boolean | No | false if left out. A hidden test returns only its verdict. |
| tests[].weight | number | No | Above 0; 1 if left out. Counts only for weighted scoring. |
| time_limit | number | No | Seconds each test may run, above 0 and up to 30; 2 if left out. Java, Groovy and F# get a start-up allowance on top (see below). |
| checker | string | No | How output is compared: trim (the default), exact, tokens or float. |
| tolerance | number | No | For the float checker: 0 to 1; 1e-6 if left out. |
| scoring | string | No | all_or_nothing (the default), percent or weighted. |
| stop_on_failure | boolean | No | Stop starting tests after the first one that is not accepted. true with all_or_nothing, false otherwise. |
Limits for one request
| Plan | Tests per request | Run at once | Most tests at the default time_limit |
|---|---|---|---|
| Free | 8 | 2 | 8 |
| Starter | 20 | 3 | 20 |
| Pro | 40 | 3 | 30 |
| Business | 80 | 3 | 30 |
The last column is for a language with the default round overhead of 3 seconds and no start-up allowance, such as Python or C++. Languages that compile slowly fit fewer tests (see below).
- The number of tests is capped by your plan's pending limit. Tests run in the order you list them, at most as many at once as the table shows, and never more than your plan's runs at once.
- One request has a 60-second budget. Tests run in rounds (tests divided by tests at once, rounded up), and a round takes up to
time_limit+ start-up allowance + the language's round overhead for compiling and starting. All the rounds must fit in 60 seconds, and the last must be able to start within 45. A request over budget gets 400 with the largesttime_limitthat would fit. - The round overhead is 3 seconds, except for languages that compile slowly: Crystal (13 s), Kotlin (6 s), Nim (5.5 s), Zig (4.5 s), Scala (4 s), C# (4 s) and Visual Basic (4 s). Each test compiles the program again, so these fit fewer tests; at the default
time_limit, a Crystal request holds at most 12 tests on Pro. - C, C++ and Java compile once per request when there are more tests than run at once: one sandbox compiles the program, without any test input, then each test runs the build in its own fresh sandbox. If a C or C++ compile fails, the first test gets the verdict and counts as one run, and the rest are skipped; a Java program that fails to compile runs as before, compiling in every test. A request whose tests all run at once compiles in every test, which is faster for so few tests.
- No test starts after 45 seconds from the request's arrival. Tests that never started are
skipped, are not counted as runs and leave no history. When the cut-off skipped tests and none failed, the overall verdict isincomplete. The budget leaves time for every round, so this usually means tests waited for a sandbox, held by other users or by your account's other runs: retry the request. A retry runs, and counts, every test again. - A compilation error stops the remaining tests, because they would fail the same way. With
stop_on_failure, the first test that is not accepted does too. - Inputs and expected outputs together may hold at most 1 MB.
- A bad request answers 400 with
{"error": "..."}and starts nothing. Account limits and a busy host answer 429, and nothing runs.
Verdicts
Each test gets one verdict, decided in the order of this table (accepted and wrong_answer last). The last column is the Judge0 status id it maps to.
| Verdict | When | Judge0 id |
|---|---|---|
| internal_error | We could not run the test. | 13 |
| compilation_error | Compiling failed (languages with a compile step; a syntax error in an interpreted language is a runtime_error). | 6 |
| time_limit_exceeded | Exit code 124, or the run took longer than the time limit plus any start-up allowance. | 5 |
| memory_limit_exceeded | Killed at the 512 MB memory limit (exit code 137). Judge0 has no memory status, so it reports 12. | 12 |
| output_limit_exceeded | Signal 25, or stdout was cut at 64KB. | 8 |
| runtime_error | Any other non-zero exit code or signal. | 7 to 12 |
| wrong_answer | Exit code 0 and the checker rejects the output. | 4 |
| accepted | Exit code 0 and the checker accepts the output. | 3 |
| skipped | The test never started: the program failed to compile, or failed with stop_on_failure, or the start cut-off came first. Test entries only; it counts as not accepted. | none |
| incomplete | Overall verdict only: the start cut-off skipped tests and none failed, usually because the host or your account's other runs kept the sandboxes busy. Retry the request. | none |
Checkers and scoring
| checker | Compares |
|---|---|
| trim | Strips trailing whitespace from every line and trailing blank lines, then compares exactly. The default; it is what Judge0 does. |
| exact | The two outputs are identical, byte for byte. |
| tokens | Splits both on whitespace and compares the lists, so spacing and line breaks do not matter. |
| float | As tokens, but two numbers match when they differ by at most tolerance times the larger of 1 and the expected value. Anything that is not a finite number must match as text. |
| scoring | score |
|---|---|
| all_or_nothing | 100 when every test is accepted, otherwise 0. |
| percent | 100 times accepted tests over all tests. |
| weighted | 100 times the weights of accepted tests over all weights. |
Response (200)
| Field | Description |
|---|---|
| verdict | The overall verdict: accepted when every test is, otherwise the verdict of the first test (in your order) that failed. incomplete when tests were skipped only by the 45-second start cut-off, usually because the host or your account's other runs kept the sandboxes busy; retry the request. |
| score | From 0 to 100, rounded to 2 decimals. Skipped tests count as not accepted. |
| passed, total | Tests accepted, and tests sent. |
| time_limit | The time limit used, in seconds, without the start-up allowance. |
| compile_error | The compiler output (first 4096 characters) when the code failed to compile and at least one test is visible; null otherwise. A request that compiles in every test takes it from the first visible test that failed to compile, so there it is also null when only hidden tests did. |
| tests | One entry per test, in the order sent. Each has verdict and hidden. A visible test that ran also has time, memory, exit_code, signal, output, error and truncated. |
{
"verdict": "runtime_error",
"score": 33.33,
"passed": 1,
"total": 2,
"time_limit": 2,
"compile_error": null,
"tests": [
{"verdict": "accepted", "hidden": false, "time": "0.0213", "memory": "9000",
"exit_code": 0, "signal": null, "output": "3
", "error": "", "truncated": false},
{"verdict": "runtime_error", "hidden": true}
]
}Inputs and expected outputs are not sent back. output and error are cut to the first 4096 characters, and truncated is true when either was cut. time and memory are strings, as on the sync endpoint. The response above is for the examples below: the hidden test puts the two numbers on separate lines, which the program does not read, so it ends in a runtime_error and the score is 1 of 3 weight points.
{"verdict": ..., "hidden": ...} and nothing else: no output, error, exit code, time or memory. Compiler output from a compile that saw a hidden test's input never appears in compile_error; a request that compiles once compiles without any test input, so a failed compile's output appears in compile_error whenever a test is visible. A program can encode a hidden input in anything it controls, so a student's code cannot read a hidden test back through your results.Start-up allowance for Java, Groovy and F#
These three compile as they start, inside the timed run, so even a hello-world uses part of a small time_limit. They get extra seconds on top of the limit: Java (1 s), Groovy (1.5 s) and F# (2.5 s). The run is stopped at time_limit plus the allowance, and a test is time_limit_exceeded only past that. time is still reported as measured, start-up included, and the response's time_limit is the one you asked for. The allowance applies wherever a time limit is honoured: here, the native time_limit on the run endpoints, and the Judge0 and Piston layers. In run-tests requests that compile once, Java compiles before the timed run, so its time is lower there; the allowance still applies everywhere for now. We will remove it once compiling always happens before the timed run.
Examples
curl -X POST https://api.onlinecompiler.io/api/run-tests/ \
-H "Authorization: YOUR_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"compiler": "python-3.14",
"code": "a, b = map(int, input().split())\nprint(a + b)",
"tests": [
{"input": "1 2\n", "expected_output": "3\n"},
{"input": "5\n7\n", "expected_output": "12\n", "hidden": true, "weight": 2}
],
"scoring": "weighted"
}'const res = await fetch('https://api.onlinecompiler.io/api/run-tests/', {
method: 'POST',
headers: { Authorization: 'YOUR_API_KEY', 'Content-Type': 'application/json' },
body: JSON.stringify({
compiler: 'python-3.14',
code: 'a, b = map(int, input().split())\nprint(a + b)',
tests: [
{ input: '1 2\n', expected_output: '3\n' },
{ input: '5\n7\n', expected_output: '12\n', hidden: true, weight: 2 }
],
scoring: 'weighted'
})
});
const result = await res.json();
console.log(result.verdict, result.score, result.passed + '/' + result.total);Questions
- Does each test count as a run?
- Yes. A request with 10 tests uses 10 runs of your monthly allowance and 10 of your per-minute and pending limits. Tests that never started, such as those skipped after a compile error, are not counted.
- How many tests can one request hold?
- Up to your plan's pending limit: 8 on Free, 20 on Starter, 40 on Pro, 80 on Business. They must also fit the request's 60-second budget, so a long time_limit or a slow-compiling language fits fewer; the table above shows the most at the default time limit.
- Can students see the hidden tests?
- No. A hidden test returns only its verdict: no output, error, time or memory. compile_error is filled in only when at least one test is visible.
- How is the output compared?
- trim, the default, strips trailing whitespace from each line and trailing blank lines, then compares exactly. exact compares byte for byte, tokens ignores all spacing and line breaks, and float accepts numbers within a tolerance.