Giter Club home page Giter Club logo

launchwrappertestsuite's Introduction

LaunchWrapperTestSuite

LaunchWrapperTestSuite makes it possible to run JUnit tests that require transformed classes. It provides a custom test runner that will load the test class in a separate LaunchClassLoader that applies previously configured transformers.

Setup

LaunchWrapperTestSuite can be used with any build system. The following examples will use Gradle.

  1. Add test dependency on LaunchWrapperTestSuite:

    dependencies {
        testCompile 'org.spongepowered:lwts:1.0.0'
    }
  2. Implement a test tweak class that configures the transformers. LaunchWrapperTestSuite comes with AbstractTestTweaker which provides some utility methods and sets up the class loader to work with JUnit.

    package com.example.test.launch;
    
    import net.minecraft.launchwrapper.LaunchClassLoader;
    import org.spongepowered.lwts.AbstractTestTweaker;
    
    public class MyTestTweaker extends AbstractTestTweaker {
    
        @Override
        public void injectIntoClassLoader(LaunchClassLoader loader) {
            // Important so we can configure some settings for JUnit
            super.injectIntoClassLoader(loader);
            
            // Configure your transformers here (a few examples below)
            
            // Access transformer
            registerAccessTransformer("META-INF/test_at.cfg");
            
            // Mixin environment
            MixinBootstrap.init();
            Mixins.addConfiguration("mixins.test.json");
            // Set Mixin side, otherwise you get a warning when running the tests
            MixinEnvironment.getDefaultEnvironment().setSide(SERVER);
            
            // Custom transformer
            loader.registerTransformer("com.example.test.launch.transformer.MyCustomTransformer");
        }
    
    }
  3. Set a system property lwts.tweaker with the full qualified class name of your tweaker:

    test {
        systemProperty 'lwts.tweaker', 'com.example.test.launch.MyTestTweaker'
        
        // Run tests in a temporary directory
        workingDir = {test.temporaryDir}
    }

Usage

To make a test class use the custom test runner, all you need to do is add a annotation to it:

@RunWith(LaunchWrapperTestRunner.class)
public class MyTest {

    @Test
    public void testSomething() {
        // ...
    }

}

When you run your tests using gradle test it should load the test class in the custom classloader and apply the configured transformers.

Parameterized test

If you are using a parameterized test you need to change the test runner to LaunchWrapperParameterized:

@RunWith(LaunchWrapperParameterized.class)
public class MyParameterizedTest {

    @Parameterized.Parameters
    public static Collection<Object[]> getParameters() {
        // ...
    }

}

launchwrappertestsuite's People

Contributors

stephan-gh avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

launchwrappertestsuite's Issues

README documentation (or example project) how to test plugin with this? (Status: POC with NPEs)

