Amazon выпустила «умную» кнопку для облегчения покупок

Amazon предложила избранным пользователям своего магазина попробовать новый способ совершения домашних покупок, выпустив «умную» кнопку Dash Button. Устройство размером немногим более коробки спичек хозяину дома необходимо будет установить в тех местах, которые он сочтёт нужным: к примеру, на кухне или в ванной. В нужный момент достаточно будет только нажать на кнопку и дождаться, пока выполненную таким образом покупку, не доставят прямо к порогу. Предложение бесплатно и действительно только для жителей США. Владелец одного аккаунта может получить максимум три таких кнопки Dash.

Работает Dash Button в связке со специальным приложением на смартфоне. Скачав его, хозяину дома надо будет выбрать количество и вид товара, который и будет куплен, если конкретная «умная» кнопка будет нажата. Ассортимент возможных покупок пока определяется обычными домашними нуждами: минеральная вода, овсянка, памперсы и прочие надобности.

image

Для защиты от случайных покупок предусмотрена специальная функция — до тех пор, пока товар не будет доставлен покупателю, новые покупки с Dash Button будут заблокированы. Если хозяин в принципе передумал покупать стиральный порошок, то покупку можно будет отменить. Однако сделать это чуть тяжелее — придётся взять в руки смартфон и сделать это из приложения.

Весной прошлого года в Amazon уже пробовали облегчать пользователям покупки. Для этого был представлен специальный сканер штрих-кодов с почти тем же самым названием Amazon Dash. Чтобы приобрести что-нибудь, хозяину дома предлагалось отсканировать штрих-код, и сканер самостоятельно сформирует список покупок, который можно было просмотреть или на сайте, или в мобильном приложении. Также сканер поддерживал и голосовые покупки:

ссылка на оригинал статьи http://geektimes.ru/post/248186/

Учеными разработан атомно-силовой микроскоп, позволяющий наблюдать динамику нейронов на нано уровне

Исследователям института неврологии Макса Планка (Max Planck Florida Institute for Neuroscience) и университета Каназава (Kanazawa University) (Япония) удалось получить изображения структурной динамики живых нейронов с беспрецедентным пространственным разрешением



Исследователи произвели модернизацию имеющегося в их распоряжении атомно-силового микроскопа (atomic force microscope, AFM). Благодаря этой модернизации он стал способен снимать динамичные изменения структуры живых нейронов с беспрецедентным на нынешнее время пространственным разрешением и скоростью.

— Атомно-силовая микроскопия (АСМ) является ведущим инструментом для работы с изображениями, измерения и манипулирования материалами с атомным разрешением — порядка долей нанометра.

— АСМ получает изображения топографии поверхности структуры буквально «трогая» поверхность, сканируя очень тонкой иглой (диаметр кончика около 5 нм, 1/100 длины световой волны или 1/10000 волоса)

-Эта технология применяется для получения изображения твердых материалов. Но было трудно применять АСМ для мягких и больших образцов таких, как эукариотические клетки и нейроны, не повреждая образец. Кроме того, получение изображений обычным АСМ слишком медленно, чтобы захватить быстрые изменения клеточной морфологии.

-Эта новая система позволяет анализировать изменения морфологии в ~20-100 раз быстрее, чем стандартным световым микроскопом

Ученые, разрабатывая технологию скоростной съемки (long-tip high-speed, LT-HS-AFM) нашли способ избежать повреждения биологических образцов. Они использовали чрезвычайно длинный и острый зонд, закрепленный на гибкой пластине, такая мягкая и податливая консоль нового микроскопа обеспечивает минимальное давление зонда на образец. А управляет перемещениями наконечника зонда быстродействующая оптическая система, срабатывающая с частотой 800 кГц (тысяч раз в секунду).

Видео процесса

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


Изображение нейрона гиппокампа, трансфицированного с mEGFP. Белые пунктирные линии показывают тень кантилевера. Белый квадрат показывает область изображения LT-HS-АСМ.

540nm

710nm

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

