diff --git a/src/main/java/com/xceptance/neodymium/module/statement/testdata/SkipDataSet.java b/src/main/java/com/xceptance/neodymium/module/statement/testdata/SkipDataSet.java new file mode 100644 index 000000000..578a119ae --- /dev/null +++ b/src/main/java/com/xceptance/neodymium/module/statement/testdata/SkipDataSet.java @@ -0,0 +1,20 @@ +package com.xceptance.neodymium.module.statement.testdata; + +import static java.lang.annotation.ElementType.METHOD; +import static java.lang.annotation.ElementType.TYPE; +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import java.lang.annotation.Retention; +import java.lang.annotation.Target; + +@Retention(RUNTIME) +@Target( +{ + TYPE, METHOD +}) +public @interface SkipDataSet +{ + int value() default 0; + + String id() default ""; +} diff --git a/src/main/java/com/xceptance/neodymium/module/statement/testdata/TestdataStatement.java b/src/main/java/com/xceptance/neodymium/module/statement/testdata/TestdataStatement.java index 710bd615a..7db1274e0 100644 --- a/src/main/java/com/xceptance/neodymium/module/statement/testdata/TestdataStatement.java +++ b/src/main/java/com/xceptance/neodymium/module/statement/testdata/TestdataStatement.java @@ -9,6 +9,7 @@ import java.util.List; import java.util.Map; import java.util.Map.Entry; +import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; import org.junit.runners.model.FrameworkMethod; @@ -182,6 +183,28 @@ private List processOverrides(TestClass testClass, FrameworkMethod metho // at this point neither the class nor the method could have data sets suppressed List classDataSetAnnotations = getAnnotations(testClass.getJavaClass(), DataSet.class); + List classSkipDataSetAnnotations = getAnnotations(testClass.getJavaClass(), SkipDataSet.class); + List methodSkipDataSetAnnotations = getAnnotations(method.getMethod(), SkipDataSet.class); + + // if class annotation states that the data set should be skipped but the method annotation explicitly declares + // that the data set should be used for the execution, the method annotation has a priority + if (!methodDataSetAnnotations.isEmpty()) + { + List classSkipDataSetAnnotationsAdjusted = new LinkedList<>(); + + for (SkipDataSet skipDataSet : classSkipDataSetAnnotations) + { + for (DataSet methodDataSet : methodDataSetAnnotations) + { + if (!(skipDataSet.id().equals(methodDataSet.id()) || skipDataSet.value() == methodDataSet.value())) + { + classSkipDataSetAnnotationsAdjusted.add(skipDataSet); + } + } + } + classSkipDataSetAnnotations = classSkipDataSetAnnotationsAdjusted; + } + if (!methodDataSetAnnotations.isEmpty()) { dataSetAnnotations = methodDataSetAnnotations; @@ -273,7 +296,51 @@ else if (!classDataSetAnnotations.isEmpty()) // choose the random data sets [0,randomSetAmount[ fixedIterations = fixedIterations.subList(0, randomSetAmount); } - return fixedIterations; + + List skipDataSetAnnotations = new LinkedList<>(); + if (!methodSkipDataSetAnnotations.isEmpty()) + { + skipDataSetAnnotations.addAll(methodSkipDataSetAnnotations); + } + else if (!classSkipDataSetAnnotations.isEmpty()) + { + skipDataSetAnnotations.addAll(classSkipDataSetAnnotations); + } + + return applyFilterToSkipIterations(skipDataSetAnnotations, fixedIterations); + } + + private List applyFilterToSkipIterations(List skipDataSetAnnotations, List iterations) + { + + class DataObject + { + int index; + + String id; + + DataObject(int index, String id) + { + this.index = index; + this.id = id; + } + + @Override + public boolean equals(Object object) + { + DataObject another = (DataObject) object; + return another.index == this.index || (another.id != null && another.id.equals(this.id)); + } + } + List skipDataSetObjects = skipDataSetAnnotations.stream().map(dataSet -> new DataObject(dataSet.value(), dataSet.id())) + .collect(Collectors.toList()); + + return iterations.stream() + .filter(iteration -> !skipDataSetObjects.contains(new DataObject(((TestdataStatementData) iteration).getIndex() + + 1, (((TestdataStatementData) iteration).getDataSet() != null ? ((TestdataStatementData) iteration).getDataSet() + .get(TEST_ID) + : null)))) + .collect(Collectors.toList()); } @Override diff --git a/src/test/java/com/xceptance/neodymium/testclasses/data/override/classonly/ClassSkipDataSetAnnotations.java b/src/test/java/com/xceptance/neodymium/testclasses/data/override/classonly/ClassSkipDataSetAnnotations.java new file mode 100644 index 000000000..5df116d72 --- /dev/null +++ b/src/test/java/com/xceptance/neodymium/testclasses/data/override/classonly/ClassSkipDataSetAnnotations.java @@ -0,0 +1,41 @@ +package com.xceptance.neodymium.testclasses.data.override.classonly; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +import com.xceptance.neodymium.NeodymiumRunner; +import com.xceptance.neodymium.module.statement.testdata.DataSet; +import com.xceptance.neodymium.module.statement.testdata.SkipDataSet; +import com.xceptance.neodymium.util.DataUtils; + +@RunWith(NeodymiumRunner.class) +@SkipDataSet(1) +public class ClassSkipDataSetAnnotations +{ + @Test + public void testSomething1() + { + String key = DataUtils.asString("key1"); + Assert.assertTrue("Test should only run for 2 and 3 data set", key.equals("val2") || key.equals("val3")); + // should run 2 and 3 + } + + @Test + @DataSet(1) + public void testSomething2() + { + String key = DataUtils.asString("key1"); + Assert.assertTrue("Test should only run for 1 data set", key.equals("val1")); + // should run 1 ??? + } + + @Test + @DataSet(2) + public void testSomething3() + { + String key = DataUtils.asString("key1"); + Assert.assertTrue("Test should only run for 2 data set", key.equals("val2")); + // should run 2 + } +} diff --git a/src/test/java/com/xceptance/neodymium/testclasses/data/override/methodonly/MethodSkipDataSetAnnotations.java b/src/test/java/com/xceptance/neodymium/testclasses/data/override/methodonly/MethodSkipDataSetAnnotations.java new file mode 100644 index 000000000..3b0f993b8 --- /dev/null +++ b/src/test/java/com/xceptance/neodymium/testclasses/data/override/methodonly/MethodSkipDataSetAnnotations.java @@ -0,0 +1,33 @@ +package com.xceptance.neodymium.testclasses.data.override.methodonly; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +import com.xceptance.neodymium.NeodymiumRunner; +import com.xceptance.neodymium.module.statement.testdata.DataSet; +import com.xceptance.neodymium.module.statement.testdata.SkipDataSet; +import com.xceptance.neodymium.util.DataUtils; + +@RunWith(NeodymiumRunner.class) +public class MethodSkipDataSetAnnotations +{ + @Test + @SkipDataSet(2) + public void testSomething4() + { + String key = DataUtils.asString("key1"); + Assert.assertTrue("Test should only run for 1 and 3 data set", key.equals("val1") || key.equals("val3")); + // should run 1 and 3 + } + + @Test + @DataSet(2) + @SkipDataSet(2) + public void testSomething5() + { + String key = DataUtils.asString("key1", null); + Assert.assertNull("Test should run with supressed data sets", key); + // should run without data set (same as SuppressDataSets) ??? + } +} diff --git a/src/test/java/com/xceptance/neodymium/testclasses/data/override/mixed/MixedSkipDataSetAnnotations.java b/src/test/java/com/xceptance/neodymium/testclasses/data/override/mixed/MixedSkipDataSetAnnotations.java new file mode 100644 index 000000000..21ae4b34e --- /dev/null +++ b/src/test/java/com/xceptance/neodymium/testclasses/data/override/mixed/MixedSkipDataSetAnnotations.java @@ -0,0 +1,34 @@ +package com.xceptance.neodymium.testclasses.data.override.mixed; + +import org.junit.Assert; +import org.junit.Test; +import org.junit.runner.RunWith; + +import com.xceptance.neodymium.NeodymiumRunner; +import com.xceptance.neodymium.module.statement.testdata.DataSet; +import com.xceptance.neodymium.module.statement.testdata.SkipDataSet; +import com.xceptance.neodymium.util.DataUtils; + +@RunWith(NeodymiumRunner.class) +@SkipDataSet(1) +public class MixedSkipDataSetAnnotations +{ + @Test + @SkipDataSet(2) + public void testSomething4() + { + String key = DataUtils.asString("key1"); + Assert.assertTrue("Test should only run for 1 and 3 data set", key.equals("val1") || key.equals("val3")); + // should run 1 and 3 + } + + @Test + @DataSet(2) + @SkipDataSet(2) + public void testSomething5() + { + String key = DataUtils.asString("key1", null); + Assert.assertNull("Test should run with supressed data sets", key); + // should run without data set (same as SuppressDataSets) ??? + } +} diff --git a/src/test/java/com/xceptance/neodymium/tests/TestDataStatementTest.java b/src/test/java/com/xceptance/neodymium/tests/TestDataStatementTest.java index c1d84f490..50d8e1c88 100644 --- a/src/test/java/com/xceptance/neodymium/tests/TestDataStatementTest.java +++ b/src/test/java/com/xceptance/neodymium/tests/TestDataStatementTest.java @@ -19,6 +19,7 @@ import com.xceptance.neodymium.testclasses.data.override.classonly.ClassMultipleSameDataSet; import com.xceptance.neodymium.testclasses.data.override.classonly.ClassRandomDataSets; import com.xceptance.neodymium.testclasses.data.override.classonly.ClassRandomDataSetsFromRange; +import com.xceptance.neodymium.testclasses.data.override.classonly.ClassSkipDataSetAnnotations; import com.xceptance.neodymium.testclasses.data.override.methodonly.MethodDefaultEmptyDataSets; import com.xceptance.neodymium.testclasses.data.override.methodonly.MethodDefaultNoDataSets; import com.xceptance.neodymium.testclasses.data.override.methodonly.MethodDefaultOneDataSet; @@ -27,10 +28,12 @@ import com.xceptance.neodymium.testclasses.data.override.methodonly.MethodMultipleSameDataSet; import com.xceptance.neodymium.testclasses.data.override.methodonly.MethodRandomDataSets; import com.xceptance.neodymium.testclasses.data.override.methodonly.MethodRandomDataSetsFromRange; +import com.xceptance.neodymium.testclasses.data.override.methodonly.MethodSkipDataSetAnnotations; import com.xceptance.neodymium.testclasses.data.override.mixed.ClassWithoutTwoMethodsOneForced; import com.xceptance.neodymium.testclasses.data.override.mixed.ForceOfNoneDataSets; import com.xceptance.neodymium.testclasses.data.override.mixed.MixRandomAndValueDataSets; import com.xceptance.neodymium.testclasses.data.override.mixed.MixRandomDataSetsFromRange; +import com.xceptance.neodymium.testclasses.data.override.mixed.MixedSkipDataSetAnnotations; import com.xceptance.neodymium.testclasses.data.override.mixed.OneDataSetTwoMethodsOneWithout; import com.xceptance.neodymium.testclasses.data.override.mixed.OnlyImplicitOneDataSet; import com.xceptance.neodymium.testclasses.data.override.mixed.OverrideClassRandomDataSetsOnMethodLevel; @@ -452,4 +455,47 @@ public void testRandomDataSetsException() checkFail(result, 1, 0, 1, "java.lang.IllegalArgumentException: Method 'test' is marked to be run with 4 random data sets, but there are only 2 available"); } + + @Test + public void testClassSkipDataSetsAnnotationsTest() throws Throwable + { + String[] expected = new String[] + { + "testSomething1 :: Data set 2 / 3", + "testSomething3 :: Data set 2 / 3", + "testSomething1 :: Data set 3 / 3", + "testSomething2 :: Data set 1 / 3", + }; + checkDescription(ClassSkipDataSetAnnotations.class, expected); + Result result = JUnitCore.runClasses(ClassSkipDataSetAnnotations.class); + checkPass(result, 4, 0); + } + + @Test + public void testMethodSkipDataSetsAnnotationsTest() throws Throwable + { + String[] expected = new String[] + { + "testSomething4 :: Data set 1 / 3", + "testSomething4 :: Data set 3 / 3", + "testSomething5", + }; + checkDescription(MethodSkipDataSetAnnotations.class, expected); + Result result = JUnitCore.runClasses(MethodSkipDataSetAnnotations.class); + checkPass(result, 3, 0); + } + + @Test + public void testMixedSkipDataSetsAnnotationsTest() throws Throwable + { + String[] expected = new String[] + { + "testSomething4 :: Data set 1 / 3", + "testSomething4 :: Data set 3 / 3", + "testSomething5", + }; + checkDescription(MixedSkipDataSetAnnotations.class, expected); + Result result = JUnitCore.runClasses(MixedSkipDataSetAnnotations.class); + checkPass(result, 3, 0); + } } diff --git a/src/test/resources/com/xceptance/neodymium/testclasses/data/override/classonly/ClassSkipDataSetAnnotations.csv b/src/test/resources/com/xceptance/neodymium/testclasses/data/override/classonly/ClassSkipDataSetAnnotations.csv new file mode 100644 index 000000000..8012d043e --- /dev/null +++ b/src/test/resources/com/xceptance/neodymium/testclasses/data/override/classonly/ClassSkipDataSetAnnotations.csv @@ -0,0 +1,4 @@ +key1 +val1 +val2 +val3 diff --git a/src/test/resources/com/xceptance/neodymium/testclasses/data/override/methodonly/MethodSkipDataSetAnnotations.csv b/src/test/resources/com/xceptance/neodymium/testclasses/data/override/methodonly/MethodSkipDataSetAnnotations.csv new file mode 100644 index 000000000..8012d043e --- /dev/null +++ b/src/test/resources/com/xceptance/neodymium/testclasses/data/override/methodonly/MethodSkipDataSetAnnotations.csv @@ -0,0 +1,4 @@ +key1 +val1 +val2 +val3 diff --git a/src/test/resources/com/xceptance/neodymium/testclasses/data/override/mixed/MixedSkipDataSetAnnotations.csv b/src/test/resources/com/xceptance/neodymium/testclasses/data/override/mixed/MixedSkipDataSetAnnotations.csv new file mode 100644 index 000000000..8012d043e --- /dev/null +++ b/src/test/resources/com/xceptance/neodymium/testclasses/data/override/mixed/MixedSkipDataSetAnnotations.csv @@ -0,0 +1,4 @@ +key1 +val1 +val2 +val3