пятница, 23 декабря 2011 г.

Oracle: небольшая помощь для отладки и тестирования

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

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

Каждый ухищряется по-своему : самодельные заглушки, перевод системного времени и т.д. и т.п..

На случай , если Ваше приложение работает с СУБД Oracle, то наверняка при этом использует функцию sysdate этой самой СУБД (если , конечно, вы не изобрели свой "велосипед").
sysdate возвращает текущее дату-время на сервере, где запущен данный инстанс Oracle.
Создатели Oracle пошли на встречу разработчикам и тестировщикам , реализовав возможность активации режима, при котором sysdate будет возвращать фиксированную дату до тех пор, пока этот режим не будет деактивирован.

Вот как заставить sysdate возвращать фиксированную дату:
ALTER SYSTEM SET fixed_date = '2011-12-31 23:59:59';

А вот так все можно "вернуть вернуть на место":
ALTER SYSTEM SET fixed_date=NONE

Плюсы:

1. легко включается и отключается
2. не влияет на системное время ОС

Минусы:

Условный минус по сути вижу один - это особенность, на которую не все сразу обращают внимание:
Данный трюк работает на уровне "системы" , а не "сессии" и меняет поведение sysdate для всего инстанса. Соответственно, необходимо не забывать "возвращать на место" и вообще отдавать себе в этом отчет, если это инстанс может одновременно использоваться несколькими пользователями.

среда, 30 ноября 2011 г.

Драйвер сидирома в интернете, драйвер модема на болванке (с)



Попалась на тестирование программка. Читаю , значит требования. Абстрактно если, то озвучить их можно так:

Требование 1: найти объект по номеру одного из его дочерних объектов и вернуть код ошибки 1, если дочерний объект с указанным номером не найден

Требование 2: если у найденного объекта список дочерних объектов пуст, то вернуть код ошибки 2

И ведь считается, что разработчик все закончил , система ДОЛЖНА соответствовать требованиям и остались "только баги" (вероятные) :)

Вот такие вот "дедлоки" )

воскресенье, 27 ноября 2011 г.

Эти страшные системные ограничения )

Несколько месяцев назад натолкнулся на один очень странный баг в linux-приложении, которое активно использует unix-сокеты для общения своих дрочерних процессов. На одной из инсталляций приложение работало очень странно: запускалось , фурычило, но отказывалось останавливаться , а после принудительной остановки, отказывалось повторно запускаться. После продолжительных копаний со словами "мистика!" выяснилась причина была найдена - приложение было установлено по слишком длинному пути и unix-сокеты (читай файлы) создавались тут же (по их полному пути в системе ) . По их обрезанным именам стало ясно, что уперлись в какой-то системный лимит. Это было странно, потому что помилось, что полное имя файла может быть более 4кб. В данном случае уперлись в странную цифру 108 - не степень двойки, не круглая - вообще черт знает что.
В общем, оказалось это длина буфера одного из поля структуры sockaddr_un, расширить которое нельзя. "Нельзя так нельзя" - подумали мы и больше длинных путей ко временным файлам приложения не создавали и заказчикам деплоили с учетом этой "системой" проблемы. Думать о том, как бы это пофиксить времени тогда не было, раз был неплохой воркэраунд.
Ну вот пару дней назад, когда описанная выше проблема почти стерлась из памяти опять на это напоролись на одной из автоматически создаваемых тестовых инсталляций. В этот раз матчасть перечитали повнимательнее и в код заглянули более въедливо ... в результате поняли , что никакого такого "системного" ограничения на самом деле нет (не считая 4кб на полный путь к файлу), ведь можно указывать относительное имя к файлу unix-сокета, вместо полного) Ну 108 байт на относительное имя хватит на китай..
Смотрели друг на друга с разработчиком и посмеялись сами над собой - "Эх, Семен семеныч!", как говорится))

суббота, 15 октября 2011 г.

Забавный секурити баг на досуге


