Вчера наконец то обратил внимание, что на одном из наших проектов билдбот показал:
14 тестов прошли, 42 пропущены.
Пошел выяснять, почему такая странность?
Третья посылка на тему "я не я, корова не моя, спроси Васю - авось он знает" помогла.
Камрад Хени оказался именно тем, кто нужен. Хени - тот еще жук, и я сразу же предвкушал интересный ответ. Но реальность, как обычно, оказалась круче:
- да, я знаю. Да, тесты пропускаются потому что уже давно устарели и не имеют смысла.
- А почему они все еще в codebase?
- Да потому, что задания на подчищание за собой собственных экскрементов Хени не получил. А по собственному почину шевелиться не желает.
Такие пироги.
пятница, 10 апреля 2009 г.
четверг, 12 марта 2009 г.
Система билдов
Кстати, еще летом нас была совсем страшная система создания билда, java ant с вкраплениями питоновского кода.
Когда она ломалась - атас. Никто не проверял, чем закончились эти самые вызовы подпроцессов. Собиралка продолжала работать дальше. Очень долго.
Через примерно 40 минут можно было увидеть - билд не прошел. Почему - догадаться можно. Иногда. Часто - нет. Все очень сложно и запутанно. Повторить - извольте начать все сначала (40 мин, помните?)
И так раз за разом.
Летом я как раз был в Нью-Йорке пару месяцев. И выпала моя неделя почетного билдера. После третьего проблемного билда за мою неделю (мне везло просто сказочно) - озверел. Переписал все к черту.
Теперь, как водится, все делается Питоном. С очень строгими проверками. Теперь все бросает exception и он, заметьте, не съедается как except Exception - долго бил по рукам за такое. Еще бить и бить - есть их у нас в рабочем коде... Если сломалось - стоп с максимально полной инфой.
Система сделана в стиле: запустил и забыл. Иди пить свой кофе. Потом остается только проверить результат.
Билд - пошаговый (Бикинга вовремя почитал). Если шаг был успешен - запомним его (записали в локальный файл). Следующий шаг поломается - получим полную инфу и, самое главное, возможность продолжить с поломавшегося места минуя предыдущие шаги. При это в начале билд делает tag и patch. И есть возможность на этапе, например, сломавшихся юниттестов автоматически обновиться из trunk, сделать patch commit и новый tag. Сильно экономит время.
Все в целом сейчас - 10 мин. Потом идут regression tests, и тут уж помочь ничем нельзя.
Да, мы используем svn без branch for every new task. Такая схема работы - все в trunk. Был бы рад переключиться на bazaar (сторонникам mercurial и git - я вас тоже люблю и уважаю) - но невозможно сейчас по организационным причинам.
Посидев месяц почетным билдером, отладил систему до состояния швейцарских часов.
Теперь у нас скользящий график переходящего знамени. С маленькой поправкой. Индивидум, заваливший билд сегодня - получает знамя на два следующих дня (если завтра будут проблемы от другого индивидума - знамя незамедлительно переходит к виновнику). Очень эффективная система. Позволяющая получить некоторое удовлетворение от того, что ты до хрен знает какого часа решал проблемы, созданные другими.
Сейчас это как правило нерабочие regression - которые 40 мин (летом было 20) и полный стек мало кто проверяет. Я - крайне редко. Но если попался - получи свои 2 почетных дня.
Забавная система получилась.
Когда она ломалась - атас. Никто не проверял, чем закончились эти самые вызовы подпроцессов. Собиралка продолжала работать дальше. Очень долго.
Через примерно 40 минут можно было увидеть - билд не прошел. Почему - догадаться можно. Иногда. Часто - нет. Все очень сложно и запутанно. Повторить - извольте начать все сначала (40 мин, помните?)
И так раз за разом.
Летом я как раз был в Нью-Йорке пару месяцев. И выпала моя неделя почетного билдера. После третьего проблемного билда за мою неделю (мне везло просто сказочно) - озверел. Переписал все к черту.
Теперь, как водится, все делается Питоном. С очень строгими проверками. Теперь все бросает exception и он, заметьте, не съедается как except Exception - долго бил по рукам за такое. Еще бить и бить - есть их у нас в рабочем коде... Если сломалось - стоп с максимально полной инфой.
Система сделана в стиле: запустил и забыл. Иди пить свой кофе. Потом остается только проверить результат.
Билд - пошаговый (Бикинга вовремя почитал). Если шаг был успешен - запомним его (записали в локальный файл). Следующий шаг поломается - получим полную инфу и, самое главное, возможность продолжить с поломавшегося места минуя предыдущие шаги. При это в начале билд делает tag и patch. И есть возможность на этапе, например, сломавшихся юниттестов автоматически обновиться из trunk, сделать patch commit и новый tag. Сильно экономит время.
Все в целом сейчас - 10 мин. Потом идут regression tests, и тут уж помочь ничем нельзя.
Да, мы используем svn без branch for every new task. Такая схема работы - все в trunk. Был бы рад переключиться на bazaar (сторонникам mercurial и git - я вас тоже люблю и уважаю) - но невозможно сейчас по организационным причинам.
Посидев месяц почетным билдером, отладил систему до состояния швейцарских часов.
Теперь у нас скользящий график переходящего знамени. С маленькой поправкой. Индивидум, заваливший билд сегодня - получает знамя на два следующих дня (если завтра будут проблемы от другого индивидума - знамя незамедлительно переходит к виновнику). Очень эффективная система. Позволяющая получить некоторое удовлетворение от того, что ты до хрен знает какого часа решал проблемы, созданные другими.
Сейчас это как правило нерабочие regression - которые 40 мин (летом было 20) и полный стек мало кто проверяет. Я - крайне редко. Но если попался - получи свои 2 почетных дня.
Забавная система получилась.
сериализация и юниттесты (сумбурно)
Я понемногу склоняюсь к мысли, что pickle - очень удобный, но далеко не всегда оптимальный формат.
Во первых - слишком он легко идет. Сериализует почти все, что угодно. В этом есть и минусы.
Вчера после работы чуть задержался в офисе. Приятель получил почетное переходящее знамя билдера (мы их ежедневно делаем), а я за компанию.
Плюс хотел юниттестами новое изобретение покрыть полностью и строго. Без них отдашь хорошую задумку людям, а через месяц-два в ней появится куча слабых мест и откровенных ляпов. Заметил: если программист не понял основную мысль дизайна/архитектуры - он начинает "гладить кошку против шерсти". А на работе на пальцах можно пересчитать тех, кто задумывается: а почему класс А был сделан так, а не как-нибудь иначе? Вот и лепят свои патчики так, что волосы дыбом.
Юниттесты позволяют вовремя дать по рукам. Получивший с большой вероятностью подойдет ко мне с вопросом, а там уж я ему заясню генеральную линию партии.
Это - помимо основной задачи: находить баги в коде. С этим тоже есть своя проблема. Если архитектура "правильная" - тесты пишутся легко и непринужденно, в больших количествах. И выполняют свое главное предназначение. Я только относительно недавно смог ощутить это в полной мере. И, думаю, все еще очень далек от совершенства.
Большая часть нашего немальнького кода, естественно, этому критерию не отвечает. Т.е. тесты баги не находят и не могут найти - т.к. для тестирования функции приходится подменять практически все ее окружение. Но тесты пишут, ибо начальство этого настоятельно требует. Результат тоже небесполезен: если ломается тест в результате твоих изменений - то вынужденно следует review, правится либо тест либо код, а чаще все вместе. Заодно есть шанс познакомиться с результатами чужого творчества и увидеть, что успели сделать другие люди/команды. К слову, американы в основной массе очень не любят смотреть чужой код. Наверное, это общая проблема - до этого мне просто сильно везло с коллегами.
Отвлекся.
Возвращаясь к pickle. Тесты в тот вечер я, как вы уже догадались, не писал.
Внезапно сервисы перестали работать. Практически совсем. Каждая транзакция заканчивалась exception и требуемого ответа не было. У нас клиент-сервер, так что сломалась серверная часть. Локальная катастрофа, вечерний неудачный билд не уйдет к тестерам, они не расскажут о новых ошибках, на один день сломается вся структура. Камрад Нил быстро понял, что последний находящийся в офисе чел из команды сервисописателей дупля откровенно не отбивает, окинул острым взором оставшийся народ и безошибочно направился ко мне.
Проблема была вроде бы тривиальная: что-то не могло пройти через pickle потому что было слабой ссылкой (weakref). Как я быстро обнаружил, пытались протолкнуть весьма нетривиальный объект, внутри которого к тому же было колечко (pickle ведь отлично сериализует объекты с циклическими ссылками).
Какой из многочисленных претендентов имел внутри этот самый weakref - непонятно по генерируемому исключению (к слову, использовался cPickle, а от него stacktrace совсем куцый). Путем дедукции и напряжения мозга сообразил, что пытались запиклить объект из нашего ORM (а-ля SQLAlchemy, но в силу наших внутренних особенностей алхимию использовать невозможно, создано ее подобие).
Я и не предполагал, что кому-то прийдет в голову передавать по сетке объект базы данных. Это же невозможно по ахитектурным соображениям: где сессия, к чему теперь информация об изменениях полей? Весь концепт рушится!!! Примерно как недавно кто-то пытался сериализовать boundmethod.
Быстро переопределил для всех сущностей из ORM __getnewargs__, дабы бросал хорошее и информативное исключение. Естественно, на следующем прогоне сразу же поймал вора.
Потребовался крошечный фикс на 10 строк, и успешный билд ушел.
А на следующий день я крепко насел на Тима, лида этих сервисников (к слову, Тим - весьма неглупый парень и голова у него работает как надо). Настоящая ПРОБЛЕМА была в том, что пересылалось ОЧЕНЬ МНОГО ИЗБЫТОЧНЫХ ДАННЫХ. Которые гораздо быстрее было бы получить на приемнике (они у него на самом деле уже есть). Т.е. вместо того, чтобы проталкивать очень большой объект, очень редко изменяемый (обе стороны уже имеют его в своем кеше, следят за изменениями и сами перечитывают когда нужно, прогнозируемые изменения не чаще раза в день) - можно передать его unique key, и подхватить его на другой стороне.
Отчасти ее видели по резкому снижению производительности серверной части. Но ведь «кажется, стало медленней работать» - еще не показатель»
Тим сильно удивился такому положению дел. Предложил быстрый патчик (и он прошел - еще бы, тривиально, когда знаешь в чем дело). Посопротивлялся идее "а давайте напишем свой pickle с нашими ограничениями".
Это его не спасет, т.к. только свой сериализатор позволит вовремя заорать: не то в меня пихают, на что я согласный!!!
Для начала сделаем свой restricted pickle(унаследоваться от Pickler и UnPickler и зарезать функциональность) , а потом, если будет нужно - перепишем на плюсах, как водится.
Уже практически сказал все, что хотел.
Теперь - во вторых (мелочь).
Специализированный pickle может быть быстрее. Не знаю насколько. Быть может - на "совсем чуть-чуть". Можно быстрее обрабатывать твои специфические типы, не кодируя их как "наследник от object, лежащий в модуле my_pope.my_cardinal.my_priest.my_guy", а просто вставив свой префикс для класса.
Улучшение, наверное, будет иметь только академически интересный прирост в скорости. Но к тому, что в стандартный pickle пролезут совсем неожиданно огромные объекты - будь готов. Просто по недосмотру и незнанию. Сейчас ты контролируешь все - но что будет, если проект разрастется?
Во первых - слишком он легко идет. Сериализует почти все, что угодно. В этом есть и минусы.
Вчера после работы чуть задержался в офисе. Приятель получил почетное переходящее знамя билдера (мы их ежедневно делаем), а я за компанию.
Плюс хотел юниттестами новое изобретение покрыть полностью и строго. Без них отдашь хорошую задумку людям, а через месяц-два в ней появится куча слабых мест и откровенных ляпов. Заметил: если программист не понял основную мысль дизайна/архитектуры - он начинает "гладить кошку против шерсти". А на работе на пальцах можно пересчитать тех, кто задумывается: а почему класс А был сделан так, а не как-нибудь иначе? Вот и лепят свои патчики так, что волосы дыбом.
Юниттесты позволяют вовремя дать по рукам. Получивший с большой вероятностью подойдет ко мне с вопросом, а там уж я ему заясню генеральную линию партии.
Это - помимо основной задачи: находить баги в коде. С этим тоже есть своя проблема. Если архитектура "правильная" - тесты пишутся легко и непринужденно, в больших количествах. И выполняют свое главное предназначение. Я только относительно недавно смог ощутить это в полной мере. И, думаю, все еще очень далек от совершенства.
Большая часть нашего немальнького кода, естественно, этому критерию не отвечает. Т.е. тесты баги не находят и не могут найти - т.к. для тестирования функции приходится подменять практически все ее окружение. Но тесты пишут, ибо начальство этого настоятельно требует. Результат тоже небесполезен: если ломается тест в результате твоих изменений - то вынужденно следует review, правится либо тест либо код, а чаще все вместе. Заодно есть шанс познакомиться с результатами чужого творчества и увидеть, что успели сделать другие люди/команды. К слову, американы в основной массе очень не любят смотреть чужой код. Наверное, это общая проблема - до этого мне просто сильно везло с коллегами.
Отвлекся.
Возвращаясь к pickle. Тесты в тот вечер я, как вы уже догадались, не писал.
Внезапно сервисы перестали работать. Практически совсем. Каждая транзакция заканчивалась exception и требуемого ответа не было. У нас клиент-сервер, так что сломалась серверная часть. Локальная катастрофа, вечерний неудачный билд не уйдет к тестерам, они не расскажут о новых ошибках, на один день сломается вся структура. Камрад Нил быстро понял, что последний находящийся в офисе чел из команды сервисописателей дупля откровенно не отбивает, окинул острым взором оставшийся народ и безошибочно направился ко мне.
Проблема была вроде бы тривиальная: что-то не могло пройти через pickle потому что было слабой ссылкой (weakref). Как я быстро обнаружил, пытались протолкнуть весьма нетривиальный объект, внутри которого к тому же было колечко (pickle ведь отлично сериализует объекты с циклическими ссылками).
Какой из многочисленных претендентов имел внутри этот самый weakref - непонятно по генерируемому исключению (к слову, использовался cPickle, а от него stacktrace совсем куцый). Путем дедукции и напряжения мозга сообразил, что пытались запиклить объект из нашего ORM (а-ля SQLAlchemy, но в силу наших внутренних особенностей алхимию использовать невозможно, создано ее подобие).
Я и не предполагал, что кому-то прийдет в голову передавать по сетке объект базы данных. Это же невозможно по ахитектурным соображениям: где сессия, к чему теперь информация об изменениях полей? Весь концепт рушится!!! Примерно как недавно кто-то пытался сериализовать boundmethod.
Быстро переопределил для всех сущностей из ORM __getnewargs__, дабы бросал хорошее и информативное исключение. Естественно, на следующем прогоне сразу же поймал вора.
Потребовался крошечный фикс на 10 строк, и успешный билд ушел.
А на следующий день я крепко насел на Тима, лида этих сервисников (к слову, Тим - весьма неглупый парень и голова у него работает как надо). Настоящая ПРОБЛЕМА была в том, что пересылалось ОЧЕНЬ МНОГО ИЗБЫТОЧНЫХ ДАННЫХ. Которые гораздо быстрее было бы получить на приемнике (они у него на самом деле уже есть). Т.е. вместо того, чтобы проталкивать очень большой объект, очень редко изменяемый (обе стороны уже имеют его в своем кеше, следят за изменениями и сами перечитывают когда нужно, прогнозируемые изменения не чаще раза в день) - можно передать его unique key, и подхватить его на другой стороне.
Отчасти ее видели по резкому снижению производительности серверной части. Но ведь «кажется, стало медленней работать» - еще не показатель»
Тим сильно удивился такому положению дел. Предложил быстрый патчик (и он прошел - еще бы, тривиально, когда знаешь в чем дело). Посопротивлялся идее "а давайте напишем свой pickle с нашими ограничениями".
Это его не спасет, т.к. только свой сериализатор позволит вовремя заорать: не то в меня пихают, на что я согласный!!!
Для начала сделаем свой restricted pickle(унаследоваться от Pickler и UnPickler и зарезать функциональность) , а потом, если будет нужно - перепишем на плюсах, как водится.
Уже практически сказал все, что хотел.
Теперь - во вторых (мелочь).
Специализированный pickle может быть быстрее. Не знаю насколько. Быть может - на "совсем чуть-чуть". Можно быстрее обрабатывать твои специфические типы, не кодируя их как "наследник от object, лежащий в модуле my_pope.my_cardinal.my_priest.my_guy", а просто вставив свой префикс для класса.
Улучшение, наверное, будет иметь только академически интересный прирост в скорости. Но к тому, что в стандартный pickle пролезут совсем неожиданно огромные объекты - будь готов. Просто по недосмотру и незнанию. Сейчас ты контролируешь все - но что будет, если проект разрастется?
Подписаться на:
Сообщения (Atom)