Jump to content

Recommended Posts

Posted

Hi,

 

I'm trying to write a unit test that access Items and Blocks. Now, Items and Blocks lists are null during such tests.... Like:

 

println(Items.leather)

 

This prints null. Is there a way to initialize correctly the items and blocks in a test scope, i.e., without having the game running?

 

thank you!

 

[]s,

just you wait! ;)

Posted

Because those items are defined at runtime.

 

Look at Item.java

Apparently I'm a complete and utter jerk and come to this forum just like to make fun of people, be confrontational, and make your personal life miserable.  If you think this is the case, JUST REPORT ME.  Otherwise you're just going to get reported when you reply to my posts and point it out, because odds are, I was trying to be nice.

 

Exception: If you do not understand Java, I WILL NOT HELP YOU and your thread will get locked.

 

DO NOT PM ME WITH PROBLEMS. No help will be given.

Posted

I see. So I figured I could call

Item.registerItems()

but this fails with:

 

sun.misc.Launcher$AppClassLoader cannot be cast to net.minecraft.launchwrapper.LaunchClassLoader
java.lang.ClassCastException: sun.misc.Launcher$AppClassLoader cannot be cast to net.minecraft.launchwrapper.LaunchClassLoader
at cpw.mods.fml.common.ModClassLoader.<init>(ModClassLoader.java:46)
at cpw.mods.fml.common.Loader.<init>(Loader.java:181)

just you wait! ;)

Posted

Unit testing Minecraft is a pain you have to run through the full startup because we do a lot of black magic.

It's better to just unit test your own code apart from the MC code.

I do Forge for free, however the servers to run it arn't free, so anything is appreciated.
Consider supporting the team on Patreon

Posted

I would be ok with a full startup if that is what is required. I'm developing a lib for modders, so it is quite hard to be totally isolated here.

 

From the error, I got that using the LaunchClassLoader is necessary. I tried a custom junit runner which included the code bellow. The code is scala but is very straightforward to read.

 

val classLoader = new LaunchClassLoader(Thread.currentThread.getContextClassLoader.asInstanceOf[urlClassLoader].getURLs)
Thread.currentThread.setContextClassLoader(classLoader)

 

But then this ended up destroying the specs2 context. The error is:

 

java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.junit4.IdeaSuite.getDescription(IdeaSuite.java:55)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:43)
at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:211)
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:67)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: java.lang.ClassCastException: com.easyforger.recipes.RecipesSpec cannot be cast to org.specs2.specification.core.SpecificationStructure

 

which feels like classloaders being mixed up. Does what I tried make sense? Or perhaps there is a better way to trigger the full startup and lets things be available for usage?

just you wait! ;)

Posted

Hi

 

I've run into this problem myself and after wasting hours trying to set up stubs for vanilla objects, the way I solved it was to add a "Tester" item ingame.  When the player uses the item, it interrupts the game and executes all the unit tests and integration tests using the already-set-up vanilla objects.  Not as friendly as separate junit tests but it did the trick.

 

-TGG

Posted

Hi

 

I've run into this problem myself and after wasting hours trying to set up stubs for vanilla objects, the way I solved it was to add a "Tester" item ingame.  When the player uses the item, it interrupts the game and executes all the unit tests and integration tests using the already-set-up vanilla objects.  Not as friendly as separate junit tests but it did the trick.

 

-TGG

 

Now this is something I haven't considered. Other than being triggered from inside the game, the tests ended up being just plain old junit tests? Even if it is not a clean way to write tests, it certainly sounds like a whole lot more fun then fighting classloaders or stubbing whole universes =)

just you wait! ;)

Posted

Hi

 

I've run into this problem myself and after wasting hours trying to set up stubs for vanilla objects, the way I solved it was to add a "Tester" item ingame.  When the player uses the item, it interrupts the game and executes all the unit tests and integration tests using the already-set-up vanilla objects.  Not as friendly as separate junit tests but it did the trick.

 

-TGG

 

Now this is something I haven't considered. Other than being triggered from inside the game, the tests ended up being just plain old junit tests? Even if it is not a clean way to write tests, it certainly sounds like a whole lot more fun then fighting classloaders or stubbing whole universes =)

I guess it would be more accurate to call them "junit-style" tests because I didn't actually write them using the usual junit annotations, and the testing code is in the main src not in testing packages (The Tester Item is enabled using a command line parameter).  But yes, that's the idea.  It worked really well for the mod I was making which had to copy blocks back and forth - I created a testing world, used the "Testing Item" to initialise a test region, perform a series of test copy & rotate operations, and check the results against the expected outcome at each step.  Logging of any errors.  I must have discovered twenty or thirty subtle bugs that way.

 

If you know a lot more about junit than me, you could probably figure out how to do it more cleanly by calling the right junit methods to set up the logging, start the testing, etc.  Might not be worth it.

 

You just have to be careful to remember which side your test code needs to run on, but that's not hard.  You wouldn't need an item either, just a command line parameter or similar should be enough - for example you have a tick handler which checks for the presence of the parameter and runs tests if required.

 

-TGG

Posted

Thank you TGG !

 

I managed to kick-start my tests from a preInit - which is enough for now. I might change for a item or something if I end up needing a running world at some point.

 

I'm not using junit as well, but specs2 instead, a scala testing framework. I still have to figure out a good way to call specs2 (its a bit ugly right now) - but I already know it is possible and solve the previous issues.

 

My plan to lower issue with the tests in the src/main folder is to have all tests in a separated mod, so that they don't have to be bundled with the library itself. So the idea would be that the test mod depends on the library, and all I have to do is to add the mod to a mods folder of any minecraft installation and it should work. Makes sense?

 

[]s,

just you wait! ;)

Posted

Makes sense to me

 

And from what I've seen, it would make you the second person in the history of modding to use automated testing on their mod :P

 

I can tell you from painful experience of two version upgrades that regression testing in particular is very very important.

 

-TGG

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.

Guest
Unfortunately, your content contains terms that we do not allow. Please edit your content to remove the highlighted words below.
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Announcements



×
×
  • Create New...

Important Information

By using this site, you agree to our Terms of Use.