8000 GitHub - imagineDevit/giwt at 0.1.4
[go: up one dir, main page]
More Web Proxy on the site http://driver.im/
Skip to content

imagineDevit/giwt

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

33 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸ§ͺGIWT


minimum java version javadoc Maven Central GitHub build maven test GitHub issues GitHub contributors

GIWT is a java test library based on JUnit platform. It gives developers the ability to write unit tests in the GWT (Given-When-Then) format.

This is a simple usage example πŸ‘‡

import io.github.imagineDevit.giwt.annotations.Test;

class MyTest {

    @Test("1 + 1 should be 2")
    void test(TestCase<Integer, Integer> testCase) {
        testCase
                .given("state is 1", 1)
                .when("1 is added to the state", i -> i + 1)
                .then("the result should be equal to 2", result -> result.shouldBe().equalTo(2));
    }
}

πŸ“­ TestCase

As seen in the example above, the test method takes a TestCase<T,R> as a parameter.

⚠️ It is a particularity of GIWT : ️ all test methods should have at least one parameter of type TestCase<T,R>.

TestCase is a generic Object that takes two types as parameters : T and R.

T represent the type of the state of the test. It can be any type. Use Void if you don't need a state.

R represent the type of the result of the test. It can be any type. Use Void if you don't need a result.

TestCase and its linked statements (GivenStmt<T,R>, WhenStmt<T,R> and ThenStmt<T,R> ) come with a set of methods that can be chained to write the test in the GWT format.

Each method takes a string first parameter representing the statement description.

βš™οΈ Statement methods

  • given()

    This method sets the initial state of the test. It returns a GivenStmt<T,R> object.

  • when()

    This method represents the action to be tested. It returns a WhenStmt<T,R> object.

  • then()

    This method allows the verification of the result of the test. It returns a ThenStmt<T,R> object.

  • and()

    GivenStmt<T,R> and ThenStmt<T,R> classes have an and() method that allows to chain multiple statements of the same type.

⏳ State

When it comes to testing a method, the test state is represented by the method parameters.

Thus, can we represent the state of a method test as an object of type T when the method has a single parameter otherwise as a List<Object>.

Managing a List<Object> as test state is possible but may not be very conformable.

This is why GIWT introduces @GiwtProxyable annotation.

@GiwtProxyable annotation has a processor that generate a proxy class for each annotated class and a parameters record for each public method with more than one parameter.

This parameters record contains all parameters of the given method.

The proxy class has a one parameter proxy methods for each original class public method.

Let's see an example

Consider the following class πŸ‘‡

package io.example.helpers;

import io.github.imagineDevit.giwt.annotations.GiwtProxyable;

@GiwtProxyable
public class StringHelper {

    public String repeat(String text, int times, String separator) {
        return String.repeat(separator + times).replaceFirst(separator, "");
    }
}

After compiling your project, the following proxy class should be generated πŸ‘‡:
package io.example.helpers;

public class StringHelperTestProxy {
    
    private final StringHelper delegate;
    
    public StringUtilsTestProxy(StringHelper delegate) {
        this.delegate = delegate;
    }
    
    record RepeatParams(String text, int times, String separator) {}
  
    public String repeat(RepeatParams param) {
        return this.delegate.repeat(param.text(), param.times(), param.separator());
    }
}

As seen above, the generated record name is the name of the method suffixed with Params.

What if we have method overloading (several methods with the same name and different parameters) in our class?

🧨️ Compilation will fail !!!!️

To solve the problem, annotate the overloaded method with @ParameterRecordName and specify the name of the record.

import io.github.imagineDevit.giwt.annotations.ParameterRecordName;

@ParameterRecordName("justRepeat")
public String repeat(String text, int times) {
    return String.repeat(times);
}

The generated proxy class can then be used for testing as follows:

import io.github.imagineDevit.giwt.TestCase;
import io.github.imagineDevit.giwt.annotations.Test;

import static io.example.helpers.StringHelperTestProxy.*;

class StringHelperTest {

    private StringHelperTestProxy proxy = new StringHelperTestProxy(new StringHelper());

    @Test
    public void repeat(TestCase<RepeatParams, String> testCase) {
        testCase
                .given("a param", new RepeatParams("A", 3, "_"))
                .when("repeat is called", proxy::repeat)
                .then("the result should be A_A_A", result -> result.shouldBe().equalTo("A_A_A"));
    }

