Golang에서지도의 동등성을 테스트하는 방법은 무엇입니까?
다음과 같은 테이블 기반 테스트 케이스가 있습니다.
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
}
}
길이가 동일한 지 확인하고 모든 키-값 쌍이 동일한 지 확인하는 루프를 작성할 수 있습니다. 그러나 다른 유형의지도에 사용하려면이 수표를 다시 작성해야합니다 (예 :) map[string]string
.
결국 내가 한 것은 맵을 문자열로 변환하고 문자열을 비교하는 것입니다.
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)
}
이것은 동등한 맵의 문자열 표현이 동일하다고 가정합니다.이 경우에는 사실 인 것처럼 보입니다 (키가 동일하면 동일한 값으로 해시되므로 순서가 동일합니다). 이 작업을 수행하는 더 좋은 방법이 있습니까? 테이블 기반 테스트에서 두 맵을 비교하는 관용적 방법은 무엇입니까?
Go 라이브러리는 이미 당신을 덮었습니다. 이 작업을 수행:
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.")
}
당신이 보면 소스 코드 에 대한 reflect.DeepEqual
의 Map
경우 그들이 전에 마지막으로 그들이 (키의 동일한 세트가 있는지 확인 같은 길이가 있다면, 당신은 다음 수표, 모두 매핑하고있는 경우에 최초로 확인이 전무 것을 볼 수 있습니다 값) 쌍.
reflect.DeepEqual
인터페이스 유형을 취하기 때문에 유효한 모든지도 ( map[string]bool, map[struct{}]interface{}
등)에서 작동합니다. 비맵 값에서도 작동하므로 전달하는 것이 실제로 두 개의 맵이라는 점에 유의하십시오. 두 개의 정수를 전달하면 같은지 여부를 기꺼이 알려줍니다.
이것은 내가 할 일입니다 (테스트되지 않은 코드).
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
}
테이블 기반 테스트에서 두 맵을 비교하는 관용적 방법은 무엇입니까?
당신은 go-test/deep
도울 프로젝트 가 있습니다.
하지만 기본적으로 Go 1.12 (2019 년 2 월)를 사용하면이 작업이 더 쉬워 질 것입니다 . 출시 노트를 참조하세요 .
fmt
이제 맵은 테스트를 쉽게하기 위해 키 정렬 순서로 인쇄됩니다 .
주문 규칙은 다음과 같습니다.
- 적용 가능한 경우 nil은 낮음을 비교합니다.
- 정수, 부동 소수점 및 문자열 순서
<
- NaN은 비 NaN 수레보다 적은 수를 비교합니다.
bool
false
전에 비교true
- 복잡함은 실제와 가상의 비교
- 컴퓨터 주소로 포인터 비교
- 컴퓨터 주소로 채널 값 비교
- 구조체는 각 필드를 차례로 비교합니다.
- 배열은 각 요소를 차례로 비교합니다.
- 인터페이스 값은 먼저
reflect.Type
구체적인 유형 을 설명하여 비교 한 다음 이전 규칙에서 설명한대로 구체적인 값으로 비교 합니다.When printing maps, non-reflexive key values like NaN were previously displayed as . As of this release, the correct values are printed.
Sources:
golang/go
issue 21095,- Tweet (original idea for that patch: ᴊᴀᴍᴇꜱ ᴊᴜꜱᴛ ᴊᴀᴍᴇꜱ (
purpleidea
) - CL 142737:
The CL adds: (CL stands for "Change List")
To do this, we add a package at the root,
internal/fmtsort
, that implements a general mechanism for sorting map keys regardless of their type.This is a little messy and probably slow, but formatted printing of maps has never been fast and is already always reflection-driven.
The new package is internal because we really do not want everyone using this to sort things. It is slow, not general, and only suitable for the subset of types that can be map keys.
Also use the package in text/template
, which already had a weaker version of this mechanism.
You can see that used in src/fmt/print.go#
Disclaimer: Unrelated to map[string]int
but related to testing the equivalence of maps in Go, which is the title of the question
If you have a map of a pointer type (like map[*string]int
), then you do not want to use reflect.DeepEqual because it will return false.
Finally, if the key is a type that contains an unexported pointer, like time.Time, then reflect.DeepEqual on such a map can also return false.
Use the "Diff" method of github.com/google/go-cmp/cmp:
Code:
// Let got be the hypothetical value obtained from some logic under test
// and want be the expected golden data.
got, want := MakeGatewayInfo()
if diff := cmp.Diff(want, got); diff != "" {
t.Errorf("MakeGatewayInfo() mismatch (-want +got):\n%s", diff)
}
Output:
MakeGatewayInfo() mismatch (-want +got):
cmp_test.Gateway{
SSID: "CoffeeShopWiFi",
- IPAddress: s"192.168.0.2",
+ IPAddress: s"192.168.0.1",
NetMask: net.IPMask{0xff, 0xff, 0x00, 0x00},
Clients: []cmp_test.Client{
... // 2 identical elements
{Hostname: "macchiato", IPAddress: s"192.168.0.153", LastSeen: s"2009-11-10 23:39:43 +0000 UTC"},
{Hostname: "espresso", IPAddress: s"192.168.0.121"},
{
Hostname: "latte",
- IPAddress: s"192.168.0.221",
+ IPAddress: s"192.168.0.219",
LastSeen: s"2009-11-10 23:00:23 +0000 UTC",
},
+ {
+ Hostname: "americano",
+ IPAddress: s"192.168.0.188",
+ LastSeen: s"2009-11-10 23:03:05 +0000 UTC",
+ },
},
}
Simplest way:
assert.InDeltaMapValues(t, got, want, 0.0, "Word count wrong. Got %v, want %v", got, want)
Example:
import (
"github.com/stretchr/testify/assert"
"testing"
)
func TestCountWords(t *testing.T) {
got := CountWords("hola hola que tal")
want := map[string]int{
"hola": 2,
"que": 1,
"tal": 1,
}
assert.InDeltaMapValues(t, got, want, 0.0, "Word count wrong. Got %v, want %v", got, want)
}
One of the options is to fix rng:
rand.Reader = mathRand.New(mathRand.NewSource(0xDEADBEEF))
참고URL : https://stackoverflow.com/questions/18208394/how-to-test-the-equivalence-of-maps-in-golang
'Nice programing' 카테고리의 다른 글
(.1f + .2f ==. 3f)! = (.1f + .2f) .Equals (.3f) 왜? (0) | 2020.11.10 |
---|---|
Android에서 게임 클라이언트 초기화 (0) | 2020.11.10 |
JSON.net으로 JToken의 이름 / 키 얻기 (0) | 2020.11.10 |
Python 스크립트를 벤치마킹하는 간단한 방법이 있습니까? (0) | 2020.11.10 |
XP가 설치된 VirtualBox 시스템에 스토리지를 쉽게 추가하려면 어떻게해야합니까? (0) | 2020.11.10 |