使用参数并行运行 nunit 测试 (nunit 3.8.x)
Posted
技术标签:
【中文标题】使用参数并行运行 nunit 测试 (nunit 3.8.x)【英文标题】:Run nunit tests parallel with parameters (nunit 3.8.x) 【发布时间】:2018-05-04 21:47:25 【问题描述】:我想并行运行我的 selenium 测试并在我的 assembly.cs 中设置以下内容。
[assembly: Parallelizable(ParallelScope.Fixtures)]
好的,好的。这行得通。
这是代码结构的一个简短示例
using NUnit.Framework;
namespace MyExample
[TestFixture]
[Category("TestsRunningWithLogin1")]
public class Test_Example1
[Test, Order(1)]
public void Test1()
[Test, Order(2)]
public void Test2()
[TestFixture]
[Category("TestsRunningWithLogin2")]
public class Test_Example2
[Test, Order(1)]
public void Test1()
[Test, Order(2)]
public void Test2()
测试需要用户名和密码,并在网页中执行某些操作。登录等当前在 OneTimeSetUp 方法中处理。该网页将上次使用的视图保存在用户设置中。
如果我按顺序运行测试,我没有问题,因为测试不会相互影响。所有测试都可以使用相同的用户名运行。
如果我并行运行,它们可能会相互影响。比如test1配置了一个视图,test2中不应该看到的。
我的想法是为不同的用户运行这些课程(其中有很多)。当测试开始时,它应该使用一个用户名,当前并行运行的测试不使用该用户名。目前我不知道nunit并行运行了哪些测试,所以无法直接参数化。
我没有找到任何控制并行测试的方法。我可以定义是否并行以及并行执行的数量。我想要的是,提供并行运行测试参数。如果我有 3 个并行运行的测试类,我想给出所有 3 个不同的参数。
有什么想法可以实现吗?
【问题讨论】:
我会先阅读 NUnit 文档并尝试一些代码。完成后,如果它不起作用,请发布您尝试的内容和结果(以及任何错误消息)。 如果您能提供minimal reproducible example,那就太好了。 抱歉,不太容易描述。我希望它现在更容易理解了。 【参考方案1】:如果使用单例模式从一组基于 threadid 的密码中分配呢?
快速解释,
IThreadCredentials 是一个描述凭据的接口,无论它们在您的情况下是什么样子。
ThreadCredentials 是我编写的一个实现 IThreadCredentials 的简单类。
ICredentialManager 是一个接口,用于描述如何分配和返回凭据。
CredentialManager.Instance 是在您的设备之间共享以借用和返回凭据的单例。
public interface IThreadCredentials
string UserName get;
string Password get;
public class ThreadCredentials : IThreadCredentials
public ThreadCredentials(string userName, string password)
this.UserName = userName;
this.Password = password;
public string UserName get;
public string Password get;
public interface ICredentialManager
IThreadCredentials GetCredentialsFromPool();
void ReturnCredentialsToPool();
public sealed class CredentialManager : ICredentialManager
private static readonly Lazy<CredentialManager> lazy = new Lazy<CredentialManager>(() => new CredentialManager());
private static readonly object syncRoot = new object ();
private static readonly Queue<IThreadCredentials> availableCredentialQueue = new Queue<IThreadCredentials>();
private static readonly IDictionary<int, IThreadCredentials> credentialsByThread = new Dictionary<int, IThreadCredentials>();
private CredentialManager()
IEnumerable<IThreadCredentials> availableCredentials = new[]new ThreadCredentials("Foo", "FooPassword"), new ThreadCredentials("Bar", "BarPassword");
foreach (IThreadCredentials availableCredential in availableCredentials)
availableCredentialQueue.Enqueue(availableCredential);
public static CredentialManager Instance => lazy.Value;
public IThreadCredentials GetCredentialsFromPool()
return GetCredentialsFromPool(Thread.CurrentThread.ManagedThreadId);
public void ReturnCredentialsToPool()
ReturnCredentialsToPool(Thread.CurrentThread.ManagedThreadId);
private static IThreadCredentials GetCredentialsFromPool(int threadId)
lock (syncRoot)
IThreadCredentials result;
if (credentialsByThread.TryGetValue(threadId, out result))
return result;
// This presupposes you have enough credentials for the concurrency you are permitting
result = availableCredentialQueue.Dequeue();
credentialsByThread.Add(threadId, result);
return result;
private static void ReturnCredentialsToPool(int threadId)
lock (syncRoot)
if (credentialsByThread.ContainsKey(threadId))
IThreadCredentials credentials = credentialsByThread[threadId];
credentialsByThread.Remove(threadId);
availableCredentialQueue.Enqueue(credentials);
用法:
在您的测试夹具设置中,您可以执行以下操作:
IThreadCredentials credentials = CredentialManager.Instance.GetCredentialsFromPool();
// Now you can use credentials for whatever
在拆解中,您可以
CredentialManager.Instance.ReturnCredentialsToPool();
// Then promise you stop using those credentials
显然,在并行运行线程时,您至少需要有足够数量的可用凭据,否则在出队时会出现异常。
【讨论】:
【参考方案2】:使用 nunit TestCase("data") 属性 示例:
[TestCase("differentUserName", "password")]
public void MyTest(string username, string password)
// Test steps
【讨论】:
感谢 Magesh,我知道这个属性。问题是,如何控制哪个并行运行的实例获取哪个参数。由于 nunit “随机”启动并行测试,它可能会发生,并行测试使用相同的参数。这是我想避免的。【参考方案3】:没有 nunit 的一个可能答案是提供参数的小服务。所以每个并行测试都应该调用一个 web 服务,并且会得到它唯一的参数。 Web 服务将在每次调用时返回下一个参数集。
如果我提供 10 个不同的参数集,并并行运行 3 个测试,我可以非常确定,3 个并行测试永远不会得到相同的参数。假设所有测试用例需要几乎相同的时间。
我将其称为 hack,因此我要求提供 nunit 解决方案。
【讨论】:
以上是关于使用参数并行运行 nunit 测试 (nunit 3.8.x)的主要内容,如果未能解决你的问题,请参考以下文章
运行 vstest.console.exe 时如何过滤 NUnit 测试