Сведения о вопросе

None

09:10, 17th August, 2020

Теги

Базы Данных Модульного Тестирования

Просмотров: 485   Ответов: 9

Этим летом я разрабатывал базовое приложение ASP.NET/SQL Server CRUD, и модульное тестирование было одним из требований. Я столкнулся с некоторыми неприятностями, когда пытался протестировать их с помощью базы данных. Насколько я понимаю, модульные тесты должны быть:

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

Эти требования, по-видимому, противоречат друг другу при разработке базы данных. Например, я не могу проверить Insert(), не убедившись, что вставляемые строки еще не существуют, поэтому мне нужно сначала вызвать Delete(). Но что, если их там еще нет? Тогда мне нужно было бы сначала вызвать функцию Exists().

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

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

Итак, что же сделало сообщество SO, столкнувшись с этой ситуацией?


tgmdbm сказал:

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

Так что, если я правильно прочитал это, на самом деле нет никакого способа эффективно провести модульное тестирование уровня доступа к данным. Или же "unit test" уровня доступа к данным будет включать тестирование, скажем, команд SQL/, генерируемых классами, независимо от фактического взаимодействия с базой данных?



  Сведения об ответе

LIZA

02:30, 19th August, 2020

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

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

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


  Сведения об ответе

VERSUION

04:28, 12th August, 2020

DBunit

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


  Сведения об ответе

ASSembler

14:21, 28th August, 2020

Обычным решением для внешних зависимостей в модульных тестах является использование фиктивных объектов - то есть библиотек, имитирующих поведение реальных объектов, с которыми вы проводите тестирование. Это не всегда просто, и иногда требуется некоторая изобретательность, но есть несколько хороших (бесплатных) макетов библиотек для .Net, если вы не хотите "roll your own". Две сразу приходят на ум:

Носорог издевается над тем, что имеет довольно хорошую репутацию.

NMock -это другое.

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

В database mocks это означает "mocking" ваш собственный слой доступа DB с объектами, которые возвращают составленные объекты таблицы, строки или набора данных для обработки модульными тестами.

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


  Сведения об ответе

DO__IT

10:31, 24th August, 2020

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

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


  Сведения об ответе

screen

13:29, 7th August, 2020

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

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

Шаблоны Модульного Тестирования


  Сведения об ответе

dumai

21:06, 1st October, 2020

Я объяснил технику, которую я использовал для этой самой ситуации здесь .

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

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


  Сведения об ответе

piter

21:42, 13th August, 2020

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


  Сведения об ответе

9090

08:05, 4th August, 2020

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


    [TestFixture]
    public class TrannsactionScopeTests
    {
        private TransactionScope trans = null;

        [SetUp]
        public void SetUp()
        {
            trans = new TransactionScope(TransactionScopeOption.Required);
        }

        [TearDown]
        public void TearDown()
        {
            trans.Dispose();
        }

        [Test]
        public void TestServicedSameTransaction()
        {
            MySimpleClass c = new MySimpleClass();
            long id = c.InsertCategoryStandard("whatever");
            long id2 = c.InsertCategoryStandard("whatever");
            Console.WriteLine("Got id of " + id);
            Console.WriteLine("Got id of " + id2);
            Assert.AreNotEqual(id, id2);
        }
    }


  Сведения об ответе

DAAA

10:35, 25th August, 2020

Если вы используете LINQ - SQL в качестве ORM, то вы можете создать базу данных on-the-fly (при условии, что у вас есть достаточный доступ из учетной записи, используемой для модульного тестирования). Видите http://www.aaron-powell.com/blog.aspx?id=1125


Ответить на вопрос

Чтобы ответить на вопрос вам нужно войти в систему или зарегистрироваться