From fbbed233e3930ec744b992f9476a7feb4613d409 Mon Sep 17 00:00:00 2001 From: Vladyslava Kanivets Date: Thu, 19 Oct 2023 22:09:22 +0300 Subject: [PATCH 1/2] test description + timeoutCheck implemented --- src/main/java/com/test/junit/TestRunner.java | 54 ++++++++++++++++++- .../com/test/junit/anotation/TimeUnit.java | 15 ++++-- .../com/test/junit/anotation/Timeout.java | 7 +++ 3 files changed, 72 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/test/junit/TestRunner.java b/src/main/java/com/test/junit/TestRunner.java index f1ead61..bfa3c6b 100644 --- a/src/main/java/com/test/junit/TestRunner.java +++ b/src/main/java/com/test/junit/TestRunner.java @@ -4,7 +4,10 @@ import com.test.junit.anotation.AfterMethod; import com.test.junit.anotation.BeforeAll; import com.test.junit.anotation.BeforeMethod; +import com.test.junit.anotation.Description; import com.test.junit.anotation.Test; +import com.test.junit.anotation.TimeUnit; +import com.test.junit.anotation.Timeout; import com.test.junit.assertion.AssertionsRuntimeException; import java.lang.annotation.Annotation; @@ -14,6 +17,9 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeoutException; public class TestRunner { @@ -78,7 +84,8 @@ private static void invokeTestMethods(Object instance, List beforeEachMe try { method.setAccessible(true); invokeMethods(instance, beforeEachMethods); - method.invoke(instance); + printDescription(method); + invokeMethodTimed(instance, method); invokeMethods(instance, afterEachMethods); handleSunnyDayScenario(method); } catch (InvocationTargetException e) { @@ -86,6 +93,8 @@ private static void invokeTestMethods(Object instance, List beforeEachMe AssertionsRuntimeException ae = (AssertionsRuntimeException) e.getCause(); handleAssertionException(method, ae); } + } catch (TimeoutException e) { + handleTimedOutException(method, e.getMessage()); } catch (IllegalAccessException e) { throw new RuntimeException(e); } @@ -98,9 +107,52 @@ private static void handleAssertionException(Method method, AssertionsRuntimeExc System.out.println(ConsoleColors.RESET); } + private static void handleTimedOutException(Method method, String message) { + System.out.println(ConsoleColors.RED); + System.out.println(String.format("[Test method %s] is failed. Timed out. %s", method.getName(), message)); + System.out.println(ConsoleColors.RESET); + } + private static void handleSunnyDayScenario(Method method) { System.out.println(ConsoleColors.GREEN); System.out.println(String.format("[Test method %s] is successful", method.getName())); System.out.println(ConsoleColors.RESET); } + + private static void printDescription(Method method) { + if (method.isAnnotationPresent(Description.class)) { + Description description = method.getAnnotation(Description.class); + System.out.print(String.format("[Test method %s] detailed description: %s", method.getName(), description.message())); + } + } + + private static void invokeMethodTimed(Object instance, Method method) throws InvocationTargetException, IllegalAccessException, TimeoutException { + if (!method.isAnnotationPresent(Timeout.class)) { + method.invoke(instance); + } else { + long targetTime = method.getAnnotation(Timeout.class).time(); + TimeUnit timeUnit = method.getAnnotation(Timeout.class).timeUnit(); + ExecutorService executor = Executors.newSingleThreadExecutor(); + try { + executor.submit(() -> { + try { + method.invoke(instance); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + if (e.getCause() instanceof AssertionsRuntimeException) { + AssertionsRuntimeException ae = (AssertionsRuntimeException) e.getCause(); + handleAssertionException(method, ae); + } + } + }); + if (!executor.awaitTermination(targetTime, timeUnit.getTimeUnit())) { + executor.shutdownNow(); + throw new TimeoutException("Expected running time is " + targetTime + " " + timeUnit.name()); + } + } catch (InterruptedException e) { + throw new TimeoutException("Expected running time is " + targetTime + " " + timeUnit.name()); + } + } + } } diff --git a/src/main/java/com/test/junit/anotation/TimeUnit.java b/src/main/java/com/test/junit/anotation/TimeUnit.java index 84f3f58..9dc8357 100644 --- a/src/main/java/com/test/junit/anotation/TimeUnit.java +++ b/src/main/java/com/test/junit/anotation/TimeUnit.java @@ -1,8 +1,17 @@ package com.test.junit.anotation; public enum TimeUnit { - MILLISECOND, - SECONDS, + MILLISECOND (java.util.concurrent.TimeUnit.MILLISECONDS), + SECONDS(java.util.concurrent.TimeUnit.SECONDS), - MINUTES + MINUTES(java.util.concurrent.TimeUnit.MINUTES); + + java.util.concurrent.TimeUnit timeUnit; + TimeUnit(java.util.concurrent.TimeUnit timeUnit) { + this.timeUnit=timeUnit; + } + + public java.util.concurrent.TimeUnit getTimeUnit() { + return timeUnit; + } } diff --git a/src/main/java/com/test/junit/anotation/Timeout.java b/src/main/java/com/test/junit/anotation/Timeout.java index 5fc0c6c..bec9893 100644 --- a/src/main/java/com/test/junit/anotation/Timeout.java +++ b/src/main/java/com/test/junit/anotation/Timeout.java @@ -1,5 +1,12 @@ package com.test.junit.anotation; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.METHOD) +@Retention(RetentionPolicy.RUNTIME) public @interface Timeout { int time(); From 0d0e24a6cb2bc32683a95bd91bb02890e118ab86 Mon Sep 17 00:00:00 2001 From: Vladyslava Kanivets Date: Fri, 20 Oct 2023 10:32:55 +0300 Subject: [PATCH 2/2] exception throw --- src/main/java/com/test/junit/TestRunner.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/test/junit/TestRunner.java b/src/main/java/com/test/junit/TestRunner.java index bfa3c6b..807e879 100644 --- a/src/main/java/com/test/junit/TestRunner.java +++ b/src/main/java/com/test/junit/TestRunner.java @@ -137,13 +137,8 @@ private static void invokeMethodTimed(Object instance, Method method) throws Inv executor.submit(() -> { try { method.invoke(instance); - } catch (IllegalAccessException e) { + } catch (IllegalAccessException | InvocationTargetException e) { throw new RuntimeException(e); - } catch (InvocationTargetException e) { - if (e.getCause() instanceof AssertionsRuntimeException) { - AssertionsRuntimeException ae = (AssertionsRuntimeException) e.getCause(); - handleAssertionException(method, ae); - } } }); if (!executor.awaitTermination(targetTime, timeUnit.getTimeUnit())) { @@ -152,6 +147,12 @@ private static void invokeMethodTimed(Object instance, Method method) throws Inv } } catch (InterruptedException e) { throw new TimeoutException("Expected running time is " + targetTime + " " + timeUnit.name()); + } catch (RuntimeException e){ + if (e.getCause() instanceof InvocationTargetException){ + throw new InvocationTargetException(e); + } else { + throw new RuntimeException(e); + } } } }