Skip to content

Commit

Permalink
add annotation based test system
Browse files Browse the repository at this point in the history
  • Loading branch information
OliverSchlueter committed Sep 4, 2024
1 parent 08c80a9 commit 633879b
Show file tree
Hide file tree
Showing 9 changed files with 226 additions and 92 deletions.
10 changes: 3 additions & 7 deletions src/main/java/de/oliver/fancynpcs/commands/FancyNpcsCMD.java
Original file line number Diff line number Diff line change
Expand Up @@ -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!");
Expand Down
109 changes: 109 additions & 0 deletions src/main/java/de/oliver/fancynpcs/tests/FNTestClass.java
Original file line number Diff line number Diff line change
@@ -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<Method> testMethods
) {

public static FNTestClass fromClass(Class<?> testClass) {
Method beforeEach = null;
Method afterEach = null;
List<Method> 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() + ")";
}

}
13 changes: 0 additions & 13 deletions src/main/java/de/oliver/fancynpcs/tests/FancyNpcsTest.java

This file was deleted.

42 changes: 11 additions & 31 deletions src/main/java/de/oliver/fancynpcs/tests/FancyNpcsTests.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,50 +5,30 @@
import java.util.ArrayList;
import java.util.List;

public class FancyNpcsTests implements FancyNpcsTest {
public class FancyNpcsTests {

private final List<FancyNpcsTest> tests;
private final List<FNTestClass> 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;
}
}
Original file line number Diff line number Diff line change
@@ -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 {
}
Original file line number Diff line number Diff line change
@@ -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 {
}

14 changes: 14 additions & 0 deletions src/main/java/de/oliver/fancynpcs/tests/annotations/FNTest.java
Original file line number Diff line number Diff line change
@@ -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;
}
48 changes: 25 additions & 23 deletions src/main/java/de/oliver/fancynpcs/tests/api/CreateNpcTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand All @@ -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);

Expand All @@ -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;
}


}
Loading

0 comments on commit 633879b

Please sign in to comment.