在Go语言中测试具有相同内容的映射是否等价时,测试失败了。

huangapple go评论94阅读模式
英文:

Testing equivalence of maps in Go with the same contents, but the test failed

问题

这是一个在Go语言中的单词计数函数:

package wc

import (
    "regexp"
    "strings"
)

type Histogram map[string]int

func WordCount(input string) Histogram {
    histogram := make(map[string]int)
    re := regexp.MustCompile("[^a-zA-Z0-9 ]*")
    input = re.ReplaceAllString(input, "")

    for _, word := range strings.Split(input, " ") {
        if word == "" {
            continue
        }
        histogram[strings.ToLower(word)]++
    }

    return histogram
}

这段代码在测试中有时会通过,有时会失败,这是非确定性的。有时会因为预期的映射和实际的映射不匹配而失败。然而,两者的内容完全相同。我认为这是映射比较的问题。我不知道如何修复它。请有人帮帮我!

这是测试套件的代码:

package wc

import (
    "fmt"
    "testing"
)

var testCases = []struct {
    description string
    input       string
    output      Histogram
}{
    {
        description: "一个单词",
        input:       "word",
        output:      Histogram{"word": 1},
    },
    {
        description: "每个单词各一个",
        input:       "one of each",
        output:      Histogram{"one": 1, "of": 1, "each": 1},
    },
    {
        description: "多次出现",
        input:       "one fish two fish red fish blue fish",
        output:      Histogram{"one": 1, "fish": 4, "two": 1, "red": 1, "blue": 1},
    },
    {
        description: "忽略标点符号",
        input:       "car : carpet as java : javascript!!&@$%^&",
        output:      Histogram{"car": 1, "carpet": 1, "as": 1, "java": 1, "javascript": 1},
    },
    {
        description: "包括数字",
        input:       "testing, 1, 2 testing",
        output:      Histogram{"testing": 2, "1": 1, "2": 1},
    },
    {
        description: "规范化大小写",
        input:       "go Go GO",
        output:      Histogram{"go": 3},
    },
}

func TestWordCount(t *testing.T) {
    for _, tt := range testCases {
        expected := fmt.Sprintf("%v", tt.output)
        actual := fmt.Sprintf("%v", WordCount(tt.input))

        if expected != actual {
            t.Fatalf("%s\n\t预期结果: %v\n\t实际结果: %v", tt.description, expected, actual)
        } else {
            t.Logf("通过: %s - WordCount(%s)", tt.description, tt.input)
        }
    }
}

以下是失败情况的示例:

预期结果: map[two:1 red:1 blue:1 one:1 fish:4]
实际结果: map[one:1 fish:4 two:1 red:1 blue:1]

预期结果: map[one:1 fish:4 two:1 red:1 blue:1]
实际结果: map[red:1 blue:1 one:1 fish:4 two:1]

预期结果: map[java:1 javascript:1 car:1 carpet:1 as:1]
实际结果: map[javascript:1 car:1 carpet:1 as:1 java:1]

...

附加信息在这里:
http://exercism.io/submissions/cf94f4732fd97335be2e755f

英文:

Here is a word-count function in Go

package wc
import (
"regexp"
"strings"
)
type Histogram map[string]int
func WordCount(input string) Histogram {
histogram := make(map[string]int)
re := regexp.MustCompile("[^a-zA-Z0-9 ]*")
input = re.ReplaceAllString(input, "")
for _, word := range strings.Split(input, " ") {
if word == "" {
continue
}
histogram[strings.ToLower(word)]++
}
return histogram
}

This code passes or fails the tests non-deterministically. Sometimes it failed due to not matching the expected map and the actual map. However, the contents of both are exactly the same. I think that there is some problem with map comparison. I don't know how can I fix it. Somebody help me please!

Here is the test-suite code

package wc
import (
"fmt"
"testing"
)
var testCases = []struct {
description string
input       string
output      Histogram
}{
{
description: "a single word",
input:       "word",
output:      Histogram{"word": 1},
},
{
description: "one of each",
input:       "one of each",
output:      Histogram{"one": 1, "of": 1, "each": 1},
},
{
description: "multiple occurrences",
input:       "one fish two fish red fish blue fish",
output:      Histogram{"one": 1, "fish": 4, "two": 1, "red": 1, "blue": 1},
},
{
description: "ignore punctuation",
input:       "car : carpet as java : javascript!!&@$%^&",
output:      Histogram{"car": 1, "carpet": 1, "as": 1, "java": 1, "javascript": 1},
},
{
description: "including numbers",
input:       "testing, 1, 2 testing",
output:      Histogram{"testing": 2, "1": 1, "2": 1},
},
{
description: "normalises case",
input:       "go Go GO",
output:      Histogram{"go": 3},
},
}
func TestWordCount(t *testing.T) {
for _, tt := range testCases {
expected := fmt.Sprintf("%v", tt.output)
actual := fmt.Sprintf("%v", WordCount(tt.input))
if expected != actual {
t.Fatalf("%s\n\tExpected: %v\n\tGot: %v", tt.description, expected, actual)
} else {
t.Logf("PASS: %s - WordCount(%s)", tt.description, tt.input)
}
}
}

Below are examples of the failure situation:

1.
Expected: map[two:1 red:1 blue:1 one:1 fish:4]
Got: map[one:1 fish:4 two:1 red:1 blue:1]
2.
Expected: map[one:1 fish:4 two:1 red:1 blue:1]
Got: map[red:1 blue:1 one:1 fish:4 two:1]
3.
Expected: map[java:1 javascript:1 car:1 carpet:1 as:1]
Got: map[javascript:1 car:1 carpet:1 as:1 java:1]
...

<strike>Additional information are here:
http://exercism.io/submissions/cf94f4732fd97335be2e755f&lt;/strike>

答案1

得分: 3

你不能使用!=来比较expectedactual,因为它比较的是映射的字符串表示,所以只会随机工作(如果值以相同的顺序打印)。你需要使用reflect包的DeepEqual()方法来比较这些映射:

import "reflect"
// ...

if !reflect.DeepEqual(tt.output, WordCount(tt.input)) {
// ...

它首先检查两个映射是否都为nil,然后检查它们是否具有相同的长度,最后检查它们是否具有相同的(键,值)对的集合。

英文:

You can't compare expected and actual with !=, because it compares the string representation of the maps, so it will work only randomly (if the values are printed in the same order).

What you have to do, is to use the reflect package DeepEqual() method to compare the maps :

import &quot;reflect&quot;
// ...
if !reflect.DeepEqual(tt.output, WordCount(tt.input)) {
// ...

It will first checks if both maps are nil, then if they have the same length, then if they have the same set of (key, value) pairs.

答案2

得分: 2

你不是在比较两个地图,而是在比较两个地图的String()输出。然而,当地图被打印或使用range()函数时,内容是随机选择的,所以你不能将其与字符串进行比较。

你可以先比较它们的长度,然后对其中一个地图使用range()函数,并检查第一个地图中每个键的值是否存在且等于第二个地图中相同键的值。

英文:

You are not comparing two maps, you are comparing the String() output of two maps. However, when a map is printed or range()'d, the content is randomly picked, so you cannot compare it with strings.

You could compare lengths first, then range() one of them and check if the value of every key in the first map is present and equal to the value of the same key in the second map.

huangapple
  • 本文由 发表于 2014年2月13日 12:09:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/21745073.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定