[JAVA] Automatically test with Gauge

Overview

My name is @SatohJohn and I am in charge of the third day of the Java Advent Calendar. This time, I will write the settings for writing automated tests using Gauge. Apparently, it's a little the same as announced at JJUG, but I'm sorry. I would like to summarize the details in a sentence.

What is Gauge

https://getgauge.io/index.html A tool that allows you to write automated tests in markdown.

merit

Demerit

Preparation

Install Gauge https://getgauge.io/get-started.html On mac you can install it with brew.

Constitution

Create a maven project as follows. (tree command convenient!

.
├── driver
│   ├── chromedriver_linux
│   ├── chromedriver_mac
│   └── chromedriver_windows.exe
├── env
│   └── default
│       ├── default.properties
│       └── java.properties
├── manifest.json
├── pom.xml
├── specs
│   └── test.spec
└── src
    └── test
        └── java
            ├── StepImplementation.java
            └── VerifyImplementation.java

The driver is included because chrome is used in selenium this time. manifest.json describes the implementation format and Gauge plugin information.

manifest.json


{
  "Language": "java",
  "Plugins": [
    "spectacle"
  ]
}

Put the settings in env. There are other parameters, but I think this is what you actually use.

default.properties


#Directory to put the execution result
gauge_reports_dir = reports
#Whether to update the implementation results
overwrite_reports = true
#Do you want to take a screenshot if it fails
screenshot_on_failure = true
#Implementation details log
logs_directory = logs

java.properties


#Parameters to pass to the JVM
gauge_jvm_args = -Dselenide.browser=chrome
#Level of state initialization(See below)
gauge_clear_state_level = scenario

pom.xml looks like this:

pom.xml


<dependencies>
    <dependency>
        <groupId>com.thoughtworks.gauge</groupId>
        <artifactId>gauge-java</artifactId>
        <version>0.6.5</version>
        <scope>test</scope>
        <exclusions>
            <exclusion>
                <groupId>com.google.guava</groupId>
                <artifactId>guava</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>junit</groupId>
        <artifactId>junit</artifactId>
        <version>4.12</version>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.codeborne</groupId>
        <artifactId>selenide</artifactId>
        <version>4.8</version>
        <scope>test</scope>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.1</version>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
                <encoding>UTF-8</encoding>
            </configuration>
        </plugin>
        <plugin>
            <groupId>com.thoughtworks.gauge.maven</groupId>
            <artifactId>gauge-maven-plugin</artifactId>
            <version>1.3.0</version>
            <executions>
                <execution>
                    <phase>test</phase>
                    <configuration>
                        <specsDir>specs</specsDir> <!--Spec directory to run-->
                    </configuration>
                    <goals>
                        <goal>execute</goal>
                    </goals>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>

Please change the version of guava. Otherwise, it will conflict with the selenide library before execution and you will get the following exception.

Failed: Before Suite
Message: java.lang.NoSuchMethodError: com.google.common.util.concurrent.SimpleTimeLimiter.create(Ljava/util/concurrent/ExecutorService;)Lcom/google/common/util/concurrent/SimpleTimeLimiter;

The directory where specs puts markdown. java in test is an implementation of markdown. The writing method is as follows.

How to write

Basically, I think the flow of writing an automated test is as follows.

  1. Implement the method with @ Step
  2. Call that method from the spec file
  3. If similar steps appear, summarize them

1. Implement the method with @ Step

To implement the part to be executed, create an appropriate class as shown below and add @ Step to the method. At this time, decide the name when it is called from the spec file. [1]

StepImplementation.java


import com.codeborne.selenide.Selenide;
import com.thoughtworks.gauge.Step;

public class StepImplementation {
    @Step("<url>open") //[1]
    public void open(String url/*[2]*/) {
        Selenide.open(url); //[3]
    }
}

The represents a variable, but it doesn't matter if it doesn't match the argument name. (Is it easier to see if they match) [2] If there is an implementation with the same name "Open" Variable "", it will not be tested as "Duplicate step implementation". Be careful when writing Steps in multiple classes. This test uses Selenide to open the variable page. [3] The same is true for Verify.

VerifyImplementation.java


import com.codeborne.selenide.Selenide;
import com.thoughtworks.gauge.Step;
import org.hamcrest.CoreMatchers;
import org.junit.Assert;

public class VerifyImplementation {
    @Step("The title is<title>To be")
    public void verifyTitle(String title) {
        String actual = Selenide.title();
        Assert.assertThat(actual, CoreMatchers.is(title));
    }
}

In this example, Selenide gets the title of the page and compares it with the argument.

2. Call that method from the spec file

test.spec


test[4]
====================

##Open the JJUG page[5]
[6]
* "http://www.java-users.jp/ccc2017fall/"open
*The title is"JJUG CCC 2017 Fall"To be

[4] Will be the overall specification of this file. You can execute the scenario of the same file at the time of execution. [5] It will be the name of the test case (scenario). [6] \ * is the content (step) of the test to be performed. The implementation written in Java earlier is called. "The contents are passed as an argument. You can also write with <>. You can pass local files and tables as well as simple characters. If you write the text without writing \ # etc., it will be treated as a comment. (I really wanted to write [6] on the * line

See https://docs.getgauge.io/longstart.html for a detailed description method.

3. If similar steps appear, summarize them

The summary is called a concept. Write the concept in a .cpt file.

test.cpt


#test
* "http://www.java-users.jp/ccc2017fall/"open

If you write as above, you can rewrite test.spec as follows

test.spec


test
====================

##Open the JJUG page
*test
*The title is"JJUG CCC 2017 Fall"To be

Processing before test execution

With @BeforeSuite, you can change your browser settings before performing the automated test.

public class BeforeStepImplementation {
    @BeforeSuite
    public void beforeSuite() {
        ChromeOptions options = new ChromeOptions();
        if (SystemUtils.IS_OS_MAC) {
            System.setProperty("webdriver.chrome.driver", "./driver/chromedriver_mac");
        } else if (SystemUtils.IS_OS_WINDOWS) {
            System.setProperty("webdriver.chrome.driver", "./driver/chromedriver_windows.exe");
        } else if (SystemUtils.IS_OS_LINUX) {
            System.setProperty("webdriver.chrome.driver", "./driver/chromedriver_linux");
        }
        options.addArguments("--no-experiments",
                "--disable-translate",
                "--disable-plugins",
                "--disable-extensions",
                "--no-default-browser-check",
                "--clear-token-service",
                "--disable-default-apps",
                "--enable-logging",
                "--headless", "--disable-gpu", //If you have these two, it will be headless execution
                "test-type");
        ChromeDriver chromeDriver = new ChromeDriver(options);
        WebDriverRunner.setWebDriver(chromeDriver);
    }
}

Besides, there are @BeforeSpec, @BeforeScenario, @BeforeStep, and After of each timing, so it is possible to initialize at each timing.

Run automated tests from maven

I have a plugin, so I just run mvn test. The result will be as follows.

#test
  ##Open the JJUG page ✔ ✔

Specifications: 1 executed      1 passed        0 failed        0 skipped
Scenarios:      1 executed      1 passed        0 failed        0 skipped

Total time taken: 5.535s
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 15.036 s
[INFO] Finished at: 2017-12-02T22:17:39+09:00
[INFO] Final Memory: 11M/159M
[INFO] ------------------------------------------------------------------------

Summary

Introduced the automated test tool Gauge. I like the fact that it can be described in markup. Also, it is easy to review because it is markdown. Let's write an automated test! By the way, this demo is posted on github, so please try it! https://github.com/furyu-john/gauge-sample

Recommended Posts

Automatically test with Gauge
Integration Test with Gradle
Test Nokogiri with Rspec.
Load test with JMeter
Unit test with Junit.
Test Active Strage with RSpec
Test GraphQL resolver with rspec
test
REST API test with REST Assured Part 2
test
Automatically scroll the background with libGDX
test
test
[Java] Test private methods with JUnit
Copy and paste test with RSpec
Test list inclusion relationships with AssertJ
Test Spring framework controller with Junit
Let's unit test with [rails] Rspec!
With EqualsVerifier, the equals () test was instant
Control test order in Junit4 with enumeration
Java EE test (CDI / interceptor) with Arquillian
Perform transaction confirmation test with Spring Boot
[Ruby on Rails] Controller test with RSpec
[Ruby on Rails] Model test with RSpec
How to test private scope with JUnit
JUnit 5 gradle test fails with lombok annotation
rails test fails with database reference error
Java automated test implementation with JUnit 5 + Gradle
Form class validation test with Spring Boot