В самом ближайшем будущем мы планируем на основе уже имеющейся технологии создать технологию визуализации морфологии синапсов в режиме реального времени, получив при этом суб-нанометровую разрешающую способность" — рассказывает Риохеи Ясуда (Ryohei Yasuda), ученый из института Макса Планка, — «Эти данные имеют очень большое значение для современной науки, ведь изменения морфологии синапсов являются основой синаптической пластичности, основой нашей памяти и познавательной функции. Исследуя эти процессы, мы сможем узнать много нового о том, как нейроны хранят информацию, и это, в конечном счете, поможет нам вплотную подойти к возможности генерирования искусственных воспоминаний, мгновенного обучения и многих других вещей, которые пока являются лишь фантастикой

ссылка на оригинал статьи http://geektimes.ru/post/248184/

Single Sign-On (SSO): OpenAM + mod_auth_mellon

Пост расcчитан на новичков, которые только знакомятся с SSO. В интернете не очень много документации по связке OpenAM и mod_auth_mellon, тем более на русском языке.
Для быстрого старта буду использовать образы Docker. Для аутентификации пользователя рассмотрю модуль mod_auth_mellon, но можно использовать и другие методы, к примеру Policy Agent или OpenIG.

Теория

Технология единого входа (англ. Single Sign-On) — технология, при использовании которой пользователь переходит из одного раздела портала в другой без повторной аутентификации.
OpenAM (Access Management) — провайдер идентификации (IdP, англ. identity provider), осуществляет аутентификацию пользователя.
mod_auth_mellon — модуль apache, который аутентифицирует пользователя через IdP (OpenAM).

Настройка

Добавить в /etc/hosts домены для OpenAM и тестовых приложений:

127.0.0.1 openam.example.com fake.mellon.app.one fake.mellon.app.two 

Запускаем OpenAM:

docker run -d -t -p 8080:8080 --add-host "openam.example.com:127.0.0.1" wstrange/openam-base-nightly 

Запускаем тестовые приложения:

git clone git@bitbucket.org:agobzhelyan/openam_mellon.git cd openam_mellon 
docker build -t fake_mellon_app_one fake_app_1 docker run -d -p 8091:80 --name fake_mellon_app_one fake_mellon_app_one 
docker build -t fake_mellon_app_two fake_app_2 docker run -d -p 8092:80 --name fake_mellon_app_two fake_mellon_app_two 

Настраиваем OpenAM. Можно было создать docker образ, чтобы не делать это вручную. Но, думаю, будет лучше пройти эти простые шаги самому, чтобы лучше понять, как это работает:

— открываем http://openam.example.com:8080/openam/;
— нажимаем Create Default Configuration;
— пароль для amAdmin — secret12, для UrlAccessAgent — secret123;
— переходим в Home (amAdmin / secret12), далее Federation и добавляем новый Circle of Trust с именем TestCOT;
— переходим на страницу Create Identity Provider: http://openam.example.com:8080/openam/task/CreateHostedIDP. Меняем Signing Key на test и ждем на Configure, потом Finish;
— переходим на страницу Create Remote Service Provider: http://openam.example.com:8080/openam/task/CreateRemoteSP. Ждем на File и загружаем fake_app_1/mellon/fake_mellon_app_one.xml, убеждаемся что COT выбран TestCOT
— тоже самое для fake_mellon_app_two.xml.

Настройка mod_auth_mellon. Тут лучше почитать https://github.com/UNINETT/mod_auth_mellon и посмотреть пример реализации в тестовых приложениях https://bitbucket.org/agobzhelyan/openam_mellon/src.

Тестирование

— выходим из админки http://openam.example.com:8080/openam/ и переходим в приложение 1 — http://fake.mellon.app.one:8091/;
— нажимаем ссылку backend;
— нас перенаправит на логин страницу. Вводим demo / changeit;
— после этого возвращаемся на запрашиваемую (защищенную) страницу;
— переходим в приложение 2 http://fake.mellon.app.two:8092/backend/ и обращаем внимание что и тут мы залогинены.

