As an Android developer by day, I’m used to writing rigorous unit tests, taking advantage of nice tools and libraries like JUnit and Mockito. However, as a hobbyist game developer by night, I feel like my game project is a bit lacking in terms of testing. How about we fix that?

Testing, testing..?

First off, LibGDX doesn’t sport any unit tests for your game project whatsoever. The project itself has lots of tests, which is nice, but they are Eclipse-only at the time of writing this and don’t really lend themselves to properly testing your own code. For instance, the base classes for the tests such as GdxTest are not available for your production code. Bummer.

However, let’s not give up just yet. Getting your unit tests up and running takes just a bit of extra effort. With your fresh game project created (or an old one loaded up), let’s open the project-wide build.gradle and navigate to the core project portion. You should see something like this:

project(":core") {
    apply plugin: "java"

    dependencies {
        compile "com.badlogicgames.gdx:gdx:$gdxVersion"
        compile "com.badlogicgames.gdx:gdx-box2d:$gdxVersion"
        compile "com.badlogicgames.gdx:gdx-freetype:$gdxVersion"

        testCompile "com.badlogicgames.gdx:gdx-backend-headless:$gdxVersion"
        testCompile "com.badlogicgames.gdx:gdx:$gdxVersion"
        testCompile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"
        testCompile "com.badlogicgames.gdx:gdx-box2d:$gdxVersion"
        testCompile "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-desktop"
    }
}

Nothing special here - just the dependencies for LibGDX and some other stuff you might have included. Now, we just need three new lines here. First, before the dependencies, we declare the source directory for our unit tests:

project(":core") {
    apply plugin: "java"

    sourceSets.test.java.srcDirs = ["/test"]

    dependencies {
        ...
}

This tells the project that your tests are located inside a folder called test, just like when you’re working on an Android project. Next, let’s add two dependencies for JUnit and Mockito:

dependencies {
    compile "com.badlogicgames.gdx:gdx:$gdxVersion"
    compile "com.badlogicgames.gdx:gdx-box2d:$gdxVersion"
    compile "com.badlogicgames.gdx:gdx-freetype:$gdxVersion"
    compile "net.onedaybeard.artemis:artemis-odb:$artemisVersion"
    compile "net.onedaybeard.artemis:artemis-odb-serializer-json-libgdx:2.0.0"

    // These are new!
    testCompile "junit:junit:4.12"
    testCompile "org.mockito:mockito-core:2.2.7"

    testCompile "com.badlogicgames.gdx:gdx-backend-headless:$gdxVersion"
    testCompile "com.badlogicgames.gdx:gdx:$gdxVersion"
    testCompile "com.badlogicgames.gdx:gdx-platform:$gdxVersion:natives-desktop"
    testCompile "com.badlogicgames.gdx:gdx-box2d:$gdxVersion"
    testCompile "com.badlogicgames.gdx:gdx-box2d-platform:$gdxVersion:natives-desktop"
}

First Test

Let’s create our first unit test now. Open a class you’d like to write your test for, place your caret on the class name and hit Alt + Enter. This should Open a contextual menu with the option “Create Test”.

Create a test

Now, let’s write a simple test. I’ll write my test for my own class called TilesetHandler which is a simple class for managing textures and tilesets. My test would look something like this:

public class TilesetTest {

    @Test
    public void testHandler() {
        // Create a new handler
        TilesetHandler handler = new TilesetHandler();

        // Create a new texture to create a tileset from
        Texture texture = new Texture(512, 512, Pixmap.Format.RGB888);

        // Create a tileset from the texture
        Tileset tileset = handler.load(texture);

        // Assert the tileset is not null
        assertNotNull(tileset);
    }
}

So far so good, but what happens when I try to run this?

java.lang.UnsatisfiedLinkError: com.badlogic.gdx.graphics.g2d.Gdx2DPixmap.setBlend(I)V

    at com.badlogic.gdx.graphics.g2d.Gdx2DPixmap.setBlend(Native Method)
    at com.badlogic.gdx.graphics.g2d.Gdx2DPixmap.<clinit>(Gdx2DPixmap.java:84)
    at com.badlogic.gdx.graphics.Pixmap.<init>(Pixmap.java:122)
    at com.badlogic.gdx.graphics.Texture.<init>(Texture.java:116)
    at me.manabreak.neverdone.tiles.TilesetTest.testHandler(TilesetTest.java:16)

Err… It appears that we don’t have the native dependencies of LibGDX when we try to run our test. Well, let’s solve that! If you recall from our test dependencies, there was a dependency for gdx-backend-headless which is normally used for running your LibGDX application on a server. We can also use this headless backend to run our tests!

First, let’s create a new test class called GameTest that will be the base class for all our upcoming tests.

public class GameTest {
    // This is our "test" application
    private static Application application;

    // Before running any tests, initialize the application with the headless backend
    @BeforeClass
    public static void init() {
        // Note that we don't need to implement any of the listener's methods
        application = new HeadlessApplication(new ApplicationListener() {
            @Override public void create() {}
            @Override public void resize(int width, int height) {}
            @Override public void render() {}
            @Override public void pause() {}
            @Override public void resume() {}
            @Override public void dispose() {}
        });

        // Use Mockito to mock the OpenGL methods since we are running headlessly
        Gdx.gl20 = Mockito.mock(GL20.class);
        Gdx.gl = Gdx.gl20;
    }

    // After we are done, clean up the application
    @AfterClass
    public static void cleanUp() {
        // Exit the application first
        application.exit();
        application = null;
    }
}

One more thing: make our actual test class extend from GameTest:

public class TilesetTest extends GameTest {

    @Test
    public void testHandler() {
        TilesetHandler handler = new TilesetHandler();

        Texture texture = new Texture(512, 512, Pixmap.Format.RGB888);
        Tileset tileset = handler.load(texture);
        assertNotNull(tileset);
    }
}

And there we go! Now your test should work as intended. Whoo!

Great success!

Conclusion

LibGDX is a powerful library and framework to make games in, but unfortunately unit testing your own code is made a tad difficult. Hopefully this post helps you on your journey to greater test coverage and better quality of your code!