Принимал я тут как-то на досуге участие в тестировании одного веб-проекта.
Функциональное тестирование. Работа с системой требует авторизации, капчи на каждом шагу, сесии и все такое.
В одном из сценариев пользователи аттачат файлы. По логике бизнес-процесса , скорее всего это будут в том числе и приватные документы. При аплоаде много чего проверяется, в том числе и допустимый размер аттача как на клиентской стороне , так и на сервере.
В общем , " как учили ". На залитый аттач пользователь потом может всегда найти ссылку для скачивания. Ссылка располагается в private-части. Вроде все вроде бы ок, если бы не тот факт, что в ссылке есть параметр file_id, который меня и заинтересовал.
Путем перебора от 1 до "пока не надоест" мне удалось вытянуть все аттачи, которые были зарегистрированы в БД всеми пользователями этого проекта.. К счастью заказчика тестирования - пока еще тестовыми пользователями. полный приват, в общем :) О баге, конечно же доложено.
Название проекта, конечно же , не сообщаю :)

"А король то голый.." (с) :)

p.s. Надо будет антивирусом проверить все выкачанное, а то как бы на радостях самого себя не протроянить через какой-нибудь "документ"...:D
Всем удачи и побольше любопытства - без него в нашем деле никуда )

среда, 5 октября 2011 г.

Автотесты: почему важно "не делать лишних движений"

Несколько слов о дизайне автоматических тестов.
Точнее о вопросе избыточности проверок. Существует подход к разработке модульных (Unit) автоматических тестов, который можно описать так "Проверяем одно условие за один тест" (Verify one condition per test). Применение такой стратегии дает множество плюсов: при провале тестов можно максимально быстро выявить узкое место, и, как следствие, максимально быстро устранить проблему. Пусть тестов станет больше, но плюсы, как правило перевешивают.
При автоматизации более громоздких регрессионных функциональных тестов подобная стратегия также применима. Только в роли единицы проверки должны выступать уже не "условия" , а конкретный вариант поведения. При этом, все что лишнее, и не влияющее на данный конкретный вариант поведения должно быть безжалостно ампутировано. Лишними могут быть: некоторые инициализирующие параметры объектов, а также проверки , которые уже делались или будут делаться в тестах, специально для этого предназначенных. В общем, не надо делать лишних движений, у которых нет конкретных целей.
Вот пример из реальной практике, иллюстрирующий вышесказанное:

1. есть автоматический функциональный тест, проверяющий некий вариант поведения системы
2. в ходе его инициализации создается объект "клиент", у которого есть как обязательные так и необязательные параметры, причем данному тесту ни один из них не важен - важен факт наличия объекта "клиент" и все..
3. тестировщик, который создавал тест, то ли копипастом, то ли для разнообразия решил заполнить поле email , причем указал там строку с емейлом "не по RFC" (на момент написания теста проверке необязательного email внимания не уделялось)
4. тест долгое время работал, проверял нужные варианты, давал результат
5. в какой-то момент проверке полей данного объекта уделили внимание, и ужесточили ее, создав соответствующие автотесты на эту новую "функциональность"
6. старый же тест начал проваливаться, причем, не доходя до своей целевой проверки - проваливаться на этапе инициализации. Причина, думаю, ясна - строка "отбалды" в поле email.

Тест пришлось править, тратить время. Пусть не много времени ушло данный конкретный тест, но в принципе - это лишняя трата времени, лишнее отвлечение внимания на провал теста. Причина - "лишние движения" и никому ненужная "кучерявость" теста. Всему свое место - фантазии и творчеству, в том числе :)

Вывод: чуть больше осознанности может сэкономить чуть больше времени для чуть более полезных вещей :)

Анализ покрытия кода с помощью gcov+lcov





Сегодня наконец-то выделил время на то, чтобы наладить анализ покрытия кода. Пока только покрытие операторов и функций.
Тестируемое приложение написано на Си, ОС linux. Компиллятор gcc. Приложение должно быть собрано с флагами компиллятора : -ftest-coverage -fprofile-arcs.
Для анализа покрытия использовалась утилита gcov, которая помогает провести анализ того, какие строчки кода и сколько раз были задействованы в ходе выполнения приложения.
В результате выполнения приложения генерируются специальные файлы для каждого файла исходников , в которых и содержится собранная информация о покрытии. Дальше с помощью утилиты lcov полученные данные обрабатываются и генерируется , цветастый и веселый html-отчет . Я , как преимущественно визуалист, особенно был рад получившейся наглядности :) Даже в первом приближении мне стало понятно, что в плане автоматизации будут некоторые изменения :)
Упомянутые утилиты бесплатны, присутствуют в репозиториях всех популярных дистрибутивов linux, а также могут быть скачаны с sourceforge, например.
Итак, метод опробовал. Планирую проводить отдельный анализ покрытия для сеансов unit-тестирования и отдельно для сеансов автоматического регрессионного тестирования.
В более отдаленной перспективе постараюсь также наладить анализ покрытия путей выполнения и условий, а также освоить gcov в связке с gprof, для профилирования приложения.

