Модульный, интеграционный или функциональный тест? - PullRequest
1 голос
/ 11 апреля 2019

Простой вопрос: Как вы различаете функцию, модуль и интеграционный тест?

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

public function prices()
{
    return $this->hasMany(Prices::class);
}


public function getPriceAttribute($)
{
    return $this->prices()->first() * 2;
}

Описание тестов, как я их понимаю (не стесняйтесь меня поправлять):

Единицаtest

  • Проверяет наименьшую часть вашего кода
  • Не касается базы данных
  • Не взаимодействует с какой-либо другой частью системы

Интеграционный тест

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

Функциональный тест

  • Тест Blackbox
  • например, Вызовите конечную точку API, убедитесь, что она вернула правильный ответ JSON

Вот моя проблема, учитывая эти описания:

  • Мой тест модели Laravel должен проверить наименьшую единицу кода - вычисленный метод доступа модели, который делает егочувствую, что юнит-тест
  • Но, это касается базы данных при загрузкеОтношения модели
  • Это не похоже на интеграционный тест, потому что он касается только связанных моделей, а не внутренних или внешних сервисов
  • Другие тесты доступа к свойствам в Laravel подпадают под юнит-тесты, когда онине касайтесь базы данных или связей модели
  • Разделение этих типов тестов на интеграционные тесты будет означать, что тесты одной модели по своим свойствам фрагментированы между интеграционными и юнит-тестами

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

Ответы [ 2 ]

2 голосов
/ 11 апреля 2019

Если я правильно интерпретирую ваш исходный вопрос, я думаю, что ограничение убийцы здесь:

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

Если насмешка запрещена, и вам необходимо прикоснуться к БД, то, по вашему / и определению Google, она должна рассматриваться как тест интеграции / среднего размера :)


Я так думаю об этом, чтобы получить функциональность атрибута price отдельно от БД. Хотя это в модели, цены могут прийти откуда угодно. Сейчас это СУБД, но что если ваша организация станет действительно большой и разделится на другую службу? По сути, я считаю, что способность getPriceAttributes отличается от хранения атрибутов:

public function getPriceAttribute($)
{
    return $this->prices()->first() * 2;
}

Если вы купитесь на это рассуждение, оно создаст логическое разделение, которое поддерживает модульные тесты. prices() можно смоделировать, чтобы получить коллекцию из 0, 1 и многих (2) результатов. Этот тест может быть выполнен как модульные тесты (для более быстрого выполнения теста на несколько порядков (т. Е. Порядка 1 мс против потенциально 10 с или 100 с мс при разговоре с локальной БД)


Я не знаком с тестовой экосистемой php, но один из способов сделать это может быть с помощью специфичного для теста подкласса (не уверен, что следующее действительное PHP: p):

class PricedModel extends YourModel {
   function __construct($stub_prices_supporting_first) {
     $this->stub_prices = $stub_prices_supporting_first;
   }

   public function prices() {
     return $this->stub_prices;
   }

}

Тесты

function test_priced_model_0_prices() {
   p = new PricedModel(new Prices(array()));
   assert.equal(null, p.getPriceAttribute());
}

function test_priced_model_1_price() {
   p = new PricedModel(new Prices(array(1)));
   assert.equal(2, p.getPriceAttribute());
}

function test_priced_model_2_prices() {
   p = new PricedModel(new Prices(array(5, 1)));
   assert.equal(10, p.getPriceAttribute());
}

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

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

0 голосов
/ 18 апреля 2019

Что отличает тесты, так это их цель:

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

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

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

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

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

...