Gesaan dan skop
Fungsi ini memulakan goroutine latar belakang, mencuba semula dengan exponential backoff, dan merekodkan hasil melalui context.AfterFunc apabila had masa tamat berlaku. Ujian yang menggunakan time.Sleep adalah perlahan, tidak stabil (flaky), atau meninggalkan kerja latar belakang. Gunakan Go testing/synctest untuk mereka bentuk ujian deterministik, dan meliputi API eksperimen lawan stabil, kebocoran goroutine, I/O sebenar, dan sempadan jam.
API dan versi mesti sepadan dengan keluaran Go sasaran. Ini sesuai untuk peranan pengekodan bahagian belakang (backend), pustaka keserempakan, dan infrastruktur. Kemahiran teras ialah ujian serempak deterministik, jadi ia tergolong dalam coding.
Perkara yang dinilai oleh penemu duga
Pertama, adakah anda memahami gelembung synctest? Ia mengasingkan goroutine dan masa, manakala Wait membolehkan kerja di dalam gelembung mencapai keadaan tenang (quiescence).
Kedua, bolehkah anda memisahkan masa maya dan masa sebenar? API masa yang digunakan di dalam gelembung boleh dimajukan secara maya, tetapi tingkah laku rangkaian, fail atau goroutine luaran yang sebenar tidak menjadi deterministik secara automatik.
Ketiga, bolehkah anda menguji pembatalan dan pembersihan (cleanup)? Pembatalan konteks, panggilan balik AfterFunc, dan goroutine percubaan semula mesti selesai atau dihentikan secara eksplisit sebelum ujian tamat.
Keempat, bolehkah anda mengendalikan perbezaan versi? Go 1.24 mendedahkan synctest secara eksperimen di sebalik bendera; Go 1.25 menyediakan API yang stabil. CI mesti menetapkan (pin) versi tersebut.
Kelima, bolehkah anda mengekalkan liputan integrasi? Ujian masa maya mengesahkan susunan logik, bukan tingkah laku HTTP, pangkalan data, penjadual atau pengesan perlumbaan (race detector) dalam proses sebenar.
Soalan untuk dijelaskan terlebih dahulu
- Adakah CI menggunakan eksperimen Go 1.24 atau API stabil Go 1.25?
- Adakah semua goroutine ujian dicipta di dalam gelembung?
- Adakah percubaan semula menggunakan
time.After, pemasa, atau penjadual luaran? - Selepas pembatalan, adakah I/O semasa dibenarkan selesai atau mesti kembali serta-merta?
- Adakah kita memerlukan kependaman rangkaian sebenar, kunci pangkalan data, dan liputan perlumbaan?
- Bolehkah kod menerima antara muka jam atau kebergantungan, atau adakah fungsi sedia ada mesti dibungkus?
Rangka jawapan 30 saat
“Saya akan menjalankan fungsi tersebut di dalam gelembung synctest.Test, memajukan masa maya melalui backoff dan tarikh akhir, serta menggunakan synctest.Wait untuk mencapai ketenangan (quiescence). Saya akan menegaskan (assert) bilangan percubaan semula, ralat akhir, tingkah laku satu kali AfterFunc, dan tiada kerja selepas pembatalan. Go 1.24 memerlukan bendera eksperimen; Go 1.25 mempunyai API yang stabil, jadi CI menetapkannya. Semakan HTTP, pangkalan data, penjadual, dan perlumbaan sebenar dijalankan secara berasingan kerana ia tidak dikawal secara automatik oleh gelembung.”
Jawapan langkah demi langkah
Langkah 1: Tetapkan versi dan API
testing/synctest Go 1.24 adalah eksperimen dan memerlukan GOEXPERIMENT=synctest; Go 1.25 mendedahkan API piawai Test dan Wait. Tetapkan go.mod, imej CI, dan persekitaran baris arahan supaya semantik setempat dan CI sepadan.
Langkah 2: Letakkan kerja di dalam gelembung
Cipta setiap goroutine ujian di dalam gelembung dan bukannya memulakan kerja yang tidak terkawal di luar fungsi ujian. Gelembung harus memiliki pembatalan, penutupan saluran, dan pembersihan sumber, dan semua tugas mesti kembali sebelum ia keluar.
func TestRetryTimeout(t *testing.T) {
synctest.Test(t, func(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
got := runWithRetry(ctx)
synctest.Wait()
// Advance virtual time and assert retry/timeout state here.
_ = got
})
}Langkah 3: Majukan masa maya
Jangan gunakan time.Sleep sebenar untuk backoff. Majukan jam gelembung ke pemasa seterusnya atau tarikh akhir eksplisit, kemudian panggil Wait supaya goroutine yang boleh dijalankan dilaksanakan. Lakukan penegasan selepas setiap kemajuan dan bukannya melangkau beberapa sempadan yang akan menyembunyikan peralihan yang gagal.
Langkah 4: Sahkan AfterFunc dan pembatalan
context.AfterFunc memulakan goroutine panggilan balik apabila pembatalan berlaku. Rekodkan kiraan panggilan balik dan ralat yang diperhatikan, kemudian panggil Wait selepas pembatalan. Jika fungsi mendaftarkan panggilan balik berulang kali, tegaskan bahawa laluan pembatalan hanya menghasilkan kesan sampingan yang direka bentuk.
Langkah 5: Lindungi percubaan semula dan hasil akhir
Suntik urutan kegagalan yang terkawal, seperti dua kegagalan diikuti dengan kejayaan, dan tegaskan setiap backoff dan kiraan panggilan. Uji juga tamat tempoh tarikh akhir, pembatalan induk, dan kegagalan kekal; pembatalan mesti menghentikan percubaan semula selanjutnya dan memastikan pengelasan ralat kekal stabil.
Langkah 6: Periksa sempadan gelembung
Goroutine yang dimulakan di luar gelembung, panggilan sistem, rangkaian sebenar, dan masa jalan pihak ketiga mungkin tidak menggunakan masa maya. Gantikan kebergantungan tersebut dengan antara muka atau uji mereka dalam suite integrasi; determinisme gelembung bukanlah jaminan hujung ke hujung.
Langkah 7: Gabungkan alat pengesahan lain
Synctest meliputi pemasaan logik. go test -race memeriksa perlumbaan data (data race), manakala ujian HTTP dan pangkalan data sebenar memeriksa sambungan, tarikh akhir, dan tingkah laku protokol. Jejaki tempoh ujian, sempadan percubaan semula, dan penumpuan tugas supaya ujian tidak bocor atau menjadi perlahan secara senyap.
Jawapan model
“Saya akan menetapkan versi Go terlebih dahulu. Synctest Go 1.24 memerlukan bendera eksperimen; Go 1.25 menggunakan synctest.Test dan synctest.Wait yang stabil. Saya akan mencipta semua goroutine ujian di dalam gelembung, menyuntik urutan kegagalan, memajukan masa maya melalui backoff dan tarikh akhir, menunggu ketenangan selepas setiap kemajuan, dan menegaskan panggilan, ralat, panggilan balik, serta pembersihan pembatalan.
Saya tidak akan menggunakan sleep sebenar atau menganggap goroutine rangkaian, pangkalan data, atau pihak ketiga di luar gelembung sebagai kerja masa maya. Laluan tersebut menerima antara muka palsu (fakes) untuk ujian logik dan integrasi sebenar serta go test -race untuk protokol, kunci, dan perlumbaan. Ujian mesti membuktikan bahawa tiada tugas gelembung yang tinggal semasa keluar.”
Kesilapan lazim
- Mengekalkan
time.Sleepdi dalam gelembung → ujian kekal perlahan dan tidak deterministik → majukan masa maya. - Hanya menegaskan hasil akhir → percubaan semula dan pembersihan pembatalan mungkin salah → tegaskan pemasa, panggilan, dan panggilan balik langkah demi langkah.
- Memulakan goroutine di luar gelembung → penumpuan tidak boleh ditunggu → jadikan gelembung memiliki kerja tersebut.
- Menganggap rangkaian sebenar sebagai masa maya → I/O kekal tidak stabil (flaky) → gunakan palsu (fakes) dan ujian integrasi berasingan.
- Mengabaikan perbezaan API 1.24/1.25 → binaan setempat dan CI berbeza → tetapkan Go dan bendera eksperimen.
- Melangkau pengesan perlumbaan → pemasaan boleh menjadi betul sementara perlumbaan data kekal → gabungkan
go test -race. - Mencuba semula selepas pembatalan → permintaan dan penggunaan sumber meningkat → semak konteks sebelum setiap menunggu dan panggilan.
- Menggunakan satu
Waitakhir untuk semua penegasan → sempadan kegagalan tidak jelas → majukan dan sahkan secara berfasa.
Soalan susulan
Soalan susulan 1: Adakah synctest menggantikan ujian masa nyata?
Tidak. Ia mengesahkan logik serempak terkawal dan hubungan temporal; jam, rangkaian, pangkalan data, dan penjadual masih memerlukan ujian persekitaran sebenar.
Soalan susulan 2: Mengapa memanggil Wait?
Memajukan masa maya menamatkan pemasa; Wait menjalankan goroutine yang boleh dijalankan di dalam gelembung sehingga ia mencapai ketenangan, menjadikan penegasan stabil.
Soalan susulan 3: Bagaimanakah anda menguji sekatan kekal?
Berikan operasi tarikh akhir, majukan masa ke tarikh akhir tersebut, dan tegaskan ralat serta pembersihan. Untuk sekatan luaran yang tidak boleh dibatalkan, gunakan ujian palsu atau had masa tamat yang diasingkan dan bukannya menunggu selama-lamanya di dalam gelembung.
Soalan susulan 4: Bolehkah eksperimen Go 1.24 digunakan dalam pengeluaran?
Ia boleh menyokong ujian terkawal, tetapi status eksperimen, bendera, dan risiko peningkatan mesti dijelaskan. Untuk keserasian yang stabil, lebih baik gunakan API Go 1.25 dan tetapkan pada CI.
Soalan susulan 5: Bagaimanakah anda mencari kebocoran di luar gelembung?
Semak isyarat penyelesaian dan sumber yang ditutup sebelum keluar, kemudian gabungkan -race, profil goroutine, atau had masa tamat integrasi. Synctest bukanlah pengesan kebocoran peringkat proses yang lengkap.
Soalan susulan 6: Bagaimanakah anda mengesan hanyutan backoff (backoff drift)?
Rekodkan cap masa maya setiap panggilan dan bandingkannya dengan urutan yang dijangkakan. Uji juga pemotongan tarikh akhir bagi penantian akhir dan pembatalan awal.