Тем, кто планирует внедрять подобные практики позволю сразу дать совет. Использование тех или иных инструментов для генерации статистики покрытия влияет на скорость работы приложения, поэтому для анализа покрытия необходимо запускать сеансы отдельные от сеансов регрессионного автоматического тестирования.
p.s.

лучше 1 раз увидеть, чем 100 раз предположить :)

UPD 05/10/2011
При анализе результатов ночного прогона обнаружил небольшой бонус - gcov умеет и условия анализировать (см. пример на картинке вверху статьи ) . Приятная неожиданность :)

суббота, 24 сентября 2011 г.

Стандарты именования объектов БД

Когда речь идет о написании кода, например на том или ином языке программирования , то в профессиональных командах разработчиков рано или поздно приходят к использованию единой нотации переменных , констант, классов , функций и так далее. Каждый разработчик понимает , для чего это нужно и следует принятым правилам и соглашениям о кодировании, делая "хорошо" прежде всего самому себе.
Но когда заходит речь о проектировании и создании схем БД, то зачастую необходимость применения унифицированных принципов именования не всеми осознается и тем более не всеми применяется. Хотя в этом направлении стандартизированность не менее важна и не менее нужна...Не знаю , как на этот вопрос смотрят разработчики, но попытаюсь изложить взгляд со стороны тестирования...

По своему личному опыту могу точно утверждать, что единообразие наименований объектов в БД очень часто существенно экономит время . Преимущественно речь идет о времени на написание SQL-запросов особенно, когда приходится их писать сотнями в день и когда имеешь дело с большой разветвленной БД, где десятки а иногда и сотни таблиц. В этом случае все названия запомнить , конечно же , нереально, но если ты заранее знаешь , что имеешь дело со словарной таблицей и у нее обязательно есть mnemonic , и description, то это существенно облегчает жизнь. Если же проектировщики и разработчики задумывали и создавали БД "кто в лес, кто по дрова", то ты заранее не знаешь, description там или же desc, а может descr или вообще поле с опечаткой.. В итоге запрос с первого раза не пишется, надо смотреть описание таблицы - в общем, делать лишние движения. Они небольшие, но их много и вообще , как в песне поется, "не думай о секундах свысока"...
С экономией времени на составлении запросов вроде бы все ясно, потому что явно. Есть и другие менее явные положительные эффекты от единой стратегии именования.
Буквально на днях сталкивался с конкретной задачей автоматизации, которая решалась бы гораздо меньшими усилиями и существенно меньшим количеством строк кода, если бы не винегрет в названии одинаковых по смыслу полей в разных таблицах. То есть и в направлении автоматизации тестирования возможна экономия сил , нервов и средств при минимально едином подходе.
Еще один положительный эффект - новички ( и разработчики , и тестировщики ) гораздо быстрее осваивают систему, если при ее проектировании и разработке применяются единые правила наименований объектов. Быстрее осваивают - читай, быстрее начинают приносить реальную пользу.

В общем, везет тем , кто везет. А что делать если приходится работать с тем, что есть? Если , к примеру, схема БД росла и множилась годами, накопила кучу болячек, пережила не одну текучку кадров и к стандартизации нотации объектов в этой БД относились "с прохладцей"? Конечно же, не надо посыпать себе и тем более другим голову пеплом , не надо искать виноватых и жаловаться всем на всех.. Просто старайтесь конструктивно доводить до ответственных лиц необходимость рефакторинга схемы БД , если такого осознания у них нет. Если же это осознание уже есть, то готовьте тесты , проверяющие, что в результате рефакторинга система дает конечному пользователю как минимум то же самое, что и до него ))

