在不修改Test类的情况下排除单个JUnit Test方法?

时间:2009-09-02 16:54:28

标签: java ant junit junit4

我目前正在针对我的代码重新使用来自其他项目的JUnit 4测试。作为自动化Ant构建的一部分,我直接从其他项目的存储库中获取它们。这很棒,因为它可以确保我的代码在最新版本的测试中保持绿色。

但是,有一部分测试我从未希望传递给我的代码。但是如果我开始在这些测试中添加@Ignore注释,我将不得不维护我自己的测试实现的单独副本,我真的不想这样做。

有没有一种方法可以在不修改测试源的情况下排除单个测试?以下是我到目前为止所看到的内容:

  • 据我所知,Ant JUnit任务只允许你排除整个Test类,而不是单独的测试方法 - 这对我没用,我需要方法粒度。

  • 我考虑整合一个TestSuite,它使用反射动态查找并添加所有原始测试,然后添加代码以显式删除我不想运行的测试。但是当我注意到TestSuite API没有提供删除测试的方法时,我放弃了这个想法。

  • 我可以创建自己的Test类来扩展原始的Test类,覆盖我不想运行的特定测试,并使用@Ignore注释它们。然后我在我的子类上运行JUnit。这里的缺点是,如果将新的测试类添加到原始项目中,我将不会自动选择它们。我将不得不监视新的Test类,因为它们被添加到原始项目中。到目前为止,这是我最好的选择,但感觉并不理想。

  • 我能想到的唯一另一个选择是无论如何都要运行错误的测试并忽略失败。但是,这些测试需要一段时间才能运行(并且失败!)所以我宁愿根本不运行它们。另外,我看不到告诉Ant任务忽略特定测试方法失败的方法(再次 - 我知道如何为单个测试类而不是方法执行此操作)。

7 个答案:

答案 0 :(得分:4)

如果您无法触及原始测试,那么您将面临一些严重的限制。你的压倒性声音是最好的选择,但有一些变化:

构建特别排除超类的Ant测试,以便您不了解的其他类可以运行。

您可以使用@Rule注释(JUnit 4.7的新增内容)来了解正在运行的测试并中止它(通过返回空的Statement实现)而不是覆盖特定的方法,让您更灵活地了解是否要避免测试。此方法的唯一问题是您无法使用此方法停止运行@Before方法,这可能很慢。如果这是一个问题(并且你真的无法触及测试),那么在重写方法中的@Ignore是我唯一能想到的。

但是,如果您可以触摸这些测试,则会打开一些其他选项:

您可以通过在类上指定@RunWith标记来使用自定义运行器运行它们。这个运行器只是将执行传递给该项目中的标准运行器(JUnit4.class),但是在您的项目中(通过系统属性或其他一些机制)将检查测试名称而不运行测试。这样做的优点是侵入性最小,但最难实现(跑步者是毛茸茸的野兽,@ Rule的既定目标之一就是消除制造它们的大部分需求)。

另一个是在测试中做一个假设的声明,它会检查一些配置设置,如果该测试应该运行则该设置是真的。这实际上涉及注入测试,这很可能是任何远程标记为“单独项目”的交易破坏者。

答案 1 :(得分:3)

现在它没有帮助,但TestNG支持这种能力。

答案 2 :(得分:2)

好的,这是一个相当重要的解决方案,但如果听起来很荒谬,不要向我扔东西。

Junit4的核心是org.junit.runner.Runner类及其各种子类,最重要的是org.junit.runners.Suite。这些运行器使用@Test和@Ignore之类的东西确定给定测试类的测试内容。

创建一个跑步者的自定义实现非常容易,通常你可以通过在测试类上使用@RunWith注释来连接它们,但显然这不适合你。

但是,从理论上讲,您可以编写自己的Ant任务,可能基于标准的Ant Junit任务,该任务采用您的自定义测试运行器并直接使用它,依次将每个测试类传递给它。您的运行器实现可以使用外部配置文件,该文件指定要忽略的测试方法。

这需要做很多工作,你必须花时间在史前的Ant Junit代码库中挖掘它,看看它是如何工作的。然而,时间投入可能是值得的。

令人遗憾的是,Junit Ant任务没有提供指定测试运行器的机制,这是理想的。

答案 3 :(得分:1)

我可以想到用规定的约束来实现你想要的东西是使用字节码修改。您可以在单独的文件中保留要忽略的类和方法的列表,并在加载它们时修补测试类的字节码以完全删除这些方法。

如果我没有弄错,JUnit使用反射来查找要执行的测试方法。然后,方法重命名操作将允许您在JUnit找到它们之前删除这些方法。或者可以修改方法以立即返回,而不执行任何操作。

BCEL这样的库可用于在加载时修改类。

答案 4 :(得分:1)

如果你只想运行一部分测试,那么听起来这个类有多个责任,应该重构。或者,测试类可以拆分,以便原始项目具有所有测试,但是在一个或多个类上(我猜测某些测试实际上是集成测试并触摸数据库或网络)并且您可以排除类( es)你不想要的。

如果你不能做到这一点,你可以选择覆盖最好。无论何时需要忽略扩展该类的某些方法并将其添加到Ant排除列表,都需要执行此过程。这样你就可以排除你无法传递的内容,并且仍然会在不修改你的构建的情况下引入所有新的测试(你没有覆盖的方法和新的测试类)。

答案 5 :(得分:0)

如果不需要的测试在特定的类/包中,您可以使用Ant中的文件集排除在导入期间排除它们。

答案 6 :(得分:0)

两个选项

  1. 与借用测试的所有者合作,将您的测试提取到您可以共享的单独课程中。
  2. 创建您自己的测试类,代理您要使用的测试类。对于要包含的每个方法,在您的类中都有一个方法。你需要构建一个你正在调用的测试类的实例,并且如果它们是原始的那样,也需要在方法之前和之后进行。
  3. 基于blockjunitrunner创建一个自定义Junit运行器,并使用它来过滤掉您想要的测试。