    @Test("just repeat A 3 times should give AAA")
    public void justRepeat(TestCase<JustRepeatParams, String> testCase) {
        testCase
                .given("a param", new JustRepeatParams("A", 3))
                .when("repeat is called", proxy::repeat)
                .then("the result should be AAA", result -> result.shouldBe().equalTo("AAA"));
    }
}

πŸ“¬ TestCase with context

In some cases, it is necessary to store variables other than the state and the result of the test. In this case a testCase can be converted into a TestCaseWithContext<T,R> by calling the withContext() method.

TestCaseWithContext<T,R> offers some methods :

  • to store state : setState(T state)
  • to transform state: mapState(Function<T,T> mapper)
  • to map state into result : stateToResult(Function<T,R> mapper)
  • to store a context variable : setVar(String key, Object value)
  • to get a context variable : getVar(String key)

This is a simple usage example πŸ‘‡

 class MyTest {
    
    @Test("1 + 1 should be 2")
    void test(TestCase<Integer, Integer> testCase) {
        testCase.withContext()
                .given("the state is set to 1", ctx -> ctx.setState(1))
                .when("result is set to state + 1", ctx -> ctx.stateToResult(state -> state + 1))
                .then("the result should be 2", (ctx, result) ->
                        result.shouldBe()
                                .notNull()
                                .equalTo(2)
                );
    }
}

πŸ“Œ Annotations

GIWT provides a set of annotations that can be used to configure the test classes and methods.

  • @Test

    GIWT provide a custom annotation @Test that can take a string as a parameter representing the test name.

    If no parameter is provided, the test name will be the method name.

  • @ParameterizedTest

    This annotation marks a test method as parameterized. It can take two parameters :

    • name : the test name. If not provided, the test name will be the method name.

    • source : the parameter source. Parameter source can be :

      • a method annotated @ParameterSource that returns a TestParameters object. (The source is the @ParameterSource value))
      • a entry of the Map<String, TestParameters> returned by the test configuration class (The source is the entry key)

    A parameterized test method must have all paremeters as arguments. The order of the parameters must be the same as the order of the parameters in the TestParameters object.

    class MyTest {
    
        @ParameterizedTest(
                name = "Length of {0} should be equal to {1}",
                source = "getParams"
        )
        void test2(TestCase<String, Integer> testCase, String text, Integer expectedResult) {
            testCase
                    .given("state is %s".formatted(text), () -> text)
                    .when("state length is evaluated", i -> i.length())
                    .then("the result should be %d".formatted(expectedResult), result ->
                            result
                                    .shouldBe()
                                    .equalTo(expectedResult)
                    );
        }

        @ParameterSource("getParams")
        private TestParameters<TestParameters.Parameter.P2<Integer, Integer>> getParams() {
            return TestParameters.of(
                    TestParameters.Parameter.P2.of("Hello", 5),
                    TestParameters.Parameter.P2.of("Bonjour", 7),
                    TestParameters.Parameter.P2.of("Good morning", 12)
            );
        }
    }

⚠️ Please note that test parameters can be incorporated in the test name. The value of the parameter is denoted by placing its index within curly brackets πŸ‘‰ Length of {0} should be equal to {1}

  • @Skipped

    This annotation marks a test method as skipped.

  • @ParameterSource

    This annotation marks a method as a parameter source for a parameterized test method. It can take a string as a parameter representing the parameter source name. If no parameter is provided, the parameter source name will be the method name.

  • @BeforeEach

    This annotation marks a method as a before each method. It will be executed before each test method.

  • @AfterEach

    This annotation marks a method as a after each method. It will be executed after each test method.

  • @BeforeAll

    This annotation marks a method as a before all method. It will be executed before all test methods.

  • @AfterAll

    This annotation marks a method as a after all method. It will be executed after all test methods.

  • @ExtendWith

    This annotation registers a list of callbacks for a test class. It can take a list of classes as a parameter. These classes must implement the BeforeEachCallback, BeforeAllCallback,
    AfterEachCallback and/or AfterAllCallback interfaces.

  • @ConfigureWith

    This annotation registers a class as the test class configuration. It take a class that must implement TestConfiguration as parameter


πŸ“‘ Report generation

GIWT provides a report generation feature. This feature is disabled by default.

To enable it, you must add a new environment variable giwt.generate.report = true.

The report file report.html is generated and stored in the target/giwt directory.

About

A Junit platform test library

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Contributors 2

  •  
  •  
0