首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Go中测试管道

如何在Go中测试管道
EN

Software Engineering用户
提问于 2020-08-15 20:52:09
回答 1查看 804关注 0票数 3

在Go中,我经常使用“通道管道”模式,如下所示:

代码语言:javascript
复制
// 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)

我反复遇到的问题是,我必须测试这些管道函数的许多不同特性:

  • 将一个值放入输入通道时,将一个值放在输出通道上。
  • 当您不将输出通道放在输入通道上时,它不会在输出通道上放值。
  • 如果输出通道在输入通道上出现值后花费太长时间,则超时。
  • 当输入通道关闭时关闭输出通道。
  • 在关闭输入通道之前不关闭输出通道。
  • 对输入执行正确的转换。

此外,这只是一个很简单的例子。更典型的情况如下所示,在这个例子中,我们试图使用冗余温度传感器来查找输出中的错误:

代码语言:javascript
复制
// 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 }
        }

    }
}

现在,我必须测试管道函数(safify)的数量显著增加:

  • 当在所有输入通道上得到输出通道时,将值放在输出通道上。
  • 如果没有在所有输入通道上获得输出通道值,则不会在输出通道上设置值。
  • 如果输出通道在所有三个输入通道上输入后花费的时间太长,但只需要全部三个输入通道,则超时。
  • 在任何输入通道关闭时关闭输出通道。
  • 如果没有关闭输入通道,则不会关闭输出通道。
  • 如果第一个通道与其他信道有很大的不同,则标志为非isSafe,其中包含超时。
  • 如果第二个信道与其他信道有很大差异,则标记为非isSafe,并带有超时。
  • 如果第三个通道与其他信道有很大差异,则标记为非isSafe,并带有超时。
  • 如果所有通道都与其他通道有很大差异,则标记为非isSafe,并带有超时。

此外,这三个输入通道可能彼此不同步,这就增加了比上面显示的更多的复杂性。

看来,很多这些检查(特别是那些与正确计算有关的检查)对于Go中的任何扇入式通道管道函数都是常见的,而停止问题保证了我们必须为所有这些操作使用超时,除非我们希望停止测试的测试依赖于被测试函数的停止和最终的信道推送行为。

考虑到这些类型的测试是如此的相似,以及我如何编写非常类似的测试--本质上是测试这些通道管道功能与基本通道管道功能的一致性,而不是函数的行为--一次又一次,是否也有:

  1. 围绕这类通道管道功能可靠性测试的标准实践
  2. 测试信道本机功能的标准的或完善的框架或框架集?
EN

回答 1

Software Engineering用户

发布于 2020-08-16 18:27:54

你混合了两种不同的关注点。如果对管道进行了单独的抽象,则可以对其进行一次测试。比如(原谅语法,我不知道去吧):

代码语言:javascript
复制
func double(v int) int {
    return v * 2
}

pipeline(in, out, double)

代码语言:javascript
复制
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)

如果没有参数多态,就不能真正进行完全通用的pipeline抽象,因此您必须接受一定数量的复制。但是,您至少应该能够将管道模式的关注点与更特定于应用程序的逻辑分离开来。

票数 2
EN
页面原文内容由Software Engineering提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://softwareengineering.stackexchange.com/questions/414861

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档