Организация BDD подхода при использовании Webdriver + PageObject + PageFactoty + Maven

Всем привет.  Давайте поговорим о BDD подходе в Java при использовании Webdriver'a. Кто, какие использует фреймворки и почему?

Предистория: Работаю с IDE - IDEA. Я испробовал несколько штукенций и вот какие вижу проблемы:

1) Если использовать Thucydidies то у проекта нет гибкости (хотелось бы  немного другой отчет, хотелось бы управлять браузером и его запуском (профилем, настройками, расширениями), хотелось бы видеть TestNG и поддержку AfterSuite / BeforeSuite аннотаций, хотелось бы перехватывать результат выполнения сценария каким-нибудь AterMethod)

2) Попробовал использовать Cucumber - нет учета времени при выполнении шагов, нет все той же поддержки TestNG (Если использовать пример из документации, то тогда все тесты будут выполнятья в 1 методе и называться run, что не дает никакого представления о том в каком состоянии проект) и самое главное ХЗ как запустить тесты из Maven (Хотя А. Дзыне вроде тут помогли - https://groups.google.com/forum/?fromgroups=#!topic/cukes/1DSrCLkhXZo)

3) Попрообал Jbehave, все так же нет поддержки TestNG (хотя в документации заявлено, что можно, но у меня так и не вышло), нет никакой отчетности и наглядности, зато оно отлично запускаеся Maven"ом.

Итого, очень хочу иметь гибкость в проекте, использовать TestNG и BDD подход, при этом хочу запускать это все дело из Maven. Как быть? Как организованы тесты у вас?

 

Почему именно TestNG? JUnit из всех "свистелок" пока вроде как параллельное выполнение не поддерживает. А в остальном они практически идентичны. Хотя, вот для JBehave пример TestNG теста: https://github.com/jbehave/jbehave-core/blob/master/examples/trader-testng/src/main/java/org/jbehave/examples/trader/testng/TestNGTraderStories.java

Про отчетность и наглядность JBehave - это вы скорее всего недосмотрели. Для этого в конфигурации JBehave  надо указать форматы вывода. Вот один из примеров:

public Configuration configuration() {
return new MostUsefulConfiguration()
.useStoryLoader(new JiraStoryLoader("SC-10"))
.useStoryReporterBuilder(
new StoryReporterBuilder()
.withRelativeDirectory("")
.withDefaultFormats()
.withFormats(Format.CONSOLE, Format.TXT,
Format.XML, Format.HTML));
}

В-общем, все, что нужно, должно быть.

Спасибо, по поводу отчетности, действительно недоглядел, буду пробовать. А вот по поводу примера - он не рабочий :) Попробуйте его запустить.  Там есть импорт import org.jbehave.examples.trader.TraderStories; которого нет в пакете, а без этого файла не запускается.

TestNG потому что функциональных возможностей больше, например поддержка большего числа аннотаций и dataprovider (BeforeSuite, BeforeTest, BeforeMethod и тд.). А по поводу параллельного выполнения, я слышал что наоборот TestNG поддежирвает а Junit нет, но в данный момент мне это не важно, нет больших проектов.

А вот по поводу примера - он не рабочий :) Попробуйте его запустить.  Там есть импорт import org.jbehave.examples.trader.TraderStories; которого нет в пакете, а без этого файла не запускается.

Его можно найти здесь: https://github.com/jbehave/jbehave-core/blob/master/examples/trader/src/main/java/org/jbehave/examples/trader/TraderStories.java . Там много всяких пакетов и для того, чтобы всё нормально запускалось, надо тянуть всё.

TestNG потому что функциональных возможностей больше, например поддержка большего числа аннотаций и dataprovider (BeforeSuite, BeforeTest, BeforeMethod и тд.).

Разного рода hooks есть в самом JBehave: http://jbehave.org/reference/stable/annotations.html (как раз те самые аналоги BeforeSuite, BeforeTest, BeforeMethod и тд.). TestNG DataProvider для JBehave не особо нужен. Посмотрите в сторону Examples в JBehave: http://jbehave.org/reference/stable/tabular-parameters.html (см. раздел Parametrized Tables ). Это по сути аналог DataProvider,  с той разницей, что входные параметры вы задаете прямо в сценарии в качестве примеров (что в-общем-то и задумывалось)

А по поводу параллельного выполнения, я слышал что наоборот TestNG поддежирвает а Junit нет, но в данный момент мне это не важно, нет больших проектов.

Я про TestNG и говорил. Возможность параллельного запуска - это его фича, которая никак не представлена в JUnit. Все остальное - это разного рода "свистелки", просто представленные под разным соусом.

 

Круто, спасибо вам большое. Действительно не доглядел с отчетами, они формируются во вложенную папку target/jbehave/view я сначала не заметил их там, выглядят отлично и наглядно. И за аннотации тоже спасибо, это для меня было главным критерием, оказывается тоже не доглядел в документацию.

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

Осталось только найти как использовать русский язык и перехватывать результаты выполнения сценариев (чтобы работало снятие скриншота при падении).

Осталось только найти как использовать русский язык

http://jbehave.org/reference/stable/stories-in-your-language.html

и перехватывать результаты выполнения сценариев (чтобы работало снятие скриншота при падении).

Ссылку на hooks я скинул ,также дополнительно ищите hooks для TestNG.

Еще раз большое вам спасибо за подробный ответ, буду пробовать.

У вас случайно примера не найдется? У меня не получилось, может я что-то не так делаю:

1) создал файл keywords_ru.properties.

2) добавил его в архив C:\Users\***\.m2\repository\org\jbehave\jbehave-core\3.7.5\

