与参数并行运行nunit测试(nunit 3.8.x)

时间:2018-05-04 21:47:25

标签: c# selenium-webdriver nunit

我想并行运行我的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个不同的参数。

任何想法如何实现?

3 个答案:

答案 0 :(得分:2)

如何使用单例模式从一组基于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

显然,当您打算并行运行线程时,您需要至少拥有可用凭据的数量,否则您将在出列时获得异常。

答案 1 :(得分:0)

使用nunit TestCase(&#34; data&#34;)属性 示例:

 [TestCase("differentUserName", "password")]
 public void MyTest(string username, string password)          
 {  
   // Test steps
  }

答案 2 :(得分:0)

没有nunit的一个可能的答案是提供参数的小服务。因此,每个并行测试应调用Web服务并获取其唯一参数。每次调用时,webservice都将返回下一个参数集。

如果我提供10个不同的参数集,并且并行运行3个测试,我可以肯定的是,3个并行测试永远不会得到相同的参数。假设所有测试用例几乎需要相同的时间。

我称之为黑客,因此我要求一个nunit解决方案。