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.
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)".
As software developers, we naturally write unit tests using JUnit and so on.
However, there are the following issues.
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.
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.
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).
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.
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.
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.
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.
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.
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.
To use the HTML5 reporting feature, add a dependency on jgiven-html5-report in addition to the jgiven-core you already got.
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.
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
The report is here!
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/
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