Полезная информация по теме:
[1] Форумы на sql.ru - искать по "правила именования объектов базы данных" - тут знающий народ, решающий реальные задачи. Много хороших и дельных советов и практик.
[2] Хорошая книга как раз о рефакторинге уже существующей БД: Refactoring Databases: Evolutionary Database Design (Addison-Wesley Signature Series)
Scott W. Ambler, Pramodkumar J. Sadalage

среда, 14 сентября 2011 г.

Результаты опроса: "Какую систему контроля версий Вы используете"..



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

Системы контроля версий
Небольшие комментарии по результатам:
Лидерство Subversion предсказуемо. Как говорится - "сложилось исторически". Для меня наиболее интересен был "спор" Git и Mercurial. Git действительно более раскручен (чего стоит только один github), хотя особых преимуществ в функциональном плане не дает. Остается интересным и открытым вопрос, что кроется за словом "Другая" - там точно есть TFS, bazaar и многие другие... Удивила CVS - судя по всему , эта система скоро станет экзотикой - мир не стоит на месте...

воскресенье, 11 сентября 2011 г.

Небольшой оффтоп: возвращаем в жизни роутер

Несколько дней назад внезапно из строя вышел мой домашний WiFi-роутер Asus Wl=500G Premium.   Симптомы: невозможно достучаться даже по проводу ни по одному из протоколов, горят все лампочки, выключение , сброс настроек ни к чему не приводят. Обращение к знакомым обладателям подобных устройств и поисковой выдаче гугла выявило, что "слабым" местом этого девайса является его блок питания. Симптомы при выходе его из строя похожи. Вскрываю БП и действительно вижу слегка вздутый конденсатор. Радуюсь, что как правило в двух местах сразу такие вещи не ломаются и причина скорее всего в этом. У меня полетел конденсатор на 1200микрофарад, 10 вольтовый. В "Чипидип"е , что на Проспекте Мира куплена замена : радиальный , 1000 микрофарад (на 1200 найти не удалость), 10 вольтовый. Старый выпаян, новый впаян и, ура, в каждом уголке моей квартиры снова появился его величество Интернет =)

Конечно же, можно было просто купить новый БП. Но как-то это не интересно, что ли.

В общем, небольшой крюк в электронный магазин по дороге с работы домой , 20 минут на разбор корпуса БП (та еще нервотрепка) и 10 минут пайки неопытными в этом деле руками. В итоге все работает отлично.
Надеюсь, кому-нибудь, приведенная информация будет полезна.

среда, 17 августа 2011 г.

Загрузка файлов клиентом и Selenium

В целях автоматизации тестирования  некоторых сценариев точечно применяю Selenium-тесты на perl-е + Selenium RC.
До сих пор не приходилось сталкиваться с автоматизацией кейсов, связанных  с аплоадом файлов. И вот такая необходимость возникла.
Итак , запускаю Firefox + Selenium IDE , записываю действия по аплоаду и экспортирую в perl-виде.
Смотрю, какими же командами IDE мне сэмулировал нужную последовательность. Удивленно вижу, что для указания нужного файла используется всего навсего type с локатором файлового INPUT-поля и полным путем файла.
Отсекаю лишнее ,добавляю нужное , встраиваю в perl-фреймворк и вижу , что тест не проходит.
Копаю perl-библиотеку для работы с Selenium (WWW::Selenium) , радостно нахожу команду attach_file , пытаюсь ее применить и не получаю результата.
Гуглю, вижу всяческие рецепты,  как можно извратиться с помощью спец js-скриптов, дополнительных exe-утилит (для Windows).. Ни то ни то не подходит. Как раз в тот момент, когда хотелось "забить" на аплоад, в "буржнете" попался очень простой совет - принудительно установить фокус на поле с именем файла после его заполнения. НЕ веря в успех, попробовал и получилось...Работает (в *chrome - режиме) , аплоадит, тестируется =)

p.s.
По поводу Selenium 2.0 - слышал, что там проблема пользовательского аплоада стоит гораздо менее остро. Лишний повод познакомится и попробовать.

UPD 22/08/2011:
Перечитал пост и понял, что из него до конца неясно, какая же последовательность команд решает проблему? Ответ: focus +  type . attachfile можно вообще не использовать. По крайней мере, в моей ситуации со стандартными контролами пользы от этой команды  никакой.