Поэтому я пытаюсь сделать свои юнит-тесты как можно более простыми, но это становится проблематичным, когда я тестирую несколько простых методов добавления / удаления.
Для метода add мне нужно создать фиктивный объект и добавить его, а затем, после успешного прохождения теста, я должен удалить фиктивный объект.
И для теста удаления мне, очевидно, нужно создать фиктивный объект, чтобы я мог его удалить.
Как вы можете видеть, если один тест не пройден, другой тоже не удастся, так как они оба нужны.
То же самое с системой, в которой вам нужно было бы написать тест «Отмена заказа» ... ну, сначала нужно было бы сделать какой-нибудь фиктивный заказ, чтобы отменить его, не противоречит ли это принципам модульного тестирования?
Как такие случаи должны рассматриваться?
источник
Ответы:
Ну, нет ничего плохого в том, что ты делаешь. Несколько тестов могут охватывать один и тот же код; это просто означает, что одна проблема приведет к сбою нескольких тестов. Чего вы хотите избежать, так это тестов, которые зависят от результатов других тестов. То есть, ваш тест на удаление зависит от того, был ли запущен тест на добавление, и, таким образом, если вы выполните тест на удаление ДО вашего теста на добавление, он потерпит неудачу. Чтобы избежать этой проблемы, убедитесь, что у вас есть «чистый лист» в начале каждого теста, чтобы то, что происходит в данном тесте, не могло повлиять на последующие тесты.
Отличный способ сделать это - запустить тесты для базы данных в памяти.
В тесте добавления создайте пустую базу данных, добавьте объект и подтвердите, что он действительно был добавлен.
В своем тесте на удаление создайте базу данных, в которой уже будет удален объект. Удалите объект и подтвердите, что он был удален.
Унесите базу данных в свой код.
источник
Используйте транзакции.
Если вы используете базу данных, которая поддерживает транзакции, запустите каждый тест в транзакции. Откат транзакции в конце теста. Тогда каждый тест оставит базу данных без изменений.
Да, чтобы отменить заказ, вам сначала нужно будет его создать. Все в порядке. Тест сначала создает заказ, затем отменяет его, а затем проверяет, отменен ли заказ.
источник
Вы делаете это хорошо. Единственный фундаментальный принцип модульного тестирования состоит в том, чтобы охватить каждый путь кода, который вы имеете, так что вы можете быть уверены, что ваш код делает то, что должен, и продолжает делать это после изменений и рефакторингов. Делать юнит-тесты маленькими, простыми и одноцелевыми - это стоящая цель, но это не принципиально. Наличие теста, который вызывает два связанных метода вашего API, само по себе не вызывает сомнений, на самом деле, как вы отмечаете, это часто необходимо. Недостаток наличия избыточных тестов состоит лишь в том, что они требуют больше времени для написания, но, поскольку почти все в разработке, это компромисс, который вы должны делать постоянно, и лучшее решение почти никогда не является одним из крайних моментов.
источник
Методы тестирования программного обеспечения чрезвычайно разнообразны, и чем больше вы будете узнавать о них, вы начнете видеть множество разных (и иногда противоречивых) рекомендаций. Там нет ни одной «книги», чтобы пройти.
Я думаю, что вы находитесь в ситуации, когда вы видели некоторые рекомендации для модульных тестов, которые говорят такие вещи, как
и так далее. И все это правильно, в зависимости от того, как вы определяете «модульный тест» .
Я бы определил «модульный тест» как что-то вроде: «тест, который выполняет одну часть функциональности для одной единицы кода, изолированную от других зависимых компонентов».
Согласно этому определению, то, что вы делаете (если для запуска теста требуется добавить запись в базу данных), это вовсе не «модульный тест», а скорее то, что обычно называют «интеграционным тестом». (Настоящий модульный тест, по моему определению, не попадет в базу данных, поэтому вам не нужно добавлять запись перед ее удалением.)
Тест интеграции будет осуществлять функции , которая использует несколько компонентов (например, пользовательский интерфейс и базу данных), а также рекомендации , которые будут применяться к юнит - тесты не обязательно относится к интеграции тестов.
Как уже упоминали другие в своих ответах, то, что вы делаете, не обязательно неправильно, даже если вы делаете вещи, противоречащие руководству по тестированию. Вместо этого попробуйте рассуждать о том, что вы действительно тестируете в каждом методе тестирования, и если вы обнаружите, что вам нужно несколько компонентов, чтобы выполнить ваш тест, а некоторые компоненты требуют предварительной конфигурации, то продолжайте и сделайте это.
Но, прежде всего, понимайте, что существует много видов программных тестов (модульные тесты, системные тесты, интеграционные тесты, предварительные тесты и т. Д.), И не пытайтесь применять руководство одного типа ко всем остальным.
источник
Именно поэтому одно из других указаний - использовать интерфейсы. Если ваш метод берет объект, который реализует интерфейс вместо конкретной реализации класса, вы можете создать класс, который не зависит от остальной части кода.
Другой альтернативой является использование насмешливого фреймворка. Они позволяют легко создавать фиктивные объекты такого типа, которые можно передать в метод, который вы тестируете. Возможно, вам придется создать некоторые реализации-заглушки для класса-пустышки, но это все равно создает разделение от фактической реализации и того, чем занимается тест.
источник
Так?
Нет.
Несколько тестов могут быть независимыми и все не пройдены из-за одной и той же ошибки. Это на самом деле нормально. Многие тесты могут - косвенно - тестировать некоторые общие функции. И все терпят неудачу, когда общая функциональность нарушена. Ничего плохого в этом нет.
Модульные тесты определяются как классы точно, чтобы они могли легко обмениваться кодом, как обычная фиктивная запись, используемая для тестирования обновления и удаления.
источник
Вы можете использовать макет фреймворка или использовать «среду» с базой данных в памяти. Последний класс - это класс, в котором вы можете создать все необходимое для прохождения теста до его запуска.
Я предпочитаю последний - пользователи могут помочь вам ввести некоторые данные, чтобы ваши тесты стали ближе к реальному миру.
источник