Я предложил бы дразнить Ваши вызовы к базе данных. Насмешки являются в основном объектами, которые похожи на объект, Вы пытаетесь обратиться к методу, в том смысле, что у них есть те же свойства, методы, и т.д. доступные вызывающей стороне. Но вместо того, чтобы работать безотносительно действия они программируются, чтобы сделать, когда конкретный метод называют, это пропускает это в целом, и просто возвращает результат. Тот результат обычно определяется Вами загодя.
для установки объектов для насмешки, вероятно, необходимо использовать своего рода инверсию управления / шаблон внедрения зависимости, как в следующем псевдокоде:
class Bar
{
private FooDataProvider _dataProvider;
public instantiate(FooDataProvider dataProvider) {
_dataProvider = dataProvider;
}
public getAllFoos() {
// instead of calling Foo.GetAll() here, we are introducing an extra layer of abstraction
return _dataProvider.GetAllFoos();
}
}
class FooDataProvider
{
public Foo[] GetAllFoos() {
return Foo.GetAll();
}
}
Теперь в Вашем модульном тесте, Вы создаете насмешку для FooDataProvider, который позволяет Вам называть метод GetAllFoos, не имея необходимость на самом деле поражать базу данных.
class BarTests
{
public TestGetAllFoos() {
// here we set up our mock FooDataProvider
mockRepository = MockingFramework.new()
mockFooDataProvider = mockRepository.CreateMockOfType(FooDataProvider);
// create a new array of Foo objects
testFooArray = new Foo[] {Foo.new(), Foo.new(), Foo.new()}
// the next statement will cause testFooArray to be returned every time we call FooDAtaProvider.GetAllFoos,
// instead of calling to the database and returning whatever is in there
// ExpectCallTo and Returns are methods provided by our imaginary mocking framework
ExpectCallTo(mockFooDataProvider.GetAllFoos).Returns(testFooArray)
// now begins our actual unit test
testBar = new Bar(mockFooDataProvider)
baz = testBar.GetAllFoos()
// baz should now equal the testFooArray object we created earlier
Assert.AreEqual(3, baz.length)
}
}
А общий сценарий насмешки, вкратце. Конечно, Вы все еще, вероятно, захотите к модульному тесту, который Ваша фактическая база данных называет также, для которого необходимо будет поразить базу данных.
Идеально, Ваши объекты должны быть персистентные неосведомленный. Например, у Вас должен быть "уровень доступа к данным", к которому Вы выполнили бы запросы, который будет эхо-сигналы. Таким образом, можно упустить ту часть из модульных тестов или протестировать их в изоляции.
, Если Ваши объекты сильно связываются к Вашему слою данных, трудно сделать надлежащее поблочное тестирование. первая часть модульного теста, "единица". Все единицы должны быть в состоянии быть протестированными в изоляции.
В моих c# проектах, я использую NHibernate с абсолютно отдельным уровнем Data. Мои объекты живут в базовой модели предметной области и получены доступ от моего прикладного уровня. Прикладной уровень говорит и со слоем данных и со слоем модели предметной области.
прикладной уровень также иногда называют "Бизнес-Слоем".
при использовании PHP создайте определенный набор классов для [ТОЛЬКО 116] доступ к данным. Удостоверьтесь, что Ваши объекты понятия не имеют, как они сохраняются и обеспечивают электричеством два в Ваших классах приложений.
Другая опция состояла бы в том, чтобы использовать насмешку/тупики.
Самый легкий путь к модульному тесту объект с доступом к базе данных использует области транзакций.
, Например:
[Test]
[ExpectedException(typeof(NotFoundException))]
public void DeleteAttendee() {
using(TransactionScope scope = new TransactionScope()) {
Attendee anAttendee = Attendee.Get(3);
anAttendee.Delete();
anAttendee.Save();
//Try reloading. Instance should have been deleted.
Attendee deletedAttendee = Attendee.Get(3);
}
}
Это вернется назад состояние базы данных, в основном как откат транзакции, таким образом, можно будет запускать тест так много раз, как Вы хотите без любого sideeffects. Мы использовали этот подход успешно в крупных проектах. Наша сборка действительно занимает много времени немного для выполнения (15 минут), но это не ужасно для того, чтобы иметь 1 800 модульных тестов. Кроме того, если время изготовления является беспокойством, можно изменить процесс сборки для имения нескольких сборок, один для создания src, другой, который разжигает впоследствии, который обрабатывает модульные тесты, анализ кода, упаковку, и т.д.
Книга xUnit Тестовые Шаблоны описывает некоторые способы обработать код поблочного тестирования, который поражает базу данных. Я соглашаюсь с другими людьми, которые говорят, что Вы не хотите делать это, потому что это медленно, но необходимо сделать это когда-то, IMO. Насмешка соединения дб для тестирования высокоуровневого материала является хорошей идеей, но проверьте эту книгу для предложений о вещах, которые можно сделать для взаимодействия с фактической базой данных.
Опции Вы имеете:
Вводят базу данных. (Пример в псевдо-Java, но относится ко всем языкам OO)
class Database { public Result query(String query) {... real db here ...} }теперь в производстве, Вы используете нормальную базу данных, и для всех тестов Вы просто вводите ложную базу данных, которую можно создать для данного случая.class MockDatabase extends Database { public Result query(String query) { return "mock result"; } }
class ObjectThatUsesDB { public ObjectThatUsesDB(Database db) { this.database = db; } }
User
вместо кортежа {name: "marcin", password: "blah"}
), пишут все Ваши тесты со специальным, созданным реальный объекты, и пишут один большой тест, который зависит от базы данных, которая удостоверяется это преобразование работы хорошо. , Конечно, эти подходы не являются взаимоисключающими, и Вы можете смешивание и подгонка их, как Вам нужно.
Необходимо дразнить доступ к базе данных, если Вы хотите к модульному тесту свои классы. В конце концов, Вы не хотите тестировать базу данных в модульном тесте. Это было бы интеграционным тестом.
Абстрагируют вызовы далеко и затем вставляют насмешку, которая просто возвращает ожидаемые данные. Если Ваши классы не делают больше, чем выполнение запросов, даже не может стоить тестировать их, хотя...
Я могу, возможно, дать Вам вкус нашего опыта, когда мы начали смотреть на поблочное тестирование наш процесс среднего уровня, который включал тонну "бизнес-логики" sql операции.
Мы сначала создали уровень абстракции, который позволил нам "слоту в" любом разумном соединении с базой данных (в нашем случае, мы просто поддерживали единственное соединение типа ODBC).
, Как только это существовало, мы тогда смогли сделать что-то вроде этого в нашем коде (мы работаем в C++, но я уверен, что Вы получаете идею):
GetDatabase ().ExecuteSQL ("нечто INSERT INTO (вздор, вздор)")
В нормальное время выполнения, GetDatabase () возвратил бы объект, который подал весь наш sql (включая запросы) через ODBC непосредственно к базе данных.
Мы тогда начали смотреть на базы данных в оперативной памяти - лучшее длинным путем, кажется, SQLite. ( http://www.sqlite.org/index.html ). Это удивительно просто настроить и использовать, и позволило нам подкласс и переопределение GetDatabase () для передачи sql базе данных в оперативной памяти, которая была создана и уничтожена для каждого выполненного теста.
Мы находимся все еще на ранних стадиях этого, но это выглядит хорошим до сих пор, однако мы действительно должны удостовериться, что составляем любые таблицы, которые требуются и заполняют их с данными тестирования - однако мы уменьшили рабочую нагрузку несколько здесь путем создания универсального набора функций помощника, которые могут сделать многое из всего этого для нас.
В целом, помогло очень с нашим процессом TDD, начиная с создания, что кажется, что довольно безвредные изменения для исправления определенных ошибок могут иметь довольно странное влияние на другом (трудный обнаружить) области системы - из-за самой природы sql/databases.
, Очевидно, наши события центрировались вокруг среды разработки C++, однако я уверен, что Вы могли, возможно, получить что-то подобная работа под PHP/Python.
Hope это помогает.
Поблочное тестирование Ваш доступ к базе данных достаточно легок, если Ваш проект имеет высокосвязную и слабую связь повсюду. Таким образом, можно протестировать только вещи, что каждый конкретный класс обходится без необходимости протестировать все сразу.
, Например, модульный тест Ваш пользовательский интерфейс при классификации тестов Вы пишете, должен только попытаться проверить, что логика в UI работала как ожидалось, не бизнес-логика или действие базы данных позади той функции.
, Если Вы хотите к модульному тесту фактический доступ к базе данных, Вы на самом деле закончите с большим количеством интеграционного теста, потому что Вы будете зависеть от сетевого стека и Вашего сервера базы данных, но можно проверить, что код SQL делает то, что Вы попросили, чтобы он сделал.
скрытое питание поблочного тестирования на меня лично состояло в том, что оно вынуждает меня разработать свои приложения намного лучшим способом, чем я мог бы без них. Это вызвано тем, что это действительно помогло мне покончить с "этой функцией, должен сделать все" менталитет.
Жаль у меня нет определенных примеров кода для PHP/Python, но если Вы хотите видеть пример.NET, я имею сообщение , который описывает технику, я раньше делал это очень то же тестирование.
Я никогда не делал этого в PHP, и я никогда не использовал Python, но что Вы хотите сделать, дразнить вызовы к базе данных. Чтобы сделать это, можно реализовать [приблизительно 110] МОК , управляете ли сторонний инструмент или Вы им сами, тогда можно реализовать некоторую ложную версию вызывающей стороны базы данных, которая является, где Вы будете управлять результатом того поддельного вызова.
А простая форма МОК может быть выполнена только путем кодирования к Интерфейсам. Это требует некоторой объектной ориентации, продолжающейся в Вашем коде, таким образом, это не может относиться к тому, что Ваше выполнение (я говорю, что начиная со всего должен продолжить, является Вашим упоминанием о PHP и Python)
Hope, это полезно, если ничто иное у Вас есть некоторые условия для поиска на теперь.
Я обычно пытаюсь разбить свои тесты между тестированием объектов (и ORM, если таковые имеются) и тестированием дб. Я тестирую объектную сторону вещей путем насмешки вызовов доступа к данным, тогда как я тестирую сторону дб вещей путем тестирования объектных взаимодействий с дб, который, по моему опыту, обычно справедливо ограничивается.
я раньше расстраивался записью модульных тестов, пока я не начинаю дразнить часть доступа к данным, таким образом, я не должен был создать тестовый дб или генерировать данные тестирования на лету. Путем насмешки данных можно генерировать все это во время выполнения и быть уверены, что объекты работают правильно с известными исходными данными.
Вы могли использовать платформы насмешки для абстракции механизма базы данных. Я не знаю, получил ли PHP/Python некоторых, но для типизированных языков (C#, Java и т.д.) существует много выбора
, Это также зависит от того, как Вы разработали тех код доступа к базе данных, потому что некоторый дизайн легче к модульному тесту, чем другой как более ранние сообщения упомянул.
Я соглашаюсь с первым сообщением - доступ к базе данных должен быть снят на уровень DAO, который реализует интерфейс. Затем можно протестировать логику против тупиковой реализации уровня DAO.