jmeter-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pmoua...@apache.org
Subject svn commit: r1817424 [2/2] - in /jmeter/trunk: src/core/org/apache/jmeter/services/ src/jorphan/org/apache/jorphan/reflect/ test/src/org/apache/jmeter/assertions/ test/src/org/apache/jmeter/config/ test/src/org/apache/jmeter/functions/ test/src/org/apa...
Date Thu, 07 Dec 2017 21:31:05 GMT
Modified: jmeter/trunk/test/src/org/apache/jorphan/test/AllTests.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/test/src/org/apache/jorphan/test/AllTests.java?rev=1817424&r1=1817423&r2=1817424&view=diff
==============================================================================
--- jmeter/trunk/test/src/org/apache/jorphan/test/AllTests.java (original)
+++ jmeter/trunk/test/src/org/apache/jorphan/test/AllTests.java Thu Dec  7 21:31:04 2017
@@ -13,44 +13,50 @@
  * 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.jorphan.test;
 
+import javax.crypto.Cipher;
 import java.awt.GraphicsEnvironment;
 import java.io.File;
 import java.io.IOException;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Modifier;
 import java.nio.charset.Charset;
+import java.nio.file.Files;
+import java.nio.file.Paths;
 import java.security.NoSuchAlgorithmException;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Locale;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
 
-import javax.crypto.Cipher;
+import junit.framework.TestCase;
 
+import org.apache.commons.lang3.time.StopWatch;
 import org.apache.jmeter.junit.categories.ExcludeCategoryFilter;
 import org.apache.jmeter.junit.categories.NeedGuiTests;
 import org.apache.jmeter.util.JMeterUtils;
 import org.apache.jorphan.reflect.ClassFilter;
 import org.apache.jorphan.reflect.ClassFinder;
 import org.apache.jorphan.util.JOrphanUtils;
-import org.junit.internal.RealSystem;
+import org.junit.experimental.ParallelComputer;
 import org.junit.internal.TextListener;
 import org.junit.runner.Computer;
+import org.junit.runner.Description;
 import org.junit.runner.JUnitCore;
 import org.junit.runner.Request;
 import org.junit.runner.Result;
+import org.junit.runner.notification.RunListener;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import spock.lang.Specification;
 
