mirror of https://github.com/apache/jmeter.git
Bug 58897 : Improve JUnit Test code
#resolve #85
Bugzilla Id: 58897
git-svn-id: https://svn.apache.org/repos/asf/jmeter/trunk@1727442 13f79535-47bb-0310-9956-ffa450edef68
Former-commit-id: 9bc6974087
This commit is contained in:
parent
2bdd4541c9
commit
0a811618f6
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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.jorphan.reflect;
|
||||
|
||||
/**
|
||||
* filter class when visiting the search path with {@link ClassFinder}
|
||||
* @since 3.0
|
||||
*/
|
||||
public interface ClassFilter {
|
||||
|
||||
/**
|
||||
* @param className String class name
|
||||
* @return true if class is included
|
||||
*/
|
||||
boolean accept(String className);
|
||||
}
|
||||
|
|
@ -56,13 +56,10 @@ public final class ClassFinder {
|
|||
}
|
||||
|
||||
/**
|
||||
* Filter updates to TreeSet by only storing classes
|
||||
* Filter updates by only storing classes
|
||||
* that extend one of the parent classes
|
||||
*
|
||||
*
|
||||
*/
|
||||
private static class FilterTreeSet extends TreeSet<String>{
|
||||
private static final long serialVersionUID = 234L;
|
||||
private static class ExtendsClassFilter implements ClassFilter {
|
||||
|
||||
private final Class<?>[] parents; // parent classes to check
|
||||
private final boolean inner; // are inner classes OK?
|
||||
|
|
@ -75,73 +72,50 @@ public final class ClassFinder {
|
|||
private final transient ClassLoader contextClassLoader
|
||||
= Thread.currentThread().getContextClassLoader(); // Potentially expensive; do it once
|
||||
|
||||
FilterTreeSet(Class<?> []parents, boolean inner, String contains, String notContains){
|
||||
super();
|
||||
this.parents=parents;
|
||||
this.inner=inner;
|
||||
this.contains=contains;
|
||||
this.notContains=notContains;
|
||||
ExtendsClassFilter(Class<?> []parents, boolean inner, String contains, String notContains){
|
||||
this.parents = parents;
|
||||
this.inner = inner;
|
||||
this.contains = contains;
|
||||
this.notContains = notContains;
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the superclass so we only add classnames that
|
||||
* meet the criteria.
|
||||
*
|
||||
* @param s - classname (must be a String)
|
||||
* @return true if it is a new entry
|
||||
*
|
||||
* @see java.util.TreeSet#add(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean add(String s){
|
||||
if (contains(s)) {
|
||||
return false;// No need to check it again
|
||||
}
|
||||
if (contains!=null && s.indexOf(contains) == -1){
|
||||
public boolean accept(String className) {
|
||||
|
||||
if (contains!=null && className.indexOf(contains) == -1){
|
||||
return false; // It does not contain a required string
|
||||
}
|
||||
if (notContains!=null && s.indexOf(notContains) != -1){
|
||||
if (notContains!=null && className.indexOf(notContains) != -1){
|
||||
return false; // It contains a banned string
|
||||
}
|
||||
if ((s.indexOf('$') == -1) || inner) { // $NON-NLS-1$
|
||||
if (isChildOf(parents,s, contextClassLoader)) {
|
||||
return super.add(s);
|
||||
if ((className.indexOf('$') == -1) || inner) { // $NON-NLS-1$
|
||||
if (isChildOf(parents,className, contextClassLoader)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private static class AnnoFilterTreeSet extends TreeSet<String>{
|
||||
private static final long serialVersionUID = 240L;
|
||||
|
||||
|
||||
private static class AnnoClassFilter implements ClassFilter {
|
||||
|
||||
private final boolean inner; // are inner classes OK?
|
||||
|
||||
private final Class<? extends Annotation>[] annotations; // annotation classes to check
|
||||
private final transient ClassLoader contextClassLoader
|
||||
= Thread.currentThread().getContextClassLoader(); // Potentially expensive; do it once
|
||||
AnnoFilterTreeSet(Class<? extends Annotation> []annotations, boolean inner){
|
||||
super();
|
||||
|
||||
AnnoClassFilter(Class<? extends Annotation> []annotations, boolean inner){
|
||||
this.annotations = annotations;
|
||||
this.inner=inner;
|
||||
this.inner = inner;
|
||||
}
|
||||
/**
|
||||
* Override the superclass so we only add classnames that
|
||||
* meet the criteria.
|
||||
*
|
||||
* @param s - classname (must be a String)
|
||||
* @return true if it is a new entry
|
||||
*
|
||||
* @see java.util.TreeSet#add(java.lang.Object)
|
||||
*/
|
||||
|
||||
@Override
|
||||
public boolean add(String s){
|
||||
if (contains(s)) {
|
||||
return false;// No need to check it again
|
||||
}
|
||||
if ((s.indexOf('$') == -1) || inner) { // $NON-NLS-1$
|
||||
if (hasAnnotationOnMethod(annotations,s, contextClassLoader)) {
|
||||
return super.add(s);
|
||||
public boolean accept(String className) {
|
||||
if ((className.indexOf('$') == -1) || inner) { // $NON-NLS-1$
|
||||
if (hasAnnotationOnMethod(annotations,className, contextClassLoader)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
|
|
@ -276,12 +250,31 @@ public final class ClassFinder {
|
|||
log.debug("contains: " + contains + " notContains: " + notContains);
|
||||
}
|
||||
|
||||
|
||||
ClassFilter filter = null;
|
||||
if(annotations) {
|
||||
@SuppressWarnings("unchecked") // Should only be called with classes that extend annotations
|
||||
final Class<? extends Annotation>[] annoclassNames = (Class<? extends Annotation>[]) classNames;
|
||||
filter = new AnnoClassFilter(annoclassNames, innerClasses);
|
||||
}
|
||||
else {
|
||||
filter = new ExtendsClassFilter(classNames, innerClasses, contains, notContains);
|
||||
}
|
||||
|
||||
return findClasses(searchPathsOrJars, filter);
|
||||
}
|
||||
|
||||
public static List<String> findClasses(String[] searchPathsOrJars, ClassFilter filter) throws IOException {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("searchPathsOrJars : " + Arrays.toString(searchPathsOrJars));
|
||||
}
|
||||
|
||||
// Find all jars in the search path
|
||||
String[] strPathsOrJars = addJarsInPath(searchPathsOrJars);
|
||||
for (int k = 0; k < strPathsOrJars.length; k++) {
|
||||
strPathsOrJars[k] = fixPathEntry(strPathsOrJars[k]);
|
||||
}
|
||||
|
||||
|
||||
// Now eliminate any classpath entries that do not "match" the search
|
||||
List<String> listPaths = getClasspathMatches(strPathsOrJars);
|
||||
if (log.isDebugEnabled()) {
|
||||
|
|
@ -289,16 +282,13 @@ public final class ClassFinder {
|
|||
log.debug("listPaths : " + path);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked") // Should only be called with classes that extend annotations
|
||||
final Class<? extends Annotation>[] annoclassNames = (Class<? extends Annotation>[]) classNames;
|
||||
Set<String> listClasses =
|
||||
annotations ?
|
||||
new AnnoFilterTreeSet(annoclassNames, innerClasses)
|
||||
:
|
||||
new FilterTreeSet(classNames, innerClasses, contains, notContains);
|
||||
|
||||
Set<String> listClasses = new TreeSet<>();
|
||||
// first get all the classes
|
||||
findClassesInPaths(listPaths, listClasses);
|
||||
for (String path : listPaths) {
|
||||
findClassesInOnePath(path, listClasses, filter);
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("listClasses.size()="+listClasses.size());
|
||||
for (String clazz : listClasses) {
|
||||
|
|
@ -440,10 +430,11 @@ public final class ClassFinder {
|
|||
return strClassName;
|
||||
}
|
||||
|
||||
private static void findClassesInOnePath(String strPath, Set<String> listClasses) throws IOException {
|
||||
|
||||
private static void findClassesInOnePath(String strPath, Set<String> listClasses, ClassFilter filter) throws IOException {
|
||||
File file = new File(strPath);
|
||||
if (file.isDirectory()) {
|
||||
findClassesInPathsDir(strPath, file, listClasses);
|
||||
findClassesInPathsDir(strPath, file, listClasses, filter);
|
||||
} else if (file.exists()) {
|
||||
ZipFile zipFile = null;
|
||||
try {
|
||||
|
|
@ -452,7 +443,10 @@ public final class ClassFinder {
|
|||
while (entries.hasMoreElements()) {
|
||||
String strEntry = entries.nextElement().toString();
|
||||
if (strEntry.endsWith(DOT_CLASS)) {
|
||||
listClasses.add(fixClassName(strEntry));
|
||||
String fixedClassName = fixClassName(strEntry);
|
||||
if(filter.accept(fixedClassName)) {
|
||||
listClasses.add(fixedClassName);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
|
|
@ -466,29 +460,30 @@ public final class ClassFinder {
|
|||
}
|
||||
}
|
||||
|
||||
private static void findClassesInPaths(List<String> listPaths, Set<String> listClasses) throws IOException {
|
||||
for (String path : listPaths) {
|
||||
findClassesInOnePath(path, listClasses);
|
||||
}
|
||||
}
|
||||
|
||||
private static void findClassesInPathsDir(String strPathElement, File dir, Set<String> listClasses) throws IOException {
|
||||
private static void findClassesInPathsDir(String strPathElement, File dir, Set<String> listClasses, ClassFilter filter) throws IOException {
|
||||
String[] list = dir.list();
|
||||
if(list==null) {
|
||||
if(list == null) {
|
||||
log.warn(dir.getAbsolutePath()+" is not a folder");
|
||||
return;
|
||||
}
|
||||
|
||||
for (String aList : list) {
|
||||
File file = new File(dir, aList);
|
||||
if (file.isDirectory()) {
|
||||
// Recursive call
|
||||
findClassesInPathsDir(strPathElement, file, listClasses);
|
||||
} else if (aList.endsWith(DOT_CLASS) && file.exists() && (file.length() != 0)) {
|
||||
findClassesInPathsDir(strPathElement, file, listClasses, filter);
|
||||
}
|
||||
else if (aList.endsWith(DOT_CLASS) && file.exists() && (file.length() != 0)) {
|
||||
final String path = file.getPath();
|
||||
listClasses.add(path.substring(strPathElement.length() + 1,
|
||||
String className = path.substring(strPathElement.length() + 1,
|
||||
path.lastIndexOf('.')) // $NON-NLS-1$
|
||||
.replace(File.separator.charAt(0), '.')); // $NON-NLS-1$
|
||||
.replace(File.separator.charAt(0), '.');// $NON-NLS-1$
|
||||
if(filter.accept(className)) {
|
||||
listClasses.add(className);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -18,10 +18,16 @@
|
|||
|
||||
package org.apache.jmeter.gui.util;
|
||||
|
||||
import java.awt.GraphicsEnvironment;
|
||||
|
||||
import org.apache.jmeter.junit.JMeterTestCase;
|
||||
import org.apache.jorphan.logging.LoggingManager;
|
||||
import org.apache.log.Logger;
|
||||
|
||||
public final class TestMenuFactory extends JMeterTestCase {
|
||||
|
||||
private static final Logger log = LoggingManager.getLoggerForClass();
|
||||
|
||||
public TestMenuFactory() {
|
||||
super();
|
||||
}
|
||||
|
|
@ -35,6 +41,11 @@ public final class TestMenuFactory extends JMeterTestCase {
|
|||
}
|
||||
|
||||
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());
|
||||
|
|
|
|||
|
|
@ -19,6 +19,7 @@
|
|||
package org.apache.jmeter.junit;
|
||||
|
||||
import java.awt.Component;
|
||||
import java.awt.GraphicsEnvironment;
|
||||
import java.awt.HeadlessException;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
|
|
@ -129,12 +130,18 @@ public class JMeterTest extends JMeterTestCase {
|
|||
* Use a suite to allow the tests to be generated at run-time
|
||||
*/
|
||||
public static Test suite() throws Exception {
|
||||
TestSuite suite = new TestSuite("JMeterTest");
|
||||
if(GraphicsEnvironment.isHeadless()) {
|
||||
System.out.println("Skipping test:"+JMeterTest.class.getName()+", cannot run in Headless mode");
|
||||
log.warn("Skipping test:"+JMeterTest.class.getName()+", cannot run in Headless mode");
|
||||
return suite;
|
||||
}
|
||||
|
||||
// The Locale used to instantiate the GUI objects
|
||||
JMeterUtils.setLocale(TEST_LOCALE);
|
||||
Locale.setDefault(TEST_LOCALE);
|
||||
// Needs to be done before any GUI classes are instantiated
|
||||
|
||||
TestSuite suite = new TestSuite("JMeterTest");
|
||||
suite.addTest(new JMeterTest("readAliases"));
|
||||
suite.addTest(new JMeterTest("createTitleSet"));
|
||||
suite.addTest(new JMeterTest("createTagSet"));
|
||||
|
|
|
|||
|
|
@ -24,24 +24,26 @@ import java.io.FileNotFoundException;
|
|||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.nio.charset.Charset;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
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 junit.framework.Test;
|
||||
import junit.framework.TestCase;
|
||||
import junit.framework.TestResult;
|
||||
import junit.framework.TestSuite;
|
||||
import junit.textui.TestRunner;
|
||||
|
||||
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||
import org.apache.jmeter.util.JMeterUtils;
|
||||
import org.apache.jorphan.logging.LoggingManager;
|
||||
import org.apache.jorphan.reflect.ClassFinder;
|
||||
import org.apache.jorphan.util.JOrphanUtils;
|
||||
import org.apache.log.Logger;
|
||||
|
||||
/**
|
||||
* Provides a quick and easy way to run all <a
|
||||
* href="http://junit.sourceforge.net">junit</a> unit tests in your java
|
||||
|
|
@ -181,78 +183,18 @@ public final class AllTests {
|
|||
}
|
||||
log.info(sb.toString());
|
||||
|
||||
// ++
|
||||
// GUI tests throw the error
|
||||
// testArgumentCreation(org.apache.jmeter.config.gui.ArgumentsPanel$Test)java.lang.NoClassDefFoundError
|
||||
// at java.lang.Class.forName0(Native Method)
|
||||
// at java.lang.Class.forName(Class.java:141)
|
||||
// at
|
||||
// java.awt.GraphicsEnvironment.getLocalGraphicsEnvironment(GraphicsEnvironment.java:62)
|
||||
//
|
||||
// Try to find out why this is ...
|
||||
|
||||
System.out.println("+++++++++++");
|
||||
logprop("java.awt.headless", true);
|
||||
logprop("java.awt.graphicsenv", true);
|
||||
//
|
||||
// try {//
|
||||
// Class c = Class.forName(n);
|
||||
// System.out.println("Found class: "+n);
|
||||
// // c.newInstance();
|
||||
// // System.out.println("Instantiated: "+n);
|
||||
// } catch (Exception e1) {
|
||||
// System.out.println("Error finding class "+n+" "+e1);
|
||||
// } catch (java.lang.InternalError e1){
|
||||
// System.out.println("Error finding class "+n+" "+e1);
|
||||
// }
|
||||
//
|
||||
|
||||
System.out.println("------------");
|
||||
// don't call isHeadless() here, as it has a side effect.
|
||||
// --
|
||||
System.out.println("Creating test suite");
|
||||
TestSuite suite = suite(args[0]);
|
||||
|
||||
int countTestCases = suite.countTestCases();
|
||||
System.out.println("Starting test run, test count = "+countTestCases);
|
||||
// for (int i=0;i<suite.testCount();i++){
|
||||
// Test testAt = suite.testAt(i);
|
||||
// int testCases = testAt.countTestCases();
|
||||
// if (testAt instanceof junit.framework.TestCase){
|
||||
// System.out.print(((junit.framework.TestCase) testAt).getName());
|
||||
// }
|
||||
// if (testAt instanceof TestSuite){
|
||||
// TestSuite testSuite = ((TestSuite) testAt);
|
||||
// String name = testSuite.getName();
|
||||
// System.out.print(name);
|
||||
// System.out.println(" "+testCases);
|
||||
// }
|
||||
// }
|
||||
|
||||
// Jeremy Arnold: This method used to attempt to write results to
|
||||
// a file, but it had a bug and instead just wrote to System.out.
|
||||
// Since nobody has complained about this behavior, I'm changing
|
||||
// the code to not attempt to write to a file, so it will continue
|
||||
// behaving as it did before. It would be simple to make it write
|
||||
// to a file instead if that is the desired behavior.
|
||||
TestResult result = TestRunner.run(suite);
|
||||
// ++
|
||||
// Recheck settings:
|
||||
//System.out.println("+++++++++++");
|
||||
// System.out.println(e+"="+System.getProperty(e));
|
||||
// System.out.println(g+"="+System.getProperty(g));
|
||||
// System.out.println("Headless?
|
||||
// "+java.awt.GraphicsEnvironment.isHeadless());
|
||||
// try {
|
||||
// Class c = Class.forName(n);
|
||||
// System.out.println("Found class: "+n);
|
||||
// c.newInstance();
|
||||
// System.out.println("Instantiated: "+n);
|
||||
// } catch (Exception e1) {
|
||||
// System.out.println("Error with class "+n+" "+e1);
|
||||
// } catch (java.lang.InternalError e1){
|
||||
// System.out.println("Error with class "+n+" "+e1);
|
||||
// }
|
||||
//System.out.println("------------");
|
||||
// --
|
||||
|
||||
System.exit(result.wasSuccessful() ? 0 : 1); // this is needed because the test may start the AWT EventQueue thread which is not a daemon.
|
||||
}
|
||||
|
||||
|
|
@ -335,8 +277,7 @@ public final class AllTests {
|
|||
int suites=0;
|
||||
try {
|
||||
log.info("ClassFinder(TestCase)");
|
||||
List<String> classList = ClassFinder.findClassesThatExtend(JOrphanUtils.split(searchPaths, ","),
|
||||
new Class[] { TestCase.class }, true);
|
||||
List<String> classList = findJMeterJUnitTests(searchPaths);
|
||||
int sz=classList.size();
|
||||
log.info("ClassFinder(TestCase) found: "+sz+ " TestCase classes");
|
||||
System.out.println("ClassFinder found: "+sz+ " TestCase classes");
|
||||
|
|
@ -382,4 +323,42 @@ public final class AllTests {
|
|||
System.out.println("Created: "+tests+" tests including "+suites+" suites");
|
||||
return suite;
|
||||
}
|
||||
|
||||
private static List<String> findJMeterJUnitTests(String searchPaths) throws IOException {
|
||||
List<String> classList = ClassFinder.findClasses(JOrphanUtils.split(searchPaths, ","), new JunitTestFilter());
|
||||
|
||||
return classList;
|
||||
}
|
||||
|
||||
/**
|
||||
* find the junit tests in the test search path
|
||||
*/
|
||||
private static class JunitTestFilter implements ClassFilter {
|
||||
|
||||
private final transient ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
|
||||
|
||||
@Override
|
||||
public boolean accept(String className) {
|
||||
|
||||
boolean isJunitTest = false;
|
||||
try {
|
||||
Class<?> c = Class.forName(className, false, contextClassLoader);
|
||||
|
||||
if (!c.isInterface() && !Modifier.isAbstract(c.getModifiers())) {
|
||||
if (TestCase.class.isAssignableFrom(c)) {
|
||||
isJunitTest = true;
|
||||
}
|
||||
}
|
||||
} catch (UnsupportedClassVersionError ignored) {
|
||||
log.debug(ignored.getLocalizedMessage());
|
||||
} catch (NoClassDefFoundError ignored) {
|
||||
log.debug(ignored.getLocalizedMessage());
|
||||
} catch (ClassNotFoundException ignored) {
|
||||
log.debug(ignored.getLocalizedMessage());
|
||||
}
|
||||
|
||||
return isJunitTest;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -211,6 +211,7 @@ Summary
|
|||
<li><bug>57110</bug>Fixed spelling+grammar, formatting, removed commented out code etc. Contributed by Graham Russell (jmeter at ham1.co.uk)</li>
|
||||
<li>Correct instructions on running jmeter in help.txt. Contributed by Pascal Schumacher (pascalschumacher at gmx.net)</li>
|
||||
<li><bug>58704</bug>Non regression testing : Ant task batchtest fails if tests and run in a non en_EN locale and use a JMX file that uses a Csv DataSet</li>
|
||||
<li><bug>58897</bug>Improve JUnit Test code. Contributed by Benoit Wiart (benoit dot wiart at gmail.com)</li>
|
||||
</ul>
|
||||
|
||||
<!-- =================== Bug fixes =================== -->
|
||||
|
|
|
|||
Loading…
Reference in New Issue