我对单元测试很陌生,目前正在尝试使用Visual Studio的测试工具。
我的问题是如何在这些测试中定义关于并发行为的断言。例如。给定一个实现有界通道的类BoundedChan<T>
,我如何指定像
channel.Send
不会阻止”或channel.Send
将会阻止,直到读取一个值”有没有一个优雅的解决方案来编写这些断言?
答案 0 :(得分:6)
这是讨论该主题的blog article;它侧重于NUnit。
不幸的是,并发仍然是单元测试的一个领域,很容易构建。这不是一个简单的问题,仍然需要在测试中实现一些自己的同步和并发逻辑。
对于您提供的示例,可能无法编写最终证明某个方法在某些条件下会阻止或不会阻止的测试。您可以通过首先创建您希望阻塞行为的最坏情况来获得某种程度的置信度 - 然后编写测试以确定是否发生这种情况。
答案 1 :(得分:4)
这个问题可能会导致足够的内容填满一本书。
通常,我不建议为您的类添加单元测试以用于并发方案。通过练习,我认为您将了解到自动化单元测试有一个或几个“最佳点” - 将您的工作重点放在这些领域(并在其他领域使用其他实践)可以获得更好的投资回报率。
但是你的类似乎是关于并发(基于提供的信息无法确定),因此这可能是你真正想要进行并发模拟测试的情况。
如果您愿意,您可以(据我所知)在单元测试中启动多个线程。但可能有一种更简单的方法。考虑利用Compose Method模式。虽然我们正在研究这个问题 - 这种模式对于所有人的有效单元测试非常关键,而不仅仅是并发性。
答案 2 :(得分:1)
我创建了一个帮助程序,可以启动一堆线程来执行并发操作。帮助程序提供同步原语和日志记录机制。 它可以与任何单元测试框架一起使用。这是来自单元测试的代码片段:
[Test]
public void TwoCodeBlocksInParallelTest()
{
// This static method runs the provided Action delegates in parallel using threads
CTestHelper.Run(
c =>
{
Thread.Sleep(1000); // Here should be the code to provide something
CTestHelper.AddSequenceStep("Provide"); // We record a sequence step for the expectations after the test
CTestHelper.SetEvent();
},
c =>
{
CTestHelper.WaitEvent(); // We wait until we can consume what is provided
CTestHelper.AddSequenceStep("Consume"); // We record a sequence step for the expectations after the test
},
TimeSpan.FromSeconds(10)); // This is a timeout parameter, if the threads are deadlocked or take too long, the threads are terminated and a timeout exception is thrown
// After Run() completes we can analyze if the recorded sequence steps are in the correct order
Expect(CTestHelper.GetSequence(), Is.EqualTo(new[] { "Provide", "Consume" }));
}
它可用于测试客户端/服务器或组件中的同步,或者只是运行超时的线程。我将在接下来的几周内继续改进这一点。这是项目页面: Concurrency Testing Helper
答案 3 :(得分:0)
这应该是一个有趣的阅读 - &gt; http://c2.com/cgi-bin/wiki?ExtremeProgrammingChallengeFourteen