简体   繁体   English

有条件地忽略 JUnit 4 中的测试

[英]Conditionally ignoring tests in JUnit 4

OK, so the @Ignore annotation is good for marking that a test case shouldn't be run.好的,所以@Ignore注释非常适合标记不应运行的测试用例。

However, sometimes I want to ignore a test based on runtime information.但是,有时我想忽略基于运行时信息的测试。 An example might be if I have a concurrency test that needs to be run on a machine with a certain number of cores.一个例子可能是,如果我有一个需要在具有一定数量内核的机器上运行的并发测试。 If this test were run on a uniprocessor machine, I don't think it would be correct to just pass the test (since it hasn't been run), and it certainly wouldn't be right to fail the test and break the build.如果这个测试是在单处理器机器上运行的,我认为仅仅通过测试是不正确的(因为它没有运行过),而且测试失败并破坏构建肯定是不对的.

So I want to be able to ignore tests at runtime, as this seems like the right outcome (since the test framework will allow the build to pass but record that the tests weren't run).所以我希望能够在运行时忽略测试,因为这似乎是正确的结果(因为测试框架将允许构建通过但记录未运行测试)。 I'm fairly sure that the annotation won't give me this flexibility, and suspect that I'll need to manually create the test suite for the class in question.我相当确定注释不会给我这种灵活性,并怀疑我需要为相关类手动创建测试套件。 However, the documentation doesn't mention anything about this and looking through the API it's also not clear how this would be done programmatically (ie how do I programatically create an instance of Test or similar that is equivalent to that created by the @Ignore annotation?).但是,文档没有提到任何关于此的内容,并且通过API也不清楚这将如何以编程方式完成(即,我如何以编程方式创建Test或类似的实例,该实例等效于由@Ignore注释创建的@Ignore ?)。

If anyone has done something similar in the past, or has a bright idea of how else I could go about this, I'd be happy to hear about it.如果有人在过去做过类似的事情,或者对我如何才能做到这一点有一个很好的想法,我很高兴听到它。

The JUnit way is to do this at run-time is org.junit.Assume . JUnit 方法是在运行时执行此操作是org.junit.Assume

 @Before
 public void beforeMethod() {
     org.junit.Assume.assumeTrue(someCondition());
     // rest of setup.
 }

You can do it in a @Before method or in the test itself, but not in an @After method.您可以在@Before方法或测试本身中执行此操作,但不能在@After方法中执行。 If you do it in the test itself, your @Before method will get run.如果您在测试本身中执行此操作,您的@Before方法将运行。 You can also do it within @BeforeClass to prevent class initialization.您也可以在@BeforeClass执行此操作以防止类初始化。

An assumption failure causes the test to be ignored.假设失败会导致测试被忽略。

Edit: To compare with the @RunIf annotation from junit-ext , their sample code would look like this:编辑:为了与junit-ext 中@RunIf注释进行比较,它们的示例代码如下所示:

@Test
public void calculateTotalSalary() {
    assumeThat(Database.connect(), is(notNull()));
    //test code below.
}

Not to mention that it is much easier to capture and use the connection from the Database.connect() method this way.更不用说以这种方式捕获和使用来自Database.connect()方法的连接要容易得多。

You should checkout Junit-ext project.您应该检查Junit-ext项目。 They have RunIf annotation that performs conditional tests, like:它们具有执行条件测试的RunIf注释,例如:

@Test
@RunIf(DatabaseIsConnected.class)
public void calculateTotalSalary() {
    //your code there
}

class DatabaseIsConnected implements Checker {
   public boolean satisify() {
        return Database.connect() != null;
   }
}

[Code sample taken from their tutorial] [从他们的教程中获取的代码示例]

In JUnit 4, another option for you may be to create an annotation to denote that the test needs to meet your custom criteria, then extend the default runner with your own and using reflection, base your decision on the custom criteria.在 JUnit 4 中,您的另一个选择可能是创建一个注释来表示测试需要满足您的自定义标准,然后使用您自己的并使用反射扩展默认运行器,根据自定义标准做出决定。 It may look something like this:它可能看起来像这样:

public class CustomRunner extends BlockJUnit4ClassRunner {
    public CTRunner(Class<?> klass) throws initializationError {
        super(klass);
    }

    @Override
    protected boolean isIgnored(FrameworkMethod child) {
        if(shouldIgnore()) {
            return true;
        }
        return super.isIgnored(child);
    }

    private boolean shouldIgnore(class) {
        /* some custom criteria */
    }
}

Additionally to the answer of @tkruse and @Yishai :除了@tkruse 和@Yishai 的回答
I do this way to conditionally skip test methods especially for Parameterized tests, if a test method should only run for some test data records.我这样做是为了有条件地跳过测试方法,特别是对于Parameterized测试,如果测试方法应该只针对某些测试数据记录运行。

public class MyTest {
    // get current test method
    @Rule public TestName testName = new TestName();
    
    @Before
    public void setUp() {
        org.junit.Assume.assumeTrue(new Function<String, Boolean>() {
          @Override
          public Boolean apply(String testMethod) {
            if (testMethod.startsWith("testMyMethod")) {
              return <some condition>;
            }
            return true;
          }
        }.apply(testName.getMethodName()));
        
        ... continue setup ...
    }
}

A quick note: Assume.assumeTrue(condition) ignores rest of the steps but passes the test.快速说明: Assume.assumeTrue(condition)忽略其余步骤但通过了测试。 To fail the test, use org.junit.Assert.fail() inside the conditional statement.要使测试失败,请在条件语句中使用org.junit.Assert.fail() Works same like Assume.assumeTrue() but fails the test.Assume.assumeTrue()但测试失败。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM