From e2b1be2aa3f2a0870e8e65f4b5c6024e1a7188cc Mon Sep 17 00:00:00 2001 From: benoit Date: Wed, 3 Feb 2016 18:02:20 +0100 Subject: [PATCH] use junit categories (https://github.com/junit-team/junit/wiki/Categories) to exclude test that need a gui this is only available for junit 4 tests and not for junit 3 suite style tests. A test can be annotated with @Category(NeedGuiTests.class) and it will not be executed in headless mode Also remove the AllTests#suite implementation as it's not compatible with junit4 tests --- .../control/TestOnceOnlyController.java | 90 -------------- .../jmeter/gui/util/TestMenuFactory.java | 47 +++----- .../org/apache/jmeter/junit/JMeterTest.java | 8 +- .../categories/ExcludeCategoryFilter.java | 59 +++++++++ .../jmeter/junit/categories/NeedGuiTests.java | 26 ++++ .../control/gui/TestHttpTestSampleGui.java | 45 +++---- .../protocol/http/sampler/PackageTest.java | 14 +-- .../src/org/apache/jorphan/test/AllTests.java | 114 ++++++------------ 8 files changed, 164 insertions(+), 239 deletions(-) create mode 100644 test/src/org/apache/jmeter/junit/categories/ExcludeCategoryFilter.java create mode 100644 test/src/org/apache/jmeter/junit/categories/NeedGuiTests.java diff --git a/test/src/org/apache/jmeter/control/TestOnceOnlyController.java b/test/src/org/apache/jmeter/control/TestOnceOnlyController.java index 402454a9393..e75fa40f155 100644 --- a/test/src/org/apache/jmeter/control/TestOnceOnlyController.java +++ b/test/src/org/apache/jmeter/control/TestOnceOnlyController.java @@ -238,94 +238,4 @@ public void testInsideInnerLoop() throws Exception { assertEquals(expectedNoSamples, counter); } - // Test skipped for now as behaviour is not yet properly defined - public void notestInsideInterleave() throws Exception { - // Test to show current problem with InterleaveController - // I am not sure if the expected order of the samples - // below are correct, because I am not sure if it is - // properly defined how the InterleaveController and - // OnlyOnceController should function. - - // Test plan with OnlyOnceController inside inner loop - // Set up the test plan - LoopController controller = new LoopController(); - final int outerLoopCount = 4; - controller.setLoops(outerLoopCount); - // OnlyOnce samples - OnceOnlyController sub_1 = new OnceOnlyController(); - sub_1.setName("outer OnlyOnce"); - sub_1.addTestElement(new TestSampler("one")); - sub_1.addTestElement(new TestSampler("two")); - controller.addTestElement(sub_1); - controller.addIterationListener(sub_1); - // Outer sample - controller.addTestElement(new TestSampler("three")); - // Inner loop - LoopController sub_2 = new LoopController(); - final int innerLoopCount = 5; - sub_2.setLoops(innerLoopCount); - sub_2.addTestElement(new TestSampler("four")); - // OnlyOnce inside inner loop - OnceOnlyController sub_3 = new OnceOnlyController(); - sub_3.setName("In loop OnlyOnce"); - sub_3.addTestElement(new TestSampler("five")); - sub_3.addTestElement(new TestSampler("six")); - sub_2.addTestElement(sub_3); - sub_2.addIterationListener(sub_3); - // InterleaveController in inner loop - InterleaveControl sub_4 = new InterleaveControl(); - sub_4.setStyle(InterleaveControl.USE_SUB_CONTROLLERS); - // OnlyOnce inside InterleaveController - OnceOnlyController sub_5 = new OnceOnlyController(); - sub_5.addTestElement(new TestSampler("seven")); - sub_5.addTestElement(new TestSampler("eight")); - sub_5.setName("Inside InterleaveController OnlyOnce"); - sub_4.addTestElement(sub_5); - sub_4.addIterationListener(sub_5); - // Samples inside InterleaveController - sub_4.addTestElement(new TestSampler("nine")); - sub_4.addTestElement(new TestSampler("ten")); - sub_2.addTestElement(sub_4); - // Sample in inner loop - sub_2.addTestElement(new TestSampler("eleven")); - controller.addTestElement(sub_2); - - // Compute the expected sample names - String[] onlyOnceOrder = new String[] { "one", "two" }; - String[] order = new String[] { "three", "four", "five", "six", "seven", "eight", "eleven", - "four", "nine", "eleven", - "four", "ten", "eleven", - "four", "nine", "eleven", - "four", "ten", "eleven" }; - // Outer only once + ("three" + "only once five and six" + "eight in interleave only once" + ("four" + "interleave" + "eleven") * innerLoopCount) * outerLoopCount; - int expectedNoSamples = 2 + (1 + 2 + 1 + (1 + 1 + 1) * innerLoopCount) * outerLoopCount; - String[] expectedSamples = new String[expectedNoSamples]; - // The only once samples - System.arraycopy(onlyOnceOrder, 0, expectedSamples, 0, onlyOnceOrder.length); - - // The outer sample and the inner loop samples - final int onceOnlySamples = onlyOnceOrder.length; - for (int i = 0; i < order.length * outerLoopCount; i++) { - expectedSamples[onceOnlySamples + i] = order[i % order.length]; - } - - // Execute the test pan - controller.setRunningVersion(true); - sub_1.setRunningVersion(true); - sub_2.setRunningVersion(true); - sub_3.setRunningVersion(true); - sub_4.setRunningVersion(true); - sub_5.setRunningVersion(true); - controller.initialize(); - - int counter = 0; - TestElement sampler = null; - while ((sampler = controller.next()) != null) { - System.out.println("ex: " + expectedSamples[counter] + " ac: " + sampler.getPropertyAsString(TestElement.NAME)); - assertEquals(expectedSamples[counter], sampler.getPropertyAsString(TestElement.NAME)); - - counter++; - } - assertEquals(expectedNoSamples, counter); - } } diff --git a/test/src/org/apache/jmeter/gui/util/TestMenuFactory.java b/test/src/org/apache/jmeter/gui/util/TestMenuFactory.java index 17b85e14411..a5dc31a6b42 100644 --- a/test/src/org/apache/jmeter/gui/util/TestMenuFactory.java +++ b/test/src/org/apache/jmeter/gui/util/TestMenuFactory.java @@ -20,40 +20,33 @@ import static org.junit.Assert.assertFalse; -import java.awt.GraphicsEnvironment; - import org.apache.jmeter.junit.JMeterTestCase; -import org.apache.jorphan.logging.LoggingManager; -import org.apache.log.Logger; +import org.apache.jmeter.junit.categories.NeedGuiTests; import org.junit.Test; +import org.junit.experimental.categories.Category; +@Category(NeedGuiTests.class) public final class TestMenuFactory extends JMeterTestCase { - private static final Logger log = LoggingManager.getLoggerForClass(); - private static void check(String s, int i) throws Exception { assertFalse("The number of " + s + " should not be 0", 0 == i); } - @Test - public void testMenu() throws Exception { - if(GraphicsEnvironment.isHeadless()) { - System.out.println("Skipping test:"+getClass().getName()+"#testCloneSampler"+", cannot run in Headless mode"); - log.warn("Skipping test:"+getClass().getName()+"#testCloneSampler"+", cannot run in Headless mode"); - return; - } - check("menumap", MenuFactory.menuMap_size()); - - check("assertions", MenuFactory.assertions_size()); - check("configElements", MenuFactory.configElements_size()); - check("controllers", MenuFactory.controllers_size()); - check("listeners", MenuFactory.listeners_size()); - check("nonTestElements", MenuFactory.nonTestElements_size()); - check("postProcessors", MenuFactory.postProcessors_size()); - check("preProcessors", MenuFactory.preProcessors_size()); - check("samplers", MenuFactory.samplers_size()); - check("timers", MenuFactory.timers_size()); - - check("elementstoskip", MenuFactory.elementsToSkip_size()); - } + @Test + public void testMenu() throws Exception { + + check("menumap", MenuFactory.menuMap_size()); + + check("assertions", MenuFactory.assertions_size()); + check("configElements", MenuFactory.configElements_size()); + check("controllers", MenuFactory.controllers_size()); + check("listeners", MenuFactory.listeners_size()); + check("nonTestElements", MenuFactory.nonTestElements_size()); + check("postProcessors", MenuFactory.postProcessors_size()); + check("preProcessors", MenuFactory.preProcessors_size()); + check("samplers", MenuFactory.samplers_size()); + check("timers", MenuFactory.timers_size()); + + check("elementstoskip", MenuFactory.elementsToSkip_size()); + } } diff --git a/test/src/org/apache/jmeter/junit/JMeterTest.java b/test/src/org/apache/jmeter/junit/JMeterTest.java index cde3ce19e55..43a0a32cb08 100644 --- a/test/src/org/apache/jmeter/junit/JMeterTest.java +++ b/test/src/org/apache/jmeter/junit/JMeterTest.java @@ -37,9 +37,6 @@ import java.util.Properties; import java.util.Set; -import junit.framework.Test; -import junit.framework.TestSuite; - import org.apache.jmeter.config.gui.ObsoleteGui; import org.apache.jmeter.engine.util.CompoundVariable; import org.apache.jmeter.functions.Function; @@ -61,6 +58,9 @@ import org.jdom.Element; import org.jdom.input.SAXBuilder; +import junit.framework.Test; +import junit.framework.TestSuite; + public class JMeterTest extends JMeterTestCaseJUnit3 { private static final Logger log = LoggingManager.getLoggerForClass(); @@ -653,8 +653,6 @@ private static void checkElementCloning(TestElement item) { PropertyIterator iter2 = item.propertyIterator(); while (iter2.hasNext()) { JMeterProperty item2 = iter2.next(); - // [sebb] assertEquals(item2, - // clonedItem.getProperty(item2.getName())); assertEquals(item2.getStringValue(), clonedItem.getProperty(item2.getName()).getStringValue()); assertTrue(item2 != clonedItem.getProperty(item2.getName())); } diff --git a/test/src/org/apache/jmeter/junit/categories/ExcludeCategoryFilter.java b/test/src/org/apache/jmeter/junit/categories/ExcludeCategoryFilter.java new file mode 100644 index 00000000000..a7c3240520a --- /dev/null +++ b/test/src/org/apache/jmeter/junit/categories/ExcludeCategoryFilter.java @@ -0,0 +1,59 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.jmeter.junit.categories; + +import org.junit.experimental.categories.Category; +import org.junit.runner.Description; +import org.junit.runner.manipulation.Filter; + +/** + * Junit Filter that excludes test annotated with a given marker interface + * @since 3.0 + */ +public class ExcludeCategoryFilter extends Filter { + + private Class excludedClass; + + public ExcludeCategoryFilter(Class excludedClass) { + super(); + this.excludedClass = excludedClass; + } + + @Override + public String describe() { + return "JMeter ExcludeCategoryFilter"; + } + + @Override + public boolean shouldRun(Description description) { + //TODO : check the class hierarchy and not only the current class + Category cat = description.getAnnotation(Category.class); + if(cat != null) { + Class[] categories = cat.value(); + for (Class class1 : categories) { + if(excludedClass.isAssignableFrom(class1)) { + return false; + } + } + } + + return true; + } + +} diff --git a/test/src/org/apache/jmeter/junit/categories/NeedGuiTests.java b/test/src/org/apache/jmeter/junit/categories/NeedGuiTests.java new file mode 100644 index 00000000000..5a53631d459 --- /dev/null +++ b/test/src/org/apache/jmeter/junit/categories/NeedGuiTests.java @@ -0,0 +1,26 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.jmeter.junit.categories; + +/** + * JUnit category marker for tests that could not not run in headless mode + */ +public interface NeedGuiTests { + // yeah ! +} diff --git a/test/src/org/apache/jmeter/protocol/http/control/gui/TestHttpTestSampleGui.java b/test/src/org/apache/jmeter/protocol/http/control/gui/TestHttpTestSampleGui.java index 5626c21be6a..94dae7b3e32 100644 --- a/test/src/org/apache/jmeter/protocol/http/control/gui/TestHttpTestSampleGui.java +++ b/test/src/org/apache/jmeter/protocol/http/control/gui/TestHttpTestSampleGui.java @@ -20,41 +20,30 @@ import static org.junit.Assert.assertEquals; -import java.awt.GraphicsEnvironment; +import org.apache.jmeter.junit.categories.NeedGuiTests; import org.apache.jmeter.protocol.http.sampler.HTTPSamplerBase; -import org.apache.jorphan.logging.LoggingManager; -import org.apache.log.Logger; import org.junit.Before; import org.junit.Test; +import org.junit.experimental.categories.Category; +@Category(NeedGuiTests.class) public class TestHttpTestSampleGui { - private static final Logger log = LoggingManager.getLoggerForClass(); private HttpTestSampleGui gui; - @Before - public void setUp() { - if(GraphicsEnvironment.isHeadless()) { - System.out.println("Skipping test:"+getClass().getName()+", cannot run in Headless mode"); - log.warn("Skipping test:"+getClass().getName()+", cannot run in Headless mode"); - return; - } - gui = new HttpTestSampleGui(); - } + @Before + public void setUp() { + gui = new HttpTestSampleGui(); + } - @Test - public void testCloneSampler() throws Exception { - if(GraphicsEnvironment.isHeadless()) { - System.out.println("Skipping test:"+getClass().getName()+"#testCloneSampler"+", cannot run in Headless mode"); - log.warn("Skipping test:"+getClass().getName()+"#testCloneSampler"+", cannot run in Headless mode"); - return; - } - HTTPSamplerBase sampler = (HTTPSamplerBase) gui.createTestElement(); - sampler.addArgument("param", "value"); - HTTPSamplerBase clonedSampler = (HTTPSamplerBase) sampler.clone(); - clonedSampler.setRunningVersion(true); - sampler.getArguments().getArgument(0).setValue("new value"); - assertEquals("Sampler didn't clone correctly", "new value", sampler.getArguments().getArgument(0) - .getValue()); - } + @Test + public void testCloneSampler() throws Exception { + HTTPSamplerBase sampler = (HTTPSamplerBase) gui.createTestElement(); + sampler.addArgument("param", "value"); + HTTPSamplerBase clonedSampler = (HTTPSamplerBase) sampler.clone(); + clonedSampler.setRunningVersion(true); + sampler.getArguments().getArgument(0).setValue("new value"); + assertEquals("Sampler didn't clone correctly", "new value", sampler.getArguments().getArgument(0) + .getValue()); + } } diff --git a/test/src/org/apache/jmeter/protocol/http/sampler/PackageTest.java b/test/src/org/apache/jmeter/protocol/http/sampler/PackageTest.java index 02a2c49033c..c34e5ef7d8f 100644 --- a/test/src/org/apache/jmeter/protocol/http/sampler/PackageTest.java +++ b/test/src/org/apache/jmeter/protocol/http/sampler/PackageTest.java @@ -23,28 +23,20 @@ import static org.junit.Assert.assertEquals; -import java.awt.GraphicsEnvironment; - import org.apache.jmeter.config.Arguments; import org.apache.jmeter.config.ConfigTestElement; +import org.apache.jmeter.junit.categories.NeedGuiTests; import org.apache.jmeter.protocol.http.config.gui.HttpDefaultsGui; import org.apache.jmeter.protocol.http.control.gui.HttpTestSampleGui; import org.apache.jmeter.protocol.http.util.HTTPArgument; -import org.apache.jorphan.logging.LoggingManager; -import org.apache.log.Logger; import org.junit.Test; +import org.junit.experimental.categories.Category; +@Category(NeedGuiTests.class) public class PackageTest { - private static final Logger log = LoggingManager.getLoggerForClass(); @Test public void testConfiguring() throws Exception { - if(GraphicsEnvironment.isHeadless()) { - System.out.println("Skipping test:"+getClass().getName()+"#testConfiguring"+", cannot run in Headless mode"); - log.warn("Skipping test:"+getClass().getName()+"#testConfiguring"+", cannot run in Headless mode"); - return; - } - HTTPSamplerBase sampler = (HTTPSamplerBase) new HttpTestSampleGui().createTestElement(); configure(sampler); } diff --git a/test/src/org/apache/jorphan/test/AllTests.java b/test/src/org/apache/jorphan/test/AllTests.java index 9708c918a90..3f3247d993a 100644 --- a/test/src/org/apache/jorphan/test/AllTests.java +++ b/test/src/org/apache/jorphan/test/AllTests.java @@ -18,6 +18,7 @@ package org.apache.jorphan.test; +import java.awt.GraphicsEnvironment; import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -31,18 +32,23 @@ import java.util.Locale; import java.util.Properties; -import org.apache.commons.lang3.exception.ExceptionUtils; +import org.apache.jmeter.junit.categories.ExcludeCategoryFilter; +import org.apache.jmeter.junit.categories.NeedGuiTests; import org.apache.jmeter.util.JMeterUtils; import org.apache.jorphan.logging.LoggingManager; import org.apache.jorphan.reflect.ClassFilter; import org.apache.jorphan.reflect.ClassFinder; import org.apache.jorphan.util.JOrphanUtils; import org.apache.log.Logger; +import org.junit.internal.RealSystem; +import org.junit.internal.TextListener; +import org.junit.runner.Computer; import org.junit.runner.JUnitCore; +import org.junit.runner.Request; +import org.junit.runner.Result; +import org.junit.runner.notification.RunListener; -import junit.framework.Test; import junit.framework.TestCase; -import junit.framework.TestSuite; /** * Provides a quick and easy way to run all junit @@ -192,12 +198,37 @@ public static void main(String[] args) { try { System.out.println("Searching junit tests in : "+args[0]); List tests = findJMeterJUnitTests(args[0]); - JUnitCore.main(tests.toArray(new String[0])); - } catch (IOException e) { + Class[] classes = asClasses(tests); + JUnitCore jUnitCore = new JUnitCore(); + + // this listener is in the internal junit package + // if it breaks, replace it with a custom text listener + RunListener listener = new TextListener(new RealSystem()); + jUnitCore.addListener(listener); + + Request request = Request.classes(new Computer(), classes); + if(GraphicsEnvironment.isHeadless()) { + request = request.filterWith(new ExcludeCategoryFilter(NeedGuiTests.class)); + } + Result result = jUnitCore.run(request); + + System.exit(result.wasSuccessful() ? 0 : 1); + } catch (Exception e) { + e.printStackTrace(); System.exit(1); } } + private static Class[] asClasses(List tests) throws ClassNotFoundException { + Class[] classes = new Class[tests.size()]; + for (int i = 0; i < classes.length; i++) { + String test = tests.get(i); + classes[i] = Class.forName(test, true, Thread.currentThread().getContextClassLoader()); + } + + return classes; + } + /** * An overridable method that initializes the logging for the unit test run, * using the properties file passed in as the second argument. @@ -253,79 +284,6 @@ protected static void initializeManager(String[] args) { } } - /* - * Externally callable suite() method for use by JUnit Allows tests to be - * run directly under JUnit, rather than using the startup code in the rest - * of the module. No parameters can be passed in, so it is less flexible. - */ - @Deprecated - public static TestSuite suite() { - String args[] = { "../lib/ext", "./testfiles/jmetertest.properties", "org.apache.jmeter.util.JMeterUtils" }; - - initializeManager(args); - return suite(args[0]); - } - - /** - * A unit test suite for JUnit. - * - * @return The test suite - */ - @Deprecated - private static TestSuite suite(String searchPaths) { - TestSuite suite = new TestSuite("All Tests"); - System.out.println("Scanning "+searchPaths+ " for test cases"); - int tests=0; - int suites=0; - try { - log.info("ClassFinder(TestCase)"); - List classList = findJMeterJUnitTests(searchPaths); - int sz=classList.size(); - log.info("ClassFinder(TestCase) found: "+sz+ " TestCase classes"); - System.out.println("ClassFinder found: "+sz+ " TestCase classes"); - for (String name : classList) { - try { - /* - * TestSuite only finds testXXX() methods, and does not look - * for suite() methods. - * - * To provide more compatibilty with stand-alone tests, - * where JUnit does look for a suite() method, check for it - * first here. - * - */ - - Class clazz = Class.forName(name); - Test t = null; - try { - Method m = clazz.getMethod("suite", new Class[0]); - t = (Test) m.invoke(clazz, (Object[])null); - suites++; - } catch (NoSuchMethodException e) { - } // this is not an error, the others are - // catch (SecurityException e) {} - // catch (IllegalAccessException e) {} - // catch (IllegalArgumentException e) {} - // catch (InvocationTargetException e) {} - - if (t == null) { - t = new TestSuite(clazz); - } - - tests++; - suite.addTest(t); - } catch (Exception ex) { - System.out.println("ERROR: (see logfile) could not add test for class " + name + " " + ExceptionUtils.getStackTrace(ex)); - log.error("error adding test :", ex); - } - } - } catch (IOException e) { - log.error("", e); - } - System.out.println("Created: "+tests+" tests including "+suites+" suites"); - return suite; - } - private static List findJMeterJUnitTests(String searchPaths) throws IOException { List classList = ClassFinder.findClasses(JOrphanUtils.split(searchPaths, ","), new JunitTestFilter());