Skip to content

Commit 11901be

Browse files
committed
XCTVapor from PR suggestions
1 parent 942f287 commit 11901be

File tree

1 file changed

+80
-12
lines changed

1 file changed

+80
-12
lines changed

docs/advanced/testing.md

+80-12
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,13 @@
11
# Testing
22

3+
## VaporTesting
4+
35
Vapor includes a module named `VaporTesting` that provides test helpers built on `Swift Testing`. These testing helpers allow you to send test requests to your Vapor application programmatically or running over an HTTP server.
46

5-
## Getting Started
7+
!!! note
8+
For newer projects or teams adopting Swift concurrency, `VaporTesting` is highly recommended due to its simplicity and integration with Vapor.
9+
10+
### Getting Started
611

712
To use the `VaporTesting` module, ensure it has been added to your package's test target.
813

@@ -49,11 +54,11 @@ To ensure your tests run in a serialized manner (e.g., when testing with a datab
4954
@Suite("App Tests with DB", .serialized)
5055
```
5156

52-
### Running Tests
57+
#### Running Tests
5358

5459
Use `cmd+u` with the `-Package` scheme selected to run tests in Xcode. Use `swift test --enable-test-discovery` to test via the CLI.
5560

56-
## Testable Application
61+
### Testable Application
5762

5863
Define a private method function `withApp` to streamline and standardize the setup and teardown for our tests. This method encapsulates the lifecycle management of the `Application` instance, ensuring that the application is properly initialized, configured, and shut down for each test.
5964

@@ -76,7 +81,7 @@ private func withApp(_ test: (Application) async throws -> ()) async throws {
7681

7782
Pass the `Application` to your package's `configure(_:)` method to apply your configuration. Then you test the application calling the `test()` method. Any test-only configurations can also be applied.
7883

79-
### Send Request
84+
#### Send Request
8085

8186
To send a test request to your application, use the `withApp` private method and inside use the `app.testing().test()` method:
8287

@@ -108,7 +113,7 @@ try await app.testing().test(.POST, "todos", beforeRequest: { req in
108113
})
109114
```
110115

111-
### Testing Method
116+
#### Testing Method
112117

113118
Vapor's testing API supports sending test requests programmatically and via a live HTTP server. You can specify which method you would like to use through the `testing` method.
114119

@@ -128,7 +133,7 @@ The `running` option supports passing a specific port to use. By default `8080`
128133
app.testing(method: .running(port: 8123)).test(...)
129134
```
130135

131-
### Database Integration Tests
136+
#### Database Integration Tests
132137

133138
Configure the database specifically for testing to ensure that your live database is never used during tests.
134139

@@ -161,11 +166,13 @@ private func withApp(_ test: (Application) async throws -> ()) async throws {
161166
}
162167
```
163168

164-
## Using XCTest
169+
## XCTVapor
170+
171+
Vapor includes a module named `XCTVapor` that provides test helpers built on `XCTest`. These testing helpers allow you to send test requests to your Vapor application programmatically or running over an HTTP server.
165172

166-
If you prefer XCTest over the Swift Testing framework, or if a project requires compatibility with a more traditional approach, XCTest is fully supported. Here’s how you can get started:
173+
### Getting Started
167174

168-
First ensure that the `XCTVapor` module has been added to your package's test target.
175+
To use the `XCTVapor` module, ensure it has been added to your package's test target.
169176

170177
```swift
171178
let package = Package(
@@ -183,7 +190,7 @@ let package = Package(
183190
)
184191
```
185192

186-
Then, add `import XCTVapor` at the top of your test files. Create classes extending `XCTestCase` to write tests cases.
193+
Then, add `import XCTVapor` at the top of your test files. Create classes extending `XCTestCase` to write test cases.
187194

188195
```swift
189196
import XCTVapor
@@ -195,5 +202,66 @@ final class MyTests: XCTestCase {
195202
}
196203
```
197204

198-
!!! note
199-
For newer projects or teams adopting Swift concurrency, `VaporTesting` is highly recommended due to its simplicity and integration with Vapor.
205+
Each function beginning with `test` will run automatically when your app is tested.
206+
207+
#### Running Tests
208+
209+
Use `cmd+u` with the `-Package` scheme selected to run tests in Xcode. Use `swift test --enable-test-discovery` to test via the CLI.
210+
211+
### Testable Application
212+
213+
Initialize an instance of `Application` using the `.testing` environment. You must call `app.shutdown()` before this application deinitializes.
214+
The shutdown is necessary to help release the resources that the app has claimed. In particular it is important to release the threads the application requests at startup. If you do not call `shutdown()` on the app after each unit test, you may find your test suite crash with a precondition failure when allocating threads for a new instance of `Application`.
215+
216+
```swift
217+
let app = Application(.testing)
218+
defer { app.shutdown() }
219+
try configure(app)
220+
```
221+
222+
Pass the `Application` to your package's `configure(_:)` method to apply your configuration. Any test-only configurations can be applied after.
223+
224+
#### Send Request
225+
226+
To send a test request to your application, use the `test` method.
227+
228+
```swift
229+
try app.test(.GET, "hello") { res in
230+
XCTAssertEqual(res.status, .ok)
231+
XCTAssertEqual(res.body.string, "Hello, world!")
232+
}
233+
```
234+
235+
The first two parameters are the HTTP method and URL to request. The trailing closure accepts the HTTP response which you can verify using `XCTAssert` methods.
236+
237+
For more complex requests, you can supply a `beforeRequest` closure to modify headers or encode content. Vapor's [Content API](../basics/content.md) is available on both the test request and response.
238+
239+
```swift
240+
try app.test(.POST, "todos", beforeRequest: { req in
241+
try req.content.encode(["title": "Test"])
242+
}, afterResponse: { res in
243+
XCTAssertEqual(res.status, .created)
244+
let todo = try res.content.decode(Todo.self)
245+
XCTAssertEqual(todo.title, "Test")
246+
})
247+
```
248+
249+
#### Testable Method
250+
251+
Vapor's testing API supports sending test requests programmatically and via a live HTTP server. You can specify which method you would like to use by using the `testable` method.
252+
253+
```swift
254+
// Use programmatic testing.
255+
app.testable(method: .inMemory).test(...)
256+
257+
// Run tests through a live HTTP server.
258+
app.testable(method: .running).test(...)
259+
```
260+
261+
The `inMemory` option is used by default.
262+
263+
The `running` option supports passing a specific port to use. By default `8080` is used.
264+
265+
```swift
266+
.running(port: 8123)
267+
```

0 commit comments

Comments
 (0)