Support to write JUnit tests in BDD style.
Subpackages
Intention
You might know this problem: 10 years ago some developer wrote a sophisticated test to test some implemented feature. 10 years ago this person knew the feature very well and wrote a test with many preparation steps and perhaps with some assertions. Guess - this person might have been you.
Now, 10 years later, your product got refactored many times. The once so obvious feature is hidden somewhere or you just forgot about it. But suddenly the test fails. It might be that you just removed the feature - perhaps by intention to get rid of dead unused code. But could you tell this from the test which now fails? If you are lucky. Practice tells another story. Sometimes you glare at the test and don't understand a word. What was it meant to do? What did it test?
Joala BDD provides a solution for this using a well known language template to write tests and without the need to learn any other technology. You just need to know Java - and perhaps need a slight idea about Spring.
Approach
BDD is the acronym for Behavior Driven Development. You describe a wanted behavior. And if you do it in a formal language, the description can be used for automated tests. This is where tools like Cucumber or JBehave started. The formal language used is called Gherkin.
If you start with 3rd party tools you will need to find the one which is best supported by your IDE. Otherwise you will get stuck like many others did with a heap of unmaintainable stories you cannot refactor.
Joala BDD stays in the world of Java - and such you have full refactoring support in your IDE and can use many static code analysis tools like for example locating unused step definitions.
References
If you describe a story step by step you typically need to carry information between those steps. For example you create a HTML document in one preparation step (Given), fill in some unicode text into that document in the action step (When) and eventually you assert that the text is correctly rendered in a browser (Then).
Using methods with return values will degrade the readability of your tests and you will stumble across preparation steps preparing multiple test artifacts. References are the solution. They are used as container for the prepared objects and have advantages like providing properties for later assertions. See more in the next chapter.
Concepts/Recommendations
The following describes a set of concepts and/or recommendations. You don't need to stick to all of them but the following approach promises to work best. Mind that most steps are only done once in case you use a base class for your tests (which is recommended). Thus to create the real story files later on is most of the time a piece of cake.
@Rule public final TestWatcher testWatcher = new JUnitScenarioWatcher();
@RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration
<import resource="classpath:META-INF/joala/bdd/bdd-context.xml"/> <context:component-scan base-package="your.test.package"/>
@Inject @Singleton public Steps _;
@Test public scenario_describe_title_with_underscores() throws Exception { ... }
@Test public scenario_describe_title_with_underscores() throws Exception { _.given_there_is_a_HTML_document_D(); _.when_the_HTML_document_D_contains_unicode_text_U(); _.when_I_open_document_D_with_browser_B(); _.then_browser_B_correctly_renders_text_U(); }
@Test public scenario_describe_title_with_underscores() throws Exception { Reference<File> documentD = ref("D"); Reference<String> textU = ref("U"); Reference<WebDriver> browserB = ref("B"); _.given_there_is_a_HTML_document_D(documentD); _.when_the_HTML_document_D_contains_unicode_text_U(documentD, textU); _.when_I_open_document_D_with_browser_B(browserB); _.then_browser_B_correctly_renders_text_U(browserB, textU); }Enhanced Reference Usage: In order to provide steps which are easy to reuse you can use parametrized steps. Although it might feel somewhat uncommon the reference will be done via
$0
, $1
, $2
, ... Thus the code example from above will look
like this:
public scenario_describe_title_with_underscores() throws Exception { Reference<File> documentD = ref("D"); Reference<String> textU = ref("U"); Reference<WebDriver> browserB = ref("B"); _.given_there_is_a_HTML_document_$0(documentD); _.when_the_HTML_document_$0_contains_$1_lines_of_unicode_text_$2(documentD, 5, textU); ... }As you can see you can also use any Java types as parameters. Their
toString()
method will be
used for logging.
<?xml version="1.0" encoding="UTF-8"?> <configuration> <include resource="META-INF/joala/bdd/bdd-logback.xml"/> <root level="warn"> ... </root> </configuration>This configures the logging for BDD to be done to console. If you want to log the stories, scenarios and steps to a file appender in addition you can simply define additional loggers:
<?xml version="1.0" encoding="UTF-8"?> <configuration> <include resource="META-INF/joala/bdd/bdd-logback.xml"/> <logger name="${bdd.story.logger.name}" level="${bdd.log.level}"> <appender-ref ref="myFileAppender"/> </logger> <logger name="${bdd.steps.logger.name}" level="${bdd.log.level}"> <appender-ref ref="myFileAppender"/> </logger> <root level="warn"> ... </root> </configuration>