Skip to content

Commit

Permalink
fix: Add new configuration options, add example. (#197)
Browse files Browse the repository at this point in the history
* feat: add documenation for new configuration options

* feat: add advanced example for database connections limit

* fix: correct typo

* fix(review): align tables with other documentation
  • Loading branch information
hampuslavin authored Oct 30, 2024
1 parent bd2e4ba commit fbb5bee
Show file tree
Hide file tree
Showing 2 changed files with 47 additions and 27 deletions.
38 changes: 12 additions & 26 deletions docs/06-concepts/18-testing/02-the-basics.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@

The `withServerpod` helper provides a `sessionBuilder` that helps with setting up different scenarios for tests. To modify the session builder's properties, call its `copyWith` method. It takes the following named parameters:

|Property|Type|Default|Description|
|:-----|:-----|:---:|:-----|
|`authentication`|`AuthenticationOverride?`|`AuthenticationOverride.unauthenticated()`|See section [Setting authenticated state](#setting-authenticated-state).|
|`enableLogging`|`bool?`|`false`|Wether logging is turned on for the session.|
|Property|Description|Default|
|:---|:---|:---:|
|`authentication`|See section [Setting authenticated state](#setting-authenticated-state).|`AuthenticationOverride.unauthenticated()`|
|`enableLogging`|Whether logging is turned on for the session.|`false`|

The `copyWith` method creates a new unique session builder with the provided properties. This can then be used in endpoint calls (see section [Setting authenticated state](#setting-authenticated-state) for an example).

Expand Down Expand Up @@ -125,13 +125,15 @@ withServerpod(

The following optional configuration options are available to pass as a second argument to `withServerpod`:

|Property|Type|Default|
|Property|Description|Default|
|:-----|:-----|:---:|
|`rollbackDatabase`|`RollbackDatabase?`|`RollbackDatabase.afterEach`|
|`runMode`|`String?`|`ServerpodRunmode.test`|
|`enableSessionLogging`|`bool?`|`false`|
|`applyMigrations`|`bool?`|`true`|
|`testGroupTagsOverride`|`List<String>?`|`null`|
|`applyMigrations`|Whether pending migrations should be applied when starting Serverpod.|`true`|
|`enableSessionLogging`|Whether session logging should be enabled.|`false`|
|`rollbackDatabase`|Options for when to rollback the database during the test lifecycle (or disable it). See detailed description [here](#rollback-database-configuration).|`RollbackDatabase.afterEach`|
|`runMode`|The run mode that Serverpod should be running in.|`ServerpodRunmode.test`|
|`serverpodLoggingMode`|The logging mode used when creating Serverpod.|`ServerpodLoggingMode.normal`|
|`serverpodStartTimeout`|The timeout to use when starting Serverpod, which connects to the database among other things. Defaults to `Duration(seconds: 30)`.|`Duration(seconds: 30)`|
|`testGroupTagsOverride`|By default Serverpod test tools tags the `withServerpod` test group with `"integration"`. This is to provide a simple way to only run unit or integration tests. This property allows this tag to be overridden to something else. Defaults to `['integration']`.|`['integration']`|

### `rollbackDatabase` {#rollback-database-configuration}

Expand Down Expand Up @@ -224,22 +226,6 @@ await transactionFuture;

In production, the transaction call will throw if any database exception happened during its execution, _even_ if the exception was first caught inside the transaction. However, in the test tools this will not throw an exception due to how the nested transactions are emulated. Quelling exceptions like this is not best practise, but if the code under test does this setting `rollbackDatabase` to `RollbackDatabse.disabled` will ensure the code behaves like in production.

### `runMode`

The run mode that Serverpod should be running in. Defaults to `test`.

### `enableSessionLogging`

Wether session logging should be enabled. Defaults to `false`.

### `applyMigrations`

Wether pending migrations should be applied when starting Serverpod. Defaults to `true`.

### `testGroupTagsOverride` {#test-group-tags-override-configuration}

By default Serverpod test tools tags the `withServerpod` test group with `"integration"`. This is to provide a simple way to only run unit or integration tests. This property allows this tag to be overridden to something else. Defaults to `null` (i.e. no override).

## Test exceptions

The following exceptions are exported from the generated test tools file and can be thrown by the test tools in various scenarios, see below.
Expand Down
36 changes: 35 additions & 1 deletion docs/06-concepts/18-testing/03-advanced-examples.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ dart test -t integration
dart test -x integration
```

To change the name of this tag, see the [`testGroupTagsOverride`](the-basics#test-group-tags-override-configuration) configuration option.
To change the name of this tag, see the [`testGroupTagsOverride`](the-basics#configuration) configuration option.

## Test business logic that depends on `Session`

Expand Down Expand Up @@ -113,3 +113,37 @@ withServerpod('Given CommunicationExampleEndpoint', (sessionBuilder, endpoints)
});
});
```

## Optimising number of database connections

By default, Dart's test runner runs tests concurrently. The number of concurrent tests depends on the running hosts' available CPU cores. If the host has a lot of cores it could trigger a case where the number of connections to the database exceeeds the maximum connections limit set for the database, which will cause tests to fail.

Each `withServerpod` call will lazily create its own Serverpod instance which will connect to the database. Specifically, the code that causes the Serverpod instance to be created is `sessionBuilder.build()`, which happens at the latest in an endpoint call if not called by the test before.

If a test needs a session before the endpoint call (e.g. to seed the database), `sessionBuilder.build()` has to be called which then triggers a database connection attempt.

If the max connection limit is hit, there are two options:

- Raise the max connections limit on the database.
- Build out the session in `setUp`/`setUpAll` instead of the top level scope:

```dart
withServerpod('Given example test', (sessionBuilder, endpoints) {
// Instead of this
var session = sessionBuilder.build();
// Do this to postpone connecting to the database until the test group is running
late Session session;
setUpAll(() {
session = sessionBuilder.build();
});
// ...
});
```

:::info

This case should be rare and the above example is not a recommended best practice unless this problem is anticipated, or it has started happening.

:::

0 comments on commit fbb5bee

Please sign in to comment.