-
-
Notifications
You must be signed in to change notification settings - Fork 327
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Italian Testing, Transaction and Migration translation (#971)
- Loading branch information
1 parent
d2b06a8
commit a1f70a8
Showing
4 changed files
with
267 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,99 @@ | ||
# Test | ||
|
||
Vapor include un modulo chiamato `XCTVapor` che fornisce supporto per i test utilizzando `XCTest`. Questo supporto al testing ti permette di inviare richieste di test alla tua applicazione Vapor programmaticamente o attraverso un server HTTP. | ||
|
||
## Inizio | ||
|
||
Per usare il modulo `XCTVapor`, assicurati sia stato aggiunto ai target dei test del tuo pacchetto. | ||
|
||
```swift | ||
let package = Package( | ||
... | ||
dependencies: [ | ||
.package(url: "https://github.com/vapor/vapor.git", from: "4.0.0") | ||
], | ||
targets: [ | ||
... | ||
.testTarget(name: "AppTests", dependencies: [ | ||
.target(name: "App"), | ||
.product(name: "XCTVapor", package: "vapor"), | ||
]) | ||
] | ||
) | ||
``` | ||
|
||
Dopodiché, aggiungi `import XCTVapor` in cima ai file dei tuoi test. Per scrivere dei test, crea classi che estendono `XCTestCase`. | ||
|
||
```swift | ||
import XCTVapor | ||
|
||
final class MyTests: XCTestCase { | ||
func testStub() throws { | ||
// Esegui il test qui. | ||
} | ||
} | ||
``` | ||
|
||
Ciascuna funzione che inizia con `test` sarà eseguita automaticamente quando la tua app viene testata. | ||
|
||
### Eseguire i Test | ||
|
||
Per eseguire i test su Xcode, usa `cmd+u` con `-Package` come schema. Usa `swift test --enable-test-discovery` per testare attraverso l'interfaccia a riga di comando. | ||
|
||
## Application Testabile | ||
|
||
Inizializza un'instanza di `Application` usando l'ambiente `.testing`. Devi chiamare `app.shutdown()` prima che questa applicazione si deinizializzi. | ||
Lo shutdown è necessario per aiutare a rilasciare le risorse che l'app ha reclamato, in particolare è importante rilasciare i thread richiesti all'avvio dell'applicazione. Se non chiami `shutdown()` sull'app dopo ogni test, potresti vedere la tua suite di test crashare con un fallimento di precondizione quando alloca thread per una nuova istanza di `Application`. | ||
|
||
```swift | ||
let app = Application(.testing) | ||
defer { app.shutdown() } | ||
try configure(app) | ||
``` | ||
|
||
Passa la `Application` al metodo `configure(_:)` del tuo pacchetto per applicare la tua configurazione. Qualsiasi configurazione relativa ai soli test può essere applicata successivamente. | ||
|
||
### Invia Richiesta | ||
|
||
Per inviare una richiesta di test alla tua applicazione, usa il metodo `test`. | ||
|
||
```swift | ||
try app.test(.GET, "ciao") { res in | ||
XCTAssertEqual(res.status, .ok) | ||
XCTAssertEqual(res.body.string, "Ciao, mondo!") | ||
} | ||
``` | ||
|
||
I primi due parametri sono il metodo HTTP e l'URL da interrogare. La chiusura successiva accetta la risposta HTTP che puoi verificare usando i metodi `XCTAssert`. | ||
|
||
Per richieste più complesse, puoi fornire una chiusura `beforeRequest` per modificare gli header o per codificare il contenuto. L'[API Content](../basics/content.md) di Vapor è disponibile sia sulla richiesta che sulla risposta di test. | ||
|
||
```swift | ||
try app.test(.POST, "promemoria", beforeRequest: { req in | ||
try req.content.encode(["titolo": "Test"]) | ||
}, afterResponse: { res in | ||
XCTAssertEqual(res.status, .created) | ||
let todo = try res.content.decode(Todo.self) | ||
XCTAssertEqual(todo.title, "Test") | ||
}) | ||
``` | ||
|
||
### Metodo Testable | ||
|
||
L'API di testing di Vapor supporta l'invio di richieste di test programmaticamente e attraverso un server HTTP attivo. Puoi specificare quale metodo vorresti usare utilizzando il metodo `testable`. | ||
|
||
```swift | ||
// Usa il testing programmatico. | ||
app.testable(method: .inMemory).test(...) | ||
|
||
// Esegui i test attraverso un server HTTP attivo. | ||
app.testable(method: .running).test(...) | ||
``` | ||
|
||
L'opzione `inMemory` è usata di default. | ||
|
||
L'opzione `running` supporta il passaggio di una porta specifica da utilizzare. Di default è usata la `8080`. | ||
|
||
```swift | ||
.running(port: 8123) | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,96 @@ | ||
# Migrazioni | ||
|
||
Le migrazioni sono come un sistema di controllo versione per il tuo database. Ogni migrazione definisce un cambiamento al database e come disfarlo. Utilizzando le migrazioni per applicare modifiche al database, stabilisci un approccio coeso, testabile, e condivisibile per evolvere nel tempo i tuoi database. | ||
|
||
```swift | ||
// Un esempio di migrazione. | ||
struct MyMigration: Migration { | ||
func prepare(on database: Database) -> EventLoopFuture<Void> { | ||
// Fai una modifica al database. | ||
} | ||
|
||
func revert(on database: Database) -> EventLoopFuture<Void> { | ||
// Disfai le modifiche fatte in `prepare`, se possibile. | ||
} | ||
} | ||
``` | ||
|
||
Se usi `async`/`await` devi implementare il protocollo `AsyncMigration`: | ||
|
||
```swift | ||
struct MyMigration: AsyncMigration { | ||
func prepare(on database: Database) async throws { | ||
// Fai una modifica al database. | ||
} | ||
|
||
func revert(on database: Database) async throws { | ||
// Disfai le modifiche fatte in `prepare`, se possibile. | ||
} | ||
} | ||
``` | ||
|
||
Il metodo `prepare` è dove fai le modifiche al `Database` fornito. Potrebbero essere modifiche allo schema del database come aggiungere o rimuovere una relazione o una collezione, attributo, o vincolo. Possono anche modificare il contenuto del database, come creare nuove istanze del modello, aggiornare valori di un attributo, o fare pulizia. | ||
|
||
Il metodo `revert` è dove disfai queste modifiche, se possibile. Essere in grado di disfare le migrazioni può rendere la prototipazione e il testing più facili. Forniscono anche un piano di backup se un deploy in produzione non va come pianificato. | ||
|
||
## Registra | ||
|
||
Le migrazioni vengono registrate alla tua applicazione usando `app.migrations`. | ||
|
||
```swift | ||
import Fluent | ||
import Vapor | ||
|
||
app.migrations.add(MyMigration()) | ||
``` | ||
|
||
Puoi aggiungere una migrazione a un database specifico usando il parametro `to`, altrimenti sarà utilizzato il database di default. | ||
|
||
```swift | ||
app.migrations.add(MyMigration(), to: .myDatabase) | ||
``` | ||
|
||
Le migrazioni dovrebbero essere listate in ordine di dipendenza. Per esempio, se `MigrationB` dipende da `MigrationA`, deve essere aggiunto a `app.migrations` per secondo. | ||
|
||
## Migra | ||
|
||
Per migrare il tuo database, esegui il comando `migrate`. | ||
|
||
```sh | ||
swift run App migrate | ||
``` | ||
|
||
Puoi anche eseguire questo [comando attraverso Xcode](../advanced/commands.md#xcode). Il comando di migrazione controllerà il database per vedere se sono state registrate nuove migrazioni dall'ultima volta in cui è stato eseguito. Se ci sono nuove migrazioni, chiederà una conferma prima di eseguirle. | ||
|
||
### Ripristinare | ||
|
||
Per disfare una migrazione sul tuo database, esegui `migrate` con la flag `--revert`. | ||
|
||
```sh | ||
swift run App migrate --revert | ||
``` | ||
|
||
Il comando controllerà il database per vedere quale gruppo di migrazioni è stato eseguito per ultimo e chiederà conferma prima di ripristinarle. | ||
|
||
### Migra Automaticamente | ||
|
||
Se vuoi che le migrazioni vengano eseguite automaticamente prima degli altri comandi, puoi passare la flag `--auto-migrate`. | ||
|
||
```sh | ||
swift run App serve --auto-migrate | ||
``` | ||
|
||
Puoi farlo anche programmaticamente. | ||
|
||
```swift | ||
try app.autoMigrate().wait() | ||
|
||
// oppure | ||
try await app.autoMigrate() | ||
``` | ||
|
||
Entrambe queste opzioni esistono anche per ripristinare: `--auto-revert` e `app.autoRevert()`. | ||
|
||
## Prossimi Passi | ||
|
||
Per avere più informazioni riguardo a cosa mettere dentro le tue migrazioni, consulta le guide per [costruire gli schemi](schema.md) e per [costruire le query](query.md). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
# Transazioni | ||
|
||
Le transazioni garantiscono che varie operazioni vengano eseguite con successo prima di effettuare l'aggiornamento dei dati sul tuo database. | ||
Una volta avviata una transazione, puoi procedere con le query Fluent come al solito, tuttavia i dati non verranno effettivamente salvati sul database fino al completamento della transazione. | ||
In caso di errore durante la transazione, che sia scaturito da te o dal sistema di gestione del database, le modifiche proposte non saranno applicate. | ||
|
||
Per eseguire una transazione, devi accedere a qualcosa che si può connettere al database. Questo solitamente è una richiesta HTTP. In questo caso, usa `req.db.transaction(_ :)`: | ||
```swift | ||
req.db.transaction { database in | ||
// usa il database | ||
} | ||
``` | ||
Una volta dentro la chiusura della transazione, devi usare il database fornito nel parametro della chiusura (chiamato `database` nell'esempio) per eseguire query. | ||
|
||
Quando questa chiusura ritorna con successo, la transazione sarà confermata. | ||
```swift | ||
var sun: Star = ... | ||
var sirius: Star = ... | ||
|
||
return req.db.transaction { database in | ||
return sun.save(on: database).flatMap { _ in | ||
return sirius.save(on: database) | ||
} | ||
} | ||
``` | ||
L'esempio qui sopra salverà `sun` e *dopo* `sirius` prima di completare la transazione. Se il salvataggio di una delle due `Star` fallisce, nessuna delle due verrà salvata. | ||
|
||
Quando la transazione è completa, il risultato può essere trasformato in una future diversa, per esempio in uno status HTTP per indicare il completamento come mostrato qui sotto: | ||
```swift | ||
return req.db.transaction { database in | ||
// usa il database e esegui la transazione | ||
}.transform(to: HTTPStatus.ok) | ||
``` | ||
|
||
## `async`/`await` | ||
|
||
Se usi `async`/`await` puoi ristrutturare il codice come segue: | ||
|
||
```swift | ||
try await req.db.transaction { database in | ||
try await sun.save(on: database) | ||
try await sirius.save(on: database) | ||
} | ||
return .ok | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters