0Pricing
Swift Academy · Pelajaran

Menyusun dan Menguji Fitur

Gabungkan reducer dan lakukan pengujian menyeluruh.

Menyusun dan Menguji Fitur adalah pelajaran Swift Academy gratis di CoddyKit. Ini adalah pelajaran 4 dari 4. Kamu bisa membaca pelajaran lengkapnya di bawah secara gratis — lalu praktikkan langsung di browser dengan editor kode bawaan dan tutor AI 24/7. Ini adalah bagian dari jalur belajar Swift Academy, dan progresmu tersinkronisasi di web dan aplikasi CoddyKit. Kursus Swift Academy mencakup 4 pelajaran total.

Menyusun Fitur

Aplikasi nyata dibangun dari banyak fitur kecil. TCA memungkinkan fitur induk menyematkan fitur anak agar masing-masing tetap fokus, lalu menggabungkannya menjadi satu kesatuan yang lebih besar. Alat untuk melakukannya adalah Scope serta penyematan status dan tindakan anak.

Komposisi inilah yang memberi nama Arsitektur Komposabel.

import ComposableArchitecture

// A parent feature embeds child State and Action,
// then uses Scope to run the child's reducer.

Menyematkan Status Anak

State milik induk menyimpan status anak sebagai sebuah properti. Enum Action milik induk memiliki kasus yang membungkus tindakan anak. Penyarangan ini mencerminkan cara antarmuka pengguna disusun bertingkat.

Di sini, fitur induk menyimpan anak berupa penghitung.

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() }
}

Membatasi Cakupan ke Anak

Scope menjalankan pereduksi anak pada bagian status dan tindakan induk yang menjadi miliknya. Anda memberinya jalur kunci status dan jalur kasus tindakan, lalu pereduksi anak.

Ini menghubungkan anak ke dalam siklus pembaruan induk.

import ComposableArchitecture

var body: some ReducerOf<Self> {
    Scope(state: \.counter, action: \.counter) {
        CounterFeature()
    }
    Reduce { state, action in
        // parent-specific logic here
        return .none
    }
}

Menggabungkan Beberapa Pereduksi

body sebuah fitur dapat mencantumkan beberapa pereduksi; TCA menjalankannya secara berurutan untuk setiap tindakan. Dengan demikian, Anda dapat menempatkan satu atau beberapa Scope berdampingan dengan Reduce milik induk.

Di sini, dua anak dan logika induk berjalan bersama.

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
    }
}

Membatasi Cakupan Store untuk Tampilan Anak

Di sisi tampilan, tampilan anak memerlukan store yang dikhususkan untuk anak tersebut. Induk membuatnya melalui store.scope, dengan memetakan ke status dan tindakan anak.

Di sini, tampilan induk meneruskan store dengan cakupan tersebut kepada tampilan penghitung.

import ComposableArchitecture
import SwiftUI

struct AppView: View {
    let store: StoreOf<AppFeature>
    var body: some View {
        CounterView(
            store: store.scope(state: \.counter, action: \.counter)
        )
    }
}

Memperkenalkan TestStore

TestStore memungkinkan Anda memverifikasi secara tepat perilaku sebuah fitur. Anda mengirimkan tindakan dan menjelaskan perubahan status yang diharapkan; jika hasil sebenarnya berbeda, pengujian gagal. Pemeriksaan menyeluruh ini menemukan regresi yang sulit terlihat.

Anda membuatnya seperti store biasa, dengan status awal dan pereduksi.

import ComposableArchitecture
import XCTest

func testIncrement() async {
    let store = await TestStore(initialState: CounterFeature.State()) {
        CounterFeature()
    }
}

Memverifikasi Perubahan Status

Saat Anda mengirimkan tindakan ke TestStore, Anda memberikan blok yang menjelaskan perubahan yang diharapkan. Pengujian hanya berhasil jika status berubah persis seperti itu.

Di sini, penambahan harus menaikkan jumlah dari 0 menjadi 1.

import ComposableArchitecture
import XCTest

func testIncrement() async {
    let store = await TestStore(initialState: CounterFeature.State()) {
        CounterFeature()
    }
    await store.send(.incrementTapped) {
        $0.count = 1
    }
}

Kelengkapan

Secara bawaan, TestStore bersifat menyeluruh: Anda harus memperhitungkan setiap perubahan status dan setiap tindakan yang dikirimkan kembali oleh efek. Perubahan yang tidak ditangani akan menggagalkan pengujian sehingga pernyataan Anda tetap dapat dipercaya.

Anda dapat melonggarkan aturan ini dengan store.exhaustivity = .off untuk pengujian yang terfokus.

