ClaudiaR
ClaudiaR

Reputation: 3414

AssertJ-Swing and Junit 5 support

I'm currently working at a Java application that I'm testing using JUnit Jupiter. I am starting to work at the GUI and I was wondering if it was possible to use AssertJ-Swing with JUnit 5. As a matter of fact I have found an open issue on AssertJ-Swing GitHub page.

The suggestion they give is to define a GUITestExtension like so:

import org.assertj.swing.junit.runner.ImageFolderCreator;
import org.junit.jupiter.api.extension.Extension;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.InvocationInterceptor;
import org.junit.jupiter.api.extension.ReflectiveInvocationContext;

import java.lang.reflect.Method;

import static org.assertj.swing.annotation.GUITestFinder.isGUITest;
import static org.assertj.swing.junit.runner.Formatter.testNameFrom;

/**
 * Understands a JUnit 5 extension that takes a screenshot of a failed GUI test.
 * The Junit 4 runner is available in {@link org.assertj.swing.junit.runner.GUITestRunner}.
 *
 * @see <a href="https://github.com/assertj/assertj-swing/issues/259">assertj-swing #259</a>
 * @author William Bakker
 */
public class GUITestExtension implements Extension, InvocationInterceptor {
    private final FailureScreenshotTaker screenshotTaker;

    public GUITestExtension() {
        screenshotTaker = new FailureScreenshotTaker(new ImageFolderCreator().createImageFolder());
    }

    @Override
    public void interceptTestMethod(
            Invocation<Void> invocation,
            ReflectiveInvocationContext<Method> invocationContext,
            ExtensionContext extensionContext) 
            throws Throwable {
        try {
            invocation.proceed();
        } catch (Throwable t) {
            takeScreenshot(invocationContext.getExecutable());
            throw t;
        }
    }

    private void takeScreenshot(Method method) {
        final Class<?> testClass = method.getDeclaringClass();
        if (!(isGUITest(testClass, method)))
            return;
        screenshotTaker.saveScreenshot(testNameFrom(testClass, method));
    }
}

I am a bit familiar with the GUITestRunner that can be used with JUnit 4, but I have no idea on how to replace it with this.

Note: Usually GUITestRunner is used like so with JUnit 4:

import org.assertj.swing.junit.runner.GUITestRunner; 
import org.assertj.swing.junit.testcase.AssertJSwingJUnitTestCase;
import org.junit.runner.RunWith;
import org.assertj.swing.edt.GuiActionRunner; 
import org.assertj.swing.fixture.FrameFixture;

@RunWith(GUITestRunner.class) 
public class WelcomeSwingViewTest extends AssertJSwingJUnitTestCase{
    private FrameFixture window;
    private WelcomeSwingView welcomeSwingView;
    @Override
    protected void onSetUp() { 
        GuiActionRunner.execute(() -> {
         welcomeSwingView = new WelcomeSwingView();
         return welcomeSwingView; 
        });
        window = new FrameFixture(robot(), welcomeSwingView);
        window.show(); 
    }
}

Any help is appreciated.

Upvotes: 2

Views: 931

Answers (2)

ClaudiaR
ClaudiaR

Reputation: 3414

I changed my test class according to Stefano's answer, and now everything is working. In case anyone needs it my test class code is something like this:

import org.assertj.swing.core.matcher.JLabelMatcher;
import org.assertj.swing.edt.GuiActionRunner;
import org.assertj.swing.fixture.FrameFixture;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.assertj.swing.annotation.GUITest;

@ExtendWith(GUITestExtension.class)
class WelcomeSwingViewTest  {

    private FrameFixture window;
    private WelcomeSwingView welcomeSwingView;
    
    @BeforeAll
    static void setUpOnce() {
        FailOnThreadViolationRepaintManager.install();
    }

    @BeforeEach
    void setup() {

        GuiActionRunner.execute(() -> {
            welcomeSwingView = new WelcomeSwingView();
            return welcomeSwingView;
        });
        window = new FrameFixture(welcomeSwingView);
        window.show();
    }

    @AfterEach
    void clean() {
        window.cleanUp();
    }

    @Test @GUITest
    void testControlsInitialStates() {
        window.label(JLabelMatcher.withText("label"));
    }
}

Of course you also have to import the GUITestExtension (defined as in my question) to your test class. Also the test is successful because in my view I have a label with text "label".

Upvotes: 2

Stefano Cordio
Stefano Cordio

Reputation: 2257

Assuming that the GUITestExtension mentioned in the issue is defined in your codebase, it could be registered in the following way:

@Test
@ExtendWith(GUITestExtension.class)
void test() {
    ...
}

More can be found in the extension model section of the JUnit 5 documentation.

Ideally, the extension should come directly from AssertJ Swing, but the project lead has no longer time for it, unfortunately, therefore we are looking for committers.

If anyone is interested, feel free to get in touch on GitHub.

Upvotes: 1

Related Questions