Заключение

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

Список используемой литературы

www.lab-ic.ru/solutions/sso
doc.arcgis.com/ru/arcgis-online/reference/configure-openam.htm
openam.forgerock.org/doc/getting-started/index.html
en.wikipedia.org/wiki/Single_sign-on
blog.kaliconseil.fr/2011/02/21/using-openam-with-apache-as-a-reverse-proxy
mkchendil.blogspot.ch/2015/02/apache-and-openam-saml-federation.html
blogs.splunk.com/2013/03/28/splunkweb-sso-samlv2

Используете ли вы SSO?

Проголосовало 13 человек. Воздержалось 2 человека.

Только зарегистрированные пользователи могут участвовать в опросе. Войдите, пожалуйста.

ссылка на оригинал статьи http://habrahabr.ru/post/254503/

Лекарство тысячелетней давности оказалось эффективнее современных антибиотиков

image

Исследователи из университета Бирмингема воспроизвели лекарство из древней медицинской книги, которое оказалось эффективным против метициллин-резистентного золотистого стафилококка (MRSA). Эти зловредные микроорганизмы вызывают тяжёлые заболевания,– сепсисы, пневмонии,- будучи при этом устойчивыми к большой группе антибиотиков.

Медицинская наука шла к текущему уровню постепенно. Чёткие научные методы стали появляться лишь в конце 19 – начале 20 веков, а раньше всё основывалось на эмпирических методах и практиках. Некоторые древние рецепты, например применение толчёной коры ивы (которая содержит салициловую кислоту) для снятия жара или коры хинного дерева (хинин) при лечении малярии, были научно подтверждены. Другие же – кровопускание по любому поводу, лечение ртутью или даже радием, были отвергнуты.

image

Но, похоже, история не устанет преподносить нам сюрпризы. Неожиданный рецепт был найден в одной из самых древних медицинских книг, датируемой 9-м веком Н.Э. Книга известна как Bald’s Leechbook, или Medicinale Anglicum, и представляет собой образец самых первых попыток применения методов, похожих на научные. В результате исследований и наблюдений медики прошлого составили несколько рецептов для лекарств. В частности, в книге упоминается «глазная мазь» для лечения инфекций.

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

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

image

А вот и сам рецептик, хозяйке на заметку:

Равные доли чеснока и лука (луковицы или порея) мелко порезать и тереть в ступке две минуты. Добавить 25 мл вина. Добавить коровью желчь, растворённую в воде, и выдерживать при температуре в 4 градуса девять дней.

ссылка на оригинал статьи http://geektimes.ru/post/248182/

Модульное тестирование поведения Yii2 с помощью Codeception

В разработке программного обеспечения написание автоматических тестов часто отодвигается на второй план более насущными проблемами. Так и в моем случае, код писать приходилось, а тесты к нему — нет. При этом давно хотелось попробовать модульное тестирование собственного кода, а тут под руку подвернулось поведение Yii2 ManyToMany Behavior, о котором уже писали на Хабре. Это поведение я сначала немного расширил, а затем решил собрать комплект тестов.

Сами тесты, в том числе те, о которых идет речь в этой статье, можно посмотреть в репозитории по ссылке выше. Все команды выполнялись под Windows с глобально установленным composer, но я думаю, что разработчики, пользующиеся Linux, без затруднений смогут адаптировать их под себя.

Далее мы рассмотрим настройку Codeception с модулем для Yii2 и создание тестов для поведения.

Зачем тестировать?

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