import ComposableArchitecture

// Exhaustive (default): every change must be asserted.
// Relax when you only care about part of the behavior:
store.exhaustivity = .off

Menerima Tindakan dari Efek

Saat efek mengirimkan tindakan kembali, pengujian harus melakukan receive terhadapnya dan memverifikasi status yang dihasilkan. Ini membuktikan bahwa alur asinkron bekerja dari awal hingga akhir.

Di sini, pemuatan ulang memicu respons yang ditunggu dan diperiksa oleh pengujian.

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
    }
}

Mengganti Dependensi dalam Pengujian

Agar efek bersifat deterministik, gantilah dependensi saat membuat TestStore. Sediakan klien tiruan atau jam pengujian agar hasilnya dapat diprediksi.

Di sini, klien angka diganti dengan klien yang selalu mengembalikan 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 }
}

Menguji Fitur yang Disusun

Karena komposisi menyarangkan status dan tindakan, Anda menguji fitur induk dengan mengirimkan tindakan anak yang dibungkus dalam kasus milik induk. Pernyataan menyeluruh yang sama tetap berlaku untuk memverifikasi seluruh hierarki.

Di sini, induk menerima penambahan penghitung melalui cakupannya.

import ComposableArchitecture
import XCTest

func testChildInParent() async {
    let store = await TestStore(initialState: AppFeature.State()) {
        AppFeature()
    }
    await store.send(.counter(.incrementTapped)) {
        $0.counter.count = 1
    }
}

Pemeriksaan Singkat: Perilaku TestStore

Ingat kembali hal yang harus diverifikasi oleh TestStore bawaan dalam pernyataan Anda.

Ringkasan: Menyusun dan Menguji

Anda telah menyelesaikan perangkat TCA:

  • Scope menjalankan pereduksi anak pada bagian status dan tindakan induk, dan beberapa pereduksi dapat digabungkan dalam satu body.
  • store.scope memberikan store khusus kepada tampilan anak.
  • TestStore memverifikasi perubahan status secara tepat saat Anda send tindakan.
  • Secara bawaan, TestStore bersifat menyeluruh dan menggunakan receive untuk tindakan yang digerakkan oleh efek.
  • Gantilah dependensi dengan withDependencies untuk pengujian deterministik.

Sekarang Anda dapat membangun, menyusun, dan menguji fitur secara ketat dengan Arsitektur Komposabel.

import ComposableArchitecture

// Recap: Scope to compose, TestStore to verify.
// Exhaustive assertions + injected fakes = confidence.

Pertanyaan yang Sering Diajukan

Apakah pelajaran “Menyusun dan Menguji Fitur” gratis?

Ya — teks lengkap “Menyusun dan Menguji Fitur” gratis dibaca di sini di web. Untuk praktiknya secara interaktif (editor kode bawaan dan tutor AI 24/7) dan buka sisa kursus Swift Academy, upgrade ke CoddyKit PRO. Kursus Swift Academy mencakup 4 pelajaran total.

Apa yang akan aku pelajari di “Menyusun dan Menguji Fitur”?

Gabungkan reducer dan lakukan pengujian menyeluruh. Kamu berlatih Swift Academy dengan kode praktik yang langsung kamu jalankan di browser, dan tutor AI 24/7 menjawab pertanyaanmu saat kamu mengerjakan pelajaran ini.

Apakah aku perlu pengalaman untuk memulai Swift Academy?

Tidak diperlukan pengalaman sebelumnya. Swift Academy di CoddyKit dirancang untuk pemula hingga pelajar tingkat lanjut, jadi kamu bisa memulai di sini atau dari awal dan belajar sesuai kecepatan kamu sendiri. Ini adalah pelajaran 4 dari 4.

Berapa lama pelajaran “Menyusun dan Menguji Fitur” memakan waktu?

Sebagian besar pelajaran CoddyKit memakan waktu sekitar 5–10 menit. Setiap pelajaran ringkas dan interaktif, jadi kamu membuat kemajuan stabil dan melanjutkan dari tempat kamu tinggalkan di web dan aplikasi.

Bisakah aku menulis dan menjalankan kode dalam pelajaran Swift Academy ini?

Ya. Setiap pelajaran Swift Academy menyertakan editor kode bawaan, jadi kamu menulis dan menjalankan kode nyata langsung di browser dan mendapatkan umpan balik AI instan — tidak diperlukan penyiapan lokal.

Semua pelajaran dalam kursus ini

  1. State, Action, dan Reducer
  2. Store dan Integrasi SwiftUI
  3. Efek dan Dependensi
  4. Menyusun dan Menguji Fitur
← Kembali ke Swift Academy