Одна вещь, которую я люблю использовать NHibernate, поскольку моя O / RM — это возможность выталкивать схему базы данных из домена. Это позволяет мне создавать базу данных с нуля для каждого интеграционного тестового устройства и переводить ее в требуемое состояние. Создать базу данных с помощью NHibernate быстро и просто. Черт, вот код для этого:
Configuration cfg = container.Resolve<Configuration>();
SchemaExport export = new SchemaExport(cfg);
export.Execute(true, true, false, true);
Отличная, а?
Но тесты, которые попадают в базу данных, запоздалые , и они быстро становятся тестами, которые не запускаются Тесты, которые запрашивают базу данных, медленные, и, поскольку я регенерирую всю базу данных для каждого TestFixture, они действительно медленные. Я думаю, что одним из решений было бы не запускать интеграционные тесты локально, но мне не нравится этот вариант, и я считаю, что тесты следует запускать как можно чаще.
К счастью, NHibernate предоставляет ряд поставщиков RDBMS. Моим первым портом захода был SQLServer CE, но после первого запуска теста, когда он ничего не дал по формуле, я быстро отказался от нее.
Введите SQLite , «самый широко используемый в мире движок баз данных SQL». Потрясающие.
Быстрая модификация NHibernate и тесты были запущены так быстро, как свинья, чтобы …
Все было быстро и безболезненно.
Во-первых: возьмите необходимые сборки с http://sqlite.phxsoftware.com/ и добавьте ссылку.
Второе: настроить NHibernate; лично я использую возможности Castle NHibernate и Binsor для настройки Castle. Ниже приведены настройки, которые я использую:
facility NHibernateFacility:
configuration:
@isWeb = false, @useReflectionOptimizer = false
factory:
@id = 'nhibernate.factory'
settings(keymap, item: 'item'):
provider = 'NHibernate.Connection.DriverConnectionProvider'
connection.driver_class = 'NHibernate.Driver.SQLite20Driver'
dialect = 'NHibernate.Dialect.SQLiteDialect'
connection.connection_string = 'Data Source=intranet.db;Version=3;New=True'
cache.use_second_level_cache= 'false'
show_sql = 'true'
assemblies = [ Assembly.Load("Intranet") ]
facility TransactionFacility
И это в значительной степени это. Один известный мне недостаток — это SQLite на 64-битной ОС. Я не испытал это из первых рук, но я постараюсь выкопать некоторую информацию. Да, и на всю жизнь я не могу заставить его работать в памяти, но я опубликую об этом позже, как только получу решение .
Однако я отвлекся; В этой удивительной истории есть еще одна часть: сервер непрерывной интеграции . На мой взгляд, SQLite идеально подходит для локального запуска тестов, где важна скорость, а CI-сервер может успешно работать с SQL Server. Итак, давайте получим скрипт сборки, который меняет конфигурацию NHibernate.
Для этого я использовал три файла бу:
- container.boo
Это мой основной файл бу, он устанавливает все мои классы в Windsor - sql_server_facilities.boo
Это версия Sql Server версии файла средств, которая настраивает NHibernate для использования Sql Server. - sql_lite_facilites.boo
Как и выше, но для SQLite
Container.boo выглядит примерно так:
import System.Web.Mvc from System.Web.Mvc
import Spark.Web.Mvc
import Spark
import Spark.FileSystem
import Invocas.Tools.Binsor.Macros from Invocas.Tools
import file from sql_lite_facilities.boo
LoadFacilities()
for type in AllTypesBased of IController("Invocas.Intranet"):
component type.FullName, type:
lifestyle Transient
log
В файл контейнера я включаю файл sql_lite_facilities.boo. Это, как вы уже не сомневаетесь, хранит конфигурацию объектов.
import System
import System.Reflection
import Castle.Facilities.AutomaticTransactionManagement
import Castle.Facilities.FactorySupport from Castle.MicroKernel
import Castle.Facilities.NHibernateIntegration from Castle.Facilities.NHibernateIntegration
def LoadFacilities():
LoadNHibernate()
def LoadNHibernate():
facility NHibernateFacility:
configuration:
@isWeb = false, @useReflectionOptimizer = false
factory:
@id = 'nhibernate.factory'
settings(keymap, item: 'item'):
provider = 'NHibernate.Connection.DriverConnectionProvider'
connection.driver_class = 'NHibernate.Driver.SQLite20Driver'
dialect = 'NHibernate.Dialect.SQLiteDialect'
connection.connection_string = 'Data Source=:memory:;Version=3;New=True'
cache.use_second_level_cache= 'false'
show_sql = 'true'
assemblies = [ Assembly.Load("Invocas.Intranet") ]
facility TransactionFacility
Sql_server_facilities.boo по сути тот же, но с правильно заданными провайдером, драйвером, диалектом и строкой соединения:
provider = 'NHibernate.Connection.DriverConnectionProvider'
connection.driver_class = 'NHibernate.Driver.SQLite20Driver'
dialect = 'NHibernate.Dialect.SQLiteDialect'
connection.connection_string = 'Data Source=:memory:;Version=3;New=True'
По умолчанию я обычно сохраняю этот файл, чтобы в нем был установлен файл Facilities.boo, установленный на SQLite, и использую NAnt, чтобы установить правильный файл. Ниже то, что нужно для файла NAnt:
<property name="common.booFileName" value="sql_lite_facilities" overwrite="true" readonly="true" />
<property name="common.defaultString" value="sql_lite_facilities" overwrite="true" readonly="true" />
....
<target name="modifyBoo">
<property name="booContainerFile" value="${build.dir}/container.boo" />
<property name="valueToFind" value="${common.defaultString}"/>
<property name="valueToReplace" value="${common.booFileName}"/>
<script language="C#">
<imports>
<import namespace="System.Text.RegularExpressions"/>
<import namespace="System.IO"/>
</imports>
<code>
<![CDATA[
public static void ScriptMain(Project project) {
StreamReader reader = File.OpenText(project.Properties["booContainerFile"]);
string file = String.Empty;
try {
Regex exp = new Regex(project.Properties["valueToFind"]);
file = reader.ReadToEnd();
file = exp.Replace(file, project.Properties["valueToReplace"]);
} finally {
reader.Close();
}
TextWriter tw = new StreamWriter(project.Properties["booContainerFile"]);
try {
tw.WriteLine(file);
} finally {
tw.Close();
}
}
]]>
</code>
</script>
</target>
Цель modifiyBoo должна быть вызвана до запуска модульных тестов, но я уверен, что вы это поняли. Чтобы предоставить новый файл бу, просто используйте следующее:
nant -D:common.booFileName=sql_server_facilities
И вот, у вас есть сверхбыстрые тесты интеграции SQLite локально и тесты SQL Server на CI-сервере. Zoom Zoom!