Что не стоит тестировать, когда речь идет о модульном тестировании?

В каких частях проекта написание модульных тестов практически невозможно или практически невозможно? Доступ к данным? ftp?

Если на этот вопрос есть ответ, то 100% покрытие - это миф, не так ли?

Почему это не было закрыто как дубликат? stackoverflow.com/questions/62625/…, stackoverflow.com/questions/61400/what-makes-a-good-unit-tes‌ т и т. д.

raven 25.10.2008 23:45

Я думаю, что эти три вопроса разные, и их нужно обсуждать на разных страницах.

spinodal 29.10.2008 13:33

100% покрытие кода - это не миф, это асимптота.

James 23.02.2013 01:24
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
33
3
5 303
21
Перейти к ответу Данный вопрос помечен как решенный

Ответы 21

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

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

Кроме того, одного 100% покрытия кода недостаточно.

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

James McMahon 03.12.2008 18:12

Рад видеть кого-то, кто выступает за тестирование с реальными данными. Обычно мы имитируем / подставляем некоторые данные, но используем нашу базу данных для проверки достоверности тестов.

Beep beep 10.03.2009 07:54

но общение с тестовой базой данных было бы интеграционным тестом, а не модульным тестом ... Не так ли?

Robert Koritnik 03.08.2009 13:46

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

Garry Shutler 03.08.2009 20:20

@Garry: Да ... Поскольку мы можем использовать «фреймворк модульного тестирования» как для модульного тестирования, так и для интеграционного тестирования, возможно, нам пора начать называть его просто «фреймворком тестирования».

Alfred Myers 19.08.2009 23:42

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

Sklivvz 08.11.2010 02:24

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

То, что 100% покрытие - это миф, но это не означает, что 80% покрытие бесполезно. Конечно, цель - 100%, и между модульными и интеграционными тестами вы можете приблизиться к ней.

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

Странно, мягко говоря.

johnny 14.08.2018 18:36

Все, что требует очень большой и сложной настройки. Конечно, вы можете протестировать ftp (клиент), но тогда вам нужно настроить ftp-сервер. Для модульного тестирования вам понадобится воспроизводимая тестовая установка. Если вы не можете его предоставить, вы не можете его протестировать.

достижение 100% покрытия кода почти всегда расточительно. По этому поводу есть много ресурсов.

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

@GarryShutler

Я фактически тестирую электронную почту, используя поддельный SMTP-сервер (Wiser). Убедитесь, что код вашего приложения правильный:

http://maas-frensch.com/peter/2007/08/29/unittesting-e-mail-sending-using-spring/

Что-то подобное, вероятно, можно было бы сделать для других серверов. В противном случае вы сможете издеваться над API ...

Кстати: 100% покрытие - это только начало ... просто означает, что весь код фактически выполнил bean-компонент однажды .... ничего о крайних случаях и т. д.

Да, это возможно, но разве тогда это еще модульное тестирование? Где вы проводите грань между модульными и интеграционными тестами?

philant 21.09.2008 11:08

Ты прав; использование поддельных серверов было бы интеграционным тестированием ... издевательство над их интерфейсами было бы модульным тестированием.

p3t0r 21.09.2008 11:54

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

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

Конечно, часть ненужной обработки ошибок можно удалить. Но если в будущем будет ошибка кодирования, то это плохо.

Что бы вы не тестировали? Все, что не могло сломаться.

Когда дело доходит до покрытия кода, вы должны стремиться к 100% кода, который вы действительно пишете, то есть вам не нужно тестировать код сторонней библиотеки или код операционной системы, поскольку этот код будет доставлен вам протестированным. Если только это не так. В этом случае вы можете захотеть его протестировать. Или, если есть известные ошибки, в этом случае вы можете проверить наличие ошибок, чтобы получить уведомление о том, когда они будут исправлены.

«Что бы вы не испытали? Все, что не может сломаться». Очевидно, таких вещей не существует;)

Thomas 21.09.2008 04:07

Я считаю, что то, что не может сломаться, - это то, где труднее всего найти ошибки. Интересно, почему?

Matthew Scouten 21.09.2008 04:14

Держись! Я просто цитирую традиционное Agile-мышление: тестируйте все, что может сломаться. Такие вещи, как аксессоры, считаются «нерушимыми», поэтому нет необходимости в явном тестировании, они просто тестируются в ходе тестирования чего-то еще.

quamrana 28.09.2008 20:43

Предложение, возможно, следует перефразировать следующим образом: «все, что невозможно сломать, если не будет сломан также интерпретатор модуля компиляции». Или просто «все, что не может сломаться без нарушения среды выполнения».

Steen 04.11.2010 16:16

Большинство тестов, требующих огромных и дорогих (по стоимости ресурсов или времени вычислений) настроек, являются интеграционными. Модульные тесты должны (теоретически) тестировать только небольшие единицы кода. Индивидуальные функции.

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

Очень полезно проводить различие между юнит-тестами и интеграционными тестами. Модульные тесты должны выполняться очень быстро. Должно быть возможно легко запустить все ваши модульные тесты, прежде чем вы вернете свой код.

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

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

Основная причина использования кода модульного тестирования - это, прежде всего, проверка правильности дизайна вашего кода. Можно получить 100% покрытие кода, но не без использования фиктивных объектов или какой-либо формы изоляции или внедрения зависимостей.

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

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

Все остальное - это интеграционное тестирование.