-import junit.framework.TestCase;
-
 /**
- * Provides a quick and easy way to run all <a href="http://http://junit.org">junit</a>

+ * Provides a quick and easy way to run all <a href="http://http://junit.org">junit</a>
  * unit tests (including Spock tests) in your Java project.
  * It will find all unit test classes and run all their test methods.
  * There is no need to configure it in any way to find these classes except to
@@ -59,9 +65,9 @@ import junit.framework.TestCase;
  * Here is an example Ant target (See Ant at <a
  * href="http://ant.apache.org">Apache Ant</a>) that runs all your unit
  * tests:
- * 
+ *
  * <pre>
- * 
+ *
  *       &lt;target name=&quot;test&quot; depends=&quot;compile&quot;&gt;
  *           &lt;java classname=&quot;org.apache.jorphan.test.AllTests&quot;
fork=&quot;yes&quot;&gt;
  *               &lt;classpath&gt;
@@ -73,34 +79,34 @@ import junit.framework.TestCase;
  *               &lt;arg value=&quot;NAME_OF_UNITTESTMANAGER_CLASS&quot;/&gt;
  *           &lt;/java&gt;
  *       &lt;/target&gt;
- *  
+ *
  * </pre>
- * 
+ *
  * <dl>
  * <dt>YOUR_CLASSPATH</dt>
  * <dd>Refers to the classpath that includes all jars and libraries need to run
  * your unit tests</dd>
- * 
+ *
  * <dt>ROOT_DIR_OF_YOUR_COMPILED_CLASSES</dt>
  * <dd>The classpath should include the directory where all your project's
  * classes are compiled to, if it doesn't already.</dd>
- * 
+ *
  * <dt>SEARCH_PATH</dt>
  * <dd>The first argument tells AllTests where to look for unit test classes to
  * execute. In most cases, it is identical to ROOT_DIR_OF_YOUR_COMPILED_CLASSES.
  * You can specify multiple directories or jars to search by providing a
  * comma-delimited list.</dd>
- * 
+ *
  * <dt>PROPERTY_FILE</dt>
  * <dd>A simple property file that sets logging parameters. It is optional and
  * is only relevant if you use the same logging packages that JOrphan uses.</dd>
- * 
+ *
  * <dt>NAME_OF_UNITTESTMANAGER_CLASS</dt>
  * <dd>If your system requires some configuration to run correctly, you can
  * implement the {@link UnitTestManager} interface and be given an opportunity
  * to initialize your system from a configuration file.</dd>
  * </dl>
- * 
+ *
  * @see UnitTestManager
  */
 public final class AllTests {
@@ -132,16 +138,15 @@ public final class AllTests {
      * implements the UnitTestManager interface. This provides a means of
      * initializing your application with a configuration file prior to the
      * start of any unit tests.
-     * 
-     * @param args
-     *            the command line arguments
+     *
+     * @param args the command line arguments
      */
     public static void main(String[] args) {
         if (args.length < 1) {
             System.out.println("You must specify a comma-delimited list of paths to search
" + "for unit tests");
             return;
         }
-        
+
         String home = new File(System.getProperty("user.dir")).getParent();
         System.out.println("Setting JMeterHome: "+home);
         JMeterUtils.setJMeterHome(home);
@@ -169,7 +174,7 @@ public final class AllTests {
         logprop("os.version", true);
         logprop("os.arch");
         logprop("java.class.version");
-        
+
         String cp = System.getProperty("java.class.path");
         String[] cpe = JOrphanUtils.split(cp, java.io.File.pathSeparator);
         StringBuilder sb = new StringBuilder(3000);
@@ -194,52 +199,111 @@ public final class AllTests {
         System.out.println("+++++++++++");
         logprop("java.awt.headless", true);
         logprop("java.awt.graphicsenv", true);
-        
+
         System.out.println("------------");
+        JUnitCore jUnitCore = new JUnitCore();
+        // this listener is in the internal junit package
+        // if it breaks, replace it with a custom text listener
+        jUnitCore.addListener(new TextListener(System.out));
+        // this will time each unit test and then print to file
+        // TODO: put behind a flag
+        jUnitCore.addListener(new TimePrinter());
+
+        System.out.println("Searching junit tests in : "+args[0]);
+
         try {
-            System.out.println("Searching junit tests in : "+args[0]);
             List<String> tests = findJMeterJUnitTests(args[0]);
-            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
-            jUnitCore.addListener(new TextListener(new RealSystem()));
-            
-            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);
+            List<Class<?>> classes = asClasses(tests);
+
+            Result parallelResults = jUnitCore.run(getParallelTests(classes));
+            Result serialResults = jUnitCore.run(getSerialTests(classes));
+
+            boolean allTestsSuccessful =
+                    parallelResults.wasSuccessful() && serialResults.wasSuccessful();
+            System.exit(allTestsSuccessful ? 0 : 1);
         } catch (Exception e) {
             e.printStackTrace();
             System.exit(1);
         }
     }
 
-    private static Class<?>[] asClasses(List<String> 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());
+    private static Request getParallelTests(List<Class<?>> classes) {
+        Request parallelRequest = Request.classes(
+                ParallelComputer.methods(), // ParallelComputer.classes() causes failures
+                classes.stream()
+                        .filter(c -> !JMeterSerialTest.class.isAssignableFrom(c))
+                        .toArray(Class<?>[]::new));
+        return filterGUITests(parallelRequest);
+    }
+
+    private static Request getSerialTests(List<Class<?>> classes) {
+        Request serialRequest = Request.classes(Computer.serial(),
+                classes.stream()
+                        .filter(JMeterSerialTest.class::isAssignableFrom)
+                        .toArray(Class<?>[]::new));
+        return filterGUITests(serialRequest);
+    }
+
+    private static Request filterGUITests(Request request) {
+        if (GraphicsEnvironment.isHeadless()) {
+            return request.filterWith(new ExcludeCategoryFilter(NeedGuiTests.class));
+        } else {
+            return request;
+        }
+    }
+
+    private static List<Class<?>> asClasses(List<String> tests) {
+        return tests.stream()
+                .map(AllTests::asClass)
+                .collect(Collectors.toList());
+    }
+
+    private static Class<?> asClass(String test) {
+        try {
+            return Class.forName(test, true, Thread.currentThread().getContextClassLoader());
+        } catch (ClassNotFoundException e) {
+            throw new RuntimeException(e);
         }
+    }
 
-        return classes;
+    /**
+     * Used to time each unit test and then write the results to file
+     */
+    private static class TimePrinter extends RunListener {
+        private ConcurrentHashMap<Description, StopWatch> testTimers = new ConcurrentHashMap<>();
+        private List<String> logLines = new ArrayList<>();
+
+        @Override
+        public void testStarted(Description description) {
+            StopWatch sw = new StopWatch();
+            sw.start();
+            testTimers.put(description, sw);
+        }
+
+        @Override
+        public void testFinished(Description desc) {
+            StopWatch sw = testTimers.get(desc);
+            sw.stop();
+            logLines.add(desc.getClassName() + "." + desc.getMethodName() + "\t" + sw.getNanoTime());
+        }
+
+        @Override
+        public void testRunFinished(Result result) throws Exception {
+            Files.write(Paths.get("unit-test-perf.log"), logLines);
+        }
     }
 
     /**
      * An overridable method that instantiates a UnitTestManager (if one
      * was specified in the command-line arguments), and hands it the name of
      * the properties file to use to configure the system.
-     * 
+     *
      * @param args arguments with the initialization parameter
      * arg[0] - not used
      * arg[1] - relative name of properties file
      * arg[2] - used as label
      */
-    protected static void initializeManager(String[] args) {
+    private static void initializeManager(String[] args) {
         if (args.length >= 3) {
             try {
                 System.out.println("Using initializeProperties() from " + args[2]);

Added: jmeter/trunk/test/src/org/apache/jorphan/test/JMeterSerialTest.java
URL: http://svn.apache.org/viewvc/jmeter/trunk/test/src/org/apache/jorphan/test/JMeterSerialTest.java?rev=1817424&view=auto
==============================================================================
--- jmeter/trunk/test/src/org/apache/jorphan/test/JMeterSerialTest.java (added)
+++ jmeter/trunk/test/src/org/apache/jorphan/test/JMeterSerialTest.java Thu Dec  7 21:31:04
2017
@@ -0,0 +1,8 @@
+package org.apache.jorphan.test;
+
+/**
+ * Used to tag tests which need to be run on their own (in serial) because
+ * either, they cause other tests to fail, or they fail when run in parallel.
+ */
+public interface JMeterSerialTest {
+}

Propchange: jmeter/trunk/test/src/org/apache/jorphan/test/JMeterSerialTest.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: jmeter/trunk/test/src/org/apache/jorphan/test/JMeterSerialTest.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: jmeter/trunk/xdocs/changes.xml
URL: http://svn.apache.org/viewvc/jmeter/trunk/xdocs/changes.xml?rev=1817424&r1=1817423&r2=1817424&view=diff
==============================================================================
--- jmeter/trunk/xdocs/changes.xml [utf-8] (original)
+++ jmeter/trunk/xdocs/changes.xml [utf-8] Thu Dec  7 21:31:04 2017
@@ -202,6 +202,7 @@ Summary
     <li><pr>334</pr>Enable running of JUnit tests from within IntelliJ
with default config. Contributed by Graham Russell (graham at ham1.co.uk)</li>
     <li><pr>335</pr>Removed <code>functions.util.*</code> as
they don't seem to be used (for many years). Contributed by Graham Russell (graham at ham1.co.uk)</li>
     <li><bug>61867</bug><pr>345</pr>Updated to latest checkstyle
(v8.5), Added many more rules to checkstyle, Included checking of test files and more file
types. Contributed by Graham Russell (graham at ham1.co.uk)</li>
+    <li><pr>350</pr> Parallelised unit tests</li>
 </ul>
 
  <!-- =================== Bug fixes =================== -->



Mime
View raw message