{"id":20271203,"url":"https://github.com/mjaroslav/mcingametester","last_synced_at":"2026-05-06T14:36:53.882Z","repository":{"id":57968282,"uuid":"529409348","full_name":"MJaroslav/MCInGameTester","owner":"MJaroslav","description":"Engine for tests, that requires minecraft to be loaded.","archived":false,"fork":false,"pushed_at":"2024-01-06T03:33:39.000Z","size":123,"stargazers_count":2,"open_issues_count":2,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-01-14T05:47:29.584Z","etag":null,"topics":["gradle","gradle-plugin","gradle-task","minecraft-forge","minecraft-forge-mod","minecraft-forge-mod-util","minecrat","test","test-automation","test-framework","testing","testing-framework","testing-library"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"wtfpl","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/MJaroslav.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-08-26T21:27:17.000Z","updated_at":"2024-02-29T20:16:25.000Z","dependencies_parsed_at":"2024-11-19T21:47:01.294Z","dependency_job_id":null,"html_url":"https://github.com/MJaroslav/MCInGameTester","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MJaroslav%2FMCInGameTester","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MJaroslav%2FMCInGameTester/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MJaroslav%2FMCInGameTester/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/MJaroslav%2FMCInGameTester/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/MJaroslav","download_url":"https://codeload.github.com/MJaroslav/MCInGameTester/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":241758953,"owners_count":20015249,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["gradle","gradle-plugin","gradle-task","minecraft-forge","minecraft-forge-mod","minecraft-forge-mod-util","minecrat","test","test-automation","test-framework","testing","testing-framework","testing-library"],"created_at":"2024-11-14T12:37:00.589Z","updated_at":"2026-05-06T14:36:48.845Z","avatar_url":"https://github.com/MJaroslav.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# MCInGameTester\n\nEngine for tests, that requires minecraft to be loaded.\n\n[![GitHub issues](https://img.shields.io/github/issues/mjaroslav/mcingametester)](https://github.com/mjaroslav/mcingametester/issues \"GitHub issues\")\n[![GitHub forks](https://img.shields.io/github/forks/mjaroslav/mcingametester)](https://github.com/mjaroslav/mcingametester/network \"GitHub forks\")\n[![GitHub stars](https://img.shields.io/github/stars/mjaroslav/mcingametester)](https://github.com/mjaroslav/mcingametester/stargazers \"GitHub stars\")\n[![GitHub license](https://img.shields.io/github/license/mjaroslav/mcingametester)](https://github.com/MJaroslav/mcingametester/blob/master/LICENSE \"Open license\")\n[![JitPack](https://jitpack.io/v/MJaroslav/MCInGameTester.svg)](https://jitpack.io/#MJaroslav/MCInGameTester \"JitPack\")\n[![JitCI status](https://jitci.com/gh/MJaroslav/MCInGameTester/svg)](https://jitci.com/gh/MJaroslav/MCInGameTester \"JitCI\")\n![GitHub CI test status](https://github.com/MJaroslav/MCInGameTester/actions/workflows/ci-test.yml/badge.svg)\n\n## Usage\n\n### Adding to gradle\n\nJust add next line after `apply plugin: 'forge'`:\n\n```groovy\napply from: 'https://raw.githubusercontent.com/MJaroslav/MCInGameTester/master/gradle/configurations/v1.gradle'\n```\n\n**Note:** This build script extension just adds some tasks and last project version to dependencies. If you want to use\nspecific version of engine, add next to your build script:\n\n```groovy\nconfigurations.all {\n    resolutionStrategy {\n        force 'com.github.MJaroslav:MCInGameTester:VERSION:dev'\n    }\n}\n```\n\nWhere `VERSION` is a selected engine version.\n\n### Tasks\n\n- `testClient` - runs client with test engine and test source set added in classpath.\n- `testServer` - runs server with test engine and test source set added in classpath.\n- `testJar` - builds temp jar from test source set. You no needs in this, its utility task.\n\n**Note**: Any game test task will stop game after all test execution if configuration don't say else.\n\n### Declaring tests\n\nAll that you need for making tests, contains in `com.github.mjaroslav.mcingametester.api` (API) package.  \nIf you need to log something, use `com.github.mjaroslav.mcingametester.lib.ModInfo#LOG` logger.\n\n**Test-like method** - it's a non-static void method without parameters.  \n**Test container** - it's a simple class with test-like methods.\n\n**Note:** All annotated things by annotations from API in test containers can be with any access modifier.\n\nFor begin, just create test containers in your test source set and then annotate them with `@Client` (for only client\nside), `@Server` (for only server side) or `@Common` (for both side).\n\n**Note:** For these three annotations, you can use  `when` parameter with `LoaderState` type for setting loading state\nwhen tests should be run.\n\nNow, you can write tests in these classes. Just write test-like methods and annotate them with `@Test`.\n\nIf you needs in executing something before or after each test, you can make test-like method but annotate it\nwith `@BeforeEach` or `@AfterEach` instead of `@Test`.\n\nIf you needs in executing something before or after all tests in class, you can make **static** test-like method but\nannotate it with `@BeforeClass` or `@AfterClass` instead of `@Test`.\n\nIn addition, for Server sided tests you can make non-static World-typed field with `@WorldShadow` annotation. It's sets\nOverworld World object to this field.\n\n**Note:** Only logger from `ModInfo` showed in game test tasks by default.\n\n#### Examples\n\n```java\n// Tests from this test container will executed on both sides.\n@Common\npublic class TestCommomSide {\n    // Be careful, all before/after methods should not throwing any exceptions.\n    @BeforeClass\n    static void beforeClass() {\n        // Static imported LOG from ModInfo.\n        LOG.info(\"Will executed on both sides before all tests from this class\");\n    }\n    \n    @Test\n    void test$common() {\n        LOG.info(\"Will executed on both sides\");\n    }\n}\n\n// Tests from this test container will executed only on server side.\n@Server(when = LoaderState.INITIALIZATION) // Tests will executed in end (after other mods) of initialization state.\npublic class TestServerSide {\n    @WorldShadow\n    World overworld; // Getter for server Overworld (dim 0). \n\n    @AfterEach\n    void afterEach() {\n        LOG.info(\"Will executed after each test of this class on server side\");\n    }\n    \n    @Test\n    void test$server() {\n        LOG.info(\"Will executed on server side\");\n    }\n}\n```\n\n### Test writing\n\nEvery test can return one of three results:\n\n- `SUCCESS` - expected throwable was thrown (if present by `expected` parameter in `@Test`) and anything else wasn't\n  thrown.\n- `FAILED` - expected throwable wasn't thrown (if present by `expected` parameter in `@Test`) or `AssertionError` was\n  thrown and anything else\n  wasn't thrown.\n- `ERROR` - just error in test engine, for example bad test syntax. It will crash the game.\n\n**Note:** For not throwing AssertionErrors in tests manually, you can use `Assert` class from API. You can also use same\nname class from JUnit or any helper for throwing `AssertionError` from another libs.\n\n#### Examples\n\n```java\n@Test(expected = ClassNotFoundException.class)\nvoid test$clientClassOnServer() throws ClassNotFoundException {\n    // Test will cause ClassNotFoundException on server and fail test.\n    // All unexpected exceptions will wrapped in AssertionError and cause test fail.\n    Class.forName(\"net.minecraft.client.Minecraft\"); \n   // Use deobf names without any problems.\n   // I hope you don't run this in obfuscated environment, do you?\n}\n\n@Test\nvoid test$isServerSide() {\n    // Fails test if condition return false.\n    Assert.isTrue(FMLCommonHandler.instance().getSide().isServer(), \"Non server side\");\n}\n\n@WorldShadow // Only for server side test containers.\nWorld overworld;\n\n@Test\nvoid test$shadowWorld() {\n    // You can combine several assertions.\n    Assert.isTrue(overworld != null, \"Null world\");\n    Assert.isEquals(overworld.provider.dimensionId, 0, \"Not Overworld\");\n}\n```\n\n### Test execution\n\nFor run tests manually you should execute `testClient` and/or `testServer` task.\n\n## Configuration\n\n### Engine options\n\nYou can change next options of engine by system environments or JVM system properties (`-Dkey=value`):\n\n|                                 Parameter                                  |                                                                        Description                                                                        |                   Default value                   |\n|:--------------------------------------------------------------------------:|:---------------------------------------------------------------------------------------------------------------------------------------------------------:|:-------------------------------------------------:|\n|    MCIGT_STOP_AFTER_SUCCESS\u003cbr/\u003eor\u003cbr/\u003eMCInGameTester.stopAfterSuccess     |                                                         Stop game after success tests execution.                                                          |                       true                        |\n| MCIGT_FORCED_GAME_STOP_STATE\u003cbr/\u003eor\u003cbr/\u003eMCInGameTester.forcedGameStopState | Forces LoaderState for game stopping. All tests in test containers where `when` parameter set with LoaderState that should be after forced, will ignored. | Used max value from annotations `when` parameter. |\n|         MCIGT_STOP_NO_TESTS\u003cbr/\u003eor\u003cbr/\u003eMCInGameTester.stopNoTests          |                                                               Stop game if no tests loaded.                                                               |                       true                        |\n|       MCIGT_STOP_FIRST_FAIL\u003cbr/\u003eor\u003cbr/\u003eMCInGameTester.stopFirstFail        |                                                              Stop game on first failed test.                                                              |                       false                       |\n|             MCIGT_HALT_EXIT\u003cbr/\u003eor\u003cbr/\u003eMCInGameTester.haltExit             |                                                 Use System.halt instead of System.exit for game stopping.                                                 |                       false                       |\n\n**Note:** Value from environment variable will force JVM system property value.\n\n### Build script\n\nYou can configure `testClient`/`testServer` like as `runClient`/`runServer` tasks (it's JavaExec-typed tasks), but these\ntasks contains some additional parameters:\n\n```groovy\ntestServer { // or testClient\n    // Recreate working dir before game launch.\n    clearWorkingDirBeforeLaunch = true\n    // Auto accepting eula for server.\n    eula = true // (false for testClient)\n    // Use custom Log4J configuration (mcingametester.xml) for showning only ModInfo#LOG logger.\n    logOnlyTests = true\n    // Copies mapping to `../conf` of working directory. It's can be useful\n    // if you use CodeChickenLib in project: version from GregTech repository \n    // can find mappings automatically, witout showing Java Swing File Chooser.\n    copyMappingsLocally = true\n    \n    // In additional, testServer have default \"nogui\" program argument.\n}\n```\n\nScript extension also can set  `testClient` and `testServer` as `test` task dependencies if `CI` environment variable\nis `true`, but for client also required environment variable `MCIGT_HAS_DISPLAY` with same value. It's required because\nOS can be headless and client game will crash. In this case use any display faker for it, for example XVFB.\n\n## CI environments\n\n### GitHub actions\n\nThis action will run all tests (`test` with `testClient` and `testServer` as dependencies) on any push or pull request.\n\n```yaml\nname: Run gradle tests\n\non: [push, pull_request]\n\npermissions:\n  contents: read\n\njobs:\n  build:\n    runs-on: ubuntu-latest\n    steps:\n    - uses: actions/checkout@v3\n    - name: Set up JDK 8\n      uses: actions/setup-java@v3\n      with:\n        java-version: '8'\n        distribution: 'temurin'\n    - name: Grant execute permission for gradlew\n      run: chmod +x gradlew\n    - name: Run all tests headless\n      uses: GabrielBB/xvfb-action@v1\n      with:\n        run: ./gradlew test\n      env:\n        MCIGT_HAS_DISPLAY: true\n```\n\n### JitCI\n\nThanks jitpack.io command for adding XVFB to their docker containers by my request.\n\nI use next non-standard settings for this project:\n\n- Environment variable `MCIGT_HAS_DISPLAY` that equals `true`\n- Replace test command\n  by `xvfb-run -e /dev/stdout -s \"-screen 0 1280x1024x24 -ac -nolisten tcp -nolisten unix\" -a ./gradlew test`\n\n**Note:** Disable dependency cache in init command if you have `cache('http')` or something problem.\n\n**Note:** In `jitpack.yml` I use next configuration for building without CI (but you can try use XVFB too):\n\n```yaml\njdk:\n  - openjdk8\ninstall:\n  - ./gradlew build publishToMavenLocal\nenv:\n  CI: false\n```\n\n## Released and planned features\n\n- [X] \"Engine\".\n- [X] Run tasks.\n- [X] CI integration.\n- [ ] Real Gradle Plugin.\n- [ ] JUtil implementation.\n- [ ] JUnit report implementation.\n- [ ] Port to next game versions without alternative frameworks.\n- [ ] Implement fake display or make mocked client graphics.\n\n## Post Scriptum\n\nFeel free to correct typos and errors in the text or code :)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmjaroslav%2Fmcingametester","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmjaroslav%2Fmcingametester","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmjaroslav%2Fmcingametester/lists"}