Пять идей «на вооружение», или Впечатления от московского «Гейзенбага»

    image

    Как убедиться, что на конференции, на которую ты берёшь билет, не будет «лажи»? На мой взгляд, лучший способ — стать спикером одной из конференций того же организатора и на себе протестировать процесс отбора и подготовки докладов. Весной я был спикером на конференции, проводимой компанией JUG.ru Group, а всё происходившее перед этим напоминало защиту учёной степени. Несколько раз мой доклад прослушивал программный комитет, после каждого из прогонов я получал длинный список вопросов и замечаний. Один из членов комитета стал «оппонентом» и в бесконечных дискуссиях в Slack-е требовал дополнительных экспериментов, чтобы получить безусловные доказательства эффективности того, о чём я собирался рассказать в докладе. Когда пришла новость, что доклад одобрен — это был ещё не финал: мне было предложено вместе с другими докладчиками пройти двухдневные курсы ораторского мастерства. Пройдя через это испытание, я знаю: ребята из JUG.ru Group не допустят на своих конференциях ни капли «лажи». И я доверяю им: в этом году я посетил большинство их конференций.

    Московский «Гейзенбаг» для меня — последняя конференция уходящего года, закрывающая насыщенный сезон. Судя по статистике, которую озвучивал программный директор Андрей Дмитриев во время вступительного слова, большинство людей на «Гейзенбаге» — профессиональные тестировщики. По ощущениям от общения — в основном это люди, работающие в крупных компаниях, имеющих выделенные QA команды.

    Я не являюсь типичным посетителем «Гейзенбага». В нашей компании всего около 25 человек, и многие совмещают роли. Мне приходится быть техническим лидом, менеджером проектов и просто «решателем проблем», а автоматизацией тестирования у нас занимаются всего пара человек. Выживание нашей компании буквально зависит от эффективности команды. Наращивание эффективности возможно только лишь через получение новых знаний и расширение кругозора, за чем я и ещё двое моих коллег отправились на «Гейзенбаг».

    День 1


    Открытие конференции


    Хороший настрой был задан с самого открытия конференции. Во время открытия программный директор Андрей Дмитриев дал публике задание: за тридцать секунд познакомиться с кем-то из сидящих вокруг соседей. Зал тут же наполнился громким шумом голосов. Это было очень полезное задание! Ведь конференция — инструмент, которым нужно умело пользоваться для того, чтобы он выдал для тебя максимальную пользу. Хотя кажется, что главная составляющая конференции — доклады, в действительности от сидения на докладах ты можешь получить лишь около 40% от общей пользы, а оставшиеся 60% нужно взять самому — общаясь со специалистами в кулуарах, дискуссионных зонах и на конференционной вечеринке. Если ты — айтишник-интроверт, то для того, чтобы начать разговор с новым человеком, приходится перебарывать себя. Но это трудно только в самом начале — очень скоро ты узнаешь, что все здесь, как и ты, пришли за чем-то новым, и заводить общение на конференции в действительности просто.

    Когда шум поутих, Андрей дал другое задание: за предстоящие два дня запомнить для себя хотя бы пять ключевых идей, которые, вынеся с конференции, мы могли бы применить на практике. Я взял это на заметку, и в трёх залах начались доклады.

    1




    В первый таймслот я отправился на доклад Дмитрия Буздина «Как построить свой фреймворк для автотестов?». Основываясь на теоретической схеме «ISTQB Generic Test Automation Architecture», Дмитрий рассказывал о том, как можно скомбинировать open-source решения, чтобы они полностью перекрывали все задачи процесса тестирования. Лично для меня доклад не содержал каких-то готовых рецептов, но зато я узнал про модель ISTQB, и мои знания о том, из каких деталей должен состоять любой тестовый фреймворк, серьёзно упорядочились.



    В это же время в параллельном зале шёл доклад Сергея Егорова, посвящённый TestContainers. На него я не пошёл по очень простой причине: впервые доклад Сергея о TestContainers я слышал ещё весной на JEEConf, в начале осени мы успешно внедрили у себя эту технологию, а в октябре на Joker-е нам удалось подробно и успешно пообщаться с Сергеем по всем особенностям, которые нам встретились. Идея TestContainers — простая и мощная: используя существующую инфраструктуру Docker и скачиваемых образов, в вашем тесте получить, например, JDBC connection к реальной базе данных Oracle можно просто через инстанцирование класса, причём не сложнее, чем какой нибудь HashMap. Браузеры, базы данных и многое другое доступно «из коробки» простым инстанцированием класса! То, что раньше требовало сложной настройки тестового окружения и конфигурирования самих тестов, теперь сводится к трём простым требованиям: на машине должны быть JDK, Maven (Gradle) и Docker. Создатели TestContainers — большие молодцы, и я им желаю удачи.

    2


    image

    Затем я отправился на доклад Саймона Стюарта «Scaling Selenium». Саймон говорил об общих наболевших проблемах, которые возникают по мере роста и усложнения UI-тестов: «хрупких» локаторах, ожиданиях, масштабировании при помощи Selenium, в том числе в облаке. Хотя я и не чувствовал себя глубоко погружённым в тему, но внезапно понял, что Саймон озвучил первую идею, которую обязательно хочу применить у себя: «check for preconditions». Перед тем, как запускать тесты системы, проверь: все ли сервисы, от которых система зависит, запущены. Работают ли база данных, сервер аутентификации и прочие компоненты, от которых зависит приложение? Ведь если хотя бы один из них «лежит», тестировать смысла не имеет, а стоит остановиться и явно сообщить о проблеме. Иначе — в логи попадает большое количество нерелевантных ошибок, которые подрывают доверие к результатам тестирования как таковым.

    В это же время мой коллега Николай посетил «Selenide Puzzlers» Алексея Виноградова и Андрея Солнцева. Доклады-викторины — отличная идея блеснуть быстротой ума и заработать футболочку. Вернувшись оттуда, Коля сказал, что тянул руку изо всех сил, но ему ни разу не дали слова. Зная деликатного Колю и ажиотаж, который обычно творится на «паззлерах», могу предположить, что стоило тянуть руку ещё сильнее :-) Selenide — прекрасный фреймворк, решающий большую часть проблем «голого» Selenium. Мы довольно успешно экспериментировали с ним, но сейчас используем другой. Хотя после Гейзенбага задумались о правильности своего выбора.

    3


    Следом мы думали, стоит ли идти на доклад Владимира Ситникова «Тестирование производительности веб-приложений на стороне браузера» или на круглый стол «Что должен знать тестировщик в 2018 году?» Мы решили, что в производительность на стороне браузера пока не упираемся, и пошли на «круглый стол».

    image

    Стола там не оказалось, а оказались пять спикеров, сидящих в ряд, ведущий и вопросы, задаваемые из зала и по телеграм-каналу. Обсуждение в основном велось не вокруг технологий, а вокруг карьерного пути тестировщика и организационного устройства компании — вещей, не очень актуальных для такой микро-компании с плоской структурой, как наша. Хотя докладчиков было пять, больше и активнее всех говорил Николай Алименков, а некоторым хорошо если за час удалось вставить несколько реплик. Я считаю Николая одним из лучших экспертов и тренеров в IT области, да и просто классным остроумным чуваком. Но на этой конференции у него и так было своих два доклада, и поэтому, может быть, иногда стоило дать больше времени высказаться другим ребятам.

    Я понял такую вещь: идти на «круглый стол» имеет смысл лишь в том случае, когда у тебя есть конкретный вопрос, который бы ты хотел задать группе экспертов. Если ты идёшь на «послушать», то нить разговора может уйти не туда, куда ты ожидаешь. Задать же свой специфический вопрос спикерам бывает удобнее в дискуссионной зоне или на вечеринке, что делает саму идею «круглого стола» довольно сомнительной.

    Но не сказать, что в этом тайм-слоте мы плохо провели время. Оказавшись рядом со своим коллегой, я показал ему несколько падающих UI-тестов, из-за которых Jenkins спамил мне в почту, а я нервничал перед предстоящим на следующей неделе показом заказчику. Совместно нам удалось довольно быстро докопаться до причин падения этих тестов, и я вышел из зала удовлетворённый. Иногда на конференции бывает нужно и поработать. А доклад Владимира Ситникова мы обязательно посмотрим в видеозаписи!

    Обед


    К тому, что я скажу, можно относиться с иронией, но я считаю обед важнейшим показателем качества любой конференции. Ты тратишь целый день, уезжаешь в командировку или просто приходишь домой в глубокой ночи, постоянно сфокусирован на получении знаний — это энергозатратно. Питание на конференции должно быть таким, чтобы мысли о еде и жажде не отвлекали, и с учётом того, что у тебя могут оказаться специфические требования к еде. JUG.ru Group в этом плане молодцы, качество питания у них хорошее, хотя бывают и проколы: телеграм и каменты на Хабре долго бурлили по поводу киноа на Joker-е 2017 :-) В этот раз, оказавшись на обеде, я обнаружил, что хотя весь народ уже явно насытился, столы ещё ломились от закусок и горячих блюд. Это вселило в меня приятную уверенность, и я не отказал себе ещё в одной порции рыбки под овощами и баклажачников с сыром, после чего был готов продолжить :-)

    4


    image

    На предыдущем, питерском «Гейзенбаге» Андрей Сатарин рассказывал о специальных инструментах для анализа исполнения кода на C++. Мы пишем на Java, поэтому я думал, что и его нынешний доклад «Как проверить систему, не запуская её» не будет актуален для нас. Но всё-таки я подошёл к самому Андрею и спросил у него. Оказалось, что доклад вовсе не ограничен C++, я остался — и не пожалел. Отсюда вывод: никогда не стесняйтесь заранее уточнить, о чём будет доклад, у спикера или у члена программного комитета. Вам с готовностью ответят, и это повысит эффективность вашего времяпровождения на конференции.

    Идея, которую излагал Андрей, одновременно дёшева в реализации и эффективна: конфигурационные файлы распределённых систем могут и должны быть верифицированы автоматически. Самое простое, что можно проверить — это то, что эти файлы вообще существуют и являются валидными JSON/YAML/XML, но возможны и более сложные проверки: например, что распределение сервисов по нодам / стойкам / датацентрам соответствует требованиям к отказоустойчивости системы. Или что хосты и порты связывается в единую сеть, иначе может оказаться, например, что из-за неправильной настройки портов в вашем кластере меньше связанных инстансов, чем вы думали.

    Для меня картина, однако, не складывалась в одном месте: Андрей рассказывал о случае, когда конфигурационные файлы находятся в системе контроля версий в готовом виде, но, например, у нас конфигурационные файлы создаются динамически и раскладываются по виртуалкам при помощи Ansible, а на виртуалках они уже перестают быть доступны. Я пошёл в дискуссионную зону и небольшой «мозговой штурм» привёл к решению: достаточно во время прогона ansible-playbook сложить копии конфигов в отдельную папку и сразу после этого запустить проверки получившихся конфигов. И хотя пока ещё риски, о которых говорил Андрей, для моего проекта не существенны, я знаю, что со временем они станут существенными, и тогда эти проверки можно и нужно будет реализовать. Так была получена вторая идея «на вооружение».

    5




    Автор следующего доклада «The Abuse and Misuse of Test Automation» Алан Пейдж принимал участие в выпусках Microsoft Windows в те годы, когда я в институте писал «hello world» на Borland C++. Одно это стоило того, чтобы сходить на него. Доклад упоминал широко известную концепцию «пирамиды тестирования», которая часто имеет тенденцию вырождаться вот в такой смешной «рожок мороженого»:

    image

    «Тестовая пирамида означает, что вы должны писать настолько мало меньше UI-тестов, насколько это возможно,» — говорил Алан. UI-тесты 1) трудно писать, 2) они требуют огромных вычислительных ресурсов и всё равно медленные, 3) они ненадёжны (flaky). Самые надёжные и дешёвые тесты — это Unit-тесты, их и должно быть больше всего. А в случае обнаружения бага, тест на него должен быть написан на как можно более низком ярусе тестовой пирамиды — идеально, если это будет Unit-test.

    Казалось бы — это самые азы! Но странно, что я не сформулировал для себя это раньше в столь кристально ясном виде. Таким образом, обновлённое представление о сути тестовой пирамиды явилось для меня ещё одной идеей «на вооружение» с конференции.

    6


    Закрывал первый день доклад Николая Алименкова «Бытовая классификация тестировщиков с точки зрения разработчика», где он остроумно описал архетипичные случаи неэффективного и деструктивного поведения тестировщиков в компании: «тестировщик-нацист», «тестировщик-слизняк», «тестировщик-одуванчик»… Действительно, от эффективно работающих людей в организации зависит гораздо больше, чем от технологий, и такой доклад кому-то, возможно, откроет глаза на то, что творится у них в команде, а руководителям — позволит диагностировать случаи неэффективного поведения сотрудников.

    Вечеринка


    Вечеринки на конференциях устраиваются в основном для того, чтобы можно было встретиться и поговорить с коллегами-специалистами, не будучи скованным временными рамками перерыва между докладами. Поэтому там необходимы напитки, еда и достаточно тихих удобных мест, где можно беседовать. На огромных конференциях типа Joker образуются шумные толпы, вокруг популярных спикеров возникает толкучка и общаться бывает нелегко. В этом плане мне больше по душе менее многочисленные конференции, и «Гейзенбаг» на этот счёт оказался хорош. Мы прекрасно пообщались с Владимиром Ситниковым на темы, связанные с SQL, а затем я перешёл к группе, образовавшейся вокруг Николая Алименкова: как оказалось, там вовсю шло обсуждение его закрывающего доклада, люди обсуждали организационные проблемы в их компаниях. Все сошлись на мысли, что «чинить» проблемы с людьми — гораздо более сложное занятие, чем самые запутанные баги. Удалось и мне поговорить с Николаем и что-то узнать относительно того, как лучше проводить трансформацию процессов в нашей компании, ставить цель, выстраивать delivery-конвейер. Разговор ушёл далеко от темы тестирования в тему управления процессами, и это прекрасно: ты ездишь на конференции для того, чтобы общаться с экспертами на любые волнующие тебя темы, не обязательно ограниченные рамками названия конференции.



    День 2


    1




    Наступил второй день. Я явился к первому слоту невыспавшийся и с головой, уже пухнущей от информации, полученной в первый день. Также мне надо было кое-что закодить и сделать пулл-реквест. Поэтому, хотя я и находился в зале на докладе Артема Ерошенко «Простота, доверие, контроль — три кита автоматизации веб-тестирования», половина моего фокуса была направлена на мой IDE. PageElements — это круто и правильно. Retrofit превращает HTTP API в Java-интерфейс. Хозяйке на заметку: яндексовый htmlelements в его улучшенной инкарнации надо брать с гитхабника Артёма eroshenkoam.

    Извините, Артём, я был не самым лучшим слушателем Вашего доклада. Пожалуй, этот доклад надо как-нибудь пересмотреть в видеозаписи. Нет ничего страшного в том, чтобы на конференции какой-то из слотов пропустить: всего ухватить невозможно. Информация, как и еда, требует переваривания.

    2




    В своём докладе «Разработчик + тестировщик = качество++» Николай Алименков продолжил вчерашнюю тему борьбы за улучшение процессов в организации. Не в первый раз Николай выступает ярым противником существования «отдела тестирования», в который, как через кирпичную стену, разработчики «закидывают» продукт, чтобы через какое-то время получить его от тестировщиком «откинутым» обратно. Николай рассказывал о преимуществах Agile Feature Teams с совместной работой разработчиков и тестировщиков, и «основных ингредиентах эффективности», которые могут внести тестировщики и разработчики во время выполнения основных практик такого процесса, и, как результат, о переходе от идеологии Quality Assurance к идеологии Quality Assistance.

    3




    Мы — давние пользователи Jenkins, поэтому я в обязательном порядке пошёл на доклад Олега Ненашева «Строим свой тестовый фреймворк, c Jenkins Pipeline и библиотеками». Правда, как я вижу из докладов на митапах, в уровне использования Jenkins мы отстаём: в Jenkins предлагается использовать Pipeline, мы же до сих пор сидим на Freestyle Jobs / Maven Build Jobs. О необходимости перевода всех jobs на Pipeline Олег говорил в выводах своего доклада уже прямым текстом.

    Но те примеры, которые показываются на докладах Олега по Jenkins, на мой взгляд, довольно сложны, изобилуют кодом на Groovy, который мы не знаем, отсылками к API, которых мы не знаем, и в целом производят впечатление трудно отлаживаемых хаков. Хотя, судя по глубине вопросов из публики, вокруг очень много людей, которые этим пользуются «на полную катушку». В нашем простом случае несколько пугает порог вхождения. А ведь нам нужно от Jenkins не так уж много: чтобы он собирал Maven-проекты, публиковал артефакты и при этом полностью бы конфигурировался через код на контроле версий. Куда деваться — надо всё это учить, надо разобраться с примерами Олега на гитхабе.

    И ещё мы слышали, как некоторые люди, выходя с доклада, говорили между собой: «Всё ясно, надо переходить на TeamCity». Между CI системами сейчас существует серьёзная конкуренция, и Jenkins ещё предстоит за себя побороться…

    4




    Павел Сенин в своём докладе Selenoid — сотни параллельных UI-тестов легко и быстро продемонстрировал, как при помощи системы Selenoid можно подменить ненадёжный и плохо масштабируемый Selenium хаб красивым решением, которое запускает браузеры в контейнерах и выдаёт сессии тестам, при нехватке ресурсов выстраивает запросы на сессии в очередь, и, что самое главное, при этом не требует, чтобы сами имеющиеся у вас Selenium-тесты были переписаны.

    Так как по роду проектной работы я хорошо знаю, что браузер — это зверь, готовый сожрать все ресурсы, и потому его лучше держать «в клетке», полностью изолируя от других процессов, идея с Selenoid мне очень понравилась. Это определённо ещё один takeaway с конференции. Мы попробуем развернуть у себя Selenoid-сервер как общий ресурс для UI-тестов в нашей компании.

    В процессе доклада Павел невольно раскрыл и общие для многих организационные проблемы в его команде, что не ускользнуло от писавших в твиттер. Решение организационных проблем — это то, что проходило для меня на этом «Гейзенбаге» красной строкой.



    5




    Доклад Андрея Солнцева под кратким названием «Flaky tests», на мой взгляд, оказался самым лучшим на конференции. Отправляясь на него, думал: «Ну да, есть такая вещь, как тесты, которые неизвестно почему иногда не срабатывают — что же тут можно рассказать?» И действительно, что тут скажешь? Андрей не дал готовых простых рецептов избавления этот таких ситуаций, хотя обозначил основные направления борьбы с ними.

    Зато он рассказал ряд по-настоящему детективных историй из собственной практики, иногда длившихся месяцы и годы. Например, «Проклятие зелёной кнопки», которую на долю секунды закрывал собой всплывающий progress bar, из-за чего кнопка не нажималась.

    Или самое лучшее: «Почему зависает Chrome?» — загадка, которую Андрей не мог разрешить на протяжении целых двух лет, перепробовав всё, что только можно: логи, таймауты, отладку… Однажды, когда он безуспешно отрабатывал самые уже безумные гипотезы, дочка позвала его играть в кубики. Он нехотя отвлёкся от работы, с сожалением поглядывая на монитор. Тест был оставлен без присмотра минут на двадцать. Внезапно на экране показалось следующее, и разгадка настала:



    Завершал Андрей тем же, о чём говорил Николай: разработчики должны участвовать в работе тестировщиков, чтобы через «взаимопроникновение» команды взаимно обогащались.

    Одна из причин ‘flakiness’ наших собственных тестов на одном из проектов состоит в том, что данные в нашей тестовой базе «загрязняются» по результатам работы предыдущих тестов. В дискуссионной зоне я хотел спросить у Андрея, с помощью каких механизмов лучше быстро поднимать свежую копию базы с данными перед каждым тестом. Рядом оказались ребята, опытные в этой области, завязалась дискуссия, и буквально за пару минут мы выработали решение, подходящее именно для нас и оптимальное в нашем случае. Мы так и реализуем в ближайшее время, это безусловно ещё одна идея «на вооружение». И круто же, когда конкретно тебе твою инженерную задачу на конференции помогают решить лучшие эксперты в области :-).

    6




    Завершал конференцию доклад Алана Пейджа 'Truths about technical testing'. Алан рассуждал о том, что ждёт тестировщиков в трансформирующемся мире, где разделение между специальностями «разработчик» и «тестировщик» стирается.

    Например, нынешний стереотип, что «тестировщик» — это непременно «автоматизатор UI тестов» — должен сломаться, тем более, что принцип тестовой пирамиды вынуждает нас писать как можно меньше UI тестов. Вместо этого тестировщик должен как можно больше вливаться в процесс разработки. Казалось, что Алан прямо продолжает мысли Николая и Андрея, выступавших в этом зале перед ним, и так оно и было: например, у Николая был слайд про «перекидывание продукта через стену» между командами разработчиков и тестеров, а Алан смешно изображал это перекидывание пантомимой.

    Алан рассказал, что в его бытность разработчиком самое большое удовлетворение он испытывал не тогда, когда создавал новую функциональность, а когда отлавливал какой-нибудь баг, и я согласен с ним полностью — у меня то же самое. После своего доклада и официального закрытия конференции Алан вышел в опустевший коридор в самую последнюю дискуссионную зону конференции, и мы с ним немного поговорили на эти темы: он оказался очень приятным в общении человеком.

    Заключение


    В завершающем слове Андрей Дмитриев спросил публику — «сколько ‘take-aways’ вы увозите с конференции»? Честно говоря, я к этому моменту уже не считал. Но зато я точно знал, какой я увожу самый-пресамый главный take-away, про него я написал в твиттере:

    Поделиться публикацией
    AdBlock похитил этот баннер, но баннеры не зубы — отрастут

    Подробнее
    Реклама
    Комментарии 12
    • +2
      Извините, Артём, я был не самым лучшим слушателем Вашего доклада. Пожалуй, этот доклад надо как-нибудь пересмотреть в видеозаписи. Нет ничего страшного в том, чтобы на конференции какой-то из слотов пропустить: всего ухватить невозможно. Информация, как и еда, требует переваривания.

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

      Конференция действительно интересная и полезная
      • 0
        Мне вот интересно почему у статьи есть теги «Конференции, Java», хотя есть в статье есть всего 2 упоминания о Java, но нет тега «тестирование», как мне казалось оно является основой темой на конференции «Гейзенбаг»…
        • 0
          Потому, что куда-то я мышью ткнул не туда, вот почему) я изначально ставил хаб «тестирование», но сегодня его не обнаружил и только что даже с администратором говорил, не они ли с хаба сняли. Нет, не они. Поправил, есть теперь хаб «тестирование» )
      • +3
        Иван, спасибо за пост и теплые! Мы стараемся делать каждый Heisenbug лучше предыдущего.
        • +3
          И пока что вам это удаётся, так держать! ))
        • +2
          В защиту Jenkins скажу, что доклад был рассчитан на большие проекты, где реально требуется шаринг кода между задачами и построение фреймворков. Для этого порог входа действительно высок. Для простых кейсов («чекаут/запустить Maven/опубликовать отчет») всё это не нужно, можно писать Pipeline-scripted/declarative скрипты на несколько строк. Об этом я говорил в дисклеймере и начале доклада, но видимо получилось нечётко.

          • 0
            И я тоже скажу в защиту Jenkins! Написанное в секции про выступление Олега — написано с точки зрения очень базового пользователя Jenkins, стремящегося к улучшению своего CI-сетапа, и ни в коем случае не претендует на экспертную оценку Jenkins как такового или уровня доклада Олега как такового.
            • 0
              Наиболее простой способ начать с Pipeline — это Declarative Pipeline + Pipeline Editor в Blue Ocean. В этом случае многое можно собрать в UI, вообще не занимаясь написанием кода вручную.
          • 0
            Интересно узнать по-подробнее касательно 5го пункта, а точнее какие решения вы выработали касательно БД и ее очистки после прогонки тестов, поделитесь пожалуйста!
            • 0
              Конкретно в нашем случае лучший вариант — это использование in-memory СУБД H2, которая умеет моментально стартовать. К счастью, мы специально поддерживаем совместимость с базой H2 для юнит-тестов, но UI-тесты мы гоняем на PostgreSQL, что неверно. Мне подсказали, что совершенно нормальный вариант — заиметь дамп H2-базы с тестовыми данными и восстанавливать его перед каждым UI тестом.

              Иногда совместимость с H2 невозможна. В этом случае, как я слышал, хорошим решением является использование RAM-дисков: их образ можно довольно быстро восстанавливать из файла и уже с RAM-диска запускать настоящую СУБД типа PostgreSQL или Oracle — говорят, это работает.
            • 0
              Хозяйке на заметку: яндексовый htmlelements в его улучшенной инкарнации надо брать с гитхабника Артёма eroshenkoam.

              А лучше с Bintray
              Кстати, рекомендую использовать версию 2.0-BETA16 — там есть пара прикольных фишек, которые мне пригодились в работе.

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