Scheduled Runs

Automate test execution on a recurring basis using cron expressions. Configure schedules for entire projects or individual suites, and manage data retention to keep your disk usage under control.

Overview

Scheduled runs let you execute your tests automatically on a recurring basis without manual intervention. Each schedule is tied to a project and optionally to a specific test suite. When a schedule fires, it runs all project tests (or the suite's tests) with a concurrency of 2, records the results, and updates the schedule's status tracking fields.

Schedules are managed through the REST API and persisted in the SQLite database. On server startup, all enabled schedules are reloaded via loadAllSchedules(), ensuring that your automation survives server restarts.

Warning

Schedules persist across server restarts. All enabled schedules are automatically reloaded when the server starts up via loadAllSchedules(). If you stop the server for an extended period, any schedules that were due to fire during that time will not retroactively execute — they will simply resume on the next scheduled time after the server starts.

Creating a Schedule

To create a schedule, send a POST request to the schedules endpoint with the following fields:

Field Type Required Description
projectId string Yes The ID of the project whose tests to run.
name string Yes A descriptive name for the schedule (1-100 characters).
cronExpression string Yes A valid cron expression defining the schedule frequency.
suiteId string No Optional suite ID. If provided, only that suite's tests will run. If omitted, all project tests run.
enabled boolean No Whether the schedule is active. Defaults to true.
POST /api/schedules
{
  "projectId": "proj_abc123",
  "name": "Nightly Regression Suite",
  "cronExpression": "0 0 * * *",
  "suiteId": "suite_xyz789",
  "enabled": true
}

The server validates the cron expression using the node-cron library. If the expression is invalid, a 400 error is returned. If the schedule is enabled, it is immediately activated via scheduleJob().

Cron Expression Format

Cron expressions follow the standard five-field format:

Format
┌───────────── minute (0-59)
│ ┌───────────── hour (0-23)
│ │ ┌───────────── day of month (1-31)
│ │ │ ┌───────────── month (1-12)
│ │ │ │ ┌───────────── day of week (0-7, where 0 and 7 are Sunday)
│ │ │ │ │
* * * * *

Common Presets

Here are some commonly used cron expressions:

Expression Description
0 * * * * Every hour, on the hour
0 0 * * * Every day at midnight
0 9 * * 1-5 Every weekday at 9:00 AM
*/30 * * * * Every 30 minutes
0 6,18 * * * Twice daily at 6:00 AM and 6:00 PM
0 0 * * 0 Every Sunday at midnight
0 0 1 * * First day of every month at midnight

Schedule Behavior

When a schedule fires:

  • If a suiteId is set, only the tests in that suite are executed.
  • If no suiteId is set, all tests in the project are executed.
  • Tests run with a concurrency of 2, meaning up to 2 tests execute in parallel.
  • Each test execution creates a run record, exactly as if you had manually triggered the run.
  • Results contribute to the analytics dashboard (pass rate, trends, flaky detection).

Schedule Status Tracking

Each schedule record tracks its execution history through three status fields:

Field Type Description
lastRunAt string (ISO timestamp) or null The timestamp of the most recent execution. Null if never run.
lastRunStatus string or null The result of the most recent execution ("passed" or "failed"). Null if never run.
nextRunAt string (ISO timestamp) or null The calculated timestamp of the next scheduled execution.

These fields allow you to monitor schedule health at a glance and detect any schedules that may be consistently failing.

Enable / Disable Toggle

Schedules can be enabled or disabled at any time by updating the enabled field. When a schedule is disabled, its cron job is unregistered via unscheduleJob() and it will not fire until re-enabled.

PUT /api/schedules/:id
{
  "enabled": false
}

When re-enabled, the schedule is immediately re-registered with the cron scheduler. You can also update the name, cronExpression, and suiteId in the same request.

Managing Schedules

The full set of schedule management endpoints:

Endpoint Method Description
/api/projects/:projectId/schedules GET List all schedules for a project, ordered by creation date.
/api/schedules POST Create a new schedule. Activates immediately if enabled.
/api/schedules/:id PUT Update a schedule's name, cron expression, suiteId, or enabled status.
/api/schedules/:id DELETE Delete a schedule. The cron job is unregistered and the record is removed.

Data Cleanup & Retention

As tests run automatically on a recurring basis, run records, screenshots, videos, and diff images accumulate over time. QA Studio includes an automatic cleanup system to manage disk usage.

Retention Configuration

The retention period is controlled by the RETENTION_DAYS environment variable:

Variable Default Description
RETENTION_DAYS 30 Number of days to keep run data. Set to 0 to disable automatic cleanup.

Automatic Cleanup

The cleanup system runs automatically in two ways:

  • On server startup — A deferred cleanup runs 5 seconds after the server starts, removing any data older than the retention period.
  • Daily at 3:00 AM — A cron job (0 3 * * *) runs the cleanup every day via startCleanupSchedule().

The cleanup process removes:

  • Old run records — Deleted from the runs table.
  • Old suite run records — Deleted from the suite_runs table.
  • Screenshot files — Deleted from disk for expired runs.
  • Video files — Deleted from disk for expired runs.
  • Diff image files — Actual and diff images for expired runs are removed. Baseline images referenced by diffs are preserved.

Manual Cleanup

You can trigger a cleanup on demand at any time using the admin endpoint:

HTTP
POST /api/admin/cleanup

This runs the same cleanup logic as the automatic schedule, using the current RETENTION_DAYS value. The response confirms success:

Response
{
  "success": true
}
Tip

Use the POST /api/admin/cleanup endpoint to manually free disk space when needed. This is especially useful after bulk test runs or when you have lowered the RETENTION_DAYS value and want the change to take effect immediately.

Example Workflow

A typical scheduling workflow looks like this:

Create a Test Suite

Group your most important tests into a test suite. For example, create a "Smoke Tests" suite with your critical path tests.

Create a Schedule

Create a schedule targeting your suite. For nightly regression testing, use 0 0 * * * (midnight daily). For continuous monitoring, use 0 * * * * (every hour).

Monitor Results

Check the Analytics dashboard to monitor trends. The scheduled run results feed into the same analytics as manual runs — you will see trends, pass rates, and flaky test detection all reflect the automated runs.

Manage Retention

Configure RETENTION_DAYS based on your disk space and data needs. 30 days is the default and works well for most projects. Reduce it if disk space is limited; increase it if you need longer historical data for trend analysis.