Bye bye JUnit 4, hello WebDriver 3.6.0 and some firsts.

Bye bye JUnit 4, hello WebDriver 3.6.0 and some firsts.

A lot has happened this week!

So although I have completed the code changes and committed already. I don’t think I will get it all explained in this post. Probably a multi part post for you this week.

So I was wrong!

JUnit 5 can be used to do everything I want as of now so it is finally time to get rid of my JUnit4 compatibility. If you recall I was hanging on to it as I could not configure things to be able to run a single test from Intellij IDEA or to report the results graphically. I had read a few articles going back some way showing JUnit5 tests running properly so what was I doing wrong? The answer it seems was in the settings

How to get it right!
Working JUnit5 Runner Configuration

Setting the Gradle Runner to Platform Test Runner seems to have done the trick.

JUnit5 reporting in Intellij IDEA
It works! Clickable Stack Trace and all.

That then triggered my first set of changes. Its not perfect – (tests run from the gradle task don’t visually report in the IDE) but I can develop with visual prompts in the IDE, and when I want to run the suite I just set it off and check the final report. Good enough to clear out the last vestiges of JUnit4 (including the random assume I had in there!)

 

Some firsts this week:

My first bug report

I filed my first Selenium bug report complete with test demonstration, a couple of weeks ago that I discovered whilst trying to get my work running on IE11. Sadly it turns out I was not the first to report it, (Sorry guys!) but I was told that the fix would be in the 3.6.0 release. I was therefore thrilled to see it released earlier this week.

I also have started to get more people finding their way here courtesy of Google. Welcome if you are one of my visitors. I hope you find this helpful.

There were also some API Changes (notably the preferred constructor for a WebDriver is now using options rather than capabilities.) This got me trying to work out how WebDriverServices worked with it. This soon led to the realisation that really what I was looking for was using a RemoteWebDriver, so of course I had to have a go at setting up my own grid too.

Changes this week

I won’t post them all here, but as described above, I was excited to finally get rid of the JUnit4 legacy support. That means:

  • Removing JUnit4 annotations
  • Adding DisplayNames
  • Making test methods package-protected
  • Converting my JUnit4 Assume
  • To reuse the WebdriverService this also allowed me to switch my default AbstractTest to using
    @TestInstance(TestInstance.Lifecycle.PER_CLASS)

So my (JUnit5 only) build.gradle becomes

group 'tech.alexontest'
version '1.0-SNAPSHOT'

buildscript {
    repositories {
        mavenCentral()
    }
    dependencies {
        classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.0'
    }
}

apply plugin: 'org.junit.platform.gradle.plugin'

junitPlatform {
    platformVersion '1.0.0'
    reportsDir file('build/test-results/junit-platform')
    enableStandardTestTask true
    filters {
        tags {
            // Framework tests need to be run only when required to verify the this framework is still working.
            exclude "Framework"
            //include "Navigation", "Content"
        }
        includeClassNamePatterns '.*Test', '.*Tests'
    }
}

apply plugin: 'java'

sourceCompatibility = 1.8

repositories {
    mavenCentral()
}

dependencies {
    compile group: 'org.seleniumhq.selenium', name: 'selenium-java', version: '3.6.0'
    compile group: 'org.assertj', name: 'assertj-core', version: '3.8.0'

    testCompile group: 'org.junit.jupiter', name: 'junit-jupiter-api', version: '5.0.0'

    testRuntime group: 'org.seleniumhq.selenium', name: 'selenium-server', version: '3.6.0'
    testRuntime group: 'org.junit.jupiter', name: 'junit-jupiter-engine', version: '5.0.0'
}

and AbstractTest

package tech.alexontest.poftutor.infrastructure;

import org.junit.jupiter.api.*;
import org.openqa.selenium.WebDriver;

/**
 * My default AbstractTest class that creates a new WebDriver of the same type for Each Test.
 * Supports only JUnit 5 tests.
 */
@TestInstance(TestInstance.Lifecycle.PER_CLASS)
abstract public class AbstractTest {
    private WebDriver driver;
    private WebDriverManager driverManager;

    @BeforeAll
    void startService() {
        System.out.println("Preparing DriverManager");
        driverManager = DriverManagerFactory.getManager(DriverType.CHROME);
    }

    @BeforeEach
    void setup() {
        System.out.println("Getting Driver");
        driver = driverManager.getDriver();
    }

    @AfterEach
    void teardown() {
        System.out.println("Quitting Driver");
        driverManager.quitDriver();
    }

    @AfterAll
    void stopService() {
        driverManager.stopService();
    }

    protected WebDriver getDriver(final String url) {
        driver.get(url);
        return driver;
    }
}

I’m still not entirely happy with that (I really shouldn’t be using Webdrivers in my Test classes!) but it will do for now.

package tech.alexontest.poftutor;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;
import tech.alexontest.poftutor.infrastructure.AbstractTest;

import static org.assertj.core.api.Assertions.assertThat;

@Tag("Content")
class HomePageTests extends AbstractTest {
    private HomePage homePage;

    @BeforeEach
    void setupHomepage() {
        homePage = new PfHomePage(getDriver("https://alexanderontesting.com/"));                             //Page Factory implementation
    }

    @Test
    void titleIsCorrect() {
        assertThat(homePage.getPageTitle())
                .isEqualToIgnoringCase("Alexander on Testing");
    }

    @Test
    void pageContainsFiveWidgets() {
        assertThat(homePage.getWidgets())
                .size()
                .isEqualTo(5);
    }

    @Test
    void pageContainsUpToFiveArticles() {
        assertThat(homePage.getArticles())
                .size()
                .isLessThanOrEqualTo(5);
    }
}

A lot tidier.

DriverFactory part 2

More importantly this week was extending the DriverFactory to support my Windows Browsers. (adding Firefox, Edge and Internet Explorer 11) I use Opera too and may get around to supporting it, but as it uses ChromeDriver it is not so much to worry about.

The problem I had with this was that ChromeDriver appears to be the only one supporting using a pre-existing WebDriverServer in the constructor. Given the effort put into supporting that for Chrome, it left me wondering what they actually do. Experimentation showed that all other WebDriver implementations appear to always create a new service when the constructor is called. hmm (Not a happy chappy!)

I haven’t come across the DriverServers at work so I wanted to understand what was going on. Eventually I realised that this is really more important for RemoteWebDrivers.  So not only am I trying to optimise my code, but now I need to set up a grid too! (I had it in mind already to set one up on my HTPC anyway)

It’s getting very late here and I don’t want to rush this too much. The code is in the repo at https://github.com/AlexanderOnTesting/POFTutor if you want to go have a look in the meantime.

Progress made this week:

  • Removed JUnit4 support
  • Implemented DriverFactories for Firefox, Internet Explorer 11 and Edge.
  • Switched to using RemoteWebDrivers.
  • Configured a grid (2 actually – one local and one remote)

Lessons learnt:

  • The role of the WebDriverService
  • Grid setup and configuration
  • A reminder of how much stuff goes on under the hood that I have never even thought about
Comments are closed.