Когда я решил поучаствовать в разработке Yii2 ManyToMany Behavior, функционал по работе со связями типа 1-N был реализован частично и не проверен. Как минимум, мне надо было убедиться, что существующий код работает. Если бы я не написал автоматические тесты, все равно бы пришлось создавать какое-то приложение Yii2, подключать к его моделям поведение, а затем на каких-то тестовых данных проверять, работает ли оно. С этой точки зрения тесты выгодны, так как затраты на написание самих тестов — это капля в море по сравнению с подготовкой тестовых данных и тестового приложения. Кроме того, разрабатываемое поведение — достаточно простая штука, для работы которой нужен только стандартный код Yii2, который практически гарантированно работоспособен. Это сильно облегчает подготовку тестов.
В моем случае автоматически тесты себя оправдали. Как оказалось, разрешая конфликт при объединении веток, я что-то испортил, и связи 1-N перестали сохраняться. Благодаря тесту, я быстро нашел ошибку и исправил ее.

Что тестируем?

Поведение, которое мы рассматриваем, позволяет при сохранении модели также сохранять ее связи с другими моделями. Для примера рассмотрим простую структуру данных, состоящую из книг (Book), авторов (Author) и отзывов на книги (Review). Книги и авторы связаны как N-N, то есть у книги может быть много авторов, а у автора — много книг. Книги и отзывы связаны как 1-N, то есть у книги может быть много отзывов, но каждый отзыв может относиться только к одной книге.

Во время тестирования мы будем сохранять одну книгу со всеми ее связями. При сохранении модели нужно рассмотреть несколько возможных вариантов входных данных:

  1. Непустой массив идентификаторов связанной модели. При этом должны быть удалены старые связи и созданы новые.
  2. Пустой массив, в результате чего должны быть удалены старые связи.
  3. Полное отсутствие данных, соответствующее, например, форме редактирования книги, в которой нет полей, относящихся к авторам. В этом случае поведение не должно делать ничего, то есть существующие связи не должны измениться.

Необходимо проверить работоспособность поведения во всех трех случаях.

Особенности, связанные с Yii2

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

Разумеется, для тестирования нам понадобится база данных. К счастью, для нашей задачи необязательно иметь отдельный сервер баз данных. Будет достаточно воспользоваться СУБД SQLite, которая поддерживается Yii2 и хранит базу в файле. Сами же тестовые данные будут храниться в виде дампа, который загружается перед каждым тестом.

Настройка Codeception

Для начала с помощью composer выполним глобальную установку codeception:

composer global require codeception/codeception 

Теперь подготовим все необходимое для тестирования нашего поведения. В директории с поведением уже есть файл composer.json, в котором дано описание поведения и его зависимостей. Добавим к нему библиотеку yii2-codeception:

composer require --dev yiisoft/yii2-codeception 

Затем выполним инициализацию окружения codeception в директории поведения:

codecept bootstrap --customize 

Имя актора (actor) можно оставить по умолчанию (Tester), а набор тестов (suite) нам понадобится только один — unit.

Появится директория tests и файл codeception.yml, в котором мы зададим нужные нам параметры. Параметры по умолчанию нас вполне устраивают, за исключением подключения к базе данных.

actor: Tester paths:     tests: tests     log: tests/_output     data: tests/_data     helpers: tests/_support settings:     bootstrap: _bootstrap.php     colors: false     memory_limit: 1024M modules:     config:         Db:             dsn: 'sqlite:tests/_output/temp.db'             user: ''             password: ''             dump: tests/_data/dump.sql 

Теперь нужно настроить набор тестов unit в файле tests/unit.suite.yml:

class_name: UnitTester modules:     enabled: [Asserts, Db] 

Модуль UnitHelper, который был включен по умолчанию, нам не понадобится, зато мы добавили Asserts и Db. Теперь построим окружение с учетом выбранных модулей:

codecept build 

Наконец, нужно настроить автозагрузчик Yii2 в файле tests/_bootstrap.php:

defined('YII_DEBUG') or define('YII_DEBUG', true); defined('YII_ENV') or define('YII_ENV', 'dev'); require_once __DIR__ . implode(DIRECTORY_SEPARATOR, ['', '..', 'vendor', 'autoload.php']); require_once __DIR__ . implode(DIRECTORY_SEPARATOR, ['', '..', 'vendor', 'yiisoft', 'yii2', 'Yii.php']); Yii::setAlias('@tests', __DIR__); Yii::setAlias('@data', __DIR__ . DIRECTORY_SEPARATOR . '_data'); 

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

