Skip to content

Commit

Permalink
Overhaul tests to run in parallel and use template database (#2205)
Browse files Browse the repository at this point in the history
  • Loading branch information
benjie authored Oct 4, 2024
2 parents 697cfad + 23aeb2f commit 44ca3da
Show file tree
Hide file tree
Showing 23 changed files with 240 additions and 218 deletions.
15 changes: 4 additions & 11 deletions .github/workflows/test-base.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,23 +22,18 @@ on:
type: string
default: ""
required: false
exportSchema:
description: Optional mode for graphile-export
type: string
default: ""
required: false

jobs:
build:
runs-on: ubuntu-latest

env:
CI: true
JEST_MAX_WORKERS: 4
PGUSER: postgres
PGPASSWORD: postgres
PGHOST: localhost
PGVERSION: ${{ matrix.postgres-version}}
ROOT_DATABASE_URL: postgres://postgres:postgres@localhost:5432/postgres
TEST_DATABASE_URL: postgres://postgres:postgres@localhost:5432/graphileengine_test
TEST_PG_URL: postgres://postgres:postgres@localhost:5432/postgraphile_test
LDS_TEST_DATABASE_URL: postgres://postgres:postgres@localhost:5432/lds_test
TEST_SIMPLIFY_DATABASE_URL: postgres://postgres:postgres@localhost:5432/pg_simplify_inflectors
TERM: xterm
FORCE_COLOR: 1
Expand Down Expand Up @@ -105,8 +100,6 @@ jobs:
run prepack

- name: "Test Project"
env:
EXPORT_SCHEMA: ${{ inputs.exportSchema }}
run:
yarn run pretest && yarn workspaces foreach -vp --jobs 2 --from '${{
inputs.package }}' run ${{ inputs.testcommand }} ${{ inputs.args }}
84 changes: 12 additions & 72 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,100 +12,40 @@ jobs:
testcommand: "test"
args: "--ci"

postgraphile_queries_v4:
name: PostGraphile v4 queries tests
postgraphile_jest:
name: PostGraphile jest tests
uses: ./.github/workflows/test-base.yml
with:
prepackPackages: "{pg-sql2,tamedevil,postgraphile}"
package: "postgraphile"
testcommand: "test:operations:v4"
testcommand: "test:jest"
args: "--ci"

postgraphile_queries_v4_export_typeDefs:
name: PostGraphile v4 queries tests (exported as typeDefs)
postgraphile_schema_exports:
name: PostGraphile schema export tests
uses: ./.github/workflows/test-base.yml
with:
prepackPackages: "{pg-sql2,tamedevil,postgraphile}"
package: "postgraphile"
testcommand: "test:operations:v4"
testcommand: "test:schema-exports"
args: "--ci"
exportSchema: "typeDefs"

postgraphile_queries_v4_export_graphqljs:
name: PostGraphile v4 queries tests (exported as graphql-js)
postgraphile_export_typeDefs:
name: PostGraphile tests (exported as typeDefs)
uses: ./.github/workflows/test-base.yml
with:
prepackPackages: "{pg-sql2,tamedevil,postgraphile}"
package: "postgraphile"
testcommand: "test:operations:v4"
testcommand: "test:operations-exports:typeDefs"
args: "--ci"
exportSchema: "graphql-js"

postgraphile_queries_polymorphic:
name: PostGraphile polymorphic query tests
postgraphile_export_graphqljs:
name: PostGraphile tests (exported as graphql-js)
uses: ./.github/workflows/test-base.yml
with:
prepackPackages: "{pg-sql2,tamedevil,postgraphile}"
package: "postgraphile"
testcommand: "test:operations:polymorphic_etc"
args: "--ci"

postgraphile_queries_polymorphic_export_typeDefs:
name: PostGraphile polymorphic query tests (exported as typeDefs)
uses: ./.github/workflows/test-base.yml
with:
prepackPackages: "{pg-sql2,tamedevil,postgraphile}"
package: "postgraphile"
testcommand: "test:operations:polymorphic_etc"
args: "--ci"
exportSchema: "typeDefs"

postgraphile_queries_polymorphic_export_graphqljs:
name: PostGraphile polymorphic query tests (exported as graphql-js)
uses: ./.github/workflows/test-base.yml
with:
prepackPackages: "{pg-sql2,tamedevil,postgraphile}"
package: "postgraphile"
testcommand: "test:operations:polymorphic_etc"
args: "--ci"
exportSchema: "graphql-js"

postgraphile_mutations:
name: PostGraphile mutation tests
uses: ./.github/workflows/test-base.yml
with:
prepackPackages: "{pg-sql2,tamedevil,postgraphile}"
package: "postgraphile"
testcommand: "test:operations:mutations"
args: "--ci"

