Запускать тесты nunit параллельно с параметрами (nunit 3.8.x) - PullRequest
0 голосов
/ 05 мая 2018

Я хочу запустить мои тесты на селен параллельно и установить следующее в файле 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 голосов
/ 05 мая 2018

Одним из возможных ответов без nunit будет небольшой сервис, который доставляет параметры. Поэтому каждый параллельный тест должен вызывать веб-сервис и получать его уникальные параметры. Веб-сервис будет возвращать при каждом вызове следующий набор параметров.

Если бы я предоставил 10 различных наборов параметров и выполнил бы 3 теста параллельно, я вполне могу быть уверен, что 3 параллельных теста никогда не получат одинаковые параметры. Предполагается, что все тестовые случаи требуют почти одинакового времени.

Я бы назвал это хаком, поэтому я прошу решение об объединении.

0 голосов
/ 07 мая 2018

Как насчет использования одноэлементного шаблона для выделения из набора паролей на основе идентификатора потока.

Краткое объяснение,

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

Очевидно, вам потребуется как минимум количество доступных учетных данных, так как вы намерены запускать потоки параллельно, или вы получите исключение по очереди.

0 голосов
/ 05 мая 2018

Использовать атрибут nunit TestCase ("data") Пример:

 [TestCase("differentUserName", "password")]
 public void MyTest(string username, string password)          
 {  
   // Test steps
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...