Komposition og testning af features
Kombinér reducers, og test udtømmende.
Komposition og testning af features er en gratis Swift Academy-lektion på CoddyKit. Dette er lektion 4 af 4. Du kan læse alle 3 lektioner i dette læringsspor gratis i deres fulde længde — derefter låser CoddyKit PRO alle lektioner op samt praktiske øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Den er en del af læringsforløbet i Swift Academy, og dine fremskridt synkroniseres på tværs af nettet og CoddyKit-appen. Swift Academy-kurset indeholder 4 lektioner i alt.
Sammensætning af funktioner
Rigtige apps er bygget af mange små funktioner. TCA lader en overordnet funktion indeholde underfunktioner, så hver funktion kan fokusere på sit eget område, hvorefter de kan samles til en større helhed. Værktøjerne til dette er Scope samt indlejring af underfunktioners tilstand og handlinger.
Det er sammensætningen, der har givet The Composable Architecture sit navn.
import ComposableArchitecture
// A parent feature embeds child State and Action,
// then uses Scope to run the child's reducer.Indlejring af underfunktionens tilstand
Den overordnede funktions State indeholder underfunktionens tilstand som en egenskab. Den overordnede funktions Action-enum har en case, der omslutter underfunktionens handlinger. Denne indlejring afspejler, hvordan brugergrænsefladen er indlejret.
Her indeholder en overordnet funktion en tæller som underfunktion.
import ComposableArchitecture
@Reducer
struct AppFeature {
@ObservableState
struct State: Equatable {
var counter = CounterFeature.State()
}
enum Action {
case counter(CounterFeature.Action)
}
var body: some ReducerOf<Self> { EmptyReducer() }
}Afgrænsning til underfunktionen
Scope kører underfunktionens reducer på den del af den overordnede tilstand og handling, der hører til underfunktionen. Du angiver en key path til tilstanden og en case path til handlingen og derefter underfunktionens reducer.
Det kobler underfunktionen ind i den overordnede funktions opdateringssløjfe.
import ComposableArchitecture
var body: some ReducerOf<Self> {
Scope(state: \.counter, action: \.counter) {
CounterFeature()
}
Reduce { state, action in
// parent-specific logic here
return .none
}
}Kombination af flere reducere
En funktions body kan indeholde flere reducere; TCA kører dem i rækkefølge for hver handling. Det lader dig placere en eller flere Scope ved siden af den overordnede funktions egen Reduce.
Her fungerer to underfunktioner sammen med logikken i den overordnede funktion.
import ComposableArchitecture
var body: some ReducerOf<Self> {
Scope(state: \.profile, action: \.profile) { ProfileFeature() }
Scope(state: \.settings, action: \.settings) { SettingsFeature() }
Reduce { state, action in
return .none
}
}Afgrænsning af storet til underordnede visninger
På visningssiden skal en underordnet visning have en store, der er specialiseret til underfunktionen. Den overordnede visning afleder den med store.scope ved at kortlægge til underfunktionens tilstand og handling.
Her giver den overordnede visning en afgrænset store videre til tællervisningen.
import ComposableArchitecture
import SwiftUI
struct AppView: View {
let store: StoreOf<AppFeature>
var body: some View {
CounterView(
store: store.scope(state: \.counter, action: \.counter)
)
}
}Introduktion til TestStore
TestStore lader dig kontrollere præcis, hvordan en funktion opfører sig. Du sender handlinger og beskriver, hvordan tilstanden skal ændre sig; hvis virkeligheden afviger, fejler testen. Denne udtømmende kontrol fanger subtile regressioner.
Du opretter den som en normal store med den indledende tilstand og reduceren.
import ComposableArchitecture
import XCTest
func testIncrement() async {
let store = await TestStore(initialState: CounterFeature.State()) {
CounterFeature()
}
}Kontrol af tilstandsændringer
Når du sender en handling til en TestStore, giver du en closure, der beskriver den forventede ændring. Testen består kun, hvis tilstanden ændrer sig præcis på denne måde.
Her skal en forøgelse hæve count fra 0 til 1.
import ComposableArchitecture
import XCTest
func testIncrement() async {
let store = await TestStore(initialState: CounterFeature.State()) {
CounterFeature()
}
await store.send(.incrementTapped) {
$0.count = 1
}
}Udtømmende kontrol
Som standard er en TestStore udtømmende: du skal tage højde for alle tilstandsændringer og alle handlinger, som en effekt sender tilbage. Ubehandlede ændringer får testen til at fejle, så dine kontroller forbliver retvisende.
Du kan lempe dette med store.exhaustivity = .off i fokuserede test.
import ComposableArchitecture
// Exhaustive (default): every change must be asserted.
// Relax when you only care about part of the behavior:
store.exhaustivity = .offModtagelse af effekthandlinger
Når en effekt sender en handling tilbage, skal testen receive den og kontrollere den resulterende tilstand. Det beviser, at det asynkrone forløb fungerer fra start til slut.
Her udløser en genindlæsning et svar, som testen afventer og kontrollerer.
import ComposableArchitecture
import XCTest
func testReload() async {
let store = await TestStore(initialState: NumberFeature.State()) {
NumberFeature()
}
await store.send(.reload)
await store.receive(\.response) {
$0.value = 42
}
}Tilsidesættelse af afhængigheder i test
For at gøre effekter deterministiske tilsidesætter du afhængigheder, når du opretter TestStore. Angiv en falsk klient eller et testur, så resultaterne bliver forudsigelige.
Her erstattes tal-klienten med en, der altid returnerer 42.
import ComposableArchitecture
import XCTest
func testReload() async {
let store = await TestStore(initialState: NumberFeature.State()) {
NumberFeature()
} withDependencies: {
$0.numberClient.fetch = { 42 }
}
await store.send(.reload)
await store.receive(\.response) { $0.value = 42 }
}Test af sammensatte funktioner
Fordi sammensætning indlejrer tilstand og handlinger, tester du en overordnet funktion ved at sende underfunktionens handlinger pakket ind i den overordnede case. De samme udtømmende kontroller gælder og bekræfter hele træet.
Her modtager en overordnet funktion en tællerforøgelse gennem sit scope.
import ComposableArchitecture
import XCTest
func testChildInParent() async {
let store = await TestStore(initialState: AppFeature.State()) {
AppFeature()
}
await store.send(.counter(.incrementTapped)) {
$0.counter.count = 1
}
}Hurtigt tjek: TestStore-adfærd
Husk, hvad en TestStore som standard kræver af dine kontroller.
Opsamling: sammensætning og test
Du har gennemført TCA-værktøjskassen:
Scopekører en underfunktions reducer på en del af den overordnede tilstand og handling, og flere reducere kan kombineres i énbody.store.scopegiver en underordnet visning sin egen specialiserede store.TestStorekontrollerer præcise tilstandsændringer, når dusend-er handlinger.- Den er som standard udtømmende og bruger
receivetil effektdrevne handlinger. - Tilsidesæt afhængigheder med
withDependenciesfor at få deterministiske test.
Du kan nu bygge, sammensætte og grundigt teste funktioner med The Composable Architecture.
import ComposableArchitecture
// Recap: Scope to compose, TestStore to verify.
// Exhaustive assertions + injected fakes = confidence.Lær Swift med en AI-underviser — gratis
Skriv og kør rigtig kode i din browser, få øjeblikkelig hjælp fra en AI-underviser døgnet rundt, og fortsæt, hvor du slap, på web eller i appen.
- Kurser
- 122
- Lektioner
- 409
Ofte stillede spørgsmål
Er lektionen “Komposition og testning af features” gratis?
Ja — alle 3 lektioner i læringssporet Swift Academy, inklusive “Komposition og testning af features”, kan læses gratis i deres fulde længde her på webstedet. Derefter låser CoddyKit PRO alle lektioner op samt interaktive øvelser med en indbygget kodeeditor og en AI-underviser døgnet rundt. Swift Academy-kurset indeholder 4 lektioner i alt.
Hvad lærer jeg i “Komposition og testning af features”?
Kombinér reducers, og test udtømmende. Du øver dig i Swift Academy med praktisk kode, som du kører direkte i browseren, og en AI-vejleder døgnet rundt besvarer dine spørgsmål, mens du arbejder dig gennem lektionen.
Skal jeg have erfaring for at begynde på Swift Academy?
Der kræves ingen tidligere erfaring. Swift Academy på CoddyKit er tilrettelagt for både begyndere og øvede, så du kan starte her eller fra begyndelsen og lære i dit eget tempo. Dette er lektion 4 af 4.
Hvor lang tid tager lektionen “Komposition og testning af features”?
De fleste CoddyKit-lektioner tager cirka 5–10 minutter. Hver lektion er kort og interaktiv, så du gør løbende fremskridt og kan fortsætte, hvor du slap – på både web og app.
Kan jeg skrive og køre kode i denne Swift Academy-lektion?
Ja. Alle Swift Academy-lektioner har en indbygget kodeeditor, så du kan skrive og køre rigtig kode direkte i din browser og få øjeblikkelig feedback fra AI – uden lokal opsætning.
Alle lektioner i dette kursus
- State, action og reducer
- Store og SwiftUI-integration
- Effects og dependencies
- Komposition og testning af features