+ Have an existing project? Follow these steps first!
+
+For existing non-Mini projects, a few extra things need to be done:
+1. Add the `server_test_tools_path` key to `config/generator.yaml`. Without this key, the test tools file is not generated. The default location for the generated file is `integration_test/test_tools/serverpod_test_tools.dart`, but this can be set to any path (though should be outside of `lib` as per Dart's test conventions).
+
+2. New projects now come with a test profile in `docker-compose.yaml`. This is not strictly mandatory, but is recommended to ensure that the testing state is never polluted. Add the snippet below to the `docker-compose.yaml` file in the server directory:
+
+```yaml
+# Test services
+postgres_test:
+ image: postgres:16.3
+ ports:
+ - '9090:5432'
+ environment:
+ POSTGRES_USER: postgres_test
+ POSTGRES_DB: projectname_test
+ POSTGRES_PASSWORD: ""
+ volumes:
+ - projectname_data:/var/lib/postgresql/data
+ profiles:
+ - '' # Default profile
+ - test
+redis_test:
+ image: redis:6.2.6
+ ports:
+ - '9091:6379'
+ command: redis-server --requirepass ""
+ environment:
+ - REDIS_REPLICATION_MODE=master
+ profiles:
+ - '' # Default profile
+ - test
+```
+
+
+Or copy the complete file here.
+
+
+```yaml
+services:
+ # Development services
+ postgres:
+ image: postgres:16.3
+ ports:
+ - '8090:5432'
+ environment:
+ POSTGRES_USER: postgres
+ POSTGRES_DB: projectname
+ POSTGRES_PASSWORD: ""
+ volumes:
+ - projectname_data:/var/lib/postgresql/data
+ profiles:
+ - '' # Default profile
+ - dev
+ redis:
+ image: redis:6.2.6
+ ports:
+ - '8091:6379'
+ command: redis-server --requirepass ""
+ environment:
+ - REDIS_REPLICATION_MODE=master
+ profiles:
+ - '' # Default profile
+ - dev
+
+ # Test services
+ postgres_test:
+ image: postgres:16.3
+ ports:
+ - '9090:5432'
+ environment:
+ POSTGRES_USER: postgres_test
+ POSTGRES_DB: projectname_test
+ POSTGRES_PASSWORD: ""
+ volumes:
+ - projectname_data:/var/lib/postgresql/data
+ profiles:
+ - '' # Default profile
+ - test
+ redis_test:
+ image: redis:6.2.6
+ ports:
+ - '9091:6379'
+ command: redis-server --requirepass ""
+ environment:
+ - REDIS_REPLICATION_MODE=master
+ profiles:
+ - '' # Default profile
+ - test
+
+volumes:
+ projectname_data:
+```
+
+
+
+3. Create a `test.yaml` file and add it to the `config` directory:
+
+```yaml
+# This is the configuration file for your local test environment. By
+# default, it runs a single server on port 8090. To set up your server, you will
+# need to add the name of the database you are connecting to and the user name.
+# The password for the database is stored in the config/passwords.yaml.
+#
+# When running your server locally, the server ports are the same as the public
+# facing ports.
+
+# Configuration for the main API test server.
+apiServer:
+ port: 9080
+ publicHost: localhost
+ publicPort: 9080
+ publicScheme: http
+
+# Configuration for the Insights test server.
+insightsServer:
+ port: 9081
+ publicHost: localhost
+ publicPort: 9081
+ publicScheme: http
+
+# Configuration for the web test server.
+webServer:
+ port: 9082
+ publicHost: localhost
+ publicPort: 9082
+ publicScheme: http
+
+# This is the database setup for your test server.
+database:
+ host: localhost
+ port: 9090
+ name: projectname_test
+ user: postgres
+
+# This is the setup for your Redis test instance.
+redis:
+ enabled: false
+ host: localhost
+ port: 9091
+```
+
+4. Add this entry to `config/passwords.yaml`
+
+```yaml
+test:
+ database: ''
+ redis: ''
+```
+
+That's it, the project setup should be ready to start using the test tools!
+
+
+
+Go to the server directory and generate the test tools by running `serverpod generate --experimental-features testTools`. The default location for the generated file is `integration_test/test_tools/serverpod_test_tools.dart`. The folder name `integration_test` is chosen to differentiate from unit tests (see the [best practises section](best-practises#unit-and-integration-tests) for more information on this).
+
+The generated file exports a `withServerpod` helper that enables you to call your endpoints directly like regular functions:
+
+```dart
+// Import the generated file, it contains everything you need.
+import 'test_tools/serverpod_test_tools.dart';
+
+void main() {
+ withServerpod('Given Example endpoint', (sessionBuilder, endpoints) {
+ test('when calling `hello` then should return greeting', () async {
+ final greeting =
+ await endpoints.example.hello(sessionBuilder, 'Michael');
+ expect(greeting, 'Hello, Michael!');
+ });
+ });
+}
+```
+
+A few things to note from the above example:
+
+- The test tools should be imported from the generated test tools file and not the `serverpod_test` package.
+- The `withServerpod` callback takes two parameters: `sessionBuilder` and `endpoints`.
+ - `sessionBuilder` is used to build a `session` object that represents the server state during an endpoint call and is used to set up scenarios.
+ - `endpoints` contains all your Serverpod endpoints and lets you call them.
+
+:::tip
+
+The location of the test tools can be changed by changing the `server_test_tools_path` key in `config/generator.yaml`. If you remove the `server_test_tools_path` key, the test tools will stop being generated.
+
+:::
+
+Before the test can be run the Postgres and Redis also have to be started:
+
+```bash
+docker-compose up --build --detach
+```
+
+By default this starts up both the `development` and `test` profiles. To only start one profile, simply add `--profile test` to the command.
+
+Now the test is ready to be run:
+
+```bash
+dart test integration_test
+```
+
+Happy testing!
diff --git a/docs/06-concepts/18-testing/02-the-basics.md b/docs/06-concepts/18-testing/02-the-basics.md
new file mode 100644
index 00000000..ddd24ba3
--- /dev/null
+++ b/docs/06-concepts/18-testing/02-the-basics.md
@@ -0,0 +1,248 @@
+# The basics
+
+## Set up a test scenario
+
+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.|
+
+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).
+
+To build out a `Session` (to use for [database calls](#seeding-the-database) or [pass on to functions](advanced-examples#test-business-logic-that-depends-on-session)), simply call the `build` method:
+
+```dart
+Session session = sessionBuilder.build();
+```
+
+Given the properties set on the session builder through the `copyWith` method, this returns a Serverpod `Session` that has the corresponding state.
+
+### Setting authenticated state
+
+To control the authenticated state of the session, the `AuthenticationOverride` class can be used.
+
+To create an unauthenticated override (this is the default value for new sessions), call `AuthenticationOverride unauthenticated()`:
+
+```dart
+static AuthenticationOverride unauthenticated();
+```
+
+To create an authenticated override, call `AuthenticationOverride.authenticationInfo(...)`:
+
+```dart
+static AuthenticationOverride authenticationInfo(
+ int userId,
+ Set