Go'da kanal ardışık düzenleri nasıl test edilir
Go'da "kanal ardışık düzeni" modelini oldukça kullanıyorum, bu şuna benzer:
// getSomeNums spits out ints onto a channel. Temperatures, pressures, doesn't matter
func getSomeNums(ch chan<- int) {
// Imagination goes here
}
// double takes numbers from in, doubles them, and pushes them into out
func double(in <-chan int, out chan<- int) {
for v := range in {
out <- v * 2
close(out)
}
source := make(chan int)
go getSomeNums(source)
doubles := make(chan int)
double(source, doubles)
Tekrar tekrar karşılaştığım sorun, bu boru hattı işlevlerinin bir dizi farklı özelliğini test etmem gerektiğidir:
- Giriş kanalına bir tane koyduğunuzda çıkış kanalına bir değer koyar
- Giriş kanalına bir değer koymadığınızda çıkış kanalına bir değer koymaz
- Giriş kanalında bir değer göründükten sonra çıkış kanalı çok uzun sürerse zaman aşımına uğradı
- Giriş kanalı kapandığında çıkış kanalını kapatır
- Giriş kanalı kapanmadan çıkış kanalını kapatmaz
- Girdi üzerinde doğru dönüşümü gerçekleştirir
Üstelik bu sadece gerçekten basit bir örnek. Daha tipik durumlar, çıktıdaki hataları bulmak için yedekli sıcaklık sensörlerini kullanmaya çalıştığımız bu örnek gibi bir şeye benziyor:
// Provided we have channels for sensorA, sensorB, and sensorC
import "math"
LIMIT = 0.1 // Set acceptable variation limit between sensors to 10%
type SafeTemp struct {
Temp float64
isSafe bool
}
// variation returns relative error between inputs. Unfortunately, "error" was taken
func variation(a, b float64) float64 {
return math.Abs((a - b) / (a + b))
}
// safify zips together temperatures so long as error is below LIMIT
func safify(chA, chB, chC <-chan float64, chOut chan<- SafeTemp) {
for {
a, aOk := <-chA
b, bOk := <-chB
c, cOk := <-chC
if !(aOk && bOk && cOk) {
close(chOut)
return
}
if variation(a, b) < LIMIT && variation(b, c) < LIMIT &&
variation(c, a) < LIMIT {
chOut <- SafeTemp{ (a + b + c) / 3, true }
} else {
chOut <- SafeTemp{ 0.0, false }
}
}
}
Şimdi, ardışık düzen işlevi ( safify
) için test etmem gereken şeylerin sayısı önemli ölçüde artıyor:
- Tüm giriş kanallarında bir tane aldığınızda çıkış kanalına bir değer koyar
- Tüm giriş kanallarında bir tane almadığınızda çıkış kanalına bir değer koymaz
- Çıkış kanalı, üç giriş kanalının tümünde girişlerden sonra çok uzun sürerse, ancak yalnızca üçü
- Herhangi bir giriş kanalı kapandığında çıkış kanalını kapatır
- Hiçbir giriş kanalı kapalı değilse çıkış kanalını kapatmaz
- Değil Bayraklar
isSafe
birinci kanal zaman aşımı ile diğerlerinden önemli ölçüde farklılık gösteriyorsa - Değil Bayraklar
isSafe
ikinci kanal zaman aşımı ile diğerlerinden önemli ölçüde farklılık gösteriyorsa - Değil Bayraklar
isSafe
üçüncü kanal zaman aşımı ile diğerlerinden önemli ölçüde farklılık gösteriyorsa - Olarak değil Bayraklar
isSafe
eğer bütün kanallar diğerlerinden, zaman aşımları ile önemli ölçüde değişir
Ayrıca, üç giriş kanalı birbiriyle senkronize olmayabilir, bu da yukarıda gösterilenin ötesinde önemli bir karmaşıklık ekler.
Görünüşe göre bu kontrollerin çoğu (özellikle doğru hesaplamalarla yapmak zorunda olanlar hariç) Go'daki tüm fan tarzı kanal ardışık düzeni işlevlerinde ortaktır ve Durma Sorunu herkes için zaman aşımlarını kullanmamız gerektiğini garanti eder. Testlerimizin durdurulmasının, test edilen fonksiyonların durdurulmasına ve nihai kanal itme davranışına bağlı olmasını istemediğimiz sürece, bu işlemlerden bazıları.
Bu tür testlerin pano genelinde ne kadar benzer olduğu ve nasıl oldukça benzer testler yazdığım göz önüne alındığında, temelde bu kanal boru hattı işlevlerinin , işlevlerin davranışları yerine, temel kanal işlem hattı işlev garantilerine ne kadar iyi uyduğunu tekrar tekrar test ediyorum. , ya:
- Bu tür kanal boru hattı işlevi güvenilirlik testleri etrafında standart bir uygulama seti VEYA
- Kanala özgü işlevleri test etmek için standart veya iyi güçlendirilmiş bir çerçeve veya çerçeve kümesi mi?
Yanıtlar
İki farklı endişeyi karıştırıyorsunuz. Ardışık düzen için ayrı bir soyutlama yaptıysanız, bunu bir kez test edebilirsiniz. Gibi bir şey (affet sözdizimi, gitmeyi bilmiyorum):
func double(v int) int {
return v * 2
}
pipeline(in, out, double)
veya
func safe(v [3]float64) SafeTemp {
if variation(v[0], v[1]) < LIMIT && variation(v[1], v[2]) < LIMIT &&
variation(v[2], v[0]) < LIMIT {
return SafeTemp{ (v[0] + v[1] + v[2]) / 3, true }
} else {
return SafeTemp{ 0.0, false }
}
}
pipeline(in, out, safe)
Parametrik polimorfizm olmadan, tam anlamıyla genel bir pipeline
soyutlama yapamazsınız , bu yüzden belirli bir miktarda tekrarlamayı kabul etmeniz gerekir. Bununla birlikte, en azından boru hattı modelinin endişelerini daha uygulamaya özgü mantıktan ayırabilmelisiniz.