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

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