Hello @Minecrell, this project looks interesting! (FYI I had toyed with something vaguely related 1.5 yrs ago on http://blog2.vorburger.ch/2015/10/how-to-integration-test-minecraft.html, but not pursued it since.)

When attempting to use this for a POC to test a plugin (for developers with limited understanding of SpongePowered internals, Mixins and all; like myself), in something like my NewsServiceTest, with this TestTweaker, I'm getting about half way, currently failing with a lot of NPEs... perhaps you could advise what's missing to get something like this to work? I could contribute README documentation (or example project) how to test plugin with the LaunchWrapperTestSuite in return, if that would be of any value to this community.

From what little I understand, what the NPEs may really be trying to tell me could "just" be that I'm missing the (decompiled...) net.minecraft.* and com.mojang.* from the dependencies in the build.gradle ... but ... are those available as Maven artifacts? If they are not, how could one get them "dynamically" made available to such a test?

Thank you!

LWTS does not seem to work with liteloader

When I run unit tests with liteloader, things do not work; it seems like the mixins are not being properly applied.

Here is the test output:

com.examplemod.SomeTest STANDARD_OUT
    [13:19:23] [Test worker/INFO]: Loading tweak class name com.examplemod.TestTweaker
    [13:19:23] [Test worker/INFO]: Using primary tweak class name com.examplemod.TestTweaker
    [13:19:23] [Test worker/INFO]: Calling tweak class com.examplemod.TestTweaker
    [13:19:23] [Test worker/INFO]: SpongePowered MIXIN Subsystem Version=0.7.3 Source=file:/C:/Users/Pokechu22/.gradle/caches/modules-2/files-2.1/org.spongepowered/mixin/0.7.3-SNAPSHOT/484e9031a994cdcc68cf79653c9d5dc288faa350/mixin-0.7.3-SNAPSHOT.jar Service=LaunchWrapper Env=UNKNOWN

com.examplemod.SomeTest STANDARD_ERROR
    /*************************************************************************************************************************************************************************************************************/
    /*                                                                              SpongePowered MIXIN (Verbose debugging enabled)                                                                              */
    /*************************************************************************************************************************************************************************************************************/
    /*                        Code source : file:/C:/Users/Pokechu22/.gradle/caches/modules-2/files-2.1/org.spongepowered/mixin/0.7.3-SNAPSHOT/484e9031a994cdcc68cf79653c9d5dc288faa350/mixin-0.7.3-SNAPSHOT.jar */
    /*                   Internal Version : 0.7.3                                                                                                                                                                */
    /*                   Java 8 Supported : true                                                                                                                                                                 */
    /*************************************************************************************************************************************************************************************************************/
    /*                       Service Name : LaunchWrapper                                                                                                                                                        */
    /*                      Service Class : org.spongepowered.asm.service.mojang.MixinServiceLaunchWrapper                                                                                                       */
    /*************************************************************************************************************************************************************************************************************/
    /*                        mixin.debug : <true>                                                                                                                                                               */
    /*                 mixin.debug.export : - <true>                                                                                                                                                             */
    /*          mixin.debug.export.filter : - - <null>                                                                                                                                                           */
    /*       mixin.debug.export.decompile : - - <true>                                                                                                                                                           */
    /* mixin.debug.export.decompile.async : - - - <true>                                                                                                                                                         */
    /*                 mixin.debug.verify : - <true>                                                                                                                                                             */
    /*                mixin.debug.verbose : - <true>                                                                                                                                                             */
    /*        mixin.debug.countInjections : - <true>                                                                                                                                                             */
    /*                 mixin.debug.strict : - <false>                                                                                                                                                            */
    /*          mixin.debug.strict.unique : - - <false>                                                                                                                                                          */
    /*         mixin.debug.strict.targets : - - <false>                                                                                                                                                          */
    /*               mixin.debug.profiler : - <true>                                                                                                                                                             */
    /*          mixin.dumpTargetOnFailure : <false>                                                                                                                                                              */
    /*                       mixin.checks : <false>                                                                                                                                                              */
    /*            mixin.checks.interfaces : - <false>                                                                                                                                                            */
    /*     mixin.checks.interfaces.strict : - - <false>                                                                                                                                                          */
    /*            mixin.ignoreConstraints : <false>                                                                                                                                                              */
    /*                      mixin.hotSwap : <false>                                                                                                                                                              */
    /*                          mixin.env : <false>                                                                                                                                                              */
    /*                      mixin.env.obf : - <false>                                                                                                                                                            */
    /*            mixin.env.disableRefMap : - <false>                                                                                                                                                            */
    /*              mixin.env.remapRefMap : - <false>                                                                                                                                                            */
    /*      mixin.env.refMapRemappingFile : - <>                                                                                                                                                                 */
    /*       mixin.env.refMapRemappingEnv : - <searge>                                                                                                                                                           */
    /*           mixin.env.ignoreRequired : - <false>                                                                                                                                                            */
    /*              mixin.env.compatLevel : - <false>                                                                                                                                                            */
    /*         mixin.env.shiftByViolation : - <warn>                                                                                                                                                             */
    /*     mixin.initialiserInjectionMode : <default>                                                                                                                                                            */
    /*************************************************************************************************************************************************************************************************************/
    /*                      Detected Side : UNKNOWN                                                                                                                                                              */
    /*************************************************************************************************************************************************************************************************************/

com.examplemod.SomeTest STANDARD_OUT
    [13:19:24] [Test worker/INFO]: Attempting to load Fernflower decompiler (Threaded mode)
    [13:19:24] [Test worker/INFO]: Fernflower could not be loaded, exported classes will not be decompiled. NoClassDefFoundError: org/jetbrains/java/decompiler/main/extern/IResultSaver
    [13:19:24] [Test worker/INFO]: FML platform manager could not load class cpw.mods.fml.relauncher.CoreModManager. Proceeding without FML support.
    [13:19:24] [Test worker/WARN]: MixinBootstrap.doInit() called during a tweak constructor. Expect CoModificationException in 5.. 4..
    [13:19:24] [Test worker/INFO]: Compatibility level set to JAVA_8
    sun.misc.Launcher$AppClassLoader@73d16e93
    [13:19:24] [Test worker/INFO]: Loading tweak class name org.spongepowered.asm.mixin.EnvironmentStateTweaker
    [13:19:24] [Test worker/INFO]: Calling tweak class org.spongepowered.asm.mixin.EnvironmentStateTweaker
    [13:19:24] [Test worker/INFO]: Preparing mixins for MixinEnvironment[DEFAULT]
    [13:19:24] [Test worker/INFO]: Selecting config mixins.example.json
    [13:19:24] [Test worker/WARN]: Reference map 'mixins.example.refmap.json' for mixins.example.json could not be read. If this is a development environment you can ignore this message
    [13:19:24] [Test worker/INFO]: Preparing mixins.example.json (2)
    [13:19:24] [Test worker/INFO]: Prepared 2 mixins in 0.381 sec (190.5ms avg) (14ms load, 0ms transform, 0ms plugin)
    [13:19:24] [Test worker/INFO]: Launching wrapped minecraft {org.spongepowered.lwts.TestMain}

com.examplemod.SomeTest > testFoo STANDARD_OUT
    sun.misc.Launcher$AppClassLoader@73d16e93
Gradle Test Executor 7 finished executing tests.

com.examplemod.SomeTest > testFoo FAILED
    java.lang.ClassCastException: net.minecraft.util.ResourceLocation cannot be cast to com.examplemod.Foo
        at com.examplemod.SomeTest.testFoo(SomeTest.java:14)

Here's a zip of my test project (which is just the liteloader examplemod plus some other code that works with tests; the mixin I'm testing is only for this and doesn't actually have any value when launched with MC). lwts-test.zip

LWTS does work on sponge on my machine. I added System.out.println(this.getClass().getClassLoader()) to TestTweaker and CatalogTypeClassesTest (the second was just randomly chosen as one of the tests that uses LWTS), and for TestTweaker it was sun.misc.Launcher$AppClassLoader@73d16e93 but for CatalogTypeClassesTest it was net.minecraft.launchwrapper.LaunchClassLoader@30f10695. This differs from my liteloader result, where both were AppClassLoader (see log above). I'm guessing that that is the reason why I'm getting non-mixed-in classes... but I have no clue why this is happening otherwise.

I'm running with gradle wrapper 4.4.1.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.