Свойства UnitTesting в .Net?

Я работаю над библиотекой, которую хочу выпустить с открытым исходным кодом. Я начал писать тесты для кода, и мне было интересно, как я должен тестировать свойство в объекте .Net. Допустим, у меня есть следующее:


public class Person{
    #region variables
    private string _name = String.Empty;
    private string _surname = String.Empty;
    #region properties
    public string Name{
        get{
             return _name;
        }
    }
    public string Surname{
        get{
            return _surname;
        }
        set{
            _surname = value;
        }
    }
}

У меня два вопроса по коду:

  1. Как выполнить модульное тестирование свойства, имеющего только метод получения (например, Name в примере)
  2. Как выполнить модульное тестирование свойства с помощью установщика и получателя (например, Surname в примере)

Я хочу протестировать свойства, которые настолько просты, потому что я уже обнаружил ошибки в другом коде, когда Itellinsense выполнял неправильное автозаполнение, а свойство не возвращало правильную переменную.

Обновлять:

Я не говорю о простых свойствах, как в примере, у них есть некоторая логика, и их довольно сложно отладить. Написание теста, который использует сеттер для проверки получателя и наоборот, нехорошо, потому что если произойдет сбой, я не буду знать, какой метод виноват. Я использую свойства, потому что они были добавлены как общедоступные переменные, и позже пришлось добавить дополнительную логику.

Ответов (9)

Решение

Как выполнить модульное тестирование свойства, имеющего только метод получения (например, Name в примере)

На самом деле не так уж отличается от тестирования, если у вас был сеттер. вам просто нужно найти другой способ определения вывода. Может быть в ctor или в результате других установщиков / операций с объектом.

[Test]
public void NamePropTest()
{
    Person p = new Person();

    //Some code here that will set up the Person object
    //  so that you know what the name will be

    Assert.AreEqual("some known value...", p.Name);
}

Если бы у нас были сеттеры для Name и SurName, но только геттер для FullName, тест мог бы выглядеть так:

[Test]
public void NamePropTest()
{
    Person p = new Person();

    p.Name = "Sean";
    p.Surname = "Penn";

    Assert.AreEqual("Sean Penn", p.FullName);
}

Мой вопрос больше связан с КАК написать тест. Я думал об этом, и мне нужно получить доступ к частным значениям, чтобы убедиться, что свойства работают должным образом, иначе я не знаю, как это сделать. https://stackoverflow.com/users/59332/mandel

Хорошо ... раз уж вы настаиваете на том, чтобы знать, как это сделать ....

[Test]
TestMethod()
{

    Person p = new Person();
    p.Name = "a name";
    p.Surname = "a surname";

    Assert.That(p.Name, Is.EqualTo("a name"));
    Assert.That(p.Surname, Is.EqualTo("a surname"));
}

Однако это работает, только если у вас есть сеттеры ....

Если у вас есть только геттеры, я могу придумать только два способа сделать это.

  1. заранее знать возвращаемое значение и утверждать против него.
  2. Используйте Reflection, чтобы установить значение, а затем подтвердить это известное значение.

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

Эти свойства должны быть там, потому что они нужны вам. Что касается них, то должны быть модульные тесты, у вас уже должно быть покрытие для них. Если нет сценария, в котором они нужны, возможно, их вообще не должно быть.

Насколько я понимаю, вам не следует тестировать свойства (т.е. те, которые просто получить / установить).

Я не уверен, какую версию C# вы используете. Но вы можете использовать автоматические свойства, чтобы избежать простых проблем с установкой / получением, с которыми вы сталкиваетесь.

См. Эту ссылку

Дон тратит ваше время на написание глупых тестов для геттеров и сеттеров.

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

Я думаю, вам стоит проверить их, если вы напишете их так, как вы это сделали. В конце концов, вы можете ошибиться при вводе.

Просто что-то вроде

var person = New Person();
person.Surname = "test";
Assert.AreEqual("test", person.Surname);

В конце концов, TDD и модульное тестирование в целом сводятся к тому, чтобы избежать как можно большего количества ошибок.

Если вы случайно написали это.

public class Person{
    #region variables
    private string _name = String.Empty;
    private string _surname = String.Empty;
    #region properties
    public string Name{
        get{
             return _name;
        }
    }
    public string Surname{
        get{
            return _name;
        }
        set{
            _name = value;
        }
    }
}

тогда у вас будет ошибка.

Тестирование автоматических свойств, возможно, менее ценно. Но это другой вопрос.

Вы должны проверить свойства. Также автоматические свойства!

Unittests гарантирует, что изменения в программе не нарушат ее.

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

Даже если вы используете автоматические свойства (как замену полям / переменным-членам), причина для создания их свойств заключается в том, что вы захотите позже изменить их реализацию. Тогда вы захотите, чтобы тесты были там.

РЕДАКТИРОВАТЬ: (В ответ на комментарий Шахкалпеша ...)

Если вы меняете реализацию, тесты также могут потребовать изменения. Итак, я не знаю, почему кто-то должен тестировать простой get / set?

Начиная с этого класса:

public class TimeOfDay
{
    public int Hour{get; private set;}
    public int Minute{get; private set;}

    public TimeOfDay(int hour, int minute)
    {
        Hour = hour;
        Minute = minute;
    }
}

При изменении реализации тесты остаются в силе!

public class TimeOfDay
{
    public int _minutesSinceMidnight = 0;

    public int Hour
    {
        get { return _minutesSinceMidnight / 60; }
        set { _minutesSinceMidnight = value * 60 + Minutes; }
    }

    public int Minute
    {
        get { return _minutesSinceMidnight % 60; }
        set { _minutesSinceMidnight = Hour * 60 + value; }
    }

    public TimeOfDay(int hour, int minute)
    {
        Hour = hour;
        Minute = minute;
    }
}

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

Я думаю, вы имели в виду, что ваше свойство только для получения использует частные поля или другие частные данные. Если вам нужно их установить, единственный способ - получить их с помощью Reflection (см. Все (что-то) классы Info в System.Reflection). Но есть жесткая дискуссия, является ли это хорошей практикой.

Дон тратит ваше время на написание глупых тестов для геттеров и сеттеров.

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

Вы должны протестировать все, что находится в открытом доступе, включая свойства. Если вы не тестируете свойство, вы рискуете, что кто-то может добавить в него логику, нарушив функциональность.

Также не стоит полагаться на его тестирование в других тестах. Это делает ваши тесты хрупкими и затрудняет определение проблемы, поскольку тест будет проверять более одного объекта.