您的位置:軟件測試 > 開源軟件測試 > 開源單元測試工具 > junit
使用 JUnit 5 進行單元測試
作者:ibm 發(fā)布時間:[ 2017/3/24 15:27:42 ] 推薦標簽:單元測試 Junit 5 單元測試工具

  動態(tài)測試
  目前所介紹的 JUnit 5 測試方法的創(chuàng)建都是靜態(tài)的,在編譯時刻已經(jīng)存在。JUnit 5 新增了對動態(tài)測試的支持,可以在運行時動態(tài)創(chuàng)建測試并執(zhí)行。通過動態(tài)測試,可以滿足一些靜態(tài)測試無法解的需求,也可以完成一些重復(fù)性很高的測試。比如,有些測試用例可能依賴運行時的變量,有時候會需要生成上百個不同的測試用例。這些場景都是動態(tài)測試可以發(fā)揮其長處的地方。動態(tài)測試是通過新的@TestFactory 注解來實現(xiàn)的。測試類中的方法可以添加@TestFactory 注解的方法來聲明其是創(chuàng)建動態(tài)測試的工廠方法。這樣的工廠方法需要返回 org.junit.jupiter.api.DynamicTest 類的集合,可以是 Stream、Collection、Iterable 或 Iterator 對象。每個表示動態(tài)測試的 DynamicTest 對象由顯示名稱和對應(yīng)的 Executable 接口的實現(xiàn)對象來組成。清單 13 中展示了@TestFactory 的示例。
  清單 13. 動態(tài)測試
  @TestFactory
  public Collection<DynamicTest> simpleDynamicTest() {
  return Collections.singleton(dynamicTest
  ("simple dynamic test", () -> assertTrue(2 > 1)));
  }
  DynamicTest 提供了一個靜態(tài)方法 stream 來根據(jù)輸入生成動態(tài)測試,如清單 14 所示。
  清單 14. 通過 stream 方法來生成動態(tài)測試
  @TestFactory
  public Stream<DynamicTest> streamDynamicTest() {
  return stream(
  Stream.of("Hello", "World").iterator(),
  (word) -> String.format("Test - %s", word),
  (word) -> assertTrue(word.length() > 4)
  );
  }
  執(zhí)行測試用例
  JUnit 5 提供了三種不同的方式來執(zhí)行測試用例,分別是通過 Gradle 插件、Maven 插件和命令行來運行。
  Gradle
  JUnit 5 提供了 Gradle 插件,在 Gradle 項目中運行單元測試,如清單 15 所示。
  清單 15. 使用 JUnit 5 的 Gradle 插件
  buildscript {
  repositories {
  mavenCentral()
  }
  dependencies {
  classpath 'org.junit.platform:junit-platform-gradle-plugin:1.0.0-M2'
  }
  }
  apply plugin: 'org.junit.platform.gradle.plugin'
  在啟用了 Gradle 插件之后,可以通過 junitPlatformTest 任務(wù)來運行單元測試?梢栽 Gradle 腳本中對插件進行定制,如通過 reportsDir 設(shè)置測試結(jié)果報告的生成路徑,通過 tags 來設(shè)置包含或排除的標簽名稱,如清單 16 所示。
  清單 16. 配置 JUnit 5 的 Gradle 插件
  junitPlatform {
  platformVersion 1.0
  reportsDir "build/test-results/junit-platform"
  tags {
  include 'fast', 'smoke'
  }
  }
  Maven
  在 Maven 項目中可以通過 Surefire 插件來運行 JUnit 5 測試,只需要在 POM 文件中進行配置即可。如清單 17 所示。
  清單 17. 在 Maven 項目中使用 JUnit 5
  <build>
  <plugins>
  <plugin>
  <artifactId>maven-surefire-plugin</artifactId>
  <version>2.19</version>
  <dependencies>
  <dependency>
  <groupId>org.junit.platform</groupId>
  <artifactId>junit-platform-surefire-provider</artifactId>
  <version>1.0.0-M2</version>
  </dependency>
  </dependencies>
  </plugin>
  </plugins>
  </build>
  命令行
  除了 Gradle 和 Maven 之外,還可以通過命令行來運行 JUnit 5 測試。只需要直接運行 Java 類 org.junit.platform.console.ConsoleLauncher 即可。ConsoleLauncher 提供了不同的命令行參數(shù)來配置測試運行的行為,如-n 來指定包含的 Java 類名滿足的模式,-t 來包含標簽,-T 來排除標簽。
  擴展機制
  JUnit 5 提供了標準的擴展機制來允許開發(fā)人員對 JUnit 5 的功能進行增強。JUnit 5 提供了很多的標準擴展接口,第三方可以直接實現(xiàn)這些接口來提供自定義的行為。通過@ExtendWith 注解可以聲明在測試方法和類的執(zhí)行中啟用相應(yīng)的擴展。
  擴展的啟用是繼承的,這既包括測試類本身的層次結(jié)構(gòu),也包括測試類中的測試方法。也是說,測試類會繼承其父類中的擴展,測試方法會繼承其所在類中的擴展。除此之外,在一個測試上下文中,每一個擴展只能出現(xiàn)一次。
  創(chuàng)建擴展
  JUnit 5 中的擴展非常容易創(chuàng)建,只是實現(xiàn)了特定接口的 Java 類。JUnit 5 的擴展都需要實現(xiàn) org.junit.jupiter.api.extension.Extension 接口,不過該接口只是一個標記接口,并沒有任何需要實現(xiàn)的具體方法。真正起作用的是 Extension 的子接口,作為 JUnit 5 提供的擴展點。
  測試執(zhí)行條件
  ContainerExecutionCondition 和 TestExecutionCondition 接口用來配置是否啟用測試類或測試方法。前面提到的@Disabled 注解也是通過這樣的機制來實現(xiàn)的。ContainerExecutionCondition 接口對應(yīng)的是測試類,而 TestExecutionCondition 接口對應(yīng)的是測試方法。
  ContainerExecutionCondition 接口的 evaluate 方法接受 ContainerExtensionContext 接口作為參數(shù),并返回 ConditionEvaluationResult 類的對象作為結(jié)果。通過 ContainerExtensionContext 接口可以獲取到當前測試類的上下文信息,而 ConditionEvaluationResult 類則表示該測試類是否被啟用。
  TestExecutionCondition 接口也是包含一個 evaluate 方法,只不過參數(shù)類型是 TestExtensionContext,其返回結(jié)果也是 ConditionEvaluationResult 類的對象。
  通過擴展的方式禁用的測試類和方法,可以通過 JVM 參數(shù) junit.conditions.deactivate 來重新啟用,只需要把相應(yīng)的條件類禁用即可。
  清單 18 中擴展 DisableAPITests 實現(xiàn)了 ContainerExecutionCondition 和 TestExecutionCondition 接口,當測試類或方法中包含標簽 api 時,通過 ConditionEvaluationResult.disabled()表示對其禁用。
  清單 18. 測試執(zhí)行條件擴展示例
  public class DisableAPITests implements ContainerExecutionCondition,
  TestExecutionCondition {
  @Override
  public ConditionEvaluationResult evaluate
  (final ContainerExtensionContext context) {
  return checkTags(context.getTags());
  }
  @Override
  public ConditionEvaluationResult evaluate
  (final TestExtensionContext context) {
  return checkTags(context.getTags());
  }
  private ConditionEvaluationResult checkTags
  (final Set<String> tags) {
  if (tags.contains("api")) {
  return ConditionEvaluationResult.disabled("No API tests!");
  }
  return ConditionEvaluationResult.enabled("");
  }
  }
  清單 19 中的測試類的 simpleAPITest 方法使用了標簽 api,在執(zhí)行時會被禁用。
  清單 19. 使用 DisableAPITests 的測試用例
  @ExtendWith(DisableAPITests.class)
  public class APITests {
  @Test
  @Tag("api")
  public void simpleAPITest() {
  System.out.println("simple API test");
  }
  }
  后處理測試實例
  通過 TestInstancePostProcessor 可以對測試實例添加后處理的邏輯,從而進一步對實例進行定制,比如可以通過依賴注入的方式來設(shè)置其中的屬性,或是添加額外的初始化邏輯等。
  在清單 20 中,擴展 InjectAPIEnv 實現(xiàn)了 TestInstancePostProcessor 接口,在 postProcessTestInstance 方法中通過 Commons Lang 中的 MethodUtils.invokeMethod 來調(diào)用當前測試實例中的 setEnv 方法,并設(shè)置為 DEV。
  清單 20. 后處理測試實例的示例
  public class InjectAPIEnv implements TestInstancePostProcessor {
  @Override
  public void postProcessTestInstance
  (final Object testInstance,
  final ExtensionContext context) throws Exception {
  MethodUtils.invokeMethod(testInstance, "setEnv", "DEV");
  }
  }
  清單 21 中給出了使用該擴展的示例。
  清單 21. 使用后處理測試實例的示例
  @ExtendWith(InjectAPIEnv.class)
  public class APITests {
  private String env;
  public void setEnv(final String env) {
  this.env = env;
  }
  @Test
  public void showInjected() {
  assertEquals("DEV", this.env);
  }
  }
  參數(shù)解析
  在之前介紹 JUnit 5 的參數(shù)解析時,提到了 JUnit 5 可以自動解析 TestInfo 和 TestReporter 類型的參數(shù)。除了這兩種類型的參數(shù)之外,也可以通過擴展 ParameterResolver 接口來提供自定義的參數(shù)解析功能。ParameterResolver 接口中有兩個方法,分別是 supports 和 resolve。兩個方法的參數(shù)是一樣的,分別是 ParameterContext 和 ExtensionContext 接口的對象。通過 ParameterContext 可以獲取到需要解析的參數(shù)的信息,而 ExtensionContext 接口可以獲取到當前測試類或方法的上下文信息。
上一頁1234下一頁
軟件測試工具 | 聯(lián)系我們 | 投訴建議 | 誠聘英才 | 申請使用列表 | 網(wǎng)站地圖
滬ICP備07036474 2003-2017 版權(quán)所有 上海澤眾軟件科技有限公司 Shanghai ZeZhong Software Co.,Ltd