Minimal setup for unit testing

I’m trying to get some unit tests going for my game and I was wondering what was the minimal setup necessary to allow spatials (specifically quads and boxes) to be created? I’d like to not put up a window on the screen if possible and of course since it’s a unit test it needs to run pretty fast. Is this even possible?



Currently in my test I have a suite that invokes oneTimeSetUp() and oneTimeTearDown() for that suite.



   public static void oneTimeSetUp()
   {
      System.out.println("Onetime setup");
      
      try
      {
         ds = DisplaySystem.getDisplaySystem("LWJGL");
         ds.createWindow(640, 480, 16, 60, false);
      }
      catch (JmeException e)
      {
         e.printStackTrace();
       }
   }
   
   public static void oneTimeTearDown()
   {
      ds.close();
   }



I bomb out on the ds.create call (no error message or stack trace the unit test just stops running). That is most likely because I'm on my POS work machine and it can't run any OpenGL apps. Is there a better way that doesn't require creating the display system so that I could for example run these tests automatically when I do a check-in to my Subversion repository (linux box)?

by Spatials being “created”, do you mean on-screen, or simply in memory? If you mean in memory, you shouldn’t need to create any DisplaySystem stuff.

When I get to the line:



quad = new Quad("Card", 3f, 5f);



I get:


java.lang.NullPointerException
   at com.jme.scene.Geometry.<init>(Unknown Source)
   at com.jme.scene.TriMesh.<init>(Unknown Source)
   at com.jme.scene.shape.Quad.<init>(Unknown Source)
   at com.hcs.palabra.Card.<init>(Card.java:47)
   at com.hcs.palabra.DeckManager.Reset(DeckManager.java:79)
   at com.hcs.palabra.DeckManager.<init>(DeckManager.java:32)
   at com.hcs.palabra.DeckManager.Create(DeckManager.java:38)
   at com.hcs.palabra.TestDeckManager.setUp(TestDeckManager.java:41)
   at junit.framework.TestCase.runBare(TestCase.java:125)
   at junit.framework.TestResult$1.protect(TestResult.java:106)
   at junit.framework.TestResult.runProtected(TestResult.java:124)
   at junit.framework.TestResult.run(TestResult.java:109)
   at junit.framework.TestCase.run(TestCase.java:118)
   at junit.framework.TestSuite.runTest(TestSuite.java:208)
   at junit.framework.TestSuite.run(TestSuite.java:203)
   at junit.extensions.TestDecorator.basicRun(TestDecorator.java:22)
   at junit.extensions.TestSetup$1.protect(TestSetup.java:19)
   at junit.framework.TestResult.runProtected(TestResult.java:124)
   at junit.extensions.TestSetup.run(TestSetup.java:23)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:421)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:305)
   at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:186)



I'm pretty sure Quad (at Geometry) is invoking up the chain a call to DisplaySystem which hasn't been created in my code and thus the null pointer.


public Geometry(String name) {
      super(name);
      vertex = new Vector3f[0];
      int textureUnits = DisplaySystem.getDisplaySystem().getRenderer()
            .createTextureState().getNumberOfUnits();
      texture = new Vector2f[textureUnits][0];
      texBuf = new FloatBuffer[textureUnits];
      vboTextureIDs = new int[textureUnits];
   }

Ah yeah, damn textures… you should be able to use the no arg constructor instead to get around this.

"renanse" wrote:
Ah yeah, damn textures... you should be able to use the no arg constructor instead to get around this.

The problem with this is the class the code is in is a Card and I'm testing the DeckManager which of course creates a deck of Cards. I can't modify the constructor inside the Card constructor call or else the class won't work when I use it in the game. I can't think of a way to take out the quad from the Card class and still make the inner workings of the Card invisible to the rest of the system.

Hmm, would it be possible to break it into a model/view structure where the card class holds all the logic but a CardView class with a reference to the Card actually extends Trimesh or whatever for renderering purposes?

How would you suggest I link those two classes together? I’m assuming I would just extend Trimesh or Quad or whatever and do all my texture loading in CardView but won’t Card need to create a CardView? I suppose I could break out the CardView init code into it’s own method and then just never call that method.



My problem would be, I would want to just call Card(param) and have my entire card built which means I couldn’t test anything that calls the Card constructor (as is the case with my DeckManager). If I build a “special” constructor for testing that doesn’t init the CardView then I have two blocks of nearly identical code and I will invariably forget to update one which means my test will lie by passing when the real code would fail. Am I missing what you’re saying about the MVC pattern?

I guess I’m assuming you are testing logic since GL unit testing strikes me as difficult at best. In my previous post I meant that you’d have all your logic in a Card class that had no references to CardView at all. To add the Card to the scene graph, you’d grab a new instance of CardView and set the Card in the CardView and add the CardView to the scene. CardView would grab any specific info about the Card it needed from the card as needed. Given I know nothing about your testing procedure/aims though, this may not be what you are trying to do. :stuck_out_tongue:

No that makes perfect sense, I just had it backwards in my head. I was trying to put the CardView in the Card instead of the other way around. Your suggestion will probably work fine. I’ll give it some testing and report my results here.