diff --git a/src/main/java/de/oliver/fancynpcs/commands/FancyNpcsCMD.java b/src/main/java/de/oliver/fancynpcs/commands/FancyNpcsCMD.java index 7f48dfc6..6097eacb 100644 --- a/src/main/java/de/oliver/fancynpcs/commands/FancyNpcsCMD.java +++ b/src/main/java/de/oliver/fancynpcs/commands/FancyNpcsCMD.java @@ -23,19 +23,15 @@ public enum FancyNpcsCMD { @Permission("fancynpcs.command.fancynpcs.version") public void onVersion(final CommandSender sender) { plugin.getVersionConfig().checkVersionAndDisplay(sender, false); - - new FancyNpcsTests() - .addTest(new CreateNpcTest()) - .test((Player) sender); } @Command("fancynpcs test") @Permission("fancynpcs.command.fancynpcs.test") public void onTest(final Player player) { boolean tested = new FancyNpcsTests() - .addTest(new CreateNpcTest()) - .addTest(new CreateCMDTest()) - .test(player); + .addTest(CreateNpcTest.class) + .addTest(CreateCMDTest.class) + .runAllTests(player); if (tested) { player.sendMessage("Tested successfully!"); diff --git a/src/main/java/de/oliver/fancynpcs/tests/FNTestClass.java b/src/main/java/de/oliver/fancynpcs/tests/FNTestClass.java new file mode 100644 index 00000000..8f902ca3 --- /dev/null +++ b/src/main/java/de/oliver/fancynpcs/tests/FNTestClass.java @@ -0,0 +1,109 @@ +package de.oliver.fancynpcs.tests; + +import de.oliver.fancynpcs.tests.annotations.FNAfterEach; +import de.oliver.fancynpcs.tests.annotations.FNBeforeEach; +import de.oliver.fancynpcs.tests.annotations.FNTest; +import org.bukkit.entity.Player; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +public record FNTestClass( + Class testClass, + Method beforeEach, + Method afterEach, + List testMethods +) { + + public static FNTestClass fromClass(Class testClass) { + Method beforeEach = null; + Method afterEach = null; + List testMethods = new ArrayList<>(); + + for (Method method : testClass.getDeclaredMethods()) { + if (method.isAnnotationPresent(FNTest.class)) { + if (method.getParameterCount() != 1) continue; + if (method.getParameterTypes()[0] != Player.class) continue; + + testMethods.add(method); + continue; + } + + if (method.isAnnotationPresent(FNBeforeEach.class)) { + if (method.getParameterCount() != 1) continue; + if (method.getParameterTypes()[0] != Player.class) continue; + + beforeEach = method; + continue; + } + + if (method.isAnnotationPresent(FNAfterEach.class)) { + if (method.getParameterCount() != 1) continue; + if (method.getParameterTypes()[0] != Player.class) continue; + + afterEach = method; + } + } + + return new FNTestClass(testClass, beforeEach, afterEach, testMethods); + } + + public boolean runTests(Player player) { + for (Method testMethod : testMethods) { + Object testClassObj; + try { + testClassObj = testClass.getDeclaredConstructor().newInstance(); + } catch (Exception e) { + System.out.println("Failed to create test class instance: " + e.getMessage()); + player.sendMessage("Failed to create test class instance: " + e.getMessage()); + e.printStackTrace(); + return false; + } + + FNTest fnTest = testMethod.getAnnotation(FNTest.class); + if (fnTest.skip()) { + System.out.println("Skipping test " + displayName(testMethod)); + player.sendMessage("Skipping test " + displayName(testMethod)); + continue; + } + + + long testStart = System.currentTimeMillis(); + + try { + if (beforeEach != null) beforeEach.invoke(testClassObj, player); + + testMethod.invoke(testClassObj, player); + + if (afterEach != null) afterEach.invoke(testClassObj, player); + } catch (InvocationTargetException e) { + System.out.println("Test " + displayName(testMethod) + " failed with exception: " + e.getCause().getMessage()); + player.sendMessage("Test " + displayName(testMethod) + " failed with exception: " + e.getCause().getMessage()); + e.getCause().printStackTrace(); + return false; + } catch (Exception e) { + System.out.println("Unexpected exception in test " + fnTest.name() + ": " + e.getMessage()); + e.printStackTrace(); + return false; + } + + long testEnd = System.currentTimeMillis(); + System.out.println("Test " + displayName(testMethod) + " took " + (testEnd - testStart) + "ms"); + player.sendMessage("Test " + displayName(testMethod) + " took " + (testEnd - testStart) + "ms"); + } + + return true; + } + + public String displayName(Method m) { + if (!m.isAnnotationPresent(FNTest.class)) { + return testClass.getSimpleName() + "#" + m.getName(); + } + + FNTest fnTest = m.getAnnotation(FNTest.class); + return testClass.getSimpleName() + "#" + m.getName() + " (" + fnTest.name() + ")"; + } + +} diff --git a/src/main/java/de/oliver/fancynpcs/tests/FancyNpcsTest.java b/src/main/java/de/oliver/fancynpcs/tests/FancyNpcsTest.java deleted file mode 100644 index a579d590..00000000 --- a/src/main/java/de/oliver/fancynpcs/tests/FancyNpcsTest.java +++ /dev/null @@ -1,13 +0,0 @@ -package de.oliver.fancynpcs.tests; - -import org.bukkit.entity.Player; - -public interface FancyNpcsTest { - - boolean before(Player player); - - boolean test(Player player); - - boolean after(Player player); - -} diff --git a/src/main/java/de/oliver/fancynpcs/tests/FancyNpcsTests.java b/src/main/java/de/oliver/fancynpcs/tests/FancyNpcsTests.java index 51682c9e..47823a2a 100644 --- a/src/main/java/de/oliver/fancynpcs/tests/FancyNpcsTests.java +++ b/src/main/java/de/oliver/fancynpcs/tests/FancyNpcsTests.java @@ -5,50 +5,30 @@ import java.util.ArrayList; import java.util.List; -public class FancyNpcsTests implements FancyNpcsTest { +public class FancyNpcsTests { - private final List tests; + private final List tests = new ArrayList<>(); public FancyNpcsTests() { - this.tests = new ArrayList<>(); - } - public FancyNpcsTests addTest(FancyNpcsTest test) { - tests.add(test); - return this; } - - @Override - public boolean before(Player player) { - return true; + public FancyNpcsTests addTest(Class testClass) { + tests.add(FNTestClass.fromClass(testClass)); + return this; } - @Override - public boolean test(Player player) { - for (FancyNpcsTest test : tests) { - long testStart = System.currentTimeMillis(); - + public boolean runAllTests(Player player) { + for (FNTestClass test : tests) { + System.out.println("Running tests for " + test.testClass().getSimpleName()); try { - if (!test.before(player)) return false; - if (!test.test(player)) return false; - if (!test.after(player)) return false; + if (!test.runTests(player)) { + return false; + } } catch (Exception e) { - System.out.println("Test " + test.getClass().getSimpleName() + " failed with exception: " + e.getMessage()); - player.sendMessage("Test " + test.getClass().getSimpleName() + " failed with exception: " + e.getMessage()); - e.printStackTrace(); return false; } - - long testEnd = System.currentTimeMillis(); - System.out.println("Test " + test.getClass().getSimpleName() + " took " + (testEnd - testStart) + "ms"); - player.sendMessage("Test " + test.getClass().getSimpleName() + " took " + (testEnd - testStart) + "ms"); } return true; } - - @Override - public boolean after(Player player) { - return true; - } } diff --git a/src/main/java/de/oliver/fancynpcs/tests/annotations/FNAfterEach.java b/src/main/java/de/oliver/fancynpcs/tests/annotations/FNAfterEach.java new file mode 100644 index 00000000..997a0e14 --- /dev/null +++ b/src/main/java/de/oliver/fancynpcs/tests/annotations/FNAfterEach.java @@ -0,0 +1,11 @@ +package de.oliver.fancynpcs.tests.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface FNAfterEach { +} diff --git a/src/main/java/de/oliver/fancynpcs/tests/annotations/FNBeforeEach.java b/src/main/java/de/oliver/fancynpcs/tests/annotations/FNBeforeEach.java new file mode 100644 index 00000000..6ab0a228 --- /dev/null +++ b/src/main/java/de/oliver/fancynpcs/tests/annotations/FNBeforeEach.java @@ -0,0 +1,12 @@ +package de.oliver.fancynpcs.tests.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface FNBeforeEach { +} + diff --git a/src/main/java/de/oliver/fancynpcs/tests/annotations/FNTest.java b/src/main/java/de/oliver/fancynpcs/tests/annotations/FNTest.java new file mode 100644 index 00000000..0df857a9 --- /dev/null +++ b/src/main/java/de/oliver/fancynpcs/tests/annotations/FNTest.java @@ -0,0 +1,14 @@ +package de.oliver.fancynpcs.tests.annotations; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Retention(RetentionPolicy.RUNTIME) +@Target(ElementType.METHOD) +public @interface FNTest { + String name(); + + boolean skip() default false; +} diff --git a/src/main/java/de/oliver/fancynpcs/tests/api/CreateNpcTest.java b/src/main/java/de/oliver/fancynpcs/tests/api/CreateNpcTest.java index 9b552eda..ea5a2a6a 100644 --- a/src/main/java/de/oliver/fancynpcs/tests/api/CreateNpcTest.java +++ b/src/main/java/de/oliver/fancynpcs/tests/api/CreateNpcTest.java @@ -4,13 +4,15 @@ import de.oliver.fancynpcs.api.Npc; import de.oliver.fancynpcs.api.NpcData; import de.oliver.fancynpcs.api.NpcManager; -import de.oliver.fancynpcs.tests.FancyNpcsTest; +import de.oliver.fancynpcs.tests.annotations.FNAfterEach; +import de.oliver.fancynpcs.tests.annotations.FNBeforeEach; +import de.oliver.fancynpcs.tests.annotations.FNTest; import org.bukkit.Location; import org.bukkit.entity.Player; import java.util.UUID; -public class CreateNpcTest implements FancyNpcsTest { +public class CreateNpcTest { private static final NpcManager NPC_MANAGER = FancyNpcsPlugin.get().getNpcManager(); @@ -20,16 +22,29 @@ public class CreateNpcTest implements FancyNpcsTest { private Npc createdNpc; - @Override - public boolean before(Player player) { - this.npcName = "test-" + UUID.randomUUID().toString().substring(0, 8); - this.creatorUUID = player.getUniqueId(); - this.location = player.getLocation().clone(); - return true; + @FNBeforeEach + public void setUp(Player player) { + npcName = "test-" + UUID.randomUUID().toString().substring(0, 8); + creatorUUID = player.getUniqueId(); + location = player.getLocation().clone(); + createdNpc = null; } - @Override - public boolean test(Player player) { + @FNAfterEach + public void tearDown(Player player) { + NPC_MANAGER.removeNpc(createdNpc); + if (NPC_MANAGER.getNpc(npcName) != null) { + throw new IllegalStateException("Npc was not removed"); + } + + createdNpc = null; + npcName = null; + creatorUUID = null; + location = null; + } + + @FNTest(name = "Create and register npc") + public void createAndRegisterNpc(Player player) { NpcData data = new NpcData(npcName, creatorUUID, location); createdNpc = FancyNpcsPlugin.get().getNpcAdapter().apply(data); @@ -48,19 +63,6 @@ public boolean test(Player player) { if (NPC_MANAGER.getNpc(npcName) == null) { throw new IllegalStateException("Npc was not created"); } - - return true; - } - - @Override - public boolean after(Player player) { - NPC_MANAGER.removeNpc(createdNpc); - if (NPC_MANAGER.getNpc(npcName) != null) { - throw new IllegalStateException("Npc was not removed"); - } - - return true; } - } diff --git a/src/main/java/de/oliver/fancynpcs/tests/commands/CreateCMDTest.java b/src/main/java/de/oliver/fancynpcs/tests/commands/CreateCMDTest.java index 62a769a4..090e247d 100644 --- a/src/main/java/de/oliver/fancynpcs/tests/commands/CreateCMDTest.java +++ b/src/main/java/de/oliver/fancynpcs/tests/commands/CreateCMDTest.java @@ -3,26 +3,41 @@ import de.oliver.fancynpcs.api.FancyNpcsPlugin; import de.oliver.fancynpcs.api.Npc; import de.oliver.fancynpcs.api.NpcManager; -import de.oliver.fancynpcs.commands.npc.CreateCMD; -import de.oliver.fancynpcs.tests.FancyNpcsTest; +import de.oliver.fancynpcs.tests.annotations.FNAfterEach; +import de.oliver.fancynpcs.tests.annotations.FNBeforeEach; +import de.oliver.fancynpcs.tests.annotations.FNTest; +import org.bukkit.entity.EntityType; import org.bukkit.entity.Player; -public class CreateCMDTest implements FancyNpcsTest { +public class CreateCMDTest { private static final NpcManager NPC_MANAGER = FancyNpcsPlugin.get().getNpcManager(); private String npcName; private Npc createdNpc; - @Override - public boolean before(Player player) { - this.npcName = "test-" + player.getUniqueId().toString().substring(0, 8); - return true; + @FNBeforeEach + public void setUp(Player player) { + npcName = "test-" + player.getUniqueId().toString().substring(0, 8); + createdNpc = null; } - @Override - public boolean test(Player player) { - CreateCMD.INSTANCE.onCreate(player, npcName, null, null, null); + @FNAfterEach + public void tearDown(Player player) { + NPC_MANAGER.removeNpc(createdNpc); + if (NPC_MANAGER.getNpc(npcName) != null) { + throw new IllegalStateException("Npc was not removed"); + } + + createdNpc = null; + npcName = null; + } + + @FNTest(name = "Create npc") + public void createNpc(Player player) { + if (!player.performCommand("npc create " + npcName)) { + throw new IllegalStateException("Command failed"); + } createdNpc = NPC_MANAGER.getNpc(npcName); if (createdNpc == null) { @@ -32,17 +47,25 @@ public boolean test(Player player) { if (createdNpc.getEntityId() < 0) { throw new IllegalStateException("Npc entity was not created"); } - - return true; } - @Override - public boolean after(Player player) { - NPC_MANAGER.removeNpc(createdNpc); - if (NPC_MANAGER.getNpc(npcName) != null) { - throw new IllegalStateException("Npc was not removed"); + @FNTest(name = "Create npc with type") + public void createNpcWithType(Player player) { + if (!player.performCommand("npc create " + npcName + " --type PIG")) { + throw new IllegalStateException("Command failed"); + } + + createdNpc = NPC_MANAGER.getNpc(npcName); + if (createdNpc == null) { + throw new IllegalStateException("Npc was not created"); } - return true; + if (createdNpc.getEntityId() < 0) { + throw new IllegalStateException("Npc entity was not created"); + } + + if (createdNpc.getData().getType() != EntityType.PIG) { + throw new IllegalStateException("Npc entity type is not correct"); + } } }