🇮🇹 Italiano (Italian)
🇮🇹 Italiano (Italian)
Aspetto
🇮🇹 Italiano (Italian)
🇮🇹 Italiano (Italian)
Aspetto
This page is written for:
1.21
This page is written for:
1.21
Questa pagina spiega come scrivere codice che testi parti della tua mod automaticamente. Ci sono due modi per testare la tua mod automaticamente: unit test con Fabric Loader JUnit o test nel gioco con il framework Gametest di Minecraft.
Gli unit test dovrebbero essere usato per testare le componenti del tuo codice, come i metodi e le classi helper, mentre test nel gioco avviano un client e un server Minecraft reali per eseguire i tuoi test, il che li rende appropriati per testare funzionalità e gameplay.
WARNING
Per ora, questa guida si occupa solo dello unit testing.
Poiché il modding in Minecraft si affida a strumenti di modifica del byte-code da eseguire come i Mixin, aggiungere e usare JUnit normalmente non funzionerebbe. Questo è il motivo per cui Fabric fornisce Fabric Loader JUnit, un plugin JUnit che attiva lo unit testing in Minecraft.
Anzitutto, dobbiamo aggiungere Fabric Loader JUnit all'ambiente di sviluppo. Aggiungi il seguente blocco di dipendenze al tuo build.gradle
:
testImplementation "net.fabricmc:fabric-loader-junit:${project.loader_version}"
Poi, dobbiamo informare Gradle su come usare Fabric Loader JUnit per il testing. Puoi fare ciò aggiungendo il codice seguente al tuo build.gradle
:
test {
useJUnitPlatform()
}
Appena ricaricato Gradle, sei pronto a scrivere test.
Questi test si scrivono proprio come altri test JUnit regolari, con un po' di configurazione aggiuntiva se vuoi accedere a classi che dipendono dalle registry, come ItemStack
. Se JUnit ti è familiare, puoi saltare a Impostare le Registry.
I test si scrivono nella cartella src/test/java
.
Una convenzione per i nomi è quella di rispecchiare la struttura del package della classe che stai testando. Per esempio, per testare src/main/java/com/example/docs/codec/BeanType.java
, dovresti creare la classe src/test/java/com/example/docs/codec/BeanTypeTest.java
. Nota che abbiamo aggiunto Test
alla fine del nome della classe. Questo ti permette anche di accedere facilmente a metodi e attributi privati al package.
Un'altra convenzione è avere un package test
, quindi src/test/java/com/example/docs/test/codec/BeanTypeTest.java
. Questo previene alcuni problemi dovuti all'uso dello stesso package se usi i moduli Java.
Dopo aver creato la classe di test, usa ⌘/CTRLN per aprire il menu Generate. Seleziona Test e comincia a scrivere il nome del tuo metodo, che di solito inizia con test
. Premi Invio quando hai fatto. Per altri trucchi riguardo all'ambiente di sviluppo, vedi Trucchi Riguardanti l'IDE.
Puoi ovviamente scrivere la firma del metodo manualmente, e qualsiasi istanza del metodo senza parametri e come tipo restituito void sarà identificato come metodo di test. Dovresti alla fine avere il seguente:
Nota gli indicatori a freccia verde nel margine: puoi facilmente eseguire un test cliccandoci sopra. In alternativa, i tuoi test si eseguiranno in automatico ad ogni build, incluse le build di CI come GitHub Actions. Se stai usando GitHub Actions, non dimenticare di leggere Configurare le GitHub Actions.
Ora è il tempo di scrivere il tuo codice di test effettivo. Puoi assicurare condizioni con org.junit.jupiter.api.Assertions
. Dai un'occhiata ai test seguenti:
public class BeanTypeTest {
private static final Gson GSON = new GsonBuilder().create();
@BeforeAll
static void beforeAll() {
BeanTypes.register();
}
@Test
void testBeanCodec() {
StringyBean expectedBean = new StringyBean("This bean is stringy!");
Bean actualBean = Bean.BEAN_CODEC.parse(JsonOps.INSTANCE, GSON.fromJson("{\"type\":\"example:stringy_bean\",\"stringy_string\":\"This bean is stringy!\"}", JsonObject.class)).getOrThrow();
Assertions.assertInstanceOf(StringyBean.class, actualBean);
Assertions.assertEquals(expectedBean.getType(), actualBean.getType());
Assertions.assertEquals(expectedBean.getStringyString(), ((StringyBean) actualBean).getStringyString());
}
@Test
void testDiamondItemStack() {
// I know this isn't related to beans, but I need an example :)
ItemStack diamondStack = new ItemStack(Items.DIAMOND, 65);
Assertions.assertTrue(diamondStack.isOf(Items.DIAMOND));
Assertions.assertEquals(65, diamondStack.getCount());
}
}
Per una spiegazione di cosa fa questo codice, leggi Codec.
Ottimo, il primo test è funzionato! Ma aspetta, il secondo test è fallito? Nei log, otteniamo uno dei seguenti errori.
java.lang.ExceptionInInitializerError
at net.minecraft.item.ItemStack.<clinit>(ItemStack.java:94)
at com.example.docs.codec.BeanTypeTest.testBeanCodec(BeanTypeTest.java:20)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
Caused by: java.lang.IllegalArgumentException: Not bootstrapped (called from registry ResourceKey[minecraft:root / minecraft:game_event])
at net.minecraft.Bootstrap.createNotBootstrappedException(Bootstrap.java:118)
at net.minecraft.Bootstrap.ensureBootstrapped(Bootstrap.java:111)
at net.minecraft.registry.Registries.create(Registries.java:238)
at net.minecraft.registry.Registries.create(Registries.java:229)
at net.minecraft.registry.Registries.<clinit>(Registries.java:139)
... 5 more
Not bootstrapped (called from registry ResourceKey[minecraft:root / minecraft:game_event])
java.lang.IllegalArgumentException: Not bootstrapped (called from registry ResourceKey[minecraft:root / minecraft:game_event])
at net.minecraft.Bootstrap.createNotBootstrappedException(Bootstrap.java:118)
at net.minecraft.Bootstrap.ensureBootstrapped(Bootstrap.java:111)
at net.minecraft.registry.Registries.create(Registries.java:238)
at net.minecraft.registry.Registries.create(Registries.java:229)
at net.minecraft.registry.Registries.<clinit>(Registries.java:139)
at net.minecraft.item.ItemStack.<clinit>(ItemStack.java:94)
at com.example.docs.codec.BeanTypeTest.testBeanCodec(BeanTypeTest.java:20)
at java.base/java.lang.reflect.Method.invoke(Method.java:580)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
at java.base/java.util.ArrayList.forEach(ArrayList.java:1596)
Questo è perché stiamo provando ad accedere alla registry o a una classe che dipende su queste (o, in casi rari, dipende su altre classi Minecraft come SharedConstants
), ma Minecraft non è stato inizializzato. Dobbiamo solo inizializzarlo un po' perché funzionino le registry. Ti basta aggiungere il codice seguente all'inizio del tuo metodo beforeAll
.
SharedConstants.createGameVersion();
Bootstrap.initialize();
INFO
Questa sezione suppone che stia usando il workflow GitHub Action standard incluso con la mod di esempio e con la mod modello.
I tuoi test ora verranno eseguiti ad ogni build, incluse quelle di fornitori CI come GitHub Actions. E se una build fallisce? Dovrai caricare i log come artifact per permetterci di vedere i report del test.
Aggiungi questo al tuo file .github/workflows/build.yml
, sotto alla fase ./gradlew build
.
- name: Store reports
if: failure()
uses: actions/upload-artifact@v4
with:
name: reports
path: |
**/build/reports/
**/build/test-results/