Testing 使用Go'生成随机数字和字母字符串;s";“测试/快速”;包裹

Testing 使用Go'生成随机数字和字母字符串;s";“测试/快速”;包裹,testing,go,unicode,generator,unicode-normalization,Testing,Go,Unicode,Generator,Unicode Normalization,这几天来,我一直在为这件事伤脑筋,似乎无法理解。也许这是显而易见的,但我似乎无法发现。我已经阅读了unicode、UTF-8、UTF-16、规范化等的所有基础知识,但都没有用。希望有人能在这里帮助我 我正在使用包中的Go的Value函数为我的数据结构中的字段生成随机值,以便为所讨论的结构实现。具体来说,给定一个元数据结构,我将实现定义如下: 现在,我想我已经试过了几乎所有的方法,但我总是以一系列远离拉丁语范围的字符串结束,例如: 令人困惑的是,Generate接口需要一个使用类型而不是指向类

这几天来,我一直在为这件事伤脑筋,似乎无法理解。也许这是显而易见的,但我似乎无法发现。我已经阅读了unicode、UTF-8、UTF-16、规范化等的所有基础知识,但都没有用。希望有人能在这里帮助我

我正在使用包中的Go的
Value
函数为我的数据结构中的字段生成随机值,以便为所讨论的结构实现。具体来说,给定一个
元数据
结构,我将实现定义如下:

现在,我想我已经试过了几乎所有的方法,但我总是以一系列远离拉丁语范围的字符串结束,例如:


令人困惑的是,Generate接口需要一个使用类型而不是指向类型指针的函数。您希望您的类型签名看起来像

func(m元数据)生成(r*rand.rand,size int)(值reflect.value)

你可以玩这个。注意:在这个操场上要做的最重要的事情是将generate函数的类型从
m Metadata
切换到
m*Metadata
,然后看到Hi-Mom!从不打印

此外,我认为使用您自己的类型并使用您想要使用的所有字符的列表为该类型编写生成方法会更好。例如:

func (l LatinString) Generate(rand *rand.Rand, size int) reflect.Value {
    var buffer bytes.Buffer
    for i := 0; i < size; i++ {
        buffer.WriteString(string(latin[rand.Intn(len(latin))]))
    }
    s := LatinString(buffer.String())
    return reflect.ValueOf(s)
}
然后使用发电机

func(l拉丁字符串)生成(rand*rand.rand,size int)reflect.Value{
变量缓冲区字节。缓冲区
对于i:=0;i


编辑:这个库也很酷,谢谢你给我展示它

我自己问题的答案似乎是@nj_u和@jimb评论中提供的答案和@benjaminkadish提供的答案的组合

简言之,答案归结为:

  • “不是你想象中的好主意”或“有点不适定的问题”
  • “您使用的是字母、拉丁语和数字的并集(
    Letter | | | | | | | | | | |拉丁语
    ),而不是“拉丁语”与字母和数字的并集(
    (Letter | | Number)和拉丁语)
  • 现在看更长的版本

    我使用
    测试/quick
    软件包背后的想法是我想要随机数据(模糊)测试我的代码。过去,我总是自己一次又一次地编写类似的代码。这意味着在不同的项目中有很多相同的代码。现在,我当然可以为它编写自己的包,但事实证明,甚至比这更好的是,实际上有一个标准包,它完全符合我的要求需要

    现在,事实证明,这个包完全符合我的要求。它生成的字符串中的代码点实际上是随机的,而不仅仅限于我们在日常生活中习惯使用的代码点。现在,这当然正是你在进行模糊测试时想要做的事,以便用超出常规值的值测试代码假设

    实际上,这意味着我遇到了两个问题:


    <> LI>对于一个字符串,我认为合理的输入有一些限制。这意味着,在测试<代码>名称<代码>字段或<代码> URL< /Cord>字段时,我可以合理地假设不会有像“James Mc”这样的值。⌢' (更不用说“James McYou”了,你从随机unicode码点开始,但尝试只过滤非常小的一个子集的拉丁字符,因此即使你使用这种方法,你在大多数情况下也只能得到空字符串。是的,我已经意识到了这一点。但是,过滤后我仍然不会得到空字符串。我主要关心的是h为什么它似乎不起作用。-所以你可能会得到任何(拉丁字母号)-这是一个可能的大量字符。啊哈!是的,当然!这不是交叉点!非常感谢你指出…将尽快更新帖子(同时指出JimB早些时候的小子集评论)你有没有考虑过使用随机输入测试?谢谢你指出了指针部分。你的建议确实是合乎逻辑的解决办法。问题是,像这样的事情正是我为了生成测试数据而反复做的。这意味着我必须重新定义生成随机字符串的函数基本上,我需要很多额外的代码,在我需要的地方重复,结果证明我可以很容易地用一个标准包来替换。
    func runefilter(in reflect.Value) (out reflect.Value) {
        out = in // Make sure you return something
        if in.Kind() == reflect.String {
            instr := in.String()
            t := transform.Chain(norm.NFD, runes.Remove(runes.NotIn(rangetable.Merge(unicode.Letter, unicode.Latin, unicode.Number))), norm.NFC)
            outstr, _, _ := transform.String(t, instr)
            out = reflect.ValueOf(outstr)
        }
        return
    }
    
    Confusingly the Generate interface needs a function using the type not a the pointer to the type. You want your type signature to look like

    func (m Metadata) Generate(r *rand.Rand, size int) (value reflect.Value)

    You can play with this here. Note: the most important thing to do in that playground is to switch the type of the generate function from
    m Metadata
    to
    m *Metadata
    and see that Hi Mom! never prints.

    In addition, I think you would be better served using your own type and writing a generate method for that type using a list of all of the characters you want to use. For example:

    type LatinString string
    const latin = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz01233456789"
    
    func (l LatinString) Generate(rand *rand.Rand, size int) reflect.Value {
        var buffer bytes.Buffer
        for i := 0; i < size; i++ {
            buffer.WriteString(string(latin[rand.Intn(len(latin))]))
        }
        s := LatinString(buffer.String())
        return reflect.ValueOf(s)
    }