3) Добавил строчку  Keywords keywords = new LocalizedKeywords(new Locale("ru")); в класс конфига.

Запускаю и получаю:

 Resource bundle i18n/keywords not found for locale ru in classLoader ClassRealm[plugin>org.jbehave:jbehave-maven-plugin:3.7.5, parent: sun.misc.Launcher$AppClassLoader@5d91dd1d]: Can't find bundle for base name i18n/keywords, locale ru -> [Help 1]

 

Потом нашел пример тут http://jockeholm.wordpress.com/2010/01/25/localizing-jbehave-scenarios/  запустить не удалось.

Вы сами скинули ссылку на ответ на свой вопрос. Там же приведен пример инициализации поля keywords:

this.keywords = new I18nKeyWords(
new Locale("sv", "SE"),
new StringEncoder("ISO-8859-1", "ISO-8859-1"),
"se/adaptiv/minesweeper/scenario/keywords",
classLoader);

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

В последней версии Jbehave 3.7.5 нету класса  I18nKeyWords и насколько я понял, его заменили на LocalizedKeywords;  А вот альтернативу StringEncoder не могу найти :( кажется его совсем удалили. На всякий случай вот код:

 

package Autotests;

import java.text.SimpleDateFormat;
import java.util.List;
import java.util.Locale;
import java.util.Properties;

import org.jbehave.core.Embeddable;
import org.jbehave.core.configuration.Configuration;
import org.jbehave.core.configuration.Keywords;
import org.jbehave.core.configuration.MostUsefulConfiguration;
import org.jbehave.core.i18n.LocalizedKeywords;
import org.jbehave.core.io.CodeLocations;
import org.jbehave.core.io.LoadFromClasspath;
import org.jbehave.core.io.StoryFinder;
import org.jbehave.core.junit.JUnitStories;
import org.jbehave.core.model.ExamplesTableFactory;
import org.jbehave.core.parsers.RegexPrefixCapturingPatternParser;
import org.jbehave.core.parsers.RegexStoryParser;
import org.jbehave.core.reporters.CrossReference;
import org.jbehave.core.reporters.StoryReporterBuilder;
import org.jbehave.core.steps.InjectableStepsFactory;
import org.jbehave.core.steps.InstanceStepsFactory;
import org.jbehave.core.steps.ParameterConverters;
import org.jbehave.core.steps.ParameterConverters.DateConverter;
import org.jbehave.core.steps.ParameterConverters.ExamplesTableConverter;
import Autotests.steps.MySteps;

import static org.jbehave.core.io.CodeLocations.codeLocationFromClass;
import static org.jbehave.core.reporters.Format.CONSOLE;
import static org.jbehave.core.reporters.Format.HTML;
import static org.jbehave.core.reporters.Format.TXT;
import static org.jbehave.core.reporters.Format.XML;

/**
 * <p>
 * {@link Embeddable} class to run multiple textual stories via JUnit.
 * </p>
 * <p>
 * Stories are specified in classpath and correspondingly the {@link LoadFromClasspath} story loader is configured.
 * </p>
 */
public class StoryRunner extends JUnitStories {
    
    public StoryRunner() {
        configuredEmbedder().embedderControls().doGenerateViewAfterStories(true).doIgnoreFailureInStories(true)
                .doIgnoreFailureInView(true).useThreads(2).useStoryTimeoutInSecs(60);
    }

    private ClassLoader classLoader;

    @Override
    public Configuration configuration() {

        Keywords keywords = new LocalizedKeywords(new Locale("ru"));

        keywords = new LocalizedKeywords (new Locale("ru", "RU"), new StringEncoder("ISO-8859-1", "ISO-8859-1"), "se/adaptiv/minesweeper/scenario/keywords", classLoader);

        Class<? extends Embeddable> embeddableClass = this.getClass();
        // Start from default ParameterConverters instance
        ParameterConverters parameterConverters = new ParameterConverters();
        // factory to allow parameter conversion and loading from external resources (used by StoryParser too)
        ExamplesTableFactory examplesTableFactory = new ExamplesTableFactory(new LocalizedKeywords(), new LoadFromClasspath(embeddableClass), parameterConverters);
        // add custom converters
        parameterConverters.addConverters(new DateConverter(new SimpleDateFormat("yyyy-MM-dd")),
                new ExamplesTableConverter(examplesTableFactory));
        return new MostUsefulConfiguration()
            .useStoryLoader(new LoadFromClasspath(embeddableClass))
            .useStoryParser(new RegexStoryParser(examplesTableFactory))
            .useStoryReporterBuilder(new StoryReporterBuilder()
                .withCodeLocation(CodeLocations.codeLocationFromClass(embeddableClass))
                .withDefaultFormats()
                .withFormats(CONSOLE, TXT, HTML, XML))
            .useParameterConverters(parameterConverters);
    }

    @Override
    public InjectableStepsFactory stepsFactory() {
        return new InstanceStepsFactory(configuration(), new MySteps());
    }

    @Override
    protected List<String> storyPaths() {
        return new StoryFinder().findPaths(codeLocationFromClass(this.getClass()), "**/*.story", "**/excluded*.story");
                
    }

}

Вот отталкиваемся вот от этого:

keywords = new LocalizedKeywords (new Locale("ru", "RU"), new StringEncoder("ISO-8859-1", "ISO-8859-1"), "se/adaptiv/minesweeper/scenario/keywords", classLoader);

3-й параметр - это путь. Он направлен на некоторый локальный каталог. Попробуйте его поменять на путь к вашему файлу.

Не находит класс StringEncoder и не предлагает сделать нужный импорт, наверно его тоже убрали, чем заменить - непонятно.