Подготовка дампа базы данных

Для создания структуры базы данных удобно использовать визуальный инструмент, такой как DB Browser for SQLite.

Создаем таблицы book, author, review и book_has_author, заполняем их тестовыми данными. Затем делаем дамп и сохраняем его в tests/_data/dump.sql.

Мой дамп выглядит следующим образом:

BEGIN TRANSACTION; CREATE TABLE "review" (     `id`    INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,     `book_id`   INTEGER,     `comment`   VARCHAR(150) NOT NULL,     `rating`    INTEGER NOT NULL ); INSERT INTO `review` VALUES (1,3,'Старая книга, не потерявшая актуальность.',5); INSERT INTO `review` VALUES (2,3,'Одобряю!',5); INSERT INTO `review` VALUES (3,3,'Неплохо.',4); INSERT INTO `review` VALUES (4,5,'Хлам!',2); CREATE TABLE "book_has_author" (     `book_id`   INTEGER NOT NULL,     `author_id` INTEGER NOT NULL ); INSERT INTO `book_has_author` VALUES (1,1); INSERT INTO `book_has_author` VALUES (1,2); INSERT INTO `book_has_author` VALUES (2,1); INSERT INTO `book_has_author` VALUES (2,3); INSERT INTO `book_has_author` VALUES (3,4); INSERT INTO `book_has_author` VALUES (4,5); INSERT INTO `book_has_author` VALUES (4,6); INSERT INTO `book_has_author` VALUES (5,9); CREATE TABLE "book" (     `id`    INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,     `name`  VARCHAR(150) NOT NULL,     `year`  INTEGER NOT NULL ); INSERT INTO `book` VALUES (1,'Основы агрономии и ботаники.',2004); INSERT INTO `book` VALUES (2,'Ботаника: учеб для с/вузов.',2005); INSERT INTO `book` VALUES (3,'Краткий словарь ботанических терминов.',1964); INSERT INTO `book` VALUES (4,'Ботаника с основами геоботаники.',1979); INSERT INTO `book` VALUES (5,'Ботаника. Систематика высших или наземных растений.',2004); CREATE TABLE "author" (     `id`    INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,     `name`  VARCHAR(150) NOT NULL ); INSERT INTO `author` VALUES (1,'Андреев Н.Г.'); INSERT INTO `author` VALUES (2,'Андреев Л.Н.'); INSERT INTO `author` VALUES (3,'Родман Л.С.'); INSERT INTO `author` VALUES (4,'Викторов Д.П.'); INSERT INTO `author` VALUES (5,'Суворов В.В.'); INSERT INTO `author` VALUES (6,'Воронов И.Н.'); INSERT INTO `author` VALUES (7,'Еленевский А.Г.'); INSERT INTO `author` VALUES (8,'Соловьева М.П.'); INSERT INTO `author` VALUES (9,'Тихомиров В.Н.'); COMMIT; 

Конфигурирование приложения

Так как наше поведение будет тестироваться в рамках консольного приложения, нужно подготовить для него конфигурацию. Создаем файл tests/unit/_config.php:

<?php return [     'id' => 'app-console',     'class' => 'yii\console\Application',     'basePath' => \Yii::getAlias('@tests'),     'runtimePath' => \Yii::getAlias('@tests/_output'),     'bootstrap' => [],     'components' => [         'db' => [             'class' => '\yii\db\Connection',             'dsn' => 'sqlite:'.\Yii::getAlias('@tests/_output/temp.db'),             'username' => '',             'password' => '',         ]     ] ]; 

Создание моделей

Файлы классов моделей создаем в директории tests/_data, и задаем им namespace data. Чтобы не делать это вручную, я в другой директории развернул шаблон приложения basic, подключил его к базе данных и создал классы с помощью gii.

Важно, чтобы в модели Book были объявлены нужные отношения:

