Как выполнить постоянство модульного теста?

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

Я знаю, что технически это будет интеграционный тест (а не модульный тест), но я хочу найти лучшие стратегии для следующего:

  1. Тестовые запросы.
  2. Тестовые вставки. Как я узнаю, что вставка пошла не так, если она вышла из строя? Я могу проверить это, вставив, а затем запросив, но как я могу узнать, что запрос был неправильным?
  3. Тестирование обновлений и удалений - так же, как тестовые вставки

Каковы лучшие практики для этого?


Что касается тестирования SQL: я знаю, что это можно сделать, но если я использую O / R Mapper, например NHibernate, он добавляет некоторые бородавки именования в псевдонимах, используемых для выходных запросов, и, поскольку это несколько непредсказуемо, я не уверен Я могу проверить это.

Должен ли я просто отказаться от всего и просто доверять NHibernate? Я не уверен, что это разумно.

Ответов (10)

Решение

Загляните в блок БД. Это библиотека Java, но должен быть эквивалент C#. Это позволяет вам подготовить базу данных с набором данных, чтобы вы знали, что находится в базе данных, а затем вы можете взаимодействовать с DB Unit, чтобы увидеть, что находится в базе данных. Он может работать со многими системами баз данных, поэтому вы можете использовать свою фактическую настройку базы данных или использовать что-то еще, например HSQL в Java (реализация базы данных Java с опцией в памяти).

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

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

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

Для проектов на основе JDBC можно использовать мой фреймворк Acolyte: http://acolyte.eu.org . Он позволяет смоделировать доступ к данным, которые вы хотите протестировать, используя абстракцию JDBC, без необходимости управлять конкретной тестовой БД.

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

DbUnit (Java)

DbUnit.NET

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

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

Технически юнит-тесты устойчивости не являются юнит-тестами. Это интеграционные тесты.

С помощью C# MBUnit, вы просто использовать SqlRestoreInfo и RollBack атрибуты:

    [TestFixture]
    [SqlRestoreInfo(<connectionsting>, <name>,<backupLocation>]
    public class Tests
    {
      
        [SetUp]
        public void Setup()
        {
        
        }

        [Test]
        [RollBack]
        public void TEST()
        {
           //test insert. 
        }
    }

То же самое можно сделать и в NUnit, за исключением того, что названия атрибутов немного отличаются.

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

Ибо NHibernate я определенно рекомендую просто имитировать NHibernate API модульные тесты для - доверять библиотеке делать правильные вещи. Если вы хотите убедиться, что данные действительно поступают в БД, выполните интеграционный тест.

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

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

С уважением,

Роб Джи

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