Очевидный ответ на вопрос в заголовке: вам не следует проводить модульное тестирование внутренних компонентов вашего API, вам не следует полагаться на чье-то поведение, вы не должны тестировать то, за что вы не несете ответственности.

Остального должно хватить только на то, чтобы вы могли написать свой код внутри него, ни больше, ни меньше.

Конечно, 100% покрытие - хороший показатель Цель при работе над большим проектом, но для большинства проектов исправление одной или двух ошибок перед развертыванием не обязательно стоит времени на создание исчерпывающих модульных тестов.

Исчерпывающее тестирование таких вещей, как отправка форм, доступ к базе данных, доступ по FTP и т. д. На очень подробном уровне, часто является пустой тратой времени; если написанное программное обеспечение не требует очень высокого уровня надежности (99,999%), слишком много модульного тестирования может быть излишним и привести к потере в реальном времени.

Модульное тестирование графического интерфейса также сложно, хотя, как я полагаю, возможно.

Есть некоторые инструменты, которые выполняют автоматическое тестирование графических интерфейсов, хотя я сам ими не пользовался.

rlerallut 23.09.2008 00:43

При модульном тестировании вы не должны тестировать ничего, что не относится к вашему модулю; Другое дело - тестовые единицы в их контексте. Это простой ответ.

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

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

«Что не стоит тестировать, когда дело касается модульного тестирования?» * Бобы только с геттерами и сеттерами. Обоснование: Обычно пустая трата времени, которое лучше было бы потратить на тестирование чего-то другого.

Целью является не 100% покрытие кода и не 80% покрытия кода. Простота написания модульного теста не означает, что вы должны его писать, а сложность написания модульных тестов не означает, что вам следует избегать усилий.

Цель любого теста - выявить видимые пользователю проблемы наиболее доступным способом.

Стоит ли общая стоимость разработки, обслуживания и диагностики проблем, отмеченных тестом (включая ложные срабатывания), проблем, которые обнаруживает конкретный тест?

Если проблема, которую выявляет тест, «дорогая», вы можете позволить себе приложить усилия, чтобы выяснить, как ее протестировать, и поддерживать этот тест. Если проблема, которую обнаруживает тест, тривиальна, то написание (и поддержка!) Теста (даже при наличии изменений кода) лучше быть тривиальным.

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

Ответ принят как подходящий

Здесь Я нашел (через взломан что-то, что говорит Майкл Фезерс, может быть ответом:

Он говорит,

A test is not a unit test if:

  • It talks to the database
  • It communicates across the network
  • It touches the file system
  • It can't run at the same time as any of your other unit tests
  • You have to do special things to your environment (such as editing config files) to run it.

И снова в той же статье он добавляет:

Generally, unit tests are supposed to be small, they test a method or the interaction of a couple of methods. When you pull the database, sockets, or file system access into your unit tests, they are not really about those methods any more; they are about the integration of your code with that other software.

Я полностью с этим не согласен. Что делать, если рефакторинг кода, зависящего от базы данных?

Sklivvz 08.11.2010 02:22

@Skliwz: Вот для чего нужны интерфейсы / абстрактные классы и фиктивные объекты. Если она хорошо спроектирована и база данных подверглась рефакторингу, то затронутым классам нужно только принять во внимание интерфейс к базе данных.

Spoike 05.01.2011 14:25

Я не согласен с ответом quamrana относительно отказа от тестирования стороннего кода. Это идеальное использование модульного теста. Что, если в новом выпуске библиотеки появятся ошибки? В идеале, когда выпускается новая версия сторонней библиотеки, вы запускаете модульные тесты, которые представляют ожидаемое поведение этой библиотеки, чтобы убедиться, что она по-прежнему работает должным образом.

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

dss539 29.09.2009 21:10

@ dss539: Сторонние поставщики сталкиваются с теми же проблемами при разработке, что и все остальные. Если ваше бизнес-приложение зависит от сторонних библиотек, не кажется ли вам разумным устранить этот риск путем тестирования?

Mitch Wheat 30.09.2009 03:36

Конфигурация - еще один элемент, который очень сложно хорошо протестировать в модульных тестах. Интеграционные тесты и другое тестирование следует проводить в соответствии с конфигурацией. Это уменьшает избыточность тестирования и освобождает много времени. Попытка провести модульное тестирование конфигурации часто является несерьезной.

Все, что не является полностью детерминированным, недопустимо для модульного тестирования. Вы хотите, чтобы ваши модульные тесты ВСЕГДА проходили или терпели неудачу с одними и теми же начальными условиями - если на это могут повлиять странности, такие как потоки, или генерация случайных данных, или время / даты, или внешние службы, то вам не следует покрывать это в своих модульных тестах. . Время / даты - особенно неприятный случай. Обычно вы можете спроектировать код так, чтобы дата, с которой можно было работать, вводилась (с помощью кода и тестов), а не полагаться на функциональность в текущую дату и время.

Тем не менее, модульные тесты не должны быть единственным уровнем тестирования в вашем приложении. Достижение 100% покрытия модульными тестами часто является пустой тратой времени и быстро приводит к снижению отдачи.

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

FTP, SMTP, ввод-вывод в целом следует тестировать с использованием интерфейса. Интерфейс должен быть реализован с помощью адаптера (для реального кода) и макета для модульного теста.

Никакой модульный тест не должен проверять реальный внешний ресурс (FTP-сервер и т. д.)

Другие вопросы по теме