Иконка ресурса

MCInGameTester v1.2.1

Нет прав для скачивания
Версия(и) Minecraft
1.7.10

MCInGameTester​


Движок для тестов, которые требуют загруженный Minecraft.

GitHub issues GitHub forks GitHub stars Open license JitPack JitCI GitHub CI test status See on GitHub

Использование​


Добавление в gradle​


Просто добавьте следующую строку после apply plugin: 'forge':

Gradle (Groovy):
apply from: 'https://raw.githubusercontent.com/MJaroslav/MCInGameTester/master/gradle/configurations/v1.gradle'

Обратите внимание: Это расширение gradle скрипта просто добавляет пару задач и последнюю версию движка в зависимости. Если вы хотите использовать определенную версию движка, добавьте следующие строки в gradle скрипт:

Gradle (Groovy):
configurations.all {
    resolutionStrategy {
        force 'com.github.MJaroslav:MCInGameTester:VERSION:dev'
    }
}

Где VERSION выбранная вами версия.

Задачи​

  • testClient - запускает клиент с движком и тестовым classpath'ом.
  • testServer - запускает сервер с движком и тестовым classpath'ом.
  • testJar - собирает временный jar архив из тестовых исходников. Является вспомогательной задачей и прямой вашей нужды в ней нет.
Обратите внимание: Все задачи игровых тестов осталавливают игру после завершения, если в конфигурации не указано обратного.

Объявление тестов​


Все, что вам нужно для создания тестов, содержится в com.github.mjaroslav.mcingametester.api (API) пакете. Если вы хотите вывести что-либо в консоль, используйте com.github.mjaroslav.mcingametester.lib.ModInfo#LOG.

Тестоподобный метод - это нестатичный void метод без параметров.
Контейнер тестов - это простой класс с тестоподобными методами.

Обратите внимание: Все помеченные API аннотациями вещи могут иметь любой модификатор доступа.

Для начала, просто создайте контейнеры тестов в ваших тестовых исходниках и зачем пометьте их аннотацией @Client (только для стороны клиента), @Server (только для стороны сервера) или @Common (для обоих сторон).

Обратите внимание: Для этих аннотаций вы можете использовать параметр when с типом LoadState для установки стадии запуска игры во во время которой будут запущены тесты данного контейнера тестов.

Теперь вы можете писать тесты в этих классах. Просто пишите тестоподобные методы и помечайте их с помощью @Test.

Если вы хотите что-либо выполнить до или после каждого теста, вы можете пометить тестоподобный метод с помощью @BeforeEach или @AfterEach вместо @Test.

Если вы хотите что-либо выполнить до или после всех тестов в классе, вы можете пометить статичный тестоподобный метод с помощью @BeforeClass или @AfterClass вместо @Test.

В дополнение, в серверных тестах вы можете сделать нестатичное поле типа World и поменить его аннотацией @WorldShadow. Это установит в его значение серверный объект обычного мира (с id 0).

Обратите внимание: По умолчанию в gradle заданиях тестов игры отображается только логгер из ModInfo.

Примеры

Java:
// Тесты из этого контейнера будут выполнены на обоих сторонах.
@Common
public class TestCommomSide {
    // Все before/after методы не должны бросать исключения.
    @BeforeClass
    static void beforeClass() {
        // Статично импортированный LOG из ModInfo.
        LOG.info("Выполнен на обоих сторонах перед всеми тестами этого класса");
    }
 
    @Test
    void test$common() {
        LOG.info("Выполнен на обоих сторонах");
    }
}

// Тесты из этого контейнера будут выполнены только на стороне сервера.
@Server(when = LoadState.INITIALIZATION) // Тесты будут выполнены в конце (после всех модов) файлы инициализации.
public class TestServerSide {
    @WorldShadow
    World overworld; // Геттер для обычного мира (с id 0).

    @AfterEach
    void afterEach() {
        LOG.info("Выполнен после каждого теста этого класса на строне сервера");
    }
 
    @Test
    void test$server() {
        LOG.info("Выполнен на стороне сервера");
    }
}

Написание тестов​


Каждый тест может вернуть один из трех результатов:
  • SUCCESS - выброшено ожидаемое исключение (если представлено параметром expected в @Test) и нет других исключений.
  • FAILED - ожидаемое исключение не выброшено (если представлено параметром expected в @Test) или было выброшено исключение типа AssertionError.
  • ERROR - просто ошибка в движке, например неправильный синтаксис тестов. В случае возникновения роняет игру.

Обратите внимание: Для того чтобы не бросать AssertionError исключение вручную, вы можете использовать вспомогательный класс Assert из пакета API. Вы также можете использовать одноименный класс из JUnit или любой другой класс упрощающий бросок AssertionError из других фреймворков.

Примеры

Java:
@Test(expected = ClassNotFoundException.class)
void test$clientClassOnServer() throws ClassNotFoundException {
    // Тест приведет к ClassNotFoundException на стороне сервера и провалит тест.
    // Все неожидаемые исключения будут обернуты в AssertionError.
    Class.forName("net.minecraft.client.Minecraft");
    // Используйте деобфусцированные имена без всяких проблем.
    // Вы же не будете запускать движок на продакшене, не так ли?
}

@Test
void test$isServerSide() {
    // Провалит тест, если условие вернет false.
    Assert.isTrue(FMLCommonHandler.instance().getSide().isServer(), "Не сервер");
}

