指定在方法级别(非类级别)进行 4 次测试的顺序

2022-09-01 03:22:21

我知道这是不好的做法,但需要完成,否则我需要切换到.有没有办法,类似于JUnit 3的testSuite,来指定在类中运行的测试的顺序?testng


答案 1

如果你确定你真的想这样做:可能有更好的方法,但这就是我所能想到的......

JUnit4 有一个注释:它允许您覆盖测试的默认运行器。@RunWith

在你的例子中,你希望创建一个特殊的子类,并重写以按照您希望执行的顺序返回测试。例如,假设我想按相反的字母顺序执行测试:BlockJunit4ClassRunnercomputeTestMethods()

public class OrderedRunner extends BlockJUnit4ClassRunner {

    public OrderedRunner(Class klass) throws InitializationError {
        super(klass);
    }

    @Override
    protected List computeTestMethods() {
        List list = super.computeTestMethods();
        List copy = new ArrayList(list);
        Collections.sort(copy, new Comparator() {
            public int compare(FrameworkMethod o1, FrameworkMethod o2) {
                return o2.getName().compareTo(o1.getName());
            }
        });
        return copy;
    }
}
@RunWith(OrderedRunner.class)
public class OrderOfTest {
    @Test public void testA() { System.out.println("A"); }
    @Test public void testC() { System.out.println("C"); }
    @Test public void testB() { System.out.println("B"); }
}

运行此测试会产生:

C
B
A

对于您的特定情况,您需要一个比较器,该比较器将按您希望执行的顺序按名称对测试进行排序。(我建议使用类似Google Guava的类来定义比较器,其中onResultOf提供了一个将FrameworkMethod转换为其名称的函数......尽管显然您可以自由地以任何您想要的方式实现它。Ordering.explicit("methodName1","methodName2").onResultOf(...);


答案 2

我可以看到这样做的几个原因,特别是在使用JUnit运行功能测试或测试持久性对象时。例如,考虑一个持久化到某种持久性存储的对象。如果我想按照单元测试原则“所有测试都应该是可重新排序的,并且只测试功能的特定部分”来测试对象上的插入,更新和删除功能,我将有三个测试:ArticleArticle

  • testInsertArticle()
  • testUpdateArticle()
  • testDeleteArticle()

但是,为了能够测试更新功能,我首先需要插入文章。为了测试删除功能,我还需要插入一篇文章。因此,在实践中,插入功能已在 和 中进行了测试。然后,很容易创建一个测试方法来完成所有工作,但是像这样的方法最终会变得巨大(而且它们不会只是测试对象的部分功能)。testUpdateArticle()testDeleteArticle()testArticleFunctionality()Article

例如,针对Restful API运行功能测试也是如此。如果不是测试的不确定排序,JUnit对于这些情况也非常有用。

也就是说,我扩展了Michael D's,使用注释来确定测试的顺序,只是认为我应该分享。它可以进一步扩展,例如,通过准确指定每个测试所依赖的测试,但这就是我现在使用的。OrderedRunner

这就是它的使用方式。它避免了命名测试的需要,如,,,...,等。AA_testInsert()AB_testUpdate()AC_testDelete()ZC_testFilter()

@RunWith(OrderedRunner.class)
public class SomethingTest {
    @Test
    @Order(order=2)
    public void testUpdateArticle() {
        // test update
    }

    @Test
    @Order(order=1)
    public void testInsertArticle() {
        // test insert
    }

    @Test
    @Order(order=3)
    public void testDeleteArticle() {
        // test delete
    }
}

无论这些测试如何放置在文件中,它们将始终以第一个,第二个和最后一个运行,无论您从Eclipse内部,使用Ant还是任何其他方式运行它们。order=1order=2order=3

实现如下。首先,注释 。Order

@Retention(RetentionPolicy.RUNTIME)
public @interface Order {
    public int order();
}

然后,修改后的 .OrderedRunner

public class OrderedRunner extends BlockJUnit4ClassRunner {
    public OrderedRunner(Class<?> klass) throws InitializationError {
        super(klass);
    }

    @Override
    protected List<FrameworkMethod> computeTestMethods() {
        List<FrameworkMethod> copy = new ArrayList<>(super.computeTestMethods());
        Collections.sort(list, new Comparator<FrameworkMethod>() {
            @Override
            public int compare(FrameworkMethod f1, FrameworkMethod f2) {
                Order o1 = f1.getAnnotation(Order.class);
                Order o2 = f2.getAnnotation(Order.class);
        
                if(o1==null && o2 == null) return 0;
                if (o1 == null) return 1;
                if (o2 == null) return -1;

                return o1.order() - o2.order();
            }
        });
        return list;
    }
}

推荐