From d9854eb9c5075e9124b742e9dcd7de7d0eb8f4c1 Mon Sep 17 00:00:00 2001 From: alyokhina-olya Date: Sun, 20 May 2018 23:42:17 +0300 Subject: [PATCH 1/4] first commit --- .travis.yml | 7 +++++++ 05.XUnit/pom.xml | 12 ++++++++++++ .../spbau/mit/alyokhina/annotation/After.java | 12 ++++++++++++ .../mit/alyokhina/annotation/AfterClass.java | 11 +++++++++++ .../spbau/mit/alyokhina/annotation/Before.java | 11 +++++++++++ .../mit/alyokhina/annotation/BeforeClass.java | 12 ++++++++++++ .../ru/spbau/mit/alyokhina/annotation/Test.java | 17 +++++++++++++++++ buildscript.sh | 9 +++++++++ 8 files changed, 91 insertions(+) create mode 100644 .travis.yml create mode 100644 05.XUnit/pom.xml create mode 100644 05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/After.java create mode 100644 05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/AfterClass.java create mode 100644 05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/Before.java create mode 100644 05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/BeforeClass.java create mode 100644 05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/Test.java create mode 100755 buildscript.sh diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..6b8dde0 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,7 @@ +language: java +jdk: + - oraclejdk8 +os: + - linux +script: + - chmod +x buildscript.sh && ./buildscript.sh diff --git a/05.XUnit/pom.xml b/05.XUnit/pom.xml new file mode 100644 index 0000000..a562ccf --- /dev/null +++ b/05.XUnit/pom.xml @@ -0,0 +1,12 @@ + + + 4.0.0 + + XUnit + XUnit + 1.0-SNAPSHOT + + + \ No newline at end of file diff --git a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/After.java b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/After.java new file mode 100644 index 0000000..6fda24e --- /dev/null +++ b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/After.java @@ -0,0 +1,12 @@ +package ru.spbau.mit.alyokhina.annotation; + +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 After { +} diff --git a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/AfterClass.java b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/AfterClass.java new file mode 100644 index 0000000..60257e2 --- /dev/null +++ b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/AfterClass.java @@ -0,0 +1,11 @@ +package ru.spbau.mit.alyokhina.annotation; + +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 AfterClass { +} diff --git a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/Before.java b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/Before.java new file mode 100644 index 0000000..7519005 --- /dev/null +++ b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/Before.java @@ -0,0 +1,11 @@ +package ru.spbau.mit.alyokhina.annotation; + +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 Before { +} diff --git a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/BeforeClass.java b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/BeforeClass.java new file mode 100644 index 0000000..c15ba63 --- /dev/null +++ b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/BeforeClass.java @@ -0,0 +1,12 @@ +package ru.spbau.mit.alyokhina.annotation; + +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 BeforeClass { +} diff --git a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/Test.java b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/Test.java new file mode 100644 index 0000000..b3ea65b --- /dev/null +++ b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/Test.java @@ -0,0 +1,17 @@ +package ru.spbau.mit.alyokhina.annotation; + +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 Test { + String ignore() default ""; + + Class expected() default IgnoredThrowable.class; + + class IgnoredThrowable extends Throwable { + } +} diff --git a/buildscript.sh b/buildscript.sh new file mode 100755 index 0000000..1cc07e7 --- /dev/null +++ b/buildscript.sh @@ -0,0 +1,9 @@ +#!/bin/bash +files=$(find . -maxdepth 1 -type d | grep "./0.*") +for file in $files +do + cd $file + mvn test -B + cd ../ +done + From 89fc93c0e6a0b24654aa69cd56d1b8111383dff8 Mon Sep 17 00:00:00 2001 From: alyokhina-olya Date: Mon, 21 May 2018 23:07:53 +0300 Subject: [PATCH 2/4] add run tests --- 05.XUnit/pom.xml | 19 +++ .../java/ru/spbau/mit/alyokhina/Main.java | 42 +++++ .../ru/spbau/mit/alyokhina/TestExecutor.java | 145 ++++++++++++++++++ .../ru/spbau/mit/alyokhina/TestResult.java | 10 ++ 4 files changed, 216 insertions(+) create mode 100644 05.XUnit/src/main/java/ru/spbau/mit/alyokhina/Main.java create mode 100644 05.XUnit/src/main/java/ru/spbau/mit/alyokhina/TestExecutor.java create mode 100644 05.XUnit/src/main/java/ru/spbau/mit/alyokhina/TestResult.java diff --git a/05.XUnit/pom.xml b/05.XUnit/pom.xml index a562ccf..a08fa59 100644 --- a/05.XUnit/pom.xml +++ b/05.XUnit/pom.xml @@ -7,6 +7,25 @@ XUnit XUnit 1.0-SNAPSHOT + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.8 + 1.8 + + + + + + + junit + junit + 4.12 + + \ No newline at end of file diff --git a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/Main.java b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/Main.java new file mode 100644 index 0000000..1351973 --- /dev/null +++ b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/Main.java @@ -0,0 +1,42 @@ +package ru.spbau.mit.alyokhina; + +import java.util.List; + +public class Main { + public static void main(String[] args) throws Exception { + if (args.length != 1) { + System.out.println("Expected class name"); + return; + } + TestExecutor testExecutor = new TestExecutor(Class.forName(args[0])); + List results = testExecutor.run(); + int all = 0, success = 0, fail = 0, ignored = 0; + for (TestResult testResult : results) { + System.out.print("Class: " + testResult.getClassName() + ", Test: " + testResult.getTestName() + ", Time: " + ((Long)testResult.getTime()).toString()); + all++; + if (testResult.isFail()) { + fail++; + System.out.print(" -- Failed: "); + if (testResult.getException()!= null) { + System.out.println(testResult.getException().getMessage()); + } + else { + System.out.println("Expected exception not received"); + } + } + else { + if (testResult.causeOfIgnoring().equals("")) { + success++; + System.out.println(" -- Success"); + } + else { + ignored++; + System.out.println(" -- Ignored: " + testResult.causeOfIgnoring()); + } + } + System.out.println("All: " + ((Integer)all).toString() + ", success: " + ((Integer)success).toString() + + ", fail: " + ((Integer)fail).toString() + ", ignored: " + ((Integer)ignored).toString()); + } + } + +} diff --git a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/TestExecutor.java b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/TestExecutor.java new file mode 100644 index 0000000..1b7673a --- /dev/null +++ b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/TestExecutor.java @@ -0,0 +1,145 @@ +package ru.spbau.mit.alyokhina; + +import ru.spbau.mit.alyokhina.annotation.*; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.List; + +public class TestExecutor { + private Object instance; + private String testClassName; + private List before = new ArrayList<>(); + private List beforeClass = new ArrayList<>(); + private List after = new ArrayList<>(); + private List afterClass = new ArrayList<>(); + private List tests = new ArrayList<>(); + + + public TestExecutor(Class clazz) throws IllegalAccessException, InstantiationException { + getMethods(clazz); + instance = clazz.newInstance(); + testClassName = clazz.getName(); + } + + + public List run() throws InvocationTargetException, IllegalAccessException { + List results = new ArrayList<>(); + if (beforeClass.size() != 0) { + beforeClass.get(0).invoke(instance); + } + + for (Method method : tests) { + method.setAccessible(true); + results.add(invoke(method)); + } + + if (afterClass.size() != 0) { + afterClass.get(0).invoke(instance); + } + + return results; + } + + + private TestResult getResult(final long time, final String className, final String testName, + final boolean isFail, final String causeOfIgnoring, final Exception e) { + return new TestResult() { + @Override + public long getTime() { + return time; + } + + @Override + public String getClassName() { + return className; + } + + @Override + public String getTestName() { + return testName; + } + + @Override + public boolean isFail() { + return isFail; + } + + @Override + public String causeOfIgnoring() { + return causeOfIgnoring; + } + + @Override + public Exception getException() { + return e; + } + + }; + } + + + private TestResult invoke(final Method method) throws IllegalAccessException { + final Test testAnnotation = method.getAnnotation(Test.class); + + if (!testAnnotation.ignore().equals("")) { + return getResult(0, testClassName, method.getName(), false, testAnnotation.ignore(), null); + } + + long startTimer = System.currentTimeMillis(); + Exception exception = null; + try { + if (before.size() != 0) { + before.get(0).invoke(instance); + } + method.invoke(instance); + + if (after.size() != 0) { + after.get(0).invoke(instance); + } + } catch (InvocationTargetException e) { + exception = (Exception) e.getCause(); + } + long endTimer = System.currentTimeMillis(); + + if ((exception != null && !testAnnotation.expected().isInstance(exception)) || + (exception == null && !testAnnotation.expected().equals(Test.IgnoredThrowable.class))) { + return getResult(endTimer - startTimer, testClassName, method.getName(), true, "", exception); + } + + return getResult(endTimer - startTimer, testClassName, method.getName(), false, "", exception); + + } + + private void getMethods(Class testClazz) { + Class[] classes = {After.class, AfterClass.class, Before.class, BeforeClass.class, Test.class}; + List> lists = new ArrayList<>(); + lists.add(after); + lists.add(afterClass); + lists.add(before); + lists.add(beforeClass); + lists.add(tests); + for (Method method : testClazz.getDeclaredMethods()) { + boolean flag = false; + for (int i = 0; i < classes.length; i++) { + if (method.getAnnotation(classes[i]) != null) { + if (flag) { + //ERROR + System.out.println("ERROR"); + } + lists.get(i).add(method); + flag = true; + } + } + } + for (int i = 0; i < lists.size() - 1; i++) { + if (lists.get(i).size() > 1) { + //ERROR + System.out.println("ERROR"); + } + } + } + + +} diff --git a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/TestResult.java b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/TestResult.java new file mode 100644 index 0000000..f4e6aac --- /dev/null +++ b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/TestResult.java @@ -0,0 +1,10 @@ +package ru.spbau.mit.alyokhina; + +public interface TestResult { + long getTime(); + String getClassName(); + String getTestName(); + boolean isFail(); + String causeOfIgnoring(); + Exception getException(); +} From 9465054ab2f9697b8883f06efcbb7bc0995d5e0a Mon Sep 17 00:00:00 2001 From: alyokhina-olya Date: Tue, 22 May 2018 00:05:46 +0300 Subject: [PATCH 3/4] add tests --- .../ru/spbau/mit/alyokhina/TestExecutor.java | 4 + .../alyokhina/ClassForTests/TestIgnored.java | 33 +++++++ .../ClassForTests/TestWithBeforeAndAfter.java | 32 +++++++ .../TestWithBeforeClassAndAfterClass.java | 31 ++++++ .../ClassForTests/TestWithException.java | 32 +++++++ .../spbau/mit/alyokhina/TestExecutorTest.java | 94 +++++++++++++++++++ 6 files changed, 226 insertions(+) create mode 100644 05.XUnit/src/test/java/ru/spbau/mit/alyokhina/ClassForTests/TestIgnored.java create mode 100644 05.XUnit/src/test/java/ru/spbau/mit/alyokhina/ClassForTests/TestWithBeforeAndAfter.java create mode 100644 05.XUnit/src/test/java/ru/spbau/mit/alyokhina/ClassForTests/TestWithBeforeClassAndAfterClass.java create mode 100644 05.XUnit/src/test/java/ru/spbau/mit/alyokhina/ClassForTests/TestWithException.java create mode 100644 05.XUnit/src/test/java/ru/spbau/mit/alyokhina/TestExecutorTest.java diff --git a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/TestExecutor.java b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/TestExecutor.java index 1b7673a..91284ca 100644 --- a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/TestExecutor.java +++ b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/TestExecutor.java @@ -27,6 +27,7 @@ public TestExecutor(Class clazz) throws IllegalAccessException, Instantiation public List run() throws InvocationTargetException, IllegalAccessException { List results = new ArrayList<>(); if (beforeClass.size() != 0) { + beforeClass.get(0).setAccessible(true); beforeClass.get(0).invoke(instance); } @@ -36,6 +37,7 @@ public List run() throws InvocationTargetException, IllegalAccessExc } if (afterClass.size() != 0) { + afterClass.get(0).setAccessible(true); afterClass.get(0).invoke(instance); } @@ -91,11 +93,13 @@ private TestResult invoke(final Method method) throws IllegalAccessException { Exception exception = null; try { if (before.size() != 0) { + before.get(0).setAccessible(true); before.get(0).invoke(instance); } method.invoke(instance); if (after.size() != 0) { + after.get(0).setAccessible(true); after.get(0).invoke(instance); } } catch (InvocationTargetException e) { diff --git a/05.XUnit/src/test/java/ru/spbau/mit/alyokhina/ClassForTests/TestIgnored.java b/05.XUnit/src/test/java/ru/spbau/mit/alyokhina/ClassForTests/TestIgnored.java new file mode 100644 index 0000000..419774b --- /dev/null +++ b/05.XUnit/src/test/java/ru/spbau/mit/alyokhina/ClassForTests/TestIgnored.java @@ -0,0 +1,33 @@ +package ru.spbau.mit.alyokhina.ClassForTests; + +import ru.spbau.mit.alyokhina.annotation.Test; + +import java.io.IOException; + +public class TestIgnored { + static int count = 0; + @Test(ignore = "I want and I ignore") + protected void test1() { + count++; + throw new NullPointerException(); + } + + @Test(ignore = "And this test I ignore") + void test2() { + count++; + throw new NullPointerException(); + } + + @Test(ignore = "And this", expected = NullPointerException.class) + private void test3() { + count++; + throw new NullPointerException(); + } + + @Test( expected = IOException.class, ignore = "And this I don't like") + public void test4() { + count++; + throw new NullPointerException(); + } + +} diff --git a/05.XUnit/src/test/java/ru/spbau/mit/alyokhina/ClassForTests/TestWithBeforeAndAfter.java b/05.XUnit/src/test/java/ru/spbau/mit/alyokhina/ClassForTests/TestWithBeforeAndAfter.java new file mode 100644 index 0000000..88eb263 --- /dev/null +++ b/05.XUnit/src/test/java/ru/spbau/mit/alyokhina/ClassForTests/TestWithBeforeAndAfter.java @@ -0,0 +1,32 @@ +package ru.spbau.mit.alyokhina.ClassForTests; + +import ru.spbau.mit.alyokhina.annotation.*; + + +public class TestWithBeforeAndAfter { + public static int countBefore = 0, countAfter = 0; + @Before + void before() { + countBefore++; + } + + @After + void after() { + countAfter++; + } + + @Test + void test1() { + throw new NullPointerException(); + } + + @Test + void test2() { + int x = 1; + } + + @Test + void test3() { + int x = 1; + } +} diff --git a/05.XUnit/src/test/java/ru/spbau/mit/alyokhina/ClassForTests/TestWithBeforeClassAndAfterClass.java b/05.XUnit/src/test/java/ru/spbau/mit/alyokhina/ClassForTests/TestWithBeforeClassAndAfterClass.java new file mode 100644 index 0000000..e14a6fc --- /dev/null +++ b/05.XUnit/src/test/java/ru/spbau/mit/alyokhina/ClassForTests/TestWithBeforeClassAndAfterClass.java @@ -0,0 +1,31 @@ +package ru.spbau.mit.alyokhina.ClassForTests; + +import ru.spbau.mit.alyokhina.annotation.*; + +public class TestWithBeforeClassAndAfterClass { + public static int countBeforeClass = 0, countAfterClass = 0; + @BeforeClass + void before() { + countBeforeClass++; + } + + @AfterClass + void after() { + countAfterClass++; + } + + @Test + void test1() { + throw new NullPointerException(); + } + + @Test + void test2() { + int x = 1; + } + + @Test + void test3() { + int x = 1; + } +} diff --git a/05.XUnit/src/test/java/ru/spbau/mit/alyokhina/ClassForTests/TestWithException.java b/05.XUnit/src/test/java/ru/spbau/mit/alyokhina/ClassForTests/TestWithException.java new file mode 100644 index 0000000..595b174 --- /dev/null +++ b/05.XUnit/src/test/java/ru/spbau/mit/alyokhina/ClassForTests/TestWithException.java @@ -0,0 +1,32 @@ +package ru.spbau.mit.alyokhina.ClassForTests; + +import ru.spbau.mit.alyokhina.annotation.Test; + +import java.io.IOException; + +public class TestWithException { + + @Test + private void test1() { + throw new NullPointerException(); + } + + @Test(expected = NullPointerException.class) + private void test2() { + throw new NullPointerException(); + } + + @Test(expected = IOException.class) + private void test3() { + throw new NullPointerException(); + } + + @Test(expected = NullPointerException.class) + private void test4() { + } + + @Test + private void test5() { + + } +} diff --git a/05.XUnit/src/test/java/ru/spbau/mit/alyokhina/TestExecutorTest.java b/05.XUnit/src/test/java/ru/spbau/mit/alyokhina/TestExecutorTest.java new file mode 100644 index 0000000..c2264a6 --- /dev/null +++ b/05.XUnit/src/test/java/ru/spbau/mit/alyokhina/TestExecutorTest.java @@ -0,0 +1,94 @@ +package ru.spbau.mit.alyokhina; + +import org.junit.Test; + +import java.lang.reflect.InvocationTargetException; +import java.util.Comparator; +import java.util.List; + +import ru.spbau.mit.alyokhina.ClassForTests.TestWithBeforeAndAfter; +import ru.spbau.mit.alyokhina.ClassForTests.TestWithBeforeClassAndAfterClass; + +import static org.junit.Assert.*; + +public class TestExecutorTest { + + @Test + public void testWithBeforeAndAfter() throws ClassNotFoundException, InvocationTargetException, + IllegalAccessException, InstantiationException { + TestExecutor testExecutor = new TestExecutor(Class.forName("ru.spbau.mit.alyokhina.ClassForTests.TestWithBeforeAndAfter")); + List results = testExecutor.run(); + assertEquals(3, results.size()); + assertEquals(3, TestWithBeforeAndAfter.countBefore); + assertEquals(2, TestWithBeforeAndAfter.countAfter); + } + + @Test + public void testWithBeforeClassAndAfterClass() throws ClassNotFoundException, InvocationTargetException, + IllegalAccessException, InstantiationException { + TestExecutor testExecutor = new TestExecutor(Class.forName("ru.spbau.mit.alyokhina.ClassForTests.TestWithBeforeClassAndAfterClass")); + List results = testExecutor.run(); + assertEquals(3, results.size()); + assertEquals(1, TestWithBeforeClassAndAfterClass.countBeforeClass); + assertEquals(1, TestWithBeforeClassAndAfterClass.countAfterClass); + + } + + @Test + public void testWithException() throws ClassNotFoundException, InvocationTargetException, + IllegalAccessException, InstantiationException { + TestExecutor testExecutor = new TestExecutor(Class.forName("ru.spbau.mit.alyokhina.ClassForTests.TestWithException")); + List results = testExecutor.run(); + assertEquals(5, results.size()); + results.sort(Comparator.comparing(TestResult::getTestName)); + + assertEquals("test1", results.get(0).getTestName()); + assertEquals(true, results.get(0).isFail()); + assertTrue(results.get(0).getException() instanceof NullPointerException); + assertTrue(results.get(0).causeOfIgnoring().equals("")); + + assertEquals("test2", results.get(1).getTestName()); + assertEquals(false, results.get(1).isFail()); + assertTrue(results.get(1).getException() instanceof NullPointerException); + assertTrue(results.get(1).causeOfIgnoring().equals("")); + + assertEquals("test3", results.get(2).getTestName()); + assertEquals(true, results.get(2).isFail()); + assertTrue(results.get(2).getException() instanceof NullPointerException); + assertTrue(results.get(2).causeOfIgnoring().equals("")); + + assertEquals("test4", results.get(3).getTestName()); + assertEquals(true, results.get(3).isFail()); + assertTrue(results.get(3).getException() == null); + assertTrue(results.get(3).causeOfIgnoring().equals("")); + + assertEquals("test5", results.get(4).getTestName()); + assertEquals(false, results.get(4).isFail()); + assertTrue(results.get(4).getException() == null); + assertTrue(results.get(4).causeOfIgnoring().equals("")); + } + + @Test + public void testWithIgnore() throws ClassNotFoundException, InvocationTargetException, + IllegalAccessException, InstantiationException { + TestExecutor testExecutor = new TestExecutor(Class.forName("ru.spbau.mit.alyokhina.ClassForTests.TestIgnored")); + List results = testExecutor.run(); + assertEquals(4, results.size()); + results.sort(Comparator.comparing(TestResult::getTestName)); + + assertEquals("test1", results.get(0).getTestName()); + assertFalse(results.get(0).causeOfIgnoring().equals("")); + + assertEquals("test2", results.get(1).getTestName()); + assertFalse(results.get(1).causeOfIgnoring().equals("")); + + assertEquals("test3", results.get(2).getTestName()); + assertFalse(results.get(2).causeOfIgnoring().equals("")); + + assertEquals("test4", results.get(3).getTestName()); + assertFalse(results.get(3).causeOfIgnoring().equals("")); + + + } + +} \ No newline at end of file From f320a931f7c60918cf7b72499db3e6e2f08b9786 Mon Sep 17 00:00:00 2001 From: alyokhina-olya Date: Tue, 22 May 2018 01:31:17 +0300 Subject: [PATCH 4/4] add javadoc and exceptions --- .../java/ru/spbau/mit/alyokhina/Main.java | 66 +++++++++++-------- .../ru/spbau/mit/alyokhina/TestExecutor.java | 58 ++++++++++++++-- .../mit/alyokhina/TestExecutorException.java | 11 ++++ .../ru/spbau/mit/alyokhina/TestResult.java | 12 ++++ .../spbau/mit/alyokhina/annotation/After.java | 2 +- .../mit/alyokhina/annotation/AfterClass.java | 1 + .../mit/alyokhina/annotation/Before.java | 1 + .../mit/alyokhina/annotation/BeforeClass.java | 2 +- .../spbau/mit/alyokhina/annotation/Test.java | 4 ++ .../spbau/mit/alyokhina/TestExecutorTest.java | 8 +-- 10 files changed, 126 insertions(+), 39 deletions(-) create mode 100644 05.XUnit/src/main/java/ru/spbau/mit/alyokhina/TestExecutorException.java diff --git a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/Main.java b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/Main.java index 1351973..550b056 100644 --- a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/Main.java +++ b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/Main.java @@ -1,41 +1,53 @@ package ru.spbau.mit.alyokhina; +import java.lang.reflect.InvocationTargetException; import java.util.List; + +/** + * Class for print tests results + */ public class Main { - public static void main(String[] args) throws Exception { + /** + * print result + * @param args class name + */ + public static void main(String[] args) { if (args.length != 1) { System.out.println("Expected class name"); return; } - TestExecutor testExecutor = new TestExecutor(Class.forName(args[0])); - List results = testExecutor.run(); - int all = 0, success = 0, fail = 0, ignored = 0; - for (TestResult testResult : results) { - System.out.print("Class: " + testResult.getClassName() + ", Test: " + testResult.getTestName() + ", Time: " + ((Long)testResult.getTime()).toString()); - all++; - if (testResult.isFail()) { - fail++; - System.out.print(" -- Failed: "); - if (testResult.getException()!= null) { - System.out.println(testResult.getException().getMessage()); - } - else { - System.out.println("Expected exception not received"); - } - } - else { - if (testResult.causeOfIgnoring().equals("")) { - success++; - System.out.println(" -- Success"); - } - else { - ignored++; - System.out.println(" -- Ignored: " + testResult.causeOfIgnoring()); + try { + TestExecutor testExecutor = new TestExecutor(Class.forName(args[0])); + + List results = testExecutor.run(); + int all = 0, success = 0, fail = 0, ignored = 0; + for (TestResult testResult : results) { + System.out.print("Class: " + testResult.getClassName() + ", Test: " + testResult.getTestName() + ", Time: " + ((Long) testResult.getTime()).toString()); + all++; + if (testResult.isFail()) { + fail++; + System.out.print(" -- Failed: "); + if (testResult.getException() != null) { + System.out.println(testResult.getException().getMessage()); + } else { + System.out.println("Expected exception not received"); + } + } else { + if (testResult.causeOfIgnoring().equals("")) { + success++; + System.out.println(" -- Success"); + } else { + ignored++; + System.out.println(" -- Ignored: " + testResult.causeOfIgnoring()); + } } + System.out.println("All: " + ((Integer) all).toString() + ", success: " + ((Integer) success).toString() + + ", fail: " + ((Integer) fail).toString() + ", ignored: " + ((Integer) ignored).toString()); } - System.out.println("All: " + ((Integer)all).toString() + ", success: " + ((Integer)success).toString() + - ", fail: " + ((Integer)fail).toString() + ", ignored: " + ((Integer)ignored).toString()); + } catch (InstantiationException | IllegalAccessException | TestExecutorException | + InvocationTargetException | ClassNotFoundException e) { + System.out.println(e.getMessage()); } } diff --git a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/TestExecutor.java b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/TestExecutor.java index 91284ca..d5a6916 100644 --- a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/TestExecutor.java +++ b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/TestExecutor.java @@ -7,23 +7,50 @@ import java.util.ArrayList; import java.util.List; +/** Class for tests run */ public class TestExecutor { + /** Instance of class for calling tests */ private Object instance; + + /** Class name for test runs */ private String testClassName; + + /** Methods with annotation Before */ private List before = new ArrayList<>(); + + /** Methods with annotation BeforeClass */ private List beforeClass = new ArrayList<>(); + + /** Methods with annotation After */ private List after = new ArrayList<>(); + + /** Methods with annotation AfterClass */ private List afterClass = new ArrayList<>(); + + /** Methods with annotation Test */ private List tests = new ArrayList<>(); - public TestExecutor(Class clazz) throws IllegalAccessException, InstantiationException { + /** + * Constructor + * @param clazz class from which tests will be run + * @throws IllegalAccessException if newInstance threw IllegalAccessException + * @throws InstantiationException if newInstance threw InstantiationException + * @throws TestExecutorException if if wrong number methods with annotation + */ + public TestExecutor(Class clazz) throws IllegalAccessException, InstantiationException, TestExecutorException { getMethods(clazz); instance = clazz.newInstance(); testClassName = clazz.getName(); } + /** + * Run tests + * @return list of results of each test + * @throws InvocationTargetException if we catch exception from the BeforeClass or the AfterClass + * @throws IllegalAccessException if invoke threw InvocationTargetException + */ public List run() throws InvocationTargetException, IllegalAccessException { List results = new ArrayList<>(); if (beforeClass.size() != 0) { @@ -45,6 +72,16 @@ public List run() throws InvocationTargetException, IllegalAccessExc } + /** + * + * @param time test run time + * @param className class name for test + * @param testName test name + * @param isFail test failure + * @param causeOfIgnoring reason for which the test was ignored + * @param e Exception that was thrown by the test + * @return information about test in interface TestResult + */ private TestResult getResult(final long time, final String className, final String testName, final boolean isFail, final String causeOfIgnoring, final Exception e) { return new TestResult() { @@ -82,6 +119,12 @@ public Exception getException() { } + /** + * invoke method + * @param method method that will be called + * @return information about passing the test + * @throws IllegalAccessException if invoke threw IllegalAccessException + */ private TestResult invoke(final Method method) throws IllegalAccessException { final Test testAnnotation = method.getAnnotation(Test.class); @@ -116,7 +159,12 @@ private TestResult invoke(final Method method) throws IllegalAccessException { } - private void getMethods(Class testClazz) { + /** + * Group methods with annotation in class + * @param testClazz class for test + * @throws TestExecutorException if wrong number methods with annotation + */ + private void getMethods(Class testClazz) throws TestExecutorException { Class[] classes = {After.class, AfterClass.class, Before.class, BeforeClass.class, Test.class}; List> lists = new ArrayList<>(); lists.add(after); @@ -129,8 +177,7 @@ private void getMethods(Class testClazz) { for (int i = 0; i < classes.length; i++) { if (method.getAnnotation(classes[i]) != null) { if (flag) { - //ERROR - System.out.println("ERROR"); + throw new TestExecutorException("too much annotations for method " + method.getName()); } lists.get(i).add(method); flag = true; @@ -139,8 +186,7 @@ private void getMethods(Class testClazz) { } for (int i = 0; i < lists.size() - 1; i++) { if (lists.get(i).size() > 1) { - //ERROR - System.out.println("ERROR"); + throw new TestExecutorException("too much methods with annotation " + classes[i].getName()); } } } diff --git a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/TestExecutorException.java b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/TestExecutorException.java new file mode 100644 index 0000000..3b8ed0d --- /dev/null +++ b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/TestExecutorException.java @@ -0,0 +1,11 @@ +package ru.spbau.mit.alyokhina; + +/** + * Exception for Test Executor + * Throws if wrong number methods with annotation + */ +public class TestExecutorException extends Exception { + public TestExecutorException(String msg) { + super(msg); + } +} diff --git a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/TestResult.java b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/TestResult.java index f4e6aac..59f4f8e 100644 --- a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/TestResult.java +++ b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/TestResult.java @@ -1,10 +1,22 @@ package ru.spbau.mit.alyokhina; +/** Interface for information about passing the test */ public interface TestResult { + /** Time of the test */ long getTime(); + + /** The name of the class in which the test was called */ String getClassName(); + + /** The test name */ String getTestName(); + + /** Test failure */ boolean isFail(); + + /** The reason for which the test was ignored */ String causeOfIgnoring(); + + /** The exception that was thrown by the test */ Exception getException(); } diff --git a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/After.java b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/After.java index 6fda24e..60416e3 100644 --- a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/After.java +++ b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/After.java @@ -5,7 +5,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; - +/** Annotation of the method that will be run after each test */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface After { diff --git a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/AfterClass.java b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/AfterClass.java index 60257e2..07ffb51 100644 --- a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/AfterClass.java +++ b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/AfterClass.java @@ -5,6 +5,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +/** Annotation of the method that will be run after the test runs */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface AfterClass { diff --git a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/Before.java b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/Before.java index 7519005..59a7db8 100644 --- a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/Before.java +++ b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/Before.java @@ -5,6 +5,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +/** Annotation of the method that will be run before each test */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Before { diff --git a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/BeforeClass.java b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/BeforeClass.java index c15ba63..4af9a21 100644 --- a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/BeforeClass.java +++ b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/BeforeClass.java @@ -5,7 +5,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; - +/** Annotation of the method that will be run before the test runs */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface BeforeClass { diff --git a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/Test.java b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/Test.java index b3ea65b..efcd09c 100644 --- a/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/Test.java +++ b/05.XUnit/src/main/java/ru/spbau/mit/alyokhina/annotation/Test.java @@ -5,6 +5,10 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +/** + * Annotation for the test. + * Annotation can have two arguments - expected (for excepion) , ignore - to cancel the start and specify the cause + */ @Target(ElementType.METHOD) @Retention(RetentionPolicy.RUNTIME) public @interface Test { diff --git a/05.XUnit/src/test/java/ru/spbau/mit/alyokhina/TestExecutorTest.java b/05.XUnit/src/test/java/ru/spbau/mit/alyokhina/TestExecutorTest.java index c2264a6..9768d92 100644 --- a/05.XUnit/src/test/java/ru/spbau/mit/alyokhina/TestExecutorTest.java +++ b/05.XUnit/src/test/java/ru/spbau/mit/alyokhina/TestExecutorTest.java @@ -15,7 +15,7 @@ public class TestExecutorTest { @Test public void testWithBeforeAndAfter() throws ClassNotFoundException, InvocationTargetException, - IllegalAccessException, InstantiationException { + IllegalAccessException, InstantiationException, TestExecutorException { TestExecutor testExecutor = new TestExecutor(Class.forName("ru.spbau.mit.alyokhina.ClassForTests.TestWithBeforeAndAfter")); List results = testExecutor.run(); assertEquals(3, results.size()); @@ -25,7 +25,7 @@ public void testWithBeforeAndAfter() throws ClassNotFoundException, InvocationTa @Test public void testWithBeforeClassAndAfterClass() throws ClassNotFoundException, InvocationTargetException, - IllegalAccessException, InstantiationException { + IllegalAccessException, InstantiationException, TestExecutorException { TestExecutor testExecutor = new TestExecutor(Class.forName("ru.spbau.mit.alyokhina.ClassForTests.TestWithBeforeClassAndAfterClass")); List results = testExecutor.run(); assertEquals(3, results.size()); @@ -36,7 +36,7 @@ public void testWithBeforeClassAndAfterClass() throws ClassNotFoundException, In @Test public void testWithException() throws ClassNotFoundException, InvocationTargetException, - IllegalAccessException, InstantiationException { + IllegalAccessException, InstantiationException, TestExecutorException { TestExecutor testExecutor = new TestExecutor(Class.forName("ru.spbau.mit.alyokhina.ClassForTests.TestWithException")); List results = testExecutor.run(); assertEquals(5, results.size()); @@ -70,7 +70,7 @@ public void testWithException() throws ClassNotFoundException, InvocationTargetE @Test public void testWithIgnore() throws ClassNotFoundException, InvocationTargetException, - IllegalAccessException, InstantiationException { + IllegalAccessException, InstantiationException, TestExecutorException { TestExecutor testExecutor = new TestExecutor(Class.forName("ru.spbau.mit.alyokhina.ClassForTests.TestIgnored")); List results = testExecutor.run(); assertEquals(4, results.size());