пятница, 20 сентября 2013 г.

Сравнение коллекций/массивов в юнит-тестах Microsoft

Если вы используете фреймворк для юнит тестов, встроенный в Visual Studio, сравнение полученного результата с ожидаемым обычно производите используя класс Assert.
Но, если попробовать сравнить значения в коллекции или массиве (например, int[]) Assert.AreEqual() будет возвращать false для разных экземпляров массивов, даже если содержимое массивов одинаково.

Например:
[TestMethod]
public void TestArraysEquality()
{
  int[] array1 = new int[] { 1, 2, 3 };

  Assert.AreEqual(new int[] { 1, 2, 3 }, array1);
}

В результате тест завершается с ошибкой Assert.AreEqual failed.
Причина в том, что с массивом Assert.AreEqual проверяет равенство ссылок. Для простого примера, наподобие приведенного, можно просто написать три ассерта, по одному на каждый элемент... Но это решение на любителя. Или можно воспользоваться классом CollectionAssert, который пройдет через весь массив и проверит каждый элемент на равенство.
[TestMethod]
public void TestArraysEquality()
{
  int[] array1 = new int[] { 1, 2, 3 };

  CollectionAssert.AreEqual(new int[] { 1, 2, 3 }, array1);
}

Теперь тест завершится успешно.
К сожалению. CollectionAssert не обходит внутренние коллекции, и, если сравнить коллекцию коллекций, например, List<<int>>, то CollectionAssert.AreEqual все равно завершится ошибкой.

среда, 14 августа 2013 г.

NAT на Hyper-V под Windows 8

Все началось с того, что я захотел, чтобы на виртуальных машинах Hyper-V был работал интернет. При выборе сетевого адаптера для виртуальной машины доступно три варианта: private, internal и external. Private - сеть существует только для виртуальных машин на этом хосте, взаимодействия с внешним миром нет. External - создается мост (bridge) между сетевой картой хоста и виртуальной машиной. При этом интернет на хосте может не работать (у меня не работал). Internal - сеть существует между несколькими виртуальными машинами и хостом. NAT, то есть возможность взаимодействовать с внешним миром и виртуальным машинам и хосту, отсутствует. Но его можно сделать, используя средства Windows для совместного использования соединения с интернет (internet connection sharing). Для этого нужно будет выполнить три основных шага. К сожалению, после каждого шага лучше перезагрузиться, иначе вы рискуете не найти в настройках созданных виртуальных свитчей, адаптеров и соединений. Или просто ничего не будет работать...

1. Создаем Internal Virtual Switch, перезагружаемся

2. Расшариваем интернет-соединение на эту сетку, перезагружаемся

3. Подключаем созданный свитч к виртуальным машинам

П.С. Hyper-V, установленный на машину, забирает аппаратные виртуализационые возможности себе, так что другие гипервизоры (например, VirtualBox) будут работать в программном режиме виртуализации.

П.П.С. Настроенная система все равно будет глючить и выдавать подобные сообщения на гостевых машинах:
Лечиться, опять-таки, перезагрузкой...

понедельник, 15 июля 2013 г.

Возможности C++, которые лучше не использовать

Image courtesy of Idea go / FreeDigitalPhotos.net

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

Шаблоны (templates)

Без минимального использования шаблонов в C++ не обойтись. Но стоит увлечься их использованием, компиляция программы замедлиться в разы, а найти кто именно, что именно и у кого позвал, становится практически невозможно. Особо стоит упомянуть бинды (boost::bind, tr1::bind и т.п.), при использовании которых вызов в функции превращается в нечитабельную и неотлаживаемую портянку:
std::tr1::bind(
  &SomeThing::Process,
  std::tr1::cref(specificThing),
  std::tr1::placeholders::_1,
  std::tr1::cref(cancelState),
  std::tr1::ref(accumulatingProgress))

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

Лямбда-выражения

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

Макросы

В отличии от предыдущих двух, макрос - самый старый "друг" программиста, пришедший еще со времен чистого С. Но их использование чревато засорением глобального пространства имен, неудобством отладки и решения проблем компиляции. И самое неприятное, что макросы ведут себя совсем иначе, чем функции со своими аргументами, и в результате разворачивания макроса могут выполняться совсем не те операции, что были задуманы.

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