Behaviordriven Javabased Onehundret and ten percent Efficient Readable Notation
Bjoern is a universal bdd test generater (and a person). The main focus is to generate java-classes from bdd-style text files to ensure synchronisation between the specification and the code.
The generated classes are simple and are designed to be generated each time. You should not edit the generated files because they will be deleted on every run of the generator.
The generated classes are plain Junit. You can extend them to define your own runners which makes it compatible with spring or mockito.
As a gradle plugin
you then have to configure the generator in gradle
bjoern{
folder = "${projectDir}/src/test/resources"
pckg ="de.mehtrick.bjoern-sample"
gendir = "${projectDir}/src/gen/bjoern"
}Info: You need a gradle version > 7.6.2 because there is a bug with jackson dependencies, which are needed to use this project. gradle/gradle#24390
Gradle 8 is now supported.
| Taskname | Description |
|---|---|
bjoerngen |
Generates the abstract test classes |
bjoerndoc |
Generates documentation of the bjoern files. (Default is asciidoc) |
| Parameter name | required | Description | Default value | example |
|---|---|---|---|---|
| path | yes (if the folder is not set) | The absoulte path to your specification | "${projectDir}/src/test/resources/bjoern.zgr" | |
| folder | yes (if the path is not set. If both are set folder wins) | The absoulte path to the folder where all specifications are placed | "${projectDir}/src/test/resources" | |
| pckg | yes | The package declaration of the generated classes | "de.mehtrick.bjoern-sample" | |
| gendir | yes | The folder where all of the files will be generated | "${projectDir}/src/test/gen" | |
| extendedTestClass | no | Fully qualified Name of class which all of the generated files will extend | "de.mehtrick.AbstractTestClass" | |
| docdir | no(only when generating Docs) | The folder where all the documentations will be generated | "${projectDir}/src/test/resources" | |
| template | no | Name of the freemarker Templatefile that will be loaded during generation. Default is an asciidoc template, which is part of the classpath | "/asciidoc.ftlh" | "/asciidoc.ftlh" |
| templatefolder | no | The folder where selfwritten freemarker templates for documentationgeneration can be placed | By default the internal bjoern templates will be used | "${projectDir}/src/main/resources/templates" |
| docExtension | no | The extension of the generated Doc Files. | "adoc" | "adoc" |
| junitVersion | no | The used junit-version. Possible values are 4 or 5. The value changes the used junit annotations, to secure the correct test functionality | "5" | "4" |
| encoding | no | The encoding used for the spec files. This Encoding ist not used for the generated java files. Bjoern uses java poet which only generates UTF-8 files. | "UTF-8" | "UTF-16" |
| specRecursive | no | Defines if the folder of specs should be scanned recursive or not | false | true |
| gitHistory | no | Includes the git commit history in the generated documentation. Shows date, author, and commit message for each spec file | false | true |
The specification is yaml based. Bjoern uses the .zgr file extension to determine the specification files. You will find the typical BDD keywords in it. For more convenience there is a VS-Code plugin which greatly improves the usability of the specs.
example.zgr
Feature: Test eines KassenAutomaten
Version: "1.0.0"
Reference: "[TICKET-123](https://example.com/TICKET-123)"
Background:
Given:
- Ein typ der was trinken will
Scenarios:
- Scenario: Getränk nicht vorhanden
Given:
- Ein Automat
- Mit "2" Flaschen Cola
- Mit "0" Flaschen Sprite
When:
- Kaufe "1" Sprite
Then:
- Automat sagt "alle"
- Es existieren "2" Cola im Automaten
- Scenario: Getraenk vorhanden
Given:
- Ein Automat
- Mit "2" Flaschen Cola
- Mit "0" Flaschen Sprite
When:
- Kaufe "1" Cola
Then:
- Automat sagt "ok"
- Es existieren "1" Cola im Automaten
The optional Version field specifies the version of the spec:
- In generated Java: rendered as a
@versionJavadoc tag on the abstract class. - In generated docs: rendered as
Version: <value>below the feature title.
The optional Reference field links a spec to an external ticket or resource. It accepts plain text or a Markdown link [text](url):
- In generated Java: rendered as a
@see <a href="url">text</a>Javadoc tag on the abstract class. - In generated docs: rendered as an AsciiDoc hyperlink (
link:url[text]) below the feature title.
The optional Changelog field allows you to document changes, background information, or technical rationale for the specification. It accepts arbitrary free text:
- In generated Java: rendered as a
@Changelogtag in the Javadoc of the abstract class. - In generated docs: inserted after the introduction (version/reference), only when present.
Bjoern will then generate the TestClasses based on the spec
First it will generate an abstract class which contains the test structure in form of the scenarios
package de.mehtrick.bjoern;
import java.lang.Exception;
import org.junit.Before;
import org.junit.Test;
/**
* Test eines KassenAutomaten
* @version 1.0.0
* @see <a href="https://example.com/TICKET-123">TICKET-123</a> */
public abstract class AbstractTestEinesKassenautomaten extends AbstractTestclass implements TestEinesKassenautomatenInterface {
/**
* Getränk nicht vorhanden */
@Test
public void getraenkNichtVorhanden() throws Exception {
given_EinAutomat();
given_MitFlaschenCola("2");
given_MitFlaschenSprite("0");
when_KaufeSprite("1");
then_AutomatSagt("alle");
then_EsExistierenColaImAutomaten("2");
}
/**
* Getraenk vorhanden */
@Test
public void getraenkVorhanden() throws Exception {
given_EinAutomat();
given_MitFlaschenCola("2");
given_MitFlaschenSprite("0");
when_KaufeCola("1");
then_AutomatSagt("ok");
then_EsExistierenColaImAutomaten("1");
}
@Before
public void background() throws Exception {
given_EinTypDerWasTrinkenWill();
}
}
Then bjoern will also generate Interfaces defining the test method signatures
package de.mehtrick.bjoern;
import java.lang.Exception;
import java.lang.String;
public interface TestEinesKassenautomatenInterface {
void given_EinAutomat() throws Exception;
void when_KaufeSprite(String param1) throws Exception;
void then_EsExistierenColaImAutomaten(String param1) throws Exception;
void given_EinTypDerWasTrinkenWill() throws Exception;
void given_MitFlaschenSprite(String param1) throws Exception;
void then_AutomatSagt(String param1) throws Exception;
void given_MitFlaschenCola(String param1) throws Exception;
void when_KaufeCola(String param1) throws Exception;
}= Test Foo
:toc:
Version: 1.0.0
Reference: link:https://example.com/TICKET-123[TICKET-123]
== Background
[cols="10%,90%"]
|===
|*Given* |A Foo
>|*And* |A Bar
|===
== Scenario: Foo is not happy
[cols="10%,90%"]
|===
|*Given* |there are "2" bottles of wine
>|*And* |there are "0" bottles of beer
|*When* |Foo wants to drink "1" bottle of beer
|*Then* |Foo says "why is my beer empty"
|===
== Scenario: Foo is happy
[cols="10%,90%"]
|===
|*Given* |there are "2" bottles of wine
>|*And* |there are "1" bottles of beer
|*When* |Foo wants to drink "1" bottle of beer
|*Then* |Foo says "yeah beer"
|===The Developer now has to implement the missing methods. In one feature class the methods will be reused if their name is written the same all over the specification
The parser project reads the bjoern file and parses it to java-classes using mainly jackson. It does not just convert it to pojos but reads things like parameters from the statements.
The Parse also contains a validator which helps you with the correct syntax. Keep in mind, that this might catch not all the exceptions, so you might get some jackson-mapping-exceptions as well.
Is basend on the Bjoern Parser and generates java class files from the pojos of the Bjoern Parser. This is done by using java poet. Every feature will generate a coresponding class and every scenario in that feature will become a test method. The BDD statements like Given When Then will generate abstract methods which need to be implemented by the developer.
Is basend on the Bjoern Generator and wraps its functionality into a gradle plugin. The major task is called bjoern which will generate the java classes based on your gradle-bjoern-config.
Project to share base functionality like configuration or file-filter for every generator
Generates documentations based on the bjoern files. It uses apache freemarker as template engine. As default the generator will create asciidoc files. Other formats aren't supported yet. However you can create your own freemarker templates and configure them via gradle
gradlew build