Как написать тестовый пример nunit для кода ниже c#? Как написать тестовые примеры для методов без аргументов? - PullRequest
0 голосов
/ 14 апреля 2020

Как мне написать модульный тест (используя nUnit) класс, у которого есть методы без аргументов в c#? Я вызываю этот метод showinfo () в Program.cs. Я хочу написать тестовый пример для этого ... но так как он не содержит аргументов, как я могу его протестировать?

 public void showInfo() //no arguments are passes here and im calling this in Program.cs
            {
                int indexNum;
                string inId = Convert.ToString(Console.ReadLine());//taking Id as input 
                Console.Write("Enter account Password :");
                string inPass = Convert.ToString(Console.ReadLine());//taking password

                if (myId.Contains(inId)&&myPass.Contains(inPass))
                {
                    Console.ForegroundColor= ConsoleColor.Green;
                    Console.WriteLine("Login Success!", Console.ForegroundColor);
                    Console.ResetColor();
                    indexNum = Array.IndexOf(myId, inId);

                    Console.WriteLine("Your details: ");
                    Console.WriteLine("Name: " + myName[indexNum]);
                    Console.WriteLine("Id: " + myId[indexNum]);
                    Console.WriteLine("Acc Type: " + myAccType[indexNum]);
                    Console.WriteLine("Date of Joining: " + myDob[indexNum]);
                    Console.WriteLine("Domain: " + myDomain[indexNum]);
                    Console.WriteLine("Manager: " + myManager[indexNum]);
                    //Console.WriteLine("Employee name: " + empl_name[indexNum]);
                    //Console.WriteLine(myId);
                }
                else
                {
                    Console.ForegroundColor = ConsoleColor.Red;
                    Console.WriteLine("Login Error!",Console.ForegroundColor);
                    Console.ResetColor();
                }
            }

Ответы [ 2 ]

1 голос
/ 14 апреля 2020

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

Что вы хотите проверить? В самом простом случае вы захотите проверить базовый c счастливый путь , где пользователь вводит правильный пароль (подробнее об этом через минуту) и выводятся правильные данные учетной записи. Вы также захотите проверить «несчастный путь», когда пользователь вводит неверный пароль, и вместо данных учетной записи пользователя отображается сообщение об ошибке.

Еще более усложняется то, что в контексте вашего code, Console.WriteLine - это сторонняя зависимость, хотя и из надежного источника. В модульном тесте наша цель состоит в том, чтобы выделить единицу работы . Это означает, что вы не хотите вызывать реальный Console.WriteLine в методе, который вы тестируете модулем. Однако, поскольку Console.WriteLine является методом c, трудно макетировать , который вы обычно применяете для изоляции единицы работы. Конечно, вы все еще хотите убедиться, что детали, которые будут записаны на экран, соответствуют ожидаемым. Существует несколько подходов к этому, но самый простой, вероятно, состоит в том, чтобы отделить код, который создает пользовательский вывод, от кода, который фактически отображает его .

Другая проблема заключается в том, что этот метод зависит от состояния. в классе Program (поля myId, myPass, myName и c). В модульном тесте вам нужно контролировать значения, которые вы передаете в эти переменные, и вы не можете сделать это, если они являются c членами вашего Program класса. Для начала вы можете передать их в свой метод showInfo(), позволяющий контролировать то, что вы передаете в модульный тест.

Резюме: чтобы сделать этот код тестируемым, вам нужно разбить его на более мелкие компоненты. что вы можете выполнить модульное тестирование индивидуально.

Примечание: ваш .Contains тест для идентификатора пользователя и пароля выглядит подозрительно, что произойдет, если два человека имеют одинаковый пароль?

Редактировать Вот пример того, как вы можете разбить этот метод на более мелкие методы, которые могут быть индивидуально проверены модулем. Обратите внимание, что в этот код еще можно внести улучшения, но я намеренно оставил этот код очень похожим на код в OP, чтобы было легче проводить сравнения между ними:

