Skip to content
Docs

Running Integration Tests with a Database in Edgenivo CI

In this tutorial, you'll run integration tests against a real Postgres database in Edgenivo CI. You'll use Turborepo's with key to start the database next to your tests, so both run in the same compute instance and Turborepo stops the database when your tests finish.

You'll configure:

  1. A task that runs Postgres in a Docker container.
  2. A test task that starts the database with with, waits until it's ready, and runs your tests.
  • Edgenivo CI enabled for your repository.
  • An app in your monorepo at apps/api that you want to test, with the package name api.
  • An empty package for the database at packages/db, with the package name db.
  1. Add a script that runs the official Postgres image to packages/db/package.json:

    packages/db/package.json
    {
      "name": "db",
      "private": true,
      "scripts": {
        "postgres": "docker run --rm --name ci-postgres -p 5432:5432 -e POSTGRES_PASSWORD=postgres postgres:17"
      }
    }

    Then mark the task as persistent, because it runs until something stops it:

    packages/db/turbo.json
    {
      "extends": ["//"],
      "tasks": {
        "postgres": {
          "persistent": true,
          "cache": false
        }
      }
    }

    Edgenivo CI starts Docker before your task runs, so the task can use docker run without any setup. To learn more, see Running containers in your tasks.

  2. Add a test:integration task to your app's turbo.json, and list the database task in with:

    apps/api/turbo.json
    {
      "extends": ["//"],
      "tasks": {
        "test:integration": {
          "with": ["db#postgres"],
          "tags": ["ci", "ci:cpus:4"]
        }
      }
    }
    • with starts db#postgres at the same time as test:integration, in the same compute instance. When the tests finish, Turborepo stops the database, and the container removes itself.
    • db#postgres doesn't need a ci tag. Edgenivo CI only runs it as part of test:integration.
    • ci:cpus:4 gives the database and your tests more CPUs than the default of 2, because they share the instance.
  3. Postgres takes a few seconds to start, and Docker might need to download the image first. Add a script that waits until Postgres accepts connections:

    apps/api/scripts/wait-for-postgres.sh
    #!/bin/sh
    set -eu
     
    for _ in $(seq 1 120); do
      if docker exec ci-postgres pg_isready -h 127.0.0.1 -U postgres >/dev/null 2>&1; then
        exit 0
      fi
      sleep 1
    done
     
    echo "Postgres didn't start within 120 seconds." >&2
    exit 1

    The -h 127.0.0.1 flag checks the TCP port that your tests connect to. Without it, pg_isready can report that Postgres is ready while the image is still initializing the database.

  4. Install a Postgres client in your app:

    npm i -D pg

    Then add a test that connects to the database:

    apps/api/test/database.test.js
    import assert from 'node:assert/strict';
    import { test } from 'node:test';
    import pg from 'pg';
     
    test('runs a query against Postgres', async () => {
      const client = new pg.Client({ connectionString: process.env.DATABASE_URL });
      await client.connect();
      try {
        const { rows } = await client.query('SELECT 1 + 1 AS sum');
        assert.equal(rows[0].sum, 2);
      } finally {
        await client.end();
      }
    });

    Add the test:integration script to your app's package.json. It waits for the database, then runs the tests with the database's connection string:

    apps/api/package.json
    {
      "name": "api",
      "type": "module",
      "scripts": {
        "test:integration": "sh scripts/wait-for-postgres.sh && DATABASE_URL=postgres://postgres:postgres@localhost:5432/postgres node --test"
      }
    }

    The example sets DATABASE_URL inside the script because the database only exists for this task. To use a value from Edgenivo CI instead, see Make variables available to your tasks.

  5. Commit the files and push them to GitHub. When your changes affect api, Edgenivo CI runs api#test:integration, which starts Postgres, runs your tests, and stops the database.

    You can run the same task locally with Docker installed:

    terminal
    turbo run api#test:integration
Last updated October 28, 2026

Was this helpful?

supported.