testing - particion - pruebas de caja negra y caja blanca ejemplos
Prueba de equivalencia de mapas(Golang) (4)
Tengo un caso de prueba basado en tablas como este:
func CountWords(s string) map[string]int
func TestCountWords(t *testing.T) {
var tests = []struct {
input string
want map[string]int
}{
{"foo", map[string]int{"foo":1}},
{"foo bar foo", map[string]int{"foo":2,"bar":1}},
}
for i, c := range tests {
got := CountWords(c.input)
// TODO test whether c.want == got
}
}
Podría verificar si las longitudes son las mismas y escribir un ciclo que verifique si cada par clave-valor es el mismo. Pero luego tengo que escribir este cheque nuevamente cuando quiero usarlo para otro tipo de mapa (digamos map[string]string
).
Lo que terminé haciendo es convertir los mapas en cadenas y comparar las cadenas:
func checkAsStrings(a,b interface{}) bool {
return fmt.Sprintf("%v", a) != fmt.Sprintf("%v", b)
}
//...
if checkAsStrings(got, c.want) {
t.Errorf("Case #%v: Wanted: %v, got: %v", i, c.want, got)
}
Esto supone que las representaciones de cadenas de mapas equivalentes son las mismas, lo que parece ser cierto en este caso (si las claves son las mismas, entonces hash al mismo valor, por lo que sus órdenes serán las mismas). ¿Hay una mejor manera de hacer esto? ¿Cuál es la forma idiomática de comparar dos mapas en pruebas basadas en tablas?
Esto es lo que haría (código no probado):
func eq(a, b map[string]int) bool {
if len(a) != len(b) {
return false
}
for k, v := range a {
if w, ok := b[k]; !ok || v != w {
return false
}
}
return true
}
La biblioteca Go ya lo cubrió. Hacer esto:
import "reflect"
// m1 and m2 are the maps we want to compare
eq := reflect.DeepEqual(m1, m2)
if eq {
fmt.Println("They''re equal.")
} else {
fmt.Println("They''re unequal.")
}
Si miras el código fuente para el caso del Map
reflect.DeepEqual
, verás que primero verifica si ambos mapas son nulos, luego verifica si tienen la misma longitud antes de verificar para ver si tienen el mismo conjunto de pares (clave, valor).
Como reflect.DeepEqual
toma un tipo de interfaz, funcionará en cualquier mapa válido ( map[string]bool, map[struct{}]interface{}
, etc.). Tenga en cuenta que también funcionará en valores que no sean del mapa, así que tenga cuidado de que lo que le pase sea en realidad dos mapas. Si pasas dos enteros, felizmente te dirá si son iguales.
Una de las opciones es arreglar rng:
rand.Reader = mathRand.New(mathRand.NewSource(0xDEADBEEF))
Descargo de responsabilidad : no relacionado con el map[string]int
pero relacionado con la prueba de la equivalencia de los mapas en Ir, que es el título de la pregunta
Si tiene un mapa de un tipo de puntero (como map[*string]int
), entonces no desea usar reflect.DeepEqual porque devolverá false.
Finalmente, si la clave es un tipo que contiene un puntero no exportado, como time.Time, then reflect.DeepEqual en dicho mapa también puede devolver false .