Должен ли я конструкторам модульных тестов? Скажем, у меня есть такой конструктор:
IMapinfoWrapper wrapper;
public SystemInfo(IMapinfoWrapper mapinfoWrapper)
{
this.wrapper = mapinfoWrapper;
}
Нужно ли мне писать модульный тест для этого конструктора? У меня нет геттеров для переменной-оболочки, поэтому мне не нужно это проверять.





Нет. Его функциональность будет проверяться любым другим модульным тестом класса.
Не каждый, если внутри него несколько конструкторов или несколько потоков управления.
да. Если у вас есть логика в конструкторе, вы должны ее протестировать. Простая установка свойств не является логикой ИМО. Условные выражения, поток управления и т. д. Логика IS.
Редактировать: Вероятно, вам следует проверить, когда IMapinfoWrapper имеет значение null, если эта зависимость требуется. Если да, то это логика, и у вас должен быть тест, который ловит ваше исключение ArgumentNullException или что-то еще ... ваши тесты - это спецификации, которые определяют, как ведет себя код. Если он вызывает исключение ArgumentNullException, это следует указать в тесте.
Я никогда не вкладываю логику в свои конструкторы. Просто сеттеры.
@BrianGenisio, спасибо за совет, я только что добавил несколько тестов ArgumentNullException и код в свое приложение ... по какой-то причине его никогда не было ...
Модульное тестирование - это тестирование общедоступных состояний, поведения и взаимодействия ваших объектов.
Если вы просто установите частное поле в своем конструкторе, что там тестировать?
Не беспокойтесь о модульном тестировании ваших простых средств доступа и мутаторов. Это просто глупо и никому не помогает.
Если в вашем конструкторе есть, например, if (условие), вам необходимо протестировать оба потока (true, false). Если ваш конструктор выполняет какую-то работу перед установкой. Вы должны проверить, что работа выполнена.
Что делать, если у вас есть checkArgumnt в конструкторе (возможно, чтобы проверить, является ли объект нулевым или нет)? Стоит ли это тестировать?
Да, часто стоит тестировать конструкторы с их собственным сложным поведением.
Я знаю, что опаздываю на эту вечеринку, но, вообще говоря, я не считаю конструкторы хорошим местом для размещения логики или проверок. Вместо использования, например, каких-то валидаторов запросов для операций с вашими классами, для меня может быть больше смысла. Хотя мы должны проверять нулевую ссылку в конструкторе, но все же я не вижу смысла в модульном тестировании, почему? потому что ваша операция должна завершиться неудачей, если этот объект имеет значение null, что имеет смысл "поведение" терпит неудачу, и мы должны проводить модульное тестирование, а не реальных конструкторов.
Я верю в 100% покрытие. Также 100% покрытие, не просто путем тестирования простых взаимодействий с помощью насмешек или просто настройки и получения вещей, а за счет большего количества интеграционных / приемочных тестов, проверяющих функциональность. Поэтому, если вы в конечном итоге напишете действительно хорошие тесты интеграции / приемки, все ваши конструкторы (и простые методы, такие как сеттеры и геттеры) должны быть вызваны.
100% покрытие - это несбыточная мечта, и любой, кто говорит вам иное, продает вам новый блестящий инструмент для тестирования. ;) Я шучу ... вроде.
Это может быть проблемой в устаревших системах, но если вы начинаете новый проект с нуля, на мой взгляд, 100% - единственный выход. Я работал над системами со 100% покрытием. Тестируем все, проехали.
Хорошо, у вас 100% покрытие. Но вы проверили все пути выполнения? Первое не подразумевает второго.
Истинных 100% можно легко достичь с помощью тестов, которые ничего не делают, кроме заглушек и тестов на микроуровне. Но 100% покрытие тестами, которые вы считаете функцией системы. paths придадут вам большую уверенность при обслуживании или новой работе, даже если не учитывается путь выполнения каждый.
Другими словами, 100% coverage of that you believe to be the system's functional paths.: не 100%.
Какое поведение экземпляра SystemInfo зависит от значения wrapper?
Если что-то может пойти не так (например, нулевое значение вызывает поломку), я предлагаю написать сценарии, описывающие каждую такую ситуацию, и использовать их для определения соответствующих модульных тестов.
Если все сценарии в конечном итоге зависят от состояния или поведения частного экземпляра IMapinfoWrapper, я бы предложил вместо этого написать модульные тесты для этого класса.
Модульное тестирование - это проверка путей выполнения, что часто называют Цикломатическая сложность.
Если у вас нет пути для выбора, нет, если, нет цикла, нет GOTO (= P), это не очень полезно
Я не согласен с вами, что тестирование метода без каких-либо if / loops / gotos не имеет смысла. Всегда существует хотя бы один путь выполнения, и вы должны проверить его, даже если он единственный.
Эрик, как насчет проверки граничных случаев - и проверки репрезентативных значений между границами. Например, входные значения 0 и 1 могут считаться граничными случаями для функции извлечения квадратного корня, потому что там входные и выходные значения равны. Так что проверьте, например, -10, -1, -0,5, 0, 0,5, 1 и 10. Или также тестирование во всем диапазоне. Если ваша функция должна работать для входов до 4096, попробуйте 4095 и 4097 ...
В: Если вы устанавливаете переменную-член в конструкторе, зачем вы ее устанавливаете?
A: Потому что у вас есть неудачный модульный тест, который можно пройти, только установив его в конструкторе.
Если вы используете эту логику, когда вы пишете только код, обеспечивающий прохождение модульного теста (разработка через тестирование), то у вас уже будет ответ на свой вопрос.
Нет, если вы не пишете компилятор, потому что вы только проверяете, может ли компилятор генерировать код для выполнения назначений, что обычно бессмысленно.
Теперь, в более обычной ситуации, если вы хотите сделать что-то еще с оболочкой, тогда, возможно, в этом есть смысл. Например, вы можете сгенерировать исключение ArgumentNullException, если попытаетесь передать значение null, и теоретически это может иметь модульный тест. Даже тогда ценность теста довольно минимальна.
Лично я почти никогда не тестирую конструкторы явно. Если они достаточно сложны, чтобы требовать тестирования, мне кажется, что код немного дурно пахнет.
Если конструктор содержит некоторую логику, например инициализацию класса, я думаю, вам следует протестировать сам конструктор. Или вы можете поговорить с разработчиком о том, что инициализация в конструкторе снизит тестируемость тестируемого кода.
Во многих средах, регулируемых FDA, более критический код должен быть протестирован на 100% ... включая создание классов. Таким образом, тестирование конструкторов иногда необходимо независимо от того, нужно ли тестировать их или нет. Кроме того, компании, использующие инструменты статического анализа, должны будут убедиться, что ВСЕ члены данных класса правильно инициализированы, чтобы не иметь ошибок, хотя код может работать плавно и без ошибок. Обычно инициализация элемента данных выполняется в конструкторе ... просто пища для размышлений.
у вас есть ссылка на требование FDA?
Также необходимо тестирование средств доступа и мутаторов, если разработчик не убедился, что никакая логика состояния не может быть изменена. Например, если используется шаблон проектирования для синглтона, часто используются средства доступа или свойства, а если класс не инициализирован, это делается из средства доступа, поскольку конструктор является частным. В C++ можно сделать свои функции константными или статическими, в которых члены данных класса не могут быть изменены. (Примечание: даже использование static немного рискованно, поскольку эти переменные часто являются глобальными.) Однако без теста, если кто-то не может использовать превентивные меры, как вы можете гарантировать со 100% точностью, что написанное не может стать ошибкой из-за время? Техническое обслуживание вряд ли надежно.
По-разному.
Я бы не стал писать специальный тест конструктора для чего-то столь же простого, как приведенный вами пример.
Однако, если у вас есть логические тесты в конструкторе, такие как проверка параметров, то да, безусловно. Хотя, как и в случае с исходным плакатом, я по возможности не работаю в конструкторе, обычно требуется проверка параметров. В этом случае неизбежно препятствовать выполнению конструктором работы некоторый. Если в конструкторе есть логика, всегда есть вероятность, что он может быть неправильным, поэтому я отношусь к нему так же, как к любому другому вызову метода, и проверяю его соответствующим образом.
Вы обязательно должны протестировать конструктор. Если у вас есть конструктор по умолчанию, вы должны проверить, можно ли его вызвать. Что, если позже класс будет изменен - возможно, он станет одноэлементным или конструктор по умолчанию будет удален в пользу одного, требующего параметров? В этом случае тест должен завершиться неудачно, чтобы предупредить об этом изменении (чтобы класс или тест можно было исправить в соответствии с новым требованием).
Наличие конструктора по умолчанию - это требование, которое должно пройти проверку. Даже если все, что делает конструктор, устанавливает частные члены, которые будут проверяться в другом месте, необходимо проверить наличие конструктора без параметров.
Это старая угроза, но я полностью согласен, конструктор по умолчанию должен быть протестирован, а другие конструкторы должны быть протестированы, чтобы обеспечить желаемое поведение при отсутствии необходимых аргументов. С внедрением зависимостей вполне возможно, что конструктор по умолчанию может вызвать круговой цикл зависимостей, который вы никогда не увидите, если никогда не будете использовать конструктор по умолчанию.
Все приведенные там примеры (кроме, возможно, перехода на синглтон, но в этом случае не должно быть даже общедоступного конструктора по умолчанию для тестирования) - это вещи, которые приведут к ошибке компилятора. Нет необходимости не просто тестировать конструктор без логики с помощью модульного теста, но это действительно пустая трата времени и денег. Если у конструктора есть логика (кроме простой установки свойств), то его обязательно нужно протестировать. Также @EtienneCharland, конструктор по умолчанию, по определению не имеет зависимостей (вообще без параметров), поэтому он не может создать циклический цикл зависимостей.
Я думаю, что ответ на это «Да».
Существует множество кода, который, к ужасу, предполагает инициализированное состояние объекта вместо нулевой ссылки - часто, когда в конструкторе не назначены явные значения.
Я рад, что тесты конструктора прерваны, чтобы предупредить меня об изменении инициализированных значений общедоступных членов. Речь идет о защитном тестировании - я прагматичен и больше рад иметь тесты, чем нет, и удаляю их, когда оказывается, что они бесполезны или полезны.
Я тестирую конструкторы, если они содержат логику - например, проверка или условная установка частного состояния. Ошибки проверки заканчиваются исключением, создаваемым конструктором. Успешное выполнение заканчивается созданием объекта, который демонстрирует определенное поведение в зависимости от состояния, установленного в конструкторе. В любом случае это требует тестирования. Но тесты конструктора утомительны, потому что все они выглядят одинаково - вызовите конструктор, сделайте утверждение. Объявления методов тестирования часто занимают больше места, чем вся логика тестирования ... Поэтому я написал простую библиотеку тестирования, которая помогает писать декларативные тесты для конструкторов: Как легко протестировать логику валидации в конструкторах на C#
Вот пример, в котором я пробую семь тестовых примеров для конструктора одного класса:
[TestMethod]
public void Constructor_FullTest()
{
IDrawingContext context = new Mock<IDrawingContext>().Object;
ConstructorTests<Frame>
.For(typeof(int), typeof(int), typeof(IDrawingContext))
.Fail(new object[] { -3, 5, context }, typeof(ArgumentException), "Negative length")
.Fail(new object[] { 0, 5, context }, typeof(ArgumentException), "Zero length")
.Fail(new object[] { 5, -3, context }, typeof(ArgumentException), "Negative width")
.Fail(new object[] { 5, 0, context }, typeof(ArgumentException), "Zero width")
.Fail(new object[] { 5, 5, null }, typeof(ArgumentNullException), "Null drawing context")
.Succeed(new object[] { 1, 1, context }, "Small positive length and width")
.Succeed(new object[] { 3, 4, context }, "Larger positive length and width")
.Assert();
}
Таким образом, я могу протестировать все соответствующие случаи для моего конструктора, не набирая много текста.
Правда, я об этом даже не подумал. хлопает по лбу