public function getAuthors() {     return $this->hasMany(Author::className(), ['id' => 'book_id'])                 ->viaTable('book_has_author', ['author_id' => 'id']); }  public function getReviews() {     return $this->hasMany(Review::className(), ['book_id' => 'id']); } 

Туда же добавляем и поведение:

public function behaviors() { return     [         [             'class' => \voskobovich\behaviors\ManyToManyBehavior::className(),             'relations' => [                 'author_list' => ['authors'],                 'review_list' => ['reviews'],             ]         ]     ]; } 

Обязательно указываем валидатор для атрибутов, которые создаются поведением:

public function rules() {     return [         [['author_list', 'review_list'], 'safe'],          ... 

Теперь можно писать сами тесты.

Создание тестов

В codeception тест-кейсы оформляются как классы. Чтобы работать с объектами Yii2 нужно создать класс, унаследованный от yii\codeception\TestCase. Имя класса и имя файла должны заканчиваться на Test.

В файле tests/unit/BehaviorTest.php создадим тест-кейс BehaviorTest, а в нем метод testSaveManyToMany, проверяющий, сохраняется ли корректный набор данных для связи N-N:

class BehaviorTest extends \yii\codeception\TestCase {     public $appConfig = '@tests/unit/_config.php';      public function testSaveManyToMany()     {         //load         $book = Book::findOne(5);          //simulate form input         $post = [             'Book' => [                 'author_list' => [7, 9, 8]             ]         ];          $this->assertTrue($book->load($post), 'Load POST data');         $this->assertTrue($book->save(), 'Save model');          //reload         $book = Book::findOne(5);          //must have three authors         $this->assertEquals(3, count($book->authors), 'Author count after save');          //must have authors 7, 8, and 9         $author_keys = array_keys($book->getAuthors()->indexBy('id')->all());         $this->assertContains(7, $author_keys, 'Saved author exists');         $this->assertContains(8, $author_keys, 'Saved author exists');         $this->assertContains(9, $author_keys, 'Saved author exists');     }      ... 

Мы выполняем действия, которые обычно связаны с сохранением формы. Определенные данные приходят из запроса (переменная $post). Метод load() используется для записи этих данных в атрибуты модели. Затем модель сохраняется с помощью метода save().

После наших манипуляций у книги должно появиться три автора с ключами 7, 8 и 9, что и проверяется.

Аналогично описываются и остальные тесты, например, сохранение пустого набора даных для связи 1-N:

public function testResetOneToMany() {     //load     $book = Book::findOne(3);      //simulate form input     $post = [         'Book' => [             'review_list' => []         ]     ];      $this->assertTrue($book->load($post), 'Load POST data');     $this->assertTrue($book->save(), 'Save model');      //reload     $book = Book::findOne(3);      //must have zero reviews     $this->assertEquals(0, count($book->reviews), 'Review count after save'); } 

Если выполнить codecept run, система проведет все доступные тесты и отчитается об их результатах:

Codeception PHP Testing Framework v2.0.11 Powered by PHPUnit 4.5.0 by Sebastian Bergmann and contributors.  Unit Tests (2) -------------------------------------------------------------------------------------- Test save many to many (BehaviorTest::testSaveManyToMany)                                       Ok Test reset one to many (BehaviorTest::testResetOneToMany)                                       Ok -----------------------------------------------------------------------------------------------------   Time: 390 ms, Memory: 9.00Mb  OK (2 tests, 9 assertions) 

Выводы

Попробовав модульное тестирование в деле, я вижу, насколько полезным оно оказалось при разработке разных надстроек и дополнений. Иными словами, тестировать таким образом поведение — удобно, но покрывать модульными тестами весь код своего проекта я бы не стал.

Одна из проблем модульного тестирования, с которой я столкнулся — необходимость выдумывать условия, при которых проверяется код. Когда смотришь на то, что ты написал сам, сложно представить себе, где оно может сломаться. Мне кажется, что здесь бы помог взгляд со стороны.

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

ссылка на оригинал статьи http://habrahabr.ru/post/254509/