100% Pure Java BDD with JGiven (Introduction)

This article is the 14th day article of Java Advent Calendar 2016.

The article on the 13th day was written by tkxlab, "Easy database-Object-oriented database (JPA) even in Java SE. / items / 11bd9bd93fc0636ee8e8) ". On the 15th day, kokuzawa's "Story fitted with HttpURLConnection"is.

Introduction

First, let me briefly explain the motivation for using JGiven.

If you just want to know how to use it, skip this "Introduction" and read "[JGiven Saves](http://qiita.com/enk/items/240e56a00e104d7088d8#jgiven-%E3%81%8C%E6%" Please read from "95% 91% E3% 81% 86)".

I want to BDD

As software developers, we naturally write unit tests using JUnit and so on.

However, there are the following issues.

The scope of the test is not complete

In addition to unit tests, I also want to write functional tests. However, if you write them all in JUnit, the scope of the tests executed in ** JUnit will be different **.

It is possible to distinguish by using naming conventions and annotations, but in any case, special ingenuity is required.

Difficult to configure the test well

JUnit is written in Java, so (of course) it's up to the developer to split classes and methods. Experienced developers will be able to write ** DRY and easy-to-read tests ** by skillfully configuring test classes, methods, utility classes, etc.

But conversely, JUnit doesn't have any special mechanism to help you configure your tests in DRY for readability, and it takes some knowledge and experience to configure them well.

The expressiveness of the test report is low

JUnit uses naming conventions to represent test content. For example, xUnit Test Patterns suggests the following naming schemes:

testRequestApproval_shouldEndUpInAwaitingApproval)


 Besides, it is better to include the state to be tested and the input value.

 In any case, no matter how you devise it, it is the name of a Java method, and its expressiveness is limited.
 Also, because the framework doesn't enforce naming, it's possible (for example) to forget to write the expected behavior, or for new developers to go unnoticed by the rules and give them bad names.

 As a result, whether it's a business person, a test engineer, or even the software engineer who wrote the test (after a while), ** just reading the test report guarantees what it will do. You may end up in a situation where you don't know if you are **. [^ 1]

 [^ 1]: So software engineers value the readability of test code very much. You can read the test code to see what you are testing. But you can't expect business people or test engineers who aren't good at code to read and understand test code quickly.

### So I want to BDD

 So I introduced the BDD framework and

 * For the range one round (or more) above the unit
 * In a highly expressive way of reporting

 I want to write a test.