@WorldShadow // Только для серверных контейнеров тестов.
World overworld;

@Test
void test$shadowWorld() {
    // Вы можете использовать несколько условий за раз.
    Assert.isTrue(overworld != null, "Мир не найден");
    Assert.isEquals(overworld.provider.dimensionId, 0, "Не обычный мир");
}

Запуск тестов​


Для запуска тестов вы должны выполнить testClient и/или testServer в gradle.

Конфигурация​


Настройки движка​


Вы можете менять следующие настройки движка с помощью переменных среды и системных свойств JVM (-Dkey=value):

Параметр​
Описание​
Значение по умолчанию​
MCIGT_STOP_AFTER_SUCCESS
или
MCInGameTester.stopAfterSuccess
Останавливает игру после удачного выполнения тестов.​
true
MCIGT_FORCED_GAME_STOP_STATE
или
MCInGameTester.forcedGameStopState
Переопределените LoadState после которого игра будет остановлена. Все тесты у которых значение параметра when стоит после переопределенного будут проигнорированы.​
Используется максимальное значение из представленных параметром when
MCIGT_STOP_NO_TESTS
или
MCInGameTester.stopNoTests
Останавливает игру, если нет тестов.​
true
MCIGT_STOP_FIRST_FAIL
или
MCInGameTester.stopFirstFail
Останавливает игру при первом проваленном тесте.​
false
MCIGT_HALT_EXIT
или
MCInGameTester.haltExit
Использовать System.halt вместо System.exit для остановки игры.​
false


Обратите внимание: Значение из переменной среды приоритетнее системного свойства JVM.

Сборка​


Вы можете настраивать задачи testClient/testServer также как и runClient/runServer (наследники JavaExec), но они имеют дополнительные параметры:

Gradle (Groovy):
testServer { // или testClient
    // Пересоздает рабочий каталог перед запуском.
    clearWorkingDirBeforeLaunch = true
    // Автоматическое принятие eula для сервера.
    eula = true // (false у testClient)
    // Использовать специальный файл конфигурации Log4J (mcingametester.xml) отобрадающий только ModInfo#LOG.
    logOnlyTests = true
    // Копирует маппинги в `../conf` от рабочей директории. Это может быть полезно
    // если вы используете CodeChickenLib в проекте: Версия из репозитория GregTech
    // умеет находить файлы маппингов автоматически, вместо того чтобы открывать
    // файловый проводник на Java Swing.
    copyMappingsLocally = true
 
    // В дополнение, testServer имеет программный аргумент "nogui" по умолчанию.
}

Расширение скрипта сборки также может сделать testClient и testServer зависимостями test если переменная среды CI равна true, но клиент еще требует и переменную MCIGT_HAS_DISPLAY с таким же значением. Это требуется потому что операционная система может быть без монитора, что приведет к падению клиента игры. В таком случае используйте любую библиотеку фейкового дисплея, например XVFB.

CI​


GitHub actions​


Этот action запустит все тесты (test с testClient и testServer как зависимости) во время любого push'а или pull request'а.

Код:
name: Run gradle tests

on: [push, pull_request]

permissions:
  contents: read

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
    - uses: actions/[email protected]
    - name: Set up JDK 8
      uses: actions/[email protected]
      with:
        java-version: '8'
        distribution: 'temurin'
    - name: Grant execute permission for gradlew
      run: chmod +x gradlew
    - name: Run all tests headless
      uses: GabrielBB/[email protected]
      with:
        run: ./gradlew test
      env:
        MCIGT_HAS_DISPLAY: true

JitCI​


Спасибо команде jitpack.io за добавление XVFB в их докер контейнеры по моей просьбе.

Вот мои отличающиеся от стандартных настройки на примере этого проекта:
  • Переменная стреды MCIGT_HAS_DISPLAY которая равна true.
  • Заменена команда тестирования на xvfb-run -e /dev/stdout -s "-screen 0 1280x1024x24 -ac -nolisten tcp -nolisten unix" -a ./gradlew test.
Обратите внимание: Отключние "dependency cache" в "init command" если у вас возникает ошибка с cache('http') или что-то подобное.

Обратите внимание: В jitpack.yml я использую следующиую конфигурацию с выключенным CI (но вы можете попробовать XVFB и тут):

Код:
jdk:
  - openjdk8
install:
  - ./gradlew build publishToMavenLocal
env:
  CI: false

Реализованные и планируемые функции​

  • "Движок".
  • Задачи запуска.
  • Интеграция для сервисов CI.
  • Настоящий плагин для gradle.
  • JUnit реализация.
  • JUnit-подобная реализация репортов.
  • Портирование на другие версии игры, у которых нет альтернативных фреймворков.
  • Реализовать встроенный фейковый дисплей или замокать всю графику.

Постскриптум​

  • Не до конца уверен с выбором категории ресурса, но раз "движок" является модом...
  • Я изначально писал это в markdown и на английском для README, поэтому могут быть странные речевые обороты, ошибки и опечатки в тексте, не стесняйтесь исправлять меня :)
  • Like
Реакции: CMTV, Artok и unknown_user
Автор
MJaroslav
Скачивания
1
Просмотры
187
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок

Другие ресурсы пользователя MJaroslav

Последние обновления

  1. v1.2.1

    1.2.1 - 2022-09-17 Исправлено Assert.isEquals теперь логируется нормально. Игнорирование...
Сверху