Юнит-тестирование библиотеки баз данных в C # и NUnit - PullRequest
1 голос
/ 20 июля 2010

Я недавно начал использовать NUnit, а теперь Rhino Mocks.Теперь я готов начать использовать его в проекте на C #.

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

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

Итак, предположим, я хотел проверить FTP или соединение с базой данных.Я бы написал что-то вроде

[Test]
public void OpenDatabaseConnection_ValidConnection_ReturnsTrue()
{
  SomeDataBase db = new SomeDataBaseLibrary(...);
  bool connectionOk = db.Open();
  Assert.IsTrue(connectionOk);
}

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

[Test]
public void InsertData_ValidData_NoExceptions()
{
      SomeDataBase db = new SomeDataBaseLibrary(...);
      db.Open();

      db.InsertSomeRow("valid data", ...);
}

Я вижу несколько проблем с этим:

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

2) Другое дело, что, если SomeDataBaseLibrary изменится, то все методы тестирования также должны будут измениться.

3) Скорость теста снижается, когда все эти соединения должны устанавливаться при каждом запуске теста.

Как обычно это делается?

Iпонимаю, что я могу использовать макеты DataBaseLibrary, но это не проверяет саму библиотеку, что является моей первой целью в проекте.

Ответы [ 2 ]

1 голос
/ 20 июля 2010

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

http://www.nunit.org/index.php?p=attributes&r=2.2.10

Взгляните на:

TestFixtureSetUpAttribute (NUnit 2.1) Этот атрибут используется внутри TestFixture для предоставления единого набора функций, которые выполняются один раз перед выполнением любого из тестов в приборе.TestFixture может иметь только один метод TestFixtureSetUp.Если определено более одного, TestFixture успешно скомпилируется, но его тесты не будут выполняться.

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

Я считаю, что это также решает вашу третью проблему.

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

0 голосов
/ 21 июля 2010

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

  1. Как указал @sbenderli, вы можете использовать TestFixtureSetUp, чтобы запустить соединение, и написать почти пустой тест, который просто подтверждает состояние соединения с БД. Я думаю, что вам просто нужно отказаться от идеала «1 ошибка -> 1 тест, который не пройден», поскольку несколько тестов требуют подключения к тестовой базе данных. Если использование вашего уровня доступа к данным имеет какие-либо побочные эффекты (например, кеширование), будьте особенно внимательны в отношении взаимодействующих тестов (<-link может быть поврежден). </li>
  2. Это хорошо. Тесты должны продемонстрировать, как использовать SUT (тестируемое программное обеспечение - в данном случае SomeDataBaseLibrary). Если изменение в SUT требует изменения в том, как оно используется, вы хотите знать. В идеале, если вы внесете изменение в SomeDataBaseLibrary, которое нарушит клиентский код, оно сломает ваши автоматические тесты. Независимо от того, есть ли у вас автоматические тесты или нет, вам придется что-то менять в зависимости от SUT; Автоматические тесты - это еще одна вещь, которую нужно изменить, но они также сообщают вам, что вы должны внести указанное изменение.
  3. позаботился с TestFixtureSetUp.

Еще одна вещь, о которой вы, возможно, уже позаботились: InsertData_ValidData_NoExceptions не очищает после себя, что приводит к взаимодействующим тестам. Я обнаружил, что самый простой способ сделать так, чтобы тесты очищались после себя, - это использовать TransactionScope : просто создайте его в своем классе SetUp и утилизируйте его в TearDown. По моему опыту работает как шарм (с совместимыми базами данных).

EDIT: Если у вас есть логика подключения в TestFixtureSetup, вы все равно можете проверить соединение следующим образом:

[Test]    
public void Test_Connection() 
{
  Assert.IsTrue(connectionOk);
}

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

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