public class Class1
{
    public void showInfo(
        string[] myId,
        string[] myPass,
        string[] myName,
        string[] myAccType,
        string[] myDob,
        string[] myDomain,
        string[] myManager)
    {
        int indexNum;
        string inId = Convert.ToString(Console.ReadLine());//taking Id as input 
        Console.Write("Enter account Password :");
        string inPass = Convert.ToString(Console.ReadLine());//taking password

        if (IsPasswordValid(inId, inPass, myId, myPass))
        {
            var successOutputLines = GetSuccessOutput(
                inId,
                myId,
                myPass,
                myName,
                myAccType,
                myDob,
                myDomain,
                myManager);
            successOutputLines.ToList().ForEach(l => Console.WriteLine(l));
        }
        else
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine("Login Error!", Console.ForegroundColor);
            Console.ResetColor();
        }
    }

    public bool IsPasswordValid(
        string userId,
        string passwordIn,
        string[] userIds,
        string[] passwords)
    {
        var userIndex = Array.IndexOf(userIds, userId);
        if (userIndex == -1)
            throw new ArgumentException(nameof(userId));
        var expectedPassword = passwords[userIndex];
        return expectedPassword == passwordIn;
    }

    public IEnumerable<string> GetSuccessOutput(
        string userId,
        string[] myId,
        string[] myPass,
        string[] myName,
        string[] myAccType,
        string[] myDob,
        string[] myDomain,
        string[] myManager)
    {
        var userIndex = Array.IndexOf(myId, userId);
        if (userIndex == -1)
            throw new ArgumentException(nameof(userId));

        var lines = new List<string>();
        lines.Add("Login Success!");
        lines.Add("Your details: ");
        lines.Add("Your details: ");
        lines.Add("Name: " + myName[userIndex]);
        lines.Add("Id: " + myId[userIndex]);
        lines.Add("Acc Type: " + myAccType[userIndex]);
        lines.Add("Date of Joining: " + myDob[userIndex]);
        lines.Add("Domain: " + myDomain[userIndex]);
        lines.Add("Manager: " + myManager[userIndex]);

        return lines;
    }
}

затем напишите модульные тесты для методов IsPasswordValid и GetSuccessOutput.

0 голосов
/ 14 апреля 2020

Существует много способов тестирования методов без аргументов, частные методы и т. Д. c. Вам просто нужно что-то настроить, поэтому, когда вы тестируете свой метод, он вызывает другой метод (с аргументами)

В вашем AssemblyInfo.cs вы добавляете атрибут

#if DEBUG #then
InternalsVisibleTo("your test project")`.
#endif

. сделайте что-то подобное в своем классе, который вы хотите проверить

public class A
{
#if DEBUG #then
    private MethodParameters _testParameters

    internal void SetMethodParameters(MethodParameters testParameters)
    {
        _testParameters = testParameters
    }
#endif
    public void NoArgumentMethod()
    {
#if DEBUG #then
        if (_testParameters)
        {
            PrivateArgumentMethod(_testParameters);
            return;
        }
#endif 
        // collect your arguments here and pass to private method
        var mp = new MethodParameters();
        mp.Id = _someId;
        // . . . . . 
    }

    private void PrivateArgumentMethod(MethodParameters testParameters)
    {
         // execute here
    }

    internal class MethodParameters
    {
        public int Id {get; set;}
        // more properties here
    }
}

Как видите, это довольно запутанно. Есть и другие варианты этого. Самое важное - вы могли заметить, что вам нужно компилировать и запускать модульные тесты в режиме DEBUG, чтобы некоторый код был доступен для модульного тестирования, но не в выпусках сборки. Для этого используйте условную компиляцию.

Но правда в том, что это плохой дизайн! Вы должны разрабатывать свои классы таким образом, чтобы вы могли по-настоящему тестировать важные функции и выполнять функциональные. тесты. Вы можете использовать насмешки и т. Д. c. Дизайн впереди. То, что я только что показал - мы используем для тестирования некоторого старого кода, где его написали люди - логики пользовательского интерфейса c, логарифы BLL c и логики доступа к данным c в одном файле. Нет пути, вы должны написать новый код, подобный этому

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...