【问题标题】:How to write unit tests to check that methods are thread-safe如何编写单元测试来检查方法是否是线程安全的
【发布时间】:2017-06-23 18:53:05
【问题描述】:

我有一个这样的对象:

type Store struct {
    mutex sync.RWMutex
    data  map[string]int
}

func (s * Store) Read(key string) int, error {
    // ...
    defer s.mutex.RUnlock()
    s.mutex.RLock()
    // ...
    return val, nil
}

func (s * Store) Write(key string, value int) error {
    // ...
    defer s.mutex.Unlock()
    s.mutex.Lock()
    // ...
    return nil
}

对于方法ReadWrite 的单元测试应该如何检查它们是否是线程安全的?

我认为这样的案例已经存在模式,但我没有找到任何东西。

我读到了-race flag:

竞争检测器只能在运行代码实际触发竞争条件时检测它们,这意味着在实际工作负载下运行支持竞争的二进制文件很重要

我的问题是如何编写模拟实际工作负载的单元测试。

【问题讨论】:

  • 阅读go documentation 中的-race 构建/测试标志。
  • @Adrian 嗨,我读到了关于 -race 标志的信息:“竞争检测器只有在运行代码实际触发竞争条件时才能检测到竞争条件,这意味着在实际工作负载下运行支持竞争的二进制文件很重要" 我的问题是如何编写模拟实际工作负载的单元测试。
  • 通过编写一个模拟现实工作负载的测试......没有简单的答案。这取决于你的具体情况。你必须自己弄清楚那部分。
  • 单元测试不打算在实际工作负载下运行。如果您正在测试实际的工作负载,则根据定义,您不是在运行单元测试。对于您想要的测试类型,最好的办法是在生产式负载下运行-race-built 二进制文件。但不要将此与单元测试混淆,后者的目的完全不同。

标签: multithreading unit-testing go


【解决方案1】:

使用Race detector 运行您的测试。简而言之,运行:

go test -race

或者要构建一个普通的二进制文件,例如在登台服务器上运行,使用:

go build -race

但是还有更多选择,所以最好阅读一下:)

如果您的目标是在实际负载下进行测试,您最好的选择是使用go build -race 编译您的代码,然后在实际负载下运行它。这可能意味着在登台服务器上。但不要将此与单元测试混淆!

单元测试用于测试单元——代码的一小部分,通常是单个函数。负载/竞争测试是一种不同的野兽,需要不同的工具和完全不同的方法。

Go 可以轻松地使用竞赛检测器运行单元测试这一事实很好,并且经常会捕获竞赛。但它不会,也不应该期望捕获所有种比赛,因为单元测试执行的性质与生产执行的性质完全不同。

【讨论】:

  • 另外不要忘记竞争条件只是可能的并发错误之一。其他是死锁、活锁和饥饿。所有这四个都很难通过单独测试来消除,尽管测试可以证明它们的概率低于某个阈值。更多:bigbeeconsultants.uk/post/2008/four-horsemen
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-12
  • 1970-01-01
  • 2018-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多