Writing Stories in your language

Good and effective communication is key to BDD. Therefore, writing stories in the language spoken by the business users is essential. And even though the patterns used to match the scenario steps to Java methods can be written in any language, the Keywords still need to be expressed in different languages.

JBehave by default supports English as the scenario language. By supporting the internationalisation (i18n) of keywords by Java Locale, it also allows the stories to be written in any language. All is needed to configure the use of LocalizedKeywords for a given Locale. Each locale has a separate keywords properties file. E.g. for Italian locale, the file keywords_it.properties is:

Narrative=Narrativa:
InOrderTo=Per ottenere
AsA=Come
IWantTo=Voglio
Scenario=Scenario:
GivenStories=Date le storie:
ExamplesTable=Esempi:
ExamplesTableRow=Esempio:
ExamplesTableSeparator=|
Given=Dato che
When=Quando
Then=Allora
And=E
Pending=PENDENTE
NotPerformed=NON ESEGUITO
Failed=FALLITO

We need to configure the use of the i18n-ed keywords in the JUnitStory, e.g.:

public class ItTraderStory extends JUnitStory {

	public ItTraderStory() {
        StoryConfiguration storyConfiguration = new MostUsefulStoryConfiguration();
        storyConfiguration.useStoryPathResolver(new UnderscoredCamelCaseResolver(".story"));
        ClassLoader classLoader = this.getClass().getClassLoader();
        // use Italian for keywords
        Keywords keywords = new LocalizedKeywords(new Locale("it"), new StringEncoder(), "org/jbehave/examples/trader/i18n/keywords", classLoader);
        storyConfiguration.useKeywords(keywords);
        storyConfiguration.useStoryPatter(new RegexStoryParser(storyConfiguration.keywords());
        storyConfiguration.useStoryReporter(new PrintStreamOutput(storyConfiguration.keywords()));
        useConfiguration(storyConfiguration);

        StepsConfiguration stepsConfiguration = new MostUsefulStepsConfiguration();
        // use Italian for keywords
        stepsConfiguration.useKeywords(keywords);
        addSteps(new StepsFactory(stepsConfiguration).createCandidateSteps(new ItTraderSteps()));
    }
}

The corresponding i18n-ed Steps will then understand the language that has been configured via the i18n-ed keywords:

public class ItTraderSteps {

    private Stock stock;
    private ExamplesTable table;

    @Given("ho un'azione con simbolo $symbol e una soglia di $threshold")
    public void aStock(@Named("symbol") String symbol, @Named("threshold") double threshold) {
        stock = new Stock(symbol, threshold);
    }

    @When("l'azione e' scambiata al prezzo di $price")
    public void stockIsTraded(@Named("price") double price) {
        stock.tradeAt(price);
    }

    @Then("lo status di allerta e' $status")
    public void alertStatusIs(@Named("status") String status) {
        ensureThat(stock.getStatus().name(), equalTo(status));
    }

    @Given("ho una tabella $table")
    public void aTAble(ExamplesTable table) {
        this.table = table;
    }

    @Then("la tabella ha $rows righe")
    public void hasRows(int rows){
        ensureThat(table.getRowCount(), equalTo(rows));
    }
}

Note that the i18n-ed keywords not only allow the translation of the keywords used in parsing the textual story, but also the keywords used in the reporting of the story execution, e.g. Pending, NotPerformed and Failed.

Why are different languages not supported out-of-the-box?

Most non-English languages require characters that are rendered inconsistently using the native encoding of a given operating system. At moment, a consistent solution is to provide your own keywords in your native encoding. We are working on a solution that is re-usable across multiple platforms.