[跟着官方文档学JUnit5][四][WritingTests][学习笔记]

举报
John2021 发表于 2022/04/24 19:14:21 2022/04/24
【摘要】 1.禁用测试可以通过@Disabled注解、通过条件测试执行中讨论的注解之一或通过自定义执行条件禁用整个测试类或单个测试方法。下面是一个@Disabled测试类import org.junit.jupiter.api.Disabled;import org.junit.jupiter.api.Test;@Disabled("Disabled until bug #99 has been f...

1.禁用测试

可以通过@Disabled注解、通过条件测试执行中讨论的注解之一或通过自定义执行条件禁用整个测试类或单个测试方法。
下面是一个@Disabled测试类

import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

@Disabled("Disabled until bug #99 has been fixed")
class DisabledClassDemo {
    @Test
    void testWillBeSkipped() {
    }
}

下面是一个测试类,其中包含一个@Disabled测试方法

import com.example.util.Calculator;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.*;

class DisabledClassDemo1 {

    private final Calculator calculator = new Calculator();

    @Disabled("Disabled until bug #42 has been resolved")
    @Test
    void testWillBeSkipped() {
        assertEquals(3, calculator.add(1, 1));
    }

    @Test
    void testWillBeExecuted() {
        assertEquals(2, calculator.add(1, 1));
    }
}

输出结果

注意:JUnit团队建议开发人员提供一个简短的解释,说明为什么禁用了测试类或测试方法。

2.条件测试执行

JUnit Jupiter中的ExecutionCondition拓展API允许开发人员启用或禁用容器,或者根据特定条件以编程方式进行测试。此类条件的最简单示例是内置的DisableCondition,它支持@Disabled注解(参考禁用测试)。除了@Disabled之外,JUnit Jupiter还支持org.junit.jupiter.api.condition包中的其他几个基于注解的条件,这些条件允许开发人员以声明方式启用或禁用容器和测试。注册多个执行条件拓展时,只要其中一个条件返回禁用状态,就会禁用容器或测试。如果你希望提供有关它们可能被禁用的原因的详细信息,则与这些内置条件关联的每个注解都有一个可用于此目的的disabledReason属性。

组合注解

  • 注意以下各节中列出的任何条件注解也可以用作元注解,以便创建自定义组合注解。比如,@EnabledOnOS演示中的@TestOnMac注解演示了如何将@Test和@EnabledOnOS组合到单个可重用的注解中。
  • 如果条件注解在给定元素上直接存在,间接存在或元存在多次,则只会使用JUnit发现的第一个此类注解;任何其他声明都将被忽略。但请注意,每个条件注解可以与org.junit.jupiter.api.condition包中的其他条件注解结合使用。

2.1.操作系统条件

容器或测试可以通过@EnabledOnOS和@DisabledOnOS注解在特定操作系统上启用或禁用

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.*;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

class TestOnOS {
    @Test
    @EnabledOnOs(OS.MAC)
    void onlyOnMacOS() {
        //...
    }
    
    @TestOnMac
    void testOnMac() {
        //...
    }
    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Test
    @EnabledOnOs(OS.MAC)
    @interface TestOnMac{
    }
    
    @Test
    @EnabledOnOs({OS.LINUX,OS.MAC})
    void onLinuxOrMac() {
        //...
    }
}

2.2.JRE条件

容器或测试可以通过@EnabledOnJre和@DisabledOnJre注解在特定版本的JRE上启用或禁用,也可以通过@EnabledForJreRange和@DisabledForJreRange注解在特定版本的JRE上启用或禁用。默认范围是Java 8为最低值。

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.*;

class TestOnJava {
    @Test
    @EnabledOnJre(JRE.JAVA_8)
    void onlyOnJava8() {
        //...
    }

    @Test
    @EnabledOnJre({JRE.JAVA_9, JRE.JAVA_10})
    void onJava9Or10() {
        //...
    }

    @Test
    @EnabledForJreRange(min = JRE.JAVA_9, max = JRE.JAVA_18)
    void fromJava9to18() {
        //...
    }

    @Test
    @DisabledOnJre(JRE.JAVA_9)
    void notOnJava9() {
        //...
    }

    @Test
    @DisabledForJreRange(min = JRE.JAVA_9, max = JRE.JAVA_14)
    void notFromJava9to14() {
        //...
    }
}

2.3.系统属性条件

容器或测试可以通过@EnabledIfSystemProperty和@DisabledIfSystemProperty注解根据命名JVM系统属性的值来启用或禁用。通过matches属性提供的值将被解释为正则表达式。

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIfSystemProperty;
import org.junit.jupiter.api.condition.EnabledIfSystemProperty;

class TestOnSystemProperty {
    @Test
    @EnabledIfSystemProperty(named = "os.arch", matches = ".*64.*")
    void onlyOn64BitArchitectures() {
        //...
    }

    @Test
    @DisabledIfSystemProperty(named = "ci-server", matches = "true")
    void notOnCiServer() {
        //...
    }
}

2.4.环境变量条件

容器或测试可以通过@EnabledIfEnvironmentVariable和@DisabledIfEnvironmentVariable注解,根据操作系统中命名的环境变量的值来启用或禁用。通过matches属性提供的值将被解释为正则表达式。

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIfEnvironmentVariable;
import org.junit.jupiter.api.condition.EnabledIfEnvironmentVariable;

class TestOnEnvironmentVariable {
    @Test
    @EnabledIfEnvironmentVariable(named = "ENV", matches = "staging-server")
    void onlyOnStagingServer() {
        //...
    }

    @Test
    @DisabledIfEnvironmentVariable(named = "ENV", matches = ".*development.*")
    void notOnDeveloperWorkstation() {
        //...
    }
}

2.5.定制条件

容器或测试可以根据方法通过@EnabledIf的布尔值返回启用或禁用,@DisabledIf注解。该方法通过其名称提供给批注。如果需要,条件方法可以采用ExtensionContext类型的单个参数。

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.DisabledIf;
import org.junit.jupiter.api.condition.EnabledIf;

class TestOnCustomConditionDemo {
    @Test
    @EnabledIf("customCondition")
    void enabled() {
        //...
    }

    @Test
    @DisabledIf("customCondition")
    void disabled() {
        //...
    }
    
    boolean customCondition() {
        return true;
    }
}

条件方法也可以定位在测试类之外。在这种情况下,必须通过其完全限定名称引用

import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledIf;

class TestOnExternalConditionDemo {
    @Test
    @EnabledIf("com.example.conditionaltest.ExternalCondition")
    void enabled() {
        //...
    }
}

class ExternalCondition{
    static boolean customCondition() {
        return true;
    }
}

注意:在类级别使用@EnabledIf或@DisabledIf时,条件方法必须始终是静态的。位于外部类中的条件方法也必须是静态的。在任何其他情况下,可以同时使用静态方法或实例方法。

3.标记和过滤

通过@Tag注解标记测试类和方法。以后可用于筛选测试发现和执行。

import org.junit.jupiter.api.Tag;
import org.junit.jupiter.api.Test;

@Tag("fast")
@Tag("model")
class TaggingDemo {
    @Test
    @Tag("taxes")
    void testingTaxCalculation() {
        
    }
}

4.测试执行顺序

默认情况下,将使用确定性但不明显的算法对测试类和方法进行排序。可确保测试套件后续运行以相同的顺序执行测试类和测试方法,从而允许可重复的生成。

4.1.方法顺序

尽管真正的单元测试通常不依赖于执行顺序,但有时需要强制执行特定的测试方法执行顺序。在编写继承测试或功能测试时,测试的顺序很重要,特别是与@TestInstance(Lifecycle.PER_CLASS)结合使用时。
若要控制测试方法的执行顺序,使用@TestMethodOrder注解测试类或测试接口,并指定所需的MethodOrderer实现。可以自定义MethodOrderer,也可以使用以下内置MethodOrderer实现。

  • MethodOrderer.DisplayName:根据测试方法的显示名称按字母数字对测试方法进行排序(参照显示名称生成优先级规则)
  • MethodOrderer.MethodName:根据测试方法的名称和形式参数列表按字母数字对测试方法进行排序。
  • MethodOrderer.OrderAnnotation:根据通过@Order注解指定的值对测试方法进行数值排序
  • MethodOrderer.Random:伪随机排序并支持自定义种子配置
  • MethodOrderer.Alphanumeric:根据测试方法的名称和正式参数列表按字母数字对测试方法进行排序;

下面示例演示如何保证测试方法按通过@Order注解指定的顺序执行。

import org.junit.jupiter.api.MethodOrderer;
import org.junit.jupiter.api.Order;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestMethodOrder;

@TestMethodOrder(MethodOrderer.OrderAnnotation.class)
class OrderedTestsDemo {
    @Test
    @Order(1)
    void nullValues() {
        // perform assertions against null values
    }

    @Test
    @Order(2)
    void emptyValues() {
        // perform assertions against null values
    }

    @Test
    @Order(3)
    void validValues() {
        // perform assertions against null values
    }
}

设置默认方法排序

可以使用junit.jupiter.testmethod.order.default配置参数来指定默认情况下要使用MethodOrderer的完全限定类名。就想通过@TestMethodOrder注解配置的排序器一样,提供的类必须实现MethodOrderer接口。默认排序器将用于所有测试,除非封闭的测试类或接口上存在@TestMethodOrder注解。
例如,要默认使用MethodOrderer.OrderAnnotation方法排序器,应将配置参数设置为相应的完全限定类名(例如:在src/test/resouces/junit-platform.properties中)

junit.jupiter.testmethod.order.default = \
    org.junit.jupiter.api.MethodOrderer$OrderAnnotation

4.2.类顺序

尽管测试类通常不应依赖于它们的执行顺序,但有时需要强制执行特定的测试类执行顺序。您可能希望按随机顺序执行测试类,以确保测试类之间没有意外的依赖关系,或者您可能希望对测试类进行排序以优化生成时间,有以下方案。

  • 首先运行以前失败的测试和更快的测试:“快速失败”模式
  • 启用并行执行后,首先运行较长的测试:“最短测试计划执行持续时间”模式
  • 各种其他用例

若要为整个测试套件全局配置测试类执行顺序,请使用 junit.jupiter.testclass.order.default 配置参数指定要使用的 ClassOrderer 的完全限定类名。提供的类必须实现类顺序接口。
您可以实现自己的ClassOrderer,也可以使用以下内置ClassOrderer实现。

  • ClassOrderer.ClassName:根据测试类的完全限定类名按字母数字顺序对测试类进行排序
  • ClassOrderer.DisplayName:根据测试类的显示名称按字母数字顺序对测试类进行排序(请参阅显示名称生成优先级规则)
  • ClassOrderer.OrderAnnotation:根据通过@Order注解指定的值对测试类进行数值排序
  • ClassOrderer.Random:对伪随机测试类进行排序,并支持自定义配置种子

例如,对于要在测试类上接受@Order注解,应使用具有相应完全限定类名的配置参数来配置ClassOrderer.OrderAnnotation类排序器,例如:在src/test/resouces/junit-platform.properties中

junit.jupiter.testclass.order.default = \
    org.junit.jupiter.api.ClassOrderer$OrderAnnotation

配置的ClassOrderer将应用于所有顶级测试类(包括静态嵌套测试类)和@Nested测试类。
注意:顶级测试类将相对于彼此进行排序;然而,@Nested测试类将相对于共享同一封闭类的其他@Nested测试类进行排序。

若要在本地为@Nested测试类配置测试类执行顺序,请在要排序的@Nested测试类的封闭类上声明@TestClassOrder注解,并提供要直接在@TestClassOrder注解中使用的ClassOrderer实现的类引用。配置的类排序器将以递归方式应用于@Nested测试类及其子测试类。请注意,本地@TestClassOrder声明始终覆盖通过junit.jupiter.testclass.order.default配置参数全局配置的继承@TestClassOrder声明或ClassOrderer。
下面的示例演示如何保证@Nested测试类按通过@Order注解指定的顺序执行。

import org.junit.jupiter.api.*;

@TestClassOrder(ClassOrderer.OrderAnnotation.class)
class OrderedNestedTestClassesDemo {
    @Nested
    @Order(1)
    class PrimaryTests {
        @Test
        void test1() {
            //...
        }
    }

    @Nested
    @Order(2)
    class SecondaryTests{
        @Test
        void test2() {
            //...
        }
    }
}
【版权声明】本文为华为云社区用户原创内容,转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息, 否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。