вторник, 3 июля 2012 г.

Тестируем JavaScript

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

Есть несколько способов разрешения ситуации. Можно, например, возненавидеть javascript и перейти на GWT/Vaadin/etc, тестировать java код в привычном окружении и на выходе получать протестированный javascript. Но, кому-то либо уже поздно, либо нет желания, либо ещё что-нибудь.

Сегодня расскажу о том, как можно тестировать JavaScript с помощью библиотеки JavaScript Test Driver (JSTDот Google.

Краткая предыстория

Чем больше я писал JavaScript кода тем больше он вызывал у меня подозрения. Я частенько пытался найти способ протестировать только что написанный код. Годом ранее я пытался использовать QUnit, библиотеку, написанную для тестирования jQuery. Но не пошло. Resharper позволял запускать QUnit тесты, однако перспектива смотреть результаты в браузере немного огорчала.


Зимой мы с Андреем Ребровым пытались покрыть тестами веб часть достаточно крупного приложения с использованием фреймворка Selenium. C большим энтузиазмом мы написали множество тестов, фреймворк быстро оброс новым функционалом, адаптерами и вспомогательными штуками. Написание тестов мы старались сделать максимально простым и понятным для тестеров, которые будут их поддерживать.


Тем не менее, уж очень нестабильны были эти тесты и выполнялись чертовски долго. В целом ситуация получилась почти идентичной недавно описанной Александром Бындю:
Зелеными тесты не были никогда.
Очень быстро тесты на селениуме загнулись и больше не запускались.


JavaScript Test Driver

Всё ещё озадаченный вопросом покрытия, я не оставлял надежды и пытался найти фреймворк понадежнее. Через некоторое время я наткнулся на JSTD.


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


Тесткейзы пишутся всё так же на js:
Заметно, что формат ассертов максимально приближен к привычному JUnit:
JsTestDriver aims to help javascript developers use good TDD practices and aims to make writing unit tests as easy as what already exists today for java with JUnit.
Хочу сразу отметить, что если тест не начинается со слова test - запущен он не будет.

Вдаваться в подробности использования я не буду, всё очень понятно описано на сайте разработчиков.

Запускаем из IDEA

Не скажу что меня радует запускать тесты из консоли и потому очень быстро нашёлся плагин для IntelliJ IDEA.

Плагин очень радует, обновляется стабильно, поспевает за фреймворком (отдельно сервер иметь не обязательно, но возможно); запускается просто, тесты гоняет быстро. В последней версии он даже умеет считать процент покрытия.

Вот так выглядит запущенный из IDEA сервер. 
Браузеры можно захватывать кликом мыши. 

Захваченный хром.

Запуск тестов выглядит так же как и для любых других языков в IDEA.

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


CI?

Разработчики отмечают, что одним из основных назначений фреймворка является запуск тестов на continuous integration сервере:
Focus on the command line and the continuous build
Фреймворк достаточно удобно интегрируется с Maven'ом (https://code.google.com/p/jstd-maven-plugin/) и потому может быть запущена на CI серверах. Тем не менее, есть проблема — надо придумать как и когда запускать JSTD сервер. Есть две опции: либо заранее, либо вместе с билдом. Во втором случае почему-то сервер любит открывать новые окна браузера, не закрывая старые, поэтому в теории всё может закончится достаточно печально — сотней-другой открытых окон различных браузеров. А самостоятельно поднимать и убивать надоедает, тем более сервер иногда и сам падает по неизвестным причинам. В общем, есть над чем поработать.



В итоге:
  • Если у вас не hello world - пишите тесты
  • Старайтесь отделять логику отображения от бизнес логики
  • Пишите маленькие, независимые и не глобальные функции/методы/классы
  • Пишите маленькие и независимые тесткейзы
Спасибо!
Хорошего дня!