Интерфейс
net.thucydides.core.steps.StepListener
представляет собой класс, прослушивающий ход выполнения теста и получающий данные или результаты в определенных точках его выполнения. StepListener
получает информацию от Thucydides на уровне выполнения самих тестовых методов и их шагов (stepStarted, stepIgnored, stepFailed и т.д.). Thucydides использует этот интерфейс для собственных нужд, но также предоставляет нам возможность создать и зарегистрировать свой собственный listener. Для этого нужно реализовать в классе интерфейс net.thucydides.core.steps.StepListener
и зарегистрировать его в Thucydides:
import net.thucydides.core.model.Story; import net.thucydides.core.model.TestOutcome; import net.thucydides.core.steps.ExecutedStepDescription; import net.thucydides.core.steps.StepFailure; import net.thucydides.core.steps.StepListener; public class MyProjectStepListener implements StepListener { public void skippedStepStarted(ExecutedStepDescription arg0) { } public void stepFailed(StepFailure arg0) { } public void stepFinished() { } public void stepIgnored() { } . . . }
Регистрацию MyProjectStepListener можно осуществить двумя способами:
- Использовать метод
registerListener(final StepListener listener)
классаnet.thucydides.core.steps.StepEventBus
. КлассStepEventBus
является своеобразным средством передачи соответствующих уведомлений о ходе выполнения теста всем зарегистрированным слушателям.StepEventBus
использует внутри себя разделение на потоки, поэтому работа с ним осуществляется через статический методgetEventBus()
, который возвращает экземплярStepEventBus
для текущего потока:MyProjectStepListener myProjectStepListener = new MyProjectStepListener(); StepEventBus.getEventBus().registerListener(myProjectStepListener);
Отменить регистрации можно с помощью метода
dropListener
:StepEventBus.getEventBus().dropListener(myProjectStepListener);
Основное преимущество этого способа заключается в том, что выполнять регистрацию или ее отмену можно в любой момент выполнения теста.
- Установить класс MyProjectStepListener как сервис-провайдер (service provider) для интерфейса
net.thucydides.core.steps.StepListener
, тогда классStepEventBus
автоматически обнаружит слушателя и добавит его в список зарегистрированных. Пользовательские слушатели загружаются и регистрируется один раз во время запуска теста. Для того, чтобы установить Ваш класс в качестве сервис-провайдера, нужно расположить конфигурационный файл в директорииMETA-INF/services
Директория в свою очередь должна быть расположена в одной из src папок проекта (например, в src/main/java). Конфигурационный файл представляет собой обычный текстовый файл, имя которого является полным именем типа службы, в нашем случае это
net.thucydides.core.steps.StepListener
(следите за тем, чтобы у файла не было расширения .txt).
Файл должен содержать список имен классов-провайдеров, реализующих методы интерфейса, каждый с новой строки. Для нашего примера в нем будет единственная строка с именем класса MyProjectStepListener:example.support.MyProjectStepListener
Помимо регистрации слушателей класс StepEventBus
предоставляет несколько других полезных методов, например, aStepInTheCurrentTestHasFailed
. Используя этот метод можно предотвратить выполнение нежелательных действий после того, как один из шагов закончился неудачно. Необходимость в этом может возникнуть, потому что Thucydides даже после падения одного из шагов, продолжает запускать последующие шаги на выполнение, блокируя обращение только к драйверу. В итоге получается, что сопутствующие действия, вроде записи в файл или изменения ресурсов, продолжают выполняются даже после того, как тест по сути провалился. Проверяя результат метода aStepInTheCurrentTestHasFailed
можно запретить, например, выполнение дальнейших запросов к БД, которые после провала теста не представляют никакой ценности:
private static boolean isTestFailed() { return StepEventBus.getEventBus().aStepInTheCurrentTestHasFailed(); }
Татьяна, спасибо за статью.
Я пока не очень хорошо ориентируюсь в Thucydides. Поэтому хотел спросить, как применить на практике то, о чем Вы написали, в каких случаях можно/нужно использовать StepListener?
Использование StepListener совсем не обязательно. Его стоит использовать только, если Вы хотите реализовать какие-то свои дополнительные функции во время выполнения тестов, например, проверять какие-либо значения перед запуском каждого step-а или после, или может быть Вы захотите делать свой скриншот при каждом изменении на странице (notifyScreenChange). Можно, например, закрыть подключение к БД в случае stepFailed для того, чтобы не выполнялись дальнейшие ненужные запросы. Примеров может быть очень много, StepListener просто дает Вам возможность получить управление в некоторых точках выполнения шагов теста. Как это использовать — зависит от Ваших задач.
Добрый день, Татьяна! Вы интересно пишете, не хотите поделиться своим опытом с WebDriver на конференции Selenium Camp 2013 (http://seleniumcamp.com)?
Добрый день! Большое спасибо за приглашение. К сожалению, в этот раз посетить конференцию я не смогу. Постараюсь принять участие в следующий раз.
Спасибо большое за статью. Очень помогла. Долго бился над решением этого вопроса, а тут всё уже решено. Спасибо.
Пожалуйста)
Добрый день!
Спасибо за еще одну очень информативную и полезную статью.
Я хотела узнать, если в ходе прохождения теста thucydides на мой взгляд делает слишком много ненужных скриншотов, но при этом не делает скриншоты на шагах, где они нужны (вернее делает в первой и последней точке шага, показывая по сути одну и ту же страницу, пропуская при этом средний шаг — где как раз нужно сделать было скриншот). Поможет ли мне StepListener решить эту проблему? Можно ли с его помощью указать thucydides где именно следует делать скриншоты в ходе прохождения теста?
Спасибо!
Небольшое добавление. Я нашла и попробовал аннотацию @Screenshots(FOR_EACH_ACTION), но все равно получаю тот же результат — т.е. картинку в начале шага, когда нажимается кнопка на главной странице и в конце шага, когда драйвер возвращается на исходную — главную же — страницу. А скриншота подтверждающего то, что драйвер при выполнении шага действительно перешел на заданную страницу — нет.
StepListener в данном случае никак не поможет, потому что Thucydides использует его же для снятия скриншотов в BaseStepListener, делает скриншот в том числе и для notifyScreenChange().
Можно попробовать вызвать снятие скриншота в нужный момент принудительно такой вот функцией на странице:
Но это только предположение, потому что там еще присутствует логика проверки дублирования скринов, может и не заработать.
А вообще, скриншоты можно отключить через установку свойства
thucydides.only.save.failing.screenshots
в true. Это значительно ускорит процесс выполнения тестов, а проверить открытие страницы можно по урлу с помощью аннотации @At.Добрый день!
В отчете есть вкладка Progress и график Project Progress (Requirements), он у меня пустой, какой аннотацией он подключается или чем то еще?
Добрый день Татьяна)
Скажите пожалуйста можно ли с помощь этого листерна переопределить поведение тестов, то есть например сделать «сломанные тесты» если будет ексепшен типа НоСачЕлмент то вы давать не тест фейлед, а тест брокен? и есть ли подобные листерны в TestNG?
Добрый день,
нет, такого сделать нельзя. В целом, листнеры совсем не предназначены для такого глобального изменения поведения.
StepListener относится именно к библиотеке Thucydides, а не к JUnit, поэтому нельзя проводить параллель с TestNG.
Понял, спасибо)
Татьяна, добрый день!
Спасибо за статью, правда не совсем понял как использовать метод isTestFailed.
Я правильно понимаю, что этот метод надо использовать каждый раз, когда в шаге предполагается использовать базу данных (методы без драйвера) в тестовом шаге:
@Test
public void TestWithDB(){
...
endUser.step1();
...
if (!isTestFailed){
endUser.step_with_db_query();
}
...
if (!isTestFailed){
endUser.step_with_db_query();
}
}
Можно ли как-то перехватывать isTestFailed=true ?
Как можно проверять текущее состояние шага, Чтобы такие проверки можно было делать непосредственно в шаге?
Функция isTestFailed() просто пример того, как можно использовать StepEventBus не подключая своих листнеров. Обратиться к StepEventBus можно откуда угодно, в том числе непосредственно в шаге. Можно также вызывать isTestFailed из класса, который непосредственно работает с базой.
Что касается перехватов событий, то для этого как раз нужно создать и подключить свой собственный listener.
Спасибо 🙂
Добрый день, Татьяна!)
А не подскажите, как сделать чтоб логи выводились одновременно с выполнением тестов, а то они все выводятся только по завершению всех тестов?? Есть какой то параметр или надо свой listener писать?
Добрый день,
Если я правильно понимаю, то эта проблема у Вас только при запуске из командной строки. Логи выводятся после завершения тестов, если в проекте настроен параллельный запуск.
А по умолчанию в Thucydides проекте он включен, уберите в pom файле <parallel>classes</parallel> в конфигурации maven-failsafe-plugin, и тогда логи будут выводиться одновременно с выполнением.
Спасибо))
А еще не подскажите, как запускать тесты (для отладки в IDE) не через Firefox, а в специально созданyом профиле FF ? Через консоль все норм если запустить webdriver.firefox.profile в от через IDE (Idea) не выходит.
Нужно настроить конфигурацию запуска — Run -> Edit Configurations. Выберите конфигурацию JUnit для вашего теста и создайте новую environment variables для webdriver.firefox.profile.
И посмотрите вот эту статью FirefoxDriver: способы создания профилей Firefox. В ней тоже есть альтернативные способы задания профиля.
Если юзать в качестве фреймворка thucydides то почему то не выходит запустить тесты в профиле через IDE http://screencast.com/t/fDrqkwCEKB и даже если в переменную указать полный путь к профилю все равно не работает((
Странно, но больше похоже на проблему IDE, из командной строки же все работает.
Можно еще создать Maven Run configuration и имитировать запуск из командной строки, правда тогда еще нужно будет настроить выборочный запуск теста по имени.
Спасибо) А не подскажите как запустить не все тест сьюты, а какой то один? Пробывал через -Dtest=SimpletestSuit test не выходит, все тесты запускаются
Все зависит от настроек pom файла, идею можно почерпнуть отсюда, в конце статьи есть пример.
Татьяна, спасибо огромное за подробную и интересную статью!
второй способ подключения Listener работает только, если папка META-INF находится в «src\main\resources\», проверял на версии 0.9.208.
а подскажите пожалуйста, как получить доступ к драйверу внутри Listener? Thucydides при скипе шага начинает ожидать элементы, которые определены через @FindBy и использует при этом тайм-аут имплицитного ожидания.
получить доступ к текущему драйверу можно так:
ThucydidesWebDriverSupport.getDriver();
это потокобезопасный метод
спасибо!
Можно ли использовать совместно с jbehave?
Можно