postgraphile_mutations_export_typeDefs:
name: PostGraphile mutation tests (exported as typeDefs)
uses: ./.github/workflows/test-base.yml
with:
prepackPackages: "{pg-sql2,tamedevil,postgraphile}"
package: "postgraphile"
testcommand: "test:operations:mutations"
args: "--ci"
exportSchema: "typeDefs"

postgraphile_mutations_export_graphqljs:
name: PostGraphile mutation tests (exported as graphql-js)
uses: ./.github/workflows/test-base.yml
with:
prepackPackages: "{pg-sql2,tamedevil,postgraphile}"
package: "postgraphile"
testcommand: "test:operations:mutations"
args: "--ci"
exportSchema: "graphql-js"

postgraphile_schemas:
name: PostGraphile schema tests
uses: ./.github/workflows/test-base.yml
with:
prepackPackages: "{pg-sql2,tamedevil,postgraphile}"
package: "postgraphile"
testcommand: "test:schema"
testcommand: "test:operations-exports:graphql-js"
args: "--ci"

small_packages:
Expand Down
14 changes: 3 additions & 11 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,18 +28,10 @@ yarn watch # or 'yarn build'
**TODO:** check the following instructions work on a clean checkout.

We assume you have a local PostgreSQL server running in "trust" authentication
mode. Other options may or may not work.
mode. Other options may or may not work - you may need to set `PGHOST`,
`PGUSER`, `PGPASSWORD` and/or similar config variables.

First, create a database for running the tests: `createdb graphile_graphql_test`

Then tell our system this is the database you're using (you'll need to do this
each time you run the tests in a new terminal):

```bash
export TEST_DATABASE_URL="postgres:///graphile_graphql_test"
```

Then run the tests with `yarn test`
Run the tests with `yarn test`

If the above succeeds, you're good to go! If not, please try again after running
`yarn install --force` and always feel free to reach out via
Expand Down
14 changes: 11 additions & 3 deletions grafast/dataplan-pg/__tests__/helpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,11 @@ import { PgSubscriber } from "../src/adaptors/pg.js";
import { makeExampleSchema } from "../src/examples/exampleSchema.js";
//import prettier from "prettier";
import type { PgClientQuery } from "../src/index.js";
import { withTestWithPgClient } from "./sharedHelpers.js";
import {
createTestDatabase,
dropTestDatabase,
withTestWithPgClient,
} from "./sharedHelpers.js";

/**
* We go beyond what Jest snapshots allow; so we have to manage it ourselves.
Expand Down Expand Up @@ -87,12 +91,15 @@ let optimizedSchema!: GraphQLSchema;
let deoptimizedSchema!: GraphQLSchema;
/** Postgres pool */
let testPool!: Pool;
let connectionString = "";
let databaseName = "";

