t.me/atinfo_chat Telegram группа по автоматизации тестирования

C# Nunit TestCase or TestSourse or ValueSource.

Теги: #<Tag:0x00007f748b39c338> #<Tag:0x00007f748b39c220> #<Tag:0x00007f748b39c0b8> #<Tag:0x00007f7488ed3ec0> #<Tag:0x00007f7488ed3da8>

У меня сейчас такая задача. Тест принимает значения enum и tuple. Попробовала TestCase
[TestCase(DictionaryService.App.MCS)] - все отлично
[TestCase(DictionaryService.App.MCS, OrderingCenterDictionary.AdditionalOrderParameters[0])] - не работает. Хотя этот вариант предпочтительней.

Попробовала ValueSource. Сбилдилось без ошибок. Но финиш на первой же строке, фактически даже не начавшись (вот:
CustomerOrderStoppedAndCanBeResumedWhileStoppingProcess(MCS,(API1 ProductionCommenttiqrADwojhiXOWbjpXEieKUHOVZRjQeqeQKFuZIzJvfjFLNfFoIeLFarorLvKuHRshQGcyEpfaRmOOnNXIWOUThplHoupjKOnrzDstpsfwJhYIJEBwncPIlTqqCBuMHDHAgVjeEhfXcsgLQnrwSgeOqXRtrWeBbknwINPDRQYXiiMILBEoqhSwQjCmixviKITiccOrfflXjPkqUMreblFSjGucRkQzObNqgBjXCuWvRMtvBjPVYedHIVjdqdZiz, API_PO_CustomerOrder4, 270976, CM, Customer, Ordered))

public static List<Tuple<string, string, string, string, string, string>> AdditionalOrderParameters => new List<Tuple<string, string, string, string, string, string>>
        {
           new Tuple<string, string, string, string, string, string>(@"API1 ProductionComment" + GetRandom.String(255), "API_PO_CustomerOrder4", GetRandom.Int(100000, 999999).ToString(), OrderingCenterDictionary.Categories.FirstOrDefault(s => s == "CM"), OrderingCenterDictionary.OrderTypeDictionary.FirstOrDefault(s => s == "Customer"), "Ordered"),                   
        };
        private static DictionaryService.App[] NullOrBlankCases = {
            DictionaryService.App.Super,
            DictionaryService.App.MCS
        };

        [Test]
        public void CustomerOrderStoppedAndCanBeResumedWhileStoppingProcess([ValueSource("NullOrBlankCases")] DictionaryService.App requestor, [ValueSource("AdditionalOrderParameters")] Tuple<string,string,string,string,string,string> additionalparameters)
        { ... }

И проблема в Tuple. Если его убрать - все ок.

Что-то у Вас муть какая-то, почему бы не использовать TestCaseSource, который позволяет любые данные в тест передать? Да и сам метод, предоставляющий данные тест-кейсу, способен принимать параметры.

И не используйте new Tuple, делайте именованные кортежи, это удобнее.

(string testName, int Age) tuple;
tuple.Age = 5;
tuple.testName = "test";

В примере с листом можно писать так
List<(string Name, int Age)>

Откопал какой-то древний тест, где тоже использовал длинные кортежи (на самом деле это неудобно, это я понял в последствии и лучше использовать какую-то модель, с которой работать удобнее и в плане передачи её 1 аргументом, так и при необходимости расширять):

Метод предоставляющий данные. Два последних аргумента у него это enum:

public static IEnumerable<TestCaseData> ProvideC2CData(string testName,
    C2CCreateOrderPage.SenderDocument document, C2CCreateOrderPage.PayMethod payMethod)
{
    var rnd = StaticRandom.Random;
    const string senderFio = "P"; // only one letter, bcs input so slow.
    var senderPhone = "925" + rnd.GetString(7, "1234567890");
    const string issuedBy = "ОВД КАПОТНЯ";
    var serialNum = "4510" + rnd.NextUInt(100000, 999999);
    var weight = Math.Round(rnd.NextDouble(1.1, 3.7), 2).ToString(CultureInfo.InvariantCulture);
    var receiverFio = rnd.GetString(6) + " " + rnd.GetString(4) + " " + rnd.GetString(10);
    var receiverPhone = "916" + rnd.GetString(7, "1234567890");
    const string receiverMail = "auto@test.fake";
    var service = C2CCreateOrderPage.ReceiverService.Pickup.GetDescription();
    var tuple = (senderFio, senderPhone, document, issuedBy,
        serialNum, weight, receiverFio, receiverPhone, receiverMail, service, payMethod);
    yield return new TestCaseData(tuple).SetName(
        $"{testName} (\"{document.GetDescription()}\", \"{payMethod.GetDescription()}\")");
}

Тест-кейс, использующий этот метод:

[TestCaseSource(typeof(CollectionDataForC2CTests), nameof(CollectionDataForC2CTests.ProvideC2CData),
    new object[]
    {
        NewC2C + NewC2CCurrentPvz, C2CCreateOrderPage.SenderDocument.DriverLicense,
        C2CCreateOrderPage.PayMethod.Cashless
    })]
[AllureTag(AlureTag)]
[Category("C2C")]
[NonParallelizable]
public void CreateC2CCurrentPvz(
    (string senderFio, string senderPhone, C2CCreateOrderPage.SenderDocument senderDoc, string senderDocIssuedBy, string senderDocSeriaNum, string weight, string receiverFio, string receiverPhone, string receiverMail, string service, C2CCreateOrderPage.PayMethod payMethod) tuple)
{
    ....
}

Как видно, это очень неудобно, передавать кучу всего в кортеже.

Ну и так же можно передавать аргументом в метод, предоставляющий данные массив объектов. Т.е. один метод может вернуть вам бесконечное количество тест-кейсов, особенно если использовать апи/бд для получения каких-то коллекций, и для каждого вхождения возвращать кейс.
Либо массив внутри массива и прохождение по ещё большему количеству вхождений. Тут уж от фантазии зависит, ну либо от требований :slight_smile:

Но, ещё раз подчеркну, не стоит использовать кортеж, если он длиннее 3-4 элементов.

Кортеж, на мой взгляд, идеально подходит в случае, если из функции надо вернуть более 1 значения, и не хочется прибегать к out.
В таком случае у вас ещё и именованные возвращенные значения будут, для удобства и вспомнить что и для чего возвращалось.

1 Симпатия