## With 100% Pure Java

 However, many BDD frameworks require you to learn and maintain your own notation for describing behavior.

 BDD frameworks in Java include [JBehave](http://jbehave.org) and [Cucumber-JVM](https://cucumber.io/docs/reference/jvm), but the behavior description itself is It must be done in plain text and associated with Java code with annotations. [^ 2]

 [^ 2]: Another is Groovy's BDD framework called [Spock](http://spockframework.org). (Reference: [Apply Spock to Java unit tests](http://qiita.com/euno7/items/1e834d3d58da3e659f92)) Since it is Groovy, it works on the JVM and seems to be quite expressive, but Java In many cases, including the Groovy framework (albeit test code) in a product can be a daunting task.

 This method has the following drawbacks:

 * It is troublesome to remember the annotation that associates the behavior description with the Java code.
 * More description when writing equivalent tests than JUnit (written in Java only)
 * The refactoring function of the IDE does not work for the original notation part, and it is troublesome to change the name etc.

 If possible, I want to write only in Java ....

# JGiven saves

 So JGiven!

## What is JGiven

 What is JGiven? Quoted (translated) from [Official Site](http://jgiven.org).

 > JGiven is a developer-friendly and practical Java BDD tool.
 > Developers write scenarios in Java (only) using a fluent, domain-specific API.
 > Domain experts can read reports generated by JGiven.

 Yes, you can write in Java only![^ 3]

 [^ 3]: There is a drawback that domain experts who cannot write Java cannot write scenarios directly, but it can be solved by writing in pairs with the developer. Alternatively, the domain expert could write it in any notation (which fits the JGiven framework) and the developer could translate it into Java code. Again, the cost is comparable to traditional BDD frameworks that require annotations, but not higher. Once in Java code, you are free to refactor with the IDE.

 Of course, there are also easy-to-read reports.

 JGiven enables ** 100% Pure Java BDD **.

## Various resources

 Here are various links related to JGiven.

 * Official site: http://jgiven.org
* GitHub : https://github.com/TNG/JGiven
 * Lecture video by the developer
 * Long version from the basics of BDD: https://www.youtube.com/watch?v=gh_yjb3x8Yc
 * Short version with a focus on the points: https://www.youtube.com/watch?v=x-6bT_0dTWI
 * Live coding (but hard to see ...): https://www.youtube.com/watch?v=4oFl4nxoshM

 Development on GitHub is [active](https://github.com/TNG/JGiven/commits/master), and dissemination activities are being actively carried out [^ 4], and although it is still a minor framework, it is favorable. Can have.

 [^ 4]: I also had a session on JavaOne in 2016 (slide: https://janschaefer.github.io/jgiven-slides-javaone-2016/#/)

# How to use

 You can find out how to use it by looking at the user guide.

http://jgiven.org/userguide/

 That's not enough, so I will explain it step by step.

## Basics

 Let's move it first.

### Dependencies

 jgiven-core works with JUnit or TestNG.

 With the latest JGiven 0.12.1 as of 12/14/2016, JUnit requires 4.9 or higher (4.11 or higher is recommended).

 * JUnit Maven / Gradle Dependency: http://jgiven.org/userguide/#_junit
 * TestNG Maven / Gradle Dependency: http://jgiven.org/userguide/#_testng

### Make the body

 If you can resolve the dependency, write it immediately.
 The following examples are explained by JUnit.

 First, create the body of the test class.


#### **`MyShinyJGivenTest.java`**
```java

import com.tngtech.jgiven.junit.ScenarioTest;

public class MyShinyJGivenTest
        extends ScenarioTest<GivenSomeState, WhenSomeAction, ThenSomeOutcome> {
}

It's easy.

JGiven's test (scenario) class inherits from a class called ScenarioTest. ScenarioTest takes three type parameters. Each corresponds to three typical BDD steps (Given, When, Then).

Make a stage

Well, at this point, MyShinyJGivenTest's GivenSomeState, WhenSomeAction, and ThenSomeOutcome don't exist yet. Let's make it.

GivenSomeState.java


import com.tngtech.jgiven.Stage;

public class GivenSomeState extends Stage<GivenSomeState> {
public GivenSomeState When in a certain state() {
        return self();
    }
}

WhenSomeAction.java


import com.tngtech.jgiven.Stage;

public class WhenSomeAction extends Stage<WhenSomeAction> {
public WhenSomeAction If you do something() {
        return self();
    }
}

ThenSomeOutcome.java


import com.tngtech.jgiven.Stage;

public class ThenSomeOutcome extends Stage<ThenSomeOutcome> {
public ThenSomeOutcome Something happens() {
        return self();
    }
}

Since it's a big deal, I tried to change the method name to Japanese. [^ 5]

[^ 5]: I think there are pros and cons to using Japanese for the test code. At Apresso, to which I belong, Japanese is used for the method name of the test, and the test can be written and utilized fairly efficiently in terms of both descriptiveness and readability. I will. However, the situation may change again if developers who cannot read Japanese participate in product development in the future.

Add and run a scenario

I'm ready. Let's add a scenario and run it.

MyShinyJGivenTest.java


import org.junit.Test;
import com.tngtech.jgiven.junit.ScenarioTest;

public class MyShinyJGivenTest
        extends ScenarioTest<GivenSomeState, WhenSomeAction, ThenSomeOutcome> {

    @Test
public void something happens() {
        given().In a certain state();
        when().If you do something();
        then().Something happens();
    }
}

Add the scenario as a familiar JUnit / TestNG test method and write it in this notation.

From the IDE

First, let's run it from IntelliJ IDEA, which I usually use.

The framework is JUnit, so you can run it as a JUnit test as you normally would. Of course, the same is true for Eclipse and NetBeans.

The result is output to the console.

image

When I gave the scenarios and steps a sloppy name, it unexpectedly looked like the lyrics of J-POP in the 90's, but it was a success anyway.

From the command line

Of course, you can also run it from the command line.

$ mvn test

Considering that you want to automate the output of the report, this may be the main usage.

Report in HTML5

When you run the JGiven scenario, two types of reports are output by default.

The report to the console has already been seen.

Reports to the JSON file are stored in the jgiven-reports / json directory. Here's a quick way to find out where this directory is in your runtime environment. [^ 6]

System.out.println(com.tngtech.jgiven.impl.Config.config().getReportDir().get().getAbsolutePath());

[^ 6]: Reference: https://github.com/TNG/JGiven/blob/8225c0bfc0f8d7e712c2d2aa58a7db24d72a70b5/jgiven-core/src/main/java/com/tngtech/jgiven/impl/Config.java#L30

Well, it's nice to have a report in JSON, but it's hard to read JSON. Of course, there is a way to convert it to HTML.

Dependencies

To use the HTML5 reporting feature, add a dependency on jgiven-html5-report in addition to the jgiven-core you already got.

Execution method

From the command line

The method to execute from the command line is as follows.

java com.tngtech.jgiven.report.ReportGenerator \
  --format=html \
  [--sourceDir=<Directory with JSON reports>] \
  [--targetDir=<The directory where you want to output the HTML5 report>] \

It is assumed that jgiven-core and its dependent modules, jgiven-html5-report, are in the classpath. (Use the `` `-cpoption if necessary)--sourcedir/--targetdir```If is not specified, it will be the current directory.

from maven / gradle

The user guide also shows how to define it as a goal / task for maven or gradle. Please refer to it if necessary.

http://jgiven.org/userguide/#_html_report

result

The report is here!

image

You can see that there are many functions such as summary display, success / failure / pending classification, tag / class classification, search, and printing.

A test report of JGiven itself is also provided as a sample.

http://jgiven.org/jgiven-report/html5/

Summary

Notice

So far, we have introduced JGiven, but we haven't described the essential test target classes and assertions, so we can't say that we have been able to utilize it yet. In the next few days, we will publish "100% Pure Java BDD (Practice) with JGiven".

Recommended Posts

100% Pure Java BDD with JGiven (Introduction)
Server processing with Java (Introduction part.1)
[Java] Introduction
Introduction to algorithms with java --Search (depth-first search)
Introduction to algorithms with java --Search (breadth-first search)
[Java] Introduction to Java
Introduction to java
Introduction to algorithms with java --Search (bit full search)
Java Performance Chapter 1 Introduction
Install java with Homebrew
Change seats with java
Install Java with Ansible
Comfortable download with JAVA
Switch java with direnv
Download Java with Ansible
Let's scrape with Java! !!
Introduction to java command
Build Java with Wercker
Endian conversion with JAVA
Java multi-project creation with Gradle
Getting Started with Java Collection
Basic Authentication with Java 11 HttpClient
Let's experiment with Java inlining
Run batch with docker-compose with Java batch
[Template] MySQL connection with Java
Rewrite Java try-catch with Optional
Install Java 7 with Homebrew (cask)
[Java] JSON communication with jackson
Java to play with Function
Try DB connection with Java
Enable Java EE with NetBeans 9
[Java] JavaConfig with Static InnerClass
Try gRPC with Java, Maven
Let's operate Excel with Java! !!
Version control Java with SDKMAN
RSA encryption / decryption with java 8
Paging PDF with Java + PDFBox.jar
Sort strings functionally with java
Object-oriented (java) with Strike Gundam
[Java] Introduction to lambda expressions
[Java] Content acquisition with HttpCliient
Java version control with jenv
Troubleshooting with Java Flight Recorder
Streamline Java testing with Spock
Connect to DB with Java
Connect to MySQL 8 with Java
Error when playing with java
Using Mapper with Java (Spring)
Java study memo 2 with Progate
Understanding Java Concurrent Processing (Introduction)
Getting Started with Java Basics
[Java] Introduction to Stream API
Easy library introduction with Maven!
Seasonal display with Java switch
Use SpatiaLite with Java / JDBC
Study Java with Progate Note 1
Compare Java 8 Optional with Swift
[Introduction] Build MVC with Scala
HTML parsing with JAVA (scraping)
Run Java VM with WebAssembly
Screen transition with swing, java