Eclipse中的JUnit视图似乎随机排序测试。我如何按类名订购?
答案 0 :(得分:5)
正如加里在评论中所说:
如果Unit Runner可以,那就太好了 被告知要继续订购 班级名称。嗯,也许我应该看 进入源代码......
我确实看过,但没有提示对这些名称进行排序的功能。我建议对JUnit插件进行更改请求,但我不认为,有很多人使用这个东西,所以:DIY。
如果您修改插件代码,我希望看到解决方案。
答案 1 :(得分:3)
可能做的一件事是使用JUnit 3.x的模式。我们使用了一个名为AllTests的测试套件,您可以按特定顺序向其中添加测试。对于每个包装,我们都得到了另一个AllTests。为这些测试套件提供与软件包相同的名称,可以轻松构建应该由junit插件重视的层次结构。
我真的不喜欢它甚至在Junit查看器中呈现测试方法。它应该与TestCase类中指定的顺序完全相同。我以重要性和特征的方式命令这些方法。因此,最重要的失败方法是首先进行纠正,然后在测试用例的后半部分进行更加特殊的修正。
测试运动员正在争抢那些,这真令人讨厌。我将亲自看一下,如果我找到解决方案,我会更新这个答案。
更新:
我在TestCase中排序方法名称的问题与此相关: http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=7023180(谢谢Oracle!)。
所以最后oracle在class.getMethods或class.getDeclaredMethods调用中改变了方法的顺序。现在这些方法是随机的,可以在JVM的不同运行之间进行更改。它接缝与比较的优化有关,甚至是尝试压缩方法名称 - 谁知道......。
所以什么都离开了。首先可以使用:@FixMethodOrder(来自javacodegeeks.com):
- @FixMethodOrder(MethodSorters.DEFAULT) - 基于内部比较器的确定性顺序
- @FixMethodOrder(MethodSorters.NAME_ASCENDING) - 方法名称的升序
- @FixMethodOrder(MethodSorters.JVM) - 前4.11依赖于基于反射的顺序的方式
醇>
这是愚蠢的,但解释了为什么人们开始使用test1TestName架构。
<强> UPDATE2 强>:
我使用ASM,因为Javassist还在getMethods()上生成随机排序方法。他们在内部使用地图。使用ASM我只使用访问者。
package org.junit.runners.model;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import org.objectweb.asm.ClassReader;
import org.objectweb.asm.ClassVisitor;
import org.objectweb.asm.MethodVisitor;
import org.objectweb.asm.Opcodes;
import com.flirtbox.ioc.OrderTest;
/**
* @author Martin Kersten
*/
public class TestClassUtil {
public static class MyClassVisitor extends ClassVisitor {
private final List<String> names;
public MyClassVisitor(List<String> names) {
super(Opcodes.ASM4);
this.names = names;
}
@Override
public MethodVisitor visitMethod(int access, String name, String desc,
String signature, String[] exceptions) {
names.add(name);
return super.visitMethod(access, name, desc, signature, exceptions);
}
}
private static List<String> getMethodNamesInCorrectOrder(Class<?> clazz) throws IOException {
InputStream in = OrderTest.class.getResourceAsStream("/" + clazz.getName().replace('.', '/') + ".class");
ClassReader classReader=new ClassReader(in);
List<String> methodNames = new ArrayList<>();
classReader.accept(new MyClassVisitor(methodNames), 0);
return methodNames;
}
public static void sort(Class<?> fClass, List<FrameworkMethod> list) {
try {
final List<String> names = getMethodNamesInCorrectOrder(fClass);
Collections.sort(list, new Comparator<FrameworkMethod>() {
@Override
public int compare(FrameworkMethod methodA, FrameworkMethod methodB) {
int indexA = names.indexOf(methodA.getName());
int indexB = names.indexOf(methodB.getName());
if(indexA == -1)
indexA = names.size();
if(indexB == -1)
indexB = names.size();
return indexA - indexB;
}
});
} catch (IOException e) {
throw new RuntimeException("Could not optain the method names of " + fClass.getName() + " in correct order", e);
}
}
}
将它放在org.junit.runners.model包中的src / test / java文件夹中。现在将junit 4.5 lib的org.junit.runners.model.TestClass复制到同一个包中,并通过添加排序例程来改变它的构造函数。
public TestClass(Class<?> klass) {
fClass= klass;
if (klass != null && klass.getConstructors().length > 1)
throw new IllegalArgumentException(
"Test class can only have one constructor");
for (Class<?> eachClass : getSuperClasses(fClass))
for (Method eachMethod : eachClass.getDeclaredMethods())
addToAnnotationLists(new FrameworkMethod(eachMethod));
//New Part
for(List<FrameworkMethod> list : fMethodsForAnnotations.values()) {
TestClassUtil.sort(fClass, list);
}
//Remove once you have verified the class is really picked up
System.out.println("New TestClass for " + klass.getName());
}
你走了。现在,您按照在java文件中声明的顺序排序很好的方法。如果您想知道类路径通常设置为类加载器首先考虑src(目标或bin)文件夹中的所有内容。因此,在定义完全相同的包和相同的类时,您可以“覆盖”您使用的任何库中的每个类/接口。这就是诀窍!
<强> UPDATE3 强> 我能够以正确的顺序获得每个包和每个类的树视图。
就是这样。我到处添加的套件类是:
@RunWith(MySuiteRunner.class)
public class AllTests {
}
就是这样。它应该给你足够的开始和扩展这个。套件运行器仅使用反射,但我按字母顺序对子目录的测试类和套装进行排序,子目录(代表它们所在的包)最适合排序。
答案 2 :(得分:2)
mark写道:
它根据执行时间命令它们, 也许你应该排序你的方法? 来源/排序成员
标记是对的。但是你不能对你的单元测试进行排序。不允许推测执行的顺序。
单元测试必须独立构建,它是随机的,UnitRunner如何调用它们。
在大多数情况下,测试方法按字母顺序排序。这些课程是随机的。尝试使用TestSuite来订购测试。
答案 3 :(得分:2)
如果您真的需要在JUnit测试之间存在硬依赖关系,请尝试 JExample extension
JExample将生产者 - 消费者关系引入单元测试 生产者是一种测试方法,可以将其被测单位作为返回值 消费者是一种依赖于一个或多个生产者及其返回值的测试方法。
对于Junit4.4或4.5,您可以install it in Eclipse。
import jexample.Depends;
@Test
@Depends("#testEmpty")
public Stack<Integer> testPush(Stack<Integer> $) {
$.push(42);
assertFalse($.isEmpty());
return $;
}
正如本文"In pursuit of code quality: JUnit 4 vs. TestNG"中提到的那样:
JUnit框架试图实现的一件事是测试隔离 在缺点方面,这使得指定测试用例执行的顺序非常困难,这对于任何类型的相关测试都是必不可少的。
开发人员使用不同的技术来解决这个问题,比如按字母顺序指定测试用例或严重依赖于灯具(@Before
@After
)来正确设置。这些变通方法适用于成功的测试,但对于失败的测试,它们会产生不便的后果:每个后续的依赖测试也会失败。在某些情况下,这可能会导致大型测试套件报告不必要的故障
请注意:如果您保留任何解决方案以按您希望的方式订购JUnit测试...您需要考虑该解决方案是否支持“跳过”功能,以便允许其他测试继续进行,即使其中一个测试失败
答案 4 :(得分:1)
JUnit视图中的订购测试已归档为bug #386453 in Eclipse Bugzilla。评论和/或投票可能有助于提高对此问题的了解。
答案 5 :(得分:1)
11年后,JUnit视图确实具有名称顺序,并且也获得了“执行时间”顺序。
参见Eclipse 4.17 (2020-09)
按执行时间对测试结果进行排序
JUnit视图现在可以按执行时间对结果进行排序。
默认情况下,结果将按执行顺序排序。
一旦完成所有测试,从“ JUnit视图”菜单中选择Sort By > Execution Time
将对结果重新排序。当测试仍在运行时,它们将按执行顺序显示。
按执行顺序排序将导致:
答案 6 :(得分:0)
我也在寻找解决方案,我从下面的网址找到了一种破解。我不知道它是否适合您,但它在Spring Tool Suite 2.5.2中对我有用。