beforeAll(() => {
beforeAll(async () => {
optimizedSchema = makeExampleSchema();
deoptimizedSchema = makeExampleSchema({ deoptimize: true });
({ connectionString, databaseName } = await createTestDatabase());
testPool = new Pool({
connectionString: process.env.TEST_DATABASE_URL || "graphile_grafast",
connectionString,
});
testPool.on("connect", (client) => {
client.query(`set TimeZone to 'UTC'`);
Expand All @@ -110,6 +117,7 @@ afterAll(async () => {
}
testPool = null as any;
optimizedSchema = deoptimizedSchema = null as any;
await dropTestDatabase(databaseName);
});

async function resetSequences() {
Expand Down
53 changes: 53 additions & 0 deletions grafast/dataplan-pg/__tests__/sharedHelpers.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// Shared with postgraphile

import { randomBytes } from "crypto";
import type { Pool } from "pg";
import { Client } from "pg";

import type { PgClientQuery, WithPgClient } from "../src";
import { createWithPgClient } from "../src/adaptors/pg.js";
Expand Down Expand Up @@ -147,3 +149,54 @@ export async function withTestWithPgClient<T>(
poolClient.release();
}
}

const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

async function runSqlAsRoot(sql: string, maxAttempts = 1) {
let error: Error | undefined;
for (let attempts = 0; attempts < maxAttempts; attempts++) {
if (attempts > 0) {
// Randomize to avoid thundering herd
await sleep((0.5 + Math.random()) * attempts * 200);
}
try {
const rootClient = new Client(
`postgres:///${process.env.OWNER_DATABASE ?? "postgres"}`,
);
await rootClient.connect();
await rootClient.query(sql);
await rootClient.end();
return;
} catch (e) {
error = e;
}
}
throw error ?? new Error("Failed to run SQL as root");
}

export async function createTestDatabase() {
const databaseName = `gctestdb_${randomBytes(8).toString("hex")}`;

await runSqlAsRoot(
`create database ${databaseName} with owner graphilecrystaltest template = graphilecrystaltest_template;`,
5,
);

const host = process.env.PGHOST ?? "localhost";

const connectionString = host.includes("/")
? `socket://graphilecrystaltest:test@${host}?db=${encodeURIComponent(
databaseName,
)}`
: `postgres://graphilecrystaltest:test@${host}/${databaseName}`;
return { databaseName, connectionString };
}

export async function dropTestDatabase(databaseName: string) {
if (!databaseName) return;
try {
await runSqlAsRoot(`drop database ${databaseName};`, 2);
} catch {
// Noop
}
}
3 changes: 1 addition & 2 deletions grafast/dataplan-pg/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,7 @@
},
"scripts": {
"update-schema": "ts-node ./src/examples/exampleSchema.ts",
"test:install-schema": "psql -X1v ON_ERROR_STOP=1 -f __tests__/schema.sql -f __tests__/sequence_reset.sql \"${TEST_DATABASE_URL:-graphile_crystal}\"",
"test": "GRAPHILE_ENV=test yarn test:install-schema && jest -i",
"test": "GRAPHILE_ENV=test jest",
"posttest": "yarn test:exportSchema:graphql-js && yarn test:exportSchema:typeDefs",
"test:exportSchema:graphql-js": "ts-node ./scripts/exportExampleSchema.ts graphql-js && node ./scripts/runExampleSchema.mjs",
"test:exportSchema:typeDefs": "ts-node ./scripts/exportExampleSchema.ts typeDefs && node ./scripts/runExampleSchema.mjs",
Expand Down
9 changes: 7 additions & 2 deletions grafast/dataplan-pg/scripts/runExampleSchema.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,13 @@ import JSON5 from "json5";

import { schema } from "./exampleSchemaExport.mjs";

const connectionString =
process.env.TEST_DATABASE_URL || "postgres:///graphile_crystal";
const databaseName = "graphilecrystaltest";
const host = process.env.PGHOST ?? "localhost";
const connectionString = host.includes("/")
? `socket://graphilecrystaltest:test@${host}?db=${encodeURIComponent(
databaseName,
)}`
: `postgres://graphilecrystaltest:test@${host}/${databaseName}`;
const pgService = makePgService({ connectionString });
const preset = {
plugins: [PgContextPlugin],
Expand Down
2 changes: 1 addition & 1 deletion grafast/dataplan-pg/serve-example-schema.js
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ const { createWithPgClient } = require("./dist/adaptors/pg");

const schema = makeExampleSchema();
const withPgClient = createWithPgClient({
connectionString: process.env.TEST_DATABASE_URL || "graphile_grafast",
connectionString: "postgres:///graphilecrystaltest",
});
const serv = grafserv({
preset: { grafast: { context: { withPgClient }, explain: true } },
Expand Down
2 changes: 1 addition & 1 deletion graphile-build/graphile-build-pg/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
}
},
"scripts": {
"test": "jest -i",
"test": "jest",
"prepack": "tsc -b && cp src/.npmignore dist/.npmignore"
},
"repository": {
Expand Down
22 changes: 19 additions & 3 deletions graphile-build/graphile-utils/__tests__/RegisterUserPlugin.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,26 +6,42 @@ import pg from "pg";
import { PostGraphileAmberPreset } from "postgraphile/presets/amber";
import { makeV4Preset } from "postgraphile/presets/v4";

import {
createTestDatabase,
dropTestDatabase,
} from "../../../grafast/dataplan-pg/__tests__/sharedHelpers.js";
import { RegisterUserPlugin } from "./RegisterUserPlugin.js";

let pgPool: Pool | null = null;
let connectionString = "";
let databaseName = "";

beforeAll(async () => {
({ connectionString, databaseName } = await createTestDatabase());
pgPool = new pg.Pool({
connectionString: process.env.TEST_DATABASE_URL,
connectionString,
});
pgPool.on("connect", (client) => {
client.on("error", () => {});
client.query(`set TimeZone to '+04:00'`).catch(() => {});
});
pgPool.on("error", (e) => {
console.error("Pool error:", e);
});

await pgPool.query(`\
delete from graphile_utils_2.user_emails;
delete from graphile_utils_2.users;
alter sequence graphile_utils_2.users_id_seq restart with 1;
`);
});

afterAll(() => {
afterAll(async () => {
if (pgPool) {
pgPool.end();
await pgPool.end();
pgPool = null;
}
await dropTestDatabase(databaseName);
});

it("supports scalars", async () => {
Expand Down
Loading

0 comments on commit 44ca3da

Please sign in to comment.