JMonkeyEngine Test

Hi
I would like to know if I can get some information about the software testing process applicable to JME. I carry out research in the game testing area and am interested in tests applied to Game Engines. I downloaded, compiled and ran Jmonkey and reading the documentation. I’ve also already found the examples folder, which I assume is the tests folder. However, I wish understand the testing policy you use to determine quality of JME software.

For me, I am learning jmonkeyengine & native android development so throughout my learning process I used to read the java docs(most of time, w/o wiki for jme) carefully with the jme examples from github, & quick reading of jme classes, then building my own testcases from my own imagination & lessons of design patterns & when I learn something new, I keep my mind updated with very very simple testcases which involves only the minimal code to run a feature with or without logging(it depends on your needs).

There are also testing APIs from gradle team like junit testing, but I prefer simple stuff & I am more focused on core concept.

Pavl_G

Thank you. I believe you are someone that can help me. As I said, I intend to perform an experiment that involves code coverage. For that, I need Unit tests and a way to run all those tests by command line, I think something like ant, for example. In addition, I intend to build many different test switches to check the effect of the test switch over my coverage test. Of course the data will be used to write a future paper and in this paper a will make reference to Jmonkey. So, I would like to know if it is possible to do something like that with Jmonkey test system?

1 Like

Afaik, jmonkeyengine has nothing to do with this(it has no built in-testing system), you need to use gradle building tool which is ofc compatible with jme environment, check this :
https://docs.gradle.org/current/userguide/java_testing.html

For me, i do have fun taking a lot of time running my own testcases manually & do the logging stuff on my own(just regular java final classes with some logging & docs).

@Alexandre If you are writing a research paper or something, then may be a suggestion is to start first by making yourself familiar with jme ant environment & do run jme examples from github on your container, examine code by hand, observe & conclude the results with each testcase, then you build your own test cases after that you may shift to gradle junits, because junits won’t be good with you w/o jme knowledge.

Just FYI, we used to get similar questions (direct and otherwise) about 4-5 times a year… now they dwindle to maybe once a year. The results are always the same though: nothing of benefit.

I’d like to be wrong in this case but I generally classify this sort of thing as borderline spam.

Unit tests in a “code coverage” sense have almost no value without 100% code coverage and that’s practically impossible for an OpenGL library.

1 Like

Thank you for your attention. In fact, all this talk is very helpful to me. I will follow your guidelines regarding the glader.

1 Like

I apologize for the inconvenience. I never intended to disturb.

It’s fine… you are just in a long line of other ultimately unproductive folks.

Not sure how helpful this is, but my approach to this (I got so so tired of running test cases manually and/or finding things randomly broken) is:

I created my own set of classes (that I have called test drivers) that are designed to drive a player and/or the game. But they do so in a way that they are blocking on the test thread and trigger events on the main thread. This allows the tests to appear linear, but the game loop is continuing under neither. The drivers are very specific to my game so I’m not sure I can provide useful code but the concept may be useful. The tests end up looking like this. They all start SystemTestBooter.testWithin____ which does all the booting up of a game and takes a lambda that’s the actual test code. The whole thing is driven by junit

Simple example

@Test(timeout=30000)
public void playersLookDirectionRetainedOverSaveLoad() {
    SystemTestBooter.testWithinFlatLand(50, drivers -> {
        Vector3dJME eyePosition = drivers.playerDriver.player.getEyePosition();

        drivers.playerDriver.lookAt(eyePosition.add(1,0.1,0.5));
        drivers.gameDriver.waitForTick();
        Vector3dJME lookDirectionBeforeSaveLoad = drivers.playerDriver.player.getLookDirection();
        drivers.saveExitAndReboot();
        Vector3dJME lookDirectionAfterSaveLoad = drivers.playerDriver.player.getLookDirection();

        Vector3dJMEAsserts.assertEquals(lookDirectionBeforeSaveLoad, lookDirectionAfterSaveLoad, 0.01);
    });
}

Complex example

@Test(timeout = 30000)
public void fireflyWillFlee() {
    SystemTestBooter.testWithinFlatLand(drivers -> {
        drivers.worldDriver.setTimeInHours(1);
        MutableOptional<Firefly> fireflyOpt = new MutableOptional<>();

        drivers.worldDriver.addBubble(new MobBubble(
                (offset, asset, mobTextureMap, pickerFactory, world) -> {
                    Firefly firefly = new Firefly(new Vector3dJME(5, 5.5, 0.5), pickerFactory, offset, asset, mobTextureMap);
                    firefly.schedualer.removeNamedSchedual(Firefly.RANDOM_WANDER_SCHEDUAL);
                    fireflyOpt.setItem(firefly);
                    return firefly;
                }
        ));

        Firefly firefly = fireflyOpt.getItem();

        Procedure fireAtFirefly = CrabTest.createFireAtMobAndReload(drivers, firefly);

        Vector3dJME myPosition = new Vector3dJME(drivers.playerDriver.player.getPosition());
        Vector3dJME fireflyPosition =  new Vector3dJME(firefly.getPosition());
        double distance = fireflyPosition.distance(myPosition);

        fireAtFirefly.invoke();
        fireAtFirefly.invoke(); //fire twice to make test more reliable

        drivers.gameDriver.waitFor(5);

        Vector3dJME fireflyNewPosition =  new Vector3dJME(firefly.getPosition());
        double newDistance = fireflyNewPosition.distance(myPosition);

        double minimumFlee = 5;
        assertTrue(newDistance +" must be greater than " + distance + " by at least " + minimumFlee, distance+minimumFlee<newDistance );

    });
}

In the complex test you can see “bubbles” being used, which the test framework uses as well as the main game to provide a piece of code to run on the main thread.

Calls like drivers.gameDriver.waitForTick();, drivers.worldDriver.addBubble and drivers.playerDriver.lookAt are blocking, they block the test thread until the requested event has happened in the main game

Edit; I seem to have replied to an old thread, something else bumped it and I thought it was active